reactos/dll/win32/riched20/style.c

557 lines
17 KiB
C
Raw Normal View History

/*
* RichEdit style management functions
*
* Copyright 2004 by Krzysztof Foltman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "editor.h"
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
Sync to Wine-0_9: Phil Krylov <phil@newstar.rinet.ru> - Fixed encoding of non-ASCII chars. Krzysztof Foltman <wdev@foltman.com> - Bugfix in EM_GETTEXTEX - Additional traces helpful in diagnosing similar (text retrieval-related) bugs. - Fix unnecessary (and harmful) repeated statement. - Removed buffer overrun error (incrementing output pointer one time too much in non-CRLF mode) making KeyNote fail to install. - Style trace information is written to different debug channel (it's not very useful anymore, reference counting looks correct for now). - The document dump contains the character position of the end-of-text mark. - The previous implementation was a workaround for off-by-one bug in ME_RunOfsFromCharOfs, this one relies on correct behavior of that function introduced by the previous patch. - Send verbose info to different debug channels (richedit_check for output from offset checker, richedit_lists for the document list dumps). - Fix a bug in 1.0 emulation mode in EM_LINELENGTH (which broke PTE installer). - Fixed EOL detection in ME_RunOfsFromCharOfs in 1.0 emulation mode (necessary for a non-workaround version of EM_POSFROMCHAR). - Fix 1.0 emulation mode in ME_GetTextW. - Remove another potential sources of infinite loops caused by EOF in the middle of the font and color tables. - Closing brace on text level is treated as EOF (effectively protecting the control from trash after the end of RTF). - Removed misleading comment about incomplete buffers (I was definitely wrong). - Implemented EM_GETFIRSTVISIBLELINE and EM_POSFROMCHAR (basic suboptimal implementation, can be optimized to skip whole paragraphs later if it's useful at all). - Fixed another case of misunderstanding MSDN wrt StreamInProc, causing license text to be truncated in Picasa installer (as well as some other programs, especially those that display long texts with NSIS). svn path=/trunk/; revision=18955
2005-11-02 20:03:07 +00:00
WINE_DECLARE_DEBUG_CHANNEL(richedit_style);
static int all_refs = 0;
/* the following routines assume that:
* - char2[AW] extends char[AW] by adding fields at the end of the charA form)
* - szFaceName is the last field of char[AW] form, and wWeight the first of 2[AW]
* - the difference between A and W form is the szFaceName as Ansi vs Unicode string
* - because of alignment, offset of wWeight field in 2[AW] structure *IS NOT*
* sizeof(char[AW])
*/
BOOL cfany_to_cf2w(CHARFORMAT2W *to, const CHARFORMAT2W *from)
{
if (from->cbSize == sizeof(CHARFORMATA))
{
CHARFORMATA *f = (CHARFORMATA *)from;
CopyMemory(to, f, FIELD_OFFSET(CHARFORMATA, szFaceName));
to->cbSize = sizeof(CHARFORMAT2W);
if (f->dwMask & CFM_FACE) {
MultiByteToWideChar(CP_ACP, 0, f->szFaceName, -1, to->szFaceName, ARRAY_SIZE(to->szFaceName));
}
return TRUE;
}
if (from->cbSize == sizeof(CHARFORMATW))
{
CHARFORMATW *f = (CHARFORMATW *)from;
CopyMemory(to, f, sizeof(*f));
/* theoretically, we don't need to zero the remaining memory */
ZeroMemory(&to->wWeight, sizeof(CHARFORMAT2W)-FIELD_OFFSET(CHARFORMAT2W, wWeight));
to->cbSize = sizeof(CHARFORMAT2W);
return TRUE;
}
if (from->cbSize == sizeof(CHARFORMAT2A))
{
CHARFORMAT2A *f = (CHARFORMAT2A *)from;
/* copy the A structure without face name */
CopyMemory(to, f, FIELD_OFFSET(CHARFORMATA, szFaceName));
/* convert face name */
if (f->dwMask & CFM_FACE)
MultiByteToWideChar(CP_ACP, 0, f->szFaceName, -1, to->szFaceName, ARRAY_SIZE(to->szFaceName));
/* copy the rest of the 2A structure to 2W */
CopyMemory(&to->wWeight, &f->wWeight, sizeof(CHARFORMAT2A)-FIELD_OFFSET(CHARFORMAT2A, wWeight));
to->cbSize = sizeof(CHARFORMAT2W);
return TRUE;
}
if (from->cbSize == sizeof(CHARFORMAT2W))
{
CopyMemory(to, from, sizeof(CHARFORMAT2W));
return TRUE;
}
return FALSE;
}
BOOL cf2w_to_cfany(CHARFORMAT2W *to, const CHARFORMAT2W *from)
{
assert(from->cbSize == sizeof(CHARFORMAT2W));
if (to->cbSize == sizeof(CHARFORMATA))
{
CHARFORMATA *t = (CHARFORMATA *)to;
CopyMemory(t, from, FIELD_OFFSET(CHARFORMATA, szFaceName));
WideCharToMultiByte(CP_ACP, 0, from->szFaceName, -1, t->szFaceName, sizeof(t->szFaceName), NULL, NULL);
t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */
t->dwMask &= CFM_ALL;
t->dwEffects &= CFM_EFFECTS;
return TRUE;
}
if (to->cbSize == sizeof(CHARFORMATW))
{
CHARFORMATW *t = (CHARFORMATW *)to;
CopyMemory(t, from, sizeof(*t));
t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */
t->dwMask &= CFM_ALL;
t->dwEffects &= CFM_EFFECTS;
return TRUE;
}
if (to->cbSize == sizeof(CHARFORMAT2A))
{
CHARFORMAT2A *t = (CHARFORMAT2A *)to;
/* copy the A structure without face name */
CopyMemory(t, from, FIELD_OFFSET(CHARFORMATA, szFaceName));
/* convert face name */
WideCharToMultiByte(CP_ACP, 0, from->szFaceName, -1, t->szFaceName, sizeof(t->szFaceName), NULL, NULL);
/* copy the rest of the 2A structure to 2W */
CopyMemory(&t->wWeight, &from->wWeight, sizeof(CHARFORMAT2W)-FIELD_OFFSET(CHARFORMAT2W,wWeight));
t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */
return TRUE;
}
if (to->cbSize == sizeof(CHARFORMAT2W))
{
CopyMemory(to, from, sizeof(CHARFORMAT2W));
return TRUE;
}
return FALSE;
}
ME_Style *ME_MakeStyle(CHARFORMAT2W *style)
{
ME_Style *s = heap_alloc(sizeof(*s));
assert(style->cbSize == sizeof(CHARFORMAT2W));
s->fmt = *style;
s->nRefs = 1;
s->font_cache = NULL;
memset(&s->tm, 0, sizeof(s->tm));
Sync to Wine-20050419: Krzysztof Foltman <wdev@foltman.com> - removed trailing spaces from some files - tab support - indent support - PageUp key support. - Support for "normal" scroll bar functionality (line and page scrolling). - made string operations consistent wrt whitespace handling (which should greatly improve stability of the wrap code and eliminate regressions of the most recent versions) - completely new scrollbar handling (much more reliable) and related redraw fixes - Page Down handler (no Page Up yet, fixing wrap/redraw/scrollbar bugs was of higher priority) - RTF reader doesn't use RichEdit messages anymore (which saves on unnecessary repaints) - added unicode character support to RTF import (like: \u12345 ?) - small fixes - fixed whitespace identification bug - removed drawing of paragraph marks - improved stub implementations for IRichEditOle - Unknown destinations are now correctly skipped (so loading an RTF file generated by, for example, OpenOffice doesn't produce lots of garbage anymore). - Format stack for RTF groups (so that RTF reader can correctly read what RTF writer wrote :) ) - EM_STREAMIN can now deal with undo in a reasonable manner (no multiple undo actions in one EM_STREAMIN). - Related changes to undo code (umIgnore mode is now handled correctly). - Numerous improvements in the RTF reader: it reads some character attributes now (you will have proper small print in license agreements now). - Fixed a memory overwrite bug in conversion from CHARFORMAT2A to CHARFORMAT2W. - Optimized repaint of the area below the text. - ME_JoinRuns didn't mark the paragraph for rewrapping, fixed. - Removed PostQuitMessage(0) from WM_DESTROY handler (duh!). - Use of EM_GETOLEINTERFACE is reported with FIXME instead of TRACE (any app using this message is likely to encounter major problems). - WM_COPY (and WM_CUT) can now put both Unicode and RTF format (thanks to Phil Krylov's RTF generator code). - New message implemented - WM_PASTE. - RTF reader: rtfPlain implemented (kind of). - RTF writer: rewritten main loop (the old one crashed in some circumstances when SFF_SELECTION was used). - The meaning of the rewrap flag got inverted (MEPF_REWRAP instead of MEPF_WRAPPED) for consistency. - Major code cleanups in rewrap/repaint code, leading to "smarter" behaviour wrt repainting selections. - Old font management replaced by the cache-based one, which keeps maximum of 10 HFONTs at once, instead of one per a couple of runs. - EM_CANPASTE implemented - updated TODO list (including list of (un)implemented messages) - fixed WM_PASTE (the previous version might not close the clipboard if it didn't contain a usable format) - scrollbar operations (like clicking on arrows) should update scrollbar's current position Gerald Pfeifer <gerald@pfeifer.com> - Make ME_ArrowLeft() return a value in every case. Phil Krylov <phil@newstar.rinet.ru> - Make RTF reader fall back to simple text if a correct RTF header is not detected. This should fix some installers. - Made RTF reader and writer handle codepages mostly similar to the original riched20.dll. - Fixed support for RTF documents using ANSI charset and added support for multibyte charsets, so that BIG5 and UTF-8 RTF documents are working now. - Replaced slow and outdated character set handling in RTF reader by Unicode/codepages support. Added charset->codepage conversion. - Implemented hash table lookup for RTF keywords in RTF reader. - Added "generator" RTF destination handling. - Initial implementation of EM_STREAMOUT and RTF writer. - Fixed \u keyword to output signed 16-bit values. Also fixed CP_SYMBOL conversion and the detection of the default font's codepage. - Improved RTF export. Mike McCormack <mike@codeweavers.com> - Remove casts and unused code. Hannu Valtonen <Hannu.Valtonen@hut.fi> - Added mousewheel support. Vincent Beron <vberon@mecano.gme.usherb.ca> - Use "" for Windows includes in dlls, instead of <>. Jakob Eriksson <jakov@vmlinux.org> - Get rid of HeapAlloc casts. Jason Edmeades <us@the-edmeades.demon.co.uk> - Correct memory allocation macro. svn path=/trunk/; revision=15014
2005-05-05 19:00:49 +00:00
s->tm.tmAscent = -1;
s->script_cache = NULL;
list_init(&s->entry);
all_refs++;
TRACE_(richedit_style)("ME_MakeStyle %p, total refs=%d\n", s, all_refs);
return s;
}
#define COPY_STYLE_ITEM(mask, member) \
if (mod->dwMask & mask) { \
fmt.dwMask |= mask;\
fmt.member = mod->member;\
}
#define COPY_STYLE_ITEM_MEMCPY(mask, member) \
if (mod->dwMask & mask) { \
fmt.dwMask |= mask;\
CopyMemory(fmt.member, mod->member, sizeof(mod->member));\
}
void ME_InitCharFormat2W(CHARFORMAT2W *pFmt)
{
ZeroMemory(pFmt, sizeof(CHARFORMAT2W));
pFmt->cbSize = sizeof(CHARFORMAT2W);
}
ME_Style *ME_ApplyStyle(ME_TextEditor *editor, ME_Style *sSrc, CHARFORMAT2W *mod)
{
CHARFORMAT2W fmt = sSrc->fmt;
ME_Style *s;
assert(mod->cbSize == sizeof(CHARFORMAT2W));
COPY_STYLE_ITEM(CFM_ANIMATION, bAnimation);
COPY_STYLE_ITEM(CFM_BACKCOLOR, crBackColor);
COPY_STYLE_ITEM(CFM_CHARSET, bCharSet);
COPY_STYLE_ITEM(CFM_COLOR, crTextColor);
COPY_STYLE_ITEM_MEMCPY(CFM_FACE, szFaceName);
COPY_STYLE_ITEM(CFM_KERNING, wKerning);
COPY_STYLE_ITEM(CFM_LCID, lcid);
COPY_STYLE_ITEM(CFM_OFFSET, yOffset);
COPY_STYLE_ITEM(CFM_REVAUTHOR, bRevAuthor);
if (mod->dwMask & CFM_SIZE) {
fmt.dwMask |= CFM_SIZE;
fmt.yHeight = min(mod->yHeight, yHeightCharPtsMost * 20);
}
COPY_STYLE_ITEM(CFM_SPACING, sSpacing);
COPY_STYLE_ITEM(CFM_STYLE, sStyle);
COPY_STYLE_ITEM(CFM_WEIGHT, wWeight);
/* FIXME: this is not documented this way, but that's the more logical */
COPY_STYLE_ITEM(CFM_FACE, bPitchAndFamily);
fmt.dwEffects &= ~(mod->dwMask);
fmt.dwEffects |= mod->dwEffects & mod->dwMask;
fmt.dwMask |= mod->dwMask;
if (mod->dwMask & CFM_COLOR)
{
if (mod->dwEffects & CFE_AUTOCOLOR)
fmt.dwEffects |= CFE_AUTOCOLOR;
else
fmt.dwEffects &= ~CFE_AUTOCOLOR;
}
COPY_STYLE_ITEM(CFM_UNDERLINETYPE, bUnderlineType);
/* If the CFM_UNDERLINE effect is not specified, set it appropriately */
if ((mod->dwMask & CFM_UNDERLINETYPE) && !(mod->dwMask & CFM_UNDERLINE))
{
fmt.dwMask |= CFM_UNDERLINE;
if (mod->bUnderlineType == CFU_UNDERLINENONE)
fmt.dwEffects &= ~CFE_UNDERLINE;
else
fmt.dwEffects |= CFE_UNDERLINE;
}
if (mod->dwMask & CFM_BOLD && !(mod->dwMask & CFM_WEIGHT))
{
fmt.wWeight = (mod->dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL;
} else if (mod->dwMask & CFM_WEIGHT && !(mod->dwMask & CFM_BOLD)) {
if (mod->wWeight > FW_NORMAL)
fmt.dwEffects |= CFE_BOLD;
else
fmt.dwEffects &= ~CFE_BOLD;
}
LIST_FOR_EACH_ENTRY(s, &editor->style_list, ME_Style, entry)
{
if (!memcmp( &s->fmt, &fmt, sizeof(fmt) ))
{
TRACE_(richedit_style)("found existing style %p\n", s);
ME_AddRefStyle( s );
return s;
}
}
s = ME_MakeStyle( &fmt );
if (s)
list_add_head( &editor->style_list, &s->entry );
TRACE_(richedit_style)("created new style %p\n", s);
return s;
}
void ME_CopyCharFormat(CHARFORMAT2W *pDest, const CHARFORMAT2W *pSrc)
{
/* using this with non-2W structs is forbidden */
assert(pSrc->cbSize == sizeof(CHARFORMAT2W));
assert(pDest->cbSize == sizeof(CHARFORMAT2W));
*pDest = *pSrc;
}
static void ME_DumpStyleEffect(char **p, const char *name, const CHARFORMAT2W *fmt, int mask)
{
*p += sprintf(*p, "%-22s%s\n", name, (fmt->dwMask & mask) ? ((fmt->dwEffects & mask) ? "YES" : "no") : "N/A");
}
void ME_DumpStyle(ME_Style *s)
{
char buf[2048];
ME_DumpStyleToBuf(&s->fmt, buf);
Sync to Wine-0_9: Phil Krylov <phil@newstar.rinet.ru> - Fixed encoding of non-ASCII chars. Krzysztof Foltman <wdev@foltman.com> - Bugfix in EM_GETTEXTEX - Additional traces helpful in diagnosing similar (text retrieval-related) bugs. - Fix unnecessary (and harmful) repeated statement. - Removed buffer overrun error (incrementing output pointer one time too much in non-CRLF mode) making KeyNote fail to install. - Style trace information is written to different debug channel (it's not very useful anymore, reference counting looks correct for now). - The document dump contains the character position of the end-of-text mark. - The previous implementation was a workaround for off-by-one bug in ME_RunOfsFromCharOfs, this one relies on correct behavior of that function introduced by the previous patch. - Send verbose info to different debug channels (richedit_check for output from offset checker, richedit_lists for the document list dumps). - Fix a bug in 1.0 emulation mode in EM_LINELENGTH (which broke PTE installer). - Fixed EOL detection in ME_RunOfsFromCharOfs in 1.0 emulation mode (necessary for a non-workaround version of EM_POSFROMCHAR). - Fix 1.0 emulation mode in ME_GetTextW. - Remove another potential sources of infinite loops caused by EOF in the middle of the font and color tables. - Closing brace on text level is treated as EOF (effectively protecting the control from trash after the end of RTF). - Removed misleading comment about incomplete buffers (I was definitely wrong). - Implemented EM_GETFIRSTVISIBLELINE and EM_POSFROMCHAR (basic suboptimal implementation, can be optimized to skip whole paragraphs later if it's useful at all). - Fixed another case of misunderstanding MSDN wrt StreamInProc, causing license text to be truncated in Picasa installer (as well as some other programs, especially those that display long texts with NSIS). svn path=/trunk/; revision=18955
2005-11-02 20:03:07 +00:00
TRACE_(richedit_style)("%s\n", buf);
}
void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048])
{
/* FIXME only CHARFORMAT styles implemented */
/* this function sucks, doesn't check for buffer overruns but it's "good enough" as for debug code */
char *p;
p = buf;
p += sprintf(p, "Font face: ");
if (pFmt->dwMask & CFM_FACE) {
WCHAR *q = pFmt->szFaceName;
while(*q) {
*p++ = (*q > 255) ? '?' : *q;
q++;
}
} else
p += sprintf(p, "N/A");
if (pFmt->dwMask & CFM_SIZE)
p += sprintf(p, "\nFont size: %d\n", pFmt->yHeight);
else
p += sprintf(p, "\nFont size: N/A\n");
if (pFmt->dwMask & CFM_OFFSET)
p += sprintf(p, "Char offset: %d\n", pFmt->yOffset);
else
p += sprintf(p, "Char offset: N/A\n");
if (pFmt->dwMask & CFM_CHARSET)
p += sprintf(p, "Font charset: %d\n", (int)pFmt->bCharSet);
else
p += sprintf(p, "Font charset: N/A\n");
/* I'm assuming CFM_xxx and CFE_xxx are the same values, fortunately it IS true wrt used flags*/
ME_DumpStyleEffect(&p, "Font bold:", pFmt, CFM_BOLD);
ME_DumpStyleEffect(&p, "Font italic:", pFmt, CFM_ITALIC);
ME_DumpStyleEffect(&p, "Font underline:", pFmt, CFM_UNDERLINE);
ME_DumpStyleEffect(&p, "Font strikeout:", pFmt, CFM_STRIKEOUT);
ME_DumpStyleEffect(&p, "Hidden text:", pFmt, CFM_HIDDEN);
p += sprintf(p, "Text color: ");
if (pFmt->dwMask & CFM_COLOR)
{
if (pFmt->dwEffects & CFE_AUTOCOLOR)
p += sprintf(p, "auto\n");
else
p += sprintf(p, "%06x\n", (int)pFmt->crTextColor);
}
else
p += sprintf(p, "N/A\n");
ME_DumpStyleEffect(&p, "Text protected:", pFmt, CFM_PROTECTED);
}
Sync to Wine-20050725: Phil Krylov <phil@newstar.rinet.ru> - Added some useful TRACEs. - Allow NULL parameter for WM_SETTEXT in RichEdit. - Implemented EM_LINELENGTH RichEdit message. - Fixed EM_LINEINDEX handler and added EM_LINEFROMCHAR handler. - Implemented EM_EXLINEFROMCHAR, EM_LINEINDEX, EM_FINDTEXT, EM_FINDTEXTW, EM_FINDTEXTEX, and EM_FINDTEXTEXW messages. - Fixed a comment about EM_STREAMIN. - Implemented EM_GETLINECOUNT RichEdit message. - Fixed EM_GETCHARFORMAT for selection containing a single character. - Fixed an off-by-one error in EM_GETLINECOUNT handler. - Fixed an off-by-one error in EM_STREAMOUT handler for non-Unicode plain text output. - Fixed another couple of EM_STREAMOUT bugs. - Removed junk from UTF-8 RTF output. - Added emulation of RichEdit 1.0 behaviour when the 1.0 window class is being used. This emulation (introduced in M$ RichEdit 3.0) counts paragraph endings as 2 characters (CR+LF) instead of 1 (CR). - Added EM_GETZOOM and EM_SETZOOM RichEdit message handlers. - Added some missing but useful items to the TODO list. Felix Nawothnig <felix.nawothnig@t-online.de> - Check structure size and fix return values in EM_GETCHARFORMAT. Aric Stewart <aric@codeweavers.com> - Implementation for EM_GETTEXTEX. Daniel Remenak <dtremenak@gmail.com> - Basic handling of EM_SETTEXTEX. Stefan Huehner <stefan@huehner.org> - Make functions static to fix -Wmissing-declarations warnings. - Change some char* to const char* to fix warnigns. - Make some function static. - Fix -Wmissing-declarations warnings. svn path=/trunk/; revision=17335
2005-08-12 17:41:40 +00:00
static void
ME_LogFontFromStyle(ME_Context* c, LOGFONTW *lf, const ME_Style *s)
{
ZeroMemory(lf, sizeof(LOGFONTW));
lstrcpyW(lf->lfFaceName, s->fmt.szFaceName);
Sync to Wine-20050725: Phil Krylov <phil@newstar.rinet.ru> - Added some useful TRACEs. - Allow NULL parameter for WM_SETTEXT in RichEdit. - Implemented EM_LINELENGTH RichEdit message. - Fixed EM_LINEINDEX handler and added EM_LINEFROMCHAR handler. - Implemented EM_EXLINEFROMCHAR, EM_LINEINDEX, EM_FINDTEXT, EM_FINDTEXTW, EM_FINDTEXTEX, and EM_FINDTEXTEXW messages. - Fixed a comment about EM_STREAMIN. - Implemented EM_GETLINECOUNT RichEdit message. - Fixed EM_GETCHARFORMAT for selection containing a single character. - Fixed an off-by-one error in EM_GETLINECOUNT handler. - Fixed an off-by-one error in EM_STREAMOUT handler for non-Unicode plain text output. - Fixed another couple of EM_STREAMOUT bugs. - Removed junk from UTF-8 RTF output. - Added emulation of RichEdit 1.0 behaviour when the 1.0 window class is being used. This emulation (introduced in M$ RichEdit 3.0) counts paragraph endings as 2 characters (CR+LF) instead of 1 (CR). - Added EM_GETZOOM and EM_SETZOOM RichEdit message handlers. - Added some missing but useful items to the TODO list. Felix Nawothnig <felix.nawothnig@t-online.de> - Check structure size and fix return values in EM_GETCHARFORMAT. Aric Stewart <aric@codeweavers.com> - Implementation for EM_GETTEXTEX. Daniel Remenak <dtremenak@gmail.com> - Basic handling of EM_SETTEXTEX. Stefan Huehner <stefan@huehner.org> - Make functions static to fix -Wmissing-declarations warnings. - Change some char* to const char* to fix warnigns. - Make some function static. - Fix -Wmissing-declarations warnings. svn path=/trunk/; revision=17335
2005-08-12 17:41:40 +00:00
lf->lfHeight = ME_twips2pointsY(c, -s->fmt.yHeight);
lf->lfWeight = FW_NORMAL;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_BOLD)
lf->lfWeight = FW_BOLD;
if (s->fmt.dwMask & CFM_WEIGHT)
lf->lfWeight = s->fmt.wWeight;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_ITALIC)
lf->lfItalic = 1;
if ((s->fmt.dwEffects & s->fmt.dwMask & CFM_UNDERLINE) &&
!(s->fmt.dwEffects & CFE_LINK) &&
s->fmt.bUnderlineType == CFU_CF1UNDERLINE)
lf->lfUnderline = 1;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT)
lf->lfStrikeOut = 1;
if (s->fmt.dwEffects & s->fmt.dwMask & (CFM_SUBSCRIPT|CFM_SUPERSCRIPT))
lf->lfHeight = (lf->lfHeight*2)/3;
/*lf.lfQuality = PROOF_QUALITY; */
if (s->fmt.dwMask & CFM_FACE)
lf->lfPitchAndFamily = s->fmt.bPitchAndFamily;
if (s->fmt.dwMask & CFM_CHARSET)
lf->lfCharSet = s->fmt.bCharSet;
}
void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt)
{
int ry;
ME_InitCharFormat2W(fmt);
ry = GetDeviceCaps(hDC, LOGPIXELSY);
lstrcpyW(fmt->szFaceName, lf->lfFaceName);
fmt->dwEffects = 0;
fmt->dwMask = CFM_WEIGHT|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_UNDERLINETYPE|CFM_STRIKEOUT|CFM_SIZE|CFM_FACE|CFM_CHARSET;
fmt->wWeight = lf->lfWeight;
fmt->yHeight = -lf->lfHeight*1440/ry;
if (lf->lfWeight > FW_NORMAL) fmt->dwEffects |= CFM_BOLD;
if (lf->lfItalic) fmt->dwEffects |= CFM_ITALIC;
if (lf->lfUnderline) fmt->dwEffects |= CFM_UNDERLINE;
fmt->bUnderlineType = CFU_UNDERLINE;
if (lf->lfStrikeOut) fmt->dwEffects |= CFM_STRIKEOUT;
fmt->bPitchAndFamily = lf->lfPitchAndFamily;
fmt->bCharSet = lf->lfCharSet;
}
static BOOL ME_IsFontEqual(const LOGFONTW *p1, const LOGFONTW *p2)
{
if (memcmp(p1, p2, sizeof(LOGFONTW)-sizeof(p1->lfFaceName)))
return FALSE;
if (wcscmp(p1->lfFaceName, p2->lfFaceName))
return FALSE;
return TRUE;
}
static void release_font_cache(ME_FontCacheItem *item)
{
if (item->nRefs > 0)
{
item->nRefs--;
item->nAge = 0;
}
}
void select_style( ME_Context *c, ME_Style *s )
{
HFONT old_font;
LOGFONTW lf;
int i, empty, age = 0x7FFFFFFF;
ME_FontCacheItem *item;
if (c->current_style == s) return;
if (s)
{
ME_LogFontFromStyle( c, &lf, s );
for (i = 0; i < HFONT_CACHE_SIZE; i++)
c->editor->pFontCache[i].nAge++;
for (i = 0, empty = -1, age = 0; i < HFONT_CACHE_SIZE; i++)
{
item = &c->editor->pFontCache[i];
if (!item->nRefs)
{
if (item->nAge > age)
{
empty = i;
age = item->nAge;
}
}
if (item->hFont && ME_IsFontEqual( &item->lfSpecs, &lf ))
break;
}
if (i < HFONT_CACHE_SIZE) /* found */
{
item = &c->editor->pFontCache[i];
TRACE_(richedit_style)( "font reused %d\n", i );
item->nRefs++;
}
else
{
assert(empty != -1);
item = &c->editor->pFontCache[empty];
if (item->hFont)
{
TRACE_(richedit_style)( "font deleted %d\n", empty );
DeleteObject(item->hFont);
item->hFont = NULL;
}
item->hFont = CreateFontIndirectW( &lf );
TRACE_(richedit_style)( "font created %d\n", empty );
item->nRefs = 1;
item->lfSpecs = lf;
}
s->font_cache = item;
old_font = SelectObject( c->hDC, item->hFont );
GetTextMetricsW( c->hDC, &s->tm );
if (!c->orig_font) c->orig_font = old_font;
}
else
{
SelectObject( c->hDC, c->orig_font );
c->orig_font = NULL;
}
if (c->current_style && c->current_style->font_cache)
{
release_font_cache( c->current_style->font_cache );
c->current_style->font_cache = NULL;
}
c->current_style = s;
return;
}
void ME_DestroyStyle(ME_Style *s)
{
list_remove( &s->entry );
if (s->font_cache)
{
release_font_cache( s->font_cache );
s->font_cache = NULL;
}
ScriptFreeCache( &s->script_cache );
heap_free(s);
}
void ME_AddRefStyle(ME_Style *s)
{
assert(s->nRefs>0); /* style with 0 references isn't supposed to exist */
s->nRefs++;
all_refs++;
TRACE_(richedit_style)("ME_AddRefStyle %p, new refs=%d, total refs=%d\n", s, s->nRefs, all_refs);
}
void ME_ReleaseStyle(ME_Style *s)
{
s->nRefs--;
all_refs--;
if (s->nRefs==0)
Sync to Wine-0_9: Phil Krylov <phil@newstar.rinet.ru> - Fixed encoding of non-ASCII chars. Krzysztof Foltman <wdev@foltman.com> - Bugfix in EM_GETTEXTEX - Additional traces helpful in diagnosing similar (text retrieval-related) bugs. - Fix unnecessary (and harmful) repeated statement. - Removed buffer overrun error (incrementing output pointer one time too much in non-CRLF mode) making KeyNote fail to install. - Style trace information is written to different debug channel (it's not very useful anymore, reference counting looks correct for now). - The document dump contains the character position of the end-of-text mark. - The previous implementation was a workaround for off-by-one bug in ME_RunOfsFromCharOfs, this one relies on correct behavior of that function introduced by the previous patch. - Send verbose info to different debug channels (richedit_check for output from offset checker, richedit_lists for the document list dumps). - Fix a bug in 1.0 emulation mode in EM_LINELENGTH (which broke PTE installer). - Fixed EOL detection in ME_RunOfsFromCharOfs in 1.0 emulation mode (necessary for a non-workaround version of EM_POSFROMCHAR). - Fix 1.0 emulation mode in ME_GetTextW. - Remove another potential sources of infinite loops caused by EOF in the middle of the font and color tables. - Closing brace on text level is treated as EOF (effectively protecting the control from trash after the end of RTF). - Removed misleading comment about incomplete buffers (I was definitely wrong). - Implemented EM_GETFIRSTVISIBLELINE and EM_POSFROMCHAR (basic suboptimal implementation, can be optimized to skip whole paragraphs later if it's useful at all). - Fixed another case of misunderstanding MSDN wrt StreamInProc, causing license text to be truncated in Picasa installer (as well as some other programs, especially those that display long texts with NSIS). svn path=/trunk/; revision=18955
2005-11-02 20:03:07 +00:00
TRACE_(richedit_style)("destroy style %p, total refs=%d\n", s, all_refs);
else
Sync to Wine-0_9: Phil Krylov <phil@newstar.rinet.ru> - Fixed encoding of non-ASCII chars. Krzysztof Foltman <wdev@foltman.com> - Bugfix in EM_GETTEXTEX - Additional traces helpful in diagnosing similar (text retrieval-related) bugs. - Fix unnecessary (and harmful) repeated statement. - Removed buffer overrun error (incrementing output pointer one time too much in non-CRLF mode) making KeyNote fail to install. - Style trace information is written to different debug channel (it's not very useful anymore, reference counting looks correct for now). - The document dump contains the character position of the end-of-text mark. - The previous implementation was a workaround for off-by-one bug in ME_RunOfsFromCharOfs, this one relies on correct behavior of that function introduced by the previous patch. - Send verbose info to different debug channels (richedit_check for output from offset checker, richedit_lists for the document list dumps). - Fix a bug in 1.0 emulation mode in EM_LINELENGTH (which broke PTE installer). - Fixed EOL detection in ME_RunOfsFromCharOfs in 1.0 emulation mode (necessary for a non-workaround version of EM_POSFROMCHAR). - Fix 1.0 emulation mode in ME_GetTextW. - Remove another potential sources of infinite loops caused by EOF in the middle of the font and color tables. - Closing brace on text level is treated as EOF (effectively protecting the control from trash after the end of RTF). - Removed misleading comment about incomplete buffers (I was definitely wrong). - Implemented EM_GETFIRSTVISIBLELINE and EM_POSFROMCHAR (basic suboptimal implementation, can be optimized to skip whole paragraphs later if it's useful at all). - Fixed another case of misunderstanding MSDN wrt StreamInProc, causing license text to be truncated in Picasa installer (as well as some other programs, especially those that display long texts with NSIS). svn path=/trunk/; revision=18955
2005-11-02 20:03:07 +00:00
TRACE_(richedit_style)("release style %p, new refs=%d, total refs=%d\n", s, s->nRefs, all_refs);
if (!all_refs) TRACE("all style references freed (good!)\n");
assert(s->nRefs>=0);
if (!s->nRefs)
ME_DestroyStyle(s);
}
ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor)
{
if (ME_IsSelection(editor))
{
ME_Cursor *from, *to;
ME_GetSelection(editor, &from, &to);
ME_AddRefStyle(from->pRun->member.run.style);
return from->pRun->member.run.style;
}
if (editor->pBuffer->pCharStyle) {
ME_AddRefStyle(editor->pBuffer->pCharStyle);
return editor->pBuffer->pCharStyle;
}
else
{
ME_Cursor *pCursor = &editor->pCursors[nCursor];
ME_DisplayItem *pRunItem = pCursor->pRun;
ME_DisplayItem *pPrevItem = NULL;
if (pCursor->nOffset) {
ME_Run *pRun = &pRunItem->member.run;
ME_AddRefStyle(pRun->style);
return pRun->style;
}
pPrevItem = ME_FindItemBack(pRunItem, diRunOrParagraph);
if (pPrevItem->type == diRun)
{
ME_AddRefStyle(pPrevItem->member.run.style);
return pPrevItem->member.run.style;
}
else
{
ME_AddRefStyle(pRunItem->member.run.style);
return pRunItem->member.run.style;
}
}
}
void ME_SaveTempStyle(ME_TextEditor *editor, ME_Style *style)
{
ME_Style *old_style = editor->pBuffer->pCharStyle;
if (style) ME_AddRefStyle( style );
editor->pBuffer->pCharStyle = style;
if (old_style) ME_ReleaseStyle( old_style );
}
void ME_ClearTempStyle(ME_TextEditor *editor)
{
if (!editor->pBuffer->pCharStyle) return;
ME_ReleaseStyle(editor->pBuffer->pCharStyle);
editor->pBuffer->pCharStyle = NULL;
}
/******************************************************************************
* ME_SetDefaultCharFormat
*
* Applies a style change to the default character style.
*
* The default style is special in that it is mutable - runs
* in the document that have this style should change if the
* default style changes. That means we need to fix up this
* style manually.
*/
void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod)
{
ME_Style *style, *def = editor->pBuffer->pDefaultStyle;
assert(mod->cbSize == sizeof(CHARFORMAT2W));
style = ME_ApplyStyle(editor, def, mod);
def->fmt = style->fmt;
def->tm = style->tm;
if (def->font_cache)
{
release_font_cache( def->font_cache );
def->font_cache = NULL;
}
ScriptFreeCache( &def->script_cache );
ME_ReleaseStyle( style );
ME_MarkAllForWrapping( editor );
}