Synced riched20.dll with Wine HEAD

svn path=/trunk/; revision=34367
This commit is contained in:
Pierre Schweitzer 2008-07-08 10:08:54 +00:00
parent b513c98fb2
commit 0fe1322cbc
16 changed files with 2031 additions and 189 deletions

View file

@ -164,7 +164,6 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
ME_DisplayItem *pCursorRun = pCursor->pRun;
ME_DisplayItem *pSizeRun = pCursor->pRun;
assert(!pCursor->nOffset || !editor->bCaretAtEnd);
assert(height && x && y);
assert(!(ME_GetParagraph(pCursorRun)->member.para.nFlags & MEPF_REWRAP));
assert(pCursor->pRun);
@ -182,9 +181,9 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
ME_InitContext(&c, editor, hDC);
if (!pCursor->nOffset && !editor->bCaretAtEnd)
if (!pCursor->nOffset)
{
ME_DisplayItem *prev = ME_FindItemBack(pCursorRun, diRunOrStartRow);
ME_DisplayItem *prev = ME_FindItemBack(pCursorRun, diRunOrParagraph);
assert(prev);
if (prev->type == diRun)
pSizeRun = prev;
@ -209,15 +208,14 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
row->member.row.nLMargin);
}
}
if (pCursor->nOffset && !(run->member.run.nFlags & MERF_SKIPPED)) {
if (pCursor->nOffset) {
sz = ME_GetRunSize(&c, &para->member.para, &run->member.run, pCursor->nOffset,
row->member.row.nLMargin);
}
*height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent;
*x = run->member.run.pt.x + sz.cx;
*y = para->member.para.nYPos + row->member.row.nBaseline + pSizeRun->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor);
*y = para->member.para.nYPos + row->member.row.nBaseline + run->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor);
ME_DestroyContext(&c, editor->hWnd);
return;
}
@ -238,6 +236,10 @@ ME_MoveCaret(ME_TextEditor *editor)
ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height);
if(editor->bHaveFocus)
{
RECT rect;
GetClientRect(editor->hWnd, &rect);
x = min(x, rect.right-2);
CreateCaret(editor->hWnd, NULL, 0, height);
SetCaretPos(x, y);
}
@ -744,11 +746,9 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
void
ME_SelectWord(ME_TextEditor *editor)
{
if (!(editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA))
ME_MoveCursorWords(editor, &editor->pCursors[0], -1);
ME_MoveCursorWords(editor, &editor->pCursors[1], +1);
ME_InvalidateSelection(editor);
ME_SendSelChange(editor);
editor->pCursors[0] = editor->pCursors[1];
ME_MoveCursorWords(editor, &editor->pCursors[0], -1);
}
@ -797,6 +797,20 @@ static void ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *resu
}
p = pp;
}
if (p == editor->pBuffer->pLast)
{
/* The position is below the last paragraph, so the last row will be used
* rather than the end of the text, so the x position will be used to
* determine the offset closest to the pixel position. */
p = ME_FindItemBack(p, diStartRow);
if (p != NULL){
p = ME_FindItemFwd(p, diRun);
}
else
{
p = editor->pBuffer->pLast;
}
}
for (; p != editor->pBuffer->pLast; p = p->next)
{
switch (p->type)
@ -855,7 +869,7 @@ ME_CharFromPos(ME_TextEditor *editor, int x, int y)
}
void ME_LButtonDown(ME_TextEditor *editor, int x, int y)
void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
{
ME_Cursor tmp_cursor;
int is_selection = 0;
@ -872,19 +886,15 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y)
ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd);
if (GetKeyState(VK_SHIFT)>=0)
{
/* Shift key is not down */
editor->pCursors[1] = editor->pCursors[0];
if (clickNum > 1)
ME_SelectWord(editor);
}
else if (!is_selection) {
editor->pCursors[1] = tmp_cursor;
is_selection = 1;
}
ME_InvalidateSelection(editor);
HideCaret(editor->hWnd);
ME_MoveCaret(editor);
ShowCaret(editor->hWnd);
ME_ClearTempStyle(editor);
ME_SendSelChange(editor);
}
else
{
@ -918,13 +928,13 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y)
}
editor->pCursors[2] = editor->pCursors[0];
editor->pCursors[3] = editor->pCursors[1];
ME_InvalidateSelection(editor);
HideCaret(editor->hWnd);
ME_MoveCaret(editor);
ShowCaret(editor->hWnd);
ME_ClearTempStyle(editor);
ME_SendSelChange(editor);
}
ME_InvalidateSelection(editor);
HideCaret(editor->hWnd);
ME_MoveCaret(editor);
ShowCaret(editor->hWnd);
ME_ClearTempStyle(editor);
ME_SendSelChange(editor);
}
void ME_MouseMove(ME_TextEditor *editor, int x, int y)
@ -967,6 +977,7 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y)
ME_InvalidateSelection(editor);
ShowCaret(editor->hWnd);
ME_SendSelChange(editor);
SendMessageW(editor->hWnd, EM_SCROLLCARET, 0, 0);
}
static ME_DisplayItem *ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow,
@ -976,13 +987,13 @@ static ME_DisplayItem *ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pR
pNext = ME_FindItemFwd(pRow, diRunOrStartRow);
assert(pNext->type == diRun);
pLastRun = pNext;
*pbCaretAtEnd = FALSE;
if (pbCaretAtEnd) *pbCaretAtEnd = FALSE;
if (pOffset) *pOffset = 0;
do {
int run_x = pNext->member.run.pt.x;
int width = pNext->member.run.nWidth;
if (x < run_x)
{
if (pOffset) *pOffset = 0;
return pNext;
}
if (x >= run_x && x < run_x+width)
@ -1002,12 +1013,9 @@ static ME_DisplayItem *ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pR
if ((pLastRun->member.run.nFlags & MERF_ENDPARA) == 0)
{
pNext = ME_FindItemFwd(pNext, diRun);
if (pbCaretAtEnd) *pbCaretAtEnd = 1;
if (pOffset) *pOffset = 0;
if (pbCaretAtEnd) *pbCaretAtEnd = TRUE;
return pNext;
} else {
if (pbCaretAtEnd) *pbCaretAtEnd = 0;
if (pOffset) *pOffset = 0;
return pLastRun;
}
}
@ -1179,9 +1187,6 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
{
ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow);
/* bCaretAtEnd doesn't make sense if the cursor isn't set at the
first character of the next row */
assert(!editor->bCaretAtEnd || !pCursor->nOffset);
ME_WrapMarkedParagraphs(editor);
if (pRow) {
ME_DisplayItem *pRun;
@ -1297,27 +1302,13 @@ void ME_DeleteSelection(ME_TextEditor *editor)
ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor)
{
ME_Style *style;
int from, to;
ME_GetSelection(editor, &from, &to);
if (from != to) {
ME_Cursor c;
ME_CursorFromCharOfs(editor, from, &c);
style = c.pRun->member.run.style;
ME_AddRefStyle(style); /* ME_GetInsertStyle has already done that */
}
else
style = ME_GetInsertStyle(editor, 0);
return style;
return ME_GetInsertStyle(editor, 0);
}
void ME_SendSelChange(ME_TextEditor *editor)
{
SELCHANGE sc;
ME_ClearTempStyle(editor);
if (!(editor->nEventMask & ENM_SELCHANGE))
return;
@ -1336,6 +1327,8 @@ void ME_SendSelChange(ME_TextEditor *editor)
(sc.seltyp & SEL_MULTICHAR) ? "SEL_MULTICHAR" : "");
if (sc.chrg.cpMin != editor->notified_cr.cpMin || sc.chrg.cpMax != editor->notified_cr.cpMax)
{
ME_ClearTempStyle(editor);
editor->notified_cr = sc.chrg;
SendMessageW(GetParent(editor->hWnd), WM_NOTIFY, sc.nmhdr.idFrom, (LPARAM)&sc);
}
@ -1350,7 +1343,6 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
BOOL success = FALSE;
ME_CheckCharOffsets(editor);
editor->nUDArrowX = -1;
switch(nVKey) {
case VK_LEFT:
editor->bCaretAtEnd = 0;

View file

@ -124,7 +124,7 @@
- EM_SETWORDWRAPMODE 1.0asian
+ EM_SETZOOM 3.0
+ EM_SHOWSCROLLBAR 2.0
- EM_STOPGROUPTYPING 2.0
+ EM_STOPGROUPTYPING 2.0
+ EM_STREAMIN
+ EM_STREAMOUT
+ EM_UNDO
@ -190,7 +190,6 @@
* RICHED20 TODO (incomplete):
*
* - messages/styles/notifications listed above
* - Undo coalescing
* - add remaining CHARFORMAT/PARAFORMAT fields
* - right/center align should strip spaces from the beginning
* - pictures/OLE objects (not just smiling faces that lack API support ;-) )
@ -970,11 +969,11 @@ static void ME_RTFReadHook(RTF_Info *info) {
{
ME_Style *s;
RTFFlushOutputBuffer(info);
if (info->stackTop<=1) {
info->stackTop--;
if (info->stackTop<=0) {
info->rtfClass = rtfEOF;
return;
}
info->stackTop--;
assert(info->stackTop >= 0);
if (info->styleChanged)
{
@ -1102,6 +1101,9 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
if (parser.lpRichEditOle)
IRichEditOle_Release(parser.lpRichEditOle);
if (!inStream.editstream->dwError && parser.stackTop > 0)
inStream.editstream->dwError = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
/* Remove last line break, as mandated by tests. This is not affected by
CR/LF counters, since RTF streaming presents only \para tokens, which
are converted according to the standard rules: \r for 2.0, \r\n for 1.0
@ -1148,7 +1150,9 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
if (!(format & SFF_SELECTION)) {
ME_ClearTempStyle(editor);
}
HideCaret(editor->hWnd);
ME_MoveCaret(editor);
ShowCaret(editor->hWnd);
ME_SendSelChange(editor);
ME_SendRequestResize(editor, FALSE);
@ -1366,7 +1370,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
break;
}
nStart += para->member.para.nCharOfs + pCurItem->member.run.nCharOfs;
nStart += para->member.para.nCharOfs + item->member.run.nCharOfs;
if (chrgText)
{
chrgText->cpMin = nStart;
@ -1538,31 +1542,52 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
{
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
case VK_HOME:
case VK_END:
editor->nUDArrowX = -1;
/* fall through */
case VK_UP:
case VK_DOWN:
case VK_PRIOR:
case VK_NEXT:
ME_CommitUndo(editor); /* End coalesced undos for typed characters */
ME_ArrowKey(editor, nKey, shift_is_down, ctrl_is_down);
return TRUE;
case VK_BACK:
case VK_DELETE:
editor->nUDArrowX = -1;
/* FIXME backspace and delete aren't the same, they act different wrt paragraph style of the merged paragraph */
if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_READONLY)
return FALSE;
if (ME_IsSelection(editor))
{
ME_DeleteSelection(editor);
else if (nKey == VK_DELETE || ME_ArrowKey(editor, VK_LEFT, FALSE, FALSE))
ME_CommitUndo(editor);
}
else if (nKey == VK_DELETE)
{
/* Delete stops group typing.
* (See MSDN remarks on EM_STOPGROUPTYPING message) */
ME_DeleteTextAtCursor(editor, 1, 1);
ME_CommitUndo(editor);
}
else if (ME_ArrowKey(editor, VK_LEFT, FALSE, FALSE))
{
/* Backspace can be grouped for a single undo */
ME_ContinueCoalescingTransaction(editor);
ME_DeleteTextAtCursor(editor, 1, 1);
ME_CommitCoalescingUndo(editor);
}
else
return TRUE;
ME_CommitUndo(editor);
ME_UpdateSelectionLinkAttribute(editor);
ME_UpdateRepaint(editor);
ME_SendRequestResize(editor, FALSE);
return TRUE;
default:
if (nKey != VK_SHIFT && nKey != VK_CONTROL && nKey && nKey != VK_MENU)
editor->nUDArrowX = -1;
if (ctrl_is_down)
{
if (nKey == 'W')
@ -1663,7 +1688,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ed->mode = TM_RICHTEXT | TM_MULTILEVELUNDO | TM_MULTICODEPAGE;
ed->AutoURLDetect_bEnable = FALSE;
ed->bHaveFocus = FALSE;
GetClientRect(hWnd, &ed->rcFormat);
for (i=0; i<HFONT_CACHE_SIZE; i++)
{
ed->pFontCache[i].nRefs = 0;
@ -1673,7 +1697,7 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ME_CheckCharOffsets(ed);
if (GetWindowLongW(hWnd, GWL_STYLE) & ES_SELECTIONBAR)
ed->selofs = 16;
ed->selofs = SELECTIONBAR_WIDTH;
else
ed->selofs = 0;
ed->linesel = 0;
@ -2045,11 +2069,9 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
return editor->pRedoStack != NULL;
case WM_UNDO: /* FIXME: actually not the same */
case EM_UNDO:
ME_Undo(editor);
return 0;
return ME_Undo(editor);
case EM_REDO:
ME_Redo(editor);
return 0;
return ME_Redo(editor);
case EM_GETOPTIONS:
{
/* these flags are equivalent to the ES_* counterparts */
@ -2089,7 +2111,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
if (settings & ECO_AUTOWORDSELECTION)
FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n");
if (settings & ECO_SELECTIONBAR)
editor->selofs = 16;
editor->selofs = SELECTIONBAR_WIDTH;
else
editor->selofs = 0;
ME_WrapMarkedParagraphs(editor);
@ -2180,6 +2202,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
ME_StreamInRTFString(editor, 0, (char *)lParam);
else ME_InsertTextFromCursor(editor, 0, wszText, len, style);
ME_ReleaseStyle(style);
if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor);
}
else {
ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
@ -2187,6 +2211,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
ME_StreamInRTFString(editor, 0, (char *)lParam);
else ME_InsertTextFromCursor(editor, 0, wszText, len, editor->pBuffer->pDefaultStyle);
len = 1;
if (editor->AutoURLDetect_bEnable) ME_UpdateLinkAttribute(editor, 0, -1);
}
ME_CommitUndo(editor);
if (!(pStruct->flags & ST_KEEPUNDO))
@ -2375,6 +2401,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
ME_ClearTempStyle(editor);
ME_EndToUnicode(unicode, wszText);
ME_CommitUndo(editor);
if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor);
if (!wParam)
ME_EmptyUndoStack(editor);
ME_UpdateRepaint(editor);
@ -2454,6 +2481,10 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
}
else
TRACE("WM_SETTEXT - NULL\n");
if (editor->AutoURLDetect_bEnable)
{
ME_UpdateLinkAttribute(editor, 0, -1);
}
ME_SetSelection(editor, 0, 0);
editor->nModifyStep = 0;
ME_CommitUndo(editor);
@ -2607,7 +2638,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
buffer = heap_alloc((crlfmul*nCount + 1) * sizeof(WCHAR));
buflen = ME_GetTextW(editor, buffer, nStart, nCount, ex->flags & GT_USECRLF);
rc = WideCharToMultiByte(ex->codepage, flags, buffer, -1, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar);
rc = WideCharToMultiByte(ex->codepage, flags, buffer, buflen+1, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar);
if (rc) rc--; /* do not count 0 terminator */
heap_free(buffer);
@ -2889,6 +2920,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
ME_DisplayItem *pRun;
int nCharOfs, nOffset, nLength;
POINTL pt = {0,0};
SCROLLINFO si;
nCharOfs = wParam;
/* detect which API version we're dealing with */
@ -2907,12 +2939,21 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
pt.y = editor->pBuffer->pLast->member.para.nYPos;
}
pt.x += editor->selofs;
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
if (GetScrollInfo(editor->hWnd, SB_VERT, &si)) pt.y -= si.nPos;
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
if (GetScrollInfo(editor->hWnd, SB_HORZ, &si)) pt.x -= si.nPos;
if (wParam >= 0x40000) {
*(POINTL *)wParam = pt;
}
return MAKELONG( pt.x, pt.y );
return (wParam >= 0x40000) ? 0 : MAKELONG( pt.x, pt.y );
}
case WM_CREATE:
GetClientRect(hWnd, &editor->rcFormat);
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL)
{ /* Squelch the default horizontal scrollbar it would make */
ShowScrollBar(editor->hWnd, SB_HORZ, FALSE);
@ -2925,16 +2966,22 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
ME_DestroyEditor(editor);
SetWindowLongPtrW(hWnd, 0, 0);
return 0;
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
{
int clickNum = (msg == WM_LBUTTONDBLCLK) ? 2 : 1;
ME_CommitUndo(editor); /* End coalesced undos for typed characters */
if ((editor->nEventMask & ENM_MOUSEEVENTS) &&
!ME_FilterEvent(editor, msg, &wParam, &lParam))
return 0;
SetFocus(hWnd);
ME_LButtonDown(editor, (short)LOWORD(lParam), (short)HIWORD(lParam));
ME_LButtonDown(editor, (short)LOWORD(lParam), (short)HIWORD(lParam),
clickNum);
SetCapture(hWnd);
ME_LinkNotify(editor,msg,wParam,lParam);
if (!ME_SetCursor(editor, LOWORD(lParam))) goto do_default;
break;
}
case WM_MOUSEMOVE:
if ((editor->nEventMask & ENM_MOUSEEVENTS) &&
!ME_FilterEvent(editor, msg, &wParam, &lParam))
@ -2959,15 +3006,9 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
if (!ret) goto do_default;
}
break;
case WM_LBUTTONDBLCLK:
if ((editor->nEventMask & ENM_MOUSEEVENTS) &&
!ME_FilterEvent(editor, msg, &wParam, &lParam))
return 0;
ME_LinkNotify(editor,msg,wParam,lParam);
ME_SelectWord(editor);
break;
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
ME_CommitUndo(editor); /* End coalesced undos for typed characters */
if ((editor->nEventMask & ENM_MOUSEEVENTS) &&
!ME_FilterEvent(editor, msg, &wParam, &lParam))
return 0;
@ -2993,6 +3034,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
ME_SendOldNotify(editor, EN_SETFOCUS);
return 0;
case WM_KILLFOCUS:
ME_CommitUndo(editor); /* End coalesced undos for typed characters */
ME_HideCaret(editor);
editor->bHaveFocus = FALSE;
ME_SendOldNotify(editor, EN_KILLFOCUS);
@ -3036,9 +3078,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
CHAR charA = wParam;
MultiByteToWideChar(CP_ACP, 0, &charA, 1, &wstr, 1);
}
if (editor->AutoURLDetect_bEnable)
ME_AutoURLDetect(editor, wstr);
switch (wstr)
{
case 1: /* Ctrl-A */
@ -3080,17 +3120,24 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
{
ME_Style *style = ME_GetInsertStyle(editor, 0);
ME_SaveTempStyle(editor);
ME_ContinueCoalescingTransaction(editor);
if (wstr == '\r' && (GetKeyState(VK_SHIFT) & 0x8000))
ME_InsertEndRowFromCursor(editor, 0);
else
ME_InsertTextFromCursor(editor, 0, &wstr, 1, style);
ME_ReleaseStyle(style);
ME_CommitUndo(editor);
ME_CommitCoalescingUndo(editor);
}
if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor);
ME_UpdateRepaint(editor);
}
return 0;
}
case EM_STOPGROUPTYPING:
ME_CommitUndo(editor); /* End coalesced undos for typed characters */
return 0;
case EM_SCROLL: /* fall through */
case WM_VSCROLL:
{
@ -3449,9 +3496,11 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in
CopyMemory(buffer, item->member.run.strText->szData + nStart, sizeof(WCHAR)*nLen);
nChars -= nLen;
nWritten += nLen;
if (!nChars)
return nWritten;
buffer += nLen;
if (!nChars) {
*buffer = 0;
return nWritten;
}
nStart = 0;
item = ME_FindItemFwd(item, diRun);
}
@ -3713,3 +3762,277 @@ int ME_AutoURLDetect(ME_TextEditor *editor, WCHAR curChar)
}
return 0;
}
static BOOL isurlspecial(WCHAR c)
{
static const WCHAR special_chars[] = {'.','/','%','@','*','|','\\','+','#',0};
return strchrW( special_chars, c ) != NULL;
}
/**
* This proc takes a selection, and scans it forward in order to select the span
* of a possible URL candidate. A possible URL candidate must start with isalnum
* or one of the following special characters: *|/\+%#@ and must consist entirely
* of the characters allowed to start the URL, plus : (colon) which may occur
* at most once, and not at either end.
*
* sel_max == -1 indicates scan to end of text.
*/
BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_max,
int * candidate_min, int * candidate_max)
{
ME_DisplayItem * item;
ME_DisplayItem * para;
int nStart;
BOOL foundColon = FALSE;
WCHAR lastAcceptedChar = '\0';
TRACE("sel_min = %d sel_max = %d\n", sel_min, sel_max);
*candidate_min = *candidate_max = -1;
item = ME_FindItemAtOffset(editor, diRun, sel_min, &nStart);
if (!item) return FALSE;
TRACE("nStart = %d\n", nStart);
para = ME_GetParagraph(item);
if (sel_max == -1) sel_max = ME_GetTextLength(editor);
while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart < sel_max)
{
ME_DisplayItem * next_item;
if (!(item->member.run.nFlags & MERF_ENDPARA)) {
/* Find start of candidate */
if (*candidate_min == -1) {
while (nStart < ME_StrLen(item->member.run.strText) &&
!(isalnumW(item->member.run.strText->szData[nStart]) ||
isurlspecial(item->member.run.strText->szData[nStart]))) {
nStart++;
}
if (nStart < ME_StrLen(item->member.run.strText) &&
(isalnumW(item->member.run.strText->szData[nStart]) ||
isurlspecial(item->member.run.strText->szData[nStart]))) {
*candidate_min = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart;
lastAcceptedChar = item->member.run.strText->szData[nStart];
nStart++;
}
}
/* Find end of candidate */
if (*candidate_min >= 0) {
while (nStart < ME_StrLen(item->member.run.strText) &&
(isalnumW(item->member.run.strText->szData[nStart]) ||
isurlspecial(item->member.run.strText->szData[nStart]) ||
(!foundColon && item->member.run.strText->szData[nStart] == ':') )) {
if (item->member.run.strText->szData[nStart] == ':') foundColon = TRUE;
lastAcceptedChar = item->member.run.strText->szData[nStart];
nStart++;
}
if (nStart < ME_StrLen(item->member.run.strText) &&
!(isalnumW(item->member.run.strText->szData[nStart]) ||
isurlspecial(item->member.run.strText->szData[nStart]) )) {
*candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart;
nStart++;
if (lastAcceptedChar == ':') (*candidate_max)--;
return TRUE;
}
}
} else {
/* End of paragraph: skip it if before candidate span, or terminates
current active span */
if (*candidate_min >= 0) {
*candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs;
if (lastAcceptedChar == ':') (*candidate_max)--;
return TRUE;
}
}
/* Reaching this point means no span was found, so get next span */
next_item = ME_FindItemFwd(item, diRun);
if (!next_item) {
if (*candidate_min >= 0) {
/* There are no further runs, so take end of text as end of candidate */
*candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart;
if (lastAcceptedChar == ':') (*candidate_max)--;
return TRUE;
}
}
item = next_item;
para = ME_GetParagraph(item);
nStart = 0;
}
if (item) {
if (*candidate_min >= 0) {
/* There are no further runs, so take end of text as end of candidate */
*candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart;
if (lastAcceptedChar == ':') (*candidate_max)--;
return TRUE;
}
}
return FALSE;
}
/**
* This proc evaluates the selection and returns TRUE if it can be considered an URL
*/
BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max)
{
struct prefix_s {
const char *text;
int length;
} prefixes[12] = {
/* Code below depends on these being in decreasing length order! */
{"prospero:", 10},
{"telnet:", 8},
{"gopher:", 8},
{"mailto:", 8},
{"https:", 7},
{"file:", 6},
{"news:", 6},
{"wais:", 6},
{"nntp:", 6},
{"http:", 5},
{"www.", 5},
{"ftp:", 5},
};
LPWSTR bufferW = NULL;
WCHAR bufW[32];
int i;
if (sel_max == -1) sel_max = ME_GetTextLength(editor);
assert(sel_min <= sel_max);
for (i = 0; i < sizeof(prefixes) / sizeof(struct prefix_s); i++)
{
if (sel_max - sel_min < prefixes[i].length) continue;
if (bufferW == NULL) {
bufferW = (LPWSTR)heap_alloc((sel_max - sel_min + 1) * sizeof(WCHAR));
}
ME_GetTextW(editor, bufferW, sel_min, min(sel_max - sel_min, strlen(prefixes[i].text)), 0);
MultiByteToWideChar(CP_ACP, 0, prefixes[i].text, -1, bufW, 32);
if (!lstrcmpW(bufW, bufferW))
{
heap_free(bufferW);
return TRUE;
}
}
heap_free(bufferW);
return FALSE;
}
/**
* This proc walks through the indicated selection and evaluates whether each
* section identified by ME_FindNextURLCandidate and in-between sections have
* their proper CFE_LINK attributes set or unset. If the CFE_LINK attribute is
* not what it is supposed to be, this proc sets or unsets it as appropriate.
*
* Returns TRUE if at least one section was modified.
*/
BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_max)
{
BOOL modified = FALSE;
int cMin, cMax;
if (sel_max == -1) sel_max = ME_GetTextLength(editor);
do
{
int beforeURL[2];
int inURL[2];
CHARFORMAT2W link;
if (ME_FindNextURLCandidate(editor, sel_min, sel_max, &cMin, &cMax))
{
/* Section before candidate is not an URL */
beforeURL[0] = sel_min;
beforeURL[1] = cMin;
if (ME_IsCandidateAnURL(editor, cMin, cMax))
{
inURL[0] = cMin; inURL[1] = cMax;
}
else
{
beforeURL[1] = cMax;
inURL[0] = inURL[1] = -1;
}
sel_min = cMax;
}
else
{
/* No more candidates until end of selection */
beforeURL[0] = sel_min;
beforeURL[1] = sel_max;
inURL[0] = inURL[1] = -1;
sel_min = sel_max;
}
if (beforeURL[0] < beforeURL[1])
{
/* CFE_LINK effect should be consistently unset */
link.cbSize = sizeof(link);
ME_GetCharFormat(editor, beforeURL[0], beforeURL[1], &link);
if (!(link.dwMask & CFM_LINK) || (link.dwEffects & CFE_LINK))
{
/* CFE_LINK must be unset from this range */
memset(&link, 0, sizeof(CHARFORMAT2W));
link.cbSize = sizeof(link);
link.dwMask = CFM_LINK;
link.dwEffects = 0;
ME_SetCharFormat(editor, beforeURL[0], beforeURL[1] - beforeURL[0], &link);
modified = TRUE;
}
}
if (inURL[0] < inURL[1])
{
/* CFE_LINK effect should be consistently set */
link.cbSize = sizeof(link);
ME_GetCharFormat(editor, inURL[0], inURL[1], &link);
if (!(link.dwMask & CFM_LINK) || !(link.dwEffects & CFE_LINK))
{
/* CFE_LINK must be set on this range */
memset(&link, 0, sizeof(CHARFORMAT2W));
link.cbSize = sizeof(link);
link.dwMask = CFM_LINK;
link.dwEffects = CFE_LINK;
ME_SetCharFormat(editor, inURL[0], inURL[1] - inURL[0], &link);
modified = TRUE;
}
}
} while (sel_min < sel_max);
return modified;
}
void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor)
{
ME_DisplayItem * startPara, * endPara;
ME_DisplayItem * item;
int dummy;
int from, to;
ME_GetSelection(editor, &from, &to);
if (from > to) from ^= to, to ^=from, from ^= to;
startPara = NULL; endPara = NULL;
/* Find paragraph previous to the one that contains start cursor */
item = ME_FindItemAtOffset(editor, diRun, from, &dummy);
if (item) {
startPara = ME_FindItemBack(item, diParagraph);
item = ME_FindItemBack(startPara, diParagraph);
if (item) startPara = item;
}
/* Find paragraph that contains end cursor */
item = ME_FindItemAtOffset(editor, diRun, to, &dummy);
if (item) {
endPara = ME_FindItemFwd(item, diParagraph);
}
if (startPara && endPara) {
ME_UpdateLinkAttribute(editor,
startPara->member.para.nCharOfs,
endPara->member.para.nCharOfs);
} else if (startPara) {
ME_UpdateLinkAttribute(editor,
startPara->member.para.nCharOfs,
-1);
}
}

