diff --git a/reactos/dll/win32/riched20/caret.c b/reactos/dll/win32/riched20/caret.c index 3bc5b5e4f10..2337107172b 100644 --- a/reactos/dll/win32/riched20/caret.c +++ b/reactos/dll/win32/riched20/caret.c @@ -27,7 +27,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); static BOOL ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs); - void ME_GetSelection(ME_TextEditor *editor, int *from, int *to) { *from = ME_GetCursorOfs(editor, 0); @@ -59,7 +58,7 @@ int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) length = ME_GetTextLength(editor); if ((GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_MULTILINE) && (how->flags & GTL_USECRLF)) - length += editor->nParagraphs; + length += editor->nParagraphs - 1; if (how->flags & GTL_NUMBYTES) { @@ -705,102 +704,83 @@ int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor) + pCursor->pRun->member.run.nCharOfs + pCursor->nOffset; } -int ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *result, BOOL *is_eol) +static void ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *result, BOOL *is_eol) { ME_DisplayItem *p = editor->pBuffer->pFirst->member.para.next_para; + ME_DisplayItem *last = NULL; int rx = 0; - + if (is_eol) *is_eol = 0; - while(p != editor->pBuffer->pLast) + /* find paragraph */ + for (; p != editor->pBuffer->pLast; p = p->member.para.next_para) { - if (p->type == diParagraph) + assert(p->type == diParagraph); + if (y < p->member.para.nYPos + p->member.para.nHeight) { - int ry = y - p->member.para.nYPos; - if (ry < 0) - { - result->pRun = ME_FindItemFwd(p, diRun); - result->nOffset = 0; - return 0; - } - if (ry >= p->member.para.nHeight) - { - p = p->member.para.next_para; - continue; - } + y -= p->member.para.nYPos; p = ME_FindItemFwd(p, diStartRow); - y = ry; - continue; + break; } - if (p->type == diStartRow) + } + /* find row */ + for (; p != editor->pBuffer->pLast; ) + { + ME_DisplayItem *pp; + assert(p->type == diStartRow); + if (y < p->member.row.nYPos + p->member.row.nHeight) { - int ry = y - p->member.row.nYPos; - if (ry < 0) - return 0; - if (ry >= p->member.row.nHeight) - { - p = ME_FindItemFwd(p, diStartRowOrParagraphOrEnd); - if (p->type != diStartRow) - return 0; - continue; - } - p = ME_FindItemFwd(p, diRun); - continue; + p = ME_FindItemFwd(p, diRun); + break; } - if (p->type == diRun) + pp = ME_FindItemFwd(p, diStartRowOrParagraphOrEnd); + if (pp->type != diStartRow) { - ME_DisplayItem *pp; + p = ME_FindItemFwd(p, diRun); + break; + } + p = pp; + } + for (; p != editor->pBuffer->pLast; p = p->next) + { + switch (p->type) + { + case diRun: rx = x - p->member.run.pt.x; - if (rx < 0) - rx = 0; - if (rx >= p->member.run.nWidth) /* not this run yet... find next item */ + if (rx < p->member.run.nWidth) { - pp = p; - do { - p = p->next; - if (p->type == diRun) - { - rx = x - p->member.run.pt.x; - goto continue_search; - } - if (p->type == diStartRow) - { - p = ME_FindItemFwd(p, diRun); - if (is_eol) - *is_eol = 1; - rx = 0; /* FIXME not sure */ - goto found_here; - } - if (p->type == diParagraph || p->type == diTextEnd) - { - rx = 0; /* FIXME not sure */ - p = pp; - goto found_here; - } - } while(1); - continue; + found_here: + assert(p->type == diRun); + if ((p->member.run.nFlags & MERF_ENDPARA) || rx < 0) + rx = 0; + result->pRun = p; + result->nOffset = ME_CharFromPointCursor(editor, rx, &p->member.run); + if (editor->pCursors[0].nOffset == p->member.run.strText->nLen && rx) + { + result->pRun = ME_FindItemFwd(editor->pCursors[0].pRun, diRun); + result->nOffset = 0; + } + return; } - found_here: - if (p->member.run.nFlags & MERF_ENDPARA) - rx = 0; - result->pRun = p; - result->nOffset = ME_CharFromPointCursor(editor, rx, &p->member.run); - if (editor->pCursors[0].nOffset == p->member.run.strText->nLen && rx) - { - result->pRun = ME_FindItemFwd(editor->pCursors[0].pRun, diRun); - result->nOffset = 0; - } - return 1; + break; + case diStartRow: + p = ME_FindItemFwd(p, diRun); + if (is_eol) *is_eol = 1; + rx = 0; /* FIXME not sure */ + goto found_here; + case diParagraph: + case diTextEnd: + rx = 0; /* FIXME not sure */ + p = last; + goto found_here; + default: assert(0); } - assert(0); - continue_search: - ; + last = p; } result->pRun = ME_FindItemBack(p, diRun); result->nOffset = 0; assert(result->pRun->member.run.nFlags & MERF_ENDPARA); - return 0; } @@ -832,25 +812,64 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y) tmp_cursor = editor->pCursors[0]; is_selection = ME_IsSelection(editor); - ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd); - - if (GetKeyState(VK_SHIFT)>=0) + if (x >= editor->selofs) { - editor->pCursors[1] = editor->pCursors[0]; - } - else - { - if (!is_selection) { + ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd); + if (GetKeyState(VK_SHIFT)>=0) + { + editor->pCursors[1] = editor->pCursors[0]; + } + 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 + { + ME_DisplayItem *pRow; + + editor->linesel = 1; + editor->sely = y; + /* Set pCursors[0] to beginning of line */ + ME_FindPixelPos(editor, x, y, &editor->pCursors[1], &editor->bCaretAtEnd); + /* Set pCursors[1] to end of line */ + pRow = ME_FindItemFwd(editor->pCursors[1].pRun, diStartRowOrParagraphOrEnd); + assert(pRow); + /* pCursor[0] is the position where the cursor will be drawn, + * pCursor[1] is the other end of the selection range + * pCursor[2] and [3] are backups of [0] and [1] so I + * don't have to look them up again + */ + + if (pRow->type == diStartRow) { + /* FIXME WTF was I thinking about here ? */ + ME_DisplayItem *pRun = ME_FindItemFwd(pRow, diRun); + assert(pRun); + editor->pCursors[0].pRun = pRun; + editor->pCursors[0].nOffset = 0; + editor->bCaretAtEnd = 1; + } else { + editor->pCursors[0].pRun = ME_FindItemBack(pRow, diRun); + assert(editor->pCursors[0].pRun && editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA); + editor->pCursors[0].nOffset = 0; + editor->bCaretAtEnd = 0; + } + 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) @@ -861,14 +880,33 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y) tmp_cursor = editor->pCursors[0]; /* FIXME: do something with the return value of ME_FindPixelPos */ - ME_FindPixelPos(editor, x, y, &tmp_cursor, &editor->bCaretAtEnd); - - if (tmp_cursor.pRun == editor->pCursors[0].pRun && - tmp_cursor.nOffset == editor->pCursors[0].nOffset) + if (!editor->linesel) + ME_FindPixelPos(editor, x, y, &tmp_cursor, &editor->bCaretAtEnd); + else ME_FindPixelPos(editor, (y > editor->sely) * editor->rcFormat.right, y, &tmp_cursor, &editor->bCaretAtEnd); + + if (!memcmp(&tmp_cursor, editor->pCursors, sizeof(tmp_cursor))) return; - + ME_InvalidateSelection(editor); - editor->pCursors[0] = tmp_cursor; + if (!editor->linesel) + editor->pCursors[0] = tmp_cursor; + else if (!memcmp(&tmp_cursor, editor->pCursors+2, sizeof(tmp_cursor)) || + !memcmp(&tmp_cursor, editor->pCursors+3, sizeof(tmp_cursor))) + { + editor->pCursors[0] = editor->pCursors[2]; + editor->pCursors[1] = editor->pCursors[3]; + } + else if (y < editor->sely) + { + editor->pCursors[0] = tmp_cursor; + editor->pCursors[1] = editor->pCursors[2]; + } + else + { + editor->pCursors[0] = tmp_cursor; + editor->pCursors[1] = editor->pCursors[3]; + } + HideCaret(editor->hWnd); ME_MoveCaret(editor); ME_InvalidateSelection(editor); @@ -1206,11 +1244,11 @@ ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) { ME_Style *style; int from, to; - ME_Cursor c; - + ME_GetSelection(editor, &from, &to); - ME_CursorFromCharOfs(editor, from, &c); 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 */ } @@ -1240,7 +1278,6 @@ void ME_SendSelChange(ME_TextEditor *editor) SendMessageW(GetParent(editor->hWnd), WM_NOTIFY, sc.nmhdr.idFrom, (LPARAM)&sc); } - BOOL ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl) { diff --git a/reactos/dll/win32/riched20/clipboard.c b/reactos/dll/win32/riched20/clipboard.c index 376a2e5b3d9..e9b5cd0ef55 100644 --- a/reactos/dll/win32/riched20/clipboard.c +++ b/reactos/dll/win32/riched20/clipboard.c @@ -77,7 +77,7 @@ static ULONG WINAPI EnumFormatImpl_Release(IEnumFORMATETC *iface) if(!ref) { GlobalFree(This->fmtetc); - richedit_free(This); + heap_free(This); } return ref; @@ -152,7 +152,7 @@ static HRESULT EnumFormatImpl_Create(const FORMATETC *fmtetc, UINT fmtetc_cnt, I EnumFormatImpl *ret; TRACE("\n"); - ret = richedit_alloc(sizeof(EnumFormatImpl)); + ret = heap_alloc(sizeof(EnumFormatImpl)); ret->lpVtbl = &VT_EnumFormatImpl; ret->ref = 1; ret->cur = 0; @@ -195,7 +195,7 @@ static ULONG WINAPI DataObjectImpl_Release(IDataObject* iface) if(This->unicode) GlobalFree(This->unicode); if(This->rtf) GlobalFree(This->rtf); if(This->fmtetc) GlobalFree(This->fmtetc); - richedit_free(This); + heap_free(This); } return ref; @@ -388,7 +388,7 @@ HRESULT ME_GetDataObject(ME_TextEditor *editor, const CHARRANGE *lpchrg, LPDATAO DataObjectImpl *obj; TRACE("(%p,%d,%d)\n", editor, lpchrg->cpMin, lpchrg->cpMax); - obj = richedit_alloc(sizeof(DataObjectImpl)); + obj = heap_alloc(sizeof(DataObjectImpl)); if(cfRTF == 0) cfRTF = RegisterClipboardFormatA("Rich Text Format"); diff --git a/reactos/dll/win32/riched20/context.c b/reactos/dll/win32/riched20/context.c index 7eef5564a8e..56e68f78d64 100644 --- a/reactos/dll/win32/riched20/context.c +++ b/reactos/dll/win32/riched20/context.c @@ -29,6 +29,8 @@ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC) c->pt.y = 0; c->hbrMargin = CreateSolidBrush(RGB(224,224,224)); c->rcView = editor->rcFormat; + c->dpi.cx = GetDeviceCaps(hDC, LOGPIXELSX); + c->dpi.cy = GetDeviceCaps(hDC, LOGPIXELSY); } void ME_DestroyContext(ME_Context *c) diff --git a/reactos/dll/win32/riched20/editor.c b/reactos/dll/win32/riched20/editor.c index b1444c0f94c..85ac5b2fa13 100644 --- a/reactos/dll/win32/riched20/editor.c +++ b/reactos/dll/win32/riched20/editor.c @@ -228,6 +228,7 @@ #include "shlwapi.h" #include "rtf.h" #include "imm.h" +#include "res.h" #define STACK_SIZE_DEFAULT 100 #define STACK_SIZE_MAX 1000 @@ -242,6 +243,8 @@ static const WCHAR RichEdit20W[] = {'R', 'i', 'c', 'h', 'E', 'd', 'i', 't', '2', static const WCHAR RichEdit50W[] = {'R', 'i', 'c', 'h', 'E', 'd', 'i', 't', '5', '0', 'W', 0}; static const WCHAR REListBox20W[] = {'R','E','L','i','s','t','B','o','x','2','0','W', 0}; static const WCHAR REComboBox20W[] = {'R','E','C','o','m','b','o','B','o','x','2','0','W', 0}; +static HCURSOR hLeft; +static HCURSOR hBeam; int me_debug = 0; HANDLE me_heap = NULL; @@ -329,10 +332,11 @@ static void ME_RTFCharAttrHook(RTF_Info *info) { case rtfPlain: /* FIXME add more flags once they're implemented */ - fmt.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR | CFM_BACKCOLOR | CFM_SIZE | CFM_WEIGHT; + fmt.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINETYPE | CFM_STRIKEOUT | CFM_COLOR | CFM_BACKCOLOR | CFM_SIZE | CFM_WEIGHT; fmt.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR; fmt.yHeight = 12*20; /* 12pt */ fmt.wWeight = 400; + fmt.bUnderlineType = CFU_UNDERLINENONE; break; case rtfBold: fmt.dwMask = CFM_BOLD; @@ -343,13 +347,24 @@ static void ME_RTFCharAttrHook(RTF_Info *info) fmt.dwEffects = info->rtfParam ? fmt.dwMask : 0; break; case rtfUnderline: - fmt.dwMask = CFM_UNDERLINE; - fmt.dwEffects = info->rtfParam ? fmt.dwMask : 0; - fmt.bUnderlineType = CFU_CF1UNDERLINE; + fmt.dwMask = CFM_UNDERLINETYPE; + fmt.bUnderlineType = info->rtfParam ? CFU_CF1UNDERLINE : CFU_UNDERLINENONE; + break; + case rtfDotUnderline: + fmt.dwMask = CFM_UNDERLINETYPE; + fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEDOTTED : CFU_UNDERLINENONE; + break; + case rtfDbUnderline: + fmt.dwMask = CFM_UNDERLINETYPE; + fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEDOUBLE : CFU_UNDERLINENONE; + break; + case rtfWordUnderline: + fmt.dwMask = CFM_UNDERLINETYPE; + fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEWORD : CFU_UNDERLINENONE; break; case rtfNoUnderline: - fmt.dwMask = CFM_UNDERLINE; - fmt.dwEffects = 0; + fmt.dwMask = CFM_UNDERLINETYPE; + fmt.bUnderlineType = CFU_UNDERLINENONE; break; case rtfStrikeThru: fmt.dwMask = CFM_STRIKEOUT; @@ -404,6 +419,7 @@ static void ME_RTFCharAttrHook(RTF_Info *info) fmt.szFaceName[sizeof(fmt.szFaceName)/sizeof(WCHAR)-1] = '\0'; fmt.bCharSet = f->rtfFCharSet; fmt.dwMask = CFM_FACE | CFM_CHARSET; + fmt.bPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; } } break; @@ -1031,6 +1047,27 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH return -1; } +/* helper to send a msg filter notification */ +static BOOL +ME_FilterEvent(ME_TextEditor *editor, UINT msg, WPARAM* wParam, LPARAM* lParam) +{ + MSGFILTER msgf; + + msgf.nmhdr.hwndFrom = editor->hWnd; + msgf.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID); + msgf.nmhdr.code = EN_MSGFILTER; + msgf.msg = msg; + + msgf.wParam = *wParam; + msgf.lParam = *lParam; + if (SendMessageW(GetParent(editor->hWnd), WM_NOTIFY, msgf.nmhdr.idFrom, (LPARAM)&msgf)) + return FALSE; + *wParam = msgf.wParam; + *lParam = msgf.lParam; + msgf.wParam = *wParam; + + return TRUE; +} static BOOL ME_KeyDown(ME_TextEditor *editor, WORD nKey) @@ -1088,6 +1125,14 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) return FALSE; } +static void ME_SetCursor(ME_TextEditor *editor, int x) +{ + if (x < editor->selofs || editor->linesel) + SetCursor(hLeft); + else + SetCursor(hBeam); +} + static BOOL ME_ShowContextMenu(ME_TextEditor *editor, int x, int y) { CHARRANGE selrange; @@ -1115,21 +1160,21 @@ static BOOL ME_ShowContextMenu(ME_TextEditor *editor, int x, int y) ME_TextEditor *ME_MakeEditor(HWND hWnd) { ME_TextEditor *ed = ALLOC_OBJ(ME_TextEditor); - HDC hDC; int i; ed->hWnd = hWnd; ed->bEmulateVersion10 = FALSE; ed->pBuffer = ME_MakeText(); - hDC = GetDC(hWnd); - ME_MakeFirstParagraph(hDC, ed->pBuffer); - ReleaseDC(hWnd, hDC); + ed->nZoomNumerator = ed->nZoomDenominator = 0; + ME_MakeFirstParagraph(ed); ed->bCaretShown = FALSE; - ed->nCursors = 2; + ed->nCursors = 4; ed->pCursors = ALLOC_N_OBJ(ME_Cursor, ed->nCursors); ed->pCursors[0].pRun = ME_FindItemFwd(ed->pBuffer->pFirst, diRun); ed->pCursors[0].nOffset = 0; ed->pCursors[1].pRun = ME_FindItemFwd(ed->pBuffer->pFirst, diRun); ed->pCursors[1].nOffset = 0; + ed->pCursors[2] = ed->pCursors[0]; + ed->pCursors[3] = ed->pCursors[1]; ed->nLastTotalLength = ed->nTotalLength = 0; ed->nHeight = 0; ed->nUDArrowX = -1; @@ -1147,7 +1192,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) { ed->nParagraphs = 1; ed->nLastSelStart = ed->nLastSelEnd = 0; ed->pLastSelStartPara = ed->pLastSelEndPara = ME_FindItemFwd(ed->pBuffer->pFirst, diParagraph); - ed->nZoomNumerator = ed->nZoomDenominator = 0; ed->bRedraw = TRUE; ed->bHideSelection = FALSE; ed->nInvalidOfs = -1; @@ -1165,7 +1209,12 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) { } ME_CheckCharOffsets(ed); - + if (GetWindowLongW(hWnd, GWL_STYLE) & ES_SELECTIONBAR) + ed->selofs = 16; + else + ed->selofs = 0; + ed->linesel = 0; + if (GetWindowLongW(hWnd, GWL_STYLE) & ES_PASSWORD) ed->cPasswordMask = '*'; else @@ -1235,7 +1284,8 @@ void ME_DestroyEditor(ME_TextEditor *editor) if (editor->pFontCache[i].hFont) DeleteObject(editor->pFontCache[i].hFont); } - DeleteObject(editor->hbrBackground); + if (editor->rgbBackColor != -1) + DeleteObject(editor->hbrBackground); if(editor->lpOleCallback) IUnknown_Release(editor->lpOleCallback); @@ -1254,6 +1304,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) DisableThreadLibraryCalls(hinstDLL); me_heap = HeapCreate (0, 0x10000, 0); if (!ME_RegisterEditorClass(hinstDLL)) return FALSE; + hLeft = LoadCursorW(hinstDLL, MAKEINTRESOURCEW(OCR_REVERSE)); + hBeam = LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_IBEAM)); LookupInit(); break; @@ -1551,7 +1603,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, * setting the bit to work */ DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL | - ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN; + ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN | ECO_SELECTIONBAR; DWORD raw = GetWindowLongW(hWnd, GWL_STYLE); DWORD settings = mask & raw; @@ -1571,19 +1623,23 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, } SetWindowLongW(hWnd, GWL_STYLE, (raw & ~mask) | (settings & mask)); - if (lParam & ECO_AUTOWORDSELECTION) + if (settings & ECO_AUTOWORDSELECTION) FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n"); - if (lParam & ECO_SELECTIONBAR) - FIXME("ECO_SELECTIONBAR not implemented yet!\n"); - if (lParam & ECO_VERTICAL) + if (settings & ECO_SELECTIONBAR) + editor->selofs = 16; + else + editor->selofs = 0; + ME_WrapMarkedParagraphs(editor); + + if (settings & ECO_VERTICAL) FIXME("ECO_VERTICAL not implemented yet!\n"); - if (lParam & ECO_AUTOHSCROLL) + if (settings & ECO_AUTOHSCROLL) FIXME("ECO_AUTOHSCROLL not implemented yet!\n"); - if (lParam & ECO_AUTOVSCROLL) + if (settings & ECO_AUTOVSCROLL) FIXME("ECO_AUTOVSCROLL not implemented yet!\n"); - if (lParam & ECO_NOHIDESEL) + if (settings & ECO_NOHIDESEL) FIXME("ECO_NOHIDESEL not implemented yet!\n"); - if (lParam & ECO_WANTRETURN) + if (settings & ECO_WANTRETURN) FIXME("ECO_WANTRETURN not implemented yet!\n"); return settings; @@ -1677,9 +1733,13 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, } case EM_SETBKGNDCOLOR: { - LRESULT lColor = ME_GetBackColor(editor); - if (editor->rgbBackColor != -1) + LRESULT lColor; + if (editor->rgbBackColor != -1) { DeleteObject(editor->hbrBackground); + lColor = editor->rgbBackColor; + } + else lColor = GetSysColor(COLOR_WINDOW); + if (wParam) { editor->rgbBackColor = -1; @@ -1996,19 +2056,47 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, return 0; } case WM_GETTEXTLENGTH: - return ME_GetTextLength(editor); + { + GETTEXTLENGTHEX how; + + how.flags = GTL_CLOSE | (editor->bEmulateVersion10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS; + how.codepage = unicode ? 1200 : CP_ACP; + return ME_GetTextLengthEx(editor, &how); + } case EM_GETTEXTLENGTHEX: return ME_GetTextLengthEx(editor, (GETTEXTLENGTHEX *)wParam); case WM_GETTEXT: { GETTEXTEX ex; + LRESULT rc; + LPSTR bufferA = NULL; + LPWSTR bufferW = NULL; - ex.cb = wParam; + if (unicode) + bufferW = heap_alloc((wParam + 2) * sizeof(WCHAR)); + else + bufferA = heap_alloc(wParam + 2); + + ex.cb = wParam + (unicode ? 2*sizeof(WCHAR) : 2); ex.flags = GT_USECRLF; ex.codepage = unicode ? 1200 : CP_ACP; ex.lpDefaultChar = NULL; ex.lpUsedDefaultChar = NULL; - return RichEditWndProc_common(hWnd, EM_GETTEXTEX, (WPARAM)&ex, lParam, unicode); + rc = RichEditWndProc_common(hWnd, EM_GETTEXTEX, (WPARAM)&ex, unicode ? (LPARAM)bufferW : (LPARAM)bufferA, unicode); + + if (unicode) + { + memcpy((LPWSTR)lParam, bufferW, wParam); + if (lstrlenW(bufferW) >= wParam / sizeof(WCHAR)) rc = 0; + } + else + { + memcpy((LPSTR)lParam, bufferA, wParam); + if (strlen(bufferA) >= wParam) rc = 0; + } + heap_free(bufferA); + heap_free(bufferW); + return rc; } case EM_GETTEXTEX: { @@ -2039,7 +2127,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, /* potentially each char may be a CR, why calculate the exact value with O(N) when we can just take a bigger buffer? :) */ int crlfmul = (ex->flags & GT_USECRLF) ? 2 : 1; - LPWSTR buffer = richedit_alloc((crlfmul*nCount + 1) * sizeof(WCHAR)); + LPWSTR buffer = heap_alloc((crlfmul*nCount + 1) * sizeof(WCHAR)); DWORD buflen = ex->cb; LRESULT rc; DWORD flags = 0; @@ -2048,7 +2136,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, rc = WideCharToMultiByte(ex->codepage, flags, buffer, -1, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefaultChar); if (rc) rc--; /* do not count 0 terminator */ - richedit_free(buffer); + heap_free(buffer); return rc; } } @@ -2324,25 +2412,47 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, SetWindowLongPtrW(hWnd, 0, 0); return 0; case WM_LBUTTONDOWN: + if ((editor->nEventMask & ENM_MOUSEEVENTS) && + !ME_FilterEvent(editor, msg, &wParam, &lParam)) + return 0; SetFocus(hWnd); ME_LButtonDown(editor, (short)LOWORD(lParam), (short)HIWORD(lParam)); SetCapture(hWnd); ME_LinkNotify(editor,msg,wParam,lParam); + ME_SetCursor(editor, LOWORD(lParam)); break; case WM_MOUSEMOVE: + if ((editor->nEventMask & ENM_MOUSEEVENTS) && + !ME_FilterEvent(editor, msg, &wParam, &lParam)) + return 0; if (GetCapture() == hWnd) ME_MouseMove(editor, (short)LOWORD(lParam), (short)HIWORD(lParam)); ME_LinkNotify(editor,msg,wParam,lParam); + ME_SetCursor(editor, LOWORD(lParam)); break; case WM_LBUTTONUP: if (GetCapture() == hWnd) ReleaseCapture(); + if ((editor->nEventMask & ENM_MOUSEEVENTS) && + !ME_FilterEvent(editor, msg, &wParam, &lParam)) + return 0; + editor->linesel = 0; + ME_SetCursor(editor, LOWORD(lParam)); ME_LinkNotify(editor,msg,wParam,lParam); 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: + if ((editor->nEventMask & ENM_MOUSEEVENTS) && + !ME_FilterEvent(editor, msg, &wParam, &lParam)) + return 0; + goto do_default; case WM_CONTEXTMENU: if (!ME_ShowContextMenu(editor, (short)LOWORD(lParam), (short)HIWORD(lParam))) goto do_default; @@ -2384,7 +2494,15 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, case WM_COMMAND: TRACE("editor wnd command = %d\n", LOWORD(wParam)); return 0; + case WM_KEYUP: + if ((editor->nEventMask & ENM_KEYEVENTS) && + !ME_FilterEvent(editor, msg, &wParam, &lParam)) + return 0; + goto do_default; case WM_KEYDOWN: + if ((editor->nEventMask & ENM_KEYEVENTS) && + !ME_FilterEvent(editor, msg, &wParam, &lParam)) + return 0; if (ME_KeyDown(editor, LOWORD(wParam))) return 0; goto do_default; @@ -2491,7 +2609,11 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, { int gcWheelDelta; UINT pulScrollLines; - + + if ((editor->nEventMask & ENM_MOUSEEVENTS) && + !ME_FilterEvent(editor, msg, &wParam, &lParam)) + return 0; + SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0); gcWheelDelta = -GET_WHEEL_DELTA_WPARAM(wParam); @@ -2538,7 +2660,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ME_SendRequestResize(editor, TRUE); return 0; case WM_SETREDRAW: - editor->bRedraw = wParam; + if ((editor->bRedraw = wParam)) + ME_RewrapRepaint(editor); return 0; case WM_SIZE: { @@ -2804,7 +2927,10 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in if (!ME_FindItemFwd(item, diRun)) /* No '\r' is appended to the last paragraph. */ nLen = 0; - else { + else if (bCRLF && nChars == 1) { + nLen = 0; + nChars = 0; + } else { *buffer = '\r'; if (bCRLF) { @@ -2847,7 +2973,7 @@ static BOOL ME_RegisterEditorClass(HINSTANCE hInstance) wcW.cbWndExtra = sizeof(ME_TextEditor *); wcW.hInstance = NULL; /* hInstance would register DLL-local class */ wcW.hIcon = NULL; - wcW.hCursor = LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_IBEAM)); + wcW.hCursor = hBeam; wcW.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); wcW.lpszMenuName = NULL; diff --git a/reactos/dll/win32/riched20/editor.h b/reactos/dll/win32/riched20/editor.h index 83dee767847..145dc912d3e 100644 --- a/reactos/dll/win32/riched20/editor.h +++ b/reactos/dll/win32/riched20/editor.h @@ -23,24 +23,24 @@ extern HANDLE me_heap; -static inline void *richedit_alloc( size_t len ) +static inline void *heap_alloc( size_t len ) { return HeapAlloc( me_heap, 0, len ); } -static inline BOOL richedit_free( void *ptr ) +static inline BOOL heap_free( void *ptr ) { return HeapFree( me_heap, 0, ptr ); } -static inline void *richedit_realloc( void *ptr, size_t len ) +static inline void *heap_realloc( void *ptr, size_t len ) { return HeapReAlloc( me_heap, 0, ptr, len ); } -#define ALLOC_OBJ(type) richedit_alloc(sizeof(type)) -#define ALLOC_N_OBJ(type, count) richedit_alloc((count)*sizeof(type)) -#define FREE_OBJ(ptr) richedit_free(ptr) +#define ALLOC_OBJ(type) heap_alloc(sizeof(type)) +#define ALLOC_N_OBJ(type, count) heap_alloc((count)*sizeof(type)) +#define FREE_OBJ(ptr) heap_free(ptr) #define RUN_IS_HIDDEN(run) ((run)->style->fmt.dwMask & CFM_HIDDEN \ && (run)->style->fmt.dwEffects & CFE_HIDDEN) @@ -60,8 +60,8 @@ void ME_AddRefStyle(ME_Style *item); void ME_ReleaseStyle(ME_Style *item); ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor); ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style); -HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s); -void ME_UnselectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s, HFONT hOldFont); +HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s); +void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, HFONT hOldFont); void ME_InitCharFormat2W(CHARFORMAT2W *pFmt); void ME_SaveTempStyle(ME_TextEditor *editor); void ME_ClearTempStyle(ME_TextEditor *editor); @@ -150,7 +150,7 @@ ME_DisplayItem *ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, void ME_CheckCharOffsets(ME_TextEditor *editor); void ME_PropagateCharOffset(ME_DisplayItem *p, int shift); void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize); -int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run); +int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run); /* this one accounts for 1/2 char tolerance */ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run); int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset); @@ -181,7 +181,6 @@ void ME_SelectWord(ME_TextEditor *editor); void ME_HideCaret(ME_TextEditor *ed); void ME_ShowCaret(ME_TextEditor *ed); void ME_MoveCaret(ME_TextEditor *ed); -int ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *result, BOOL *is_eol); int ME_CharFromPos(ME_TextEditor *editor, int x, int y); void ME_LButtonDown(ME_TextEditor *editor, int x, int y); void ME_MouseMove(ME_TextEditor *editor, int x, int y); @@ -211,18 +210,16 @@ ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor); BOOL ME_UpdateSelection(ME_TextEditor *editor, const ME_Cursor *pTempCursor); /* wrap.c */ -void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp); -ME_DisplayItem *ME_MakeRow(int height, int baseline, int width); -void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd); -void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp); 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); void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end); -void ME_MakeFirstParagraph(HDC hDC, ME_TextBuffer *editor); +void ME_MakeFirstParagraph(ME_TextEditor *editor); ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style); ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp); void ME_DumpParaStyle(ME_Paragraph *s); @@ -243,7 +240,6 @@ void ME_RewrapRepaint(ME_TextEditor *editor); void ME_UpdateRepaint(ME_TextEditor *editor); void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph); void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun); -COLORREF ME_GetBackColor(const ME_TextEditor *editor); void ME_InvalidateSelection(ME_TextEditor *editor); void ME_QueueInvalidateFromCursor(ME_TextEditor *editor, int nCursor); BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator); @@ -258,6 +254,10 @@ void ME_UpdateScrollBar(ME_TextEditor *editor); int ME_GetYScrollPos(ME_TextEditor *editor); BOOL ME_GetYScrollVisible(ME_TextEditor *editor); +/* other functions in paint.c */ +int ME_GetParaBorderWidth(ME_TextEditor *editor, int); +int ME_GetParaLineSpace(ME_Context *c, ME_Paragraph*); + /* richole.c */ extern LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *); diff --git a/reactos/dll/win32/riched20/editstr.h b/reactos/dll/win32/riched20/editstr.h index b86aeba629b..aa7fd6b2ba0 100644 --- a/reactos/dll/win32/riched20/editstr.h +++ b/reactos/dll/win32/riched20/editstr.h @@ -167,7 +167,6 @@ typedef struct tagME_Paragraph struct tagME_TableCell *pCells; /* list of cells and their properties */ struct tagME_TableCell *pLastCell; /* points to the last cell in the list */ - int nLeftMargin, nRightMargin, nFirstMargin; int nCharOfs; int nFlags; int nYPos, nHeight; @@ -325,6 +324,7 @@ typedef struct tagME_TextEditor BOOL bHaveFocus; /*for IME */ int imeStartIndex; + DWORD selofs, linesel, sely; } ME_TextEditor; typedef struct tagME_Context @@ -334,6 +334,7 @@ typedef struct tagME_Context POINT ptRowOffset; RECT rcView; HBRUSH hbrMargin; + SIZE dpi; /* those are valid inside ME_WrapTextParagraph and related */ POINT ptFirstRun; diff --git a/reactos/dll/win32/riched20/ocr_reverse.cur b/reactos/dll/win32/riched20/ocr_reverse.cur new file mode 100644 index 00000000000..179774c60ee Binary files /dev/null and b/reactos/dll/win32/riched20/ocr_reverse.cur differ diff --git a/reactos/dll/win32/riched20/paint.c b/reactos/dll/win32/riched20/paint.c index 7c40814f88b..03a588c2aae 100644 --- a/reactos/dll/win32/riched20/paint.c +++ b/reactos/dll/win32/riched20/paint.c @@ -109,7 +109,8 @@ void ME_UpdateRepaint(ME_TextEditor *editor) { /* Should be called whenever the contents of the control have changed */ ME_Cursor *pCursor; - + + if (!editor->bRedraw) return; if (ME_WrapMarkedParagraphs(editor)) ME_UpdateScrollBar(editor); @@ -135,27 +136,47 @@ ME_RewrapRepaint(ME_TextEditor *editor) * looks, but not content. Like resizing. */ ME_MarkAllForWrapping(editor); - ME_WrapMarkedParagraphs(editor); - ME_UpdateScrollBar(editor); - - ME_Repaint(editor); + if (editor->bRedraw) + { + ME_WrapMarkedParagraphs(editor); + ME_UpdateScrollBar(editor); + ME_Repaint(editor); + } } +int ME_twips2pointsX(ME_Context *c, int x) +{ + if (c->editor->nZoomNumerator == 0) + return x * c->dpi.cx / 1440; + else + return x * c->dpi.cx * c->editor->nZoomNumerator / 1440 / c->editor->nZoomDenominator; +} + +int ME_twips2pointsY(ME_Context *c, int y) +{ + if (c->editor->nZoomNumerator == 0) + return y * c->dpi.cy / 1440; + else + return y * c->dpi.cy * c->editor->nZoomNumerator / 1440 / c->editor->nZoomDenominator; +} static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChars, ME_Style *s, int *width, int nSelFrom, int nSelTo, int ymin, int cy) { HDC hDC = c->hDC; HGDIOBJ hOldFont; - COLORREF rgbOld, rgbBack; + COLORREF rgbOld; int yOffset = 0, yTwipsOffset = 0; - hOldFont = ME_SelectStyleFont(c->editor, hDC, s); - rgbBack = ME_GetBackColor(c->editor); + SIZE sz; + COLORREF rgb; + + hOldFont = ME_SelectStyleFont(c, s); if ((s->fmt.dwMask & CFM_LINK) && (s->fmt.dwEffects & CFE_LINK)) - rgbOld = SetTextColor(hDC, RGB(0,0,255)); + rgb = RGB(0,0,255); else if ((s->fmt.dwMask & CFM_COLOR) && (s->fmt.dwEffects & CFE_AUTOCOLOR)) - rgbOld = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); + rgb = GetSysColor(COLOR_WINDOWTEXT); else - rgbOld = SetTextColor(hDC, s->fmt.crTextColor); + rgb = s->fmt.crTextColor; + rgbOld = SetTextColor(hDC, rgb); if ((s->fmt.dwMask & s->fmt.dwEffects) & CFM_OFFSET) { yTwipsOffset = s->fmt.yOffset; } @@ -164,26 +185,43 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, in if (s->fmt.dwEffects & CFE_SUBSCRIPT) yTwipsOffset = -s->fmt.yHeight/12; } if (yTwipsOffset) - { - int numerator = 1; - int denominator = 1; - - if (c->editor->nZoomNumerator) - { - numerator = c->editor->nZoomNumerator; - denominator = c->editor->nZoomDenominator; - } - yOffset = yTwipsOffset * GetDeviceCaps(hDC, LOGPIXELSY) * numerator / denominator / 1440; - } + yOffset = ME_twips2pointsY(c, yTwipsOffset); ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nChars, NULL); - if (width) { - SIZE sz; - GetTextExtentPoint32W(hDC, szText, nChars, &sz); - *width = sz.cx; + GetTextExtentPoint32W(hDC, szText, nChars, &sz); + if (width) *width = sz.cx; + if (s->fmt.dwMask & CFM_UNDERLINETYPE) + { + HPEN hPen; + switch (s->fmt.bUnderlineType) + { + case CFU_UNDERLINE: + case CFU_UNDERLINEWORD: /* native seems to map it to simple underline (MSDN) */ + case CFU_UNDERLINEDOUBLE: /* native seems to map it to simple underline (MSDN) */ + hPen = CreatePen(PS_SOLID, 1, rgb); + break; + case CFU_UNDERLINEDOTTED: + hPen = CreatePen(PS_DOT, 1, rgb); + break; + default: + WINE_FIXME("Unknown underline type (%u)\n", s->fmt.bUnderlineType); + /* fall through */ + case CFU_CF1UNDERLINE: /* this type is supported in the font, do nothing */ + case CFU_UNDERLINENONE: + hPen = NULL; + break; + } + if (hPen != NULL) + { + HPEN hOldPen = SelectObject(hDC, hPen); + /* FIXME: should use textmetrics info for Descent info */ + MoveToEx(hDC, x, y - yOffset + 1, NULL); + LineTo(hDC, x + sz.cx, y - yOffset + 1); + SelectObject(hDC, hOldPen); + DeleteObject(hPen); + } } if (nSelFrom < nChars && nSelTo >= 0 && nSelFrom nChars) nSelTo = nChars; GetTextExtentPoint32W(hDC, szText, nSelFrom, &sz); @@ -195,7 +233,7 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, in PatBlt(hDC, x, ymin, sz.cx, cy, DSTINVERT); } SetTextColor(hDC, rgbOld); - ME_UnselectStyleFont(c->editor, hDC, s, hOldFont); + ME_UnselectStyleFont(c, s, hOldFont); } static void ME_DebugWrite(HDC hDC, const POINT *pt, LPCWSTR szText) { @@ -239,7 +277,7 @@ static void ME_DrawGraphics(ME_Context *c, int x, int y, ME_Run *run, static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para) { ME_Run *run = &rundi->member.run; - ME_DisplayItem *start = ME_FindItemBack(rundi, diStartRow); + ME_DisplayItem *start; int runofs = run->nCharOfs+para->nCharOfs; int nSelFrom, nSelTo; const WCHAR wszSpace[] = {' ', 0}; @@ -247,6 +285,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa if (run->nFlags & MERF_HIDDEN) return; + start = ME_FindItemBack(rundi, diStartRow); ME_GetSelection(c->editor, &nSelFrom, &nSelTo); /* Draw selected end-of-paragraph mark */ @@ -278,15 +317,184 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa } } -COLORREF ME_GetBackColor(const ME_TextEditor *editor) +static struct {unsigned width_num : 4, width_den : 4, pen_style : 4, dble : 1;} border_details[] = { + /* none */ {0, 0, PS_SOLID, FALSE}, + /* 3/4 */ {3, 4, PS_SOLID, FALSE}, + /* 1 1/2 */ {3, 2, PS_SOLID, FALSE}, + /* 2 1/4 */ {9, 4, PS_SOLID, FALSE}, + /* 3 */ {3, 1, PS_SOLID, FALSE}, + /* 4 1/2 */ {9, 2, PS_SOLID, FALSE}, + /* 6 */ {6, 1, PS_SOLID, FALSE}, + /* 3/4 double */ {3, 4, PS_SOLID, TRUE}, + /* 1 1/2 double */ {3, 2, PS_SOLID, TRUE}, + /* 2 1/4 double */ {9, 4, PS_SOLID, TRUE}, + /* 3/4 gray */ {3, 4, PS_DOT /* FIXME */, FALSE}, + /* 1 1/2 dashed */ {3, 2, PS_DASH, FALSE}, +}; + +static 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), + /* Yellow */ RGB(0xFF, 0xFF, 0x00), /* White */ RGB(0xFF, 0xFF, 0xFF), + /* Dark blue */ RGB(0x00, 0x00, 0x80), /* Dark cyan */ RGB(0x00, 0x80, 0x80), + /* Dark green */ RGB(0x00, 0x80, 0x80), /* Dark magenta */ RGB(0x80, 0x00, 0x80), + /* Dark red */ RGB(0x80, 0x00, 0x00), /* Dark yellow */ RGB(0x80, 0x80, 0x00), + /* Dark gray */ RGB(0x80, 0x80, 0x80), /* Light gray */ RGB(0xc0, 0xc0, 0xc0), +}; + +static int ME_GetBorderPenWidth(ME_TextEditor* editor, int idx) { -/* Looks like I was seriously confused - return GetSysColor((GetWindowLong(editor->hWnd, GWL_STYLE) & ES_READONLY) ? COLOR_3DFACE: COLOR_WINDOW); -*/ - if (editor->rgbBackColor == -1) - return GetSysColor(COLOR_WINDOW); + int width; + + if (editor->nZoomNumerator == 0) + { + width = border_details[idx].width_num + border_details[idx].width_den / 2; + width /= border_details[idx].width_den; + } else - return editor->rgbBackColor; + { + width = border_details[idx].width_num * editor->nZoomNumerator; + width += border_details[idx].width_den * editor->nZoomNumerator / 2; + width /= border_details[idx].width_den * editor->nZoomDenominator; + } + return width; +} + +int ME_GetParaBorderWidth(ME_TextEditor* editor, int flags) +{ + int idx = (flags >> 8) & 0xF; + int width; + + if (idx >= sizeof(border_details) / sizeof(border_details[0])) + { + FIXME("Unsupported border value %d\n", idx); + return 0; + } + width = ME_GetBorderPenWidth(editor, idx); + if (border_details[idx].dble) width = width * 2 + 1; + return width; +} + +int ME_GetParaLineSpace(ME_Context* c, ME_Paragraph* para) +{ + int sp = 0, ls = 0; + if (!(para->pFmt->dwMask & PFM_LINESPACING)) return 0; + + /* FIXME: how to compute simply the line space in ls ??? */ + /* FIXME: does line spacing include the line itself ??? */ + switch (para->pFmt->bLineSpacingRule) + { + case 0: sp = ls; break; + case 1: sp = (3 * ls) / 2; break; + case 2: sp = 2 * ls; break; + case 3: sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); if (sp < ls) sp = ls; break; + case 4: sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); break; + case 5: sp = para->pFmt->dyLineSpacing / 20; break; + default: FIXME("Unsupported spacing rule value %d\n", para->pFmt->bLineSpacingRule); + } + if (c->editor->nZoomNumerator == 0) + return sp; + else + return sp * c->editor->nZoomNumerator / c->editor->nZoomDenominator; +} + +static int ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y) +{ + int idx, border_width; + int ybefore, yafter; + RECT rc; + + if (!(para->pFmt->dwMask & (PFM_BORDER | PFM_SPACEBEFORE | PFM_SPACEAFTER))) return 0; + + if (para->pFmt->dwMask & PFM_SPACEBEFORE) + { + rc.left = c->rcView.left; + rc.right = c->rcView.right; + rc.top = y; + ybefore = ME_twips2pointsY(c, para->pFmt->dySpaceBefore); + rc.bottom = y + ybefore; + FillRect(c->hDC, &rc, c->editor->hbrBackground); + } + else ybefore = 0; + if (para->pFmt->dwMask & PFM_SPACEAFTER) + { + rc.left = c->rcView.left; + rc.right = c->rcView.right; + rc.bottom = y + para->nHeight; + yafter = ME_twips2pointsY(c, para->pFmt->dySpaceAfter); + rc.top = rc.bottom - yafter; + FillRect(c->hDC, &rc, c->editor->hbrBackground); + } + else yafter = 0; + + border_width = 0; + idx = (para->pFmt->wBorders >> 8) & 0xF; + if ((para->pFmt->dwMask & PFM_BORDER) && idx != 0 && (para->pFmt->wBorders & 0xF)) { + int pen_width; + COLORREF pencr; + HPEN pen = NULL, oldpen = NULL; + POINT pt; + + if (para->pFmt->wBorders & 0x00B0) + FIXME("Unsupported border flags %x\n", para->pFmt->wBorders); + border_width = ME_GetParaBorderWidth(c->editor, para->pFmt->wBorders); + + if (para->pFmt->wBorders & 64) /* autocolor */ + pencr = GetSysColor(COLOR_WINDOWTEXT); + else + pencr = pen_colors[(para->pFmt->wBorders >> 12) & 0xF]; + + pen_width = ME_GetBorderPenWidth(c->editor, idx); + pen = CreatePen(border_details[idx].pen_style, pen_width, pencr); + oldpen = SelectObject(c->hDC, pen); + MoveToEx(c->hDC, 0, 0, &pt); + + /* before & after spaces are not included in border */ + if (para->pFmt->wBorders & 1) + { + MoveToEx(c->hDC, c->rcView.left, y + ybefore, NULL); + LineTo(c->hDC, c->rcView.left, y + para->nHeight - yafter); + if (border_details[idx].dble) { + MoveToEx(c->hDC, c->rcView.left + pen_width + 1, y + ybefore + pen_width + 1, NULL); + LineTo(c->hDC, c->rcView.left + pen_width + 1, y + para->nHeight - yafter - pen_width - 1); + } + } + if (para->pFmt->wBorders & 2) + { + MoveToEx(c->hDC, c->rcView.right, y + ybefore, NULL); + LineTo(c->hDC, c->rcView.right, y + para->nHeight - yafter); + if (border_details[idx].dble) { + MoveToEx(c->hDC, c->rcView.right - pen_width - 1, y + ybefore + pen_width + 1, NULL); + LineTo(c->hDC, c->rcView.right - pen_width - 1, y + para->nHeight - yafter - pen_width - 1); + } + } + if (para->pFmt->wBorders & 4) + { + MoveToEx(c->hDC, c->rcView.left, y + ybefore, NULL); + LineTo(c->hDC, c->rcView.right, y + ybefore); + if (border_details[idx].dble) { + MoveToEx(c->hDC, c->rcView.left + pen_width + 1, y + ybefore + pen_width + 1, NULL); + LineTo(c->hDC, c->rcView.right - pen_width - 1, y + ybefore + pen_width + 1); + } + } + if (para->pFmt->wBorders & 8) + { + MoveToEx(c->hDC, c->rcView.left, y + para->nHeight - yafter - 1, NULL); + LineTo(c->hDC, c->rcView.right, y + para->nHeight - yafter - 1); + if (border_details[idx].dble) { + MoveToEx(c->hDC, c->rcView.left + pen_width + 1, y + para->nHeight - yafter - 1 - pen_width - 1, NULL); + LineTo(c->hDC, c->rcView.right - pen_width - 1, y + para->nHeight - yafter - 1 - pen_width - 1); + } + } + + MoveToEx(c->hDC, pt.x, pt.y, NULL); + SelectObject(c->hDC, oldpen); + DeleteObject(pen); + } + return ybefore + + ((para->pFmt->dwMask & PFM_BORDER) && (para->pFmt->wBorders & 4) ? + border_width : 0); } void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { @@ -297,10 +505,10 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { RECT rc, rcPara; int y = c->pt.y; int height = 0, baseline = 0, no=0, pno = 0; - int xs, xe; - int visible = 0; + int xs = 0, xe = 0; + BOOL visible = FALSE; int nMargWidth = 0; - + c->pt.x = c->rcView.left; rcPara.left = c->rcView.left; rcPara.right = c->rcView.right; @@ -308,33 +516,33 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { switch(p->type) { case diParagraph: para = &p->member.para; + assert(para); + nMargWidth = ME_twips2pointsX(c, para->pFmt->dxStartIndent); + if (pno != 0) + nMargWidth += ME_twips2pointsX(c, para->pFmt->dxOffset); + xs = c->rcView.left+nMargWidth; + xe = c->rcView.right - ME_twips2pointsX(c, para->pFmt->dxRightIndent); + y += ME_DrawParaDecoration(c, para, y); break; case diStartRow: - assert(para); - nMargWidth = (pno==0?para->nFirstMargin:para->nLeftMargin); - xs = c->rcView.left+nMargWidth; - xe = c->rcView.right-para->nRightMargin; y += height; rcPara.top = y; rcPara.bottom = y+p->member.row.nHeight; visible = RectVisible(c->hDC, &rcPara); if (visible) { - HBRUSH hbr; - hbr = CreateSolidBrush(ME_GetBackColor(c->editor)); /* left margin */ rc.left = c->rcView.left; rc.right = c->rcView.left+nMargWidth; rc.top = y; rc.bottom = y+p->member.row.nHeight; - FillRect(c->hDC, &rc, hbr/* c->hbrMargin */); + FillRect(c->hDC, &rc, c->editor->hbrBackground); /* right margin */ rc.left = xe; rc.right = c->rcView.right; - FillRect(c->hDC, &rc, hbr/* c->hbrMargin */); + FillRect(c->hDC, &rc, c->editor->hbrBackground); rc.left = c->rcView.left+nMargWidth; rc.right = xe; - FillRect(c->hDC, &rc, hbr); - DeleteObject(hbr); + FillRect(c->hDC, &rc, c->editor->hbrBackground); } if (me_debug) { @@ -489,8 +697,7 @@ int ME_GetYScrollPos(ME_TextEditor *editor) SCROLLINFO si; si.cbSize = sizeof(si); si.fMask = SIF_POS; - GetScrollInfo(editor->hWnd, SB_VERT, &si); - return si.nPos; + return GetScrollInfo(editor->hWnd, SB_VERT, &si) ? si.nPos : 0; } BOOL ME_GetYScrollVisible(ME_TextEditor *editor) @@ -558,25 +765,26 @@ ME_InvalidateSelection(ME_TextEditor *editor) assert(para2->type == diParagraph); /* last selection markers aren't always updated, which means they can point past the end of the document */ - if (editor->nLastSelStart > len) - editor->nLastSelEnd = len; - if (editor->nLastSelEnd > len) - editor->nLastSelEnd = len; - - /* if the start part of selection is being expanded or contracted... */ - if (nStart < editor->nLastSelStart) { - ME_MarkForPainting(editor, para1, ME_FindItemFwd(editor->pLastSelStartPara, diParagraphOrEnd)); - } else - if (nStart > editor->nLastSelStart) { - ME_MarkForPainting(editor, editor->pLastSelStartPara, ME_FindItemFwd(para1, diParagraphOrEnd)); - } + if (editor->nLastSelStart > len || editor->nLastSelEnd > len) { + ME_MarkForPainting(editor, + ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph), + ME_FindItemFwd(editor->pBuffer->pFirst, diTextEnd)); + } else { + /* if the start part of selection is being expanded or contracted... */ + if (nStart < editor->nLastSelStart) { + ME_MarkForPainting(editor, para1, ME_FindItemFwd(editor->pLastSelStartPara, diParagraphOrEnd)); + } else + if (nStart > editor->nLastSelStart) { + ME_MarkForPainting(editor, editor->pLastSelStartPara, ME_FindItemFwd(para1, diParagraphOrEnd)); + } - /* if the end part of selection is being contracted or expanded... */ - if (nEnd < editor->nLastSelEnd) { - ME_MarkForPainting(editor, para2, ME_FindItemFwd(editor->pLastSelEndPara, diParagraphOrEnd)); - } else - if (nEnd > editor->nLastSelEnd) { - ME_MarkForPainting(editor, editor->pLastSelEndPara, ME_FindItemFwd(para2, diParagraphOrEnd)); + /* if the end part of selection is being contracted or expanded... */ + if (nEnd < editor->nLastSelEnd) { + ME_MarkForPainting(editor, para2, ME_FindItemFwd(editor->pLastSelEndPara, diParagraphOrEnd)); + } else + if (nEnd > editor->nLastSelEnd) { + ME_MarkForPainting(editor, editor->pLastSelEndPara, ME_FindItemFwd(para2, diParagraphOrEnd)); + } } ME_InvalidateMarkedParagraphs(editor); diff --git a/reactos/dll/win32/riched20/para.c b/reactos/dll/win32/riched20/para.c index a1f62611db6..af292f161c5 100644 --- a/reactos/dll/win32/riched20/para.c +++ b/reactos/dll/win32/riched20/para.c @@ -25,16 +25,22 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); static const WCHAR wszParagraphSign[] = {0xB6, 0}; -void ME_MakeFirstParagraph(HDC hDC, ME_TextBuffer *text) +void ME_MakeFirstParagraph(ME_TextEditor *editor) { + ME_Context c; + HDC hDC; PARAFORMAT2 fmt; CHARFORMAT2W cf; LOGFONTW lf; HFONT hf; + ME_TextBuffer *text = editor->pBuffer; ME_DisplayItem *para = ME_MakeDI(diParagraph); ME_DisplayItem *run; ME_Style *style; + hDC = GetDC(editor->hWnd); + + ME_InitContext(&c, editor, hDC); hf = (HFONT)GetStockObject(SYSTEM_FONT); assert(hf); GetObjectW(hf, sizeof(LOGFONTW), &lf); @@ -44,21 +50,23 @@ void ME_MakeFirstParagraph(HDC hDC, ME_TextBuffer *text) cf.dwMask |= CFM_ALLCAPS|CFM_BOLD|CFM_DISABLED|CFM_EMBOSS|CFM_HIDDEN; cf.dwMask |= CFM_IMPRINT|CFM_ITALIC|CFM_LINK|CFM_OUTLINE|CFM_PROTECTED; cf.dwMask |= CFM_REVISED|CFM_SHADOW|CFM_SMALLCAPS|CFM_STRIKEOUT; - cf.dwMask |= CFM_SUBSCRIPT|CFM_UNDERLINE; + cf.dwMask |= CFM_SUBSCRIPT|CFM_UNDERLINETYPE|CFM_WEIGHT; cf.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR; lstrcpyW(cf.szFaceName, lf.lfFaceName); - cf.yHeight=lf.lfHeight*1440/GetDeviceCaps(hDC, LOGPIXELSY); - if (lf.lfWeight>=700) /* FIXME correct weight ? */ - cf.dwEffects |= CFE_BOLD; + cf.yHeight = ME_twips2pointsY(&c, lf.lfHeight); + if (lf.lfWeight >= 700) cf.dwEffects |= CFE_BOLD; cf.wWeight = lf.lfWeight; if (lf.lfItalic) cf.dwEffects |= CFE_ITALIC; - if (lf.lfUnderline) cf.dwEffects |= CFE_UNDERLINE; + cf.bUnderlineType = (lf.lfUnderline) ? CFU_CF1UNDERLINE : CFU_UNDERLINENONE; if (lf.lfStrikeOut) cf.dwEffects |= CFE_STRIKEOUT; - + cf.bPitchAndFamily = lf.lfPitchAndFamily; + cf.bCharSet = lf.lfCharSet; + ZeroMemory(&fmt, sizeof(fmt)); fmt.cbSize = sizeof(fmt); fmt.dwMask = PFM_ALIGNMENT | PFM_OFFSET | PFM_STARTINDENT | PFM_RIGHTINDENT | PFM_TABSTOPS; + fmt.wAlignment = PFA_LEFT; CopyMemory(para->member.para.pFmt, &fmt, sizeof(PARAFORMAT2)); @@ -76,6 +84,9 @@ void ME_MakeFirstParagraph(HDC hDC, ME_TextBuffer *text) text->pLast->member.para.prev_para = para; text->pLast->member.para.nCharOfs = 1; + + ME_DestroyContext(&c); + ReleaseDC(editor->hWnd, hDC); } void ME_MarkAllForWrapping(ME_TextEditor *editor) @@ -138,11 +149,6 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME new_para->member.para.nFlags = MEPF_REWRAP; /* FIXME copy flags (if applicable) */ /* FIXME initialize format style and call ME_SetParaFormat blah blah */ CopyMemory(new_para->member.para.pFmt, run_para->member.para.pFmt, sizeof(PARAFORMAT2)); - - /* FIXME remove this as soon as nLeftMargin etc are replaced with proper fields of PARAFORMAT2 */ - new_para->member.para.nLeftMargin = run_para->member.para.nLeftMargin; - new_para->member.para.nRightMargin = run_para->member.para.nRightMargin; - new_para->member.para.nFirstMargin = run_para->member.para.nFirstMargin; new_para->member.para.bTable = run_para->member.para.bTable; @@ -277,45 +283,67 @@ ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *item) { return ME_FindItemBackOrHere(item, diParagraph); } -static void ME_DumpStyleEffect(char **p, const char *name, const PARAFORMAT2 *fmt, int mask) -{ - *p += sprintf(*p, "%-22s%s\n", name, (fmt->dwMask & mask) ? ((fmt->wEffects & mask) ? "yes" : "no") : "N/A"); -} - void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) { - /* FIXME only PARAFORMAT styles implemented */ char *p; p = buf; - p += sprintf(p, "Alignment: %s\n", - !(pFmt->dwMask & PFM_ALIGNMENT) ? "N/A" : - ((pFmt->wAlignment == PFA_LEFT) ? "left" : - ((pFmt->wAlignment == PFA_RIGHT) ? "right" : - ((pFmt->wAlignment == PFA_CENTER) ? "center" : - /*((pFmt->wAlignment == PFA_JUSTIFY) ? "justify" : "incorrect")*/ - "incorrect")))); - if (pFmt->dwMask & PFM_OFFSET) - p += sprintf(p, "Offset: %d\n", (int)pFmt->dxOffset); - else - p += sprintf(p, "Offset: N/A\n"); - - if (pFmt->dwMask & PFM_OFFSETINDENT) - p += sprintf(p, "Offset indent: %d\n", (int)pFmt->dxStartIndent); - else - p += sprintf(p, "Offset indent: N/A\n"); - - if (pFmt->dwMask & PFM_STARTINDENT) - p += sprintf(p, "Start indent: %d\n", (int)pFmt->dxStartIndent); - else - p += sprintf(p, "Start indent: N/A\n"); - - if (pFmt->dwMask & PFM_RIGHTINDENT) - p += sprintf(p, "Right indent: %d\n", (int)pFmt->dxRightIndent); - else - p += sprintf(p, "Right indent: N/A\n"); - - ME_DumpStyleEffect(&p, "Page break before:", pFmt, PFM_PAGEBREAKBEFORE); +#define DUMP(mask, name, fmt, field) \ + if (pFmt->dwMask & (mask)) p += sprintf(p, "%-22s" fmt "\n", name, pFmt->field); \ + else p += sprintf(p, "%-22sN/A\n", name); + +/* we take for granted that PFE_xxx is the hiword of the corresponding PFM_xxx */ +#define DUMP_EFFECT(mask, name) \ + p += sprintf(p, "%-22s%s\n", name, (pFmt->dwMask & (mask)) ? ((pFmt->wEffects & ((mask) >> 8)) ? "yes" : "no") : "N/A"); + + DUMP(PFM_NUMBERING, "Numbering:", "%u", wNumbering); + DUMP_EFFECT(PFM_DONOTHYPHEN, "Disable auto-hyphen:"); + DUMP_EFFECT(PFM_KEEP, "No page break in para:"); + DUMP_EFFECT(PFM_KEEPNEXT, "No page break in para & next:"); + DUMP_EFFECT(PFM_NOLINENUMBER, "No line number:"); + DUMP_EFFECT(PFM_NOWIDOWCONTROL, "No widow & orphan:"); + DUMP_EFFECT(PFM_PAGEBREAKBEFORE, "Page break before:"); + DUMP_EFFECT(PFM_RTLPARA, "RTL para:"); + DUMP_EFFECT(PFM_SIDEBYSIDE, "Side by side:"); + DUMP_EFFECT(PFM_TABLE, "Table:"); + DUMP(PFM_OFFSETINDENT, "Offset indent:", "%d", dxStartIndent); + DUMP(PFM_STARTINDENT, "Start indent:", "%d", dxStartIndent); + DUMP(PFM_RIGHTINDENT, "Right indent:", "%d", dxRightIndent); + DUMP(PFM_OFFSET, "Offset:", "%d", dxOffset); + if (pFmt->dwMask & PFM_ALIGNMENT) { + switch (pFmt->wAlignment) { + case PFA_LEFT : p += sprintf(p, "Alignment: left\n"); break; + case PFA_RIGHT : p += sprintf(p, "Alignment: right\n"); break; + case PFA_CENTER : p += sprintf(p, "Alignment: center\n"); break; + case PFA_JUSTIFY: p += sprintf(p, "Alignment: justify\n"); break; + default : p += sprintf(p, "Alignment: incorrect %d\n", pFmt->wAlignment); break; + } + } + else p += sprintf(p, "Alignment: N/A\n"); + DUMP(PFM_TABSTOPS, "Tab Stops:", "%d", cTabCount); + if (pFmt->dwMask & PFM_TABSTOPS) { + int i; + p += sprintf(p, "\t"); + for (i = 0; i < pFmt->cTabCount; i++) p += sprintf(p, "%x ", pFmt->rgxTabs[i]); + p += sprintf(p, "\n"); + } + DUMP(PFM_SPACEBEFORE, "Space Before:", "%d", dySpaceBefore); + DUMP(PFM_SPACEAFTER, "Space After:", "%d", dySpaceAfter); + DUMP(PFM_LINESPACING, "Line spacing:", "%d", dyLineSpacing); + DUMP(PFM_STYLE, "Text style:", "%d", sStyle); + DUMP(PFM_LINESPACING, "Line spacing rule:", "%u", bLineSpacingRule); + /* bOutlineLevel should be 0 */ + DUMP(PFM_SHADING, "Shading Weigth:", "%u", wShadingWeight); + DUMP(PFM_SHADING, "Shading Style:", "%u", wShadingStyle); + DUMP(PFM_NUMBERINGSTART, "Numbering Start:", "%u", wNumberingStart); + DUMP(PFM_NUMBERINGSTYLE, "Numbering Style:", "0x%x", wNumberingStyle); + DUMP(PFM_NUMBERINGTAB, "Numbering Tab:", "%u", wNumberingStyle); + DUMP(PFM_BORDER, "Border Space:", "%u", wBorderSpace); + DUMP(PFM_BORDER, "Border Width:", "%u", wBorderWidth); + DUMP(PFM_BORDER, "Borders:", "%u", wBorders); + +#undef DUMP +#undef DUMP_EFFECT } void ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFORMAT2 *pFmt) @@ -326,22 +354,51 @@ void ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFOR CopyMemory(©, para->member.para.pFmt, sizeof(PARAFORMAT2)); - if (pFmt->dwMask & PFM_ALIGNMENT) - para->member.para.pFmt->wAlignment = pFmt->wAlignment; - if (pFmt->dwMask & PFM_STARTINDENT) - para->member.para.pFmt->dxStartIndent = pFmt->dxStartIndent; - if (pFmt->dwMask & PFM_OFFSET) - para->member.para.pFmt->dxOffset = pFmt->dxOffset; +#define COPY_FIELD(m, f) \ + if (pFmt->dwMask & (m)) { \ + para->member.para.pFmt->dwMask |= m; \ + para->member.para.pFmt->f = pFmt->f; \ + } + + COPY_FIELD(PFM_NUMBERING, wNumbering); +#define EFFECTS_MASK (PFM_RTLPARA|PFM_KEEP|PFM_KEEPNEXT|PFM_PAGEBREAKBEFORE| \ + PFM_NOLINENUMBER|PFM_NOWIDOWCONTROL|PFM_DONOTHYPHEN|PFM_SIDEBYSIDE| \ + PFM_TABLE) + /* we take for granted that PFE_xxx is the hiword of the corresponding PFM_xxx */ + if (pFmt->dwMask & EFFECTS_MASK) { + para->member.para.pFmt->dwMask &= ~(pFmt->dwMask & EFFECTS_MASK); + para->member.para.pFmt->wEffects |= pFmt->wEffects & HIWORD(pFmt->dwMask); + } +#undef EFFECTS_MASK + + COPY_FIELD(PFM_STARTINDENT, dxStartIndent); if (pFmt->dwMask & PFM_OFFSETINDENT) para->member.para.pFmt->dxStartIndent += pFmt->dxStartIndent; - + COPY_FIELD(PFM_RIGHTINDENT, dxRightIndent); + COPY_FIELD(PFM_OFFSET, dxOffset); + COPY_FIELD(PFM_ALIGNMENT, wAlignment); + if (pFmt->dwMask & PFM_TABSTOPS) { para->member.para.pFmt->cTabCount = pFmt->cTabCount; - memcpy(para->member.para.pFmt->rgxTabs, pFmt->rgxTabs, pFmt->cTabCount*sizeof(int)); + memcpy(para->member.para.pFmt->rgxTabs, pFmt->rgxTabs, pFmt->cTabCount*sizeof(LONG)); } - - /* FIXME to be continued (indents, bulleting and such) */ + COPY_FIELD(PFM_SPACEBEFORE, dySpaceBefore); + COPY_FIELD(PFM_SPACEAFTER, dySpaceAfter); + COPY_FIELD(PFM_LINESPACING, dyLineSpacing); + COPY_FIELD(PFM_STYLE, sStyle); + COPY_FIELD(PFM_LINESPACING, bLineSpacingRule); + COPY_FIELD(PFM_SHADING, wShadingWeight); + COPY_FIELD(PFM_SHADING, wShadingStyle); + COPY_FIELD(PFM_NUMBERINGSTART, wNumberingStart); + COPY_FIELD(PFM_NUMBERINGSTYLE, wNumberingStyle); + COPY_FIELD(PFM_NUMBERINGTAB, wNumberingTab); + COPY_FIELD(PFM_BORDER, wBorderSpace); + COPY_FIELD(PFM_BORDER, wBorderWidth); + COPY_FIELD(PFM_BORDER, wBorders); + + para->member.para.pFmt->dwMask |= pFmt->dwMask; +#undef COPY_FIELD if (memcmp(©, para->member.para.pFmt, sizeof(PARAFORMAT2))) para->member.para.nFlags |= MEPF_REWRAP; @@ -410,28 +467,45 @@ void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) ZeroMemory(&tmp, sizeof(tmp)); tmp.cbSize = sizeof(tmp); ME_GetParaFormat(editor, para, &tmp); - - assert(tmp.dwMask & PFM_ALIGNMENT); - if (pFmt->wAlignment != tmp.wAlignment) - pFmt->dwMask &= ~PFM_ALIGNMENT; - + +#define CHECK_FIELD(m, f) \ + if (pFmt->f != tmp.f) pFmt->dwMask &= ~(m); + + CHECK_FIELD(PFM_NUMBERING, wNumbering); + /* para->member.para.pFmt->wEffects = pFmt->wEffects; */ + assert(tmp.dwMask & PFM_ALIGNMENT); + CHECK_FIELD(PFM_NUMBERING, wNumbering); assert(tmp.dwMask & PFM_STARTINDENT); - if (pFmt->dxStartIndent != tmp.dxStartIndent) - pFmt->dwMask &= ~PFM_STARTINDENT; - + CHECK_FIELD(PFM_STARTINDENT, dxStartIndent); + assert(tmp.dwMask & PFM_RIGHTINDENT); + CHECK_FIELD(PFM_RIGHTINDENT, dxRightIndent); assert(tmp.dwMask & PFM_OFFSET); - if (pFmt->dxOffset != tmp.dxOffset) - pFmt->dwMask &= ~PFM_OFFSET; - - assert(tmp.dwMask & PFM_TABSTOPS); + CHECK_FIELD(PFM_OFFSET, dxOffset); + CHECK_FIELD(PFM_ALIGNMENT, wAlignment); + + assert(tmp.dwMask & PFM_TABSTOPS); if (pFmt->dwMask & PFM_TABSTOPS) { - if (pFmt->cTabCount != tmp.cTabCount) - pFmt->dwMask &= ~PFM_TABSTOPS; - else - if (memcmp(pFmt->rgxTabs, tmp.rgxTabs, tmp.cTabCount*sizeof(int))) + if (pFmt->cTabCount != tmp.cTabCount || + memcmp(pFmt->rgxTabs, tmp.rgxTabs, tmp.cTabCount*sizeof(int))) pFmt->dwMask &= ~PFM_TABSTOPS; } - + + CHECK_FIELD(PFM_SPACEBEFORE, dySpaceBefore); + CHECK_FIELD(PFM_SPACEAFTER, dySpaceAfter); + CHECK_FIELD(PFM_LINESPACING, dyLineSpacing); + CHECK_FIELD(PFM_STYLE, sStyle); + CHECK_FIELD(PFM_SPACEAFTER, bLineSpacingRule); + CHECK_FIELD(PFM_SHADING, wShadingWeight); + CHECK_FIELD(PFM_SHADING, wShadingStyle); + CHECK_FIELD(PFM_NUMBERINGSTART, wNumberingStart); + CHECK_FIELD(PFM_NUMBERINGSTYLE, wNumberingStyle); + CHECK_FIELD(PFM_NUMBERINGTAB, wNumberingTab); + CHECK_FIELD(PFM_BORDER, wBorderSpace); + CHECK_FIELD(PFM_BORDER, wBorderWidth); + CHECK_FIELD(PFM_BORDER, wBorders); + +#undef CHECK_FIELD + if (para == para_end) return; para = para->member.para.next_para; diff --git a/reactos/dll/win32/riched20/reader.c b/reactos/dll/win32/riched20/reader.c index e0a9e1a86e3..ebc97457b40 100644 --- a/reactos/dll/win32/riched20/reader.c +++ b/reactos/dll/win32/riched20/reader.c @@ -76,18 +76,6 @@ static void RTFPutCodePageChar(RTF_Info *info, int c); /* ---------------------------------------------------------------------- */ -/* - * Memory allocation routines - */ - - -/* - * Return pointer to block of size bytes, or NULL if there's - * not enough memory available. - */ -#define RTFAlloc(size) richedit_alloc(size) -#define RTFReAlloc(ptr, size) richedit_realloc(ptr, size) -#define RTFFree(ptr) richedit_free(ptr) /* * Saves a string on the heap and returns a pointer to it. @@ -96,7 +84,7 @@ static inline char *RTFStrSave(const char *s) { char *p; - p = RTFAlloc (lstrlenA(s) + 1); + p = heap_alloc (lstrlenA(s) + 1); if (p == NULL) return NULL; return lstrcpyA (p, s); @@ -143,14 +131,14 @@ RTFDestroyAttrs(RTF_Info *info) while (info->fontList) { fp = info->fontList->rtfNextFont; - RTFFree (info->fontList->rtfFName); - RTFFree (info->fontList); + heap_free (info->fontList->rtfFName); + heap_free (info->fontList); info->fontList = fp; } while (info->colorList) { cp = info->colorList->rtfNextColor; - RTFFree (info->colorList); + heap_free (info->colorList); info->colorList = cp; } while (info->styleList) @@ -160,12 +148,12 @@ RTFDestroyAttrs(RTF_Info *info) while (eltList) { ep = eltList->rtfNextSE; - RTFFree (eltList->rtfSEText); - RTFFree (eltList); + heap_free (eltList->rtfSEText); + heap_free (eltList); eltList = ep; } - RTFFree (info->styleList->rtfSName); - RTFFree (info->styleList); + heap_free (info->styleList->rtfSName); + heap_free (info->styleList); info->styleList = sp; } } @@ -176,11 +164,11 @@ RTFDestroy(RTF_Info *info) { if (info->rtfTextBuf) { - RTFFree(info->rtfTextBuf); - RTFFree(info->pushedTextBuf); + heap_free(info->rtfTextBuf); + heap_free(info->pushedTextBuf); } RTFDestroyAttrs(info); - RTFFree(info->cpOutputBuffer); + heap_free(info->cpOutputBuffer); } @@ -196,15 +184,15 @@ void RTFInit(RTF_Info *info) if (info->rtfTextBuf == NULL) /* initialize the text buffers */ { - info->rtfTextBuf = RTFAlloc (rtfBufSiz); - info->pushedTextBuf = RTFAlloc (rtfBufSiz); + info->rtfTextBuf = heap_alloc (rtfBufSiz); + info->pushedTextBuf = heap_alloc (rtfBufSiz); if (info->rtfTextBuf == NULL || info->pushedTextBuf == NULL) ERR ("Cannot allocate text buffers.\n"); info->rtfTextBuf[0] = info->pushedTextBuf[0] = '\0'; } - RTFFree (info->inputName); - RTFFree (info->outputName); + heap_free (info->inputName); + heap_free (info->outputName); info->inputName = info->outputName = NULL; for (i = 0; i < rtfMaxClass; i++) @@ -245,7 +233,7 @@ void RTFInit(RTF_Info *info) if (!info->cpOutputBuffer) { info->dwMaxCPOutputCount = 0x1000; - info->cpOutputBuffer = RTFAlloc(info->dwMaxCPOutputCount); + info->cpOutputBuffer = heap_alloc(info->dwMaxCPOutputCount); } } @@ -564,7 +552,7 @@ RTFCharSetToCodePage(RTF_Info *info, int charset) /* FIXME: TranslateCharsetInfo does not work as good as it * should, so let's use it only when all else fails */ if (!TranslateCharsetInfo(&n, &csi, TCI_SRCCHARSET)) - ERR("%s: unknown charset %u\n", __FUNCTION__, charset); + ERR("unknown charset %d\n", charset); else return csi.ciACP; } @@ -2300,9 +2288,9 @@ void LookupInit(void) rp->rtfKHash = Hash (rp->rtfKStr); index = rp->rtfKHash % (RTF_KEY_COUNT * 2); if (!rtfHashTable[index].count) - rtfHashTable[index].value = RTFAlloc(sizeof(RTFKey *)); + rtfHashTable[index].value = heap_alloc(sizeof(RTFKey *)); else - rtfHashTable[index].value = RTFReAlloc(rtfHashTable[index].value, sizeof(RTFKey *) * (rtfHashTable[index].count + 1)); + rtfHashTable[index].value = heap_realloc(rtfHashTable[index].value, sizeof(RTFKey *) * (rtfHashTable[index].count + 1)); rtfHashTable[index].value[rtfHashTable[index].count++] = rp; } } @@ -2313,7 +2301,7 @@ void LookupCleanup(void) for (i=0; idwCPOutputCount * 2 * sizeof(WCHAR); - WCHAR *buffer = RTFAlloc(bufferMax); + WCHAR *buffer = heap_alloc(bufferMax); int length; length = MultiByteToWideChar(info->codePage, 0, info->cpOutputBuffer, @@ -2690,7 +2678,7 @@ RTFFlushCPOutputBuffer(RTF_Info *info) info->dwCPOutputCount = 0; RTFPutUnicodeString(info, buffer, length); - RTFFree((char *)buffer); + heap_free((char *)buffer); } void @@ -2719,7 +2707,7 @@ RTFPutCodePageChar(RTF_Info *info, int c) if (info->dwCPOutputCount >= info->dwMaxCPOutputCount) { info->dwMaxCPOutputCount *= 2; - info->cpOutputBuffer = RTFReAlloc(info->cpOutputBuffer, info->dwMaxCPOutputCount); + info->cpOutputBuffer = heap_realloc(info->cpOutputBuffer, info->dwMaxCPOutputCount); } info->cpOutputBuffer[info->dwCPOutputCount++] = c; } diff --git a/reactos/dll/win32/riched20/res.h b/reactos/dll/win32/riched20/res.h new file mode 100644 index 00000000000..8f329d1fb5a --- /dev/null +++ b/reactos/dll/win32/riched20/res.h @@ -0,0 +1,21 @@ +/* + * Top level resource file for MOUSE driver dll + * + * Copyright 2007 Maarten Lankhorst for CodeWeavers + * + * 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 + */ + +#define OCR_REVERSE 32768 diff --git a/reactos/dll/win32/riched20/riched20.rbuild b/reactos/dll/win32/riched20/riched20.rbuild index 0a658cb8631..1ed5e8c36db 100644 --- a/reactos/dll/win32/riched20/riched20.rbuild +++ b/reactos/dll/win32/riched20/riched20.rbuild @@ -1,5 +1,6 @@ + . @@ -35,3 +36,4 @@ version.rc riched20.spec + diff --git a/reactos/dll/win32/riched20/richole.c b/reactos/dll/win32/riched20/richole.c index 0585e43edf8..9bd44aaee4e 100644 --- a/reactos/dll/win32/riched20/richole.c +++ b/reactos/dll/win32/riched20/richole.c @@ -112,7 +112,7 @@ IRichEditOle_fnRelease(IRichEditOle *me) if (!ref) { TRACE ("Destroying %p\n", This); - richedit_free(This); + heap_free(This); } return ref; } @@ -529,7 +529,7 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) { IRichEditOleImpl *reo; - reo = richedit_alloc(sizeof(IRichEditOleImpl)); + reo = heap_alloc(sizeof(IRichEditOleImpl)); if (!reo) return 0; diff --git a/reactos/dll/win32/riched20/rtf.h b/reactos/dll/win32/riched20/rtf.h index 7234b435f88..5a1251533a3 100644 --- a/reactos/dll/win32/riched20/rtf.h +++ b/reactos/dll/win32/riched20/rtf.h @@ -36,7 +36,7 @@ * that only care about gross token distinctions. * Major/minor numbers: Within their class, tokens have a major * number, and may also have a minor number to further - * distinquish tokens with the same major number. + * distinguish tokens with the same major number. * * *** Class, major and minor token numbers are all >= 0 *** * @@ -1005,7 +1005,7 @@ struct RTFStyleElt * if no memory available. */ -# define New(t) ((t *) RTFAlloc ((int) sizeof (t))) +# define New(t) (heap_alloc (sizeof (t))) /* Parser stack size */ diff --git a/reactos/dll/win32/riched20/run.c b/reactos/dll/win32/riched20/run.c index 16306530b0b..2da891e7851 100644 --- a/reactos/dll/win32/riched20/run.c +++ b/reactos/dll/win32/riched20/run.c @@ -487,11 +487,10 @@ void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize) * pixel horizontal position. This version rounds left (ie. if the second * character is at pixel position 8, then for cx=0..7 it returns 0). */ -int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run) +int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run) { int fit = 0; HGDIOBJ hOldFont; - HDC hDC; SIZE sz; if (!run->strText->nLen) return 0; @@ -505,29 +504,28 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run) if (run->nFlags & MERF_GRAPHICS) { SIZE sz; - ME_GetGraphicsSize(editor, run, &sz); + ME_GetGraphicsSize(c->editor, run, &sz); if (cx < sz.cx) return 0; return 1; } - hDC = GetDC(editor->hWnd); - hOldFont = ME_SelectStyleFont(editor, hDC, run->style); + hOldFont = ME_SelectStyleFont(c, run->style); - if (editor->cPasswordMask) + if (c->editor->cPasswordMask) { - ME_String *strMasked = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(run->strText)); - GetTextExtentExPointW(hDC, strMasked->szData, run->strText->nLen, + ME_String *strMasked = ME_MakeStringR(c->editor->cPasswordMask,ME_StrVLen(run->strText)); + GetTextExtentExPointW(c->hDC, strMasked->szData, run->strText->nLen, cx, &fit, NULL, &sz); ME_DestroyString(strMasked); } else { - GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen, + GetTextExtentExPointW(c->hDC, run->strText->szData, run->strText->nLen, cx, &fit, NULL, &sz); } - ME_UnselectStyleFont(editor, hDC, run->style, hOldFont); - ReleaseDC(editor->hWnd, hDC); + ME_UnselectStyleFont(c, run->style, hOldFont); + return fit; } @@ -548,8 +546,8 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) /* This could point to either the run's real text, or it's masked form in a password control */ int fit = 0, fit1 = 0; + ME_Context c; HGDIOBJ hOldFont; - HDC hDC; SIZE sz, sz2, sz3; if (!run->strText->nLen) return 0; @@ -574,17 +572,17 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) else strRunText = run->strText; - hDC = GetDC(editor->hWnd); - hOldFont = ME_SelectStyleFont(editor, hDC, run->style); - GetTextExtentExPointW(hDC, strRunText->szData, strRunText->nLen, - cx, &fit, NULL, &sz); + ME_InitContext(&c, editor, GetDC(editor->hWnd)); + hOldFont = ME_SelectStyleFont(&c, run->style); + GetTextExtentExPointW(c.hDC, strRunText->szData, strRunText->nLen, + cx, &fit, NULL, &sz); if (fit != strRunText->nLen) { int chars = 1; - GetTextExtentPoint32W(hDC, strRunText->szData, fit, &sz2); + GetTextExtentPoint32W(c.hDC, strRunText->szData, fit, &sz2); fit1 = ME_StrRelPos(strRunText, fit, &chars); - GetTextExtentPoint32W(hDC, strRunText->szData, fit1, &sz3); + GetTextExtentPoint32W(c.hDC, strRunText->szData, fit1, &sz3); if (cx >= (sz2.cx+sz3.cx)/2) fit = fit1; } @@ -592,11 +590,24 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) if (editor->cPasswordMask) ME_DestroyString(strRunText); - ME_UnselectStyleFont(editor, hDC, run->style, hOldFont); - ReleaseDC(editor->hWnd, hDC); + ME_UnselectStyleFont(&c, run->style, hOldFont); + ReleaseDC(editor->hWnd, c.hDC); return fit; } +/****************************************************************************** + * ME_GetTextExtent + * + * Finds a width and a height of the text using a specified style + */ +static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size) +{ + HGDIOBJ hOldFont; + hOldFont = ME_SelectStyleFont(c, s); + GetTextExtentPoint32W(c->hDC, szText, nChars, size); + ME_UnselectStyleFont(c, s, hOldFont); +} + /****************************************************************************** * ME_PointFromChar * @@ -606,8 +617,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset) { SIZE size; - HDC hDC = GetDC(editor->hWnd); - HGDIOBJ hOldFont; + ME_Context c; ME_String *strRunText; /* This could point to either the run's real text, or it's masked form in a password control */ @@ -623,29 +633,14 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset) else strRunText = pRun->strText; - hOldFont = ME_SelectStyleFont(editor, hDC, pRun->style); - GetTextExtentPoint32W(hDC, strRunText->szData, nOffset, &size); - ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont); - ReleaseDC(editor->hWnd, hDC); + ME_InitContext(&c, editor, GetDC(editor->hWnd)); + ME_GetTextExtent(&c, strRunText->szData, nOffset, pRun->style, &size); + ReleaseDC(editor->hWnd, c.hDC); if (editor->cPasswordMask) ME_DestroyString(strRunText); return size.cx; } -/****************************************************************************** - * ME_GetTextExtent - * - * Finds a width and a height of the text using a specified style - */ -static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size) -{ - HDC hDC = c->hDC; - HGDIOBJ hOldFont; - hOldFont = ME_SelectStyleFont(c->editor, hDC, s); - GetTextExtentPoint32W(hDC, szText, nChars, size); - ME_UnselectStyleFont(c->editor, hDC, s, hOldFont); -} - /****************************************************************************** * ME_GetRunSizeCommon * @@ -683,7 +678,7 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run if (run->nFlags & MERF_TAB) { int pos = 0, i = 0, ppos; - int lpsx = GetDeviceCaps(c->hDC, LOGPIXELSX); + PARAFORMAT2 *pFmt = para->pFmt; do { if (i < pFmt->cTabCount) @@ -695,7 +690,7 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run { pos += 720-(pos%720); } - ppos = pos*lpsx/1440; + ppos = ME_twips2pointsX(c, pos); if (ppos>run->pt.x) { size.cx = ppos - run->pt.x; break; @@ -714,9 +709,7 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run } if (run->nFlags & MERF_CELL) { - int lpsx = GetDeviceCaps(c->hDC, LOGPIXELSX); - - size.cx = run->pCell->nRightBoundary * lpsx / 1440 - run->pt.x; + size.cx = ME_twips2pointsX(c, run->pCell->nRightBoundary) - run->pt.x; return size; } return size; @@ -938,8 +931,8 @@ 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; - int nEffects = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE; + int nAttribs = CFM_SIZE | CFM_FACE | CFM_COLOR | CFM_UNDERLINETYPE; + int nEffects = CFM_BOLD | CFM_ITALIC; run = ME_FindItemFwd(run, diRun); @@ -957,11 +950,14 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p { if (!(tmp.dwMask & CFM_FACE)) pFmt->dwMask &= ~CFM_FACE; - else if (lstrcmpW(pFmt->szFaceName, tmp.szFaceName)) + else if (lstrcmpW(pFmt->szFaceName, tmp.szFaceName) || + pFmt->bPitchAndFamily != tmp.bPitchAndFamily) pFmt->dwMask &= ~CFM_FACE; } if (pFmt->yHeight != tmp.yHeight) pFmt->dwMask &= ~CFM_SIZE; + if (pFmt->bUnderlineType != tmp.bUnderlineType) + pFmt->dwMask &= ~CFM_UNDERLINETYPE; if (pFmt->dwMask & CFM_COLOR) { if (!((pFmt->dwEffects&CFE_AUTOCOLOR) & (tmp.dwEffects&CFE_AUTOCOLOR))) diff --git a/reactos/dll/win32/riched20/style.c b/reactos/dll/win32/riched20/style.c index 0530c42d7f2..ba7d6d321c7 100644 --- a/reactos/dll/win32/riched20/style.c +++ b/reactos/dll/win32/riched20/style.c @@ -25,12 +25,20 @@ 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]) + */ + CHARFORMAT2W *ME_ToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from) { if (from->cbSize == sizeof(CHARFORMATA)) { CHARFORMATA *f = (CHARFORMATA *)from; - CopyMemory(to, f, sizeof(*f)-sizeof(f->szFaceName)); + CopyMemory(to, f, FIELD_OFFSET(CHARFORMATA, szFaceName)); to->cbSize = sizeof(CHARFORMAT2W); if (f->dwMask & CFM_FACE) { MultiByteToWideChar(0, 0, f->szFaceName, -1, to->szFaceName, sizeof(to->szFaceName)/sizeof(WCHAR)); @@ -42,20 +50,20 @@ CHARFORMAT2W *ME_ToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from) CHARFORMATW *f = (CHARFORMATW *)from; CopyMemory(to, f, sizeof(*f)); /* theoretically, we don't need to zero the remaining memory */ - ZeroMemory(((CHARFORMATW *)to)+1, sizeof(CHARFORMAT2W)-sizeof(CHARFORMATW)); + ZeroMemory(&to->wWeight, sizeof(CHARFORMAT2W)-FIELD_OFFSET(CHARFORMAT2W, wWeight)); to->cbSize = sizeof(CHARFORMAT2W); return to; } if (from->cbSize == sizeof(CHARFORMAT2A)) { - CHARFORMATA *f = (CHARFORMATA *)from; + CHARFORMAT2A *f = (CHARFORMAT2A *)from; /* copy the A structure without face name */ - CopyMemory(to, f, sizeof(CHARFORMATA)-sizeof(f->szFaceName)); + CopyMemory(to, f, FIELD_OFFSET(CHARFORMATA, szFaceName)); /* convert face name */ if (f->dwMask & CFM_FACE) MultiByteToWideChar(0, 0, f->szFaceName, -1, to->szFaceName, sizeof(to->szFaceName)/sizeof(WCHAR)); /* copy the rest of the 2A structure to 2W */ - CopyMemory(1+((CHARFORMATW *)to), f+1, sizeof(CHARFORMAT2A)-sizeof(CHARFORMATA)); + CopyMemory(&to->wWeight, &f->wWeight, sizeof(CHARFORMAT2A)-FIELD_OFFSET(CHARFORMAT2A, wWeight)); to->cbSize = sizeof(CHARFORMAT2W); return to; } @@ -75,8 +83,22 @@ CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from) if (to->cbSize == sizeof(CHARFORMATA)) { CHARFORMATA *t = (CHARFORMATA *)to; - CopyMemory(t, from, sizeof(*t)-sizeof(t->szFaceName)); + CopyMemory(t, from, FIELD_OFFSET(CHARFORMATA, szFaceName)); WideCharToMultiByte(0, 0, from->szFaceName, -1, t->szFaceName, sizeof(t->szFaceName), 0, 0); + if (from->dwMask & CFM_UNDERLINETYPE) + { + switch (from->bUnderlineType) + { + case CFU_CF1UNDERLINE: + to->dwMask |= CFM_UNDERLINE; + to->dwEffects |= CFE_UNDERLINE; + break; + case CFU_UNDERLINENONE: + to->dwMask |= CFM_UNDERLINE; + to->dwEffects &= ~CFE_UNDERLINE; + break; + } + } t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */ return to; } @@ -84,6 +106,20 @@ CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from) { CHARFORMATW *t = (CHARFORMATW *)to; CopyMemory(t, from, sizeof(*t)); + if (from->dwMask & CFM_UNDERLINETYPE) + { + switch (from->bUnderlineType) + { + case CFU_CF1UNDERLINE: + to->dwMask |= CFM_UNDERLINE; + to->dwEffects |= CFE_UNDERLINE; + break; + case CFU_UNDERLINENONE: + to->dwMask |= CFM_UNDERLINE; + to->dwEffects &= ~CFE_UNDERLINE; + break; + } + } t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */ return to; } @@ -91,15 +127,15 @@ CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from) { CHARFORMAT2A *t = (CHARFORMAT2A *)to; /* copy the A structure without face name */ - CopyMemory(t, from, sizeof(CHARFORMATA)-sizeof(t->szFaceName)); + CopyMemory(t, from, FIELD_OFFSET(CHARFORMATA, szFaceName)); /* convert face name */ WideCharToMultiByte(0, 0, from->szFaceName, -1, t->szFaceName, sizeof(t->szFaceName), 0, 0); /* copy the rest of the 2A structure to 2W */ - CopyMemory(&t->wWeight, &from->wWeight, sizeof(CHARFORMAT2A)-sizeof(CHARFORMATA)); + CopyMemory(&t->wWeight, &from->wWeight, sizeof(CHARFORMAT2W)-FIELD_OFFSET(CHARFORMAT2W,wWeight)); t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */ return to; } - assert(to->cbSize >= sizeof(CHARFORMAT2W)); + assert(to->cbSize >= sizeof(CHARFORMAT2W)); return from; } @@ -166,7 +202,9 @@ ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style) COPY_STYLE_ITEM(CFM_STYLE, sStyle); COPY_STYLE_ITEM(CFM_UNDERLINETYPE, bUnderlineType); 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); + s->fmt.dwEffects &= ~(style->dwMask); s->fmt.dwEffects |= style->dwEffects & style->dwMask; s->fmt.dwMask |= style->dwMask; @@ -177,6 +215,13 @@ ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style) else s->fmt.dwEffects &= ~CFE_AUTOCOLOR; } + if (style->dwMask & CFM_UNDERLINE) + { + s->fmt.dwMask |= CFM_UNDERLINETYPE; + s->fmt.dwMask &= ~CFM_UNDERLINE; + s->fmt.bUnderlineType = (style->dwEffects & CFM_UNDERLINE) ? + CFU_CF1UNDERLINE : CFU_UNDERLINENONE; + } return s; } @@ -252,37 +297,33 @@ void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048]) static void -ME_LogFontFromStyle(HDC hDC, LOGFONTW *lf, const ME_Style *s, int nZoomNumerator, int nZoomDenominator) +ME_LogFontFromStyle(ME_Context* c, LOGFONTW *lf, const ME_Style *s) { - int rx, ry; - rx = GetDeviceCaps(hDC, LOGPIXELSX); - ry = GetDeviceCaps(hDC, LOGPIXELSY); ZeroMemory(lf, sizeof(LOGFONTW)); lstrcpyW(lf->lfFaceName, s->fmt.szFaceName); - if (nZoomNumerator == 0) - { - nZoomNumerator = 1; - nZoomDenominator = 1; - } - lf->lfHeight = -s->fmt.yHeight*ry*nZoomNumerator/nZoomDenominator/1440; + lf->lfHeight = ME_twips2pointsY(c, -s->fmt.yHeight); lf->lfWeight = 400; if (s->fmt.dwEffects & s->fmt.dwMask & CFM_BOLD) lf->lfWeight = 700; - if (s->fmt.dwEffects & s->fmt.dwMask & CFM_WEIGHT) + 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 | CFE_LINK)) lf->lfUnderline = 1; + if (s->fmt.dwMask & CFM_UNDERLINETYPE && 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; */ - lf->lfPitchAndFamily = s->fmt.bPitchAndFamily; - lf->lfCharSet = s->fmt.bCharSet; + 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) @@ -316,22 +357,22 @@ static BOOL ME_IsFontEqual(const LOGFONTW *p1, const LOGFONTW *p2) return TRUE; } -HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s) +HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s) { HFONT hOldFont; LOGFONTW lf; int i, nEmpty, nAge = 0x7FFFFFFF; ME_FontCacheItem *item; - assert(hDC); + assert(c->hDC); assert(s); - ME_LogFontFromStyle(hDC, &lf, s, editor->nZoomNumerator, editor->nZoomDenominator); + ME_LogFontFromStyle(c, &lf, s); for (i=0; ipFontCache[i].nAge++; + c->editor->pFontCache[i].nAge++; for (i=0, nEmpty=-1, nAge=0; ipFontCache[i]; + item = &c->editor->pFontCache[i]; if (!item->nRefs) { if (item->nAge > nAge) @@ -342,7 +383,7 @@ HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s) } if (i < HFONT_CACHE_SIZE) /* found */ { - item = &editor->pFontCache[i]; + item = &c->editor->pFontCache[i]; TRACE_(richedit_style)("font reused %d\n", i); s->hFont = item->hFont; @@ -350,7 +391,7 @@ HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s) } else { - item = &editor->pFontCache[nEmpty]; /* this legal even when nEmpty == -1, as we don't dereference it */ + item = &c->editor->pFontCache[nEmpty]; /* this legal even when nEmpty == -1, as we don't dereference it */ assert(nEmpty != -1); /* otherwise we leak cache entries or get too many fonts at once*/ if (item->hFont) { @@ -365,22 +406,22 @@ HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s) item->nRefs = 1; memcpy(&item->lfSpecs, &lf, sizeof(LOGFONTW)); } - hOldFont = SelectObject(hDC, s->hFont); + hOldFont = SelectObject(c->hDC, s->hFont); /* should be cached too, maybe ? */ - GetTextMetricsW(hDC, &s->tm); + GetTextMetricsW(c->hDC, &s->tm); return hOldFont; } -void ME_UnselectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s, HFONT hOldFont) +void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, HFONT hOldFont) { int i; - assert(hDC); + assert(c->hDC); assert(s); - SelectObject(hDC, hOldFont); + SelectObject(c->hDC, hOldFont); for (i=0; ipFontCache[i]; + ME_FontCacheItem *pItem = &c->editor->pFontCache[i]; if (pItem->hFont == s->hFont && pItem->nRefs > 0) { pItem->nRefs--; diff --git a/reactos/dll/win32/riched20/version.rc b/reactos/dll/win32/riched20/version.rc index 73bae3dc292..ff2a2baa0dd 100644 --- a/reactos/dll/win32/riched20/version.rc +++ b/reactos/dll/win32/riched20/version.rc @@ -24,3 +24,7 @@ #define WINE_PRODUCTVERSION_STR "5,30,23,1215" #include "wine/wine_common_ver.rc" + +#include "res.h" + +OCR_REVERSE CURSOR ocr_reverse.cur diff --git a/reactos/dll/win32/riched20/wrap.c b/reactos/dll/win32/riched20/wrap.c index 946aa730e43..4daf58efc95 100644 --- a/reactos/dll/win32/riched20/wrap.c +++ b/reactos/dll/win32/riched20/wrap.c @@ -32,7 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); * - no tabs */ -ME_DisplayItem *ME_MakeRow(int height, int baseline, int width) +static ME_DisplayItem *ME_MakeRow(int height, int baseline, int width) { ME_DisplayItem *item = ME_MakeDI(diStartRow); @@ -51,7 +51,7 @@ static void ME_BeginRow(ME_WrapContext *wc) wc->pt.x = 0; } -void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) +static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) { ME_DisplayItem *p, *row, *para; int ascent = 0, descent = 0, width=0, shift = 0, align = 0; @@ -168,7 +168,7 @@ static ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem int i, idesp, len; ME_Run *run = &p->member.run; - idesp = i = ME_CharFromPoint(wc->context->editor, loc, run); + idesp = i = ME_CharFromPoint(wc->context, loc, run); len = ME_StrVLen(run->strText); assert(len>0); assert(inext; } -void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { +static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp); + +static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD beginofs) { ME_DisplayItem *p; ME_WrapContext wc; - int dpi = GetDeviceCaps(c->hDC, LOGPIXELSX); + int border = 0; + int linespace = 0; assert(tp->type == diParagraph); if (!(tp->member.para.nFlags & MEPF_REWRAP)) { @@ -350,36 +353,56 @@ void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { wc.context = c; /* wc.para_style = tp->member.para.style; */ wc.style = NULL; - tp->member.para.nRightMargin = tp->member.para.pFmt->dxRightIndent*dpi/1440; - tp->member.para.nFirstMargin = tp->member.para.pFmt->dxStartIndent*dpi/1440; - tp->member.para.nLeftMargin = (tp->member.para.pFmt->dxStartIndent+tp->member.para.pFmt->dxOffset)*dpi/1440; - wc.nFirstMargin = tp->member.para.nFirstMargin; - wc.nLeftMargin = tp->member.para.nLeftMargin; - wc.nRightMargin = tp->member.para.nRightMargin; + wc.nFirstMargin = ME_twips2pointsX(c, tp->member.para.pFmt->dxStartIndent) + beginofs; + wc.nLeftMargin = wc.nFirstMargin + ME_twips2pointsX(c, tp->member.para.pFmt->dxOffset) + beginofs; + wc.nRightMargin = ME_twips2pointsX(c, tp->member.para.pFmt->dxRightIndent); wc.nRow = 0; wc.pt.x = 0; wc.pt.y = 0; + if (tp->member.para.pFmt->dwMask & PFM_SPACEBEFORE) + wc.pt.y += ME_twips2pointsY(c, tp->member.para.pFmt->dySpaceBefore); + if (tp->member.para.pFmt->dwMask & PFM_BORDER) + { + border = ME_GetParaBorderWidth(c->editor, tp->member.para.pFmt->wBorders); + if (tp->member.para.pFmt->wBorders & 1) { + wc.nFirstMargin += border; + wc.nLeftMargin += border; + } + if (tp->member.para.pFmt->wBorders & 2) + wc.nRightMargin -= border; + if (tp->member.para.pFmt->wBorders & 4) + wc.pt.y += border; + } + wc.nTotalWidth = c->rcView.right - c->rcView.left; wc.nAvailWidth = wc.nTotalWidth - wc.nFirstMargin - wc.nRightMargin; wc.pRowStart = NULL; + linespace = ME_GetParaLineSpace(c, &tp->member.para); + ME_BeginRow(&wc); for (p = tp->next; p!=tp->member.para.next_para; ) { assert(p->type != diStartRow); if (p->type == diRun) { p = ME_WrapHandleRun(&wc, p); - continue; } - p = p->next; + else p = p->next; + if (wc.nRow && p == wc.pRowStart) + wc.pt.y += linespace; } ME_WrapEndParagraph(&wc, p); + if ((tp->member.para.pFmt->dwMask & PFM_BORDER) && (tp->member.para.pFmt->wBorders & 8)) + wc.pt.y += border; + if (tp->member.para.pFmt->dwMask & PFM_SPACEAFTER) + wc.pt.y += ME_twips2pointsY(c, tp->member.para.pFmt->dySpaceAfter); + tp->member.para.nFlags &= ~MEPF_REWRAP; tp->member.para.nHeight = wc.pt.y; tp->member.para.nRows = wc.nRow; } -void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) { +static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) { ME_DisplayItem *p, *pRow; /* remove all items that will be reinserted by paragraph wrapper anyway */ @@ -441,7 +464,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { bRedraw = TRUE; item->member.para.nYPos = c.pt.y; - ME_WrapTextParagraph(&c, item); + ME_WrapTextParagraph(&c, item, editor->selofs); if (bRedraw) { @@ -519,9 +542,11 @@ ME_SendRequestResize(ME_TextEditor *editor, BOOL force) info.nmhdr.code = EN_REQUESTRESIZE; info.rc = rc; info.rc.bottom = editor->nTotalLength; - + + editor->nEventMask &= ~ENM_REQUESTRESIZE; SendMessageW(GetParent(editor->hWnd), WM_NOTIFY, info.nmhdr.idFrom, (LPARAM)&info); + editor->nEventMask |= ENM_REQUESTRESIZE; } } }