diff --git a/reactos/lib/riched20/editor.c b/reactos/lib/riched20/editor.c index d0667201202..07a1ee03579 100644 --- a/reactos/lib/riched20/editor.c +++ b/reactos/lib/riched20/editor.c @@ -43,7 +43,7 @@ - EM_GETCHARFORMAT (partly done) - EM_GETEDITSTYLE + EM_GETEVENTMASK - - EM_GETFIRSTVISIBLELINE + + EM_GETFIRSTVISIBLELINE (can be optimized if needed) - EM_GETIMECOLOR 1.0asian - EM_GETIMECOMPMODE 2.0 - EM_GETIMEOPTIONS 1.0asian @@ -81,7 +81,7 @@ + EM_LINELENGTH + EM_LINESCROLL - EM_PASTESPECIAL - - EM_POSFROMCHARS + + EM_POSFROMCHAR + EM_REDO 2.0 - EM_REQUESTRESIZE + EM_REPLACESEL (proper style?) ANSI&Unicode @@ -290,7 +290,7 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStrea } ME_InsertTextFromCursor(editor, 0, pText, nWideChars, style); - if (stream->dwSize < STREAMIN_BUFFER_SIZE) + if (stream->dwSize == 0) break; stream->dwSize = 0; } while(1); @@ -483,7 +483,12 @@ static void ME_RTFReadHook(RTF_Info *info) { { ME_Style *s; RTFFlushOutputBuffer(info); + if (info->stackTop<=1) { + info->rtfClass = rtfEOF; + return; + } info->stackTop--; + assert(info->stackTop >= 0); if (info->styleChanged) { /* FIXME too slow ? how come ? */ @@ -1111,7 +1116,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP UNSUPPORTED_MSG(EM_GETAUTOURLDETECT) UNSUPPORTED_MSG(EM_GETBIDIOPTIONS) UNSUPPORTED_MSG(EM_GETEDITSTYLE) - UNSUPPORTED_MSG(EM_GETFIRSTVISIBLELINE) UNSUPPORTED_MSG(EM_GETIMECOMPMODE) /* UNSUPPORTED_MSG(EM_GETIMESTATUS) missing in Wine headers */ UNSUPPORTED_MSG(EM_GETLANGOPTIONS) @@ -1130,7 +1134,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP UNSUPPORTED_MSG(EM_HIDESELECTION) UNSUPPORTED_MSG(EM_LIMITTEXT) /* also known as EM_SETLIMITTEXT */ UNSUPPORTED_MSG(EM_PASTESPECIAL) -/* UNSUPPORTED_MSG(EM_POSFROMCHARS) missing in Wine headers */ UNSUPPORTED_MSG(EM_REQUESTRESIZE) UNSUPPORTED_MSG(EM_SCROLL) UNSUPPORTED_MSG(EM_SCROLLCARET) @@ -1350,6 +1353,30 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP case EM_GETPARAFORMAT: ME_GetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam); return 0; + case EM_GETFIRSTVISIBLELINE: + { + ME_DisplayItem *p = editor->pBuffer->pFirst; + int y = editor->nScrollPosY; + int ypara = 0; + int count = 0; + int ystart, yend; + while(p) { + p = ME_FindItemFwd(p, diStartRowOrParagraphOrEnd); + if (p->type == diTextEnd) + break; + if (p->type == diParagraph) { + ypara = p->member.para.nYPos; + continue; + } + ystart = ypara + p->member.row.nYPos; + yend = ystart + p->member.row.nHeight; + if (y < yend) { + break; + } + count++; + } + return count; + } case EM_LINESCROLL: { int nPos = editor->nScrollPosY, nEnd= editor->nTotalLength - editor->sizeWindow.cy; @@ -1538,16 +1565,19 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP } else { - LPWSTR buffer = HeapAlloc(GetProcessHeap(), 0, (nCount + 1) * sizeof(WCHAR)); - DWORD buflen = ex->cb; - LRESULT rc; - DWORD flags = 0; + /* 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 = HeapAlloc(GetProcessHeap(), 0, (crlfmul*nCount + 1) * sizeof(WCHAR)); + DWORD buflen = ex->cb; + LRESULT rc; + DWORD flags = 0; - buflen = ME_GetTextW(editor, buffer, nStart, nCount, ex->flags & GT_USECRLF); - rc = WideCharToMultiByte(ex->codepage, flags, buffer, buflen, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefaultChar); + buflen = ME_GetTextW(editor, buffer, nStart, nCount, ex->flags & GT_USECRLF); + rc = WideCharToMultiByte(ex->codepage, flags, buffer, buflen, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefaultChar); - HeapFree(GetProcessHeap(),0,buffer); - return rc; + HeapFree(GetProcessHeap(),0,buffer); + return rc; } } case EM_GETSELTEXT: @@ -1563,6 +1593,9 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP case EM_GETTEXTRANGE: { TEXTRANGEW *rng = (TEXTRANGEW *)lParam; + TRACE("EM_GETTEXTRANGE min=%ld max=%ld unicode=%d emul1.0=%d length=%d\n", + rng->chrg.cpMin, rng->chrg.cpMax, IsWindowUnicode(hWnd), + editor->bEmulateVersion10, ME_GetTextLength(editor)); if (IsWindowUnicode(hWnd)) return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, rng->chrg.cpMax-rng->chrg.cpMin, editor->bEmulateVersion10); else @@ -1639,7 +1672,8 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP if (item_end) nNextLineOfs = ME_CharOfsFromRunOfs(editor, ME_FindItemFwd(item_end, diRun), 0); else - nNextLineOfs = ME_FindItemFwd(item, diParagraphOrEnd)->member.para.nCharOfs-1; + nNextLineOfs = ME_FindItemFwd(item, diParagraphOrEnd)->member.para.nCharOfs + - (editor->bEmulateVersion10?2:1); nChars = nNextLineOfs - nThisLineOfs; TRACE("EM_LINELENGTH(%d)==%d\n",wParam, nChars); return nChars; @@ -1684,6 +1718,33 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP return ME_SetZoom(editor, wParam, lParam); case EM_CHARFROMPOS: return ME_CharFromPos(editor, ((POINTL *)lParam)->x, ((POINTL *)lParam)->y); + case EM_POSFROMCHAR: + { + ME_DisplayItem *pRun; + int nCharOfs, nOffset, nLength; + POINTL pt = {0,0}; + + nCharOfs = wParam; + /* detect which API version we're dealing with */ + 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.nYPos; + } else { + pt.x = 0; + pt.y = editor->pBuffer->pLast->member.para.nYPos; + } + if (wParam >= 0x40000) { + *(POINTL *)wParam = pt; + } + return MAKELONG( pt.x, pt.y ); + } case WM_CREATE: ME_CommitUndo(editor); ME_WrapMarkedParagraphs(editor); @@ -1982,12 +2043,12 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in { ME_DisplayItem *item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart); int nWritten = 0; + WCHAR *pStart = buffer; if (!item) { *buffer = L'\0'; return 0; } - assert(item); if (nStart) { @@ -2012,13 +2073,16 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in if (item->member.run.nFlags & MERF_ENDPARA) { - *buffer++ = '\r'; + *buffer = '\r'; if (bCRLF) { - *buffer = '\n'; + *(++buffer) = '\n'; nWritten++; } assert(nLen == 1); + /* our end paragraph consists of 2 characters now */ + if (editor->bEmulateVersion10) + nChars--; } else CopyMemory(buffer, item->member.run.strText->szData, sizeof(WCHAR)*nLen); @@ -2028,12 +2092,14 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in if (!nChars) { + TRACE("nWritten=%d, actual=%d\n", nWritten, buffer-pStart); *buffer = L'\0'; return nWritten; } item = ME_FindItemFwd(item, diRun); } *buffer = L'\0'; + TRACE("nWritten=%d, actual=%d\n", nWritten, buffer-pStart); return nWritten; } diff --git a/reactos/lib/riched20/list.c b/reactos/lib/riched20/list.c index e4e1f403862..857fcf3edfa 100644 --- a/reactos/lib/riched20/list.c +++ b/reactos/lib/riched20/list.c @@ -21,7 +21,7 @@ #include "editor.h" -WINE_DEFAULT_DEBUG_CHANNEL(riched20); +WINE_DEFAULT_DEBUG_CHANNEL(richedit_lists); void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat) { @@ -181,7 +181,7 @@ void ME_DumpDocument(ME_TextBuffer *buffer) pItem->member.run.nCharOfs); break; case diTextEnd: - TRACE("\nEnd\n"); + TRACE("\nEnd(ofs=%d)\n", pItem->member.para.nCharOfs); break; default: break; diff --git a/reactos/lib/riched20/reader.c b/reactos/lib/riched20/reader.c index 5c104e1c90c..c16911552b1 100644 --- a/reactos/lib/riched20/reader.c +++ b/reactos/lib/riched20/reader.c @@ -127,13 +127,6 @@ int _RTFGetChar(RTF_Info *info) TRACE("\n"); - /* Doc says, that if the last buffer wasn't full, it's EOF. - Actually, that's not true. */ -/* - if (stream->dwSize > 0 && stream->dwSize == stream->dwUsed - && stream->dwSize < sizeof(stream->buffer)) - return EOF; -*/ if (stream->dwSize <= stream->dwUsed) { ME_StreamInFill(stream); @@ -455,6 +448,10 @@ int RTFGetToken(RTF_Info *info) RTFFuncPtr p; TRACE("\n"); + /* don't try to return anything once EOF is reached */ + if (info->rtfClass == rtfEOF) { + return rtfEOF; + } for (;;) { @@ -885,6 +882,8 @@ static void ReadFontTbl(RTF_Info *info) for (;;) { RTFGetToken (info); + if (info->rtfClass == rtfEOF) + break; if (RTFCheckCM (info, rtfGroup, rtfEndGroup)) break; if (old < 0) /* first entry - determine tbl type */ @@ -901,6 +900,8 @@ static void ReadFontTbl(RTF_Info *info) if (!RTFCheckCM (info, rtfGroup, rtfBeginGroup)) RTFPanic (info, "%s: missing \"{\"", fn); RTFGetToken (info); /* yes, skip to next token */ + if (info->rtfClass == rtfEOF) + break; } fp = New (RTFFont); if (fp == NULL) @@ -1002,12 +1003,18 @@ static void ReadFontTbl(RTF_Info *info) fn,info->rtfTextBuf); } RTFGetToken (info); + if (info->rtfClass == rtfEOF) + break; } + if (info->rtfClass == rtfEOF) + break; if (old == 0) /* need to see "}" here */ { RTFGetToken (info); if (!RTFCheckCM (info, rtfGroup, rtfEndGroup)) RTFPanic (info, "%s: missing \"}\"", fn); + if (info->rtfClass == rtfEOF) + break; } /* Apply the real properties of the default font */ @@ -1055,6 +1062,8 @@ static void ReadColorTbl(RTF_Info *info) for (;;) { RTFGetToken (info); + if (info->rtfClass == rtfEOF) + break; if (RTFCheckCM (info, rtfGroup, rtfEndGroup)) break; cp = New (RTFColor); @@ -1074,6 +1083,8 @@ static void ReadColorTbl(RTF_Info *info) } RTFGetToken (info); } + if (info->rtfClass == rtfEOF) + break; if (!RTFCheckCM (info, rtfText, ';')) RTFPanic (info,"%s: malformed entry", fn); } diff --git a/reactos/lib/riched20/run.c b/reactos/lib/riched20/run.c index eab74012fe1..568472c62f2 100644 --- a/reactos/lib/riched20/run.c +++ b/reactos/lib/riched20/run.c @@ -23,6 +23,8 @@ #include "editor.h" WINE_DEFAULT_DEBUG_CHANNEL(richedit); +WINE_DECLARE_DEBUG_CHANNEL(richedit_check); +WINE_DECLARE_DEBUG_CHANNEL(richedit_lists); int ME_CanJoinRuns(ME_Run *run1, ME_Run *run2) { @@ -72,26 +74,26 @@ void ME_CheckCharOffsets(ME_TextEditor *editor) { ME_DisplayItem *p = editor->pBuffer->pFirst; int ofs = 0, ofsp = 0; - if(TRACE_ON(richedit)) + if(TRACE_ON(richedit_lists)) { - TRACE("---\n"); + TRACE_(richedit_lists)("---\n"); ME_DumpDocument(editor->pBuffer); } do { p = ME_FindItemFwd(p, diRunOrParagraphOrEnd); switch(p->type) { case diTextEnd: - TRACE("tend, real ofsp = %d, counted = %d\n", p->member.para.nCharOfs, ofsp+ofs); + TRACE_(richedit_check)("tend, real ofsp = %d, counted = %d\n", p->member.para.nCharOfs, ofsp+ofs); assert(ofsp+ofs == p->member.para.nCharOfs); return; case diParagraph: - TRACE("para, real ofsp = %d, counted = %d\n", p->member.para.nCharOfs, ofsp+ofs); + TRACE_(richedit_check)("para, real ofsp = %d, counted = %d\n", p->member.para.nCharOfs, ofsp+ofs); assert(ofsp+ofs == p->member.para.nCharOfs); ofsp = p->member.para.nCharOfs; ofs = 0; break; case diRun: - TRACE("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = \"%s\", flags=%08x, fx&mask = %08lx\n", + TRACE_(richedit_check)("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = \"%s\", flags=%08x, fx&mask = %08lx\n", p->member.run.nCharOfs, p->member.run.nCharOfs+ofsp, ofsp+ofs, p->member.run.strText->nLen, debugstr_w(p->member.run.strText->szData), p->member.run.nFlags, @@ -143,6 +145,7 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem ** if (nCharOfs < pPara->member.para.next_para->member.para.nCharOfs) { + int eollen = 1; *ppRun = ME_FindItemFwd(pPara, diRun); assert(*ppRun); while (!((*ppRun)->member.run.nFlags & MERF_ENDPARA)) @@ -157,7 +160,10 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem ** } *ppRun = pNext; } - if (nCharOfs == nParaOfs + (*ppRun)->member.run.nCharOfs) { + /* the handling of bEmulateVersion10 may be a source of many bugs, I'm afraid */ + eollen = (editor->bEmulateVersion10 ? 2 : 1); + if (nCharOfs >= nParaOfs + (*ppRun)->member.run.nCharOfs && + nCharOfs < nParaOfs + (*ppRun)->member.run.nCharOfs + eollen) { *pOfs = 0; return; } diff --git a/reactos/lib/riched20/style.c b/reactos/lib/riched20/style.c index 1d06154adfc..11fd56b02c8 100644 --- a/reactos/lib/riched20/style.c +++ b/reactos/lib/riched20/style.c @@ -21,6 +21,7 @@ #include "editor.h" WINE_DEFAULT_DEBUG_CHANNEL(richedit); +WINE_DECLARE_DEBUG_CHANNEL(richedit_style); static int all_refs = 0; @@ -197,7 +198,7 @@ void ME_DumpStyle(ME_Style *s) { char buf[2048]; ME_DumpStyleToBuf(&s->fmt, buf); - TRACE("%s\n", buf); + TRACE_(richedit_style)("%s\n", buf); } void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048]) @@ -321,7 +322,7 @@ HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s) if (i < HFONT_CACHE_SIZE) /* found */ { item = &editor->pFontCache[i]; - TRACE("font reused %d\n", i); + TRACE_(richedit_style)("font reused %d\n", i); s->hFont = item->hFont; item->nRefs++; @@ -332,13 +333,13 @@ HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s) assert(nEmpty != -1); /* otherwise we leak cache entries or get too many fonts at once*/ if (item->hFont) { - TRACE("font deleted %d\n", nEmpty); + TRACE_(richedit_style)("font deleted %d\n", nEmpty); DeleteObject(item->hFont); item->hFont = NULL; } s->hFont = CreateFontIndirectW(&lf); assert(s->hFont); - TRACE("font created %d\n", nEmpty); + TRACE_(richedit_style)("font created %d\n", nEmpty); item->hFont = s->hFont; item->nRefs = 1; memcpy(&item->lfSpecs, &lf, sizeof(LOGFONTW)); @@ -391,9 +392,9 @@ void ME_ReleaseStyle(ME_Style *s) s->nRefs--; all_refs--; if (s->nRefs==0) - TRACE("destroy style %p, total refs=%d\n", s, all_refs); + TRACE_(richedit_style)("destroy style %p, total refs=%d\n", s, all_refs); else - TRACE("release style %p, new refs=%d, total refs=%d\n", s, s->nRefs, all_refs); + TRACE_(richedit_style)("release style %p, new refs=%d, total refs=%d\n", s, s->nRefs, all_refs); if (!all_refs) TRACE("all style references freed (good!)\n"); assert(s->nRefs>=0); if (!s->nRefs) diff --git a/reactos/lib/riched20/writer.c b/reactos/lib/riched20/writer.c index 629cce2e439..c8d1226c894 100644 --- a/reactos/lib/riched20/writer.c +++ b/reactos/lib/riched20/writer.c @@ -616,7 +616,7 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars) buffer[pos++] = *letter; } else { for (i = 0; i < nBytes; i++) - pos += sprintf(buffer + pos, "\\'%02x", letter[i]); + pos += sprintf(buffer + pos, "\\'%02x", (BYTE)letter[i]); } text++; nChars--;