View file

@ -181,7 +181,7 @@ void ME_HideCaret(ME_TextEditor *ed);
void ME_ShowCaret(ME_TextEditor *ed);
void ME_MoveCaret(ME_TextEditor *ed);
int ME_CharFromPos(ME_TextEditor *editor, int x, int y);
void ME_LButtonDown(ME_TextEditor *editor, int x, int y);
void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum);
void ME_MouseMove(ME_TextEditor *editor, int x, int y);
void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars);
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
@ -214,8 +214,6 @@ void ME_DestroyContext(ME_Context *c, HWND release);
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor);
void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor);
void ME_SendRequestResize(ME_TextEditor *editor, BOOL force);
int ME_twips2pointsX(ME_Context *c, int x);
int ME_twips2pointsY(ME_Context *c, int y);
/* para.c */
ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run);
@ -244,6 +242,8 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun);
void ME_InvalidateSelection(ME_TextEditor *editor);
void ME_QueueInvalidateFromCursor(ME_TextEditor *editor, int nCursor);
BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator);
int ME_twips2pointsX(ME_Context *c, int x);
int ME_twips2pointsY(ME_Context *c, int y);
/* scroll functions in paint.c */
@ -279,12 +279,19 @@ void ME_StreamInFill(ME_InStream *stream);
int ME_AutoURLDetect(ME_TextEditor *editor, WCHAR curChar);
extern int me_debug;
extern void DoWrap(ME_TextEditor *editor);
extern BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_max,
int * candidate_min, int * candidate_max);
extern BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max);
BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_max);
void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor);
/* undo.c */
ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_DisplayItem *pdi);
void ME_CommitUndo(ME_TextEditor *editor);
void ME_Undo(ME_TextEditor *editor);
void ME_Redo(ME_TextEditor *editor);
void ME_ContinueCoalescingTransaction(ME_TextEditor *editor);
void ME_CommitCoalescingUndo(ME_TextEditor *editor);
BOOL ME_Undo(ME_TextEditor *editor);
BOOL ME_Redo(ME_TextEditor *editor);
void ME_EmptyUndoStack(ME_TextEditor *editor);
/* writer.c */

