//// Style - simple character styles for formatted text // // Provides a simple style selection mechanism for demostrating // formatted text. #include "precomp.hxx" #include "global.h" #include /* 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; } } } } }