Hi, The following patch implements EM_GETLINE. This feature was requested in bug #4305 and also mentioned at Regards, Thomas Kho 2006-03-28 Thomas Kho * dlls/riched20/editor.c, dlls/riched20/tests/editor.c: riched20: Added EM_GETLINE implementation and test editor.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++-- tests/editor.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 2 deletions(-) Signed-off-by: Thomas Kho Index: dlls/riched20/editor.c =================================================================== RCS file: /home/wine/wine/dlls/riched20/editor.c,v retrieving revision 1.104 diff -u -r1.104 editor.c --- dlls/riched20/editor.c 21 Mar 2006 19:23:02 -0000 1.104 +++ dlls/riched20/editor.c 29 Mar 2006 01:59:59 -0000 @@ -52,7 +52,7 @@ - EM_GETIMESTATUS - EM_GETLANGOPTIONS 2.0 - EM_GETLIMITTEXT - - EM_GETLINE + + EM_GETLINE + EM_GETLINECOUNT returns number of rows, not of paragraphs + EM_GETMODIFY - EM_GETOLEINTERFACE @@ -1402,7 +1401,6 @@ /* UNSUPPORTED_MSG(EM_GETIMESTATUS) missing in Wine headers */ UNSUPPORTED_MSG(EM_GETLANGOPTIONS) UNSUPPORTED_MSG(EM_GETLIMITTEXT) - UNSUPPORTED_MSG(EM_GETLINE) /* UNSUPPORTED_MSG(EM_GETOLEINTERFACE) separate stub */ UNSUPPORTED_MSG(EM_GETPASSWORDCHAR) UNSUPPORTED_MSG(EM_GETREDONAME) @@ -1997,6 +1995,61 @@ return nChars; } } + case EM_GETLINE: + { + ME_DisplayItem *run; + ME_String *strText; + int nMaxChars = (int) *(WORD *) lParam; + int nBPC = 1; /* bytes per character */ + int nEndChars; + char *dest = (char *) lParam; + + TRACE("EM_GETLINE: row=%d, nMaxChars=%d (%s)\n", (int) wParam, nMaxChars, + IsWindowUnicode(hWnd) ? "Unicode" : "Ansi"); + + if (IsWindowUnicode(hWnd)) + nBPC = sizeof(WCHAR); + + run = ME_FindRowWithNumber(editor, (int) wParam); + if (run == NULL) + return 0; + + while ((run = ME_FindItemFwd(run, diRunOrStartRow)) + && !(run->member.run.nFlags & MERF_ENDPARA) + && ((int) dest - (int) lParam) < nMaxChars * nBPC) + { + int nCopy; + if (run->type != diRun) + break; + + strText = run->member.run.strText; + nCopy = min(nMaxChars - ((int) dest - (int) lParam)/nBPC, strText->nLen); + + if (IsWindowUnicode(hWnd)) + memcpy(dest, strText->szData, nCopy * nBPC); + else + WideCharToMultiByte(CP_ACP, 0, strText->szData, -1, dest, nCopy, NULL, + NULL); + dest += nCopy * nBPC; + } + + /* append "\r\0", space allowing */ + nEndChars = min(nMaxChars - ((int) dest - (int) lParam)/nBPC, 2); + if (IsWindowUnicode(hWnd)) { + memcpy(dest, L"\r", nEndChars*2); + dest += nEndChars*2; + } else { + memcpy(dest, "\r", nEndChars); + dest += nEndChars; + } + + TRACE("EM_GETLINE: wrote %d bytes\n", (int) dest - (int) lParam); + + if (nEndChars > 1) /* don't count '\0' */ + return ((int) dest - (int) lParam - 1) / nBPC; + else + return ((int) dest - (int) lParam) / nBPC; + } case EM_GETLINECOUNT: { ME_DisplayItem *item = editor->pBuffer->pFirst->next; Index: dlls/riched20/tests/editor.c =================================================================== RCS file: /home/wine/wine/dlls/riched20/tests/editor.c,v retrieving revision 1.12 diff -u -r1.12 editor.c --- dlls/riched20/tests/editor.c 21 Mar 2006 19:23:02 -0000 1.12 +++ dlls/riched20/tests/editor.c 29 Mar 2006 01:59:59 -0000 @@ -189,6 +189,67 @@ DestroyWindow(hwndRichEdit); } +struct getline_s { + int line; + size_t buffer_len; + char *text; +} gl[] = { + {0, 10, "foo bar\r"}, + {1, 10, "\r"}, + {2, 10, "bar\r"}, + {3, 10, "\r"}, + + /* Buffer smaller than line length */ + {0, 2, "foo bar\r"}, + {0, 1, "foo bar\r"}, + {0, 0, "foo bar\r"} +}; + +static void test_EM_GETLINE(void) +{ + int i; + HWND hwndRichEdit = new_richedit(NULL); + static const int nBuf = 1024; + char dest[1024], origdest[1024]; + const char text[] = "foo bar\n" + "\n" + "bar\n"; + + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text); + + memset(origdest, 0xBB, nBuf); + for (i = 0; i < sizeof(gl)/sizeof(struct getline_s); i++) + { + int nCopied; + int expected_nCopied = min(gl[i].buffer_len, strlen(gl[i].text)); + int expected_bytes_written = min(gl[i].buffer_len, strlen(gl[i].text) + 1); + memset(dest, 0xBB, nBuf); + *(WORD *) dest = gl[i].buffer_len; + + /* EM_GETLINE appends a "\r\0" to the end of the line + * nCopied counts up to and including the '\r' */ + nCopied = SendMessage(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM) dest); + ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied, + expected_nCopied); + /* two special cases since a parameter is passed via dest */ + if (gl[i].buffer_len == 0) + ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2), + "buffer_len=0\n"); + else if (gl[i].buffer_len == 1) + ok(dest[0] == gl[i].text[0] && !dest[1] && + !strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n"); + else { + ok(!strncmp(dest, gl[i].text, expected_bytes_written), + "%d: expected_bytes_written=%d\n", i, expected_bytes_written); + ok(!strncmp(dest + expected_bytes_written, origdest + + expected_bytes_written, nBuf - expected_bytes_written), + "%d: expected_bytes_written=%d\n", i, expected_bytes_written); + } + } + + DestroyWindow(hwndRichEdit); +} + static int get_scroll_pos_y(HWND hwnd) { POINT p = {-1, -1}; @@ -760,6 +821,7 @@ hmoduleRichEdit = LoadLibrary("RICHED20.DLL"); ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError()); test_EM_FINDTEXT(); + test_EM_GETLINE(); test_EM_SCROLLCARET(); test_EM_SCROLL(); test_EM_SETTEXTMODE();