View file

@ -85,10 +85,13 @@ typedef enum {
diUndoSplitParagraph, /* 14 */
diUndoSetParagraphFormat, /* 15 */
diUndoSetCharFormat, /* 16 */
diUndoEndTransaction, /* 17 */
diUndoEndTransaction, /* 17 - marks the end of a group of changes for undo */
diUndoSetDefaultCharFormat, /* 18 */
diUndoPotentialEndTransaction, /* 19 - allows grouping typed chars for undo */
} ME_DIType;
#define SELECTIONBAR_WIDTH 9
/******************************** run flags *************************/
#define MERF_STYLEFLAGS 0x0FFF
/* run contains non-text content, which has its own rules for wrapping, sizing etc */

View file

@ -169,6 +169,7 @@ const char *ME_GetDITypeName(ME_DIType type)
case diTextEnd: return "diTextEnd";
case diStartRow: return "diStartRow";
case diUndoEndTransaction: return "diUndoEndTransaction";
case diUndoPotentialEndTransaction: return "diUndoPotentialEndTransaction";
case diUndoSetParagraphFormat: return "diUndoSetParagraphFormat";
case diUndoSetCharFormat: return "diUndoSetCharFormat";
case diUndoInsertRun: return "diUndoInsertRun";

View file

@ -98,7 +98,8 @@ void ME_Repaint(ME_TextEditor *editor)
ME_UpdateScrollBar(editor);
FIXME("ME_Repaint had to call ME_WrapMarkedParagraphs\n");
}
ME_SendOldNotify(editor, EN_UPDATE);
if (!editor->bEmulateVersion10 || (editor->nEventMask & ENM_UPDATE))
ME_SendOldNotify(editor, EN_UPDATE);
UpdateWindow(editor->hWnd);
}
@ -288,7 +289,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa
}
}
static struct {unsigned width_num : 4, width_den : 4, pen_style : 4, dble : 1;} border_details[] = {
static const struct {unsigned width_num : 4, width_den : 4, pen_style : 4, dble : 1;} border_details[] = {
/* none */ {0, 1, PS_SOLID, FALSE},
/* 3/4 */ {3, 4, PS_SOLID, FALSE},
/* 1 1/2 */ {3, 2, PS_SOLID, FALSE},
@ -303,7 +304,7 @@ static struct {unsigned width_num : 4, width_den : 4, pen_style : 4, dble : 1;}
/* 1 1/2 dashed */ {3, 2, PS_DASH, FALSE},
};
static COLORREF pen_colors[16] = {
static const COLORREF pen_colors[16] = {
/* Black */ RGB(0x00, 0x00, 0x00), /* Blue */ RGB(0x00, 0x00, 0xFF),
/* Cyan */ RGB(0x00, 0xFF, 0xFF), /* Green */ RGB(0x00, 0xFF, 0x00),
/* Magenta */ RGB(0xFF, 0x00, 0xFF), /* Red */ RGB(0xFF, 0x00, 0x00),
@ -675,7 +676,7 @@ void ME_Scroll(ME_TextEditor *editor, int value, int type)
si.nMin = 0;
si.nMax = editor->nTotalLength;
si.nPage = editor->sizeWindow.cy;
TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage);

View file

@ -52,7 +52,8 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
cf.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR;
lstrcpyW(cf.szFaceName, lf.lfFaceName);
cf.yHeight = ME_twips2pointsY(&c, lf.lfHeight);
/* Convert system font height from logical units to twips for cf.yHeight */
cf.yHeight = (lf.lfHeight * 72 * 1440) / (c.dpi.cy * c.dpi.cy);
if (lf.lfWeight > FW_NORMAL) cf.dwEffects |= CFE_BOLD;
cf.wWeight = lf.lfWeight;
if (lf.lfItalic) cf.dwEffects |= CFE_ITALIC;
@ -104,7 +105,7 @@ void ME_MarkForWrapping(ME_TextEditor *editor, ME_DisplayItem *first, const ME_D
void ME_MarkForPainting(ME_TextEditor *editor, ME_DisplayItem *first, const ME_DisplayItem *last)
{
while(first != last)
while(first != last && first)
{
first->member.para.nFlags |= MEPF_REPAINT;
first = first->member.para.next_para;

View file

@ -638,14 +638,16 @@ static void _RTFGetToken2(RTF_Info *info)
{
int c2;
if ((c = GetChar (info)) != EOF && (c2 = GetChar (info)) != EOF)
if ((c = GetChar (info)) != EOF && (c2 = GetChar (info)) != EOF
&& isxdigit(c) && isxdigit(c2))
{
/* should do isxdigit check! */
info->rtfClass = rtfText;
info->rtfMajor = RTFCharToHex (c) * 16 + RTFCharToHex (c2);
return;
}
/* early eof, whoops (class is rtfUnknown) */
/* early eof, whoops */
info->rtfClass = rtfEOF;
info->stream->editstream->dwError = -14;
return;
}
@ -2665,10 +2667,10 @@ RTFPutUnicodeString(RTF_Info *info, const WCHAR *string, int length)
memmove(info->OutputBuffer + info->dwOutputCount, string, fit * sizeof(WCHAR));
info->dwOutputCount += fit;
if (fit == sizeof(info->OutputBuffer) / sizeof(WCHAR) - info->dwOutputCount)
RTFFlushUnicodeOutputBuffer(info);
length -= fit;
string += fit;
if (sizeof(info->OutputBuffer) / sizeof(WCHAR) == info->dwOutputCount)
RTFFlushUnicodeOutputBuffer(info);
}
}

View file

@ -8,14 +8,6 @@
<define name="__WINESRC__" />
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>ole32</library>
<library>imm32</library>
<library>user32</library>
<library>gdi32</library>
<library>kernel32</library>
<library>uuid</library>
<library>ntdll</library>
<file>caret.c</file>
<file>clipboard.c</file>
<file>context.c</file>
@ -35,5 +27,13 @@
<file>writer.c</file>
<file>version.rc</file>
<file>riched20.spec</file>
<library>wine</library>
<library>uuid</library>
<library>ole32</library>
<library>imm32</library>
<library>user32</library>
<library>gdi32</library>
<library>kernel32</library>
<library>ntdll</library>
</module>
</group>

File diff suppressed because it is too large Load diff

View file

@ -241,11 +241,7 @@ void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p)
assert(p->member.run.nCharOfs != -1);
ME_GetParagraph(p)->member.para.nFlags |= MEPF_REWRAP;
/* if we were at the end of screen line, and the next run is in the new
* line, then it's not the end of the line anymore */
if (editor->bCaretAtEnd && editor->pCursors[0].pRun == pNext)
editor->bCaretAtEnd = FALSE;
/* Update all cursors so that they don't contain the soon deleted run */
/* Update all cursors so that they don't contain the soon deleted run */
for (i=0; i<editor->nCursors; i++) {
if (editor->pCursors[i].pRun == pNext) {
editor->pCursors[i].pRun = p;
@ -682,9 +678,9 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run
}
else
{
pos += 720-(pos%720);
pos += lDefaultTab - (pos % lDefaultTab);
}
ppos = ME_twips2pointsX(c, pos);
ppos = ME_twips2pointsX(c, pos) + c->editor->selofs;
if (ppos > startx + run->pt.x) {
size.cx = ppos - startx - run->pt.x;
break;
@ -838,6 +834,7 @@ void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod)
ME_Style *style;
ME_UndoItem *undo;
/* FIXME: Should this be removed? It breaks a test. */
assert(mod->cbSize == sizeof(CHARFORMAT2W));
undo = ME_AddUndoItem(editor, diUndoSetDefaultCharFormat, NULL);
if (undo) {
@ -857,6 +854,16 @@ void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod)
static void ME_GetRunCharFormat(ME_TextEditor *editor, ME_DisplayItem *run, CHARFORMAT2W *pFmt)
{
ME_CopyCharFormat(pFmt, &run->member.run.style->fmt);
if ((pFmt->dwMask & CFM_UNDERLINETYPE) && (pFmt->bUnderlineType == CFU_CF1UNDERLINE))
{
pFmt->dwMask |= CFM_UNDERLINE;
pFmt->dwEffects |= CFE_UNDERLINE;
}
if ((pFmt->dwMask & CFM_UNDERLINETYPE) && (pFmt->bUnderlineType == CFU_UNDERLINENONE))
{
pFmt->dwMask |= CFM_UNDERLINE;
pFmt->dwEffects &= ~CFE_UNDERLINE;
}
}
/******************************************************************************
@ -928,7 +935,7 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p
do {
/* FIXME add more style feature comparisons */
int nAttribs = CFM_SIZE | CFM_FACE | CFM_COLOR | CFM_UNDERLINETYPE;
int nEffects = CFM_BOLD | CFM_ITALIC;
int nEffects = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT | CFM_PROTECTED | CFM_LINK | CFM_SUPERSCRIPT;
run = ME_FindItemFwd(run, diRun);
@ -937,7 +944,6 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p
ME_GetRunCharFormat(editor, run, &tmp);
assert((tmp.dwMask & nAttribs) == nAttribs);
assert((tmp.dwMask & nEffects) == nEffects);
/* reset flags that differ */
if (pFmt->yHeight != tmp.yHeight)
@ -964,6 +970,7 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p
}
pFmt->dwMask &= ~((pFmt->dwEffects ^ tmp.dwEffects) & nEffects);
pFmt->dwEffects = tmp.dwEffects;
} while(run != run_end);
}

