diff --git a/reactos/dll/win32/riched20/editor.c b/reactos/dll/win32/riched20/editor.c index 253c7b8b93f..d92397e5258 100644 --- a/reactos/dll/win32/riched20/editor.c +++ b/reactos/dll/win32/riched20/editor.c @@ -101,6 +101,7 @@ - EM_SETIMEOPTIONS 1.0asian - EM_SETLANGOPTIONS 2.0 - EM_SETLIMITTEXT + - EM_SETMARGINS + EM_SETMODIFY (not sure if implementation is correct) - EM_SETOLECALLBACK + EM_SETOPTIONS (partially implemented) @@ -1937,6 +1938,93 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH return -1; } +typedef struct tagME_GlobalDestStruct +{ + HGLOBAL hData; + int nLength; +} ME_GlobalDestStruct; + +static DWORD CALLBACK ME_ReadFromHGLOBALUnicode(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb) +{ + ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie; + int i; + WORD *pSrc, *pDest; + + cb = cb >> 1; + pDest = (WORD *)lpBuff; + pSrc = (WORD *)GlobalLock(pData->hData); + for (i = 0; inLength+i]; i++) { + pDest[i] = pSrc[pData->nLength+i]; + } + pData->nLength += i; + *pcb = 2*i; + GlobalUnlock(pData->hData); + return 0; +} + +static DWORD CALLBACK ME_ReadFromHGLOBALRTF(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb) +{ + ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie; + int i; + BYTE *pSrc, *pDest; + + pDest = lpBuff; + pSrc = (BYTE *)GlobalLock(pData->hData); + for (i = 0; inLength+i]; i++) { + pDest[i] = pSrc[pData->nLength+i]; + } + pData->nLength += i; + *pcb = i; + GlobalUnlock(pData->hData); + return 0; +} + +static BOOL ME_Paste(ME_TextEditor *editor) +{ + DWORD dwFormat = 0; + EDITSTREAM es; + ME_GlobalDestStruct gds; + UINT nRTFFormat = RegisterClipboardFormatA("Rich Text Format"); + UINT cf = 0; + + if (IsClipboardFormatAvailable(nRTFFormat)) + cf = nRTFFormat, dwFormat = SF_RTF; + else if (IsClipboardFormatAvailable(CF_UNICODETEXT)) + cf = CF_UNICODETEXT, dwFormat = SF_TEXT|SF_UNICODE; + else + return FALSE; + + if (!OpenClipboard(editor->hWnd)) + return FALSE; + gds.hData = GetClipboardData(cf); + gds.nLength = 0; + es.dwCookie = (DWORD)&gds; + es.pfnCallback = dwFormat == SF_RTF ? ME_ReadFromHGLOBALRTF : ME_ReadFromHGLOBALUnicode; + ME_StreamIn(editor, dwFormat|SFF_SELECTION, &es, FALSE); + + CloseClipboard(); + return TRUE; +} + +static BOOL ME_Copy(ME_TextEditor *editor, CHARRANGE *range) +{ + LPDATAOBJECT dataObj = NULL; + HRESULT hr = S_OK; + + if (editor->cPasswordMask) + return FALSE; /* Copying or Cutting masked text isn't allowed */ + + if(editor->lpOleCallback) + hr = IRichEditOleCallback_GetClipboardData(editor->lpOleCallback, range, RECO_COPY, &dataObj); + if(FAILED(hr) || !dataObj) + hr = ME_GetDataObject(editor, range, &dataObj); + if(SUCCEEDED(hr)) { + hr = OleSetClipboard(dataObj); + IDataObject_Release(dataObj); + } + return SUCCEEDED(hr) != 0; +} + /* helper to send a msg filter notification */ static BOOL ME_FilterEvent(ME_TextEditor *editor, UINT msg, WPARAM* wParam, LPARAM* lParam) @@ -2022,6 +2110,49 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) ME_UpdateRepaint(editor); ME_SendRequestResize(editor, FALSE); return TRUE; + case 'A': + if (ctrl_is_down) + { + ME_SetSelection(editor, 0, -1); + return TRUE; + } + break; + case 'V': + if (ctrl_is_down) + return ME_Paste(editor); + break; + case 'C': + case 'X': + if (ctrl_is_down) + { + CHARRANGE range; + BOOL result; + + ME_GetSelection(editor, &range.cpMin, &range.cpMax); + result = ME_Copy(editor, &range); + if (result && nKey == 'X') + { + ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE); + ME_CommitUndo(editor); + ME_UpdateRepaint(editor); + } + return result; + } + break; + case 'Z': + if (ctrl_is_down) + { + ME_Undo(editor); + return TRUE; + } + break; + case 'Y': + if (ctrl_is_down) + { + ME_Redo(editor); + return TRUE; + } + break; default: if (nKey != VK_SHIFT && nKey != VK_CONTROL && nKey && nKey != VK_MENU) @@ -2103,10 +2234,29 @@ static BOOL ME_SetCursor(ME_TextEditor *editor) POINT pt; BOOL isExact; int offset; + SCROLLBARINFO sbi; DWORD messagePos = GetMessagePos(); pt.x = (short)LOWORD(messagePos); pt.y = (short)HIWORD(messagePos); + + sbi.cbSize = sizeof(sbi); + GetScrollBarInfo(editor->hWnd, OBJID_HSCROLL, &sbi); + if (!(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)) && + PtInRect(&sbi.rcScrollBar, pt)) + { + SetCursor(LoadCursorW(NULL, (WCHAR*)IDC_ARROW)); + return TRUE; + } + sbi.cbSize = sizeof(sbi); + GetScrollBarInfo(editor->hWnd, OBJID_VSCROLL, &sbi); + if (!(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)) && + PtInRect(&sbi.rcScrollBar, pt)) + { + SetCursor(LoadCursorW(NULL, (WCHAR*)IDC_ARROW)); + return TRUE; + } ScreenToClient(editor->hWnd, &pt); + if ((GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_SELECTIONBAR) && (pt.x < editor->selofs || (editor->nSelectionType == stLine && GetCapture() == editor->hWnd))) @@ -2209,8 +2359,7 @@ 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->bRedraw = TRUE; - ed->bWordWrap = (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL) ? FALSE : TRUE; + ed->bWordWrap = (GetWindowLongW(hWnd, GWL_STYLE) & (WS_HSCROLL|ES_AUTOHSCROLL)) ? FALSE : TRUE; ed->bHideSelection = FALSE; ed->nInvalidOfs = -1; ed->pfnWordBreak = NULL; @@ -2251,48 +2400,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) { return ed; } -typedef struct tagME_GlobalDestStruct -{ - HGLOBAL hData; - int nLength; -} ME_GlobalDestStruct; - -static DWORD CALLBACK ME_ReadFromHGLOBALUnicode(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb) -{ - ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie; - int i; - WORD *pSrc, *pDest; - - cb = cb >> 1; - pDest = (WORD *)lpBuff; - pSrc = (WORD *)GlobalLock(pData->hData); - for (i = 0; inLength+i]; i++) { - pDest[i] = pSrc[pData->nLength+i]; - } - pData->nLength += i; - *pcb = 2*i; - GlobalUnlock(pData->hData); - return 0; -} - -static DWORD CALLBACK ME_ReadFromHGLOBALRTF(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, LONG *pcb) -{ - ME_GlobalDestStruct *pData = (ME_GlobalDestStruct *)dwCookie; - int i; - BYTE *pSrc, *pDest; - - pDest = lpBuff; - pSrc = (BYTE *)GlobalLock(pData->hData); - for (i = 0; inLength+i]; i++) { - pDest[i] = pSrc[pData->nLength+i]; - } - pData->nLength += i; - *pcb = i; - GlobalUnlock(pData->hData); - return 0; -} - - void ME_DestroyEditor(ME_TextEditor *editor) { ME_DisplayItem *pFirst = editor->pBuffer->pFirst; @@ -2530,6 +2637,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, UNSUPPORTED_MSG(EM_SETEDITSTYLE) UNSUPPORTED_MSG(EM_SETFONTSIZE) UNSUPPORTED_MSG(EM_SETLANGOPTIONS) + UNSUPPORTED_MSG(EM_SETMARGINS) UNSUPPORTED_MSG(EM_SETPALETTE) UNSUPPORTED_MSG(EM_SETTABSTOPS) UNSUPPORTED_MSG(EM_SETTYPOGRAPHYOPTIONS) @@ -2741,8 +2849,9 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ME_GetSelection(editor, &from, &to); style = ME_GetSelectionInsertStyle(editor); ME_InternalDeleteText(editor, from, to - from, FALSE); - if (pStruct->codepage != 1200 && lParam && !strncmp((char *)lParam, "{\\rtf", 5)) - ME_StreamInRTFString(editor, 1, (char *)lParam); + if (pStruct->codepage != 1200 && lParam && + (!strncmp((char *)lParam, "{\\rtf", 5) || !strncmp((char *)lParam, "{\\urtf}", 6))) + ME_StreamInRTFString(editor, 1, (char *)lParam); else ME_InsertTextFromCursor(editor, 0, wszText, len, style); ME_ReleaseStyle(style); @@ -2750,8 +2859,9 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, } else { ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); - if (pStruct->codepage != 1200 && lParam && !strncmp((char *)lParam, "{\\rtf", 5)) - ME_StreamInRTFString(editor, 0, (char *)lParam); + if (pStruct->codepage != 1200 && lParam && + (!strncmp((char *)lParam, "{\\rtf", 5) || !strncmp((char *)lParam, "{\\urtf}", 6))) + ME_StreamInRTFString(editor, 0, (char *)lParam); else ME_InsertTextFromCursor(editor, 0, wszText, len, editor->pBuffer->pDefaultStyle); len = 1; @@ -2785,11 +2895,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, editor->rgbBackColor = lParam; editor->hbrBackground = CreateSolidBrush(editor->rgbBackColor); } - if (editor->bRedraw) - { - InvalidateRect(hWnd, NULL, TRUE); - UpdateWindow(hWnd); - } + InvalidateRect(hWnd, NULL, TRUE); + UpdateWindow(hWnd); return lColor; } case EM_GETMODIFY: @@ -3047,51 +3154,15 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, return FALSE; } case WM_PASTE: - { - DWORD dwFormat = 0; - EDITSTREAM es; - ME_GlobalDestStruct gds; - UINT nRTFFormat = RegisterClipboardFormatA("Rich Text Format"); - UINT cf = 0; - - if (IsClipboardFormatAvailable(nRTFFormat)) - cf = nRTFFormat, dwFormat = SF_RTF; - else if (IsClipboardFormatAvailable(CF_UNICODETEXT)) - cf = CF_UNICODETEXT, dwFormat = SF_TEXT|SF_UNICODE; - else - return 0; - - if (!OpenClipboard(hWnd)) - return 0; - gds.hData = GetClipboardData(cf); - gds.nLength = 0; - es.dwCookie = (DWORD)&gds; - es.pfnCallback = dwFormat == SF_RTF ? ME_ReadFromHGLOBALRTF : ME_ReadFromHGLOBALUnicode; - ME_StreamIn(editor, dwFormat|SFF_SELECTION, &es, FALSE); - - CloseClipboard(); + ME_Paste(editor); return 0; - } case WM_CUT: case WM_COPY: { - LPDATAOBJECT dataObj = NULL; CHARRANGE range; - HRESULT hr = S_OK; - - if (editor->cPasswordMask) - return 0; /* Copying or Cutting masked text isn't allowed */ - ME_GetSelection(editor, &range.cpMin, &range.cpMax); - if(editor->lpOleCallback) - hr = IRichEditOleCallback_GetClipboardData(editor->lpOleCallback, &range, RECO_COPY, &dataObj); - if(FAILED(hr) || !dataObj) - hr = ME_GetDataObject(editor, &range, &dataObj); - if(SUCCEEDED(hr)) { - hr = OleSetClipboard(dataObj); - IDataObject_Release(dataObj); - } - if (SUCCEEDED(hr) && msg == WM_CUT) + + if (ME_Copy(editor, &range) && msg == WM_CUT) { ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE); ME_CommitUndo(editor); @@ -3472,18 +3543,15 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, if (wParam >= 0x40000) nCharOfs = lParam; nLength = ME_GetTextLength(editor); - - if (nCharOfs < nLength) { - ME_RunOfsFromCharOfs(editor, nCharOfs, &pRun, &nOffset); - assert(pRun->type == diRun); - pt.y = pRun->member.run.pt.y; - pt.x = pRun->member.run.pt.x + ME_PointFromChar(editor, &pRun->member.run, nOffset); - pt.y += ME_GetParagraph(pRun)->member.para.pt.y; - } else { - pt.x = 0; - pt.y = editor->pBuffer->pLast->member.para.pt.y; - } + nCharOfs = min(nCharOfs, nLength); + + ME_RunOfsFromCharOfs(editor, nCharOfs, &pRun, &nOffset); + assert(pRun->type == diRun); + pt.y = pRun->member.run.pt.y; + pt.x = pRun->member.run.pt.x + ME_PointFromChar(editor, &pRun->member.run, nOffset); + pt.y += ME_GetParagraph(pRun)->member.para.pt.y; pt.x += editor->selofs; + pt.x++; /* for some reason native offsets x by one */ si.cbSize = sizeof(si); si.fMask = SIF_POS; @@ -3581,7 +3649,6 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, goto do_default; break; case WM_PAINT: - if (editor->bRedraw) { HDC hDC; PAINTSTRUCT ps; @@ -3604,14 +3671,11 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, return 0; case WM_ERASEBKGND: { - if (editor->bRedraw) + HDC hDC = (HDC)wParam; + RECT rc; + if (GetUpdateRect(hWnd,&rc,TRUE)) { - HDC hDC = (HDC)wParam; - RECT rc; - if (GetUpdateRect(hWnd,&rc,TRUE)) - { - FillRect(hDC, &rc, editor->hbrBackground); - } + FillRect(hDC, &rc, editor->hbrBackground); } return 1; } @@ -3642,36 +3706,11 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, MultiByteToWideChar(CP_ACP, 0, &charA, 1, &wstr, 1); } - switch (wstr) - { - case 1: /* Ctrl-A */ - ME_SetSelection(editor, 0, -1); - return 0; - case 3: /* Ctrl-C */ - SendMessageW(editor->hWnd, WM_COPY, 0, 0); - return 0; - } - if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_READONLY) { MessageBeep(MB_ICONERROR); return 0; /* FIXME really 0 ? */ } - switch (wstr) - { - case 22: /* Ctrl-V */ - SendMessageW(editor->hWnd, WM_PASTE, 0, 0); - return 0; - case 24: /* Ctrl-X */ - SendMessageW(editor->hWnd, WM_CUT, 0, 0); - return 0; - case 25: /* Ctrl-Y */ - SendMessageW(editor->hWnd, EM_REDO, 0, 0); - return 0; - case 26: /* Ctrl-Z */ - SendMessageW(editor->hWnd, EM_UNDO, 0, 0); - return 0; - } if (((unsigned)wstr)>=' ' || (wstr=='\r' && (GetWindowLongW(hWnd, GWL_STYLE) & ES_MULTILINE)) || wstr=='\t') { @@ -3930,9 +3969,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ME_SendRequestResize(editor, TRUE); return 0; case WM_SETREDRAW: - if ((editor->bRedraw = wParam)) - ME_RewrapRepaint(editor); - return 0; + return DefWindowProcW(hWnd, msg, wParam, lParam); case WM_SIZE: { GetClientRect(hWnd, &editor->rcFormat); diff --git a/reactos/dll/win32/riched20/editstr.h b/reactos/dll/win32/riched20/editstr.h index edbeb131834..248cc02be29 100644 --- a/reactos/dll/win32/riched20/editstr.h +++ b/reactos/dll/win32/riched20/editstr.h @@ -351,7 +351,6 @@ typedef struct tagME_TextEditor ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE]; int nZoomNumerator, nZoomDenominator; RECT rcFormat; - BOOL bRedraw; BOOL bWordWrap; int nInvalidOfs; int nTextLimit; @@ -401,7 +400,7 @@ typedef struct tagME_WrapContext int nAvailWidth; int nRow; POINT pt; - BOOL bOverflown; + BOOL bOverflown, bWordWrap; ME_DisplayItem *pRowStart; ME_DisplayItem *pLastSplittableRun; diff --git a/reactos/dll/win32/riched20/paint.c b/reactos/dll/win32/riched20/paint.c index eba37efa757..40761db64b0 100644 --- a/reactos/dll/win32/riched20/paint.c +++ b/reactos/dll/win32/riched20/paint.c @@ -147,6 +147,8 @@ void ME_Repaint(ME_TextEditor *editor) ME_UpdateScrollBar(editor); FIXME("ME_Repaint had to call ME_WrapMarkedParagraphs\n"); } + if (!IsWindowVisible(editor->hWnd)) + return; if (!editor->bEmulateVersion10 || (editor->nEventMask & ENM_UPDATE)) ME_SendOldNotify(editor, EN_UPDATE); UpdateWindow(editor->hWnd); @@ -159,7 +161,6 @@ void ME_UpdateRepaint(ME_TextEditor *editor) BOOL wrappedParagraphs; wrappedParagraphs = ME_WrapMarkedParagraphs(editor); - if (!editor->bRedraw) return; if (wrappedParagraphs) ME_UpdateScrollBar(editor); @@ -185,12 +186,9 @@ ME_RewrapRepaint(ME_TextEditor *editor) * looks, but not content. Like resizing. */ ME_MarkAllForWrapping(editor); - if (editor->bRedraw) - { - ME_WrapMarkedParagraphs(editor); - ME_UpdateScrollBar(editor); - ME_Repaint(editor); - } + ME_WrapMarkedParagraphs(editor); + ME_UpdateScrollBar(editor); + ME_Repaint(editor); } int ME_twips2pointsX(ME_Context *c, int x) @@ -1074,17 +1072,14 @@ void ME_Scroll(ME_TextEditor *editor, int value, int type) si.nPos = 0; } - nNewPos = SetScrollInfo(editor->hWnd, SB_VERT, &si, editor->bRedraw); + nNewPos = SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE); editor->vert_si.nPos = nNewPos; nActualScroll = nOrigPos - nNewPos; - if (editor->bRedraw) - { - if (abs(nActualScroll) > editor->sizeWindow.cy) - InvalidateRect(editor->hWnd, NULL, TRUE); - else - ScrollWindowEx(editor->hWnd, 0, nActualScroll, NULL, NULL, NULL, NULL, SW_INVALIDATE); - ME_Repaint(editor); - } + if (abs(nActualScroll) > editor->sizeWindow.cy) + InvalidateRect(editor->hWnd, NULL, TRUE); + else + ScrollWindowEx(editor->hWnd, 0, nActualScroll, NULL, NULL, NULL, NULL, SW_INVALIDATE); + ME_Repaint(editor); hWnd = editor->hWnd; winStyle = GetWindowLongW(hWnd, GWL_STYLE); @@ -1099,7 +1094,7 @@ void ME_Scroll(ME_TextEditor *editor, int value, int type) } - void ME_UpdateScrollBar(ME_TextEditor *editor) +void ME_UpdateScrollBar(ME_TextEditor *editor) { /* Note that this is the only function that should ever call SetScrolLInfo * with SIF_PAGE or SIF_RANGE. SetScrollPos and SetScrollRange should never diff --git a/reactos/dll/win32/riched20/para.c b/reactos/dll/win32/riched20/para.c index 517bf28c417..565e323422d 100644 --- a/reactos/dll/win32/riched20/para.c +++ b/reactos/dll/win32/riched20/para.c @@ -287,6 +287,7 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, { ME_AddUndoItem(editor, diUndoSetParagraphFormat, tp); *tp->member.para.pFmt = *pNext->member.para.pFmt; + tp->member.para.border = pNext->member.para.border; } if (!editor->bEmulateVersion10) { /* v4.1 */ diff --git a/reactos/dll/win32/riched20/reader.c b/reactos/dll/win32/riched20/reader.c index 3d5593a5771..ced4f7f285e 100644 --- a/reactos/dll/win32/riched20/reader.c +++ b/reactos/dll/win32/riched20/reader.c @@ -109,7 +109,7 @@ int _RTFGetChar(RTF_Info *info) if (stream->dwSize == 0) return EOF; } - ch = stream->buffer[stream->dwUsed++]; + ch = (unsigned char)stream->buffer[stream->dwUsed++]; if (!ch) return EOF; return ch; diff --git a/reactos/dll/win32/riched20/string.c b/reactos/dll/win32/riched20/string.c index 97b5a676684..7da521cdf4c 100644 --- a/reactos/dll/win32/riched20/string.c +++ b/reactos/dll/win32/riched20/string.c @@ -304,6 +304,8 @@ ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code) /* FIXME: Native also knows about punctuation */ TRACE("s==%s, start==%d, len==%d, code==%d\n", debugstr_wn(s, len), start, len, code); + /* convert number of bytes to number of characters. */ + len /= sizeof(WCHAR); switch (code) { case WB_ISDELIMITER: @@ -330,11 +332,23 @@ ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code) int ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code) { - /* FIXME: ANSIfy the string when bEmulateVersion10 is TRUE */ - if (!editor->pfnWordBreak) - return ME_WordBreakProc(str->szData, start, str->nLen, code); - else - return editor->pfnWordBreak(str->szData, start, str->nLen, code); + if (!editor->pfnWordBreak) { + return ME_WordBreakProc(str->szData, start, str->nLen*sizeof(WCHAR), code); + } else if (!editor->bEmulateVersion10) { + /* MSDN lied about the third parameter for EditWordBreakProc being the number + * of characters, it is actually the number of bytes of the string. */ + return editor->pfnWordBreak(str->szData, start, str->nLen*sizeof(WCHAR), code); + } else { + int result; + int buffer_size = WideCharToMultiByte(CP_ACP, 0, str->szData, str->nLen, + NULL, 0, NULL, NULL); + char *buffer = (char*)heap_alloc(buffer_size); + WideCharToMultiByte(CP_ACP, 0, str->szData, str->nLen, + buffer, buffer_size, NULL, NULL); + result = editor->pfnWordBreak(str->szData, start, str->nLen, code); + heap_free(buffer); + return result; + } } LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz) diff --git a/reactos/dll/win32/riched20/table.c b/reactos/dll/win32/riched20/table.c index c4de61d7a30..3581306547a 100644 --- a/reactos/dll/win32/riched20/table.c +++ b/reactos/dll/win32/riched20/table.c @@ -392,9 +392,10 @@ ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, assert(table_row); assert(table_row->type == diParagraph); if (!editor->bEmulateVersion10) { /* v4.1 */ - ME_DisplayItem *insertedCell, *para, *cell; + ME_DisplayItem *insertedCell, *para, *cell, *prevTableEnd; cell = ME_FindItemFwd(ME_GetTableRowStart(table_row), diCell); - run = ME_GetTableRowEnd(table_row)->member.para.next_para; + prevTableEnd = ME_GetTableRowEnd(table_row); + run = prevTableEnd->member.para.next_para; run = ME_FindItemFwd(run, diRun); editor->pCursors[0].pRun = run; editor->pCursors[0].nOffset = 0; @@ -412,7 +413,8 @@ ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, insertedCell->member.cell.nRightBoundary = cell->member.cell.nRightBoundary; insertedCell->member.cell.border = cell->member.cell.border; }; - ME_InsertTableRowEndFromCursor(editor); + para = ME_InsertTableRowEndFromCursor(editor); + *para->member.para.pFmt = *prevTableEnd->member.para.pFmt; /* return the table row start for the inserted paragraph */ return ME_FindItemFwd(cell, diParagraph)->member.para.next_para; } else { /* v1.0 - 3.0 */ diff --git a/reactos/dll/win32/riched20/txtsrv.c b/reactos/dll/win32/riched20/txtsrv.c index 95d6f7cb496..d4679f78313 100644 --- a/reactos/dll/win32/riched20/txtsrv.c +++ b/reactos/dll/win32/riched20/txtsrv.c @@ -57,6 +57,7 @@ typedef struct ITextServicesImpl { ITextHost *pMyHost; LONG ref; CRITICAL_SECTION csTxtSrv; + char spare[256]; } ITextServicesImpl; static const ITextServicesVtbl textservices_Vtbl; diff --git a/reactos/dll/win32/riched20/undo.c b/reactos/dll/win32/riched20/undo.c index 8f3a22bdace..49802a357d4 100644 --- a/reactos/dll/win32/riched20/undo.c +++ b/reactos/dll/win32/riched20/undo.c @@ -96,6 +96,7 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp pItem->member.para.pFmt->cbSize = sizeof(PARAFORMAT2); pItem->member.para.pFmt->dwMask = 0; *pItem->member.para.pFmt = *pdi->member.para.pFmt; + pItem->member.para.border = pdi->member.para.border; pItem->member.para.nFlags = prev_para->member.para.nFlags & ~MEPF_CELL; pItem->member.para.pCell = NULL; break; @@ -293,6 +294,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) para = ME_FindItemBack(tmp.pRun, diParagraph); ME_AddUndoItem(editor, diUndoSetParagraphFormat, para); *para->member.para.pFmt = *pItem->member.para.pFmt; + para->member.para.border = pItem->member.para.border; break; } case diUndoSetCharFormat: @@ -343,12 +345,14 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) new_para->member.para.nFlags |= MEPF_ROWSTART; assert(pItem->member.para.pFmt->cbSize == sizeof(PARAFORMAT2)); *new_para->member.para.pFmt = *pItem->member.para.pFmt; + new_para->member.para.border = pItem->member.para.border; if (pItem->member.para.pCell) { ME_DisplayItem *pItemCell, *pCell; pItemCell = pItem->member.para.pCell; pCell = new_para->member.para.pCell; pCell->member.cell.nRightBoundary = pItemCell->member.cell.nRightBoundary; + pCell->member.cell.border = pItemCell->member.cell.border; } break; } diff --git a/reactos/dll/win32/riched20/wrap.c b/reactos/dll/win32/riched20/wrap.c index 6f6e32ce1e8..3ffe09adea9 100644 --- a/reactos/dll/win32/riched20/wrap.c +++ b/reactos/dll/win32/riched20/wrap.c @@ -50,8 +50,10 @@ static void ME_BeginRow(ME_WrapContext *wc, ME_DisplayItem *para) wc->pRowStart = NULL; wc->bOverflown = FALSE; wc->pLastSplittableRun = NULL; + wc->bWordWrap = wc->context->editor->bWordWrap; if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) { wc->nAvailWidth = 0; + wc->bWordWrap = FALSE; if (para->member.para.nFlags & MEPF_ROWEND) { ME_Cell *cell = &ME_FindItemBack(para, diCell)->member.cell; @@ -73,11 +75,11 @@ static void ME_BeginRow(ME_WrapContext *wc, ME_DisplayItem *para) wc->nAvailWidth = cell->nWidth - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; - } else if (wc->context->editor->bWordWrap) { - wc->nAvailWidth = wc->context->rcView.right - wc->context->rcView.left - - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; + wc->bWordWrap = TRUE; } else { - wc->nAvailWidth = ~0u >> 1; + wc->nAvailWidth = wc->context->rcView.right - wc->context->rcView.left + - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin + - wc->context->editor->selofs; } wc->pt.x = wc->context->pt.x; if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ @@ -148,9 +150,9 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) assert(para->member.para.pFmt->dwMask & PFM_ALIGNMENT); align = para->member.para.pFmt->wAlignment; if (align == PFA_CENTER) - shift = (wc->nAvailWidth-width)/2; + shift = max((wc->nAvailWidth-width)/2, 0); if (align == PFA_RIGHT) - shift = wc->nAvailWidth-width; + shift = max(wc->nAvailWidth-width, 0); for (p = wc->pRowStart; p!=pEnd; p = p->next) { if (p->type==diRun) { /* FIXME add more run types */ @@ -377,7 +379,8 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) } /* will current run fit? */ - if (wc->pt.x + run->nWidth - wc->context->pt.x > wc->nAvailWidth) + if (wc->bWordWrap && + wc->pt.x + run->nWidth - wc->context->pt.x > wc->nAvailWidth) { int loc = wc->context->pt.x + wc->nAvailWidth - wc->pt.x; /* total white run ? */ @@ -416,9 +419,11 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) { if (run->nFlags & MERF_STARTWHITE) { - /* we had only spaces so far, so we must be on the first line of the - * paragraph, since no other lines of the paragraph start with spaces. */ - assert(!wc->nRow); + /* We had only spaces so far, so we must be on the first line of the + * paragraph (or the first line after MERF_ENDROW forced the line + * break within the paragraph), since no other lines of the paragraph + * start with spaces. */ + /* The lines will only contain spaces, and the rest of the run will * overflow onto the next line. */ wc->bOverflown = TRUE; @@ -730,30 +735,31 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { return bModified; } -void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor) { +void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor) +{ ME_Context c; + RECT rc; + int ofs; + ME_DisplayItem *item; ME_InitContext(&c, editor, GetDC(editor->hWnd)); - if (editor->bRedraw) - { - RECT rc = c.rcView; - int ofs = ME_GetYScrollPos(editor); - - ME_DisplayItem *item = editor->pBuffer->pFirst; - while(item != editor->pBuffer->pLast) { - if (item->member.para.nFlags & MEPF_REPAINT) { - rc.top = item->member.para.pt.y - ofs; - rc.bottom = item->member.para.pt.y + item->member.para.nHeight - ofs; - InvalidateRect(editor->hWnd, &rc, TRUE); - } - item = item->member.para.next_para; - } - if (editor->nTotalLength < editor->nLastTotalLength) - { - rc.top = editor->nTotalLength - ofs; - rc.bottom = editor->nLastTotalLength - ofs; + rc = c.rcView; + ofs = ME_GetYScrollPos(editor); + + item = editor->pBuffer->pFirst; + while(item != editor->pBuffer->pLast) { + if (item->member.para.nFlags & MEPF_REPAINT) { + rc.top = item->member.para.pt.y - ofs; + rc.bottom = item->member.para.pt.y + item->member.para.nHeight - ofs; InvalidateRect(editor->hWnd, &rc, TRUE); } + item = item->member.para.next_para; + } + if (editor->nTotalLength < editor->nLastTotalLength) + { + rc.top = editor->nTotalLength - ofs; + rc.bottom = editor->nLastTotalLength - ofs; + InvalidateRect(editor->hWnd, &rc, TRUE); } ME_DestroyContext(&c, editor->hWnd); } diff --git a/reactos/dll/win32/riched20/writer.c b/reactos/dll/win32/riched20/writer.c index 912cae3f48e..109ada1ef41 100644 --- a/reactos/dll/win32/riched20/writer.c +++ b/reactos/dll/win32/riched20/writer.c @@ -196,11 +196,14 @@ ME_StreamOutRTFHeader(ME_OutStream *pStream, int dwFormat) static BOOL -ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, const ME_DisplayItem *pLastRun) +ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, + ME_DisplayItem *pLastRun) { ME_DisplayItem *item = pFirstRun; ME_FontTableItem *table = pStream->fonttbl; int i; + ME_DisplayItem *pLastPara = ME_GetParagraph(pLastRun); + ME_DisplayItem *pCell = NULL; do { CHARFORMAT2W *fmt = &item->member.run.style->fmt; @@ -214,7 +217,7 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, if (table[i].bCharSet == bCharSet && (table[i].szFaceName == face || !lstrcmpW(table[i].szFaceName, face))) break; - if (i == pStream->nFontTblLen) { + if (i == pStream->nFontTblLen && i < STREAMOUT_FONTTBL_SIZE) { table[i].bCharSet = bCharSet; table[i].szFaceName = face; pStream->nFontTblLen++; @@ -226,7 +229,7 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, for (i = 1; i < pStream->nColorTblLen; i++) if (pStream->colortbl[i] == crColor) break; - if (i == pStream->nColorTblLen) { + if (i == pStream->nColorTblLen && i < STREAMOUT_COLORTBL_SIZE) { pStream->colortbl[i] = crColor; pStream->nColorTblLen++; } @@ -236,7 +239,7 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, for (i = 1; i < pStream->nColorTblLen; i++) if (pStream->colortbl[i] == crColor) break; - if (i == pStream->nColorTblLen) { + if (i == pStream->nColorTblLen && i < STREAMOUT_COLORTBL_SIZE) { pStream->colortbl[i] = crColor; pStream->nColorTblLen++; } @@ -246,6 +249,38 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, break; item = ME_FindItemFwd(item, diRun); } while (item); + item = ME_GetParagraph(pFirstRun); + do { + if (item->member.para.pCell && item->member.para.pCell) + { + pCell = item->member.para.pCell; + if (pCell) + { + ME_Border* borders[4] = { &pCell->member.cell.border.top, + &pCell->member.cell.border.left, + &pCell->member.cell.border.bottom, + &pCell->member.cell.border.right }; + for (i = 0; i < 4; i++) + { + if (borders[i]->width > 0) + { + int j; + COLORREF crColor = borders[i]->colorRef; + for (j = 1; j < pStream->nColorTblLen; j++) + if (pStream->colortbl[j] == crColor) + break; + if (j == pStream->nColorTblLen && j < STREAMOUT_COLORTBL_SIZE) { + pStream->colortbl[j] = crColor; + pStream->nColorTblLen++; + } + } + } + } + } + if (item == pLastPara) + break; + item = item->member.para.next_para; + } while (item); if (!ME_StreamOutPrint(pStream, "{\\fonttbl")) return FALSE; @@ -286,30 +321,78 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, static BOOL ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream, - const ME_DisplayItem *para) + ME_DisplayItem *para) { ME_DisplayItem *cell; char props[STREAMOUT_BUFFER_SIZE] = ""; + int i; + const char sideChar[4] = {'t','l','b','r'}; if (!ME_StreamOutPrint(pStream, "\\trowd")) return FALSE; if (!editor->bEmulateVersion10) { /* v4.1 */ - assert(para->member.para.nFlags & MEPF_ROWSTART); + PARAFORMAT2 *pFmt = ME_GetTableRowEnd(para)->member.para.pFmt; + para = ME_GetTableRowStart(para); cell = para->member.para.next_para->member.para.pCell; assert(cell); + if (pFmt->dxOffset) + sprintf(props + strlen(props), "\\trgaph%d", pFmt->dxOffset); + if (pFmt->dxStartIndent) + sprintf(props + strlen(props), "\\trleft%d", pFmt->dxStartIndent); do { + ME_Border* borders[4] = { &cell->member.cell.border.top, + &cell->member.cell.border.left, + &cell->member.cell.border.bottom, + &cell->member.cell.border.right }; + for (i = 0; i < 4; i++) + { + if (borders[i]->width) + { + int j; + COLORREF crColor = borders[i]->colorRef; + sprintf(props + strlen(props), "\\clbrdr%c", sideChar[i]); + sprintf(props + strlen(props), "\\brdrs"); + sprintf(props + strlen(props), "\\brdrw%d", borders[i]->width); + for (j = 1; j < pStream->nColorTblLen; j++) { + if (pStream->colortbl[j] == crColor) { + sprintf(props + strlen(props), "\\brdrcf%u", j); + break; + } + } + } + } sprintf(props + strlen(props), "\\cellx%d", cell->member.cell.nRightBoundary); cell = cell->member.cell.next_cell; } while (cell->member.cell.next_cell); } else { /* v1.0 - 3.0 */ + const ME_Border* borders[4] = { ¶->member.para.border.top, + ¶->member.para.border.left, + ¶->member.para.border.bottom, + ¶->member.para.border.right }; PARAFORMAT2 *pFmt = para->member.para.pFmt; - int i; assert(!(para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))); if (pFmt->dxOffset) sprintf(props + strlen(props), "\\trgaph%d", pFmt->dxOffset); if (pFmt->dxStartIndent) sprintf(props + strlen(props), "\\trleft%d", pFmt->dxStartIndent); + for (i = 0; i < 4; i++) + { + if (borders[i]->width) + { + int j; + COLORREF crColor = borders[i]->colorRef; + sprintf(props + strlen(props), "\\trbrdr%c", sideChar[i]); + sprintf(props + strlen(props), "\\brdrs"); + sprintf(props + strlen(props), "\\brdrw%d", borders[i]->width); + for (j = 1; j < pStream->nColorTblLen; j++) { + if (pStream->colortbl[j] == crColor) { + sprintf(props + strlen(props), "\\brdrcf%u", j); + break; + } + } + } + } for (i = 0; i < pFmt->cTabCount; i++) { sprintf(props + strlen(props), "\\cellx%d", pFmt->rgxTabs[i] & 0x00FFFFFF); @@ -727,7 +810,7 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC } } else if (p->member.para.nFlags & MEPF_ROWEND) { pStream->nNestingLevel--; - if (pStream->nNestingLevel > 1) { + if (pStream->nNestingLevel >= 1) { if (!ME_StreamOutPrint(pStream, "{\\*\\nesttableprops")) return FALSE; if (!ME_StreamOutRTFTableProps(editor, pStream, p))