gdi32/tests: Mark tests failing randomly on Windows as flaky.
[wine.git] / dlls / riched20 / txthost.c
blobc53aa0a3e053eca237451620ac115531a826068c
1 /*
2 * RichEdit - ITextHost implementation for windowed richedit controls
4 * Copyright 2009 by Dylan Smith
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "editor.h"
24 #include "ole2.h"
25 #include "richole.h"
26 #include "imm.h"
27 #include "textserv.h"
28 #include "wine/debug.h"
29 #include "editstr.h"
30 #include "rtf.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
34 struct host
36 ITextHost2 ITextHost_iface;
37 LONG ref;
38 ITextServices *text_srv;
39 HWND window, parent;
40 unsigned int emulate_10 : 1;
41 unsigned int dialog_mode : 1;
42 unsigned int want_return : 1;
43 unsigned int sel_bar : 1;
44 unsigned int client_edge : 1;
45 unsigned int use_set_rect : 1;
46 unsigned int use_back_colour : 1;
47 unsigned int defer_release : 1;
48 PARAFORMAT2 para_fmt;
49 DWORD props, scrollbars, event_mask;
50 RECT client_rect, set_rect;
51 COLORREF back_colour;
52 WCHAR password_char;
53 unsigned int notify_level;
56 static const ITextHost2Vtbl textHostVtbl;
58 static BOOL listbox_registered;
59 static BOOL combobox_registered;
61 static void host_init_props( struct host *host )
63 DWORD style;
65 style = GetWindowLongW( host->window, GWL_STYLE );
67 /* text services assumes the scrollbars are originally not shown, so hide them.
68 However with ES_DISABLENOSCROLL it'll immediately show them, so don't bother */
69 if (!(style & ES_DISABLENOSCROLL)) ShowScrollBar( host->window, SB_BOTH, FALSE );
71 host->scrollbars = style & (WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL |
72 ES_AUTOHSCROLL | ES_DISABLENOSCROLL);
73 if (style & WS_VSCROLL) host->scrollbars |= ES_AUTOVSCROLL;
74 if ((style & WS_HSCROLL) && !host->emulate_10) host->scrollbars |= ES_AUTOHSCROLL;
76 host->props = TXTBIT_RICHTEXT | TXTBIT_ALLOWBEEP;
77 if (style & ES_MULTILINE) host->props |= TXTBIT_MULTILINE;
78 if (style & ES_READONLY) host->props |= TXTBIT_READONLY;
79 if (style & ES_PASSWORD) host->props |= TXTBIT_USEPASSWORD;
80 if (!(style & ES_NOHIDESEL)) host->props |= TXTBIT_HIDESELECTION;
81 if (style & ES_SAVESEL) host->props |= TXTBIT_SAVESELECTION;
82 if (style & ES_VERTICAL) host->props |= TXTBIT_VERTICAL;
83 if (style & ES_NOOLEDRAGDROP) host->props |= TXTBIT_DISABLEDRAG;
85 if (!(host->scrollbars & ES_AUTOHSCROLL)) host->props |= TXTBIT_WORDWRAP;
87 host->sel_bar = !!(style & ES_SELECTIONBAR);
88 host->want_return = !!(style & ES_WANTRETURN);
90 style = GetWindowLongW( host->window, GWL_EXSTYLE );
91 host->client_edge = !!(style & WS_EX_CLIENTEDGE);
94 struct host *host_create( HWND hwnd, CREATESTRUCTW *cs, BOOL emulate_10 )
96 struct host *texthost;
98 texthost = heap_alloc(sizeof(*texthost));
99 if (!texthost) return NULL;
101 texthost->ITextHost_iface.lpVtbl = &textHostVtbl;
102 texthost->ref = 1;
103 texthost->text_srv = NULL;
104 texthost->window = hwnd;
105 texthost->parent = cs->hwndParent;
106 texthost->emulate_10 = emulate_10;
107 texthost->dialog_mode = 0;
108 memset( &texthost->para_fmt, 0, sizeof(texthost->para_fmt) );
109 texthost->para_fmt.cbSize = sizeof(texthost->para_fmt);
110 texthost->para_fmt.dwMask = PFM_ALIGNMENT;
111 texthost->para_fmt.wAlignment = PFA_LEFT;
112 if (cs->style & ES_RIGHT)
113 texthost->para_fmt.wAlignment = PFA_RIGHT;
114 if (cs->style & ES_CENTER)
115 texthost->para_fmt.wAlignment = PFA_CENTER;
116 host_init_props( texthost );
117 texthost->event_mask = 0;
118 texthost->use_set_rect = 0;
119 SetRectEmpty( &texthost->set_rect );
120 GetClientRect( hwnd, &texthost->client_rect );
121 texthost->use_back_colour = 0;
122 texthost->password_char = (texthost->props & TXTBIT_USEPASSWORD) ? '*' : 0;
123 texthost->defer_release = 0;
124 texthost->notify_level = 0;
126 return texthost;
129 static inline struct host *impl_from_ITextHost( ITextHost2 *iface )
131 return CONTAINING_RECORD( iface, struct host, ITextHost_iface );
134 static HRESULT WINAPI ITextHostImpl_QueryInterface( ITextHost2 *iface, REFIID iid, void **obj )
136 struct host *host = impl_from_ITextHost( iface );
138 if (IsEqualIID( iid, &IID_IUnknown ) || IsEqualIID( iid, &IID_ITextHost ) || IsEqualIID( iid, &IID_ITextHost2 ))
140 *obj = &host->ITextHost_iface;
141 ITextHost_AddRef( (ITextHost *)*obj );
142 return S_OK;
145 FIXME( "Unknown interface: %s\n", debugstr_guid( iid ) );
146 return E_NOINTERFACE;
149 static ULONG WINAPI ITextHostImpl_AddRef( ITextHost2 *iface )
151 struct host *host = impl_from_ITextHost( iface );
152 ULONG ref = InterlockedIncrement( &host->ref );
153 return ref;
156 static ULONG WINAPI ITextHostImpl_Release( ITextHost2 *iface )
158 struct host *host = impl_from_ITextHost( iface );
159 ULONG ref = InterlockedDecrement( &host->ref );
161 if (!ref)
163 SetWindowLongPtrW( host->window, 0, 0 );
164 ITextServices_Release( host->text_srv );
165 heap_free( host );
167 return ref;
170 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetDC,4)
171 DECLSPEC_HIDDEN HDC __thiscall ITextHostImpl_TxGetDC( ITextHost2 *iface )
173 struct host *host = impl_from_ITextHost( iface );
174 return GetDC( host->window );
177 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxReleaseDC,8)
178 DECLSPEC_HIDDEN INT __thiscall ITextHostImpl_TxReleaseDC( ITextHost2 *iface, HDC hdc )
180 struct host *host = impl_from_ITextHost( iface );
181 return ReleaseDC( host->window, hdc );
184 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowScrollBar,12)
185 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxShowScrollBar( ITextHost2 *iface, INT bar, BOOL show )
187 struct host *host = impl_from_ITextHost( iface );
188 return ShowScrollBar( host->window, bar, show );
191 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxEnableScrollBar,12)
192 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxEnableScrollBar( ITextHost2 *iface, INT bar, INT arrows )
194 struct host *host = impl_from_ITextHost( iface );
195 return EnableScrollBar( host->window, bar, arrows );
198 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollRange,20)
199 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetScrollRange( ITextHost2 *iface, INT bar, LONG min_pos, INT max_pos, BOOL redraw )
201 struct host *host = impl_from_ITextHost( iface );
202 SCROLLINFO info = { .cbSize = sizeof(info), .fMask = SIF_PAGE | SIF_RANGE };
204 if (bar != SB_HORZ && bar != SB_VERT)
206 FIXME( "Unexpected bar %d\n", bar );
207 return FALSE;
210 if (host->scrollbars & ES_DISABLENOSCROLL) info.fMask |= SIF_DISABLENOSCROLL;
212 if (host->text_srv) /* This can be called during text services creation */
214 if (bar == SB_HORZ) ITextServices_TxGetHScroll( host->text_srv, NULL, NULL, NULL, (LONG *)&info.nPage, NULL );
215 else ITextServices_TxGetVScroll( host->text_srv, NULL, NULL, NULL, (LONG *)&info.nPage, NULL );
218 info.nMin = min_pos;
219 info.nMax = max_pos;
220 return SetScrollInfo( host->window, bar, &info, redraw );
223 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollPos,16)
224 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetScrollPos( ITextHost2 *iface, INT bar, INT pos, BOOL redraw )
226 struct host *host = impl_from_ITextHost( iface );
227 DWORD style = GetWindowLongW( host->window, GWL_STYLE );
228 DWORD mask = (bar == SB_HORZ) ? WS_HSCROLL : WS_VSCROLL;
229 BOOL show = TRUE, shown = style & mask;
231 if (bar != SB_HORZ && bar != SB_VERT)
233 FIXME( "Unexpected bar %d\n", bar );
234 return FALSE;
237 /* If the application has adjusted the scrollbar's visibility it is reset */
238 if (!(host->scrollbars & ES_DISABLENOSCROLL))
240 if (bar == SB_HORZ) ITextServices_TxGetHScroll( host->text_srv, NULL, NULL, NULL, NULL, &show );
241 else ITextServices_TxGetVScroll( host->text_srv, NULL, NULL, NULL, NULL, &show );
244 if (!show ^ !shown) ShowScrollBar( host->window, bar, show );
245 return SetScrollPos( host->window, bar, pos, redraw ) != 0;
248 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxInvalidateRect,12)
249 DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxInvalidateRect( ITextHost2 *iface, const RECT *rect, BOOL mode )
251 struct host *host = impl_from_ITextHost( iface );
252 InvalidateRect( host->window, rect, mode );
255 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxViewChange,8)
256 DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxViewChange( ITextHost2 *iface, BOOL update )
258 struct host *host = impl_from_ITextHost( iface );
259 if (update) UpdateWindow( host->window );
262 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxCreateCaret,16)
263 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxCreateCaret( ITextHost2 *iface, HBITMAP bitmap, INT width, INT height )
265 struct host *host = impl_from_ITextHost( iface );
266 return CreateCaret( host->window, bitmap, width, height );
269 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowCaret,8)
270 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxShowCaret( ITextHost2 *iface, BOOL show )
272 struct host *host = impl_from_ITextHost( iface );
273 if (show) return ShowCaret( host->window );
274 else return HideCaret( host->window );
277 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCaretPos,12)
278 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetCaretPos( ITextHost2 *iface, INT x, INT y )
280 return SetCaretPos(x, y);
283 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetTimer,12)
284 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxSetTimer( ITextHost2 *iface, UINT id, UINT timeout )
286 struct host *host = impl_from_ITextHost( iface );
287 return SetTimer( host->window, id, timeout, NULL ) != 0;
290 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxKillTimer,8)
291 DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxKillTimer( ITextHost2 *iface, UINT id )
293 struct host *host = impl_from_ITextHost( iface );
294 KillTimer( host->window, id );
297 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScrollWindowEx,32)
298 DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxScrollWindowEx( ITextHost2 *iface, INT dx, INT dy, const RECT *scroll,
299 const RECT *clip, HRGN update_rgn, RECT *update_rect,
300 UINT flags )
302 struct host *host = impl_from_ITextHost( iface );
303 ScrollWindowEx( host->window, dx, dy, scroll, clip, update_rgn, update_rect, flags );
306 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCapture,8)
307 DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetCapture( ITextHost2 *iface, BOOL capture )
309 struct host *host = impl_from_ITextHost( iface );
310 if (capture) SetCapture( host->window );
311 else ReleaseCapture();
314 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetFocus,4)
315 DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetFocus( ITextHost2 *iface )
317 struct host *host = impl_from_ITextHost( iface );
318 SetFocus( host->window );
321 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor,12)
322 DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxSetCursor( ITextHost2 *iface, HCURSOR cursor, BOOL text )
324 SetCursor( cursor );
327 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScreenToClient,8)
328 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxScreenToClient( ITextHost2 *iface, POINT *pt )
330 struct host *host = impl_from_ITextHost( iface );
331 return ScreenToClient( host->window, pt );
334 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxClientToScreen,8)
335 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxClientToScreen( ITextHost2 *iface, POINT *pt )
337 struct host *host = impl_from_ITextHost( iface );
338 return ClientToScreen( host->window, pt );
341 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxActivate,8)
342 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxActivate( ITextHost2 *iface, LONG *old_state )
344 struct host *host = impl_from_ITextHost( iface );
345 *old_state = HandleToLong( SetActiveWindow( host->window ) );
346 return *old_state ? S_OK : E_FAIL;
349 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDeactivate,8)
350 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxDeactivate( ITextHost2 *iface, LONG new_state )
352 HWND ret = SetActiveWindow( LongToHandle( new_state ) );
353 return ret ? S_OK : E_FAIL;
356 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetClientRect,8)
357 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetClientRect( ITextHost2 *iface, RECT *rect )
359 struct host *host = impl_from_ITextHost( iface );
361 if (!host->use_set_rect)
363 *rect = host->client_rect;
364 if (host->client_edge) rect->top += 1;
365 InflateRect( rect, -1, 0 );
367 else *rect = host->set_rect;
369 return S_OK;
372 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetViewInset,8)
373 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetViewInset( ITextHost2 *iface, RECT *rect )
375 SetRectEmpty( rect );
376 return S_OK;
379 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetCharFormat,8)
380 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetCharFormat( ITextHost2 *iface, const CHARFORMATW **ppCF )
382 return E_NOTIMPL;
385 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetParaFormat,8)
386 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetParaFormat( ITextHost2 *iface, const PARAFORMAT **fmt )
388 struct host *host = impl_from_ITextHost( iface );
389 *fmt = (const PARAFORMAT *)&host->para_fmt;
390 return S_OK;
393 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSysColor,8)
394 DECLSPEC_HIDDEN COLORREF __thiscall ITextHostImpl_TxGetSysColor( ITextHost2 *iface, int index )
396 struct host *host = impl_from_ITextHost( iface );
398 if (index == COLOR_WINDOW && host->use_back_colour) return host->back_colour;
399 return GetSysColor( index );
402 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetBackStyle,8)
403 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetBackStyle( ITextHost2 *iface, TXTBACKSTYLE *style )
405 *style = TXTBACK_OPAQUE;
406 return S_OK;
409 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetMaxLength,8)
410 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetMaxLength( ITextHost2 *iface, DWORD *length )
412 *length = INFINITE;
413 return S_OK;
416 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetScrollBars,8)
417 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetScrollBars( ITextHost2 *iface, DWORD *scrollbars )
419 struct host *host = impl_from_ITextHost( iface );
421 *scrollbars = host->scrollbars;
422 return S_OK;
425 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPasswordChar,8)
426 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetPasswordChar( ITextHost2 *iface, WCHAR *c )
428 struct host *host = impl_from_ITextHost( iface );
430 *c = host->password_char;
431 return *c ? S_OK : S_FALSE;
434 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetAcceleratorPos,8)
435 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetAcceleratorPos( ITextHost2 *iface, LONG *pos )
437 *pos = -1;
438 return S_OK;
441 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetExtent,8)
442 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetExtent( ITextHost2 *iface, SIZEL *extent )
444 return E_NOTIMPL;
447 DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxCharFormatChange,8)
448 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_OnTxCharFormatChange( ITextHost2 *iface, const CHARFORMATW *pcf )
450 return S_OK;
453 DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxParaFormatChange,8)
454 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_OnTxParaFormatChange( ITextHost2 *iface, const PARAFORMAT *ppf )
456 return S_OK;
459 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPropertyBits,12)
460 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetPropertyBits( ITextHost2 *iface, DWORD mask, DWORD *bits )
462 struct host *host = impl_from_ITextHost( iface );
464 *bits = host->props & mask;
465 return S_OK;
468 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxNotify,12)
469 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxNotify( ITextHost2 *iface, DWORD iNotify, void *pv )
471 struct host *host = impl_from_ITextHost( iface );
472 UINT id;
474 if (!host->parent) return S_OK;
476 id = GetWindowLongW( host->window, GWLP_ID );
478 switch (iNotify)
480 case EN_DROPFILES:
481 case EN_LINK:
482 case EN_OLEOPFAILED:
483 case EN_PROTECTED:
484 case EN_REQUESTRESIZE:
485 case EN_SAVECLIPBOARD:
486 case EN_SELCHANGE:
487 case EN_STOPNOUNDO:
489 /* FIXME: Verify this assumption that pv starts with NMHDR. */
490 NMHDR *info = pv;
491 if (!info)
492 return E_FAIL;
494 info->hwndFrom = host->window;
495 info->idFrom = id;
496 info->code = iNotify;
497 SendMessageW( host->parent, WM_NOTIFY, id, (LPARAM)info );
498 break;
501 case EN_UPDATE:
502 /* Only sent when the window is visible. */
503 if (!IsWindowVisible( host->window ))
504 break;
505 /* Fall through */
506 case EN_CHANGE:
507 case EN_ERRSPACE:
508 case EN_HSCROLL:
509 case EN_KILLFOCUS:
510 case EN_MAXTEXT:
511 case EN_SETFOCUS:
512 case EN_VSCROLL:
513 SendMessageW( host->parent, WM_COMMAND, MAKEWPARAM( id, iNotify ), (LPARAM)host->window );
514 break;
516 case EN_MSGFILTER:
517 FIXME("EN_MSGFILTER is documented as not being sent to TxNotify\n");
518 /* fall through */
519 default:
520 return E_FAIL;
522 return S_OK;
525 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmGetContext,4)
526 DECLSPEC_HIDDEN HIMC __thiscall ITextHostImpl_TxImmGetContext( ITextHost2 *iface )
528 struct host *host = impl_from_ITextHost( iface );
529 return ImmGetContext( host->window );
532 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmReleaseContext,8)
533 DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxImmReleaseContext( ITextHost2 *iface, HIMC context )
535 struct host *host = impl_from_ITextHost( iface );
536 ImmReleaseContext( host->window, context );
539 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSelectionBarWidth,8)
540 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetSelectionBarWidth( ITextHost2 *iface, LONG *width )
542 struct host *host = impl_from_ITextHost( iface );
544 *width = host->sel_bar ? 225 : 0; /* in HIMETRIC */
545 return S_OK;
548 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxIsDoubleClickPending,4)
549 DECLSPEC_HIDDEN BOOL __thiscall ITextHostImpl_TxIsDoubleClickPending( ITextHost2 *iface )
551 return FALSE;
554 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetWindow,8)
555 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetWindow( ITextHost2 *iface, HWND *hwnd )
557 struct host *host = impl_from_ITextHost( iface );
558 *hwnd = host->window;
559 return S_OK;
562 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetForegroundWindow,4)
563 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxSetForegroundWindow( ITextHost2 *iface )
565 return E_NOTIMPL;
568 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPalette,4)
569 DECLSPEC_HIDDEN HPALETTE __thiscall ITextHostImpl_TxGetPalette( ITextHost2 *iface )
571 return NULL;
574 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetEastAsianFlags,8)
575 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetEastAsianFlags( ITextHost2 *iface, LONG *flags )
577 return E_NOTIMPL;
580 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor2,12)
581 DECLSPEC_HIDDEN HCURSOR __thiscall ITextHostImpl_TxSetCursor2( ITextHost2 *iface, HCURSOR cursor, BOOL text )
583 return NULL;
586 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxFreeTextServicesNotification,4)
587 DECLSPEC_HIDDEN void __thiscall ITextHostImpl_TxFreeTextServicesNotification( ITextHost2 *iface )
589 return;
592 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetEditStyle,12)
593 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetEditStyle( ITextHost2 *iface, DWORD item, DWORD *data )
595 return E_NOTIMPL;
598 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetWindowStyles,12)
599 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetWindowStyles( ITextHost2 *iface, DWORD *style, DWORD *ex_style )
601 return E_NOTIMPL;
604 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowDropCaret,16)
605 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxShowDropCaret( ITextHost2 *iface, BOOL show, HDC hdc, const RECT *rect )
607 return E_NOTIMPL;
610 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDestroyCaret,4)
611 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxDestroyCaret( ITextHost2 *iface )
613 return E_NOTIMPL;
616 DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetHorzExtent,8)
617 DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetHorzExtent( ITextHost2 *iface, LONG *horz_extent )
619 return E_NOTIMPL;
623 #ifdef __ASM_USE_THISCALL_WRAPPER
625 #define STDCALL(func) (void *) __stdcall_ ## func
626 #ifdef _MSC_VER
627 #define DEFINE_STDCALL_WRAPPER(num,func,args) \
628 __declspec(naked) HRESULT __stdcall_##func(void) \
630 __asm pop eax \
631 __asm pop ecx \
632 __asm push eax \
633 __asm mov eax, [ecx] \
634 __asm jmp dword ptr [eax + 4*num] \
636 #else /* _MSC_VER */
637 #define DEFINE_STDCALL_WRAPPER(num,func,args) \
638 extern HRESULT __stdcall_ ## func(void); \
639 __ASM_GLOBAL_FUNC(__stdcall_ ## func, \
640 "popl %eax\n\t" \
641 "popl %ecx\n\t" \
642 "pushl %eax\n\t" \
643 "movl (%ecx), %eax\n\t" \
644 "jmp *(4*(" #num "))(%eax)" )
645 #endif /* _MSC_VER */
647 DEFINE_STDCALL_WRAPPER(3,ITextHostImpl_TxGetDC,4)
648 DEFINE_STDCALL_WRAPPER(4,ITextHostImpl_TxReleaseDC,8)
649 DEFINE_STDCALL_WRAPPER(5,ITextHostImpl_TxShowScrollBar,12)
650 DEFINE_STDCALL_WRAPPER(6,ITextHostImpl_TxEnableScrollBar,12)
651 DEFINE_STDCALL_WRAPPER(7,ITextHostImpl_TxSetScrollRange,20)
652 DEFINE_STDCALL_WRAPPER(8,ITextHostImpl_TxSetScrollPos,16)
653 DEFINE_STDCALL_WRAPPER(9,ITextHostImpl_TxInvalidateRect,12)
654 DEFINE_STDCALL_WRAPPER(10,ITextHostImpl_TxViewChange,8)
655 DEFINE_STDCALL_WRAPPER(11,ITextHostImpl_TxCreateCaret,16)
656 DEFINE_STDCALL_WRAPPER(12,ITextHostImpl_TxShowCaret,8)
657 DEFINE_STDCALL_WRAPPER(13,ITextHostImpl_TxSetCaretPos,12)
658 DEFINE_STDCALL_WRAPPER(14,ITextHostImpl_TxSetTimer,12)
659 DEFINE_STDCALL_WRAPPER(15,ITextHostImpl_TxKillTimer,8)
660 DEFINE_STDCALL_WRAPPER(16,ITextHostImpl_TxScrollWindowEx,32)
661 DEFINE_STDCALL_WRAPPER(17,ITextHostImpl_TxSetCapture,8)
662 DEFINE_STDCALL_WRAPPER(18,ITextHostImpl_TxSetFocus,4)
663 DEFINE_STDCALL_WRAPPER(19,ITextHostImpl_TxSetCursor,12)
664 DEFINE_STDCALL_WRAPPER(20,ITextHostImpl_TxScreenToClient,8)
665 DEFINE_STDCALL_WRAPPER(21,ITextHostImpl_TxClientToScreen,8)
666 DEFINE_STDCALL_WRAPPER(22,ITextHostImpl_TxActivate,8)
667 DEFINE_STDCALL_WRAPPER(23,ITextHostImpl_TxDeactivate,8)
668 DEFINE_STDCALL_WRAPPER(24,ITextHostImpl_TxGetClientRect,8)
669 DEFINE_STDCALL_WRAPPER(25,ITextHostImpl_TxGetViewInset,8)
670 DEFINE_STDCALL_WRAPPER(26,ITextHostImpl_TxGetCharFormat,8)
671 DEFINE_STDCALL_WRAPPER(27,ITextHostImpl_TxGetParaFormat,8)
672 DEFINE_STDCALL_WRAPPER(28,ITextHostImpl_TxGetSysColor,8)
673 DEFINE_STDCALL_WRAPPER(29,ITextHostImpl_TxGetBackStyle,8)
674 DEFINE_STDCALL_WRAPPER(30,ITextHostImpl_TxGetMaxLength,8)
675 DEFINE_STDCALL_WRAPPER(31,ITextHostImpl_TxGetScrollBars,8)
676 DEFINE_STDCALL_WRAPPER(32,ITextHostImpl_TxGetPasswordChar,8)
677 DEFINE_STDCALL_WRAPPER(33,ITextHostImpl_TxGetAcceleratorPos,8)
678 DEFINE_STDCALL_WRAPPER(34,ITextHostImpl_TxGetExtent,8)
679 DEFINE_STDCALL_WRAPPER(35,ITextHostImpl_OnTxCharFormatChange,8)
680 DEFINE_STDCALL_WRAPPER(36,ITextHostImpl_OnTxParaFormatChange,8)
681 DEFINE_STDCALL_WRAPPER(37,ITextHostImpl_TxGetPropertyBits,12)
682 DEFINE_STDCALL_WRAPPER(38,ITextHostImpl_TxNotify,12)
683 DEFINE_STDCALL_WRAPPER(39,ITextHostImpl_TxImmGetContext,4)
684 DEFINE_STDCALL_WRAPPER(40,ITextHostImpl_TxImmReleaseContext,8)
685 DEFINE_STDCALL_WRAPPER(41,ITextHostImpl_TxGetSelectionBarWidth,8)
686 /* ITextHost2 */
687 DEFINE_STDCALL_WRAPPER(42,ITextHostImpl_TxIsDoubleClickPending,4)
688 DEFINE_STDCALL_WRAPPER(43,ITextHostImpl_TxGetWindow,8)
689 DEFINE_STDCALL_WRAPPER(44,ITextHostImpl_TxSetForegroundWindow,4)
690 DEFINE_STDCALL_WRAPPER(45,ITextHostImpl_TxGetPalette,4)
691 DEFINE_STDCALL_WRAPPER(46,ITextHostImpl_TxGetEastAsianFlags,8)
692 DEFINE_STDCALL_WRAPPER(47,ITextHostImpl_TxSetCursor2,12)
693 DEFINE_STDCALL_WRAPPER(48,ITextHostImpl_TxFreeTextServicesNotification,4)
694 DEFINE_STDCALL_WRAPPER(49,ITextHostImpl_TxGetEditStyle,12)
695 DEFINE_STDCALL_WRAPPER(50,ITextHostImpl_TxGetWindowStyles,12)
696 DEFINE_STDCALL_WRAPPER(51,ITextHostImpl_TxShowDropCaret,16)
697 DEFINE_STDCALL_WRAPPER(52,ITextHostImpl_TxDestroyCaret,4)
698 DEFINE_STDCALL_WRAPPER(53,ITextHostImpl_TxGetHorzExtent,8)
700 const ITextHost2Vtbl text_host2_stdcall_vtbl =
702 NULL,
703 NULL,
704 NULL,
705 STDCALL(ITextHostImpl_TxGetDC),
706 STDCALL(ITextHostImpl_TxReleaseDC),
707 STDCALL(ITextHostImpl_TxShowScrollBar),
708 STDCALL(ITextHostImpl_TxEnableScrollBar),
709 STDCALL(ITextHostImpl_TxSetScrollRange),
710 STDCALL(ITextHostImpl_TxSetScrollPos),
711 STDCALL(ITextHostImpl_TxInvalidateRect),
712 STDCALL(ITextHostImpl_TxViewChange),
713 STDCALL(ITextHostImpl_TxCreateCaret),
714 STDCALL(ITextHostImpl_TxShowCaret),
715 STDCALL(ITextHostImpl_TxSetCaretPos),
716 STDCALL(ITextHostImpl_TxSetTimer),
717 STDCALL(ITextHostImpl_TxKillTimer),
718 STDCALL(ITextHostImpl_TxScrollWindowEx),
719 STDCALL(ITextHostImpl_TxSetCapture),
720 STDCALL(ITextHostImpl_TxSetFocus),
721 STDCALL(ITextHostImpl_TxSetCursor),
722 STDCALL(ITextHostImpl_TxScreenToClient),
723 STDCALL(ITextHostImpl_TxClientToScreen),
724 STDCALL(ITextHostImpl_TxActivate),
725 STDCALL(ITextHostImpl_TxDeactivate),
726 STDCALL(ITextHostImpl_TxGetClientRect),
727 STDCALL(ITextHostImpl_TxGetViewInset),
728 STDCALL(ITextHostImpl_TxGetCharFormat),
729 STDCALL(ITextHostImpl_TxGetParaFormat),
730 STDCALL(ITextHostImpl_TxGetSysColor),
731 STDCALL(ITextHostImpl_TxGetBackStyle),
732 STDCALL(ITextHostImpl_TxGetMaxLength),
733 STDCALL(ITextHostImpl_TxGetScrollBars),
734 STDCALL(ITextHostImpl_TxGetPasswordChar),
735 STDCALL(ITextHostImpl_TxGetAcceleratorPos),
736 STDCALL(ITextHostImpl_TxGetExtent),
737 STDCALL(ITextHostImpl_OnTxCharFormatChange),
738 STDCALL(ITextHostImpl_OnTxParaFormatChange),
739 STDCALL(ITextHostImpl_TxGetPropertyBits),
740 STDCALL(ITextHostImpl_TxNotify),
741 STDCALL(ITextHostImpl_TxImmGetContext),
742 STDCALL(ITextHostImpl_TxImmReleaseContext),
743 STDCALL(ITextHostImpl_TxGetSelectionBarWidth),
744 /* ITextHost2 */
745 STDCALL(ITextHostImpl_TxIsDoubleClickPending),
746 STDCALL(ITextHostImpl_TxGetWindow),
747 STDCALL(ITextHostImpl_TxSetForegroundWindow),
748 STDCALL(ITextHostImpl_TxGetPalette),
749 STDCALL(ITextHostImpl_TxGetEastAsianFlags),
750 STDCALL(ITextHostImpl_TxSetCursor2),
751 STDCALL(ITextHostImpl_TxFreeTextServicesNotification),
752 STDCALL(ITextHostImpl_TxGetEditStyle),
753 STDCALL(ITextHostImpl_TxGetWindowStyles),
754 STDCALL(ITextHostImpl_TxShowDropCaret),
755 STDCALL(ITextHostImpl_TxDestroyCaret),
756 STDCALL(ITextHostImpl_TxGetHorzExtent)
759 #endif /* __ASM_USE_THISCALL_WRAPPER */
761 static const ITextHost2Vtbl textHostVtbl =
763 ITextHostImpl_QueryInterface,
764 ITextHostImpl_AddRef,
765 ITextHostImpl_Release,
766 THISCALL(ITextHostImpl_TxGetDC),
767 THISCALL(ITextHostImpl_TxReleaseDC),
768 THISCALL(ITextHostImpl_TxShowScrollBar),
769 THISCALL(ITextHostImpl_TxEnableScrollBar),
770 THISCALL(ITextHostImpl_TxSetScrollRange),
771 THISCALL(ITextHostImpl_TxSetScrollPos),
772 THISCALL(ITextHostImpl_TxInvalidateRect),
773 THISCALL(ITextHostImpl_TxViewChange),
774 THISCALL(ITextHostImpl_TxCreateCaret),
775 THISCALL(ITextHostImpl_TxShowCaret),
776 THISCALL(ITextHostImpl_TxSetCaretPos),
777 THISCALL(ITextHostImpl_TxSetTimer),
778 THISCALL(ITextHostImpl_TxKillTimer),
779 THISCALL(ITextHostImpl_TxScrollWindowEx),
780 THISCALL(ITextHostImpl_TxSetCapture),
781 THISCALL(ITextHostImpl_TxSetFocus),
782 THISCALL(ITextHostImpl_TxSetCursor),
783 THISCALL(ITextHostImpl_TxScreenToClient),
784 THISCALL(ITextHostImpl_TxClientToScreen),
785 THISCALL(ITextHostImpl_TxActivate),
786 THISCALL(ITextHostImpl_TxDeactivate),
787 THISCALL(ITextHostImpl_TxGetClientRect),
788 THISCALL(ITextHostImpl_TxGetViewInset),
789 THISCALL(ITextHostImpl_TxGetCharFormat),
790 THISCALL(ITextHostImpl_TxGetParaFormat),
791 THISCALL(ITextHostImpl_TxGetSysColor),
792 THISCALL(ITextHostImpl_TxGetBackStyle),
793 THISCALL(ITextHostImpl_TxGetMaxLength),
794 THISCALL(ITextHostImpl_TxGetScrollBars),
795 THISCALL(ITextHostImpl_TxGetPasswordChar),
796 THISCALL(ITextHostImpl_TxGetAcceleratorPos),
797 THISCALL(ITextHostImpl_TxGetExtent),
798 THISCALL(ITextHostImpl_OnTxCharFormatChange),
799 THISCALL(ITextHostImpl_OnTxParaFormatChange),
800 THISCALL(ITextHostImpl_TxGetPropertyBits),
801 THISCALL(ITextHostImpl_TxNotify),
802 THISCALL(ITextHostImpl_TxImmGetContext),
803 THISCALL(ITextHostImpl_TxImmReleaseContext),
804 THISCALL(ITextHostImpl_TxGetSelectionBarWidth),
805 /* ITextHost2 */
806 THISCALL(ITextHostImpl_TxIsDoubleClickPending),
807 THISCALL(ITextHostImpl_TxGetWindow),
808 THISCALL(ITextHostImpl_TxSetForegroundWindow),
809 THISCALL(ITextHostImpl_TxGetPalette),
810 THISCALL(ITextHostImpl_TxGetEastAsianFlags),
811 THISCALL(ITextHostImpl_TxSetCursor2),
812 THISCALL(ITextHostImpl_TxFreeTextServicesNotification),
813 THISCALL(ITextHostImpl_TxGetEditStyle),
814 THISCALL(ITextHostImpl_TxGetWindowStyles),
815 THISCALL(ITextHostImpl_TxShowDropCaret),
816 THISCALL(ITextHostImpl_TxDestroyCaret),
817 THISCALL(ITextHostImpl_TxGetHorzExtent)
820 static const char * const edit_messages[] =
822 "EM_GETSEL", "EM_SETSEL", "EM_GETRECT", "EM_SETRECT",
823 "EM_SETRECTNP", "EM_SCROLL", "EM_LINESCROLL", "EM_SCROLLCARET",
824 "EM_GETMODIFY", "EM_SETMODIFY", "EM_GETLINECOUNT", "EM_LINEINDEX",
825 "EM_SETHANDLE", "EM_GETHANDLE", "EM_GETTHUMB", "EM_UNKNOWN_BF",
826 "EM_UNKNOWN_C0", "EM_LINELENGTH", "EM_REPLACESEL", "EM_UNKNOWN_C3",
827 "EM_GETLINE", "EM_LIMITTEXT", "EM_CANUNDO", "EM_UNDO",
828 "EM_FMTLINES", "EM_LINEFROMCHAR", "EM_UNKNOWN_CA", "EM_SETTABSTOPS",
829 "EM_SETPASSWORDCHAR", "EM_EMPTYUNDOBUFFER", "EM_GETFIRSTVISIBLELINE", "EM_SETREADONLY",
830 "EM_SETWORDBREAKPROC", "EM_GETWORDBREAKPROC", "EM_GETPASSWORDCHAR", "EM_SETMARGINS",
831 "EM_GETMARGINS", "EM_GETLIMITTEXT", "EM_POSFROMCHAR", "EM_CHARFROMPOS",
832 "EM_SETIMESTATUS", "EM_GETIMESTATUS"
835 static const char * const richedit_messages[] =
837 "EM_CANPASTE", "EM_DISPLAYBAND", "EM_EXGETSEL", "EM_EXLIMITTEXT",
838 "EM_EXLINEFROMCHAR", "EM_EXSETSEL", "EM_FINDTEXT", "EM_FORMATRANGE",
839 "EM_GETCHARFORMAT", "EM_GETEVENTMASK", "EM_GETOLEINTERFACE", "EM_GETPARAFORMAT",
840 "EM_GETSELTEXT", "EM_HIDESELECTION", "EM_PASTESPECIAL", "EM_REQUESTRESIZE",
841 "EM_SELECTIONTYPE", "EM_SETBKGNDCOLOR", "EM_SETCHARFORMAT", "EM_SETEVENTMASK",
842 "EM_SETOLECALLBACK", "EM_SETPARAFORMAT", "EM_SETTARGETDEVICE", "EM_STREAMIN",
843 "EM_STREAMOUT", "EM_GETTEXTRANGE", "EM_FINDWORDBREAK", "EM_SETOPTIONS",
844 "EM_GETOPTIONS", "EM_FINDTEXTEX", "EM_GETWORDBREAKPROCEX", "EM_SETWORDBREAKPROCEX",
845 "EM_SETUNDOLIMIT", "EM_UNKNOWN_USER_83", "EM_REDO", "EM_CANREDO",
846 "EM_GETUNDONAME", "EM_GETREDONAME", "EM_STOPGROUPTYPING", "EM_SETTEXTMODE",
847 "EM_GETTEXTMODE", "EM_AUTOURLDETECT", "EM_GETAUTOURLDETECT", "EM_SETPALETTE",
848 "EM_GETTEXTEX", "EM_GETTEXTLENGTHEX", "EM_SHOWSCROLLBAR", "EM_SETTEXTEX",
849 "EM_UNKNOWN_USER_98", "EM_UNKNOWN_USER_99", "EM_SETPUNCTUATION", "EM_GETPUNCTUATION",
850 "EM_SETWORDWRAPMODE", "EM_GETWORDWRAPMODE", "EM_SETIMECOLOR", "EM_GETIMECOLOR",
851 "EM_SETIMEOPTIONS", "EM_GETIMEOPTIONS", "EM_CONVPOSITION", "EM_UNKNOWN_USER_109",
852 "EM_UNKNOWN_USER_110", "EM_UNKNOWN_USER_111", "EM_UNKNOWN_USER_112", "EM_UNKNOWN_USER_113",
853 "EM_UNKNOWN_USER_114", "EM_UNKNOWN_USER_115", "EM_UNKNOWN_USER_116", "EM_UNKNOWN_USER_117",
854 "EM_UNKNOWN_USER_118", "EM_UNKNOWN_USER_119", "EM_SETLANGOPTIONS", "EM_GETLANGOPTIONS",
855 "EM_GETIMECOMPMODE", "EM_FINDTEXTW", "EM_FINDTEXTEXW", "EM_RECONVERSION",
856 "EM_SETIMEMODEBIAS", "EM_GETIMEMODEBIAS"
859 static const char *get_msg_name( UINT msg )
861 if (msg >= EM_GETSEL && msg <= EM_CHARFROMPOS)
862 return edit_messages[msg - EM_GETSEL];
863 if (msg >= EM_CANPASTE && msg <= EM_GETIMEMODEBIAS)
864 return richedit_messages[msg - EM_CANPASTE];
865 return "";
868 static BOOL create_windowed_editor( HWND hwnd, CREATESTRUCTW *create, BOOL emulate_10 )
870 struct host *host = host_create( hwnd, create, emulate_10 );
871 IUnknown *unk;
872 HRESULT hr;
874 if (!host) return FALSE;
876 hr = create_text_services( NULL, (ITextHost *)&host->ITextHost_iface, &unk, emulate_10 );
877 if (FAILED( hr ))
879 ITextHost2_Release( &host->ITextHost_iface );
880 return FALSE;
882 IUnknown_QueryInterface( unk, &IID_ITextServices, (void **)&host->text_srv );
883 IUnknown_Release( unk );
885 SetWindowLongPtrW( hwnd, 0, (LONG_PTR)host );
887 return TRUE;
890 static HRESULT get_lineA( ITextServices *text_srv, WPARAM wparam, LPARAM lparam, LRESULT *res )
892 LRESULT len = USHRT_MAX;
893 WORD sizeA;
894 HRESULT hr;
895 WCHAR *buf;
897 *res = 0;
898 sizeA = *(WORD *)lparam;
899 *(WORD *)lparam = 0;
900 if (!sizeA) return S_OK;
901 buf = heap_alloc( len * sizeof(WCHAR) );
902 if (!buf) return E_OUTOFMEMORY;
903 *(WORD *)buf = len;
904 hr = ITextServices_TxSendMessage( text_srv, EM_GETLINE, wparam, (LPARAM)buf, &len );
905 if (hr == S_OK && len)
907 len = WideCharToMultiByte( CP_ACP, 0, buf, len, (char *)lparam, sizeA, NULL, NULL );
908 if (!len && GetLastError() == ERROR_INSUFFICIENT_BUFFER) len = sizeA;
909 if (len < sizeA) ((char *)lparam)[len] = '\0';
910 *res = len;
912 heap_free( buf );
913 return hr;
916 static HRESULT get_text_rangeA( struct host *host, TEXTRANGEA *rangeA, LRESULT *res )
918 TEXTRANGEW range;
919 HRESULT hr;
920 unsigned int count;
921 LRESULT len;
923 *res = 0;
924 if (rangeA->chrg.cpMin < 0) return S_OK;
925 ITextServices_TxSendMessage( host->text_srv, WM_GETTEXTLENGTH, 0, 0, &len );
926 range.chrg = rangeA->chrg;
927 if ((range.chrg.cpMin == 0 && range.chrg.cpMax == -1) || range.chrg.cpMax > len)
928 range.chrg.cpMax = len;
929 if (range.chrg.cpMin >= range.chrg.cpMax) return S_OK;
930 count = range.chrg.cpMax - range.chrg.cpMin + 1;
931 range.lpstrText = heap_alloc( count * sizeof(WCHAR) );
932 if (!range.lpstrText) return E_OUTOFMEMORY;
933 hr = ITextServices_TxSendMessage( host->text_srv, EM_GETTEXTRANGE, 0, (LPARAM)&range, &len );
934 if (hr == S_OK && len)
936 if (!host->emulate_10) count = INT_MAX;
937 len = WideCharToMultiByte( CP_ACP, 0, range.lpstrText, -1, rangeA->lpstrText, count, NULL, NULL );
938 if (!host->emulate_10) *res = len - 1;
939 else
941 *res = count - 1;
942 rangeA->lpstrText[*res] = '\0';
945 heap_free( range.lpstrText );
946 return hr;
949 static HRESULT set_options( struct host *host, DWORD op, DWORD value, LRESULT *res )
951 DWORD style, old_options, new_options, change, props_mask = 0;
952 DWORD mask = ECO_AUTOWORDSELECTION | ECO_AUTOVSCROLL | ECO_AUTOHSCROLL | ECO_NOHIDESEL | ECO_READONLY |
953 ECO_WANTRETURN | ECO_SAVESEL | ECO_SELECTIONBAR | ECO_VERTICAL;
955 new_options = old_options = SendMessageW( host->window, EM_GETOPTIONS, 0, 0 );
957 switch (op)
959 case ECOOP_SET:
960 new_options = value;
961 break;
962 case ECOOP_OR:
963 new_options |= value;
964 break;
965 case ECOOP_AND:
966 new_options &= value;
967 break;
968 case ECOOP_XOR:
969 new_options ^= value;
971 new_options &= mask;
973 change = (new_options ^ old_options);
975 if (change & ECO_AUTOWORDSELECTION)
977 host->props ^= TXTBIT_AUTOWORDSEL;
978 props_mask |= TXTBIT_AUTOWORDSEL;
980 if (change & ECO_AUTOVSCROLL)
982 host->scrollbars ^= WS_VSCROLL;
983 props_mask |= TXTBIT_SCROLLBARCHANGE;
985 if (change & ECO_AUTOHSCROLL)
987 host->scrollbars ^= WS_HSCROLL;
988 props_mask |= TXTBIT_SCROLLBARCHANGE;
990 if (change & ECO_NOHIDESEL)
992 host->props ^= TXTBIT_HIDESELECTION;
993 props_mask |= TXTBIT_HIDESELECTION;
995 if (change & ECO_READONLY)
997 host->props ^= TXTBIT_READONLY;
998 props_mask |= TXTBIT_READONLY;
1000 if (change & ECO_SAVESEL)
1002 host->props ^= TXTBIT_SAVESELECTION;
1003 props_mask |= TXTBIT_SAVESELECTION;
1005 if (change & ECO_SELECTIONBAR)
1007 host->sel_bar ^= 1;
1008 props_mask |= TXTBIT_SELBARCHANGE;
1009 if (host->use_set_rect)
1011 int width = SELECTIONBAR_WIDTH;
1012 host->set_rect.left += host->sel_bar ? width : -width;
1013 props_mask |= TXTBIT_CLIENTRECTCHANGE;
1016 if (change & ECO_VERTICAL)
1018 host->props ^= TXTBIT_VERTICAL;
1019 props_mask |= TXTBIT_VERTICAL;
1021 if (change & ECO_WANTRETURN) host->want_return ^= 1;
1023 if (props_mask)
1024 ITextServices_OnTxPropertyBitsChange( host->text_srv, props_mask, host->props & props_mask );
1026 *res = new_options;
1028 mask &= ~ECO_AUTOWORDSELECTION; /* doesn't correspond to a window style */
1029 style = GetWindowLongW( host->window, GWL_STYLE );
1030 style = (style & ~mask) | (*res & mask);
1031 SetWindowLongW( host->window, GWL_STYLE, style );
1032 return S_OK;
1035 /* handle dialog mode VK_RETURN. Returns TRUE if message has been processed */
1036 static BOOL handle_dialog_enter( struct host *host )
1038 BOOL ctrl_is_down = GetKeyState( VK_CONTROL ) & 0x8000;
1040 if (ctrl_is_down) return TRUE;
1042 if (host->want_return) return FALSE;
1044 if (host->parent)
1046 DWORD id = SendMessageW( host->parent, DM_GETDEFID, 0, 0 );
1047 if (HIWORD( id ) == DC_HASDEFID)
1049 HWND ctrl = GetDlgItem( host->parent, LOWORD( id ));
1050 if (ctrl)
1052 SendMessageW( host->parent, WM_NEXTDLGCTL, (WPARAM)ctrl, TRUE );
1053 PostMessageW( ctrl, WM_KEYDOWN, VK_RETURN, 0 );
1057 return TRUE;
1060 static LRESULT send_msg_filter( struct host *host, UINT msg, WPARAM *wparam, LPARAM *lparam )
1062 MSGFILTER msgf;
1063 LRESULT res;
1065 if (!host->parent) return 0;
1066 msgf.nmhdr.hwndFrom = host->window;
1067 msgf.nmhdr.idFrom = GetWindowLongW( host->window, GWLP_ID );
1068 msgf.nmhdr.code = EN_MSGFILTER;
1069 msgf.msg = msg;
1070 msgf.wParam = *wparam;
1071 msgf.lParam = *lparam;
1072 if ((res = SendMessageW( host->parent, WM_NOTIFY, msgf.nmhdr.idFrom, (LPARAM)&msgf )))
1073 return res;
1074 *wparam = msgf.wParam;
1075 *lparam = msgf.lParam;
1077 return 0;
1080 static LRESULT RichEditWndProc_common( HWND hwnd, UINT msg, WPARAM wparam,
1081 LPARAM lparam, BOOL unicode )
1083 struct host *host;
1084 HRESULT hr = S_OK;
1085 LRESULT res = 0;
1087 TRACE( "enter hwnd %p msg %04x (%s) %Ix %Ix, unicode %d\n",
1088 hwnd, msg, get_msg_name(msg), wparam, lparam, unicode );
1090 host = (struct host *)GetWindowLongPtrW( hwnd, 0 );
1091 if (!host)
1093 if (msg == WM_NCCREATE)
1095 CREATESTRUCTW *pcs = (CREATESTRUCTW *)lparam;
1097 TRACE( "WM_NCCREATE: hwnd %p style 0x%08lx\n", hwnd, pcs->style );
1098 return create_windowed_editor( hwnd, pcs, FALSE );
1100 else return DefWindowProcW( hwnd, msg, wparam, lparam );
1103 if ((((host->event_mask & ENM_KEYEVENTS) && msg >= WM_KEYFIRST && msg <= WM_KEYLAST) ||
1104 ((host->event_mask & ENM_MOUSEEVENTS) && msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) ||
1105 ((host->event_mask & ENM_SCROLLEVENTS) && msg >= WM_HSCROLL && msg <= WM_VSCROLL)))
1107 host->notify_level++;
1108 res = send_msg_filter( host, msg, &wparam, &lparam );
1109 if (!--host->notify_level && host->defer_release)
1111 TRACE( "exit (filtered deferred release) hwnd %p msg %04x (%s) %Ix %Ix -> 0\n",
1112 hwnd, msg, get_msg_name(msg), wparam, lparam );
1113 ITextHost2_Release( &host->ITextHost_iface );
1114 return 0;
1117 if (res)
1119 TRACE( "exit (filtered %Iu) hwnd %p msg %04x (%s) %Ix %Ix -> 0\n",
1120 res, hwnd, msg, get_msg_name(msg), wparam, lparam );
1121 return 0;
1125 switch (msg)
1127 case WM_CHAR:
1129 WCHAR wc = wparam;
1131 if (!unicode) MultiByteToWideChar( CP_ACP, 0, (char *)&wparam, 1, &wc, 1 );
1132 if (wparam == '\r' && host->dialog_mode && host->emulate_10 && handle_dialog_enter( host )) break;
1133 hr = ITextServices_TxSendMessage( host->text_srv, msg, wc, lparam, &res );
1134 break;
1137 case WM_CREATE:
1139 CREATESTRUCTW *createW = (CREATESTRUCTW *)lparam;
1140 CREATESTRUCTA *createA = (CREATESTRUCTA *)lparam;
1141 void *text;
1142 WCHAR *textW = NULL;
1143 LONG codepage = unicode ? CP_UNICODE : CP_ACP;
1144 int len;
1146 ITextServices_OnTxInPlaceActivate( host->text_srv, NULL );
1148 if (lparam)
1150 text = unicode ? (void *)createW->lpszName : (void *)createA->lpszName;
1151 textW = ME_ToUnicode( codepage, text, &len );
1153 ITextServices_TxSetText( host->text_srv, textW );
1154 if (lparam) ME_EndToUnicode( codepage, textW );
1155 break;
1157 case WM_DESTROY:
1158 if (!host->notify_level) ITextHost2_Release( &host->ITextHost_iface );
1159 else host->defer_release = 1;
1160 return 0;
1162 case WM_ERASEBKGND:
1164 HDC hdc = (HDC)wparam;
1165 RECT rc;
1166 HBRUSH brush;
1168 if (GetUpdateRect( hwnd, &rc, TRUE ))
1170 brush = CreateSolidBrush( ITextHost_TxGetSysColor( &host->ITextHost_iface, COLOR_WINDOW ) );
1171 FillRect( hdc, &rc, brush );
1172 DeleteObject( brush );
1174 return 1;
1176 case EM_FINDTEXT:
1178 FINDTEXTW *params = (FINDTEXTW *)lparam;
1179 FINDTEXTW new_params;
1180 int len;
1182 if (!unicode)
1184 new_params.chrg = params->chrg;
1185 new_params.lpstrText = ME_ToUnicode( CP_ACP, (char *)params->lpstrText, &len );
1186 params = &new_params;
1188 hr = ITextServices_TxSendMessage( host->text_srv, EM_FINDTEXTW, wparam, (LPARAM)params, &res );
1189 if (!unicode) ME_EndToUnicode( CP_ACP, (WCHAR *)new_params.lpstrText );
1190 break;
1192 case EM_FINDTEXTEX:
1194 FINDTEXTEXA *paramsA = (FINDTEXTEXA *)lparam;
1195 FINDTEXTEXW *params = (FINDTEXTEXW *)lparam;
1196 FINDTEXTEXW new_params;
1197 int len;
1199 if (!unicode)
1201 new_params.chrg = params->chrg;
1202 new_params.lpstrText = ME_ToUnicode( CP_ACP, (char *)params->lpstrText, &len );
1203 params = &new_params;
1205 hr = ITextServices_TxSendMessage( host->text_srv, EM_FINDTEXTEXW, wparam, (LPARAM)params, &res );
1206 if (!unicode)
1208 ME_EndToUnicode( CP_ACP, (WCHAR *)new_params.lpstrText );
1209 paramsA->chrgText = params->chrgText;
1211 break;
1213 case WM_GETDLGCODE:
1214 if (lparam) host->dialog_mode = TRUE;
1216 res = DLGC_WANTCHARS | DLGC_WANTTAB | DLGC_WANTARROWS;
1217 if (host->props & TXTBIT_MULTILINE) res |= DLGC_WANTMESSAGE;
1218 if (!(host->props & TXTBIT_SAVESELECTION)) res |= DLGC_HASSETSEL;
1219 break;
1221 case EM_GETLINE:
1222 if (unicode) hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res );
1223 else hr = get_lineA( host->text_srv, wparam, lparam, &res );
1224 break;
1226 case EM_GETPASSWORDCHAR:
1227 ITextHost_TxGetPasswordChar( &host->ITextHost_iface, (WCHAR *)&res );
1228 break;
1230 case EM_GETRECT:
1231 hr = ITextHost_TxGetClientRect( &host->ITextHost_iface, (RECT *)lparam );
1232 break;
1234 case EM_GETSELTEXT:
1236 TEXTRANGEA range;
1238 if (unicode) hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res );
1239 else
1241 ITextServices_TxSendMessage( host->text_srv, EM_EXGETSEL, 0, (LPARAM)&range.chrg, &res );
1242 range.lpstrText = (char *)lparam;
1243 range.lpstrText[0] = '\0';
1244 hr = get_text_rangeA( host, &range, &res );
1246 break;
1248 case EM_GETOPTIONS:
1249 if (host->props & TXTBIT_READONLY) res |= ECO_READONLY;
1250 if (!(host->props & TXTBIT_HIDESELECTION)) res |= ECO_NOHIDESEL;
1251 if (host->props & TXTBIT_SAVESELECTION) res |= ECO_SAVESEL;
1252 if (host->props & TXTBIT_AUTOWORDSEL) res |= ECO_AUTOWORDSELECTION;
1253 if (host->props & TXTBIT_VERTICAL) res |= ECO_VERTICAL;
1254 if (host->scrollbars & ES_AUTOHSCROLL) res |= ECO_AUTOHSCROLL;
1255 if (host->scrollbars & ES_AUTOVSCROLL) res |= ECO_AUTOVSCROLL;
1256 if (host->want_return) res |= ECO_WANTRETURN;
1257 if (host->sel_bar) res |= ECO_SELECTIONBAR;
1258 break;
1260 case WM_GETTEXT:
1262 GETTEXTEX params;
1264 params.cb = wparam * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
1265 params.flags = GT_USECRLF;
1266 params.codepage = unicode ? CP_UNICODE : CP_ACP;
1267 params.lpDefaultChar = NULL;
1268 params.lpUsedDefChar = NULL;
1269 hr = ITextServices_TxSendMessage( host->text_srv, EM_GETTEXTEX, (WPARAM)&params, lparam, &res );
1270 break;
1272 case WM_GETTEXTLENGTH:
1274 GETTEXTLENGTHEX params;
1276 params.flags = GTL_CLOSE | (host->emulate_10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS;
1277 params.codepage = unicode ? CP_UNICODE : CP_ACP;
1278 hr = ITextServices_TxSendMessage( host->text_srv, EM_GETTEXTLENGTHEX, (WPARAM)&params, 0, &res );
1279 break;
1281 case EM_GETTEXTRANGE:
1282 if (unicode) hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res );
1283 else hr = get_text_rangeA( host, (TEXTRANGEA *)lparam, &res );
1284 break;
1286 case WM_KEYDOWN:
1287 switch (LOWORD( wparam ))
1289 case VK_ESCAPE:
1290 if (host->dialog_mode && host->parent)
1291 PostMessageW( host->parent, WM_CLOSE, 0, 0 );
1292 break;
1293 case VK_TAB:
1294 if (host->dialog_mode && host->parent)
1295 SendMessageW( host->parent, WM_NEXTDLGCTL, GetKeyState( VK_SHIFT ) & 0x8000, 0 );
1296 break;
1297 case VK_RETURN:
1298 if (host->dialog_mode && !host->emulate_10 && handle_dialog_enter( host )) break;
1299 /* fall through */
1300 default:
1301 hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res );
1303 break;
1305 case WM_PAINT:
1306 case WM_PRINTCLIENT:
1308 HDC hdc;
1309 RECT rc, client, update;
1310 PAINTSTRUCT ps;
1311 HBRUSH brush = CreateSolidBrush( ITextHost_TxGetSysColor( &host->ITextHost_iface, COLOR_WINDOW ) );
1313 ITextHost_TxGetClientRect( &host->ITextHost_iface, &client );
1315 if (msg == WM_PAINT)
1317 hdc = BeginPaint( hwnd, &ps );
1318 update = ps.rcPaint;
1320 else
1322 hdc = (HDC)wparam;
1323 update = client;
1326 brush = SelectObject( hdc, brush );
1328 /* Erase area outside of the formatting rectangle */
1329 if (update.top < client.top)
1331 rc = update;
1332 rc.bottom = client.top;
1333 PatBlt( hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1334 update.top = client.top;
1336 if (update.bottom > client.bottom)
1338 rc = update;
1339 rc.top = client.bottom;
1340 PatBlt( hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1341 update.bottom = client.bottom;
1343 if (update.left < client.left)
1345 rc = update;
1346 rc.right = client.left;
1347 PatBlt( hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1348 update.left = client.left;
1350 if (update.right > client.right)
1352 rc = update;
1353 rc.left = client.right;
1354 PatBlt( hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1355 update.right = client.right;
1358 ITextServices_TxDraw( host->text_srv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, NULL, NULL,
1359 &update, NULL, 0, TXTVIEW_ACTIVE );
1360 DeleteObject( SelectObject( hdc, brush ) );
1361 if (msg == WM_PAINT) EndPaint( hwnd, &ps );
1362 return 0;
1364 case EM_REPLACESEL:
1366 int len;
1367 LONG codepage = unicode ? CP_UNICODE : CP_ACP;
1368 WCHAR *text = ME_ToUnicode( codepage, (void *)lparam, &len );
1370 hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, (LPARAM)text, &res );
1371 ME_EndToUnicode( codepage, text );
1372 res = len;
1373 break;
1375 case EM_SETBKGNDCOLOR:
1376 res = ITextHost_TxGetSysColor( &host->ITextHost_iface, COLOR_WINDOW );
1377 host->use_back_colour = !wparam;
1378 if (host->use_back_colour) host->back_colour = lparam;
1379 InvalidateRect( hwnd, NULL, TRUE );
1380 break;
1382 case WM_SETCURSOR:
1384 POINT pos;
1385 RECT rect;
1387 if (hwnd != (HWND)wparam) break;
1388 GetCursorPos( &pos );
1389 ScreenToClient( hwnd, &pos );
1390 ITextHost_TxGetClientRect( &host->ITextHost_iface, &rect );
1391 if (PtInRect( &rect, pos ))
1392 ITextServices_OnTxSetCursor( host->text_srv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, pos.x, pos.y );
1393 else ITextHost_TxSetCursor( &host->ITextHost_iface, LoadCursorW( NULL, MAKEINTRESOURCEW( IDC_ARROW ) ), FALSE );
1394 break;
1396 case EM_SETEVENTMASK:
1397 host->event_mask = lparam;
1398 hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res );
1399 break;
1401 case EM_SETOPTIONS:
1402 hr = set_options( host, wparam, lparam, &res );
1403 break;
1405 case EM_SETPASSWORDCHAR:
1406 if (wparam == host->password_char) break;
1407 host->password_char = wparam;
1408 if (wparam) host->props |= TXTBIT_USEPASSWORD;
1409 else host->props &= ~TXTBIT_USEPASSWORD;
1410 ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_USEPASSWORD, host->props & TXTBIT_USEPASSWORD );
1411 break;
1413 case EM_SETREADONLY:
1415 DWORD op = wparam ? ECOOP_OR : ECOOP_AND;
1416 DWORD mask = wparam ? ECO_READONLY : ~ECO_READONLY;
1418 SendMessageW( hwnd, EM_SETOPTIONS, op, mask );
1419 return 1;
1421 case EM_SETRECT:
1422 case EM_SETRECTNP:
1424 RECT *rc = (RECT *)lparam;
1426 if (!rc) host->use_set_rect = 0;
1427 else
1429 if (wparam >= 2) break;
1430 host->set_rect = *rc;
1431 if (host->client_edge)
1433 InflateRect( &host->set_rect, 1, 0 );
1434 host->set_rect.top -= 1;
1436 if (!wparam) IntersectRect( &host->set_rect, &host->set_rect, &host->client_rect );
1437 host->use_set_rect = 1;
1439 ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_CLIENTRECTCHANGE, 0 );
1440 break;
1442 case WM_SETTEXT:
1444 char *textA = (char *)lparam;
1445 WCHAR *text = (WCHAR *)lparam;
1446 int len;
1448 if (!unicode && textA && strncmp( textA, "{\\rtf", 5 ) && strncmp( textA, "{\\urtf", 6 ))
1449 text = ME_ToUnicode( CP_ACP, textA, &len );
1450 hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, (LPARAM)text, &res );
1451 if (text != (WCHAR *)lparam) ME_EndToUnicode( CP_ACP, text );
1452 break;
1454 case EM_SHOWSCROLLBAR:
1456 DWORD mask = 0, new;
1458 if (wparam == SB_HORZ) mask = WS_HSCROLL;
1459 else if (wparam == SB_VERT) mask = WS_VSCROLL;
1460 else if (wparam == SB_BOTH) mask = WS_HSCROLL | WS_VSCROLL;
1462 if (mask)
1464 new = lparam ? mask : 0;
1465 if ((host->scrollbars & mask) != new)
1467 host->scrollbars &= ~mask;
1468 host->scrollbars |= new;
1469 ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_SCROLLBARCHANGE, 0 );
1473 res = 0;
1474 break;
1476 case WM_WINDOWPOSCHANGED:
1478 RECT client;
1479 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1481 hr = S_FALSE; /* call defwndproc */
1482 if (winpos->flags & SWP_NOCLIENTSIZE) break;
1483 GetClientRect( hwnd, &client );
1484 if (host->use_set_rect)
1486 host->set_rect.right += client.right - host->client_rect.right;
1487 host->set_rect.bottom += client.bottom - host->client_rect.bottom;
1489 host->client_rect = client;
1490 ITextServices_OnTxPropertyBitsChange( host->text_srv, TXTBIT_CLIENTRECTCHANGE, 0 );
1491 break;
1493 default:
1494 hr = ITextServices_TxSendMessage( host->text_srv, msg, wparam, lparam, &res );
1497 if (hr == S_FALSE)
1498 res = DefWindowProcW( hwnd, msg, wparam, lparam );
1500 TRACE( "exit hwnd %p msg %04x (%s) %Ix %Ix, unicode %d -> %Iu\n",
1501 hwnd, msg, get_msg_name(msg), wparam, lparam, unicode, res );
1503 return res;
1506 static LRESULT WINAPI RichEditWndProcW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
1508 BOOL unicode = TRUE;
1510 /* Under Win9x RichEdit20W returns ANSI strings, see the tests. */
1511 if (msg == WM_GETTEXT && (GetVersion() & 0x80000000))
1512 unicode = FALSE;
1514 return RichEditWndProc_common( hwnd, msg, wparam, lparam, unicode );
1517 static LRESULT WINAPI RichEditWndProcA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
1519 return RichEditWndProc_common( hwnd, msg, wparam, lparam, FALSE );
1522 /******************************************************************
1523 * RichEditANSIWndProc (RICHED20.10)
1525 LRESULT WINAPI RichEditANSIWndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
1527 return RichEditWndProcA( hwnd, msg, wparam, lparam );
1530 /******************************************************************
1531 * RichEdit10ANSIWndProc (RICHED20.9)
1533 LRESULT WINAPI RichEdit10ANSIWndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
1535 if (msg == WM_NCCREATE && !GetWindowLongPtrW( hwnd, 0 ))
1537 CREATESTRUCTW *pcs = (CREATESTRUCTW *)lparam;
1539 TRACE( "WM_NCCREATE: hwnd %p style 0x%08lx\n", hwnd, pcs->style );
1540 return create_windowed_editor( hwnd, pcs, TRUE );
1542 return RichEditANSIWndProc( hwnd, msg, wparam, lparam );
1545 static LRESULT WINAPI REComboWndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
1547 /* FIXME: Not implemented */
1548 TRACE( "hwnd %p msg %04x (%s) %08Ix %08Ix\n",
1549 hwnd, msg, get_msg_name( msg ), wparam, lparam );
1550 return DefWindowProcW( hwnd, msg, wparam, lparam );
1553 static LRESULT WINAPI REListWndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
1555 /* FIXME: Not implemented */
1556 TRACE( "hwnd %p msg %04x (%s) %08Ix %08Ix\n",
1557 hwnd, msg, get_msg_name( msg ), wparam, lparam );
1558 return DefWindowProcW( hwnd, msg, wparam, lparam );
1561 /******************************************************************
1562 * REExtendedRegisterClass (RICHED20.8)
1564 * FIXME undocumented
1565 * Need to check for errors and implement controls and callbacks
1567 LRESULT WINAPI REExtendedRegisterClass( void )
1569 WNDCLASSW wc;
1570 UINT result;
1572 FIXME( "semi stub\n" );
1573 wc.cbClsExtra = 0;
1574 wc.cbWndExtra = 4;
1575 wc.hInstance = NULL;
1576 wc.hIcon = NULL;
1577 wc.hCursor = NULL;
1578 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1579 wc.lpszMenuName = NULL;
1581 if (!listbox_registered)
1583 wc.style = CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS;
1584 wc.lpfnWndProc = REListWndProc;
1585 wc.lpszClassName = L"REListBox20W";
1586 if (RegisterClassW( &wc )) listbox_registered = TRUE;
1589 if (!combobox_registered)
1591 wc.style = CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
1592 wc.lpfnWndProc = REComboWndProc;
1593 wc.lpszClassName = L"REComboBox20W";
1594 if (RegisterClassW( &wc )) combobox_registered = TRUE;
1597 result = 0;
1598 if (listbox_registered) result += 1;
1599 if (combobox_registered) result += 2;
1601 return result;
1604 static BOOL register_classes( HINSTANCE instance )
1606 WNDCLASSW wcW;
1607 WNDCLASSA wcA;
1609 wcW.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
1610 wcW.lpfnWndProc = RichEditWndProcW;
1611 wcW.cbClsExtra = 0;
1612 wcW.cbWndExtra = sizeof(struct host *);
1613 wcW.hInstance = NULL; /* hInstance would register DLL-local class */
1614 wcW.hIcon = NULL;
1615 wcW.hCursor = LoadCursorW( NULL, (LPWSTR)IDC_IBEAM );
1616 wcW.hbrBackground = GetStockObject( NULL_BRUSH );
1617 wcW.lpszMenuName = NULL;
1619 if (!(GetVersion() & 0x80000000))
1621 wcW.lpszClassName = RICHEDIT_CLASS20W;
1622 if (!RegisterClassW( &wcW )) return FALSE;
1623 wcW.lpszClassName = MSFTEDIT_CLASS;
1624 if (!RegisterClassW( &wcW )) return FALSE;
1626 else
1628 /* WNDCLASSA/W have the same layout */
1629 wcW.lpszClassName = (LPCWSTR)"RichEdit20W";
1630 if (!RegisterClassA( (WNDCLASSA *)&wcW )) return FALSE;
1631 wcW.lpszClassName = (LPCWSTR)"RichEdit50W";
1632 if (!RegisterClassA( (WNDCLASSA *)&wcW )) return FALSE;
1635 wcA.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
1636 wcA.lpfnWndProc = RichEditWndProcA;
1637 wcA.cbClsExtra = 0;
1638 wcA.cbWndExtra = sizeof(struct host *);
1639 wcA.hInstance = NULL; /* hInstance would register DLL-local class */
1640 wcA.hIcon = NULL;
1641 wcA.hCursor = LoadCursorW( NULL, (LPWSTR)IDC_IBEAM );
1642 wcA.hbrBackground = GetStockObject(NULL_BRUSH);
1643 wcA.lpszMenuName = NULL;
1644 wcA.lpszClassName = RICHEDIT_CLASS20A;
1645 if (!RegisterClassA( &wcA )) return FALSE;
1646 wcA.lpszClassName = "RichEdit50A";
1647 if (!RegisterClassA( &wcA )) return FALSE;
1649 return TRUE;
1652 BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved )
1654 switch (reason)
1656 case DLL_PROCESS_ATTACH:
1657 dll_instance = instance;
1658 DisableThreadLibraryCalls( instance );
1659 if (!register_classes( instance )) return FALSE;
1660 LookupInit();
1661 break;
1663 case DLL_PROCESS_DETACH:
1664 if (reserved) break;
1665 UnregisterClassW( RICHEDIT_CLASS20W, 0 );
1666 UnregisterClassW( MSFTEDIT_CLASS, 0 );
1667 UnregisterClassA( RICHEDIT_CLASS20A, 0 );
1668 UnregisterClassA( "RichEdit50A", 0 );
1669 if (listbox_registered) UnregisterClassW( L"REListBox20W", 0 );
1670 if (combobox_registered) UnregisterClassW( L"REComboBox20W", 0 );
1671 LookupCleanup();
1672 release_typelib();
1673 break;
1675 return TRUE;