View file

@ -128,7 +128,7 @@ ME_String *ME_VSplitString(ME_String *orig, int charidx)
assert(charidx>=0);
assert(charidx<=orig->nLen);
s = ME_MakeString(orig->szData+charidx);
s = ME_MakeStringN(orig->szData+charidx, orig->nLen-charidx);
orig->nLen = charidx;
orig->szData[charidx] = '\0';
return s;
@ -317,18 +317,10 @@ ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code)
return start;
case WB_RIGHT:
case WB_MOVEWORDRIGHT:
if (start && ME_IsWSpace(s[start - 1]))
{
while (start < len && ME_IsWSpace(s[start]))
start++;
}
else
{
while (start < len && !ME_IsWSpace(s[start]))
start++;
while (start < len && ME_IsWSpace(s[start]))
start++;
}
while (start < len && !ME_IsWSpace(s[start]))
start++;
while (start < len && ME_IsWSpace(s[start]))
start++;
return start;
}
return 0;

View file

@ -221,6 +221,15 @@ ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style)
s->fmt.bUnderlineType = (style->dwEffects & CFM_UNDERLINE) ?
CFU_CF1UNDERLINE : CFU_UNDERLINENONE;
}
if (style->dwMask & CFM_BOLD && !(style->dwMask & CFM_WEIGHT))
{
s->fmt.wWeight = (style->dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL;
} else if (style->dwMask & CFM_WEIGHT && !(style->dwMask & CFM_BOLD)) {
if (style->wWeight > FW_NORMAL)
s->fmt.dwEffects |= CFE_BOLD;
else
s->fmt.dwEffects &= ~CFE_BOLD;
}
return s;
}

