Windows2003-3790/windows/advcore/gdiplus/test/texttest/style.cpp
2020-09-30 16:53:55 +02:00

457 lines
10 KiB
C++

//// Style - simple character styles for formatted text
//
// Provides a simple style selection mechanism for demostrating
// formatted text.
#include "precomp.hxx"
#include "global.h"
#include <tchar.h>
/*
void SetLogFont(
PLOGFONTA plf,
int iHeight,
int iWeight,
int iItalic,
int iUnderline,
char *pcFaceName) {
memset(plf, 0, sizeof(LOGFONTA));
plf->lfCharSet = DEFAULT_CHARSET;
plf->lfHeight = iHeight;
plf->lfWeight = iWeight;
plf->lfItalic = (BYTE) iItalic;
plf->lfUnderline = (BYTE) iUnderline;
lstrcpy(plf->lfFaceName, pcFaceName);
plf->lfOutPrecision = OUT_STROKE_PRECIS;
plf->lfClipPrecision = CLIP_STROKE_PRECIS;
plf->lfQuality = DRAFT_QUALITY;
plf->lfPitchAndFamily = VARIABLE_PITCH;
plf->lfEscapement = 0;
plf->lfOrientation = 0;
}
*/
void FreeStyle(int iStyle) {
/*
if (g_style[iStyle].hf) {
DeleteObject(g_style[iStyle].hf);
}
if (g_style[iStyle].sc) {
ScriptFreeCache(&g_style[iStyle].sc);
}
*/
}
void SetStyle(
int iStyle,
int iHeight,
int iWeight,
int iItalic,
int iUnderline,
int iStrikeout,
TCHAR *pcFaceName) {
LOGFONTA lf;
FreeStyle(iStyle);
//SetLogFont(&lf, iHeight, iWeight, iItalic, iUnderline, pcFaceName);
//g_style[iStyle].hf = CreateFontIndirect(&lf);
//g_style[iStyle].sc = NULL;
g_style[iStyle].emSize = REAL(iHeight);
for (UINT i=0; i<_tcslen(pcFaceName); i++)
{
g_style[iStyle].faceName[i] = pcFaceName[i];
}
g_style[iStyle].faceName[_tcslen(pcFaceName)] = 0;
g_style[iStyle].style =
(iWeight >= 700 ? FontStyleBold : 0)
+ (iItalic ? FontStyleItalic : 0)
+ (iUnderline ? FontStyleUnderline : 0)
+ (iStrikeout ? FontStyleStrikeout : 0);
}
void InitStyles() {
memset(g_style, 0, sizeof(g_style));
}
void FreeStyles() {
int i;
for (i=0; i<5; i++) {
FreeStyle(i);
}
}
//// StyleCheckRange - dir use in ASSERTs
//
// Returns TRUE if style length matches text length
BOOL StyleCheckRange() {
int iFormatPos;
RUN *pFormatRider;
// Check that style length is same as text length
pFormatRider = g_pFirstFormatRun;
iFormatPos = 0;
while (pFormatRider != NULL) {
iFormatPos += pFormatRider->iLen;
pFormatRider = pFormatRider->pNext;
}
return iFormatPos == g_iTextLen;
}
///// Style range manipulation
//
// StyleDeleteRange
// StyleExtendRange
// StyleSetRange
//
// The style list is a linked list of RUNs (see global.h) that
// covers the entire text buffer.
//
// Each run has a length, and a style number (an index to g_Style[])
// (The analysis field in the run is not used by the style list.)
//
// StyleDeleteRange and StyleExtendRange are called as part of text
// insertion/deletion to maintain the style list.
//
// StyleSetRange is called to change the style of the current selection
// when the user clicks on one the of the numbered style buttons.
/// StyleDeleteRange - delete range of style information
//
//
void StyleDeleteRange(
int iDelPos,
int iDelLen) {
int iFormatPos;
RUN *pFormatRider;
RUN *pPrevRun;
RUN *pDelRun; // Run to be deleted
if (iDelLen <= 0) return;
// Find first run affected by the deletion
iFormatPos = 0;
pFormatRider = g_pFirstFormatRun;
pPrevRun = NULL;
while (iFormatPos + pFormatRider->iLen <= iDelPos) {
iFormatPos += pFormatRider->iLen;
pPrevRun = pFormatRider;
pFormatRider = pFormatRider->pNext;
ASSERT(pFormatRider);
}
// Delete from end of first run
if (iDelPos + iDelLen > iFormatPos + pFormatRider->iLen) {
// Delete all the way from iDelPos to the end of the first affected run
iDelLen = iDelPos + iDelLen - (iFormatPos + pFormatRider->iLen); // Amount that will remain to be deleted
pFormatRider->iLen = iDelPos - iFormatPos;
} else {
// Deletion is entirely in the first affected run
pFormatRider->iLen -= iDelLen;
iDelLen = 0;
}
// First affected run now contains no range to be deleted
// If it's empty, remove it, otherwise step over it
if (pFormatRider->iLen == 0) {
// Remove redundant run
if (pFormatRider->pNext) {
// Replace this run by the next one
pDelRun = pFormatRider->pNext;
*pFormatRider = *pDelRun; // Copy content of next run over this one
delete pDelRun;
} else {
// No runs following this one
if (pPrevRun) {
ASSERT(iDelLen == 0);
delete pFormatRider;
pPrevRun->pNext = NULL;
} else {
// No runs left at all
ASSERT(iDelLen == 0);
delete pFormatRider;
g_pFirstFormatRun = NULL;
}
}
} else {
// Current run now contains no text to be deleted, so advance to next run
iFormatPos += pFormatRider->iLen;
pPrevRun = pFormatRider;
pFormatRider = pFormatRider->pNext;
}
// Delete from start of any remaining runs
while (iDelLen > 0) {
if (pFormatRider->iLen <= iDelLen) {
// This entire run must go
ASSERT(pFormatRider->pNext);
iDelLen -= pFormatRider->iLen;
pDelRun = pFormatRider->pNext;
*pFormatRider = *pDelRun;
delete pDelRun;
} else {
// Last run is deleted in part only
pFormatRider->iLen -= iDelLen;
iDelLen = 0;
}
}
// Check whether current run (which immediately follows deletion) can
// now be collapsed into the previous run
if (pPrevRun && pFormatRider && pPrevRun->iStyle == pFormatRider->iStyle) {
pPrevRun->iLen += pFormatRider->iLen;
pPrevRun->pNext = pFormatRider->pNext;
delete pFormatRider;
}
}
/// StyleExtendRange - Extend style immediately preceeding iPos by iLen characters
//
//
void StyleExtendRange(
int iExtPos,
int iExtLen) {
int iFormatPos;
RUN *pFormatRider;
const SCRIPT_ANALYSIS nullAnalysis = {0};
if (g_pFirstFormatRun == NULL) {
// Starting from no text at all
ASSERT(iExtPos == 0);
g_pFirstFormatRun = new RUN;
g_pFirstFormatRun->iLen = iExtLen;
g_pFirstFormatRun->iStyle = 1;
g_pFirstFormatRun->pNext = NULL;
g_pFirstFormatRun->analysis = nullAnalysis;
} else {
// Find run containing character immediately prior to iExtPos
iFormatPos = 0;
pFormatRider = g_pFirstFormatRun;
while (iFormatPos + pFormatRider->iLen < iExtPos) {
iFormatPos += pFormatRider->iLen;
pFormatRider = pFormatRider->pNext;
}
pFormatRider->iLen += iExtLen;
}
}
//// StyleSetRange - Change style for a given range
//
//
void StyleSetRange(
int iSetStyle,
int iSetPos,
int iSetLen) {
int iFormatPos;
RUN *pFormatRider;
RUN *pNewRun;
if (iSetLen <= 0) return;
// Remove existing style for the range
StyleDeleteRange(iSetPos, iSetLen);
if (g_pFirstFormatRun == NULL) {
// Replace style on entire text
g_pFirstFormatRun = new RUN;
g_pFirstFormatRun->pNext = NULL;
g_pFirstFormatRun->iLen = iSetLen;
g_pFirstFormatRun->iStyle = iSetStyle;
} else {
// Find first run affected by the change
iFormatPos = 0;
pFormatRider = g_pFirstFormatRun;
while (iFormatPos + pFormatRider->iLen < iSetPos) {
iFormatPos += pFormatRider->iLen;
pFormatRider = pFormatRider->pNext;
ASSERT(pFormatRider);
}
// New style starts after beginning of this run or at beginning of next run
if (pFormatRider->iStyle == iSetStyle) {
// Already the same style - just increase length
pFormatRider->iLen += iSetLen;
} else {
if (iFormatPos + pFormatRider->iLen > iSetPos) {
// New style is within this run
// Split this run around the new run
pNewRun = new RUN; // Create second part of existing run
*pNewRun = *pFormatRider;
pNewRun->iLen -= iSetPos - iFormatPos;
pFormatRider->iLen = iSetPos - iFormatPos;
pFormatRider->pNext = pNewRun;
pNewRun = new RUN; // Create inserted run
*pNewRun = *pFormatRider;
pNewRun->iLen = iSetLen;
pNewRun->iStyle = iSetStyle;
pFormatRider->pNext = pNewRun;
} else {
// New style is between this run and the next run
if ( pFormatRider->pNext
&& pFormatRider->pNext->iStyle == iSetStyle) {
// New style is same as adjacent following run
pFormatRider->pNext->iLen += iSetLen;
} else {
// Create new run between current run and next run
pNewRun = new RUN;
*pNewRun = *pFormatRider;
pNewRun->iStyle = iSetStyle;
pNewRun->iLen = iSetLen;
pFormatRider->pNext = pNewRun;
}
}
}
}
}