This patch enables basic Richedit 1.0 functionality and is an attempt to be as useful as the edit control version. I don't expect this patch to be applied as it is still very messy, but wanted to share the progress with anyone who is interested. Notes: Doesn't process multiple paragraphs yet (treats everything as one paragraph) Doesn't display selection, although it will still handle this Mouse control very limited and buggy Many window messages unimplemented Changelog: - Made independent of edit control. Implemented basic structure, although still many bugs and unimplemented features
Index: wine/dlls/richedit/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/richedit/Makefile.in,v retrieving revision 1.12 diff -u -r1.12 Makefile.in --- wine/dlls/richedit/Makefile.in 17 May 2002 03:37:14 -0000 1.12 +++ wine/dlls/richedit/Makefile.in 4 Dec 2002 22:37:02 -0000 @@ -3,7 +3,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = riched32.dll -IMPORTS = user32 kernel32 +IMPORTS = user32 kernel32 gdi32 LDDLLFLAGS = @LDDLLFLAGS@ SYMBOLFILE = $(MODULE).tmp.o @@ -17,3 +17,4 @@ @MAKE_DLL_RULES@ ### Dependencies: + Index: wine/dlls/richedit/richedit.c =================================================================== RCS file: /home/wine/wine/dlls/richedit/richedit.c,v retrieving revision 1.25 diff -u -r1.25 richedit.c --- wine/dlls/richedit/richedit.c 2 Dec 2002 18:10:58 -0000 1.25 +++ wine/dlls/richedit/richedit.c 4 Dec 2002 22:37:03 -0000 @@ -5,7 +5,8 @@ * At the point, it is good only for application who use the RICHEDIT * control to display RTF text. * - * Copyright 2000 by Jean-Claude Batista + * Copyright 2000 by Jean-Claude Batista + * Copyrigth 2002 by Robert Shearman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,6 +22,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define _RICHEDIT_VER 0x0100 #include <string.h> #include "windef.h" @@ -36,21 +38,162 @@ #include "rtf.h" #include "rtf2text.h" -#include "wine/debug.h" +#include "wine/debug.h" +#include "wine/unicode.h" -#define ID_EDIT 1 +//#define ID_EDIT 1 WINE_DEFAULT_DEBUG_CHANNEL(richedit); HANDLE RICHED32_hHeap = (HANDLE)NULL; -/* LPSTR RICHED32_aSubclass = (LPSTR)NULL; */ + +typedef struct tagRICHTEXTSEG +{ + COMPCOLOR extras; + HFONT hSegFont; + LPWSTR pText; + int length; + struct tagRICHTEXTSEG * pNextSeg; +} RICHTEXTSEG; + +typedef struct tagLINEDEF { + INT length; +// LINE_END ending; + INT width; + int startIndex; + int cachedHeight; + int cachedWidth; + int cachedYPos; + RICHTEXTSEG * pTextSeg; + struct tagLINEDEF *next; +} LINEDEF; + +typedef struct tagPARAGRAPH { + PARAFORMAT format; + LINEDEF *pFirstLine; + struct tagPARAGRAPH * pNext; + int cachedHeight; + int cachedWidth; + LPWSTR wszBuffer; + UINT uBufferSize; // in characters + UINT uBufferLimit; // in characters +} PARAGRAPH; + +typedef struct +{ + BOOL is_unicode; /* how the control was created */ + INT x_offset; /* scroll offset this is in pixels*/ + INT y_offset; /* scroll offset in number of lines */ +// INT char_width; /* average character width in pixels */ + DWORD style; /* sane version of wnd->dwStyle */ + WORD flags; /* flags that are not in es->style or wnd->flags (EF_XXX) */ + DWORD dwEventMask; +// INT undo_insert_count; /* number of characters inserted in sequence */ +// UINT undo_position; /* character index of the insertion and deletion */ +// LPWSTR undo_text; /* deleted text */ +// UINT undo_buffer_size; /* size of the deleted text buffer */ + WCHAR password_char; /* == 0 if no password char, and for multi line controls */ + INT left_margin; /* in pixels */ + INT right_margin; /* in pixels */ + RECT format_rect; +// INT text_width; /* width of the widest line in pixels*/ + INT region_posx; /* Position of cursor relative to region: */ + INT region_posy; /* -1: to left, 0: within, 1: to right */ +// EDITWORDBREAKPROC16 word_break_proc16; + void *word_break_proc; /* 32-bit word break proc: ANSI or Unicode */ +// INT line_count; /* number of lines */ +// BOOL bCaptureState; /* flag indicating whether mouse was captured */ +// BOOL bEnableState; /* flag keeping the enable state */ + HWND hwndSelf; /* the our window handle */ + HWND hwndParent; /* Handle of parent for sending EN_* messages. + Even if parent will change, EN_* messages + should be sent to the first parent. */ + /* + * only for multi line controls + */ +// INT lock_count; /* amount of re-entries in the EditWndProc */ + INT nTabPositions; + LPINT lpnTabStopPositions; + PARAGRAPH *pFirstParagraph; + PARAGRAPH * pSelection; + CHARRANGE chrSelection; +// HLOCAL hloc32W; /* our unicode local memory block */ +// HLOCAL16 hloc16; /* alias for 16-bit control receiving EM_GETHANDLE16 +// or EM_SETHANDLE16 */ +// HLOCAL hloc32A; /* alias for ANSI control receiving EM_GETHANDLE +// or EM_SETHANDLE */ +} RICHEDITSTATE; + +/* + * extra flags for EDITSTATE.flags field + */ +#define EF_MODIFIED 0x0001 /* text has been modified */ +#define EF_FOCUSED 0x0002 /* we have input focus */ +#define EF_UPDATE 0x0004 /* notify parent of changed state */ +//#define EF_VSCROLL_TRACK 0x0008 /* don't SetScrollPos() since we are tracking the thumb */ +//#define EF_HSCROLL_TRACK 0x0010 /* don't SetScrollPos() since we are tracking the thumb */ +#define EF_AFTER_WRAP 0x0080 /* the caret is displayed after the last character of a + wrapped line, instead of in front of the next character */ +//#define EF_USE_SOFTBRK 0x0100 /* Enable soft breaks in text. */ #define DPRINTF_EDIT_MSG32(str) \ TRACE(\ "32 bit : " str ": hwnd=%p, wParam=%08x, lParam=%08x\n"\ , \ - hwnd, (UINT)wParam, (UINT)lParam) - + hwnd, (UINT)wParam, (UINT)lParam) + +#define FIXME_MSG(str) \ + FIXME(\ + str ": hwnd=%p, wParam=%08x, lParam=%08x\n"\ + , \ + hwnd, (UINT)wParam, (UINT)lParam) + +// FIXME: only send messages that parent wants (see res->dwEventMask) +#define RT_NOTIFY_PARENT(res, wNotifyCode, str) \ + do \ + { /* Notify parent which has created this edit control */ \ + TRACE("notification " str " sent to hwnd=%p\n", res->hwndParent); \ + SendMessageW(res->hwndParent, WM_COMMAND, \ + MAKEWPARAM(GetWindowLongW((res->hwndSelf),GWL_ID), wNotifyCode), \ + (LPARAM)(res->hwndSelf)); \ + } while(0) + + +static void RICHED32_LockBuffer(RICHEDITSTATE * res); +static void RICHED32_WM_Create(RICHEDITSTATE * res, HWND hwnd, LPCREATESTRUCTA lpcs); +static LRESULT RICHED32_WM_Paint(RICHEDITSTATE * res, WPARAM wParam); +static LRESULT RICHED32_WM_NCDestroy(RICHEDITSTATE * res); +static LRESULT RICHED32_NCCreate(HWND hwnd, LPCREATESTRUCTA lpcs); +static HFONT RichText_CHARFORMAT2ToHFONT(CHARFORMAT2W * pFormat); +static DWORD RichTextParagraph_Draw(PARAGRAPH * pParagraph, HDC hDC, int startx, int starty, int nTabPositions, int * lpnTabStopPositions); +static DWORD RichTextLine_Draw(LINEDEF * pLine, HDC hDC, int startx, int starty, int nTabPositions, int * lpnTabStopPositions); +static void RichTextSeg_Draw(RICHTEXTSEG * textSeg, HDC hDC, int x, int y, int index, int charCount, int nTabPositions, int * lpnTabStopPositions); +static DWORD RichTextSeg_GetExtent(RICHTEXTSEG * pTextSeg, HDC hDC, int index, int charCount, int nTabPositions, int * lpnTabStopPositions); +static int RICHED32_WM_SetText(RICHEDITSTATE * res, LPCSTR szText); +static void RichText_BuildLineDefs(RICHEDITSTATE * res, PARAGRAPH * para); +static RICHTEXTSEG * RichTextSeg_SkipToChar(RICHTEXTSEG * pTextSeg, LONG pos, LONG * remaining); +static void RICHED32_EM_SetCharFormat2A(RICHEDITSTATE * res, CHARFORMAT2A * pChf); +static void RichText_ReplaceSel(RICHEDITSTATE * res, LPWSTR wszInsertion); +static void RICHED32_EM_ReplaceSel(RICHEDITSTATE * res, BOOL bUndo, LPCSTR szText); +static void RICHED32_CreateAndShowCaret(RICHEDITSTATE * res); +static void RICHED32_UpdateScrollInfo(RICHEDITSTATE * res); +static void RICHED32_WM_Char(RICHEDITSTATE * res, WCHAR charW); +static LINEDEF * RichTextLine_SkipToChar(LINEDEF * pLine, LONG pos, LONG * remaining); +static LRESULT RichText_EM_PosFromChar(RICHEDITSTATE * res, INT index); +static INT RichText_CharFromPos(RICHEDITSTATE * res, POINTL * pPoint); +static LRESULT RichText_EM_FindTextExW(RICHEDITSTATE * res, UINT fuFlags, FINDTEXTEXW * lpFindText); +static LRESULT RichText_EM_FindTextExA(RICHEDITSTATE * res, UINT fuFlags, FINDTEXTEXA * lpFindText); +static void RichTextParagraph_SetFormat2(PARAGRAPH * pParagraph, PARAFORMAT * pFormat); +static void RichText_WM_Keydown(RICHEDITSTATE * res, int nVirtKey, long lKeyData); +int RTFToBuffer(char* pBuffer, int nBufferSize); +static void RICHED32_WM_Cut(RICHEDITSTATE * res); +static void RICHED32_WM_Copy(RICHEDITSTATE * res); +static void RICHED32_WM_Paste(RICHEDITSTATE * res); +static void RICHED32_WM_Clear(RICHEDITSTATE * res); + +/* Support routines for window procedure */ +// INT RICHEDIT_GetTextRange(HWND hwnd,TEXTRANGEA *tr); +// INT RICHEDIT_GetSelText(HWND hwnd,LPSTR lpstrBuffer); /*********************************************************************** * DllMain [Internal] Initializes the internal 'RICHED32.DLL'. @@ -64,7 +207,6 @@ * Success: TRUE * Failure: FALSE */ - BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { TRACE("\n"); @@ -78,7 +220,7 @@ break; case DLL_PROCESS_DETACH: - /* unregister all common control classes */ + /* unregister this class */ RICHED32_Unregister (); HeapDestroy (RICHED32_hHeap); RICHED32_hHeap = (HANDLE)NULL; @@ -87,11 +229,6 @@ return TRUE; } -/* Support routines for window procedure */ - INT RICHEDIT_GetTextRange(HWND hwnd,TEXTRANGEA *tr); - INT RICHEDIT_GetSelText(HWND hwnd,LPSTR lpstrBuffer); - - /* * * DESCRIPTION: @@ -101,76 +238,227 @@ static LRESULT WINAPI RICHED32_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - int RTFToBuffer(char* pBuffer, int nBufferSize); - LONG newstyle = 0; - LONG style = 0; - - static HWND hwndEdit; - static HWND hwndParent; - static char* rtfBuffer; - int rtfBufferSize; - - CHARRANGE *cr; - TRACE("previous hwndEdit: %p hwndParent %p\n",hwndEdit,hwndParent); - hwndEdit = GetWindow(hwnd,GW_CHILD); - TRACE("uMsg: 0x%x hwnd: %p hwndEdit: %p\n",uMsg,hwnd,hwndEdit); + LRESULT result = 0; + + RICHEDITSTATE *res = (RICHEDITSTATE *)GetWindowLongW( hwnd, 0 ); + + if (res) RICHED32_LockBuffer(res); switch (uMsg) { - + + // Implemented messages appear first case WM_CREATE : DPRINTF_EDIT_MSG32("WM_CREATE"); - - /* remove SCROLLBARS from the current window style */ - hwndParent = ((LPCREATESTRUCTA) lParam)->hwndParent; - - newstyle = style = ((LPCREATESTRUCTA) lParam)->style; - newstyle &= ~WS_HSCROLL; - newstyle &= ~WS_VSCROLL; - newstyle &= ~ES_AUTOHSCROLL; - newstyle &= ~ES_AUTOVSCROLL; - - TRACE("previous hwndEdit: %p\n",hwndEdit); - hwndEdit = CreateWindowA ("edit", ((LPCREATESTRUCTA) lParam)->lpszName, - style, 0, 0, 0, 0, - hwnd, (HMENU) ID_EDIT, - ((LPCREATESTRUCTA) lParam)->hInstance, NULL) ; - TRACE("hwndEdit: %p hwnd: %p\n",hwndEdit,hwnd); - - SetWindowLongA(hwnd,GWL_STYLE, newstyle); - return 0 ; - + RICHED32_WM_Create(res, hwnd, (LPCREATESTRUCTA) lParam); + break; case WM_SETFOCUS : - DPRINTF_EDIT_MSG32("WM_SETFOCUS"); - SetFocus (hwndEdit) ; - return 0 ; - - case WM_SIZE : - DPRINTF_EDIT_MSG32("WM_SIZE"); - MoveWindow (hwndEdit, 0, 0, LOWORD (lParam), HIWORD (lParam), TRUE) ; - return 0 ; - - case WM_COMMAND : - DPRINTF_EDIT_MSG32("WM_COMMAND"); - switch(HIWORD(wParam)) { - case EN_CHANGE: - case EN_HSCROLL: - case EN_KILLFOCUS: - case EN_SETFOCUS: - case EN_UPDATE: - case EN_VSCROLL: - return SendMessageA(hwndParent, WM_COMMAND, - wParam, (LPARAM)(hwnd)); - - case EN_ERRSPACE: - case EN_MAXTEXT: - MessageBoxA (hwnd, "RichEdit control out of space.", - "ERROR", MB_OK | MB_ICONSTOP) ; - return 0 ; - } - - case EM_STREAMIN: - DPRINTF_EDIT_MSG32("EM_STREAMIN"); + DPRINTF_EDIT_MSG32("WM_SETFOCUS"); + RT_NOTIFY_PARENT(res, EN_SETFOCUS, "EN_SETFOCUS"); + RICHED32_CreateAndShowCaret(res); + break; + case EM_EXSETSEL: + DPRINTF_EDIT_MSG32("EM_EXSETSEL"); + CopyMemory(&(res->chrSelection), (void *) lParam, sizeof(CHARRANGE)); + TRACE("CHARRANGE(cpMin = %ld, cpMax = %ld)\n", res->chrSelection.cpMin, res->chrSelection.cpMax); + FIXME("Update paragraph\n"); + break; + case EM_SETSEL: + DPRINTF_EDIT_MSG32("EM_SETSEL"); + res->chrSelection.cpMin = wParam; + res->chrSelection.cpMax = lParam; + break; + case WM_CHAR: + { + WCHAR charW; + DPRINTF_EDIT_MSG32("WM_CHAR"); + + MultiByteToWideChar(CP_ACP, 0, (LPSTR) &wParam, 1, &charW, 1); + RICHED32_WM_Char(res, charW); + RT_NOTIFY_PARENT(res, EN_CHANGE, "EN_CHANGE"); + break; + } + case WM_KEYDOWN: + DPRINTF_EDIT_MSG32("WM_KEYDOWN"); + RichText_WM_Keydown(res, wParam, lParam); + break; + case EM_SETMODIFY: + DPRINTF_EDIT_MSG32("EM_SETMODIFY"); + if (wParam) + res->flags |= EF_MODIFIED; + else + res->flags &= ~(EF_MODIFIED | EF_UPDATE); /* reset pending updates */ + break; + case EM_GETMODIFY: + DPRINTF_EDIT_MSG32("EM_GETMODIFY Passed to edit control"); + result = ((res->flags & EF_MODIFIED) != 0); + break; + case WM_KILLFOCUS: + DPRINTF_EDIT_MSG32("WM_KILLFOCUS"); + DestroyCaret(); + RT_NOTIFY_PARENT(res, EN_KILLFOCUS, "EN_KILLFOCUS"); + return 0; + case WM_SETTEXT: + DPRINTF_EDIT_MSG32("WM_SETTEXT"); + return RICHED32_WM_SetText(res, (LPCSTR)lParam); + case EM_REPLACESEL: + DPRINTF_EDIT_MSG32("EM_REPLACESEL"); + RICHED32_EM_ReplaceSel(res, (BOOL) wParam, (LPCSTR) lParam); + return 0; + case EM_CHARFROMPOS: + DPRINTF_EDIT_MSG32("EM_CHARFROMPOS"); + return RichText_CharFromPos(res, (POINTL *)lParam); + case EM_SETPARAFORMAT: + DPRINTF_EDIT_MSG32("EM_SETPARAFORMAT"); + RichTextParagraph_SetFormat2(res->pSelection, (PARAFORMAT *) lParam); + InvalidateRect(res->hwndSelf, NULL, TRUE); + return 0; + case EM_GETPARAFORMAT: + DPRINTF_EDIT_MSG32("EM_GETPARAFORMAT"); + res->pSelection->format.cbSize = sizeof(PARAFORMAT); + res->pSelection->format.dwMask = PFM_ALIGNMENT | PFM_NUMBERING | PFM_OFFSET | PFM_OFFSETINDENT | PFM_RIGHTINDENT | PFM_RTLPARA | PFM_STARTINDENT | PFM_TABSTOPS; + CopyMemory((void *) lParam, &res->pSelection->format, sizeof(PARAFORMAT)); + FIXME("EM_GETPARAFORMAT - Do for rest of selection too\n"); + return ((PARAFORMAT *)lParam)->dwMask; + case EM_FINDTEXT: + { + FINDTEXTEXA find; + ZeroMemory(&find, sizeof(find)); + DPRINTF_EDIT_MSG32("EM_FINDTEXT"); + CopyMemory(&find, (const FINDTEXTA *) lParam, sizeof(FINDTEXTA)); + return RichText_EM_FindTextExA(res, (UINT) wParam, &find); + } + case EM_FINDTEXTEX: + DPRINTF_EDIT_MSG32("EM_FINDTEXTEX"); + return RichText_EM_FindTextExA(res, (UINT) wParam, (FINDTEXTEXA *) lParam); + + case EM_FINDTEXTEXW: + DPRINTF_EDIT_MSG32("EM_FINDTEXTEXW"); + return RichText_EM_FindTextExW(res, (UINT) wParam, (FINDTEXTEXW *) lParam); + case EM_FINDTEXTW: + { + FINDTEXTEXW find; + DPRINTF_EDIT_MSG32("EM_FINDTEXTW"); + ZeroMemory(&find, sizeof(find)); + CopyMemory(&find, (const FINDTEXTW *) lParam, sizeof(FINDTEXTW)); + return RichText_EM_FindTextExW(res, (UINT) wParam, &find); + } + case EM_EXGETSEL: + DPRINTF_EDIT_MSG32("EM_EXGETSEL"); + CopyMemory((void *)lParam, &res->chrSelection, sizeof(res->chrSelection)); + return 0; + case EM_SETREADONLY: + DPRINTF_EDIT_MSG32("EM_SETREADONLY"); + if (wParam) { + SetWindowLongW( hwnd, GWL_STYLE, + GetWindowLongW( hwnd, GWL_STYLE ) | ES_READONLY ); + res->style |= ES_READONLY; + } else { + SetWindowLongW( hwnd, GWL_STYLE, + GetWindowLongW( hwnd, GWL_STYLE ) & ~ES_READONLY ); + res->style &= ~ES_READONLY; + } + result = 1; + break; + case EM_GETSCROLLPOS: + { + SCROLLINFO si; + DPRINTF_EDIT_MSG32("EM_GETSCROLLPOS"); + si.fMask = SIF_POS; + GetScrollInfo(res->hwndSelf, SB_VERT, &si); + FIXME("GetScrollInfo returned %d. Convert this to coordinate\n", si.nPos); + return 0; + } + case EM_SETCHARFORMAT: + DPRINTF_EDIT_MSG32("EM_SETCHARFORMAT"); + RICHED32_EM_SetCharFormat2A(res, (CHARFORMAT2A *) lParam); + return 1; + case WM_SETFONT: + { + RICHTEXTSEG * pTextSeg; + DPRINTF_EDIT_MSG32("WM_SETFONT"); + pTextSeg = RichTextSeg_SkipToChar(res->pSelection->pFirstLine->pTextSeg, res->chrSelection.cpMin, NULL); + DeleteObject(pTextSeg->hSegFont); + pTextSeg->hSegFont = (HFONT) wParam; + InvalidateRect(res->hwndSelf, NULL, TRUE); + RICHED32_CreateAndShowCaret(res); + break; + } + case WM_MOUSEACTIVATE: + DPRINTF_EDIT_MSG32("WM_MOUSEACTIVATE"); + // FIXME: is handling this message needed? + SetFocus(hwnd); + result = MA_ACTIVATE; + break; + case WM_LBUTTONDOWN: + { + POINTL p; + DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN"); + p.x = LOWORD(lParam); + p.y = HIWORD(lParam); + res->chrSelection.cpMin = RichText_CharFromPos(res, &p); + res->chrSelection.cpMax = res->chrSelection.cpMin; + RICHED32_CreateAndShowCaret(res); + break; + } + case WM_CUT: + RICHED32_WM_Cut(res); +// FIXME_MSG("WM_CUT Passed to edit control"); +// return SendMessageA( hwndEdit, uMsg, wParam, lParam); + break; + case WM_COPY: +// FIXME_MSG("WM_COPY Passed to edit control"); + RICHED32_WM_Copy(res); +// return SendMessageA( hwndEdit, uMsg, wParam, lParam); + break; + case WM_PASTE: + RICHED32_WM_Paste(res); +// FIXME_MSG("WM_PASTE Passed to edit control"); +// return SendMessageA( hwndEdit, uMsg, wParam, lParam);*/ + break; + case WM_CLEAR: +// FIXME_MSG("WM_CLEAR Passed to default"); +// return DefWindowProcA( hwnd,uMsg,wParam,lParam); + RICHED32_WM_Clear(res); + break; + case WM_PAINT: + DPRINTF_EDIT_MSG32("WM_PAINT"); + return RICHED32_WM_Paint(res, wParam); + case EM_POSFROMCHAR: + DPRINTF_EDIT_MSG32("EM_POSFROMCHAR Passed to edit control"); + return RichText_EM_PosFromChar(res, wParam); + case EM_SETEVENTMASK: + { + DWORD dwOldMask = res->dwEventMask; + res->dwEventMask = (DWORD) lParam; + return dwOldMask; + } + case WM_NCDESTROY: +// DPRINTF_EDIT_MSG32("WM_NCDESTROY Passed to default"); +// return DefWindowProcA( hwnd,uMsg,wParam,lParam); + return RICHED32_WM_NCDestroy(res); + + // Not implemented + case WM_RBUTTONDOWN: + FIXME_MSG("WM_RBUTTONDOWN - stub"); + break; + case EM_GETCHARFORMAT: + FIXME_MSG("EM_GETCHARFORMAT"); + { +/* RICHTEXTSEG * pTextSeg = RichTextSeg_SkipToChar(res->pSelection, res->chrSelection.cpMin + DPRINTF_EDIT_MSG32("EM_GETCHARFORMAT"); + CopyMemory((void *) lParam, &pTextSeg->, ((CHARFORMAT *)lParam)->cbSize); + return (CHARFORMAT *)lParam)->dwMask;*/ + return 0; + } + + + // This one is half-implemented + case EM_STREAMIN: + { + static char* rtfBuffer; + int rtfBufferSize; + DPRINTF_EDIT_MSG32("EM_STREAMIN"); /* setup the RTF parser */ RTFSetEditStream(( EDITSTREAM*)lParam); @@ -187,469 +475,349 @@ if(rtfBuffer) { RTFToBuffer(rtfBuffer, rtfBufferSize); - SetWindowTextA(hwndEdit,rtfBuffer); + SetWindowTextA(res->hwndSelf,rtfBuffer); HeapFree(RICHED32_hHeap, 0,rtfBuffer); } else WARN("Not enough memory for a allocating rtfBuffer\n"); return 0; - + } /* Messages specific to Richedit controls */ case EM_AUTOURLDETECT: - DPRINTF_EDIT_MSG32("EM_AUTOURLDETECT Ignored"); + FIXME_MSG("EM_AUTOURLDETECT Ignored"); return 0; case EM_CANPASTE: - DPRINTF_EDIT_MSG32("EM_CANPASTE Ignored"); + FIXME_MSG("EM_CANPASTE Ignored"); return 0; case EM_CANREDO: - DPRINTF_EDIT_MSG32("EM_CANREDO Ignored"); + FIXME_MSG("EM_CANREDO Ignored"); return 0; case EM_DISPLAYBAND: - DPRINTF_EDIT_MSG32("EM_DISPLAYBAND Ignored"); + FIXME_MSG("EM_DISPLAYBAND Ignored"); return 0; - case EM_EXGETSEL: - DPRINTF_EDIT_MSG32("EM_EXGETSEL -> EM_GETSEL"); - cr = (VOID *) lParam; - if (hwndEdit) SendMessageA( hwndEdit, EM_GETSEL, (INT)&cr->cpMin, (INT)&cr->cpMax); - TRACE("cpMin: 0x%x cpMax: 0x%x\n",(INT)cr->cpMin,(INT)cr->cpMax); - return 0; - case EM_EXLIMITTEXT: { - DWORD limit = lParam; - DPRINTF_EDIT_MSG32("EM_EXLIMITTEXT"); - if (limit > 65534) - { - limit = 0xFFFFFFFF; - } - return SendMessageA(hwndEdit,EM_SETLIMITTEXT,limit,0); +// DWORD limit = lParam; + FIXME_MSG("EM_EXLIMITTEXT Ignored"); +// if (limit > 65534) +// { +// limit = 0xFFFFFFFF; +// } +// return SendMessageA(hwndEdit,EM_SETLIMITTEXT,limit,0); + return 0; } case EM_EXLINEFROMCHAR: - DPRINTF_EDIT_MSG32("EM_EXLINEFROMCHAR -> LINEFROMCHAR"); - if (hwndEdit) return SendMessageA( hwndEdit, EM_LINEFROMCHAR, lParam, wParam); - return 0; - - case EM_EXSETSEL: - DPRINTF_EDIT_MSG32("EM_EXSETSEL -> EM_SETSEL"); - cr = (VOID *) lParam; - if (hwndEdit) SendMessageA( hwndEdit, EM_SETSEL, cr->cpMin, cr->cpMax); - return 0; - - case EM_FINDTEXT: - DPRINTF_EDIT_MSG32("EM_FINDTEXT Ignored"); - return 0; - - case EM_FINDTEXTEX: - DPRINTF_EDIT_MSG32("EM_FINDTEXTEX Ignored"); - return 0; - - case EM_FINDTEXTEXW: - DPRINTF_EDIT_MSG32("EM_FINDTEXTEXW Ignored"); + FIXME_MSG("EM_EXLINEFROMCHAR Ignored"); return 0; - - case EM_FINDTEXTW: - DPRINTF_EDIT_MSG32("EM_FINDTEXTW Ignored"); - return 0; - case EM_FINDWORDBREAK: - DPRINTF_EDIT_MSG32("EM_FINDWORDBREAK Ignored"); + FIXME_MSG("EM_FINDWORDBREAK Ignored"); return 0; case EM_FORMATRANGE: - DPRINTF_EDIT_MSG32("EM_FORMATRANGE Ignored"); + FIXME_MSG("EM_FORMATRANGE Ignored"); return 0; case EM_GETAUTOURLDETECT: - DPRINTF_EDIT_MSG32("EM_GETAUTOURLDETECT Ignored"); + FIXME_MSG("EM_GETAUTOURLDETECT Ignored"); return 0; case EM_GETBIDIOPTIONS: - DPRINTF_EDIT_MSG32("EM_GETBIDIOPTIONS Ignored"); - return 0; - - case EM_GETCHARFORMAT: - DPRINTF_EDIT_MSG32("EM_GETCHARFORMAT Ignored"); + FIXME_MSG("EM_GETBIDIOPTIONS Ignored"); return 0; case EM_GETEDITSTYLE: - DPRINTF_EDIT_MSG32("EM_GETEDITSTYLE Ignored"); + FIXME_MSG("EM_GETEDITSTYLE Ignored"); return 0; case EM_GETEVENTMASK: - DPRINTF_EDIT_MSG32("EM_GETEVENTMASK Ignored"); + FIXME_MSG("EM_GETEVENTMASK Ignored"); return 0; case EM_GETIMECOLOR: - DPRINTF_EDIT_MSG32("EM_GETIMECOLOR Ignored"); + FIXME_MSG("EM_GETIMECOLOR Ignored"); return 0; case EM_GETIMECOMPMODE: - DPRINTF_EDIT_MSG32("EM_GETIMECOMPMODE Ignored"); + FIXME_MSG("EM_GETIMECOMPMODE Ignored"); return 0; case EM_GETIMEOPTIONS: - DPRINTF_EDIT_MSG32("EM_GETIMEOPTIONS Ignored"); + FIXME_MSG("EM_GETIMEOPTIONS Ignored"); return 0; case EM_GETLANGOPTIONS: - DPRINTF_EDIT_MSG32("STUB: EM_GETLANGOPTIONS"); + FIXME_MSG("STUB: EM_GETLANGOPTIONS"); return 0; case EM_GETOLEINTERFACE: - DPRINTF_EDIT_MSG32("EM_GETOLEINTERFACE Ignored"); + FIXME_MSG("EM_GETOLEINTERFACE Ignored"); return 0; case EM_GETOPTIONS: - DPRINTF_EDIT_MSG32("EM_GETOPTIONS Ignored"); - return 0; - - case EM_GETPARAFORMAT: - DPRINTF_EDIT_MSG32("EM_GETPARAFORMAT Ignored"); + FIXME_MSG("EM_GETOPTIONS Ignored"); return 0; case EM_GETPUNCTUATION: - DPRINTF_EDIT_MSG32("EM_GETPUNCTUATION Ignored"); + FIXME_MSG("EM_GETPUNCTUATION Ignored"); return 0; case EM_GETREDONAME: - DPRINTF_EDIT_MSG32("EM_GETREDONAME Ignored"); - return 0; - - case EM_GETSCROLLPOS: - DPRINTF_EDIT_MSG32("EM_GETSCROLLPOS Ignored"); + FIXME_MSG("EM_GETREDONAME Ignored"); return 0; case EM_GETSELTEXT: - DPRINTF_EDIT_MSG32("EM_GETSELTEXT"); - return RICHEDIT_GetSelText(hwndEdit,(void *)lParam); + FIXME_MSG("EM_GETSELTEXT Ignored"); +// return RICHEDIT_GetSelText(hwndEdit,(void *)lParam); + return 0; + case EM_GETTEXTEX: - DPRINTF_EDIT_MSG32("EM_GETTEXTEX Ignored"); + FIXME_MSG("EM_GETTEXTEX Ignored"); return 0; case EM_GETTEXTLENGTHEX: - DPRINTF_EDIT_MSG32("EM_GETTEXTLENGTHEX Ignored"); + FIXME_MSG("EM_GETTEXTLENGTHEX Ignored"); return 0; case EM_GETTEXTMODE: - DPRINTF_EDIT_MSG32("EM_GETTEXTMODE Ignored"); + FIXME_MSG("EM_GETTEXTMODE Ignored"); return 0; case EM_GETTEXTRANGE: - DPRINTF_EDIT_MSG32("EM_GETTEXTRANGE"); - return RICHEDIT_GetTextRange(hwndEdit,(TEXTRANGEA *)lParam); + FIXME_MSG("EM_GETTEXTRANGE Ignored"); +// return RICHEDIT_GetTextRange(hwndEdit,(TEXTRANGEA *)lParam); + return 0; case EM_GETTYPOGRAPHYOPTIONS: - DPRINTF_EDIT_MSG32("EM_GETTYPOGRAPHYOPTIONS Ignored"); + FIXME_MSG("EM_GETTYPOGRAPHYOPTIONS Ignored"); return 0; case EM_GETUNDONAME: - DPRINTF_EDIT_MSG32("EM_GETUNDONAME Ignored"); + FIXME_MSG("EM_GETUNDONAME Ignored"); return 0; case EM_GETWORDBREAKPROCEX: - DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROCEX Ignored"); + FIXME_MSG("EM_GETWORDBREAKPROCEX Ignored"); return 0; case EM_GETWORDWRAPMODE: - DPRINTF_EDIT_MSG32("EM_GETWORDWRAPMODE Ignored"); + FIXME_MSG("EM_GETWORDWRAPMODE Ignored"); return 0; case EM_GETZOOM: - DPRINTF_EDIT_MSG32("EM_GETZOOM Ignored"); + FIXME_MSG("EM_GETZOOM Ignored"); return 0; case EM_HIDESELECTION: - DPRINTF_EDIT_MSG32("EM_HIDESELECTION Ignored"); + FIXME_MSG("EM_HIDESELECTION Ignored"); return 0; case EM_PASTESPECIAL: - DPRINTF_EDIT_MSG32("EM_PASTESPECIAL Ignored"); + FIXME_MSG("EM_PASTESPECIAL Ignored"); return 0; case EM_RECONVERSION: - DPRINTF_EDIT_MSG32("EM_RECONVERSION Ignored"); + FIXME_MSG("EM_RECONVERSION Ignored"); return 0; case EM_REDO: - DPRINTF_EDIT_MSG32("EM_REDO Ignored"); + FIXME_MSG("EM_REDO Ignored"); return 0; case EM_REQUESTRESIZE: - DPRINTF_EDIT_MSG32("EM_REQUESTRESIZE Ignored"); + FIXME_MSG("EM_REQUESTRESIZE Ignored"); return 0; case EM_SELECTIONTYPE: - DPRINTF_EDIT_MSG32("EM_SELECTIONTYPE Ignored"); + FIXME_MSG("EM_SELECTIONTYPE Ignored"); return 0; case EM_SETBIDIOPTIONS: - DPRINTF_EDIT_MSG32("EM_SETBIDIOPTIONS Ignored"); + FIXME_MSG("EM_SETBIDIOPTIONS Ignored"); return 0; case EM_SETBKGNDCOLOR: - DPRINTF_EDIT_MSG32("EM_SETBKGNDCOLOR Ignored"); - return 0; - - case EM_SETCHARFORMAT: - DPRINTF_EDIT_MSG32("EM_SETCHARFORMAT Ignored"); + FIXME_MSG("EM_SETBKGNDCOLOR Ignored"); return 0; case EM_SETEDITSTYLE: - DPRINTF_EDIT_MSG32("EM_SETEDITSTYLE Ignored"); - return 0; - - case EM_SETEVENTMASK: - DPRINTF_EDIT_MSG32("EM_SETEVENTMASK Ignored"); + FIXME_MSG("EM_SETEDITSTYLE Ignored"); return 0; case EM_SETFONTSIZE: - DPRINTF_EDIT_MSG32("EM_SETFONTSIZE Ignored"); + FIXME_MSG("EM_SETFONTSIZE Ignored"); return 0; case EM_SETIMECOLOR: - DPRINTF_EDIT_MSG32("EM_SETIMECOLO Ignored"); + FIXME_MSG("EM_SETIMECOLO Ignored"); return 0; case EM_SETIMEOPTIONS: - DPRINTF_EDIT_MSG32("EM_SETIMEOPTIONS Ignored"); + FIXME_MSG("EM_SETIMEOPTIONS Ignored"); return 0; case EM_SETLANGOPTIONS: - DPRINTF_EDIT_MSG32("EM_SETLANGOPTIONS Ignored"); + FIXME_MSG("EM_SETLANGOPTIONS Ignored"); return 0; case EM_SETOLECALLBACK: - DPRINTF_EDIT_MSG32("EM_SETOLECALLBACK Ignored"); + FIXME_MSG("EM_SETOLECALLBACK Ignored"); return 0; case EM_SETOPTIONS: - DPRINTF_EDIT_MSG32("EM_SETOPTIONS Ignored"); + FIXME_MSG("EM_SETOPTIONS Ignored"); return 0; case EM_SETPALETTE: - DPRINTF_EDIT_MSG32("EM_SETPALETTE Ignored"); - return 0; - - case EM_SETPARAFORMAT: - DPRINTF_EDIT_MSG32("EM_SETPARAFORMAT Ignored"); + FIXME_MSG("EM_SETPALETTE Ignored"); return 0; case EM_SETPUNCTUATION: - DPRINTF_EDIT_MSG32("EM_SETPUNCTUATION Ignored"); + FIXME_MSG("EM_SETPUNCTUATION Ignored"); return 0; case EM_SETSCROLLPOS: - DPRINTF_EDIT_MSG32("EM_SETSCROLLPOS Ignored"); + FIXME_MSG("EM_SETSCROLLPOS Ignored"); return 0; case EM_SETTARGETDEVICE: - DPRINTF_EDIT_MSG32("EM_SETTARGETDEVICE Ignored"); + FIXME_MSG("EM_SETTARGETDEVICE Ignored"); return 0; case EM_SETTEXTEX: - DPRINTF_EDIT_MSG32("EM_SETTEXTEX Ignored"); + FIXME_MSG("EM_SETTEXTEX Ignored"); return 0; case EM_SETTEXTMODE: - DPRINTF_EDIT_MSG32("EM_SETTEXTMODE Ignored"); + FIXME_MSG("EM_SETTEXTMODE Ignored"); return 0; case EM_SETTYPOGRAPHYOPTIONS: - DPRINTF_EDIT_MSG32("EM_SETTYPOGRAPHYOPTIONS Ignored"); + FIXME_MSG("EM_SETTYPOGRAPHYOPTIONS Ignored"); return 0; case EM_SETUNDOLIMIT: - DPRINTF_EDIT_MSG32("EM_SETUNDOLIMIT Ignored"); + FIXME_MSG("EM_SETUNDOLIMIT Ignored"); return 0; case EM_SETWORDBREAKPROCEX: - DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROCEX Ignored"); + FIXME_MSG("EM_SETWORDBREAKPROCEX Ignored"); return 0; case EM_SETWORDWRAPMODE: - DPRINTF_EDIT_MSG32("EM_SETWORDWRAPMODE Ignored"); + FIXME_MSG("EM_SETWORDWRAPMODE Ignored"); return 0; case EM_SETZOOM: - DPRINTF_EDIT_MSG32("EM_SETZOOM Ignored"); + FIXME_MSG("EM_SETZOOM Ignored"); return 0; case EM_SHOWSCROLLBAR: - DPRINTF_EDIT_MSG32("EM_SHOWSCROLLBAR Ignored"); + FIXME_MSG("EM_SHOWSCROLLBAR Ignored"); return 0; case EM_STOPGROUPTYPING: - DPRINTF_EDIT_MSG32("EM_STOPGROUPTYPING Ignored"); + FIXME_MSG("EM_STOPGROUPTYPING Ignored"); return 0; case EM_STREAMOUT: - DPRINTF_EDIT_MSG32("EM_STREAMOUT Ignored"); + FIXME_MSG("EM_STREAMOUT Ignored"); return 0; -/* Messages dispatched to the edit control */ +/* Messages previously dispatched to the edit control */ case EM_CANUNDO: - DPRINTF_EDIT_MSG32("EM_CANUNDO Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_CHARFROMPOS: - DPRINTF_EDIT_MSG32("EM_CHARFROMPOS Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_CANUNDO Ignored"); + return 0; case EM_EMPTYUNDOBUFFER: - DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_FMTLINES: - DPRINTF_EDIT_MSG32("EM_FMTLINES Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_EMPTYUNDOBUFFER Ignored"); + return 0; case EM_GETFIRSTVISIBLELINE: - DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_GETHANDLE: - DPRINTF_EDIT_MSG32("EM_GETHANDLE Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_GETFIRSTVISIBLELINE Ignored"); + return 0; /* case EM_GETIMESTATUS:*/ case EM_GETLIMITTEXT: - DPRINTF_EDIT_MSG32("EM_GETLIMITTEXT Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_GETLIMITTEXT Ignored"); + return 0; case EM_GETLINE: - DPRINTF_EDIT_MSG32("EM_GETLINE Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_GETLINE Ignored"); + return 0; case EM_GETLINECOUNT: - DPRINTF_EDIT_MSG32("EM_GETLINECOUNT Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_GETMARGINS: - DPRINTF_EDIT_MSG32("EM_GETMARGINS Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_GETMODIFY: - DPRINTF_EDIT_MSG32("EM_GETMODIFY Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_GETPASSWORDCHAR: - DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_GETLINECOUNT Ignored"); + return 0; case EM_GETRECT: - DPRINTF_EDIT_MSG32("EM_GETRECT Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_GETRECT Ignored"); + return 0; case EM_GETSEL: - DPRINTF_EDIT_MSG32("EM_GETSEL Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_GETSEL Ignored"); + return 0; case EM_GETTHUMB: - DPRINTF_EDIT_MSG32("EM_GETTHUMB Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_GETTHUMB Ignored"); + return 0; case EM_GETWORDBREAKPROC: - DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_GETWORDBREAKPROC Ignored"); + return 0; case EM_LINEFROMCHAR: - DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_LINEFROMCHAR Ignored"); + return 0; case EM_LINEINDEX: - DPRINTF_EDIT_MSG32("EM_LINEINDEX Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_LINEINDEX Ignored"); + return 0; case EM_LINELENGTH: - DPRINTF_EDIT_MSG32("EM_LINELENGTH Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_LINELENGTH Ignored"); + return 0; case EM_LINESCROLL: - DPRINTF_EDIT_MSG32("EM_LINESCROLL Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_POSFROMCHAR: - DPRINTF_EDIT_MSG32("EM_POSFROMCHAR Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_REPLACESEL: - DPRINTF_EDIT_MSG32("case EM_REPLACESEL Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_LINESCROLL Ignored"); + return 0; case EM_SCROLL: - DPRINTF_EDIT_MSG32("case EM_SCROLL Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_SCROLL Ignored"); + return 0; case EM_SCROLLCARET: - DPRINTF_EDIT_MSG32("EM_SCROLLCARET Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_SETHANDLE: - DPRINTF_EDIT_MSG32("EM_SETHANDLE Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_SCROLLCARET Ignored"); + return 0; /* case EM_SETIMESTATUS:*/ case EM_SETLIMITTEXT: - DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_SETMARGINS: - DPRINTF_EDIT_MSG32("case EM_SETMARGINS Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_SETMODIFY: - DPRINTF_EDIT_MSG32("EM_SETMODIFY Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_SETPASSWORDCHAR: - DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_SETREADONLY: - DPRINTF_EDIT_MSG32("EM_SETREADONLY Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_SETLIMITTEXT Ignored"); + return 0; case EM_SETRECT: - DPRINTF_EDIT_MSG32("EM_SETRECT Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_SETRECTNP: - DPRINTF_EDIT_MSG32("EM_SETRECTNP Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_SETSEL: - DPRINTF_EDIT_MSG32("EM_SETSEL Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case EM_SETTABSTOPS: - DPRINTF_EDIT_MSG32("EM_SETTABSTOPS Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_SETRECT Ignored"); + return 0; case EM_SETWORDBREAKPROC: - DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("EM_SETWORDBREAKPROC Ignored"); + return 0; case EM_UNDO: - DPRINTF_EDIT_MSG32("EM_UNDO Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - + FIXME_MSG("EM_UNDO Ignored"); + return 0; case WM_STYLECHANGING: - DPRINTF_EDIT_MSG32("WM_STYLECHANGING Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("WM_STYLECHANGING Ignored"); + return 0; case WM_STYLECHANGED: - DPRINTF_EDIT_MSG32("WM_STYLECHANGED Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case WM_NCCALCSIZE: - DPRINTF_EDIT_MSG32("WM_NCCALCSIZE Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("WM_STYLECHANGED Ignored"); + return 0; case WM_GETTEXT: - DPRINTF_EDIT_MSG32("WM_GETTEXT Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("WM_GETTEXT Ignored"); + return 0; case WM_GETTEXTLENGTH: - DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case WM_SETTEXT: - DPRINTF_EDIT_MSG32("WM_SETTEXT Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case WM_CUT: - DPRINTF_EDIT_MSG32("WM_CUT Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case WM_COPY: - DPRINTF_EDIT_MSG32("WM_COPY Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); - case WM_PASTE: - DPRINTF_EDIT_MSG32("WM_PASTE Passed to edit control"); - return SendMessageA( hwndEdit, uMsg, wParam, lParam); + FIXME_MSG("WM_GETTEXTLENGTH Ignored"); + return 0; /* Messages passed to default handler. */ case WM_NCPAINT: DPRINTF_EDIT_MSG32("WM_NCPAINT Passed to default"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); - case WM_PAINT: - DPRINTF_EDIT_MSG32("WM_PAINT Passed to default"); - return DefWindowProcA( hwnd,uMsg,wParam,lParam); case WM_ERASEBKGND: DPRINTF_EDIT_MSG32("WM_ERASEBKGND Passed to default"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); - case WM_KILLFOCUS: - DPRINTF_EDIT_MSG32("WM_KILLFOCUS Passed to default"); - return DefWindowProcA( hwnd,uMsg,wParam,lParam); case WM_DESTROY: DPRINTF_EDIT_MSG32("WM_DESTROY Passed to default"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); +// return RICHED32_WM_Destroy(res); case WM_CHILDACTIVATE: DPRINTF_EDIT_MSG32("WM_CHILDACTIVATE Passed to default"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); @@ -666,8 +834,9 @@ case WM_CTLCOLOREDIT: DPRINTF_EDIT_MSG32("WM_CTLCOLOREDIT Passed to default"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); - case WM_SETCURSOR: - DPRINTF_EDIT_MSG32("WM_SETCURSOR Passed to default"); + case WM_SETCURSOR: + // FIXME: if cursor is in the margin show the cursor the opposite way round + // FIXME: otherwise show IBEAM return DefWindowProcA( hwnd,uMsg,wParam,lParam); case WM_MOVE: DPRINTF_EDIT_MSG32("WM_MOVE Passed to default"); @@ -676,48 +845,57 @@ DPRINTF_EDIT_MSG32("WM_SHOWWINDOW Passed to default"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); case WM_NCCREATE: - DPRINTF_EDIT_MSG32("WM_NCCREATE Passed to default"); - return DefWindowProcA( hwnd,uMsg,wParam,lParam); +// DPRINTF_EDIT_MSG32("WM_NCCREATE Passed to default"); +// return DefWindowProcA( hwnd,uMsg,wParam,lParam); + return RICHED32_NCCreate(hwnd, (LPCREATESTRUCTA) lParam); case WM_PARENTNOTIFY: DPRINTF_EDIT_MSG32("WM_PARENTNOTIFY Passed to default"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); case WM_SETREDRAW: DPRINTF_EDIT_MSG32("WM_SETREDRAW Passed to default"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); - case WM_NCDESTROY: - DPRINTF_EDIT_MSG32("WM_NCDESTROY Passed to default"); - return DefWindowProcA( hwnd,uMsg,wParam,lParam); - case WM_NCHITTEST: - DPRINTF_EDIT_MSG32("WM_NCHITTEST Passed to default"); - return DefWindowProcA( hwnd,uMsg,wParam,lParam); - case WM_CTLCOLORSTATIC: +/* case WM_CTLCOLORSTATIC: DPRINTF_EDIT_MSG32("WM_CTLCOLORSTATIC Passed to default"); - return DefWindowProcA( hwnd,uMsg,wParam,lParam); - case WM_NCMOUSEMOVE: - DPRINTF_EDIT_MSG32("WM_NCMOUSEMOVE Passed to default"); - return DefWindowProcA( hwnd,uMsg,wParam,lParam); - case WM_CLEAR: - DPRINTF_EDIT_MSG32("WM_CLEAR Passed to default"); - return DefWindowProcA( hwnd,uMsg,wParam,lParam); + return DefWindowProcA( hwnd,uMsg,wParam,lParam);*/ + case WM_VSCROLL: + FIXME_MSG("WM_VSCROLL - stub"); + RT_NOTIFY_PARENT(res, EN_VSCROLL, "EN_VSCROLL"); + return 0; + case WM_HSCROLL: + FIXME_MSG("WM_HSCROLL - stub"); + RT_NOTIFY_PARENT(res, EN_HSCROLL, "EN_VSCROLL"); + return 0; + /* * used by IE in the EULA box */ case WM_ALTTABACTIVE: - DPRINTF_EDIT_MSG32("WM_ALTTABACTIVE"); + FIXME_MSG("WM_ALTTABACTIVE"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); case WM_GETDLGCODE: - DPRINTF_EDIT_MSG32("WM_GETDLGCODE"); + FIXME_MSG("WM_GETDLGCODE"); return DefWindowProcA( hwnd,uMsg,wParam,lParam); - case WM_SETFONT: - DPRINTF_EDIT_MSG32("WM_SETFONT"); - return DefWindowProcA( hwnd,uMsg,wParam,lParam); - + + // Not supported in RichEdit + case EM_FMTLINES: + case EM_GETHANDLE: + case EM_GETMARGINS: + case EM_GETPASSWORDCHAR: + case EM_SETHANDLE: + case EM_SETMARGINS: + case EM_SETPASSWORDCHAR: + case EM_SETRECTNP: + case EM_SETTABSTOPS: + case WM_CTLCOLOR: + case WM_GETFONT: + FIXME_MSG("Edit message not supported - use a RichEdit equivalent"); + return 0; + + default: + return DefWindowProcA(hwnd, uMsg, wParam, lParam); } - FIXME("Unknown message 0x%x Passed to default hwnd=%p, wParam=%08x, lParam=%08x\n", - uMsg, hwnd, (UINT)wParam, (UINT)lParam); - - return DefWindowProcA( hwnd,uMsg,wParam,lParam); + return result; } /*********************************************************************** @@ -768,18 +946,18 @@ { WNDCLASSA wndClass; - TRACE("\n"); + TRACE("()\n"); ZeroMemory(&wndClass, sizeof(WNDCLASSA)); wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; wndClass.lpfnWndProc = (WNDPROC)RICHED32_WindowProc; wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = 0; /*(sizeof(RICHED32_INFO *);*/ - wndClass.hCursor = LoadCursorA(0, IDC_ARROWA); + wndClass.cbWndExtra = sizeof(RICHEDITSTATE *); + wndClass.hCursor = LoadCursorW(0, IDC_IBEAMW); wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wndClass.lpszClassName = RICHEDIT_CLASS10A; /* WC_RICHED32A; */ + wndClass.lpszClassName = RICHEDIT_CLASS; - RegisterClassA (&wndClass); + RegisterClassA(&wndClass); } /*** @@ -794,11 +972,16 @@ */ VOID RICHED32_Unregister(void) { - TRACE("\n"); + TRACE("()\n"); UnregisterClassA(RICHEDIT_CLASS, NULL); } - + +/* INT RICHEDIT_GetTextRange(HWND hwnd,TEXTRANGEA *tr) { UINT alloc_size, text_size, range_size; @@ -821,13 +1004,931 @@ HeapFree(GetProcessHeap(), 0, text); return range_size; -} +}*/ -INT RICHEDIT_GetSelText(HWND hwnd,LPSTR lpstrBuffer) +/*INT RICHEDIT_GetSelText(HWND hwnd,LPSTR lpstrBuffer) { TEXTRANGEA textrange; textrange.lpstrText = lpstrBuffer; SendMessageA(hwnd,EM_GETSEL,(INT)&textrange.chrg.cpMin,(INT)&textrange.chrg.cpMax); return RICHEDIT_GetTextRange(hwnd,&textrange); +}*/ + +static LRESULT RICHED32_WM_Paint(RICHEDITSTATE * res, WPARAM wParam) +{ + PAINTSTRUCT ps; + PARAGRAPH * pParagraph; + HDC hdc; + TRACE("(%p, %d)\n", res, wParam); + if (!wParam) + hdc = BeginPaint(res->hwndSelf, &ps); + else + hdc = (HDC) wParam; + + for (pParagraph = res->pFirstParagraph; pParagraph; pParagraph = pParagraph->pNext) + { + // FIXME: make work for multiple paragraphs + RichTextParagraph_Draw(pParagraph, hdc, 0, 0, 0, NULL); + } + + if (!wParam) + EndPaint(res->hwndSelf, &ps); + return 1; +} + +static LRESULT RICHED32_NCCreate(HWND hwnd, LPCREATESTRUCTA lpcs) +{ + RICHEDITSTATE * res; + CHARFORMAT2W chf; + if (!(res = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*res)))) + return FALSE; + SetWindowLongW( hwnd, 0, (LONG)res ); + + /* + * Note: since the RICHEDITSTATE has not been fully initialized yet, + * we can't use any API calls that may send + * WM_XXX messages before WM_NCCREATE is completed. + */ + +// res->is_unicode = unicode; + res->style = lpcs->style; + +// res->bEnableState = !(res->style & WS_DISABLED); + + res->hwndSelf = hwnd; + /* Save parent, which will be notified by EN_* messages */ + res->hwndParent = lpcs->hwndParent; + + res->pFirstParagraph = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARAGRAPH)); + res->pFirstParagraph->pFirstLine = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF)); + res->pFirstParagraph->pFirstLine->pTextSeg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RICHTEXTSEG)); + res->pFirstParagraph->wszBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR)); + res->pFirstParagraph->pFirstLine->pTextSeg->pText = res->pFirstParagraph->wszBuffer; + res->pSelection = res->pFirstParagraph; + res->chrSelection.cpMin = 0; + res->chrSelection.cpMax = 0; + res->dwEventMask = ENM_NONE; + + ZeroMemory(&chf, sizeof(chf)); + chf.cbSize = sizeof(chf); + res->pFirstParagraph->pFirstLine->pTextSeg->hSegFont = RichText_CHARFORMAT2ToHFONT(&chf); + return 1; +} + +static void RICHED32_WM_Create(RICHEDITSTATE * res, HWND hwnd, LPCREATESTRUCTA lpcs) +{ + TRACE("(%p, %p)\n", res, lpcs); + res->hwndParent = lpcs->hwndParent; + RichText_BuildLineDefs(res, res->pFirstParagraph); + RICHED32_UpdateScrollInfo(res); +} + +/*static int RichTextLine_GetMaxHeight(LINEDEF * pLine, int currentMax) +{ + if (pLine->next) + return RichTextLine_GetMaxHeight(pLine->next, max(currentMax, pLine->cachedHeight)); + else + return max(currentMax, pLine->cachedHeight); +}*/ + +/*static int RichTextLine_GetMaxWidth(LINEDEF * pLine, int currentMax) +{ + if (pLine->next) + return RichTextLine_GetMaxWidth(pLine->next, max(currentMax, pLine->cachedWidth)); + else + return max(currentMax, pLine->cachedHeight); +}*/ + +static void RichTextSeg_Draw(RICHTEXTSEG * textSeg, HDC hDC, int x, int y, int index, int charCount, int nTabPositions, int * lpnTabStopPositions) +{ +// if (!textSeg->pText) +// return; + if (charCount == -1) + charCount = textSeg->length - index; +// TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", textSeg, hDC, x, y, charCount, nTabPositions, lpnTabStopPositions); + TRACE("Drawing: %d, %s\n", charCount, debugstr_w(textSeg->pText + index)); +// else if (charCount + index > textSeg->length + SelectObject(hDC, textSeg->hSegFont); + SetTextColor(hDC, textSeg->extras.crText); +// SetBkColor(hDC, textSeg->extras.crText); + TabbedTextOutW(hDC, x, y, textSeg->pText + index, charCount, nTabPositions, lpnTabStopPositions, 0); +} + +static DWORD RichTextSeg_GetExtent(RICHTEXTSEG * pTextSeg, HDC hDC, int index, int charCount, int nTabPositions, int * lpnTabStopPositions) +{ + TRACE("(%p, %p, %d, %d, %d, %p)\n", pTextSeg, hDC, index, charCount, nTabPositions, lpnTabStopPositions); + if (!pTextSeg->pText) + return 0; + if (charCount == -1) + charCount = pTextSeg->length - index; + SelectObject(hDC, pTextSeg->hSegFont); + if (charCount == 0) + { + WCHAR str[] = {'0', '\0'}; + return MAKELONG(0, HIWORD(GetTabbedTextExtentW(hDC, str, 1, nTabPositions, lpnTabStopPositions))); + } + else + return GetTabbedTextExtentW(hDC, pTextSeg->pText + index, charCount, nTabPositions, lpnTabStopPositions); +} + +static DWORD RichTextLine_Draw(LINEDEF * pLine, HDC hDC, int startx, int starty, int nTabPositions, int * lpnTabStopPositions) +{ + DWORD extent; + int nextx = startx; + int nexty = starty; + RICHTEXTSEG * pTextSeg = pLine->pTextSeg; + int remaining = pLine->length - 1; + BOOL first = TRUE; +// TRACE("(%p, %p, %d, %d, %d, %p)\n", pLine, hDC, startx, starty, nTabPositions, lpnTabStopPositions); + while(pTextSeg) + { + if (remaining < pTextSeg->length) + { + extent = RichTextSeg_GetExtent(pTextSeg, hDC, first ? pLine->startIndex : 0, remaining, nTabPositions, lpnTabStopPositions); + RichTextSeg_Draw(pTextSeg, hDC, nextx, nexty, first ? pLine->startIndex : 0, remaining, nTabPositions, lpnTabStopPositions); + nextx += LOWORD(extent); + break; + } + else + { + extent = RichTextSeg_GetExtent(pTextSeg, hDC, first ? pLine->startIndex : 0, -1, nTabPositions, lpnTabStopPositions); + RichTextSeg_Draw(pTextSeg, hDC, nextx, nexty, first ? pLine->startIndex : 0, -1, nTabPositions, lpnTabStopPositions); + nextx += LOWORD(extent); + remaining -= pTextSeg->length; + pTextSeg = pTextSeg->pNextSeg; + } + first = FALSE; + } + nexty += pLine->cachedHeight; + pLine->cachedYPos = nexty; + pLine->cachedWidth = nextx - startx; +// TRACE("nexty: %d, nextx: %d\n", nexty, nextx); + return MAKELONG(nextx, nexty); +} + +static DWORD RichTextParagraph_Draw(PARAGRAPH * pParagraph, HDC hDC, int startx, int starty, int nTabPositions, int * lpnTabStopPositions) +{ + DWORD extent; + int nextx = startx; + int nexty = starty; + LINEDEF * pLine; +// TRACE("(%p, %p, %d, %d, %d, %p)\n", pParagraph, hDC, startx, starty, nTabPositions, lpnTabStopPositions); + for (pLine = pParagraph->pFirstLine; pLine; pLine = pLine->next) + { + extent = RichTextLine_Draw(pLine, hDC, nextx, nexty, nTabPositions, lpnTabStopPositions); + pParagraph->cachedHeight = HIWORD(extent) - nexty; + nexty = HIWORD(extent); + } + return MAKELONG(nextx, nexty); +} + +static HFONT RichText_CHARFORMAT2ToHFONT(CHARFORMAT2W * pFormat) +{ + LOGFONTW lf; + + if (pFormat->dwMask & CFM_CHARSET) + lf.lfCharSet = pFormat->bCharSet; + else + lf.lfCharSet = '\0'; + + if (pFormat->dwMask & CFM_FACE) + lstrcpyW(lf.lfFaceName, pFormat->szFaceName); + else + *lf.lfFaceName = '\0'; + + if (pFormat->dwMask & CFM_OFFSET) + ; // ignore + + if (pFormat->dwMask & CFM_SIZE) + lf.lfHeight = pFormat->yHeight; + else + lf.lfHeight = 0; + + if (pFormat->dwMask & CFM_UNDERLINE) + lf.lfUnderline = (pFormat->bUnderlineType != CFU_UNDERLINENONE); + else + lf.lfUnderline = FALSE; + + if (pFormat->dwMask & CFM_WEIGHT) + lf.lfWeight = pFormat->wWeight; + else + lf.lfWeight = FW_DONTCARE; + + if (!(pFormat->dwMask & CFM_BOLD)) + pFormat->dwEffects &= ~CFE_BOLD; + if (!(pFormat->dwMask & CFM_DISABLED)) + pFormat->dwEffects &= ~CFE_DISABLED; + if (!(pFormat->dwMask & CFM_ITALIC)) + pFormat->dwEffects &= ~CFE_ITALIC; + if (!(pFormat->dwMask & CFM_LINK)) + pFormat->dwEffects &= ~CFE_LINK; + if (!(pFormat->dwMask & CFM_PROTECTED)) + pFormat->dwEffects &= ~CFE_PROTECTED; + if (!(pFormat->dwMask & CFM_REVISED)) + pFormat->dwEffects &= ~CFE_REVISED; + if (!(pFormat->dwMask & (CFM_SUBSCRIPT | CFM_SUPERSCRIPT))) + pFormat->dwEffects &= (~CFE_SUBSCRIPT & ~CFE_SUPERSCRIPT); + if (!(pFormat->dwMask & CFM_UNDERLINE)) + pFormat->dwEffects &= ~CFE_UNDERLINE; + + if (pFormat->dwEffects & CFE_BOLD) + lf.lfWeight = FW_BOLD; + lf.lfItalic = (pFormat->dwEffects & CFE_ITALIC); + lf.lfUnderline = (pFormat->dwEffects & CFE_UNDERLINE); + lf.lfOrientation = 0; + lf.lfEscapement = 0; + + return CreateFontIndirectW(&lf); +} + +static void RichText_ReleaseHFONT(HFONT hFont) +{ + DeleteObject(hFont); +} + +static void RichText_ReplaceSel(RICHEDITSTATE * res, LPWSTR wszInsertion) +{ + // FIXME: cope with multiple paragraphs + PARAGRAPH * pPara = res->pSelection; + LONG cpMin = res->chrSelection.cpMin; + LONG cpMax = res->chrSelection.cpMax; + LONG offset; + LONG lenInsertion = lstrlenW(wszInsertion); + LONG lenNew; + RICHTEXTSEG * pTextSeg; + + // Fix selection parameters if necessary + TRACE("cpMin = %ld, cpMax = %ld\n", cpMin, cpMax); + if (res->chrSelection.cpMin < 0) + { + res->chrSelection.cpMin = 0; + cpMin = 0; + } + if (res->chrSelection.cpMax < 0) + { + res->chrSelection.cpMax = 0; + cpMax = 0; + } + if (cpMin != cpMax && cpMin > pPara->uBufferSize && cpMax > pPara->uBufferSize) + { + res->chrSelection.cpMin = res->chrSelection.cpMax; + cpMin = cpMax; + } + + lenNew = pPara->uBufferSize + lenInsertion - (cpMax - cpMin); + + TRACE("(%p, %s)\n", res, debugstr_w(wszInsertion)); + + if (lenNew < 0) + return; + +// TRACE("Before: %s\n", debugstr_w(pPara->wszBuffer)); + + if (lenNew + 1 > pPara->uBufferLimit) + { + // Over our limit so make a new buffer + LPWSTR wszNewText = HeapAlloc(GetProcessHeap(), 0, (lenNew + 1) * sizeof(WCHAR)); + lstrcpyW(wszNewText, pPara->wszBuffer); + // Change all RICHTEXTSEGs over to new buffer + for (pTextSeg = pPara->pFirstLine->pTextSeg; pTextSeg; pTextSeg = pTextSeg->pNextSeg) + { + pTextSeg->pText = pTextSeg->pText - pPara->wszBuffer + wszNewText; + } + HeapFree(GetProcessHeap(), 0, pPara->wszBuffer); + pPara->wszBuffer = wszNewText; + pPara->uBufferLimit = lenNew + 1; +/* if (pPara->uBufferSize == 0) + pPara->uBufferSize = 1;*/ + } + + // Move everything up after the insertion point to make way for insertion text + for (offset = pPara->uBufferSize - 1 - cpMax; offset >= 0; offset--) + pPara->wszBuffer[offset + cpMax + 1] = pPara->wszBuffer[offset + cpMin]; + // Copy insertion text into buffer +// TRACE("Middle: %s, uBufferSize: %ld\n", debugstr_w(pPara->wszBuffer), pPara->uBufferSize); + for (offset = 0; offset < lenInsertion; offset++) + pPara->wszBuffer[((cpMin >= pPara->uBufferSize) ? pPara->uBufferSize : cpMin) + offset] = wszInsertion[offset]; + // Clean up + pPara->wszBuffer[lenNew] = '\0'; + pPara->uBufferSize = lenNew; + + // Find where we have to start updating the text segs + pTextSeg = RichTextSeg_SkipToChar(pPara->pFirstLine->pTextSeg, cpMin, NULL); + TRACE("Changing: %ld, %s\n", pTextSeg->length + lenInsertion - (cpMax - cpMin), debugstr_w(pTextSeg->pText)); + pTextSeg->length += lenInsertion - (cpMax - cpMin); + pTextSeg = pTextSeg->pNextSeg; + + // Update the text segs so that they are still pointing to the same chars + while (pTextSeg) + { + pTextSeg->pText += lenInsertion; + pTextSeg = pTextSeg->pNextSeg; + } + + TRACE("After: %s\n", debugstr_w(pPara->wszBuffer)); + RichText_BuildLineDefs(res, pPara); + res->chrSelection.cpMin = cpMin + lenInsertion; + res->chrSelection.cpMax = cpMin + lenInsertion; + RICHED32_UpdateScrollInfo(res); + RICHED32_CreateAndShowCaret(res); +} + +static void RichText_BuildLineDefs(RICHEDITSTATE * res, PARAGRAPH * para) +{ + LPWSTR currentPosition; + LPWSTR previousPosition; + LINEDEF * currentLine; + LINEDEF * previousLine = NULL; + RICHTEXTSEG * currentTextSeg; + RICHTEXTSEG * tempSeg; + DWORD extent; + int index; + HDC dc = GetDC(res->hwndSelf); + + currentLine = para->pFirstLine; + currentTextSeg = currentLine->pTextSeg; + + index = 0; + currentPosition = previousPosition = currentTextSeg->pText; + while (*currentPosition) + { + if (*currentPosition == '\n' || *currentPosition == '\r') + { + if (!currentLine->next) + currentLine->next = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF)); + currentLine->length = (int)(currentPosition - previousPosition + 1); + currentLine->next->pTextSeg = currentTextSeg; + extent = RichTextSeg_GetExtent(currentLine->pTextSeg, dc, currentLine->startIndex, -1, res->nTabPositions, res->lpnTabStopPositions); + currentLine->cachedWidth += LOWORD(extent); + currentLine->cachedHeight = HIWORD(extent); + currentLine->cachedYPos = (previousLine ? previousLine->cachedYPos : 0) + currentLine->cachedHeight; + TRACE("Building: %d, %s\n", currentLine->length, debugstr_w(currentLine->pTextSeg->pText)); + previousLine = currentLine; + currentLine = currentLine->next; + if (*currentPosition == '\r' && *(currentPosition + 1) == '\n') + { + currentPosition++; + index++; + } + // update these for what index and currentPosition *will* be next time round + currentLine->startIndex = index + 1; + previousPosition = currentPosition + 1; + } + if (index >= currentTextSeg->length) + { + extent = RichTextSeg_GetExtent(currentLine->pTextSeg, dc, 0, -1, res->nTabPositions, res->lpnTabStopPositions); + currentLine->cachedHeight = max(HIWORD(extent), currentLine->cachedHeight); + currentLine->cachedWidth += LOWORD(extent); + currentTextSeg = currentTextSeg->pNextSeg; + index = 0; + } + if (!currentTextSeg) + { + currentLine->length = index; + extent = RichTextSeg_GetExtent(currentLine->pTextSeg, dc, currentLine->startIndex, -1, res->nTabPositions, res->lpnTabStopPositions); + currentLine->cachedWidth += LOWORD(extent); + currentLine->cachedHeight = max(HIWORD(extent), currentLine->cachedHeight); + currentLine->cachedYPos = (previousLine ? previousLine->cachedYPos : 0) + currentLine->cachedHeight; + break; + } + if (currentTextSeg->pNextSeg && currentTextSeg->pNextSeg->length < 0) + { + tempSeg = currentTextSeg->pNextSeg; + currentTextSeg->pNextSeg = tempSeg->pNextSeg; + HeapFree(GetProcessHeap(), 0, tempSeg); + } + currentPosition++; + index++; + } + extent = RichTextSeg_GetExtent(currentLine->pTextSeg, dc, currentLine->startIndex, -1, res->nTabPositions, res->lpnTabStopPositions); + currentLine->cachedWidth += LOWORD(extent); + currentLine->cachedHeight = max(HIWORD(extent), currentLine->cachedHeight); + currentLine->cachedYPos = (previousLine ? previousLine->cachedYPos : 0) + currentLine->cachedHeight; + currentLine->length = (int)(currentPosition - previousPosition + 1); + previousLine = currentLine; + currentLine = currentLine->next; + previousLine->next = NULL; + while (currentLine) + { + previousLine = currentLine; + currentLine = currentLine->next; + HeapFree(GetProcessHeap(), 0, previousLine); + } + ReleaseDC(res->hwndSelf, dc); +} + +static void RICHED32_LockBuffer(RICHEDITSTATE * res) +{ +// TRACE("(%p)\n", res); +} + +static LRESULT RICHED32_WM_NCDestroy(RICHEDITSTATE *res) +{ +// HINSTANCE hInstance = (HINSTANCE)GetWindowLongW( res->hwndSelf, GWL_HINSTANCE ); + PARAGRAPH * pParagraph, * pParagraphNext; + LINEDEF * pLine, * pLineNext; + RICHTEXTSEG * pText, * pTextNext; + + TRACE("(%p)\n", res); +/* if (res->hloc32W) { + while (LocalUnlock(es->hloc32W)) ; + LocalFree(es->hloc32W); + } + if (es->hloc32A) { + while (LocalUnlock(es->hloc32A)) ; + LocalFree(es->hloc32A); + } + if (es->hloc16) { + while (LOCAL_Unlock(hInstance, es->hloc16)) ; + LOCAL_Free(hInstance, es->hloc16); + }*/ + + for (pParagraph = res->pFirstParagraph; pParagraph; pParagraph = pParagraphNext) + { + pParagraphNext = pParagraph->pNext; + for (pText = pParagraph->pFirstLine->pTextSeg; pText; pText = pTextNext) + { + pTextNext = pText->pNextSeg; + RichText_ReleaseHFONT(pText->hSegFont); + HeapFree(GetProcessHeap(), 0, pText); + } + for (pLine = pParagraph->pFirstLine; pLine; pLine = pLineNext) + { + pLineNext = pLine->next; + HeapFree(GetProcessHeap(), 0, pLine); + } + HeapFree(GetProcessHeap(), 0, pParagraph); + } + + SetWindowLongW(res->hwndSelf, 0, 0); + HeapFree(GetProcessHeap(), 0, res); + + return 0; +} + +static int RICHED32_WM_SetText(RICHEDITSTATE * res, LPCSTR szText) +{ + LPWSTR wszInsertion = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(szText) + 1) * sizeof(WCHAR)); + TRACE("(%p, %s)\n", res, debugstr_a(szText)); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szText, strlen(szText), wszInsertion, strlen(szText)); + RichText_ReplaceSel(res, wszInsertion); + HeapFree(GetProcessHeap(), 0, wszInsertion); + InvalidateRect(res->hwndSelf, NULL, TRUE); + return 1; +} + +static void RICHED32_EM_ReplaceSel(RICHEDITSTATE * res, BOOL bUndo, LPCSTR szText) +{ + LPWSTR wszInsertion = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(szText) + 1) * sizeof(WCHAR)); + TRACE("(%p, %s)\n", res, debugstr_a(szText)); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szText, strlen(szText), wszInsertion, strlen(szText)); + RichText_ReplaceSel(res, wszInsertion); + HeapFree(GetProcessHeap(), 0, wszInsertion); + InvalidateRect(res->hwndSelf, NULL, TRUE); +} + +static void RICHED32_EM_SetCharFormat2W(RICHEDITSTATE * res, CHARFORMAT2W * pChf) +{ + HFONT font = RichText_CHARFORMAT2ToHFONT(pChf); + int length = res->chrSelection.cpMax - res->chrSelection.cpMin; + LONG remaining; + RICHTEXTSEG * pFirstSelTextSeg = RichTextSeg_SkipToChar(res->pSelection->pFirstLine->pTextSeg, res->chrSelection.cpMin, &remaining); + RICHTEXTSEG * pTextSeg = pFirstSelTextSeg; + RICHTEXTSEG * pPreviousSeg; + LPWSTR lpwstrLast; + TRACE("(%p, %p)\n", res, pChf); + + // Check if we should insert a new RICHTEXTSEG + if (remaining > pFirstSelTextSeg->length && pFirstSelTextSeg->pNextSeg == NULL) + { + pFirstSelTextSeg->pNextSeg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RICHTEXTSEG)); + pFirstSelTextSeg->pNextSeg->pText = pFirstSelTextSeg->pText + pFirstSelTextSeg->length; + pFirstSelTextSeg = pFirstSelTextSeg->pNextSeg; + pTextSeg = pFirstSelTextSeg; + } + + // Systematically remove RICHTEXTSEGs in the selection area and add them to the first one + if (length - res->chrSelection.cpMin > res->chrSelection.cpMax - res->chrSelection.cpMin) + { + lpwstrLast = pTextSeg->pText + pTextSeg->length; + length -= pTextSeg->length - res->chrSelection.cpMin; + pTextSeg = pTextSeg->pNextSeg; + while (pTextSeg && (length + pTextSeg->length < res->chrSelection.cpMax - res->chrSelection.cpMin)) + { + lpwstrLast = pTextSeg->pText + pTextSeg->length; + length -= pTextSeg->length; + RichText_ReleaseHFONT(pTextSeg->hSegFont); + pPreviousSeg = pTextSeg; + pTextSeg = pTextSeg->pNextSeg; + HeapFree(GetProcessHeap(), 0, pPreviousSeg); + } + } + else + lpwstrLast = pFirstSelTextSeg->pText + pFirstSelTextSeg->length; + pFirstSelTextSeg->pNextSeg = pTextSeg; + if (pFirstSelTextSeg->pNextSeg == pFirstSelTextSeg) + pFirstSelTextSeg->pNextSeg = NULL; + pFirstSelTextSeg->hSegFont = font; + pFirstSelTextSeg->extras.crText = pChf->crTextColor; + pFirstSelTextSeg->extras.crBackground = pChf->crBackColor; + pFirstSelTextSeg->length = (int)(lpwstrLast - pFirstSelTextSeg->pText); +// while(pFirstSelTextSeg->pText[pFirstSelTextSeg->length - 1] == '\n' || pFirstSelTextSeg->pText[pFirstSelTextSeg->length - 1] == '\r') +// pFirstSelTextSeg->length--; +// pTextSeg->extras = pChf-> + RichText_BuildLineDefs(res, res->pSelection); + InvalidateRect(res->hwndSelf, NULL, TRUE); +} + +static RICHTEXTSEG * RichTextSeg_SkipToChar(RICHTEXTSEG * pTextSeg, LONG pos, LONG * remaining) +{ + TRACE("pos = %ld, pTextSeg->length = %d\n", pos, pTextSeg->length); + // EXSETSEL with cpMax = -1 means whole selection + while ((pos == -1) || (pos > pTextSeg->length)) + { + if (pTextSeg->pNextSeg) + { + pos -= (int)(pTextSeg->pNextSeg->pText - pTextSeg->pText); + pTextSeg = pTextSeg->pNextSeg; + } + else + break; + } + if (remaining) + *remaining = pos; + return pTextSeg; +} + +static LINEDEF * RichTextLine_SkipToChar(LINEDEF * pLine, LONG pos, LONG * remaining) +{ + // EXSETSEL with cpMax = -1 means whole selection + while ((pos == -1) || (pos >= pLine->length) || (pLine->pTextSeg->pText[pos] == '\n') || (pLine->pTextSeg->pText[pos] == '\r')) + { + if (pLine->next) + { + pos -= pLine->pTextSeg->pText + pLine->startIndex - pLine->next->pTextSeg->pText - pLine->next->startIndex; + pLine = pLine->next; + } + else + break; + } + if (remaining) + *remaining = pos < 0 ? 0 : pos; + return pLine; +} + +static void RICHED32_EM_SetCharFormat2A(RICHEDITSTATE * res, CHARFORMAT2A * pChf) +{ + CHARFORMAT2W chfW; + CopyMemory(&chfW, pChf, (int)(&(pChf->szFaceName)) - (int)pChf); + CopyMemory(&(chfW.wWeight), &(pChf->wWeight), (int)(&(pChf->bRevAuthor) + sizeof(BYTE)) - (int)&(pChf->wWeight)); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pChf->szFaceName, LF_FACESIZE, chfW.szFaceName, LF_FACESIZE); + RICHED32_EM_SetCharFormat2W(res, &chfW); } + +static void RICHED32_CreateAndShowCaret(RICHEDITSTATE * res) +{ + DWORD extent = RichText_EM_PosFromChar(res, res->chrSelection.cpMax); + LONG remaining; + LINEDEF * pLine = RichTextLine_SkipToChar(res->pSelection->pFirstLine, res->chrSelection.cpMax, &remaining); + + TRACE("height: %d\n", pLine->cachedHeight); + CreateCaret(res->hwndSelf, 0, 1, pLine->cachedHeight); + TRACE("x = %d, y = %d\n", LOWORD(extent), pLine->cachedYPos - pLine->cachedHeight); + SetCaretPos(LOWORD(extent), pLine->cachedYPos - pLine->cachedHeight); + ShowCaret(res->hwndSelf); +} + +static void RICHED32_UpdateScrollInfo(RICHEDITSTATE * res) +{ + int line_count = 0; + PARAGRAPH * pParagraph; + LINEDEF * pLine; + for (pParagraph = res->pFirstParagraph; pParagraph; pParagraph = pParagraph->pNext) + { + for (pLine = pParagraph->pFirstLine; pLine; pLine = pLine->next) + { + line_count++; + } + } + if ((res->style & WS_VSCROLL) /*&& !(res->flags & EF_VSCROLL_TRACK)*/) + { + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = /*SIF_PAGE |*/ SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = line_count - 1; +// si.nPage = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + si.nPos = /*res->y_offset*/ 0; + TRACE("SB_VERT, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n", + si.nMin, si.nMax, si.nPage, si.nPos); + SetScrollInfo(res->hwndSelf, SB_VERT, &si, TRUE); + } + +/* if ((es->style & WS_HSCROLL) && !(es->flags & EF_HSCROLL_TRACK)) + { + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = es->text_width - 1; + si.nPage = es->format_rect.right - es->format_rect.left; + si.nPos = es->x_offset; + TRACE("SB_HORZ, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n", + si.nMin, si.nMax, si.nPage, si.nPos); + SetScrollInfo(es->hwndSelf, SB_HORZ, &si, TRUE); + }*/ +} + +static void RICHED32_WM_Char(RICHEDITSTATE * res, WCHAR charW) +{ + if (res->style & ES_READONLY) + { + MessageBeep(0); + return; + } + + switch (charW) + { + case 0x03: /* ^C */ + SendMessageW(res->hwndSelf, WM_COPY, 0, 0); + break; + case 0x16: /* ^V */ + SendMessageW(res->hwndSelf, WM_PASTE, 0, 0); + break; + case 0x18: /* ^X */ + SendMessageW(res->hwndSelf, WM_CUT, 0, 0); + break; + case VK_BACK: + { + WCHAR wch = '\0'; + if (res->chrSelection.cpMin == res->chrSelection.cpMax) + { + res->chrSelection.cpMin--; + } + RichText_ReplaceSel(res, &wch); + InvalidateRect(res->hwndSelf, NULL, TRUE); + break; + } + // FIXME: more handling here + default: + { + WCHAR str[2] = {charW, '\0'}; + RichText_ReplaceSel(res, str); + InvalidateRect(res->hwndSelf, NULL, TRUE); + } + } +} + +static LRESULT RichText_EM_PosFromChar(RICHEDITSTATE * res, INT index) +{ + LONG remaining; + + // FIXME: Cope with multiple paragraphs + INT nextx = 0; + INT nexty = 0; + LINEDEF * pLine = RichTextLine_SkipToChar(res->pFirstParagraph->pFirstLine, index, &remaining); + HFONT old_font; + + RICHTEXTSEG * pTextSeg = pLine->pTextSeg; + BOOL first = TRUE; + DWORD extent; + HDC dc = GetDC(res->hwndSelf); + old_font = SelectObject(dc, pTextSeg->hSegFont); + while(pTextSeg) + { + if (remaining < pTextSeg->length) + { + extent = RichTextSeg_GetExtent(pTextSeg, dc, first ? pLine->startIndex : 0, remaining, res->nTabPositions, res->lpnTabStopPositions); + nextx += LOWORD(extent); + nexty = max(HIWORD(extent), nexty); + break; + } + else + { + extent = RichTextSeg_GetExtent(pTextSeg, dc, first ? pLine->startIndex : 0, -1, res->nTabPositions, res->lpnTabStopPositions); + nextx += LOWORD(extent); + nexty = max(HIWORD(extent), nexty); + remaining -= pTextSeg->length; + pTextSeg = pTextSeg->pNextSeg; + } + first = FALSE; + } + SelectObject(dc, old_font); + ReleaseDC(res->hwndSelf, dc); + return MAKELONG(nextx, pLine->cachedHeight); +} + +/*static void RichText_SetCaretPos(RICHEDITSTATE * res, INT pos) +{ +// DWORD extent = RichText_EM_PosFromChar(res, res->chrSelection.cpMax); +// SetCaretPos(LOWORD(extent), HIWORD(extent)); + RICHED32_CreateAndShowCaret(res); +}*/ + +static INT RichText_CharFromPos(RICHEDITSTATE * res, POINTL * pPoint) +{ + // FIXME: handle margins and offsets + LONG x = pPoint->x; + LONG y = pPoint->y; + INT pos = 0; + INT linechar = 0; + PARAGRAPH * pParagraph; + LINEDEF * pLine; + INT extent; + INT oldextent; +// RICHTEXTSEG * pTextSeg; +// BOOL bStart = TRUE; + for (pParagraph = res->pFirstParagraph; pParagraph->pNext; pParagraph = pParagraph->pNext) + { + if (y < pParagraph->cachedHeight) + break; + else + { + y -= pParagraph->cachedHeight; + // FIXME: this is not quite right - buffer size takes into account linebreaks at the moment + pos += pParagraph->uBufferSize; + } + } + for (pLine = pParagraph->pFirstLine; pLine->next; pLine = pLine->next) + { + if (y < pLine->cachedHeight) + break; + else + { + y -= pLine->cachedHeight; + pos += pLine->length; + } + } + if (x >= pLine->cachedWidth) + { + pos += pLine->length; + } + else + { + HDC dc = GetDC(res->hwndSelf); + // FIXME: do for multiple text segs + oldextent = 0; + for (linechar = 1; linechar < pLine->pTextSeg->length - pLine->startIndex; linechar++) + { + extent = LOWORD(RichTextSeg_GetExtent(pLine->pTextSeg, dc, pLine->startIndex, linechar, res->nTabPositions, res->lpnTabStopPositions)); + if (x < extent) + { + if (x - oldextent < extent - x) + linechar--; + break; + } + oldextent = extent; + } + pos += linechar; +// for (pTextSeg = pLine->pTextSeg; pTextSeg->pNextSeg && linechar < pLine->length; linechar += pTextSeg->length, pTextSeg = pTextSeg->pNextSeg) +// ; +// x -= LOWORD(RichTextSeg_GetExtent(pTextSeg, dc, pLine->startIndex, -1, res->nTabPositions, res->lpnTabStops)); +// while (x < LOWORD(RichTextSeg_GetExtent(pTextSeg, dc, pLine->startIndex, -1, res->nTabPositions + ReleaseDC(res->hwndSelf, dc); + } +// TRACE("returning: %d\n", pos); + return pos; +} + +static LRESULT RichText_EM_FindTextExW(RICHEDITSTATE * res, UINT fuFlags, FINDTEXTEXW * lpFindText) +{ + FIXME("\n"); + return -1; +} + +static LRESULT RichText_EM_FindTextExA(RICHEDITSTATE * res, UINT fuFlags, FINDTEXTEXA * lpFindText) +{ + FINDTEXTEXW findTextW; + LRESULT result = -1; + findTextW.lpstrText = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(lpFindText->lpstrText) + 1) * sizeof(WCHAR)); + TRACE("(%p, %s)\n", res, debugstr_a(lpFindText->lpstrText)); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpFindText->lpstrText, strlen(lpFindText->lpstrText), findTextW.lpstrText, strlen(lpFindText->lpstrText)); + result = RichText_EM_FindTextExW(res, fuFlags, &findTextW); + HeapFree(GetProcessHeap(), 0, findTextW.lpstrText); + CopyMemory(&lpFindText->chrgText, &findTextW.chrgText, sizeof(CHARRANGE)); + return result; +} + +static void RichTextParagraph_SetFormat2(PARAGRAPH * pParagraph, PARAFORMAT * pFormat) +{ + int i; + if (pFormat->dwMask & PFM_ALIGNMENT) + pParagraph->format.wAlignment = pFormat->wAlignment; + if (pFormat->dwMask & PFM_NUMBERING) + pParagraph->format.wNumbering = pFormat->wNumbering; + if (pFormat->dwMask & PFM_OFFSET) + pParagraph->format.dxOffset = pFormat->dxOffset; + if (pFormat->dwMask & PFM_OFFSETINDENT) + pParagraph->format.dxStartIndent = pFormat->dxStartIndent; + if (pFormat->dwMask & PFM_RIGHTINDENT) + pParagraph->format.dxRightIndent = pFormat->dxRightIndent; + if (pFormat->dwMask & PFM_RTLPARA) + pParagraph->format.wEffects = pFormat->wEffects; + if (pFormat->dwMask & PFM_STARTINDENT) + pParagraph->format.dxStartIndent = pFormat->dxStartIndent; + if (pFormat->dwMask & PFM_TABSTOPS) + { + pParagraph->format.cTabCount = pFormat->cTabCount; + for (i = 0; i < pParagraph->format.cTabCount; i++) + pParagraph->format.rgxTabs[i] = pFormat->rgxTabs[i]; + } +// if (pFormat->cbSize != sizeof(PARAFORMAT2)) + return; + +// FIXME("PARAFORMAT2 not supported yet\n"); +} + +static void RichText_WM_Keydown(RICHEDITSTATE * res, int nVirtKey, long lKeyData) +{ + BOOL shift = GetKeyState(VK_SHIFT) & 0x8000; + + switch (nVirtKey) + { + case VK_LEFT: + if (!shift) + res->chrSelection.cpMax--; + res->chrSelection.cpMin--; + InvalidateRect(res->hwndSelf, NULL, TRUE); + RICHED32_CreateAndShowCaret(res); + break; + case VK_RIGHT: + if (!shift) + res->chrSelection.cpMax++; + res->chrSelection.cpMin++; + InvalidateRect(res->hwndSelf, NULL, TRUE); + RICHED32_CreateAndShowCaret(res); + break; + case VK_UP: + { + POINTL p; + DWORD extent = RichText_EM_PosFromChar(res, res->chrSelection.cpMin); + p.x = LOWORD(extent); + p.y = HIWORD(extent) - 1; + res->chrSelection.cpMax = RichText_CharFromPos(res, &p); + if (!shift) + res->chrSelection.cpMin = res->chrSelection.cpMax; + InvalidateRect(res->hwndSelf, NULL, TRUE); + RICHED32_CreateAndShowCaret(res); + break; + } + case VK_DOWN: + { + FIXME("VK_DOWN not handled yet\n"); +/* POINTL p; + DWORD extent = RichText_EM_PosFromChar(res, res->chrSelection.cpMin); + p.x = LOWORD(extent); + p.y = HIWORD(extent) + 1; // this needs to be the line height really + res->chrSelection.cpMax = RichText_CharFromPos(res, &p); + if (!shift) + res->chrSelection.cpMin = res->chrSelection.cpMax; + InvalidateRect(res->hwndSelf, NULL, TRUE); + RICHED32_CreateAndShowCaret(res);*/ + break; + } + case VK_HOME: + FIXME("VK_HOME not handled yet\n"); + break; + case VK_END: + FIXME("VK_END not handled yet\n"); + break; + case VK_DELETE: + { + WCHAR wch = '\0'; + if (res->style & ES_READONLY) + { + MessageBeep(0); + break; + } + if (res->chrSelection.cpMin == res->chrSelection.cpMax) + { + res->chrSelection.cpMax++; + } + RichText_ReplaceSel(res, &wch); + InvalidateRect(res->hwndSelf, NULL, TRUE); + break; + } + default: + } +} + +static void RICHED32_WM_Cut(RICHEDITSTATE * res) +{ + RICHED32_WM_Copy(res); + RICHED32_WM_Clear(res); +} + +static void RICHED32_WM_Copy(RICHEDITSTATE * res) +{ + FIXME("stub\n"); +} + +static void RICHED32_WM_Paste(RICHEDITSTATE * res) +{ + FIXME("stub\n"); +} + +static void RICHED32_WM_Clear(RICHEDITSTATE * res) +{ + FIXME("stub\n"); +} Index: wine/include/richedit.h =================================================================== RCS file: /home/wine/wine/include/richedit.h,v retrieving revision 1.14 diff -u -r1.14 richedit.h --- wine/include/richedit.h 19 Nov 2002 00:44:05 -0000 1.14 +++ wine/include/richedit.h 4 Dec 2002 22:37:10 -0000 @@ -470,7 +470,7 @@ UINT cbSize; DWORD dwMask; WORD wNumbering; - WORD wReserved; + WORD wEffects; // was wReserved LONG dxStartIndent; LONG dxRightIndent; LONG dxOffset; @@ -546,7 +546,8 @@ #define PFM_OFFSET 0x00000004 #define PFM_ALIGNMENT 0x00000008 #define PFM_TABSTOPS 0x00000010 -#define PFM_NUMBERING 0x00000020 +#define PFM_NUMBERING 0x00000020 +#define PFM_RTLPARA 0x00010000 #define PFM_OFFSETINDENT 0x80000000 /* numbering option */