View file

@ -59,6 +59,10 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp
((ME_UndoItem *)pItem)->nCR = ((ME_UndoItem *)pItem)->nLF = -1;
switch(type)
{
case diUndoPotentialEndTransaction:
/* only should be added for manually typed chars, not undos or redos */
assert(editor->nUndoMode == umAddToUndo);
/* intentional fall-through to next case */
case diUndoEndTransaction:
break;
case diUndoSetParagraphFormat:
@ -99,13 +103,18 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp
pItem->prev = NULL;
if (editor->nUndoMode == umAddToUndo || editor->nUndoMode == umAddBackToUndo)
{
if (editor->pUndoStack
&& editor->pUndoStack->type == diUndoPotentialEndTransaction)
{
editor->pUndoStack->type = diUndoEndTransaction;
}
if (editor->nUndoMode == umAddToUndo)
TRACE("Pushing id=%s to undo stack, deleting redo stack\n", ME_GetDITypeName(type));
else
TRACE("Pushing id=%s to undo stack\n", ME_GetDITypeName(type));
pItem->next = editor->pUndoStack;
if (type == diUndoEndTransaction)
if (type == diUndoEndTransaction || type == diUndoPotentialEndTransaction)
editor->nUndoStackSize++;
if (editor->pUndoStack)
editor->pUndoStack->prev = pItem;
@ -154,6 +163,18 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp
}
}
/**
* Commits preceding changes into a transaction that can be undone together.
*
* This should be called after all the changes occur associated with an event
* so that the group of changes can be undone atomically as a transaction.
*
* This will have no effect the undo mode is set to ignore changes, or if no
* changes preceded calling this function before the last time it was called.
*
* This can also be used to conclude a coalescing transaction (used for grouping
* typed characters).
*/
void ME_CommitUndo(ME_TextEditor *editor) {
if (editor->nUndoMode == umIgnore)
return;
@ -168,10 +189,84 @@ void ME_CommitUndo(ME_TextEditor *editor) {
if (editor->pUndoStack->type == diUndoEndTransaction)
return;
if (editor->pUndoStack->type == diUndoPotentialEndTransaction)
{
/* Previous transaction was as a result of characters typed,
* so the end of this transaction is confirmed. */
editor->pUndoStack->type = diUndoEndTransaction;
return;
}
ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
ME_SendSelChange(editor);
}
/**
* Groups supsequent changes with previous ones for an undo if coalescing.
*
* Has no effect if the previous changes were followed by a ME_CommitUndo. This
* function will only have an affect if the previous changes were followed by
* a call to ME_CommitCoalescingUndo, which allows the transaction to be
* continued.
*
* This allows multiple consecutively typed characters to be grouped together
* to be undone by a single undo operation.
*/
void ME_ContinueCoalescingTransaction(ME_TextEditor *editor)
{
ME_DisplayItem* p;
if (editor->nUndoMode == umIgnore)
return;
assert(editor->nUndoMode == umAddToUndo);
p = editor->pUndoStack;
if (p && p->type == diUndoPotentialEndTransaction) {
assert(p->next); /* EndTransactions shouldn't be at bottom of undo stack */
editor->pUndoStack = p->next;
editor->pUndoStack->prev = NULL;
editor->nUndoStackSize--;
ME_DestroyDisplayItem(p);
}
}
/**
* Commits preceding changes into a undo transaction that can be expanded.
*
* This function allows the transaction to be reopened with
* ME_ContinueCoalescingTransaction in order to continue the transaction. If an
* undo item is added to the undo stack as a result of a change without the
* transaction being reopened, then the transaction will be ended, and the
* changes will become a part of the next transaction.
*
* This is used to allow typed characters to be grouped together since each
* typed character results in a single event, and each event adding undo items
* must be committed. Using this function as opposed to ME_CommitUndo allows
* multiple events to be grouped, and undone together.
*/
void ME_CommitCoalescingUndo(ME_TextEditor *editor)
{
if (editor->nUndoMode == umIgnore)
return;
assert(editor->nUndoMode == umAddToUndo);
/* no transactions, no need to commit */
if (!editor->pUndoStack)
return;
/* no need to commit empty transactions */
if (editor->pUndoStack->type == diUndoEndTransaction)
return;
if (editor->pUndoStack->type == diUndoPotentialEndTransaction)
return;
ME_AddUndoItem(editor, diUndoPotentialEndTransaction, NULL);
ME_SendSelChange(editor);
}
static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
{
ME_UndoItem *pUItem = (ME_UndoItem *)pItem;
@ -182,6 +277,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
switch(pItem->type)
{
case diUndoPotentialEndTransaction:
case diUndoEndTransaction:
assert(0);
case diUndoSetParagraphFormat:
@ -239,50 +335,53 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
}
}
void ME_Undo(ME_TextEditor *editor) {
BOOL ME_Undo(ME_TextEditor *editor) {
ME_DisplayItem *p;
ME_UndoMode nMode = editor->nUndoMode;
if (editor->nUndoMode == umIgnore)
return;
return FALSE;
assert(nMode == umAddToUndo || nMode == umIgnore);
/* no undo items ? */
if (!editor->pUndoStack)
return;
return FALSE;
/* watch out for uncommitted transactions ! */
assert(editor->pUndoStack->type == diUndoEndTransaction);
assert(editor->pUndoStack->type == diUndoEndTransaction
|| editor->pUndoStack->type == diUndoPotentialEndTransaction);
editor->nUndoMode = umAddToRedo;
p = editor->pUndoStack->next;
ME_DestroyDisplayItem(editor->pUndoStack);
do {
ME_DisplayItem *pp = p;
ME_PlayUndoItem(editor, p);
p = p->next;
ME_DestroyDisplayItem(pp);
} while(p && p->type != diUndoEndTransaction);
ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
editor->pUndoStack = p;
editor->nUndoStackSize--;
do {
p->prev = NULL;
ME_PlayUndoItem(editor, p);
editor->pUndoStack = p->next;
ME_DestroyDisplayItem(p);
p = editor->pUndoStack;
} while(p && p->type != diUndoEndTransaction);
if (p)
p->prev = NULL;
ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
editor->nUndoStackSize--;
editor->nUndoMode = nMode;
ME_UpdateRepaint(editor);
return TRUE;
}
void ME_Redo(ME_TextEditor *editor) {
BOOL ME_Redo(ME_TextEditor *editor) {
ME_DisplayItem *p;
ME_UndoMode nMode = editor->nUndoMode;
assert(nMode == umAddToUndo || nMode == umIgnore);
if (editor->nUndoMode == umIgnore)
return;
return FALSE;
/* no redo items ? */
if (!editor->pRedoStack)
return;
return FALSE;
/* watch out for uncommitted transactions ! */
assert(editor->pRedoStack->type == diUndoEndTransaction);
@ -290,16 +389,18 @@ void ME_Redo(ME_TextEditor *editor) {
editor->nUndoMode = umAddBackToUndo;
p = editor->pRedoStack->next;
ME_DestroyDisplayItem(editor->pRedoStack);
do {
ME_DisplayItem *pp = p;
ME_PlayUndoItem(editor, p);
p = p->next;
ME_DestroyDisplayItem(pp);
} while(p && p->type != diUndoEndTransaction);
ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
editor->pRedoStack = p;
do {
p->prev = NULL;
ME_PlayUndoItem(editor, p);
editor->pRedoStack = p->next;
ME_DestroyDisplayItem(p);
p = editor->pRedoStack;
} while(p && p->type != diUndoEndTransaction);
if (p)
p->prev = NULL;
ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
editor->nUndoMode = nMode;
ME_UpdateRepaint(editor);
return TRUE;
}

View file

@ -58,21 +58,47 @@ static void ME_BeginRow(ME_WrapContext *wc)
static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
{
ME_DisplayItem *p, *row, *para;
BOOL bSkippingSpaces = TRUE;
int ascent = 0, descent = 0, width=0, shift = 0, align = 0;
/* wrap text */
para = ME_GetParagraph(wc->pRowStart);
for (p = wc->pRowStart; p!=pEnd; p = p->next)
for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev)
{
/* ENDPARA run shouldn't affect row height, except if it's the only run in the paragraph */
if (p->type==diRun && ((p==wc->pRowStart) || !(p->member.run.nFlags & MERF_ENDPARA))) { /* FIXME add more run types */
if (p->member.run.nAscent>ascent)
ascent = p->member.run.nAscent;
if (p->member.run.nDescent>descent)
descent = p->member.run.nDescent;
if (!(p->member.run.nFlags & (MERF_ENDPARA|MERF_SKIPPED)))
width += p->member.run.nWidth;
}
/* ENDPARA run shouldn't affect row height, except if it's the only run in the paragraph */
if (p->type==diRun && ((p==wc->pRowStart) || !(p->member.run.nFlags & MERF_ENDPARA))) { /* FIXME add more run types */
if (p->member.run.nAscent>ascent)
ascent = p->member.run.nAscent;
if (p->member.run.nDescent>descent)
descent = p->member.run.nDescent;
if (bSkippingSpaces)
{
/* Exclude space characters from run width.
* Other whitespace or delimiters are not treated this way. */
SIZE sz;
int len = p->member.run.strText->nLen;
WCHAR *text = p->member.run.strText->szData + len - 1;
assert (len);
while (len && *(text--) == ' ')
len--;
if (len)
{
if (len == p->member.run.strText->nLen)
{
width += p->member.run.nWidth;
} else {
sz = ME_GetRunSize(wc->context, &para->member.para,
&p->member.run, len, p->member.run.pt.x);
width += sz.cx;
}
}
bSkippingSpaces = !len;
} else if (!(p->member.run.nFlags & MERF_ENDPARA))
width += p->member.run.nWidth;
}
}
row = ME_MakeRow(ascent+descent, ascent, width);
row->member.row.nYPos = wc->pt.y;
row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin);
@ -98,7 +124,7 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p)
{
if (wc->pRowStart)
ME_InsertRowStart(wc, p->next);
ME_InsertRowStart(wc, p);
/*
p = p->member.para.prev_para->next;
@ -471,6 +497,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
ME_Context c;
BOOL bModified = FALSE;
int yStart = -1;
int yLastPos = 0;
ME_InitContext(&c, editor, GetDC(editor->hWnd));
editor->nHeight = 0;
@ -496,6 +523,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
bModified = bModified | bRedraw;
yLastPos = c.pt.y;
c.pt.y += item->member.para.nHeight;
item = item->member.para.next_para;
}
@ -503,6 +531,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top;
editor->nTotalLength = c.pt.y;
editor->pBuffer->pLast->member.para.nYPos = yLastPos;
ME_DestroyContext(&c, editor->hWnd);

View file

@ -32,6 +32,14 @@ extern "C" {
#define cchTextLimitDefault 0x7fff
#if defined(__GNUC__)
# define MSFTEDIT_CLASS (const WCHAR []){ 'R','i','c','h','E','d','i','t','5','0','W',0 }
#elif defined(_MSC_VER)
# define MSFTEDIT_CLASS L"RichEdit50W"
#else
static const WCHAR MSFTEDIT_CLASS[] = { 'R','i','c','h','E','d','i','t','5','0','W',0 };
#endif
#define RICHEDIT_CLASS20A "RichEdit20A"
#if defined(__GNUC__)
# define RICHEDIT_CLASS20W (const WCHAR []){ 'R','i','c','h','E','d','i','t','2','0','W',0 }
@ -48,6 +56,26 @@ static const WCHAR RICHEDIT_CLASS20W[] = { 'R','i','c','h','E','d','i','t','2','
#define RICHEDIT_CLASS RICHEDIT_CLASS10A
#endif
#ifndef WM_NOTIFY
#define WM_NOTIFY 0x004e
#endif
#ifndef WM_CONTEXTMENU
#define WM_CONTEXTMENU 0x007b
#endif
#ifndef WM_UNICHAR
#define WM_UNICHAR 0x0109
#endif
#ifndef WM_PRINTCLIENT
#define WM_PRINTCLIENT 0x0318
#endif
#ifndef EM_GETLIMITTEXT
#define EM_GETLIMITTEXT (WM_USER + 37)
#endif
#ifndef EM_POSFROMCHAR
#define EM_POSFROMCHAR (WM_USER + 38)
#define EM_CHARFROMPOS (WM_USER + 39)
#endif
#ifndef EM_SCROLLCARET
#define EM_SCROLLCARET (WM_USER + 49)
#endif
@ -139,6 +167,24 @@ static const WCHAR RICHEDIT_CLASS20W[] = { 'R','i','c','h','E','d','i','t','2','
#define EM_SETFONTSIZE (WM_USER + 223)
#define EM_GETZOOM (WM_USER + 224)
#define EM_SETZOOM (WM_USER + 225)
#define EM_GETVIEWKIND (WM_USER + 226)
#define EM_SETVIEWKIND (WM_USER + 227)
#define EM_GETPAGE (WM_USER + 228)
#define EM_SETPAGE (WM_USER + 229)
#define EM_GETHYPHENATEINFO (WM_USER + 230)
#define EM_SETHYPHENATEINFO (WM_USER + 231)
#define EM_GETPAGEROTATE (WM_USER + 235)
#define EM_SETPAGEROTATE (WM_USER + 236)
#define EM_GETCTFMODEBIAS (WM_USER + 237)
#define EM_SETCTFMODEBIAS (WM_USER + 238)
#define EM_GETCTFOPENSTATUS (WM_USER + 240)
#define EM_SETCTFOPENSTATUS (WM_USER + 241)
#define EM_GETIMECOMPTEXT (WM_USER + 242)
#define EM_ISIME (WM_USER + 243)
#define EM_GETIMEPROPERTY (WM_USER + 244)
#define EM_GETQUERYRTFOBJ (WM_USER + 269)
#define EM_SETQUERYRTFOBJ (WM_USER + 270)
/* New notifications */
#define EN_MSGFILTER 0x0700
@ -155,16 +201,25 @@ static const WCHAR RICHEDIT_CLASS20W[] = { 'R','i','c','h','E','d','i','t','2','
#define EN_LINK 0x070b
#define EN_DRAGDROPDONE 0x070c
#define EN_PARAGRAPHEXPANDED 0x070d
#define EN_PAGECHANGE 0x070e
#define EN_LOWFIRTF 0x070f
#define EN_ALIGNLTR 0x0710
#define EN_ALIGNRTL 0x0711
typedef DWORD (CALLBACK * EDITSTREAMCALLBACK)( DWORD_PTR, LPBYTE, LONG, LONG * );
#define yHeightCharPtsMost 1638
#define lDefaultTab 720
/* tab stops number limit */
#define MAX_TAB_STOPS 0x00000020
#define MAX_TABLE_CELLS 63
/* Rich edit control styles */
#define ES_NOOLEDRAGDROP 0x00000008
#define ES_DISABLENOSCROLL 0x00002000
#define ES_SUNKEN 0x00004000
#define ES_SAVESEL 0x00008000
@ -180,6 +235,18 @@ typedef DWORD (CALLBACK * EDITSTREAMCALLBACK)( DWORD_PTR, LPBYTE, LONG, LONG * )
#define SCF_WORD 0x00000002
#define SCF_ALL 0x00000004
#define SCF_USEUIRULES 0x00000008
#define SCF_ASSOCIATEFONT 0x00000010
#define SCF_NOKBUPDATE 0x00000020
#define SCF_ASSOCIATEFONT2 0x00000040
#ifndef WM_NOTIFY
typedef struct _nmhdr
{
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR;
#endif
/* CHARFORMAT structure */
typedef struct _charformat
@ -208,6 +275,8 @@ typedef struct _charformatw
WCHAR szFaceName[LF_FACESIZE];
} CHARFORMATW;
DECL_WINELIB_TYPE_AW(CHARFORMAT)
typedef struct _charformat2a {
UINT cbSize;
DWORD dwMask;
@ -252,6 +321,10 @@ typedef struct _charformat2w {
BYTE bRevAuthor;
} CHARFORMAT2W;
DECL_WINELIB_TYPE_AW(CHARFORMAT2)
#define CHARFORMATDELTA (sizeof(CHARFORMAT2) - sizeof(CHARFORMAT))
/* CHARFORMAT masks */
#define CFM_BOLD 0x00000001
#define CFM_ITALIC 0x00000002
@ -284,7 +357,47 @@ typedef struct _charformat2w {
#define CFM_FACE 0x20000000
#define CFM_COLOR 0x40000000
#define CFM_SIZE 0x80000000
#define CFM_EFFECTS (CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_COLOR | CFM_STRIKEOUT | CFE_PROTECTED | CFM_LINK)
#define CFM_EFFECTS (CFM_BOLD | \
CFM_ITALIC | \
CFM_UNDERLINE | \
CFM_COLOR | \
CFM_STRIKEOUT | \
CFE_PROTECTED | \
CFM_LINK)
#define CFM_EFFECTS2 (CFM_EFFECTS | \
CFM_DISABLED | \
CFM_SMALLCAPS | \
CFM_ALLCAPS | \
CFM_HIDDEN | \
CFM_OUTLINE | \
CFM_SHADOW | \
CFM_EMBOSS | \
CFM_IMPRINT | \
CFM_DISABLED | \
CFM_REVISED | \
CFM_SUBSCRIPT | \
CFM_SUPERSCRIPT | \
CFM_BACKCOLOR)
#define CFM_ALL (CFM_EFFECTS | \
CFM_SIZE | \
CFM_FACE | \
CFM_OFFSET | \
CFM_CHARSET)
#define CFM_ALL2 (CFM_ALL | \
CFM_EFFECTS2 | \
CFM_BACKCOLOR | \
CFM_LCID | \
CFM_UNDERLINETYPE | \
CFM_WEIGHT | \
CFM_REVAUTHOR | \
CFM_SPACING | \
CFM_KERNING | \
CFM_STYLE | \
CFM_ANIMATION)
/* CHARFORMAT effects */
#define CFE_BOLD 0x00000001
@ -308,13 +421,27 @@ typedef struct _charformat2w {
#define CFE_REVISED CFM_REVISED
#define CFE_AUTOBACKCOLOR CFM_BACKCOLOR
#define CFU_CF1UNDERLINE 0xFF
#define CFU_INVERT 0xFE
#define CFU_UNDERLINEDOTTED 0x04
#define CFU_UNDERLINEDOUBLE 0x03
#define CFU_UNDERLINEWORD 0x02
#define CFU_UNDERLINE 0x01
#define CFU_UNDERLINENONE 0x00
#define CFU_UNDERLINENONE 0x00
#define CFU_UNDERLINE 0x01
#define CFU_UNDERLINEWORD 0x02
#define CFU_UNDERLINEDOUBLE 0x03
#define CFU_UNDERLINEDOTTED 0x04
#define CFU_UNDERLINEDASH 0x05
#define CFU_UNDERLINEDASHDOT 0x06
#define CFU_UNDERLINEDASHDOTDOT 0x07
#define CFU_UNDERLINEWAVE 0x08
#define CFU_UNDERLINETHICK 0x09
#define CFU_UNDERLINEHAIRLINE 0x0a
#define CFU_UNDERLINEDOUBLEWAVE 0x0b
#define CFU_UNDERLINEHEAVYWAVE 0x0c
#define CFU_UNDERLINELONGDASH 0x0d
#define CFU_UNDERLINETHICKDASH 0x0e
#define CFU_UNDERLINETHICKDASHDOT 0x0f
#define CFU_UNDERLINETHICKDASHDOTDOT 0x10
#define CFU_UNDERLINETHICKDOTTED 0x11
#define CFU_UNDERLINETHICKLONGDASH 0x12
#define CFU_INVERT 0xFE
#define CFU_CF1UNDERLINE 0xFF
/* ECO operations */
#define ECOOP_SET 0x0001
@ -338,6 +465,10 @@ typedef struct _charformat2w {
#define ENM_CHANGE 0x00000001
#define ENM_UPDATE 0x00000002
#define ENM_SCROLL 0x00000004
#define ENM_SCROLLEVENTS 0x00000008
#define ENM_DRAGDROPDONE 0x00000010
#define ENM_PARAGRAPHEXPANDED 0x00000020
#define ENM_PAGECHANGE 0x00000040
#define ENM_KEYEVENTS 0x00010000
#define ENM_MOUSEEVENTS 0x00020000
#define ENM_REQUESTRESIZE 0x00040000
@ -346,7 +477,17 @@ typedef struct _charformat2w {
#define ENM_PROTECTED 0x00200000
#define ENM_CORRECTTEXT 0x00400000
#define ENM_IMECHANGE 0x00800000
#define ENM_LANGCHANGE 0x01000000
#define ENM_OBJECTPOSITIONS 0x02000000
#define ENM_LINK 0x04000000
#define ENM_LOWFIRTF 0x08000000
typedef struct _bidioptions
{
UINT cbSize;
WORD wMask;
WORD wEffects;
} BIDIOPTIONS;
#ifndef __RICHEDIT_CHARRANGE_DEFINED
#define __RICHEDIT_CHARRANGE_DEFINED
@ -371,6 +512,8 @@ typedef struct _textrangew
LPWSTR lpstrText;
} TEXTRANGEW;
DECL_WINELIB_TYPE_AW(TEXTRANGE)
typedef struct _editstream
{
DWORD dwCookie;
@ -405,6 +548,11 @@ typedef struct _enlink {
CHARRANGE chrg;
} ENLINK;
typedef struct _enlowfirtf {
NMHDR nmhdr;
char *szControl;
} ENLOWFIRTF;
typedef struct {
NMHDR nmhdr;
LONG iob;
@ -436,6 +584,8 @@ typedef struct _findtextW {
LPCWSTR lpstrText;
} FINDTEXTW;
DECL_WINELIB_TYPE_AW(FINDTEXT)
typedef struct _findtextexA {
CHARRANGE chrg;
LPCSTR lpstrText;
@ -448,6 +598,8 @@ typedef struct _findtextexW {
CHARRANGE chrgText;
} FINDTEXTEXW;
DECL_WINELIB_TYPE_AW(FINDTEXTEX)
typedef struct _formatrange {
HDC hdc;
HDC hdcTarget;
@ -456,6 +608,31 @@ typedef struct _formatrange {
CHARRANGE chrg;
} FORMATRANGE;
typedef enum tagKHYPH
{
khyphNil = 0,
khyphNormal = 1,
khyphAddBefore = 2,
khyphChangeBefore = 3,
khyphDeleteBefore = 4,
khyphChangeAfter = 5,
khyphDelAndChange = 6
} KHYPH;
typedef struct hyphresult
{
KHYPH khyph;
long ichHyph;
WCHAR chHyph;
} HYPHRESULT;
typedef struct tagHyphenateInfo
{
SHORT cbSize;
SHORT dxHyphenateZone;
void (WINAPI* pfnHyphenate)(WCHAR*, LANGID, long, HYPHRESULT*);
} HYPHENATEINFO;
typedef struct _msgfilter {
NMHDR nmhdr;
UINT msg;
@ -463,6 +640,12 @@ typedef struct _msgfilter {
LPARAM lParam;
} MSGFILTER;
typedef struct _objectpositions {
NMHDR nmhdr;
LONG cObjectCount;
LONG *pcpPositions;
} OBJECTPOSITIONS;
typedef struct _paraformat {
UINT cbSize;
DWORD dwMask;
@ -524,6 +707,13 @@ typedef struct _gettextex {
LPBOOL lpUsedDefChar;
} GETTEXTEX;
typedef struct _imecomptext {
LONG cb;
DWORD flags;
} IMECOMPTEXT;
void WINAPI HyphenateProc(WCHAR*, LANGID, long, HYPHRESULT*);
#define SF_TEXT 0x00000001
#define SF_RTF 0x00000002
#define SF_RTFNOOBJS 0x00000003
@ -533,11 +723,86 @@ typedef struct _gettextex {
#define SF_NCRFORNONASCII 0x00000040
#define SF_RTFVAL 0x00000700
/* BIDIOPTIONS.wMask flag values */
#define BOM_DEFPARADIR 0x00000001
#define BOM_PLAINTEXT 0x00000002
#define BOM_NEUTRALOVERRIDE 0x00000004
#define BOM_CONTEXTREADING 0x00000008
#define BOM_CONTEXTALIGNMENT 0x00000010
#define BOM_LEGACYBIDICLASS 0x00000040
/* BIDIOPTIONS.wEffects flag values */
#define BOE_RTLDIR 0x00000001
#define BOE_PLAINTEXT 0x00000002
#define BOE_NEUTRALOVERRIDE 0x00000004
#define BOE_CONTEXTREADING 0x00000008
#define BOE_CONTEXTALIGNMENT 0x00000010
#define BOE_LEGACYBIDICLASS 0x00000040
/* Clipboard formats */
#define CF_RTF TEXT("Rich Text Format")
#define CF_RTFNOOBJS TEXT("Rich Text Format Without Objects")
#define CF_RETEXTOBJ TEXT("RichEdit Text and Objects")
/* Mode bias wParam values for EM_SETCTFMODEBIAS message */
#define CTFMODEBIAS_DEFAULT 0x00000000
#define CTFMODEBIAS_FILENAME 0x00000001
#define CTFMODEBIAS_NAME 0x00000002
#define CTFMODEBIAS_READING 0x00000003
#define CTFMODEBIAS_DATETIME 0x00000004
#define CTFMODEBIAS_CONVERSATION 0x00000005
#define CTFMODEBIAS_NUMERIC 0x00000006
#define CTFMODEBIAS_HIRAGANA 0x00000007
#define CTFMODEBIAS_KATAKANA 0x00000008
#define CTFMODEBIAS_HANGUL 0x00000009
#define CTFMODEBIAS_HALFWIDTHKATAKANA 0x0000000a
#define CTFMODEBIAS_FULLWIDTHALPHANUMERIC 0x0000000b
#define CTFMODEBIAS_HALFWIDTHALPHANUMERIC 0x0000000c
#define EMO_EXIT 0x00000000
#define EMO_ENTER 0x00000001
#define EMO_PROMOTE 0x00000002
#define EMO_EXPAND 0x00000003
#define EMO_MOVESELECTION 0x00000004
#define EMO_GETVIEWMODE 0x00000005
#define EMO_EXPANDSELECTION 0x00000000
#define EMO_EXPANDDOCUMENT 0x00000001
/* Page Rotate values used in wParam of EM_SETPAGEROTATE message */
#define EPR_0 0x00000000
#define EPR_270 0x00000001
#define EPR_180 0x00000002
#define EPR_90 0x00000003
/* Find flags for wParam of EM_FINDTEXT message */
#define FR_MATCHDIAC 0x20000000
#define FR_MATCHKASHIDA 0x40000000
#define FR_MATCHALEFHAMZA 0x80000000
/* IME Compatibility Mode return values for EM_GETIMECOMPMODE message */
#define ICM_NOTOPEN 0x00000000
#define ICM_LEVEL3 0x00000001
#define ICM_LEVEL2 0x00000002
#define ICM_LEVEL2_5 0x00000003
#define ICM_LEVEL2_SUI 0x00000004
#define ICM_CTF 0x00000005
/* Flags value for IMECOMPTEXT structure */
#define ICT_RESULTREADSTR 0x00000001
/* Input Method Flags used in EM_SETLANGOPTIONS message */
#define IMF_AUTOKEYBOARD 0x00000001
#define IMF_AUTOFONT 0x00000002
#define IMF_IMECANCELCOMPLETE 0x00000004
#define IMF_IMEALWAYSSENDNOTIFY 0x00000008
#define IMF_AUTOFONTSIZEADJUST 0x00000010
#define IMF_UIFONTS 0x00000020
#define IMF_DUALFONT 0x00000080
/* Parameters values for the EM_SETIMEMODEBIAS message */
#define IMF_SMODE_PLAURALCLAUSE 0x00000001
#define IMF_SMODE_NONE 0x00000002
/* Parameters of the EM_SETIMEOPTIONS message */
#define IMF_FORCENONE 0x00000001
@ -548,6 +813,7 @@ typedef struct _gettextex {
#define IMF_FORCEACTIVE 0x00000040
#define IMF_FORCEINACTIVE 0x00000080
#define IMF_FORCEREMEMBER 0x00000100
#define IMF_MULTIPLEEDIT 0x00000400
/* return values of the EM_SELECTION_TYPE message */
#define SEL_EMPTY 0x00000000
@ -556,6 +822,15 @@ typedef struct _gettextex {
#define SEL_MULTICHAR 0x00000004
#define SEL_MULTIOBJECT 0x00000008
/* ENOLEOPFAILED.lOper value that indicates operation failure */
#define OLEOP_DOVERB 0x00000001
/* punctionation type values for wParam of EM_SETPUNCTUATION message */
#define PC_FOLLOWING 0x00000001
#define PC_LEADING 0x00000002
#define PC_OVERFLOW 0x00000003
#define PC_DELIMITER 0x00000004
/* mask values in the PARAFORMAT structure */
#define PFM_STARTINDENT 0x00000001
#define PFM_RIGHTINDENT 0x00000002
@ -572,7 +847,6 @@ typedef struct _gettextex {
#define PFM_STYLE 0x00000400
#define PFM_BORDER 0x00000800
#define PFM_SHADING 0x00001000
#define PFM_NUMBERINGSTYLE 0x00002000
#define PFM_NUMBERINGTAB 0x00004000
#define PFM_NUMBERINGSTART 0x00008000
@ -584,10 +858,61 @@ typedef struct _gettextex {
#define PFM_NOWIDOWCONTROL 0x00200000
#define PFM_DONOTHYPHEN 0x00400000
#define PFM_SIDEBYSIDE 0x00800000
#define PFM_COLLAPSED 0x01000000
#define PFM_OUTLINELEVEL 0x02000000
#define PFM_BOX 0x04000000
#define PFM_RESERVED2 0x08000000
#define PFM_TABLEROWDELIMITER 0x10000000
#define PFM_TEXTWRAPPINGBREAK 0x20000000
#define PFM_TABLE 0x40000000
#define PFM_ALL (PFM_STARTINDENT | \
PFM_RIGHTINDENT | \
PFM_OFFSET | \
PFM_ALIGNMENT | \
PFM_TABSTOPS | \
PFM_NUMBERING | \
PFM_OFFSETINDENT | \
PFM_RTLPARA)
#define PFM_EFFECTS (PFM_RTLPARA | \
PFM_KEEP | \
PFM_KEEPNEXT | \
PFM_PAGEBREAKBEFORE | \
PFM_NOLINENUMBER | \
PFM_NOWIDOWCONTROL | \
PFM_DONOTHYPHEN | \
PFM_SIDEBYSIDE | \
PFM_TABLEROWDELIMITER | \
PFM_TABLE)
#define PFM_ALL2 (PFM_ALL | \
PFM_EFFECTS | \
PFM_SPACEBEFORE | \
PFM_SPACEAFTER | \
PFM_LINESPACING | \
PFM_STYLE | \
PFM_BORDER | \
PFM_SHADING | \
PFM_NUMBERINGSTYLE | \
PFM_NUMBERINGTAB | \
PFM_NUMBERINGSTART)
/* numbering option */
#define PFN_BULLET 0x00000001
#define PFN_ARABIC 0x00000002
#define PFN_LCLETTER 0x00000003
#define PFN_UCLETTER 0x00000004
#define PFN_LCROMAN 0x00000005
#define PFN_UCROMAN 0x00000006
/* paragraph format numbering styles */
#define PFNS_PAREN 0x00000000
#define PFNS_PARENS 0x00000100
#define PFNS_PERIOD 0x00000200
#define PFNS_PLAIN 0x00000300
#define PFNS_NONUMBER 0x00000400
#define PFNS_NEWNUMBER 0x00008000
/* paragraph alignment */
#define PFA_LEFT 0x00000001
@ -596,6 +921,9 @@ typedef struct _gettextex {
#define PFA_JUSTIFY 0x00000004
#define PFA_FULL_INTERWORD 0x00000004
#define PFA_FULL_INTERLETTER 0x00000005
#define PFA_FULL_SCALED 0x00000006
#define PFA_FULL_GLYPHS 0x00000007
#define PFA_SNAP_GRID 0x00000008
/* paragraph effects */
#define PFE_RTLPARA 0x00000001
@ -606,17 +934,64 @@ typedef struct _gettextex {
#define PFE_NOWIDOWCONTROL 0x00000020
#define PFE_DONOTHYPHEN 0x00000040
#define PFE_SIDEBYSIDE 0x00000080
#define PFE_COLLAPSED 0x00000100
#define PFE_BOX 0x00000400
#define PFE_TABLEROWDELIMITER 0x00001000
#define PFE_TEXTWRAPPINGBREAK 0x00002000
#define PFE_TABLE 0x00004000
/* Set Edit Style flags for EM_SETEDITSTYLE message */
#define SES_EMULATESYSEDIT 0x00000001
#define SES_BEEPONMAXTEXT 0x00000002
#define SES_EXTENDBACKCOLOR 0x00000004
#define SES_MAPCPS 0x00000008
#define SES_EMULATE10 0x00000010
#define SES_USECRLF 0x00000020
#define SES_NOXLTSYMBOLRANGE 0x00000020
#define SES_USEAIMM 0x00000040
#define SES_NOIME 0x00000080
#define SES_ALLOWBEEPS 0x00000100
#define SES_UPPERCASE 0x00000200
#define SES_LOWERCASE 0x00000400
#define SES_NOINPUTSEQUENCECHK 0x00000800
#define SES_BIDI 0x00001000
#define SES_SCROLLONKILLFOCUS 0x00002000
#define SES_XLTCRCRLFTOCR 0x00004000
#define SES_DRAFTMODE 0x00008000
#define SES_USECTF 0x00010000
#define SES_HIDEGRIDLINES 0x00020000
#define SES_USEATFONT 0x00040000
#define SES_CUSTOMLOOK 0x00080000
#define SES_LBSCROLLNOTIFY 0x00100000
#define SES_CTFALLOWEMBED 0x00200000
#define SES_CTFALLOWSMARTTAG 0x00400000
#define SES_CTFALLOWPROOFING 0x00800000
/* streaming flags */
#define SFF_WRITEXTRAPAR 0x00000080
#define SFF_PWD 0x00000800
#define SFF_KEEPDOCINFO 0x00001000
#define SFF_PERSISTVIEWSCALE 0x00002000
#define SFF_PLAINRTF 0x00004000
#define SFF_SELECTION 0x00008000
typedef enum _undonameid
{
UID_UNKNOWN = 0,
UID_TYPING = 1,
UID_DELETE = 2,
UID_DRAGDROP = 3,
UID_CUT = 4,
UID_PASTE = 5,
UID_AUTOCORRECT = 6
} UNDONAMEID;
typedef LONG (*EDITWORDBREAKPROCEX)(char*,LONG,BYTE,INT);
#define VM_OUTLINE 0x00000002
#define VM_NORMAL 0x00000004
#define VM_PAGE 0x00000009
/* options of the EM_FINDWORDBREAK message */
#define WB_CLASSIFY 0x00000003
#define WB_MOVEWORDLEFT 0x00000004
@ -636,6 +1011,16 @@ typedef LONG (*EDITWORDBREAKPROCEX)(char*,LONG,BYTE,INT);
#define WBF_LEVEL2 0x00000100
#define WBF_CUSTOM 0x00000200
#define WBF_CLASS ((BYTE) 0x0F)
#define WBF_ISWHITE ((BYTE) 0x10)
#define WBF_BREAKLINE ((BYTE) 0x20)
#define WBF_BREAKAFTER ((BYTE) 0x40)
/* Placeholder unicode character for an embedded object */
#ifndef WCH_EMBEDDING
#define WCH_EMBEDDING (WCHAR)0xFFFC
#endif
/* options of the EM_SETTEXTMODE message */
#define TM_PLAINTEXT 0x00000001
#define TM_RICHTEXT 0x00000002
@ -648,10 +1033,14 @@ typedef LONG (*EDITWORDBREAKPROCEX)(char*,LONG,BYTE,INT);
#define GT_DEFAULT 0x00000000
#define GT_USECRLF 0x00000001
#define GT_SELECTION 0x00000002
#define GT_RAWTEXT 0x00000004
#define GT_NOHIDDENTEXT 0x00000008
/* Options of the EM_SETTYPOGRAPHYOPTIONS message */
#define TO_ADVANCEDTYPOGRAPHY 0x00000001
#define TO_SIMPLELINEBREAK 0x00000002
#define TO_ADVANCEDTYPOGRAPHY 0x00000001
#define TO_SIMPLELINEBREAK 0x00000002
#define TO_DISABLECUSTOMTEXTOUT 0x00000004
#define TO_ADVANCEDLAYOUT 0x00000008
typedef struct _gettextlengthex {
DWORD flags;
@ -675,23 +1064,11 @@ typedef struct _settextex {
} SETTEXTEX;
/* Flags of the EM_SETTEXTEX message */
#define ST_DEFAULT 0x00000000
#define ST_DEFAULT 0x00000000
#define ST_KEEPUNDO 0x00000001
#define ST_SELECTION 0x00000002
#ifdef UNICODE
typedef CHARFORMATW CHARFORMAT;
typedef CHARFORMAT2W CHARFORMAT2;
typedef FINDTEXTW FINDTEXT;
typedef FINDTEXTEXW FINDTEXTEX;
typedef TEXTRANGEW TEXTRANGE;
#else
typedef CHARFORMATA CHARFORMAT;
typedef CHARFORMAT2A CHARFORMAT2;
typedef FINDTEXTA FINDTEXT;
typedef FINDTEXTEXA FINDTEXTEX;
typedef TEXTRANGEA TEXTRANGE;
#endif
#define ST_NEWCHARS 0x00000004
#ifdef __cplusplus
}