Release 970329
[wine/multimedia.git] / controls / edit.c
blob6f6f5ceef79ed92a7c48086fd1ad4f674d2b1f93
1 /*
2 * Edit control
4 * Copyright David W. Metcalfe, 1994
5 * Copyright William Magro, 1995, 1996
6 * Copyright Frans van Dorsselaer, 1996, 1997
8 */
11 * please read EDIT.TODO (and update it when you change things)
12 * It also contains a discussion about the 16 to 32 bit transition.
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include "windows.h"
21 #include "win.h"
22 #include "combo.h"
23 #include "local.h"
24 #include "resource.h"
25 #include "stddebug.h"
26 #include "debug.h"
27 #include "xmalloc.h"
29 #include "callback.h"
32 #define BUFLIMIT_MULTI 65534 /* maximum text buffer length (not including '\0') */
33 /* FIXME: BTW, new specs say 65535 (do you dare ???) */
34 #define BUFLIMIT_SINGLE 32766
35 #define BUFSTART_MULTI 1024 /* starting length for multi-line control */
36 #define BUFSTART_SINGLE 256 /* starting length for single line control */
37 #define GROWLENGTH 64 /* buffers grow by this much */
38 #define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */
40 #define EF_TEXTCHANGED 0x0001
41 #define EF_FOCUSED 0x0002
43 typedef enum
45 END_0 = 0,
46 END_DELIMIT,
47 END_NONE,
48 END_HARD,
49 END_SOFT,
50 } LINE_END;
52 typedef struct {
53 INT32 offset;
54 INT32 length;
55 LINE_END ending;
56 } LINEDEF;
58 typedef struct
60 HLOCAL16 hBuf16; /* For when a 16-bit multiline edit
61 * control gets a EM_GETHANDLE (which
62 * should return 16-bit local heap).
63 * From that point on we _have_ to keep
64 * using 16-bit local heap (apps rely
65 * on that ... bummer).
67 HLOCAL32 hBuf32; /* Don't worry about 'LOCAL'. LOCAL32 is
68 * identical to GLOBAL32, which is
69 * essentially a HANDLE32 created with
70 * HeapAlloc(GetProcessHeap(), ...) plus
71 * a global32 (and thus local32)
72 * descriptor, which we can return upon
73 * EM_GETHANDLE32.
74 * It is 32-bit linear addressing, so
75 * everything is fine.
77 LPSTR text; /* Depending on the fact that we are a
78 * 16 or 32 bit control, this is the
79 * pointer that we get after
80 * LocalLock32(hBuf23) (which is a typecast :-)
81 * or LOCAL_Lock(hBuf16).
82 * This is always a 32-bit linear pointer.
84 HFONT32 hFont;
85 LINEDEF *LineDefs; /* Internal table for (soft) linebreaks */
86 INT32 TextWidth; /* width of the widest line in pixels */
87 INT32 XOffset; /* offset of the viewport in pixels */
88 INT32 FirstVisibleLine;
89 INT32 LineCount;
90 INT32 LineHeight; /* height of a screen line in pixels */
91 INT32 AveCharWidth; /* average character width in pixels */
92 INT32 BufLimit;
93 INT32 BufSize;
94 UINT32 eState; /* EF flags */
95 INT32 UndoInsertLen;
96 INT32 UndoPos;
97 INT32 UndoBufSize;
98 HLOCAL32 hUndoBuf;
99 LPSTR UndoText;
100 INT32 SelStart; /* offset of selection start, == SelEnd if no selection */
101 INT32 SelEnd; /* offset of selection end == current caret position */
102 INT32 NumTabStops;
103 LPINT32 TabStops;
105 * FIXME: The following should probably be a (VOID *) that is
106 * typecast to either 16- or 32-bit callback when used,
107 * depending on the type of edit control (16 or 32 bit).
109 * EDITWORDBREAKPROC WordBreakProc;
111 * For now: no more application specific wordbreaking.
112 * (Internal wordbreak function still works)
114 CHAR PasswordChar;
115 INT32 LeftMargin;
116 INT32 RightMargin;
117 RECT32 FormatRect;
118 } EDITSTATE;
121 #define SWAP_INT32(x,y) do { INT32 temp = (INT32)(x); (x) = (INT32)(y); (y) = temp; } while(0)
122 #define ORDER_INT32(x,y) do { if ((INT32)(y) < (INT32)(x)) SWAP_INT32((x),(y)); } while(0)
124 /* macros to access window styles */
125 #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
126 #define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL)
127 #define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL)
128 #define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY)
129 #define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0)
130 #define IsPassword(wndPtr) ((wndPtr)->dwStyle & ES_PASSWORD)
131 #define IsLower(wndPtr) ((wndPtr)->dwStyle & ES_LOWERCASE)
132 #define IsUpper(wndPtr) ((wndPtr)->dwStyle & ES_UPPERCASE)
133 #define IsNoRedraw(wndPtr) ((wndPtr)->flags & WIN_NO_REDRAW)
135 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
137 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
138 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
139 (WPARAM32)(hdc), (LPARAM)(wndPtr)->hwndSelf ))
140 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
141 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_COMMAND, \
142 MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
143 (LPARAM)(wndPtr)->hwndSelf ))
144 #define DPRINTF_EDIT_MSG16(str) \
145 dprintf_edit(stddeb, \
146 "edit: 16 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
147 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
148 #define DPRINTF_EDIT_MSG32(str) \
149 dprintf_edit(stddeb, \
150 "edit: 32 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
151 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
153 /*********************************************************************
155 * Declarations
157 * Files like these should really be kept in alphabetical order.
160 LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam);
162 static void EDIT_BuildLineDefs(WND *wndPtr);
163 static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action);
164 static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x);
165 static void EDIT_DelEnd(WND *wndPtr);
166 static void EDIT_DelLeft(WND *wndPtr);
167 static void EDIT_DelRight(WND *wndPtr);
168 static INT32 EDIT_GetAveCharWidth(WND *wndPtr);
169 static INT32 EDIT_GetLineHeight(WND *wndPtr);
170 static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc);
171 static LPSTR EDIT_GetPointer(WND *wndPtr);
172 static LPSTR EDIT_GetPasswordPointer(WND *wndPtr);
173 static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e);
174 static INT32 EDIT_GetTextWidth(WND *wndPtr);
175 static LPSTR EDIT_GetUndoPointer(WND *wndPtr);
176 static INT32 EDIT_GetVisibleLineCount(WND *wndPtr);
177 static INT32 EDIT_GetWndWidth(WND *wndPtr);
178 static INT32 EDIT_GetXOffset(WND *wndPtr);
179 static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end);
180 static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y);
181 static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size);
182 static BOOL32 EDIT_MakeUndoFit(WND *wndPtr, INT32 size);
183 static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend);
184 static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend);
185 static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend);
186 static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend);
187 static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend);
188 static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend);
189 static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend);
190 static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend);
191 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend);
192 static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend);
193 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev);
194 static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev);
195 static void EDIT_ReleasePointer(WND *wndPtr);
196 static void EDIT_ReleaseUndoPointer(WND *wndPtr);
197 static void EDIT_SetSel(WND *wndPtr, INT32 ns, INT32 ne);
198 static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col);
199 static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line);
200 static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action);
202 static LRESULT EDIT_EM_CanUndo(WND *wndPtr);
203 static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
204 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr);
205 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam);
206 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr);
207 static LRESULT EDIT_EM_GetHandle(WND *wndPtr);
208 static LRESULT EDIT_EM_GetHandle16(WND *wndPtr);
209 static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
210 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
211 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr);
212 static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
213 static LRESULT EDIT_EM_GetModify(WND *wndPtr);
214 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr);
215 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
216 static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
217 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
218 static LRESULT EDIT_EM_GetThumb(WND *wndPtr);
219 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
220 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam);
221 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam);
222 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam);
223 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
224 static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam);
225 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
226 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam);
227 static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr);
228 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam);
229 static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam);
230 static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
231 static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
232 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam);
233 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam);
234 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam);
235 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
236 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
237 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
238 static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
239 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
240 static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
241 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
242 static LRESULT EDIT_EM_Undo(WND *wndPtr);
244 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
245 static LRESULT EDIT_WM_Clear(WND *wndPtr);
246 static LRESULT EDIT_WM_Command(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
247 static LRESULT EDIT_WM_ContextMenu(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
248 static LRESULT EDIT_WM_Copy(WND *wndPtr);
249 static LRESULT EDIT_WM_Cut(WND *wndPtr);
250 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
251 static LRESULT EDIT_WM_Destroy(WND *wndPtr);
252 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam);
253 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam);
254 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr);
255 static LRESULT EDIT_WM_GetFont(WND *wndPtr);
256 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
257 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr);
258 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
259 static LRESULT EDIT_WM_InitMenuPopup(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
260 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
261 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam);
262 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
263 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
264 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
265 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
266 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam);
267 static LRESULT EDIT_WM_Paste(WND *wndPtr);
268 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
269 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam);
270 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
271 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam);
272 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
273 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
274 static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
275 static LRESULT EDIT_WM_Timer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
276 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
279 /*********************************************************************
281 * General shortcuts for variable names:
283 * INT32 l; line
284 * INT32 c; column
285 * INT32 s; offset of selection start
286 * INT32 e; offset of selection end
287 * INT32 sl; line on which the selection starts
288 * INT32 el; line on which the selection ends
289 * INT32 sc; column on which the selection starts
290 * INT32 ec; column on which the selection ends
291 * INT32 li; line index (offset)
292 * INT32 fv; first visible line
293 * INT32 vlc; vissible line count
294 * INT32 lc; line count
295 * INT32 lh; line height (in pixels)
296 * INT32 tw; text width (in pixels)
297 * INT32 ww; window width (in pixels)
298 * INT32 cw; character width (average, in pixels)
303 /*********************************************************************
305 * EditWndProc()
307 * The messages are in the order of the actual integer values
308 * (which can be found in include/windows.h)
309 * Whereever possible the 16 bit versions are converted to
310 * the 32 bit ones, so that we can 'fall through' to the
311 * helper functions. These are mostly 32 bit (with a few
312 * exceptions, clearly indicated by a '16' extension to their
313 * names).
316 LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
318 LRESULT lResult = 0;
319 WND *wndPtr = WIN_FindWndPtr(hwnd);
321 if ((!EDITSTATEPTR(wndPtr)) && (msg != WM_CREATE))
322 return DefWindowProc32A(hwnd, msg, wParam, lParam);
324 switch (msg) {
325 case EM_GETSEL16:
326 DPRINTF_EDIT_MSG16("EM_GETSEL");
327 wParam = 0;
328 lParam = 0;
329 /* fall through */
330 case EM_GETSEL32:
331 DPRINTF_EDIT_MSG32("EM_GETSEL");
332 lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
333 break;
335 case EM_SETSEL16:
336 DPRINTF_EDIT_MSG16("EM_SETSEL");
337 lResult = EDIT_EM_SetSel16(wndPtr, wParam, lParam);
338 break;
339 case EM_SETSEL32:
340 DPRINTF_EDIT_MSG32("EM_SETSEL");
341 lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
342 break;
344 case EM_GETRECT16:
345 DPRINTF_EDIT_MSG16("EM_GETRECT");
346 lResult = EDIT_EM_GetRect16(wndPtr, wParam, lParam);
347 break;
348 case EM_GETRECT32:
349 DPRINTF_EDIT_MSG32("EM_GETRECT");
350 lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
351 break;
353 case EM_SETRECT16:
354 DPRINTF_EDIT_MSG16("EM_SETRECT");
355 /* fall through */
356 case EM_SETRECT32:
357 DPRINTF_EDIT_MSG32("EM_SETRECT");
358 lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
359 break;
361 case EM_SETRECTNP16:
362 DPRINTF_EDIT_MSG16("EM_SETRECTNP");
363 /* fall through */
364 case EM_SETRECTNP32:
365 DPRINTF_EDIT_MSG32("EM_SETRECTNP");
366 lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
367 break;
369 case EM_SCROLL16:
370 DPRINTF_EDIT_MSG16("EM_SCROLL");
371 /* fall through */
372 case EM_SCROLL32:
373 DPRINTF_EDIT_MSG32("EM_SCROLL");
374 lResult = EDIT_EM_Scroll(wndPtr, wParam);
375 break;
377 case EM_LINESCROLL16:
378 DPRINTF_EDIT_MSG16("EM_LINESCROLL");
379 wParam = (WPARAM32)(INT32)(INT16)HIWORD(lParam);
380 lParam = (LPARAM)(INT32)(INT16)LOWORD(lParam);
381 /* fall through */
382 case EM_LINESCROLL32:
383 DPRINTF_EDIT_MSG32("EM_LINESCROLL");
384 lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
385 break;
387 case EM_SCROLLCARET16:
388 DPRINTF_EDIT_MSG16("EM_SCROLLCARET");
389 /* fall through */
390 case EM_SCROLLCARET32:
391 DPRINTF_EDIT_MSG32("EM_SCROLLCARET");
392 lResult = EDIT_EM_ScrollCaret(wndPtr);
393 break;
395 case EM_GETMODIFY16:
396 DPRINTF_EDIT_MSG16("EM_GETMODIFY");
397 /* fall through */
398 case EM_GETMODIFY32:
399 DPRINTF_EDIT_MSG32("EM_GETMODIFY");
400 lResult = EDIT_EM_GetModify(wndPtr);
401 break;
403 case EM_SETMODIFY16:
404 DPRINTF_EDIT_MSG16("EM_SETMODIFY");
405 /* fall through */
406 case EM_SETMODIFY32:
407 DPRINTF_EDIT_MSG32("EM_SETMODIFY");
408 lResult = EDIT_EM_SetModify(wndPtr, wParam);
409 break;
411 case EM_GETLINECOUNT16:
412 DPRINTF_EDIT_MSG16("EM_GETLINECOUNT");
413 /* fall through */
414 case EM_GETLINECOUNT32:
415 DPRINTF_EDIT_MSG32("EM_GETLINECOUNT");
416 lResult = EDIT_EM_GetLineCount(wndPtr);
417 break;
419 case EM_LINEINDEX16:
420 DPRINTF_EDIT_MSG16("EM_LINEINDEX");
421 /* fall through */
422 case EM_LINEINDEX32:
423 DPRINTF_EDIT_MSG32("EM_LINEINDEX");
424 lResult = EDIT_EM_LineIndex(wndPtr, wParam);
425 break;
427 case EM_SETHANDLE16:
428 DPRINTF_EDIT_MSG16("EM_SETHANDLE");
429 lResult = EDIT_EM_SetHandle16(wndPtr, wParam);
430 break;
431 case EM_SETHANDLE32:
432 DPRINTF_EDIT_MSG32("EM_SETHANDLE");
433 lResult = EDIT_EM_SetHandle(wndPtr, wParam);
434 break;
436 case EM_GETHANDLE16:
437 DPRINTF_EDIT_MSG16("EM_GETHANDLE");
438 lResult = EDIT_EM_GetHandle16(wndPtr);
439 break;
440 case EM_GETHANDLE32:
441 DPRINTF_EDIT_MSG32("EM_GETHANDLE");
442 lResult = EDIT_EM_GetHandle(wndPtr);
443 break;
445 case EM_GETTHUMB16:
446 DPRINTF_EDIT_MSG16("EM_GETTHUMB");
447 /* fall through */
448 case EM_GETTHUMB32:
449 DPRINTF_EDIT_MSG32("EM_GETTHUMB");
450 lResult = EDIT_EM_GetThumb(wndPtr);
451 break;
453 /* messages 0x00bf and 0x00c0 missing from specs */
455 case WM_USER+15:
456 DPRINTF_EDIT_MSG16("undocumented WM_USER+15, please report");
457 /* fall through */
458 case 0x00bf:
459 DPRINTF_EDIT_MSG32("undocumented 0x00bf, please report");
460 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
461 break;
463 case WM_USER+16:
464 DPRINTF_EDIT_MSG16("undocumented WM_USER+16, please report");
465 /* fall through */
466 case 0x00c0:
467 DPRINTF_EDIT_MSG32("undocumented 0x00c0, please report");
468 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
469 break;
471 case EM_LINELENGTH16:
472 DPRINTF_EDIT_MSG16("EM_LINELENGTH");
473 /* fall through */
474 case EM_LINELENGTH32:
475 DPRINTF_EDIT_MSG32("EM_LINELENGTH");
476 lResult = EDIT_EM_LineLength(wndPtr, wParam);
477 break;
479 case EM_REPLACESEL16:
480 DPRINTF_EDIT_MSG16("EM_REPLACESEL");
481 lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
482 /* fall through */
483 case EM_REPLACESEL32:
484 DPRINTF_EDIT_MSG32("EM_REPLACESEL");
485 lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
486 break;
488 /* message 0x00c3 missing from specs */
490 case WM_USER+19:
491 DPRINTF_EDIT_MSG16("undocumented WM_USER+19, please report");
492 /* fall through */
493 case 0x00c3:
494 DPRINTF_EDIT_MSG32("undocumented 0x00c3, please report");
495 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
496 break;
498 case EM_GETLINE16:
499 DPRINTF_EDIT_MSG16("EM_GETLINE");
500 lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
501 /* fall through */
502 case EM_GETLINE32:
503 DPRINTF_EDIT_MSG32("EM_GETLINE");
504 lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
505 break;
507 case EM_LIMITTEXT16:
508 DPRINTF_EDIT_MSG16("EM_LIMITTEXT");
509 /* fall through */
510 case EM_SETLIMITTEXT32:
511 DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT");
512 lResult = EDIT_EM_SetLimitText(wndPtr, wParam, lParam);
513 break;
515 case EM_CANUNDO16:
516 DPRINTF_EDIT_MSG16("EM_CANUNDO");
517 /* fall through */
518 case EM_CANUNDO32:
519 DPRINTF_EDIT_MSG32("EM_CANUNDO");
520 lResult = EDIT_EM_CanUndo(wndPtr);
521 break;
523 case EM_UNDO16:
524 DPRINTF_EDIT_MSG16("EM_UNDO");
525 /* fall through */
526 case EM_UNDO32:
527 /* fall through */
528 case WM_UNDO:
529 DPRINTF_EDIT_MSG32("EM_UNDO / WM_UNDO");
530 lResult = EDIT_EM_Undo(wndPtr);
531 break;
533 case EM_FMTLINES16:
534 DPRINTF_EDIT_MSG16("EM_FMTLINES");
535 /* fall through */
536 case EM_FMTLINES32:
537 DPRINTF_EDIT_MSG32("EM_FMTLINES");
538 lResult = EDIT_EM_FmtLines(wndPtr, wParam);
539 break;
541 case EM_LINEFROMCHAR16:
542 DPRINTF_EDIT_MSG16("EM_LINEFROMCHAR");
543 /* fall through */
544 case EM_LINEFROMCHAR32:
545 DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR");
546 lResult = EDIT_EM_LineFromChar(wndPtr, wParam);
547 break;
549 /* message 0x00ca missing from specs */
551 case WM_USER+26:
552 DPRINTF_EDIT_MSG16("undocumented WM_USER+26, please report");
553 /* fall through */
554 case 0x00ca:
555 DPRINTF_EDIT_MSG32("undocumented 0x00ca, please report");
556 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
557 break;
559 case EM_SETTABSTOPS16:
560 DPRINTF_EDIT_MSG16("EM_SETTABSTOPS");
561 lResult = EDIT_EM_SetTabStops16(wndPtr, wParam, lParam);
562 break;
563 case EM_SETTABSTOPS32:
564 DPRINTF_EDIT_MSG32("EM_SETTABSTOPS");
565 lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
566 break;
568 case EM_SETPASSWORDCHAR16:
569 DPRINTF_EDIT_MSG16("EM_SETPASSWORDCHAR");
570 /* fall through */
571 case EM_SETPASSWORDCHAR32:
572 DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR");
573 lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam);
574 break;
576 case EM_EMPTYUNDOBUFFER16:
577 DPRINTF_EDIT_MSG16("EM_EMPTYUNDOBUFFER");
578 /* fall through */
579 case EM_EMPTYUNDOBUFFER32:
580 DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER");
581 lResult = EDIT_EM_EmptyUndoBuffer(wndPtr);
582 break;
584 case EM_GETFIRSTVISIBLELINE16:
585 DPRINTF_EDIT_MSG16("EM_GETFIRSTVISIBLELINE");
586 /* fall through */
587 case EM_GETFIRSTVISIBLELINE32:
588 DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE");
589 lResult = EDIT_EM_GetFirstVisibleLine(wndPtr);
590 break;
592 case EM_SETREADONLY16:
593 DPRINTF_EDIT_MSG16("EM_SETREADONLY");
594 /* fall through */
595 case EM_SETREADONLY32:
596 DPRINTF_EDIT_MSG32("EM_SETREADONLY");
597 lResult = EDIT_EM_SetReadOnly(wndPtr, wParam);
598 break;
600 case EM_SETWORDBREAKPROC16:
601 DPRINTF_EDIT_MSG16("EM_SETWORDBREAKPROC");
602 /* fall through */
603 case EM_SETWORDBREAKPROC32:
604 DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC");
605 lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
606 break;
608 case EM_GETWORDBREAKPROC16:
609 DPRINTF_EDIT_MSG16("EM_GETWORDBREAKPROC");
610 /* fall through */
611 case EM_GETWORDBREAKPROC32:
612 DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC");
613 lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
614 break;
616 case EM_GETPASSWORDCHAR16:
617 DPRINTF_EDIT_MSG16("EM_GETPASSWORDCHAR");
618 /* fall through */
619 case EM_GETPASSWORDCHAR32:
620 DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR");
621 lResult = EDIT_EM_GetPasswordChar(wndPtr);
622 break;
624 /* The following EM_xxx are new to win95 and don't exist for 16 bit */
626 case EM_SETMARGINS32:
627 DPRINTF_EDIT_MSG16("EM_SETMARGINS");
628 lResult = EDIT_EM_SetMargins(wndPtr, wParam, lParam);
629 break;
631 case EM_GETMARGINS32:
632 DPRINTF_EDIT_MSG16("EM_GETMARGINS");
633 lResult = EDIT_EM_GetMargins(wndPtr, wParam, lParam);
634 break;
636 case EM_GETLIMITTEXT32:
637 DPRINTF_EDIT_MSG16("EM_GETLIMITTEXT");
638 lResult = EDIT_EM_GetLimitText(wndPtr, wParam, lParam);
639 break;
641 case EM_POSFROMCHAR32:
642 DPRINTF_EDIT_MSG16("EM_POSFROMCHAR");
643 lResult = EDIT_EM_PosFromChar(wndPtr, wParam);
644 break;
646 case EM_CHARFROMPOS32:
647 DPRINTF_EDIT_MSG16("EM_CHARFROMPOS");
648 lResult = EDIT_EM_CharFromPos(wndPtr, wParam, lParam);
649 break;
651 case WM_GETDLGCODE:
652 DPRINTF_EDIT_MSG32("WM_GETDLGCODE");
653 lResult = EDIT_WM_GetDlgCode(wndPtr);
654 break;
656 case WM_CHAR:
657 DPRINTF_EDIT_MSG32("WM_CHAR");
658 lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
659 break;
661 case WM_CLEAR:
662 DPRINTF_EDIT_MSG32("WM_CLEAR");
663 lResult = EDIT_WM_Clear(wndPtr);
664 break;
666 case WM_COMMAND:
667 DPRINTF_EDIT_MSG32("WM_COMMAND");
668 lResult = EDIT_WM_Command(wndPtr, wParam, lParam);
669 break;
671 case WM_CONTEXTMENU:
672 DPRINTF_EDIT_MSG32("WM_CONTEXTMENU");
673 lResult = EDIT_WM_ContextMenu(wndPtr, wParam, lParam);
674 break;
676 case WM_COPY:
677 DPRINTF_EDIT_MSG32("WM_COPY");
678 lResult = EDIT_WM_Copy(wndPtr);
679 break;
681 case WM_CREATE:
682 DPRINTF_EDIT_MSG32("WM_CREATE");
683 lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
684 break;
686 case WM_CUT:
687 DPRINTF_EDIT_MSG32("WM_CUT");
688 lResult = EDIT_WM_Cut(wndPtr);
689 break;
691 case WM_DESTROY:
692 DPRINTF_EDIT_MSG32("WM_DESTROY");
693 lResult = EDIT_WM_Destroy(wndPtr);
694 break;
696 case WM_ENABLE:
697 DPRINTF_EDIT_MSG32("WM_ENABLE");
698 lResult = EDIT_WM_Enable(wndPtr, wParam);
699 break;
701 case WM_ERASEBKGND:
702 DPRINTF_EDIT_MSG32("WM_ERASEBKGND");
703 lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam);
704 break;
706 case WM_GETFONT:
707 DPRINTF_EDIT_MSG32("WM_GETFONT");
708 lResult = EDIT_WM_GetFont(wndPtr);
709 break;
711 case WM_GETTEXT:
712 DPRINTF_EDIT_MSG32("WM_GETTEXT");
713 lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
714 break;
716 case WM_GETTEXTLENGTH:
717 DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH");
718 lResult = EDIT_WM_GetTextLength(wndPtr);
719 break;
721 case WM_HSCROLL:
722 DPRINTF_EDIT_MSG32("WM_HSCROLL");
723 lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
724 break;
726 case WM_INITMENUPOPUP:
727 DPRINTF_EDIT_MSG32("WM_INITMENUPOPUP");
728 lResult = EDIT_WM_InitMenuPopup(wndPtr, wParam, lParam);
729 break;
731 case WM_KEYDOWN:
732 DPRINTF_EDIT_MSG32("WM_KEYDOWN");
733 lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
734 break;
736 case WM_KILLFOCUS:
737 DPRINTF_EDIT_MSG32("WM_KILLFOCUS");
738 lResult = EDIT_WM_KillFocus(wndPtr, wParam);
739 break;
741 case WM_LBUTTONDBLCLK:
742 DPRINTF_EDIT_MSG32("WM_LBUTTONDBLCLK");
743 lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
744 break;
746 case WM_LBUTTONDOWN:
747 DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN");
748 lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
749 break;
751 case WM_LBUTTONUP:
752 DPRINTF_EDIT_MSG32("WM_LBUTTONUP");
753 lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
754 break;
756 case WM_MOUSEMOVE:
758 * DPRINTF_EDIT_MSG32("WM_MOUSEMOVE");
760 lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
761 break;
763 case WM_PAINT:
764 DPRINTF_EDIT_MSG32("WM_PAINT");
765 lResult = EDIT_WM_Paint(wndPtr, wParam);
766 break;
768 case WM_PASTE:
769 DPRINTF_EDIT_MSG32("WM_PASTE");
770 lResult = EDIT_WM_Paste(wndPtr);
771 break;
773 case WM_SETCURSOR:
775 * DPRINTF_EDIT_MSG32("WM_SETCURSOR");
777 lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
778 break;
780 case WM_SETFOCUS:
781 DPRINTF_EDIT_MSG32("WM_SETFOCUS");
782 lResult = EDIT_WM_SetFocus(wndPtr, wParam);
783 break;
785 case WM_SETFONT:
786 DPRINTF_EDIT_MSG32("WM_SETFONT");
787 lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
788 break;
790 case WM_SETREDRAW:
791 DPRINTF_EDIT_MSG32("WM_SETREDRAW");
792 lResult = EDIT_WM_SetRedraw(wndPtr, wParam);
793 break;
795 case WM_SETTEXT:
796 DPRINTF_EDIT_MSG32("WM_SETTEXT");
797 lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
798 break;
800 case WM_SIZE:
801 DPRINTF_EDIT_MSG32("WM_SIZE");
802 lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
803 break;
805 case WM_SYSKEYDOWN:
806 DPRINTF_EDIT_MSG32("WM_SYSKEYDOWN");
807 lResult = EDIT_WM_SysKeyDown(wndPtr, wParam, lParam);
808 break;
810 case WM_TIMER:
811 DPRINTF_EDIT_MSG32("WM_TIMER");
812 lResult = EDIT_WM_Timer(wndPtr, wParam, lParam);
813 break;
815 case WM_VSCROLL:
816 DPRINTF_EDIT_MSG32("WM_VSCROLL");
817 lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
818 break;
820 default:
821 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
822 break;
824 EDIT_ReleasePointer(wndPtr);
825 return lResult;
829 /*********************************************************************
831 * EDIT_BuildLineDefs
833 * Build array of pointers to text lines.
834 * Lines can end with '\0' (last line), nothing (if it is too long),
835 * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
838 static void EDIT_BuildLineDefs(WND *wndPtr)
840 EDITSTATE *es = EDITSTATEPTR(wndPtr);
841 LPSTR text = EDIT_GetPasswordPointer(wndPtr);
842 INT32 ww = EDIT_GetWndWidth(wndPtr);
843 HDC32 hdc;
844 HFONT32 hFont;
845 HFONT32 oldFont = 0;
846 LPSTR start, cp;
847 INT32 prev, next;
848 INT32 width;
849 INT32 length;
850 LINE_END ending;
852 hdc = GetDC32(wndPtr->hwndSelf);
853 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr);
854 if (hFont) oldFont = SelectObject32(hdc, hFont);
856 if (!IsMultiLine(wndPtr)) {
857 es->LineCount = 1;
858 es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
859 es->LineDefs[0].offset = 0;
860 es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr);
861 es->LineDefs[0].ending = END_0;
862 es->TextWidth = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, text,
863 es->LineDefs[0].length,
864 es->NumTabStops, es->TabStops));
865 } else {
866 es->LineCount = 0;
867 start = text;
868 do {
869 if (!(cp = strstr(start, "\r\n"))) {
870 ending = END_0;
871 length = lstrlen32A(start);
872 } else if ((cp > start) && (*(cp - 1) == '\r')) {
873 ending = END_SOFT;
874 length = cp - start - 1;
875 } else {
876 ending = END_HARD;
877 length = cp - start;
879 width = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, start, length,
880 es->NumTabStops, es->TabStops));
882 if (IsWordWrap(wndPtr) && (width > ww)) {
883 next = 0;
884 do {
885 prev = next;
886 next = EDIT_CallWordBreakProc(wndPtr, start,
887 prev + 1, length, WB_RIGHT);
888 width = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, start, next,
889 es->NumTabStops, es->TabStops));
890 } while (width <= ww);
891 if (!prev) {
892 next = 0;
893 do {
894 prev = next;
895 next++;
896 width = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, start, next,
897 es->NumTabStops, es->TabStops));
898 } while (width <= ww);
899 if(!prev) prev = 1;
901 length = prev;
902 if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
903 length, WB_ISDELIMITER)) {
904 length--;
905 ending = END_DELIMIT;
906 } else
907 ending = END_NONE;
908 width = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, start, length,
909 es->NumTabStops, es->TabStops));
912 es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF));
913 es->LineDefs[es->LineCount].offset = start - text;
914 es->LineDefs[es->LineCount].length = length;
915 es->LineDefs[es->LineCount].ending = ending;
916 es->LineCount++;
917 es->TextWidth = MAX(es->TextWidth, width);
919 start += length;
920 switch (ending) {
921 case END_SOFT:
922 start += 3;
923 break;
924 case END_HARD:
925 start += 2;
926 break;
927 case END_DELIMIT:
928 start++;
929 break;
930 default:
931 break;
933 } while (*start || (ending == END_SOFT) || (ending == END_HARD));
935 if (hFont) SelectObject32(hdc, oldFont);
936 ReleaseDC32(wndPtr->hwndSelf, hdc);
938 free(text);
942 /*********************************************************************
944 * EDIT_CallWordBreakProc
946 * Call appropriate WordBreakProc (internal or external).
948 * FIXME: Heavily broken now that we have a LOCAL32 buffer.
949 * External wordbreak functions have been disabled in
950 * EM_SETWORDBREAKPROC.
953 static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action)
955 return EDIT_WordBreakProc(s, index, count, action);
957 * EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0);
959 * if (!wbp) return EDIT_WordBreakProc(s, index, count, action);
960 * else {
961 * EDITSTATE *es = EDITSTATEPTR(wndPtr);
962 * SEGPTR ptr = LOCAL_LockSegptr( wndPtr->hInstance, es->hBuf16 ) +
963 * (INT16)(s - EDIT_GetPointer(wndPtr));
964 * INT ret = CallWordBreakProc( (FARPROC16)wbp, ptr,
965 * index, count, action);
966 * LOCAL_Unlock( wndPtr->hInstance, es->hBuf16 );
967 * return ret;
973 /*********************************************************************
975 * EDIT_ColFromWndX
977 * Calculates, for a given line and X-coordinate on the screen, the column.
980 static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x)
982 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
983 INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line);
984 INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li);
985 INT32 i;
987 line = MAX(0, MIN(line, lc - 1));
988 for (i = 0 ; i < ll ; i++)
989 if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
990 break;
991 return i;
995 /*********************************************************************
997 * EDIT_DelEnd
999 * Delete all characters on this line to right of cursor.
1002 static void EDIT_DelEnd(WND *wndPtr)
1004 EDIT_EM_SetSel(wndPtr, -1, 0);
1005 EDIT_MoveEnd(wndPtr, TRUE);
1006 EDIT_WM_Clear(wndPtr);
1010 /*********************************************************************
1012 * EDIT_DelLeft
1014 * Delete character to left of cursor.
1017 static void EDIT_DelLeft(WND *wndPtr)
1019 EDIT_EM_SetSel(wndPtr, -1, 0);
1020 EDIT_MoveBackward(wndPtr, TRUE);
1021 EDIT_WM_Clear(wndPtr);
1025 /*********************************************************************
1027 * EDIT_DelRight
1029 * Delete character to right of cursor.
1032 static void EDIT_DelRight(WND *wndPtr)
1034 EDIT_EM_SetSel(wndPtr, -1, 0);
1035 EDIT_MoveForward(wndPtr, TRUE);
1036 EDIT_WM_Clear(wndPtr);
1040 /*********************************************************************
1042 * EDIT_GetAveCharWidth
1045 static INT32 EDIT_GetAveCharWidth(WND *wndPtr)
1047 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1049 return es->AveCharWidth;
1053 /*********************************************************************
1055 * EDIT_GetLineHeight
1058 static INT32 EDIT_GetLineHeight(WND *wndPtr)
1060 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1062 return es->LineHeight;
1066 /*********************************************************************
1068 * EDIT_GetLineRect
1070 * Calculates the bounding rectangle for a line from a starting
1071 * column to an ending column.
1074 static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc)
1076 rc->top = EDIT_WndYFromLine(wndPtr, line);
1077 rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
1078 rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
1079 rc->right = (ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
1080 EDIT_WndXFromCol(wndPtr, line, ecol);
1084 /*********************************************************************
1086 * EDIT_GetPointer
1088 * This acts as a LOCAL_Lock(), but it locks only once. This way
1089 * you can call it whenever you like, without unlocking.
1092 static LPSTR EDIT_GetPointer(WND *wndPtr)
1094 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1096 if (!es->text && (es->hBuf32 || es->hBuf16)) {
1097 if (es->hBuf32)
1098 es->text = (LPSTR)LocalLock32(es->hBuf32);
1099 else
1100 es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf16);
1102 return es->text;
1106 /*********************************************************************
1108 * EDIT_GetPasswordPointer
1112 static LPSTR EDIT_GetPasswordPointer(WND *wndPtr)
1114 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1115 LPSTR text = xstrdup(EDIT_GetPointer(wndPtr));
1116 LPSTR p;
1118 if(es->PasswordChar) {
1119 p = text;
1120 while(*p != '\0') {
1121 if(*p != '\r' && *p != '\n')
1122 *p = es->PasswordChar;
1123 p++;
1126 return text;
1130 /*********************************************************************
1132 * EDIT_GetSel
1134 * Beware: This is not the function called on EM_GETSEL.
1135 * This is the unordered version used internally
1136 * (s can be > e). No return value either.
1139 static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e)
1141 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1143 if (s)
1144 *s = es->SelStart;
1145 if (e)
1146 *e = es->SelEnd;
1150 /*********************************************************************
1152 * EDIT_GetTextWidth
1155 static INT32 EDIT_GetTextWidth(WND *wndPtr)
1157 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1159 return es->TextWidth;
1163 /*********************************************************************
1165 * EDIT_GetUndoPointer
1167 * This acts as a LocalLock32(), but it locks only once. This way
1168 * you can call it whenever you like, without unlocking.
1171 static LPSTR EDIT_GetUndoPointer(WND *wndPtr)
1173 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1175 if (!es->UndoText && es->hUndoBuf)
1176 es->UndoText = (LPSTR)LocalLock32(es->hUndoBuf);
1177 return es->UndoText;
1181 /*********************************************************************
1183 * EDIT_GetVisibleLineCount
1186 static INT32 EDIT_GetVisibleLineCount(WND *wndPtr)
1188 RECT32 rc;
1190 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
1191 return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
1195 /*********************************************************************
1197 * EDIT_GetWndWidth
1200 static INT32 EDIT_GetWndWidth(WND *wndPtr)
1202 RECT32 rc;
1204 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
1205 return rc.right - rc.left;
1209 /*********************************************************************
1211 * EDIT_GetXOffset
1214 static INT32 EDIT_GetXOffset(WND *wndPtr)
1216 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1218 return es->XOffset;
1222 /*********************************************************************
1224 * EDIT_InvalidateText
1226 * Invalidate the text from offset start upto, but not including,
1227 * offset end. Useful for (re)painting the selection.
1228 * Regions outside the linewidth are not invalidated.
1229 * end == -1 means end == TextLength.
1230 * start and end need not be ordered.
1233 static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end)
1235 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
1236 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
1237 INT32 sl;
1238 INT32 el;
1239 INT32 sc;
1240 INT32 ec;
1241 RECT32 rcWnd;
1242 RECT32 rcLine;
1243 RECT32 rcUpdate;
1244 INT32 l;
1246 if (end == start)
1247 return;
1249 if (end == -1)
1250 end = (INT32)EDIT_WM_GetTextLength(wndPtr);
1251 ORDER_INT32(start, end);
1252 sl = (INT32)EDIT_EM_LineFromChar(wndPtr, start);
1253 el = (INT32)EDIT_EM_LineFromChar(wndPtr, end);
1254 if ((el < fv) || (sl > fv + vlc))
1255 return;
1257 sc = start - (INT32)EDIT_EM_LineIndex(wndPtr, sl);
1258 ec = end - (INT32)EDIT_EM_LineIndex(wndPtr, el);
1259 if (sl < fv) {
1260 sl = fv;
1261 sc = 0;
1263 if (el > fv + vlc) {
1264 el = fv + vlc;
1265 ec = (INT32)EDIT_EM_LineLength(wndPtr,
1266 (INT32)EDIT_EM_LineIndex(wndPtr, el));
1268 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
1269 if (sl == el) {
1270 EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
1271 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1272 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1273 } else {
1274 EDIT_GetLineRect(wndPtr, sl, sc,
1275 (INT32)EDIT_EM_LineLength(wndPtr,
1276 (INT32)EDIT_EM_LineIndex(wndPtr, sl)),
1277 &rcLine);
1278 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1279 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1280 for (l = sl + 1 ; l < el ; l++) {
1281 EDIT_GetLineRect(wndPtr, l, 0,
1282 (INT32)EDIT_EM_LineLength(wndPtr,
1283 (INT32)EDIT_EM_LineIndex(wndPtr, l)),
1284 &rcLine);
1285 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1286 InvalidateRect32(wndPtr->hwndSelf, &rcUpdate, FALSE);
1288 EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
1289 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1290 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1295 /*********************************************************************
1297 * EDIT_LineFromWndY
1299 * Calculates, for a given Y-coordinate on the screen, the line.
1302 static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y)
1304 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
1305 INT32 lh = EDIT_GetLineHeight(wndPtr);
1306 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
1308 return MAX(0, MIN(lc - 1, y / lh + fv));
1312 /*********************************************************************
1314 * EDIT_MakeFit
1316 * Try to fit size + 1 bytes in the buffer. Constrain to limits.
1319 static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size)
1321 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1322 HLOCAL32 hNew32;
1323 HLOCAL16 hNew16;
1325 if (size <= es->BufSize)
1326 return TRUE;
1327 if (size > es->BufLimit) {
1328 dprintf_edit(stddeb, "edit: notification EN_MAXTEXT sent\n");
1329 EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
1330 return FALSE;
1332 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
1333 if (size > es->BufLimit)
1334 size = es->BufLimit;
1336 dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
1338 EDIT_ReleasePointer(wndPtr);
1339 if (es->hBuf32) {
1340 if ((hNew32 = LocalReAlloc32(es->hBuf32, size + 1, 0))) {
1341 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 32 bit handle %08x, new handle %08x\n", es->hBuf32, hNew32);
1342 es->hBuf32 = hNew32;
1343 es->BufSize = MIN(LocalSize32(es->hBuf32) - 1, es->BufLimit);
1344 if (es->BufSize < size) {
1345 dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize);
1346 dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n");
1347 EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE);
1348 return FALSE;
1350 dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
1351 return TRUE;
1353 } else {
1354 if ((hNew16 = LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf16, size + 1, LMEM_MOVEABLE))) {
1355 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 16 bit handle %08x, new handle %08x\n", es->hBuf16, hNew16);
1356 es->hBuf16 = hNew16;
1357 es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1, es->BufLimit);
1358 if (es->BufSize < size) {
1359 dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize);
1360 dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n");
1361 EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE);
1362 return FALSE;
1364 dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
1365 return TRUE;
1368 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Reallocation failed\n");
1369 dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n");
1370 EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE);
1371 return FALSE;
1375 /*********************************************************************
1377 * EDIT_MakeUndoFit
1379 * Try to fit size + 1 bytes in the undo buffer.
1382 static BOOL32 EDIT_MakeUndoFit(WND *wndPtr, INT32 size)
1384 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1385 HLOCAL32 hNew;
1387 if (size <= es->UndoBufSize)
1388 return TRUE;
1389 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
1391 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: trying to ReAlloc to %d+1\n", size);
1393 EDIT_ReleaseUndoPointer(wndPtr);
1394 if ((hNew = LocalReAlloc32(es->hUndoBuf, size + 1, 0))) {
1395 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: Old handle %08x, new handle %08x\n", es->hUndoBuf, hNew);
1396 es->hUndoBuf = hNew;
1397 es->UndoBufSize = LocalSize32(es->hUndoBuf) - 1;
1398 if (es->UndoBufSize < size) {
1399 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: FAILED ! We now have %d+1\n", es->UndoBufSize);
1400 return FALSE;
1402 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: We now have %d+1\n", es->UndoBufSize);
1403 return TRUE;
1405 return FALSE;
1409 /*********************************************************************
1411 * EDIT_MoveBackward
1414 static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend)
1416 INT32 s;
1417 INT32 e;
1418 INT32 l;
1419 INT32 li;
1421 EDIT_GetSel(wndPtr, &s, &e);
1422 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1423 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1424 if (e - li == 0) {
1425 if (l) {
1426 li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1);
1427 e = li + (INT32)EDIT_EM_LineLength(wndPtr, li);
1429 } else
1430 e--;
1431 if (!extend)
1432 s = e;
1433 EDIT_SetSel(wndPtr, s, e);
1434 EDIT_EM_ScrollCaret(wndPtr);
1438 /*********************************************************************
1440 * EDIT_MoveDownward
1443 static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend)
1445 INT32 s;
1446 INT32 e;
1447 INT32 l;
1448 INT32 lc;
1449 INT32 li;
1450 INT32 x;
1452 EDIT_GetSel(wndPtr, &s, &e);
1453 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1454 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
1455 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1456 if (l < lc - 1) {
1457 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1458 l++;
1459 e = (INT32)EDIT_EM_LineIndex(wndPtr, l) +
1460 EDIT_ColFromWndX(wndPtr, l, x);
1462 if (!extend)
1463 s = e;
1464 EDIT_SetSel(wndPtr, s, e);
1465 EDIT_EM_ScrollCaret(wndPtr);
1469 /*********************************************************************
1471 * EDIT_MoveEnd
1474 static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend)
1476 INT32 s;
1477 INT32 e;
1478 INT32 l;
1479 INT32 ll;
1480 INT32 li;
1482 EDIT_GetSel(wndPtr, &s, &e);
1483 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1484 ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
1485 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1486 e = li + ll;
1487 if (!extend)
1488 s = e;
1489 EDIT_SetSel(wndPtr, s, e);
1490 EDIT_EM_ScrollCaret(wndPtr);
1494 /*********************************************************************
1496 * EDIT_MoveForward
1499 static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend)
1501 INT32 s;
1502 INT32 e;
1503 INT32 l;
1504 INT32 lc;
1505 INT32 ll;
1506 INT32 li;
1508 EDIT_GetSel(wndPtr, &s, &e);
1509 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1510 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
1511 ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
1512 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1513 if (e - li == ll) {
1514 if (l != lc - 1)
1515 e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1);
1516 } else
1517 e++;
1518 if (!extend)
1519 s = e;
1520 EDIT_SetSel(wndPtr, s, e);
1521 EDIT_EM_ScrollCaret(wndPtr);
1525 /*********************************************************************
1527 * EDIT_MoveHome
1529 * Home key: move to beginning of line.
1532 static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend)
1534 INT32 s;
1535 INT32 e;
1536 INT32 l;
1537 INT32 li;
1539 EDIT_GetSel(wndPtr, &s, &e);
1540 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1541 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1542 e = li;
1543 if (!extend)
1544 s = e;
1545 EDIT_SetSel(wndPtr, s, e);
1546 EDIT_EM_ScrollCaret(wndPtr);
1550 /*********************************************************************
1552 * EDIT_MovePageDown
1555 static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend)
1557 INT32 s;
1558 INT32 e;
1559 INT32 l;
1560 INT32 lc;
1561 INT32 li;
1562 INT32 x;
1564 EDIT_GetSel(wndPtr, &s, &e);
1565 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1566 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
1567 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1568 if (l < lc - 1) {
1569 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1570 l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
1571 e = (INT32)EDIT_EM_LineIndex(wndPtr, l) +
1572 EDIT_ColFromWndX(wndPtr, l, x);
1574 if (!extend)
1575 s = e;
1576 EDIT_SetSel(wndPtr, s, e);
1577 EDIT_EM_ScrollCaret(wndPtr);
1581 /*********************************************************************
1583 * EDIT_MovePageUp
1586 static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend)
1588 INT32 s;
1589 INT32 e;
1590 INT32 l;
1591 INT32 li;
1592 INT32 x;
1594 EDIT_GetSel(wndPtr, &s, &e);
1595 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1596 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1597 if (l) {
1598 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1599 l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
1600 e = (INT32)EDIT_EM_LineIndex(wndPtr, l) +
1601 EDIT_ColFromWndX(wndPtr, l, x);
1603 if (!extend)
1604 s = e;
1605 EDIT_SetSel(wndPtr, s, e);
1606 EDIT_EM_ScrollCaret(wndPtr);
1610 /*********************************************************************
1612 * EDIT_MoveUpward
1615 static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend)
1617 INT32 s;
1618 INT32 e;
1619 INT32 l;
1620 INT32 li;
1621 INT32 x;
1623 EDIT_GetSel(wndPtr, &s, &e);
1624 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1625 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1626 if (l) {
1627 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1628 l--;
1629 e = (INT32)EDIT_EM_LineIndex(wndPtr, l) +
1630 EDIT_ColFromWndX(wndPtr, l, x);
1632 if (!extend)
1633 s = e;
1634 EDIT_SetSel(wndPtr, s, e);
1635 EDIT_EM_ScrollCaret(wndPtr);
1639 /*********************************************************************
1641 * EDIT_MoveWordBackward
1644 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend)
1646 INT32 s;
1647 INT32 e;
1648 INT32 l;
1649 INT32 ll;
1650 INT32 li;
1651 LPSTR text;
1653 EDIT_GetSel(wndPtr, &s, &e);
1654 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1655 ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
1656 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1657 if (e - li == 0) {
1658 if (l) {
1659 li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1);
1660 e = li + (INT32)EDIT_EM_LineLength(wndPtr, li);
1662 } else {
1663 text = EDIT_GetPointer(wndPtr);
1664 e = li + (INT32)EDIT_CallWordBreakProc(wndPtr,
1665 text + li, e - li, ll, WB_LEFT);
1667 if (!extend)
1668 s = e;
1669 EDIT_SetSel(wndPtr, s, e);
1670 EDIT_EM_ScrollCaret(wndPtr);
1674 /*********************************************************************
1676 * EDIT_MoveWordForward
1679 static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend)
1681 INT32 s;
1682 INT32 e;
1683 INT32 l;
1684 INT32 lc;
1685 INT32 ll;
1686 INT32 li;
1687 LPSTR text;
1689 EDIT_GetSel(wndPtr, &s, &e);
1690 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
1691 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
1692 ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
1693 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
1694 if (e - li == ll) {
1695 if (l != lc - 1)
1696 e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1);
1697 } else {
1698 text = EDIT_GetPointer(wndPtr);
1699 e = li + EDIT_CallWordBreakProc(wndPtr,
1700 text + li, e - li + 1, ll, WB_RIGHT);
1702 if (!extend)
1703 s = e;
1704 EDIT_SetSel(wndPtr, s, e);
1705 EDIT_EM_ScrollCaret(wndPtr);
1709 /*********************************************************************
1711 * EDIT_PaintLine
1714 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev)
1716 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
1717 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
1718 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
1719 INT32 li;
1720 INT32 ll;
1721 INT32 s;
1722 INT32 e;
1723 INT32 x;
1724 INT32 y;
1725 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1727 if ((line < fv) || (line > fv + vlc) || (line >= lc))
1728 return;
1730 dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
1732 x = EDIT_WndXFromCol(wndPtr, line, 0);
1733 y = EDIT_WndYFromLine(wndPtr, line);
1734 li = (INT32)EDIT_EM_LineIndex(wndPtr, line);
1735 ll = (INT32)EDIT_EM_LineLength(wndPtr, li);
1736 EDIT_GetSel(wndPtr, &s, &e);
1737 ORDER_INT32(s, e);
1738 s = MIN(li + ll, MAX(li, s));
1739 e = MIN(li + ll, MAX(li, e));
1740 if (rev && (s != e) &&
1741 ((es->eState & EF_FOCUSED) || (wndPtr->dwStyle & ES_NOHIDESEL)) ) {
1742 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
1743 x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
1744 x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
1745 } else
1746 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
1750 /*********************************************************************
1752 * EDIT_PaintText
1755 static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev)
1757 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1758 COLORREF BkColor;
1759 COLORREF TextColor;
1760 INT32 ret;
1761 LPSTR text;
1762 INT32 li;
1763 INT32 xoff;
1765 if (!count)
1766 return 0;
1767 BkColor = GetBkColor32(hdc);
1768 TextColor = GetTextColor32(hdc);
1769 if (rev) {
1770 SetBkColor32(hdc, GetSysColor32(COLOR_HIGHLIGHT));
1771 SetTextColor32(hdc, GetSysColor32(COLOR_HIGHLIGHTTEXT));
1773 text = EDIT_GetPasswordPointer(wndPtr);
1774 li = (INT32)EDIT_EM_LineIndex(wndPtr, line);
1775 xoff = EDIT_GetXOffset(wndPtr);
1776 ret = (INT32)LOWORD(TabbedTextOut32A(hdc, x, y, text + li + col, count,
1777 es->NumTabStops, es->TabStops, -xoff));
1778 free(text);
1779 if (rev) {
1780 SetBkColor32(hdc, BkColor);
1781 SetTextColor32(hdc, TextColor);
1783 return ret;
1787 /*********************************************************************
1789 * EDIT_ReleasePointer
1791 * This is the only helper function that can be called with es = NULL.
1792 * It is called at the end of EditWndProc() to unlock the buffer.
1795 static void EDIT_ReleasePointer(WND *wndPtr)
1797 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1799 if (!es)
1800 return;
1801 if (es->text && (es->hBuf32 || es->hBuf16)) {
1802 if (es->hBuf32)
1803 LocalUnlock32(es->hBuf32);
1804 else
1805 LOCAL_Unlock(wndPtr->hInstance, es->hBuf16);
1807 es->text = NULL;
1811 /*********************************************************************
1813 * EDIT_ReleaseUndoPointer
1815 * This is the only helper function that can be called with es = NULL.
1816 * It is called at the end of EditWndProc() to unlock the buffer.
1819 static void EDIT_ReleaseUndoPointer(WND *wndPtr)
1821 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1823 if (!es)
1824 return;
1825 if (es->UndoText && es->hUndoBuf)
1826 LocalUnlock32(es->hUndoBuf);
1827 es->UndoText = NULL;
1831 /*********************************************************************
1833 * EDIT_SetSel
1835 * Beware: This is not the function called on EM_SETSEL.
1836 * This is the unordered version used internally
1837 * (s can be > e). Doesn't accept -1 parameters either.
1838 * No range checking.
1841 static void EDIT_SetSel(WND *wndPtr, INT32 ns, INT32 ne)
1843 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1844 LRESULT pos;
1845 INT32 s;
1846 INT32 e;
1848 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
1849 es->SelStart = ns;
1850 es->SelEnd = ne;
1851 if (!IsNoRedraw(wndPtr)) {
1852 if (es->eState & EF_FOCUSED) {
1853 pos = EDIT_EM_PosFromChar(wndPtr, ne);
1854 SetCaretPos16((INT16)LOWORD(pos), (INT16)HIWORD(pos));
1856 ORDER_INT32(s, ns);
1857 ORDER_INT32(s, ne);
1858 ORDER_INT32(e, ns);
1859 ORDER_INT32(e, ne);
1860 ORDER_INT32(ns, ne);
1861 if (e != ns) {
1862 EDIT_InvalidateText(wndPtr, s, e);
1863 EDIT_InvalidateText(wndPtr, ns, ne);
1864 } else
1865 EDIT_InvalidateText(wndPtr, s, ne);
1870 /*********************************************************************
1872 * EDIT_WndXFromCol
1874 * Calculates, for a given line and column, the X-coordinate on the screen.
1877 static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col)
1879 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1880 LPSTR text = EDIT_GetPasswordPointer(wndPtr);
1881 INT32 ret;
1882 HDC32 hdc;
1883 HFONT32 hFont;
1884 HFONT32 oldFont = 0;
1885 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
1886 INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line);
1887 INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li);
1888 INT32 xoff = EDIT_GetXOffset(wndPtr);
1890 hdc = GetDC32(wndPtr->hwndSelf);
1891 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr);
1892 if (hFont) oldFont = SelectObject32(hdc, hFont);
1893 line = MAX(0, MIN(line, lc - 1));
1894 col = MIN(col, ll);
1895 ret = (INT32)LOWORD(GetTabbedTextExtent32A(hdc,
1896 text + li, col,
1897 es->NumTabStops, es->TabStops)) - xoff;
1898 if (hFont) SelectObject32(hdc, oldFont);
1899 ReleaseDC32(wndPtr->hwndSelf, hdc);
1900 free(text);
1901 return ret;
1905 /*********************************************************************
1907 * EDIT_WndYFromLine
1909 * Calculates, for a given line, the Y-coordinate on the screen.
1912 static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line)
1914 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
1915 INT32 lh = EDIT_GetLineHeight(wndPtr);
1917 return (line - fv) * lh;
1921 /*********************************************************************
1923 * EDIT_WordBreakProc
1925 * Find the beginning of words.
1926 * Note: unlike the specs for a WordBreakProc, this function only
1927 * allows to be called without linebreaks between s[0] upto
1928 * s[count - 1]. Remember it is only called
1929 * internally, so we can decide this for ourselves.
1932 static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action)
1934 INT32 ret = 0;
1936 dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%u"
1937 ", count=%u, action=%d\n", s, index, count, action);
1939 switch (action) {
1940 case WB_LEFT:
1941 if (!count)
1942 break;
1943 if (index)
1944 index--;
1945 if (s[index] == ' ') {
1946 while (index && (s[index] == ' '))
1947 index--;
1948 if (index) {
1949 while (index && (s[index] != ' '))
1950 index--;
1951 if (s[index] == ' ')
1952 index++;
1954 } else {
1955 while (index && (s[index] != ' '))
1956 index--;
1957 if (s[index] == ' ')
1958 index++;
1960 ret = index;
1961 break;
1962 case WB_RIGHT:
1963 if (!count)
1964 break;
1965 if (index)
1966 index--;
1967 if (s[index] == ' ')
1968 while ((index < count) && (s[index] == ' ')) index++;
1969 else {
1970 while (s[index] && (s[index] != ' ') && (index < count))
1971 index++;
1972 while ((s[index] == ' ') && (index < count)) index++;
1974 ret = index;
1975 break;
1976 case WB_ISDELIMITER:
1977 ret = (s[index] == ' ');
1978 break;
1979 default:
1980 fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
1981 break;
1983 return ret;
1987 /*********************************************************************
1989 * EM_CANUNDO
1992 static LRESULT EDIT_EM_CanUndo(WND *wndPtr)
1994 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1996 return (LRESULT)(es->UndoInsertLen || lstrlen32A(EDIT_GetUndoPointer(wndPtr)));
2000 /*********************************************************************
2002 * EM_CHARFROMPOS
2004 * FIXME: do the specs mean LineIndex or LineNumber (li v.s. l) ???
2006 static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2008 POINT32 pt;
2009 RECT32 rc;
2010 INT32 l;
2011 INT32 li;
2012 INT32 c;
2014 pt.x = LOWORD(lParam);
2015 pt.y = HIWORD(lParam);
2016 GetClientRect32(wndPtr->hwndSelf, &rc);
2018 if (!PtInRect32(&rc, pt))
2019 return -1;
2021 l = EDIT_LineFromWndY(wndPtr, pt.y);
2022 li = EDIT_EM_LineIndex(wndPtr, l);
2023 c = EDIT_ColFromWndX(wndPtr, l, pt.x);
2025 return (LRESULT)MAKELONG(li + c, li);
2029 /*********************************************************************
2031 * EM_EMPTYUNDOBUFFER
2034 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr)
2036 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2038 es->UndoInsertLen = 0;
2039 *EDIT_GetUndoPointer(wndPtr) = '\0';
2040 return 0;
2044 /*********************************************************************
2046 * EM_FMTLINES
2049 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam)
2051 fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented\n");
2052 return wParam ? TRUE : FALSE;
2056 /*********************************************************************
2058 * EM_GETFIRSTVISIBLELINE
2061 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr)
2063 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2065 if (IsMultiLine(wndPtr))
2066 return (LRESULT)es->FirstVisibleLine;
2067 else
2068 return (LRESULT)EDIT_ColFromWndX(wndPtr, 0, 0);
2072 /*********************************************************************
2074 * EM_GETHANDLE
2077 static LRESULT EDIT_EM_GetHandle(WND *wndPtr)
2079 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2081 if (!IsMultiLine(wndPtr))
2082 return 0;
2084 if (es->hBuf32)
2085 return (LRESULT)es->hBuf32;
2086 else
2087 return (LRESULT)es->hBuf16;
2091 /*********************************************************************
2093 * EM_GETHANDLE16
2095 * Hopefully this won't fire back at us.
2096 * We always start with a buffer in 32 bit linear memory.
2097 * However, with this message a 16 bit application requests
2098 * a handle of 16 bit local heap memory, where it expects to find
2099 * the text.
2100 * It's a pitty that from this moment on we have to use this
2101 * local heap, because applications may rely on the handle
2102 * in the future.
2104 * In this function we'll try to switch to local heap.
2106 static LRESULT EDIT_EM_GetHandle16(WND *wndPtr)
2108 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2109 LPSTR text;
2110 HLOCAL16 newBuf;
2111 LPSTR newText;
2112 INT16 newSize;
2114 if (!IsMultiLine(wndPtr))
2115 return 0;
2117 if (es->hBuf16)
2118 return (LRESULT)es->hBuf16;
2120 if (!LOCAL_HeapSize(wndPtr->hInstance)) {
2121 if (!LocalInit(wndPtr->hInstance, 0,
2122 GlobalSize16(wndPtr->hInstance))) {
2123 fprintf(stderr, "edit: EM_GETHANDLE: could not initialize local heap\n");
2124 return 0;
2126 dprintf_edit(stddeb, "edit: EM_GETHANDLE: local heap initialized\n");
2128 if (!(newBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE,
2129 EDIT_WM_GetTextLength(wndPtr) + 1))) {
2130 fprintf(stderr, "edit: EM_GETHANDLE: could not allocate new 16 bit buffer\n");
2131 return 0;
2133 newSize = MIN(LOCAL_Size(wndPtr->hInstance, newBuf) - 1, es->BufLimit);
2134 if (!(newText = LOCAL_Lock(wndPtr->hInstance, newBuf))) {
2135 fprintf(stderr, "edit: EM_GETHANDLE: could not lock new 16 bit buffer\n");
2136 LOCAL_Free(wndPtr->hInstance, newBuf);
2137 return 0;
2139 text = EDIT_GetPointer(wndPtr);
2140 lstrcpy32A(newText, text);
2141 EDIT_ReleasePointer(wndPtr);
2142 GlobalFree32(es->hBuf32);
2143 es->hBuf32 = (HLOCAL32)NULL;
2144 es->hBuf16 = newBuf;
2145 es->BufSize = newSize;
2146 es->text = newText;
2147 dprintf_edit(stddeb, "edit: EM_GETHANDLE: switched to 16 bit buffer\n");
2149 return (LRESULT)es->hBuf16;
2153 /*********************************************************************
2155 * EM_GETLIMITTEXT
2158 static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2160 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2162 return es->BufLimit;
2166 /*********************************************************************
2168 * EM_GETLINE
2171 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2173 LPSTR text;
2174 LPSTR src;
2175 LPSTR dst;
2176 INT32 len;
2177 INT32 i;
2178 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
2180 if (!IsMultiLine(wndPtr))
2181 wParam = 0;
2182 if ((INT32)wParam >= lc)
2183 return 0;
2184 text = EDIT_GetPointer(wndPtr);
2185 src = text + (INT32)EDIT_EM_LineIndex(wndPtr, wParam);
2186 dst = (LPSTR)lParam;
2187 len = MIN(*(WORD *)dst, (INT32)EDIT_EM_LineLength(wndPtr, wParam));
2188 for (i = 0 ; i < len ; i++) {
2189 *dst = *src;
2190 src++;
2191 dst++;
2193 return (LRESULT)len;
2197 /*********************************************************************
2199 * EM_GETLINECOUNT
2202 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr)
2204 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2206 return (LRESULT)es->LineCount;
2210 /*********************************************************************
2212 * EM_GETMARGINS
2215 static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2217 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2219 return (LRESULT)MAKELONG(es->LeftMargin, es->RightMargin);
2223 /*********************************************************************
2225 * EM_GETMODIFY
2228 static LRESULT EDIT_EM_GetModify(WND *wndPtr)
2230 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2232 return (LRESULT)((es->eState & EF_TEXTCHANGED) != 0);
2236 /*********************************************************************
2238 * EM_GETPASSWORDCHAR
2241 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr)
2243 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2245 return (LRESULT)es->PasswordChar;
2249 /*********************************************************************
2251 * EM_GETRECT
2254 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2256 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2258 CopyRect32((LPRECT32)lParam, &es->FormatRect);
2259 return 0;
2263 /*********************************************************************
2265 * EM_GETRECT16
2268 static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2270 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2272 CONV_RECT32TO16(&es->FormatRect, (LPRECT16)PTR_SEG_TO_LIN((SEGPTR)lParam));
2273 return 0;
2277 /*********************************************************************
2279 * EM_GETSEL
2281 * Returns the ordered selection range so that
2282 * LOWORD(result) < HIWORD(result)
2285 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2287 INT32 s;
2288 INT32 e;
2290 EDIT_GetSel(wndPtr, &s, &e);
2291 ORDER_INT32(s, e);
2292 if (wParam)
2293 *(LPINT32)wParam = s;
2294 if (lParam)
2295 *(LPINT32)lParam = e;
2296 return MAKELONG((INT16)s, (INT16)e);
2300 /*********************************************************************
2302 * EM_GETTHUMB
2304 * FIXME: is this right ? (or should it be only HSCROLL)
2305 * (and maybe only for edit controls that really have their
2306 * own scrollbars) (and maybe only for multiline controls ?)
2307 * All in all: very poorly documented
2310 static LRESULT EDIT_EM_GetThumb(WND *wndPtr)
2312 return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0),
2313 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0));
2317 /*********************************************************************
2319 * EM_GETWORDBREAKPROC
2321 * FIXME: Application defined WordBreakProc should be returned
2324 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2327 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2329 return (LRESULT)es->WordBreakProc;
2331 return 0;
2335 /*********************************************************************
2337 * EM_LINEFROMCHAR
2340 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam)
2342 INT32 l;
2344 if (!IsMultiLine(wndPtr))
2345 return 0;
2346 if ((INT32)wParam == -1)
2347 EDIT_EM_GetSel(wndPtr, (WPARAM32)&wParam, 0); /* intentional (looks weird, doesn't it ?) */
2348 l = (INT32)EDIT_EM_GetLineCount(wndPtr) - 1;
2349 while ((INT32)EDIT_EM_LineIndex(wndPtr, l) > (INT32)wParam)
2350 l--;
2351 return (LRESULT)l;
2355 /*********************************************************************
2357 * EM_LINEINDEX
2360 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam)
2362 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2363 INT32 e;
2364 INT32 l;
2365 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
2367 if ((INT32)wParam == -1) {
2368 EDIT_GetSel(wndPtr, NULL, &e);
2369 l = lc - 1;
2370 while (es->LineDefs[l].offset > e)
2371 l--;
2372 return (LRESULT)es->LineDefs[l].offset;
2374 if ((INT32)wParam >= lc)
2375 return -1;
2376 return (LRESULT)es->LineDefs[(INT32)wParam].offset;
2380 /*********************************************************************
2382 * EM_LINELENGTH
2385 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam)
2387 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2388 INT32 s;
2389 INT32 e;
2390 INT32 sl;
2391 INT32 el;
2393 if (!IsMultiLine(wndPtr))
2394 return (LRESULT)es->LineDefs[0].length;
2395 if ((INT32)wParam == -1) {
2396 EDIT_GetSel(wndPtr, &s, &e);
2397 sl = (INT32)EDIT_EM_LineFromChar(wndPtr, s);
2398 el = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
2399 return (LRESULT)(s - es->LineDefs[sl].offset +
2400 es->LineDefs[el].offset +
2401 es->LineDefs[el].length - e);
2403 return (LRESULT)es->LineDefs[(INT32)EDIT_EM_LineFromChar(wndPtr, wParam)].length;
2407 /*********************************************************************
2409 * EM_LINESCROLL
2411 * FIXME: is wParam in pixels or in average character widths ???
2412 * FIXME: we use this internally to scroll single line controls as well
2413 * (specs are vague about whether this message is valid or not for
2414 * single line controls)
2417 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2419 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2420 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
2421 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
2422 INT32 nfv = MAX(0, fv + (INT32)lParam);
2423 INT32 xoff = EDIT_GetXOffset(wndPtr);
2424 INT32 nxoff = MAX(0, xoff + (INT32)wParam);
2425 INT32 tw = EDIT_GetTextWidth(wndPtr);
2426 INT32 dx;
2427 INT32 dy;
2429 if (nfv >= lc)
2430 nfv = lc - 1;
2432 if (nxoff >= tw)
2433 nxoff = tw;
2434 dx = xoff - nxoff;
2435 dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
2436 if (dx || dy) {
2437 if (!IsNoRedraw(wndPtr))
2438 ScrollWindowEx32(wndPtr->hwndSelf, dx, dy,
2439 NULL, NULL, 0, NULL, (SW_INVALIDATE | SW_ERASE));
2440 es->FirstVisibleLine = nfv;
2441 es->XOffset = nxoff;
2442 if (IsVScrollBar(wndPtr))
2443 SetScrollPos32(wndPtr->hwndSelf, SB_VERT,
2444 EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
2445 if (IsHScrollBar(wndPtr))
2446 SetScrollPos32(wndPtr->hwndSelf, SB_HORZ,
2447 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
2449 if (IsMultiLine(wndPtr))
2450 return TRUE;
2451 else
2452 return FALSE;
2456 /*********************************************************************
2458 * EM_POSFROMCHAR
2461 static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam)
2463 INT32 len = (INT32)EDIT_WM_GetTextLength(wndPtr);
2464 INT32 l;
2465 INT32 li;
2467 wParam = MIN(wParam, len);
2468 l = EDIT_EM_LineFromChar(wndPtr, wParam);
2469 li = EDIT_EM_LineIndex(wndPtr, l);
2470 return (LRESULT)MAKELONG(EDIT_WndXFromCol(wndPtr, l, wParam - li),
2471 EDIT_WndYFromLine(wndPtr, l));
2475 /*********************************************************************
2477 * EM_REPLACESEL
2480 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2482 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2483 LPCSTR str = (LPCSTR)lParam;
2484 INT32 strl = lstrlen32A(str);
2485 INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr);
2486 INT32 utl;
2487 INT32 s;
2488 INT32 e;
2489 INT32 i;
2490 LPSTR p;
2491 LPSTR text;
2492 LPSTR utext;
2493 BOOL32 redraw;
2495 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
2497 if ((s == e) && !strl)
2498 return 0;
2500 if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl))
2501 return 0;
2503 text = EDIT_GetPointer(wndPtr);
2504 utext = EDIT_GetUndoPointer(wndPtr);
2505 if (e != s) {
2506 /* there is something to be deleted */
2507 if ((BOOL32)wParam) {
2508 /* we have to be able to undo */
2509 utl = lstrlen32A(utext);
2510 if (!es->UndoInsertLen && (*utext && (s == es->UndoPos))) {
2511 /* undo-buffer is extended to the right */
2512 EDIT_MakeUndoFit(wndPtr, utl + e - s);
2513 lstrcpyn32A(utext + utl, text + s, e - s + 1);
2514 } else if (!es->UndoInsertLen && (*utext && (e == es->UndoPos))) {
2515 /* undo-buffer is extended to the left */
2516 EDIT_MakeUndoFit(wndPtr, utl + e - s);
2517 for (p = utext + utl ; p >= utext ; p--)
2518 p[e - s] = p[0];
2519 for (i = 0 , p = utext ; i < e - s ; i++)
2520 p[i] = (text + s)[i];
2521 es->UndoPos = s;
2522 } else {
2523 /* new undo-buffer */
2524 EDIT_MakeUndoFit(wndPtr, e - s);
2525 lstrcpyn32A(utext, text + s, e - s + 1);
2526 es->UndoPos = s;
2528 /* any deletion makes the old insertion-undo invalid */
2529 es->UndoInsertLen = 0;
2530 } else
2531 EDIT_EM_EmptyUndoBuffer(wndPtr);
2533 /* now delete */
2534 lstrcpy32A(text + s, text + e);
2536 if (strl) {
2537 /* there is an insertion */
2538 if ((BOOL32)wParam) {
2539 /* we have to be able to undo */
2540 if ((s == es->UndoPos) ||
2541 ((es->UndoInsertLen) &&
2542 (s == es->UndoPos + es->UndoInsertLen)))
2544 * insertion is new and at delete position or
2545 * an extension to either left or right
2547 es->UndoInsertLen += strl;
2548 else {
2549 /* new insertion undo */
2550 es->UndoPos = s;
2551 es->UndoInsertLen = strl;
2552 /* new insertion makes old delete-buffer invalid */
2553 *utext = '\0';
2555 } else
2556 EDIT_EM_EmptyUndoBuffer(wndPtr);
2558 /* now insert */
2559 tl = lstrlen32A(text);
2560 for (p = text + tl ; p >= text + s ; p--)
2561 p[strl] = p[0];
2562 for (i = 0 , p = text + s ; i < strl ; i++)
2563 p[i] = str[i];
2564 if(IsUpper(wndPtr))
2565 CharUpperBuff32A(p, strl);
2566 else if(IsLower(wndPtr))
2567 CharLowerBuff32A(p, strl);
2568 s += strl;
2570 redraw = !IsNoRedraw(wndPtr);
2571 EDIT_WM_SetRedraw(wndPtr, FALSE);
2572 EDIT_BuildLineDefs(wndPtr);
2573 EDIT_EM_SetSel(wndPtr, s, s);
2574 EDIT_EM_ScrollCaret(wndPtr);
2575 EDIT_EM_SetModify(wndPtr, TRUE);
2576 dprintf_edit(stddeb, "edit: notification EN_UPDATE sent\n");
2577 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2578 EDIT_WM_SetRedraw(wndPtr, redraw);
2579 if (redraw) {
2580 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2581 dprintf_edit(stddeb, "edit: notification EN_CHANGE sent\n");
2582 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2584 return 0;
2588 /*********************************************************************
2590 * EM_SCROLL
2592 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam)
2594 INT32 dy;
2596 switch (wParam) {
2597 case SB_LINEUP:
2598 dy = -1;
2599 break;
2600 case SB_LINEDOWN:
2601 dy = 1;
2602 break;
2603 case SB_PAGEUP:
2604 case SB_PAGEDOWN:
2605 dy = EDIT_GetVisibleLineCount(wndPtr);
2606 if( wParam == SB_PAGEUP) dy = -dy;
2607 break;
2608 default:
2609 return FALSE;
2611 if (dy) {
2612 EDIT_EM_LineScroll(wndPtr, 0, dy);
2613 dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
2614 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
2616 return MAKELONG( ((UINT16)(INT16)dy), TRUE );
2620 /*********************************************************************
2622 * EM_SCROLLCARET
2624 * Makes sure the caret is visible.
2625 * FIXME: We use EM_LINESCROLL, but may we do that for single line
2626 * controls ???
2629 static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr)
2631 INT32 e;
2632 INT32 l;
2633 INT32 li;
2634 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
2635 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
2636 INT32 ww = EDIT_GetWndWidth(wndPtr);
2637 INT32 cw = EDIT_GetAveCharWidth(wndPtr);
2638 INT32 x;
2639 INT32 dy = 0;
2640 INT32 dx = 0;
2642 EDIT_GetSel(wndPtr, NULL, &e);
2643 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
2644 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
2645 x = EDIT_WndXFromCol(wndPtr, l, e - li);
2646 if (l >= fv + vlc)
2647 dy = l - vlc + 1 - fv;
2648 if (l < fv)
2649 dy = l - fv;
2650 if (x < 0)
2651 dx = x - ww / HSCROLL_FRACTION / cw * cw;
2652 if (x > ww)
2653 dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
2654 if (dy || dx) {
2655 EDIT_EM_LineScroll(wndPtr, dx, dy);
2656 if (dy) {
2657 dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
2658 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
2660 if (dx) {
2661 dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
2662 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
2665 return TRUE;
2669 /*********************************************************************
2671 * EM_SETHANDLE
2674 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam)
2676 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2678 if (IsMultiLine(wndPtr)) {
2679 EDIT_ReleasePointer(wndPtr);
2681 * old buffer is freed by caller
2683 es->hBuf16 = (HLOCAL16)NULL;
2684 es->hBuf32 = (HLOCAL32)wParam;
2685 es->BufSize = LocalSize32(es->hBuf32) - 1;
2686 es->LineCount = 0;
2687 es->FirstVisibleLine = 0;
2688 es->SelStart = es->SelEnd = 0;
2689 EDIT_EM_EmptyUndoBuffer(wndPtr);
2690 EDIT_EM_SetModify(wndPtr, FALSE);
2691 EDIT_BuildLineDefs(wndPtr);
2692 if (!IsNoRedraw(wndPtr))
2693 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2694 EDIT_EM_ScrollCaret(wndPtr);
2696 return 0;
2700 /*********************************************************************
2702 * EM_SETHANDLE16
2705 static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam)
2707 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2709 if (IsMultiLine(wndPtr)) {
2710 EDIT_ReleasePointer(wndPtr);
2712 * old buffer is freed by caller
2714 es->hBuf16 = (HLOCAL16)wParam;
2715 es->hBuf32 = (HLOCAL32)NULL;
2716 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1;
2717 es->LineCount = 0;
2718 es->FirstVisibleLine = 0;
2719 es->SelStart = es->SelEnd = 0;
2720 EDIT_EM_EmptyUndoBuffer(wndPtr);
2721 EDIT_EM_SetModify(wndPtr, FALSE);
2722 EDIT_BuildLineDefs(wndPtr);
2723 if (!IsNoRedraw(wndPtr))
2724 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2725 EDIT_EM_ScrollCaret(wndPtr);
2727 return 0;
2731 /*********************************************************************
2733 * EM_SETLIMITTEXT
2735 * FIXME: in WinNT maxsize is 0x7FFFFFFF / 0xFFFFFFFF
2736 * However, the windows version is not complied to yet in all of edit.c
2739 static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2741 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2743 if (IsMultiLine(wndPtr)) {
2744 if (wParam)
2745 es->BufLimit = MIN((INT32)wParam, BUFLIMIT_MULTI);
2746 else
2747 es->BufLimit = BUFLIMIT_MULTI;
2748 } else {
2749 if (wParam)
2750 es->BufLimit = MIN((INT32)wParam, BUFLIMIT_SINGLE);
2751 else
2752 es->BufLimit = BUFLIMIT_SINGLE;
2754 return 0;
2758 /*********************************************************************
2760 * EM_SETMARGINS
2762 * FIXME: We let the margins be set, but we don't use them yet !?!
2765 static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2767 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2769 if (wParam & EC_USEFONTINFO) {
2770 if (IsMultiLine(wndPtr)) {
2772 * FIXME: do some GetABCCharWidth, or so
2773 * This is just preliminary
2775 es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
2776 } else
2777 es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
2778 return 0;
2780 if (wParam & EC_LEFTMARGIN)
2781 es->LeftMargin = LOWORD(lParam);
2782 if (wParam & EC_RIGHTMARGIN)
2783 es->RightMargin = HIWORD(lParam);
2784 return 0;
2788 /*********************************************************************
2790 * EM_SETMODIFY
2793 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam)
2795 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2797 if( wParam )
2798 es->eState |= EF_TEXTCHANGED;
2799 else
2800 es->eState &= ~EF_TEXTCHANGED;
2801 return 0;
2805 /*********************************************************************
2807 * EM_SETPASSWORDCHAR
2809 * FIXME: This imlementation is way too simple
2812 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam)
2814 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2816 es->PasswordChar = (CHAR)wParam;
2817 return 0;
2821 /*********************************************************************
2823 * EM_SETREADONLY
2826 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam)
2828 if ((BOOL32)wParam)
2829 wndPtr->dwStyle |= ES_READONLY;
2830 else
2831 wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
2832 return TRUE;
2836 /*********************************************************************
2838 * EM_SETRECT
2841 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2843 fprintf(stdnimp,"edit: EM_SETRECT: message not implemented\n");
2844 return 0;
2848 /*********************************************************************
2850 * EM_SETRECTNP
2853 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2855 fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented\n");
2856 return 0;
2860 /*********************************************************************
2862 * EM_SETSEL
2865 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2867 INT32 ns = (INT32)wParam;
2868 INT32 ne = (INT32)lParam;
2869 INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr);
2871 if (ns == -1) {
2872 EDIT_GetSel(wndPtr, NULL, &ne);
2873 ns = ne;
2874 } else if ((!ns) && (ne == -1))
2875 ne = tl;
2876 else {
2877 ns = MAX(0, MIN(ns, tl));
2878 ne = MAX(0, MIN(ne, tl));
2879 ORDER_INT32(ns, ne);
2881 EDIT_SetSel(wndPtr, ns, ne);
2882 return -1;
2886 /*********************************************************************
2888 * EM_SETSEL16
2891 static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2893 INT32 ns = (INT32)LOWORD(lParam);
2894 INT32 ne = (INT32)HIWORD(lParam);
2896 if ((INT16)LOWORD(lParam) == -1)
2897 ns = -1;
2898 if ((!ns) && ((INT16)HIWORD(lParam) == -1))
2899 ne = -1;
2900 EDIT_EM_SetSel(wndPtr, ns, ne);
2901 if (!wParam)
2902 EDIT_EM_ScrollCaret(wndPtr);
2903 return -1;
2907 /*********************************************************************
2909 * EM_SETTABSTOPS
2912 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2914 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2916 if (!IsMultiLine(wndPtr))
2917 return FALSE;
2918 if (es->TabStops)
2919 free(es->TabStops);
2920 es->NumTabStops = (INT32)wParam;
2921 if (!wParam)
2922 es->TabStops = NULL;
2923 else {
2924 es->TabStops = (LPINT32)xmalloc(wParam * sizeof(INT32));
2925 memcpy( es->TabStops, (LPINT32)lParam,
2926 (INT32)wParam * sizeof(INT32) );
2928 return TRUE;
2932 /*********************************************************************
2934 * EM_SETTABSTOPS16
2937 static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2939 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2940 INT32 i;
2942 if (!IsMultiLine(wndPtr))
2943 return FALSE;
2944 if (es->TabStops)
2945 free(es->TabStops);
2946 es->NumTabStops = (INT32)wParam;
2947 if (!wParam)
2948 es->TabStops = NULL;
2949 else
2951 LPINT16 p = (LPINT16)PTR_SEG_TO_LIN(lParam);
2952 es->TabStops = (LPINT32)xmalloc(wParam * sizeof(INT32));
2953 for ( i = 0 ; i < (INT32)wParam ; i++) es->TabStops[i] = *p++;
2955 return TRUE;
2959 /*********************************************************************
2961 * EM_SETWORDBREAKPROC
2964 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2967 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2969 es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
2971 return 0;
2975 /*********************************************************************
2977 * EM_UNDO / WM_UNDO
2980 static LRESULT EDIT_EM_Undo(WND *wndPtr)
2982 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2983 LPSTR utext = xstrdup(EDIT_GetUndoPointer(wndPtr));
2985 dprintf_edit(stddeb, "edit: before UNDO:insertion length = %d, deletion buffer = %s\n",
2986 es->UndoInsertLen, utext);
2988 EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen);
2989 EDIT_EM_EmptyUndoBuffer(wndPtr);
2990 EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)utext);
2991 EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen);
2992 free(utext);
2994 dprintf_edit(stddeb, "edit: after UNDO: insertion length = %d, deletion buffer = %s\n",
2995 es->UndoInsertLen, EDIT_GetUndoPointer(wndPtr));
2997 return TRUE;
3001 /*********************************************************************
3003 * WM_CHAR
3006 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3008 char str[2];
3009 unsigned char c = (unsigned char)wParam;
3011 switch (c) {
3012 case '\r':
3013 case '\n':
3014 if (IsMultiLine(wndPtr)) {
3015 if (IsReadOnly(wndPtr)) {
3016 EDIT_MoveHome(wndPtr, FALSE);
3017 EDIT_MoveDownward(wndPtr, FALSE);
3018 } else
3019 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)"\r\n");
3021 break;
3022 case '\t':
3023 if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
3024 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)"\t");
3025 break;
3026 default:
3027 if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
3028 str[0] = c;
3029 str[1] = '\0';
3030 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)str);
3032 break;
3034 return 0;
3038 /*********************************************************************
3040 * WM_CLEAR
3043 static LRESULT EDIT_WM_Clear(WND *wndPtr)
3045 EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)"");
3047 return -1;
3051 /*********************************************************************
3053 * WM_COMMAND
3056 static LRESULT EDIT_WM_Command(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3058 if (HIWORD(wParam))
3059 return 0;
3061 switch (LOWORD(wParam)) {
3062 case EM_UNDO32:
3063 EDIT_EM_Undo(wndPtr);
3064 break;
3065 case WM_CUT:
3066 EDIT_WM_Cut(wndPtr);
3067 break;
3068 case WM_COPY:
3069 EDIT_WM_Copy(wndPtr);
3070 break;
3071 case WM_PASTE:
3072 EDIT_WM_Paste(wndPtr);
3073 break;
3074 case WM_CLEAR:
3075 EDIT_WM_Clear(wndPtr);
3076 break;
3077 case EM_SETSEL32:
3078 EDIT_EM_SetSel(wndPtr, 0, -1);
3079 EDIT_EM_ScrollCaret(wndPtr);
3080 break;
3081 default:
3082 dprintf_edit(stddeb, "edit: unknown menu item, please report\n");
3083 break;
3085 return -1;
3089 /*********************************************************************
3091 * WM_CONTEXTMENU
3093 * Note: the resource files resource/sysres_??.rc cannot define a
3094 * single popup menu. Hence we use a (dummy) menubar
3095 * containing the single popup menu as its first item.
3098 static LRESULT EDIT_WM_ContextMenu(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3100 HMENU32 hMenu = LoadMenuIndirect32A(SYSRES_GetResPtr(SYSRES_MENU_EDITMENU));
3101 HMENU32 hPopup = GetSubMenu32(hMenu, 0);
3103 TrackPopupMenu32(hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, LOWORD(lParam),
3104 HIWORD(lParam), 0, wndPtr->hwndSelf, NULL);
3105 DestroyMenu32(hMenu);
3106 return 0;
3110 /*********************************************************************
3112 * WM_COPY
3115 static LRESULT EDIT_WM_Copy(WND *wndPtr)
3117 INT32 s;
3118 INT32 e;
3119 HGLOBAL16 hdst;
3120 LPSTR text;
3121 LPSTR dst;
3123 EDIT_GetSel(wndPtr, &s, &e);
3124 if (e == s)
3125 return -1;
3126 ORDER_INT32(s, e);
3127 hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
3128 dst = GlobalLock16(hdst);
3129 text = EDIT_GetPointer(wndPtr);
3130 lstrcpyn32A(dst, text + s, e - s + 1);
3131 GlobalUnlock16(hdst);
3132 OpenClipboard32(wndPtr->hwndSelf);
3133 EmptyClipboard32();
3134 SetClipboardData16(CF_TEXT, hdst);
3135 CloseClipboard32();
3136 return -1;
3140 /*********************************************************************
3142 * WM_CREATE
3145 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3147 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
3148 EDITSTATE *es;
3149 LPSTR text;
3151 es = xmalloc(sizeof(EDITSTATE));
3152 memset(es, 0, sizeof(EDITSTATE));
3153 *(EDITSTATE **)wndPtr->wExtra = es;
3155 if (cs->style & WS_VSCROLL)
3156 cs->style |= ES_AUTOVSCROLL;
3157 if (cs->style & WS_HSCROLL)
3158 cs->style |= ES_AUTOHSCROLL;
3160 /* remove the WS_CAPTION style if it has been set - this is really a */
3161 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
3162 if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
3163 cs->style ^= WS_DLGFRAME;
3165 if (IsMultiLine(wndPtr)) {
3166 es->BufSize = BUFSTART_MULTI;
3167 es->BufLimit = BUFLIMIT_MULTI;
3168 es->PasswordChar = '\0';
3169 } else {
3170 es->BufSize = BUFSTART_SINGLE;
3171 es->BufLimit = BUFLIMIT_SINGLE;
3172 es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
3174 if (!(es->hBuf32 = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) {
3175 fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
3176 return -1;
3178 if (!(es->hUndoBuf = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) {
3179 fprintf(stderr, "edit: WM_CREATE: unable to allocate undo buffer\n");
3180 LocalFree32(es->hBuf32);
3181 es->hBuf32 = (HLOCAL32)NULL;
3182 return -1;
3184 es->BufSize = LocalSize32(es->hBuf32) - 1;
3185 es->UndoBufSize = LocalSize32(es->hUndoBuf) - 1;
3186 EDIT_EM_EmptyUndoBuffer(wndPtr);
3187 text = EDIT_GetPointer(wndPtr);
3188 *text = '\0';
3189 EDIT_BuildLineDefs(wndPtr);
3190 EDIT_WM_SetFont(wndPtr, 0, 0);
3191 if (cs->lpszName && *(cs->lpszName) != '\0')
3192 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, (LPARAM)cs->lpszName);
3193 EDIT_WM_SetRedraw(wndPtr, TRUE);
3194 return 0;
3198 /*********************************************************************
3200 * WM_CUT
3203 static LRESULT EDIT_WM_Cut(WND *wndPtr)
3205 EDIT_WM_Copy(wndPtr);
3206 EDIT_WM_Clear(wndPtr);
3207 return -1;
3211 /*********************************************************************
3213 * WM_DESTROY
3216 static LRESULT EDIT_WM_Destroy(WND *wndPtr)
3218 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3220 free(es->LineDefs);
3221 if (es->TabStops)
3222 free(es->TabStops);
3223 EDIT_ReleaseUndoPointer(wndPtr);
3224 LocalFree32(es->hUndoBuf);
3225 EDIT_ReleasePointer(wndPtr);
3226 if (es->hBuf32)
3227 LocalFree32(es->hBuf32);
3228 else
3229 LOCAL_Free(wndPtr->hInstance, es->hBuf16);
3230 free(es);
3231 wndPtr->wExtra[0] = 0;
3233 return 0;
3237 /*********************************************************************
3239 * WM_ENABLE
3242 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam)
3244 EDIT_InvalidateText(wndPtr, 0, -1);
3245 return 0;
3249 /*********************************************************************
3251 * WM_ERASEBKGND
3254 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam)
3256 HBRUSH32 hBrush;
3257 RECT32 rc;
3259 hBrush = (HBRUSH32)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
3260 if (!hBrush) hBrush = (HBRUSH32)GetStockObject32(WHITE_BRUSH);
3262 GetClientRect32(wndPtr->hwndSelf, &rc);
3263 IntersectClipRect32((HDC32)wParam, rc.left, rc.top,
3264 rc.right, rc.bottom);
3265 GetClipBox32((HDC32)wParam, &rc);
3267 * FIXME: specs say that we should UnrealizeObject() the brush,
3268 * but the specs of UnrealizeObject() say that we shouldn't
3269 * unrealize a stock object. The default brush that
3270 * DefWndProc() returns is ... a stock object.
3272 FillRect32((HDC32)wParam, &rc, hBrush);
3273 return -1;
3277 /*********************************************************************
3279 * WM_GETDLGCODE
3282 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr)
3284 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
3288 /*********************************************************************
3290 * WM_GETFONT
3293 static LRESULT EDIT_WM_GetFont(WND *wndPtr)
3295 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3297 return (LRESULT)es->hFont;
3301 /*********************************************************************
3303 * WM_GETTEXT
3306 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3308 LPSTR text = EDIT_GetPointer(wndPtr);
3309 INT32 len;
3310 LRESULT lResult = 0;
3312 len = lstrlen32A(text);
3313 if ((INT32)wParam > len) {
3314 lstrcpy32A((LPSTR)lParam, text);
3315 lResult = (LRESULT)len + 1;
3317 return lResult;
3321 /*********************************************************************
3323 * WM_GETTEXTLENGTH
3326 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr)
3328 LPSTR text = EDIT_GetPointer(wndPtr);
3330 return (LRESULT)lstrlen32A(text);
3334 /*********************************************************************
3336 * WM_HSCROLL
3338 * FIXME: scrollbar code itself is broken, so this one is a hack.
3341 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3343 INT32 ww = EDIT_GetWndWidth(wndPtr);
3344 INT32 tw = EDIT_GetTextWidth(wndPtr);
3345 INT32 cw = EDIT_GetAveCharWidth(wndPtr);
3346 INT32 xoff = EDIT_GetXOffset(wndPtr);
3347 INT32 dx = 0;
3348 BOOL32 not = TRUE;
3349 LRESULT ret = 0;
3351 switch (wParam) {
3352 case SB_LINELEFT:
3353 dx = -cw;
3354 break;
3355 case SB_LINERIGHT:
3356 dx = cw;
3357 break;
3358 case SB_PAGELEFT:
3359 dx = -ww / HSCROLL_FRACTION / cw * cw;
3360 break;
3361 case SB_PAGERIGHT:
3362 dx = ww / HSCROLL_FRACTION / cw * cw;
3363 break;
3364 case SB_LEFT:
3365 dx = -xoff;
3366 break;
3367 case SB_RIGHT:
3368 dx = tw - xoff;
3369 break;
3370 case SB_THUMBTRACK:
3372 * not = FALSE;
3374 case SB_THUMBPOSITION:
3375 dx = HIWORD(wParam) * tw / 100 - xoff;
3376 break;
3377 /* The next two are undocumented ! */
3378 case EM_GETTHUMB16:
3379 ret = tw ? xoff * 100 / tw : 0;
3380 break;
3381 case EM_LINESCROLL16:
3382 dx = (INT16)HIWORD(wParam);
3383 break;
3384 case SB_ENDSCROLL:
3385 default:
3386 break;
3388 if (dx) {
3389 EDIT_EM_LineScroll(wndPtr, dx, 0);
3390 if (not) {
3391 dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
3392 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
3395 return ret;
3399 /*********************************************************************
3401 * WM_INITMENUPOPUP
3403 * FIXME: the message identifiers have been chosen arbitrarily,
3404 * hence we use MF_BYPOSITION.
3405 * We might as well use the "real" values (anybody knows ?)
3406 * The menu definition is in resources/sysres_??.rc.
3407 * Once these are OK, we better use MF_BYCOMMAND here
3408 * (as we do in EDIT_WM_Command()).
3411 static LRESULT EDIT_WM_InitMenuPopup(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3413 HMENU32 hPopup = (HMENU32)wParam;
3414 INT32 s;
3415 INT32 e;
3417 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
3419 /* undo */
3420 EnableMenuItem32(hPopup, 0, MF_BYPOSITION |
3421 (EDIT_EM_CanUndo(wndPtr) ? MF_ENABLED : MF_GRAYED));
3422 /* cut */
3423 EnableMenuItem32(hPopup, 2, MF_BYPOSITION |
3424 ((e - s) && !IsPassword(wndPtr) ? MF_ENABLED : MF_GRAYED));
3425 /* copy */
3426 EnableMenuItem32(hPopup, 3, MF_BYPOSITION |
3427 ((e - s) && !IsPassword(wndPtr) ? MF_ENABLED : MF_GRAYED));
3428 /* paste */
3429 EnableMenuItem32(hPopup, 4, MF_BYPOSITION |
3430 (IsClipboardFormatAvailable32(CF_TEXT) ? MF_ENABLED : MF_GRAYED));
3431 /* delete */
3432 EnableMenuItem32(hPopup, 5, MF_BYPOSITION |
3433 ((e - s) ? MF_ENABLED : MF_GRAYED));
3434 /* select all */
3435 EnableMenuItem32(hPopup, 7, MF_BYPOSITION |
3436 (s || (e != EDIT_WM_GetTextLength(wndPtr)) ? MF_ENABLED : MF_GRAYED));
3438 return 0;
3441 /*********************************************************************
3443 * EDIT_CheckCombo
3446 static BOOL32 EDIT_CheckCombo(WND *wndPtr, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
3448 HWND32 hLBox;
3450 if( WIDGETS_IsControl32( wndPtr->parent, BIC32_COMBO ) &&
3451 (hLBox = COMBO_GetLBWindow( wndPtr->parent )) )
3453 HWND32 hCombo = wndPtr->parent->hwndSelf;
3454 BOOL32 bUIFlip = TRUE;
3456 dprintf_combo(stddeb, "EDIT_CheckCombo [%04x]: handling msg %04x (%04x)\n",
3457 wndPtr->hwndSelf, (UINT16)msg, (UINT16)wParam );
3458 switch( msg )
3460 case WM_KEYDOWN: /* Handle F4 and arrow keys */
3461 if( wParam != VK_F4 )
3463 bUIFlip = (BOOL32)SendMessage32A( hCombo, CB_GETEXTENDEDUI32, 0, 0 );
3464 if( SendMessage32A( hCombo, CB_GETDROPPEDSTATE32, 0, 0 ) ) bUIFlip = FALSE;
3467 if( !bUIFlip )
3468 SendMessage32A( hLBox, WM_KEYDOWN, wParam, 0 );
3469 else
3471 /* make sure ComboLBox pops up */
3473 SendMessage32A( hCombo, CB_SETEXTENDEDUI32, 0, 0 );
3474 SendMessage32A( hLBox, WM_KEYDOWN, VK_F4, 0 );
3475 SendMessage32A( hCombo, CB_SETEXTENDEDUI32, 1, 0 );
3477 break;
3479 case WM_SYSKEYDOWN: /* Handle Alt+up/down arrows */
3480 bUIFlip = (BOOL32)SendMessage32A( hCombo, CB_GETEXTENDEDUI32, 0, 0 );
3482 if( bUIFlip )
3484 bUIFlip = (BOOL32)SendMessage32A( hCombo, CB_GETDROPPEDSTATE32, 0, 0 );
3485 SendMessage32A( hCombo, CB_SHOWDROPDOWN32, (bUIFlip) ? FALSE : TRUE, 0 );
3486 } else SendMessage32A( hLBox, WM_KEYDOWN, VK_F4, 0 );
3487 break;
3489 return TRUE;
3491 return FALSE;
3494 /*********************************************************************
3496 * WM_KEYDOWN
3498 * Handling of special keys that don't produce a WM_CHAR
3499 * (i.e. non-printable keys) & Backspace & Delete
3502 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3504 INT32 s;
3505 INT32 e;
3506 BOOL32 shift;
3507 BOOL32 control;
3509 if (GetKeyState32(VK_MENU) & 0x8000)
3510 return 0;
3512 shift = GetKeyState32(VK_SHIFT) & 0x8000;
3513 control = GetKeyState32(VK_CONTROL) & 0x8000;
3515 EDIT_GetSel(wndPtr, &s, &e);
3516 switch (wParam) {
3517 case VK_F4:
3518 case VK_UP:
3519 if( EDIT_CheckCombo(wndPtr, WM_KEYDOWN, wParam, lParam) ) break;
3520 if( wParam == VK_F4 ) break;
3521 /* fall through */
3522 case VK_LEFT:
3523 if (IsMultiLine(wndPtr) && (wParam == VK_UP))
3524 EDIT_MoveUpward(wndPtr, shift);
3525 else
3526 if (control)
3527 EDIT_MoveWordBackward(wndPtr, shift);
3528 else
3529 EDIT_MoveBackward(wndPtr, shift);
3530 break;
3531 case VK_DOWN:
3532 if( EDIT_CheckCombo(wndPtr, WM_KEYDOWN, wParam, lParam) ) break;
3533 /* fall through */
3534 case VK_RIGHT:
3535 if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
3536 EDIT_MoveDownward(wndPtr, shift);
3537 else if (control)
3538 EDIT_MoveWordForward(wndPtr, shift);
3539 else
3540 EDIT_MoveForward(wndPtr, shift);
3541 break;
3542 case VK_HOME:
3543 EDIT_MoveHome(wndPtr, shift);
3544 break;
3545 case VK_END:
3546 EDIT_MoveEnd(wndPtr, shift);
3547 break;
3548 case VK_PRIOR:
3549 if (IsMultiLine(wndPtr))
3550 EDIT_MovePageUp(wndPtr, shift);
3551 break;
3552 case VK_NEXT:
3553 if (IsMultiLine(wndPtr))
3554 EDIT_MovePageDown(wndPtr, shift);
3555 break;
3556 case VK_BACK:
3557 if (!IsReadOnly(wndPtr) && !control)
3558 if (e != s)
3559 EDIT_WM_Clear(wndPtr);
3560 else
3561 EDIT_DelLeft(wndPtr);
3562 break;
3563 case VK_DELETE:
3564 if (!IsReadOnly(wndPtr) && !(shift && control))
3565 if (e != s) {
3566 if (shift)
3567 EDIT_WM_Cut(wndPtr);
3568 else
3569 EDIT_WM_Clear(wndPtr);
3570 } else {
3571 if (shift)
3572 EDIT_DelLeft(wndPtr);
3573 else if (control)
3574 EDIT_DelEnd(wndPtr);
3575 else
3576 EDIT_DelRight(wndPtr);
3578 break;
3579 case VK_INSERT:
3580 if (shift) {
3581 if (!IsReadOnly(wndPtr))
3582 EDIT_WM_Paste(wndPtr);
3583 } else if (control)
3584 EDIT_WM_Copy(wndPtr);
3585 break;
3587 return 0;
3591 /*********************************************************************
3593 * WM_KILLFOCUS
3596 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam)
3598 INT32 s;
3599 INT32 e;
3600 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3602 es->eState &= ~EF_FOCUSED;
3603 DestroyCaret32();
3604 if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
3605 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
3606 EDIT_InvalidateText(wndPtr, s, e);
3608 dprintf_edit(stddeb, "edit: notification EN_KILLFOCUS sent\n");
3609 EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
3610 return 0;
3614 /*********************************************************************
3616 * WM_LBUTTONDBLCLK
3618 * The caret position has been set on the WM_LBUTTONDOWN message
3621 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3623 INT32 s;
3624 INT32 e;
3625 INT32 l;
3626 INT32 li;
3627 INT32 ll;
3628 LPSTR text = EDIT_GetPointer(wndPtr);
3630 EDIT_GetSel(wndPtr, NULL, &e);
3631 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e);
3632 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
3633 ll = (INT32)EDIT_EM_LineLength(wndPtr, e);
3634 s = li + EDIT_CallWordBreakProc (wndPtr, text + li, e - li, ll, WB_LEFT);
3635 e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
3636 EDIT_EM_SetSel(wndPtr, s, e);
3637 EDIT_EM_ScrollCaret(wndPtr);
3638 return 0;
3642 /*********************************************************************
3644 * WM_LBUTTONDOWN
3647 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3649 INT32 x = (INT32)(INT16)LOWORD(lParam);
3650 INT32 y = (INT32)(INT16)HIWORD(lParam);
3651 INT32 l = EDIT_LineFromWndY(wndPtr, y);
3652 INT32 c;
3653 INT32 s;
3654 INT32 e;
3655 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
3656 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3657 INT32 li;
3659 SetFocus32(wndPtr->hwndSelf);
3660 SetCapture32(wndPtr->hwndSelf);
3661 l = MIN(fv + vlc - 1, MAX(fv, l));
3662 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
3663 c = EDIT_ColFromWndX(wndPtr, l, x);
3664 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
3665 e = li + c;
3666 if (GetKeyState32(VK_SHIFT) & 0x8000)
3667 EDIT_GetSel(wndPtr, &s, NULL);
3668 else
3669 s = e;
3670 EDIT_SetSel(wndPtr, s, e);
3671 EDIT_EM_ScrollCaret(wndPtr);
3672 SetTimer32(wndPtr->hwndSelf, 0, 100, NULL);
3673 return 0;
3677 /*********************************************************************
3679 * WM_LBUTTONUP
3682 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3684 if (GetCapture32() == wndPtr->hwndSelf) {
3685 KillTimer32(wndPtr->hwndSelf, 0);
3686 ReleaseCapture();
3688 return 0;
3692 /*********************************************************************
3694 * WM_MOUSEMOVE
3697 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3699 INT32 x;
3700 INT32 y;
3701 INT32 l;
3702 INT32 c;
3703 INT32 s;
3704 INT32 fv;
3705 INT32 vlc;
3706 INT32 li;
3708 if (GetCapture32() == wndPtr->hwndSelf) {
3709 x = (INT32)(INT16)LOWORD(lParam);
3710 y = (INT32)(INT16)HIWORD(lParam);
3711 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
3712 vlc = EDIT_GetVisibleLineCount(wndPtr);
3713 l = EDIT_LineFromWndY(wndPtr, y);
3714 l = MIN(fv + vlc - 1, MAX(fv, l));
3715 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
3716 c = EDIT_ColFromWndX(wndPtr, l, x);
3717 EDIT_GetSel(wndPtr, &s, NULL);
3718 li = (INT32)EDIT_EM_LineIndex(wndPtr, l);
3719 EDIT_SetSel(wndPtr, s, li + c);
3722 * FIXME: gotta do some scrolling if outside client (format ?)
3723 * area. Maybe reset the timer ?
3725 return 0;
3729 /*********************************************************************
3731 * WM_PAINT
3734 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam)
3736 PAINTSTRUCT32 ps;
3737 INT32 i;
3738 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
3739 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3740 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
3741 HDC32 hdc;
3742 HFONT32 hFont;
3743 HFONT32 oldFont = 0;
3744 RECT32 rc;
3745 RECT32 rcLine;
3746 RECT32 rcRgn;
3747 LRESULT pos;
3748 INT32 e;
3749 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3750 BOOL32 rev = IsWindowEnabled32(wndPtr->hwndSelf) &&
3751 ((es->eState & EF_FOCUSED) ||
3752 (wndPtr->dwStyle & ES_NOHIDESEL));
3754 hdc = BeginPaint32(wndPtr->hwndSelf, &ps);
3755 GetClientRect32(wndPtr->hwndSelf, &rc);
3756 IntersectClipRect32( hdc, rc.left, rc.top, rc.right, rc.bottom );
3757 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr);
3758 if (hFont)
3759 oldFont = (HFONT32)SelectObject32(hdc, hFont);
3760 EDIT_SEND_CTLCOLOR(wndPtr, hdc);
3761 if (!IsWindowEnabled32(wndPtr->hwndSelf))
3762 SetTextColor32(hdc, GetSysColor32(COLOR_GRAYTEXT));
3763 GetClipBox32(hdc, &rcRgn);
3764 for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
3765 EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
3766 if (IntersectRect32(&rc, &rcRgn, &rcLine))
3767 EDIT_PaintLine(wndPtr, hdc, i, rev);
3769 if (hFont) SelectObject32(hdc, oldFont);
3770 if (es->eState & EF_FOCUSED) {
3771 EDIT_GetSel(wndPtr, NULL, &e);
3772 pos = EDIT_EM_PosFromChar(wndPtr, e);
3773 SetCaretPos16((INT16)LOWORD(pos), (INT16)HIWORD(pos));
3775 EndPaint32(wndPtr->hwndSelf, &ps);
3776 return 0;
3780 /*********************************************************************
3782 * WM_PASTE
3785 static LRESULT EDIT_WM_Paste(WND *wndPtr)
3787 HGLOBAL16 hsrc;
3788 LPSTR src;
3790 OpenClipboard32(wndPtr->hwndSelf);
3791 if ((hsrc = GetClipboardData16(CF_TEXT))) {
3792 src = (LPSTR)GlobalLock16(hsrc);
3793 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)src);
3794 GlobalUnlock16(hsrc);
3796 CloseClipboard32();
3797 return -1;
3801 /*********************************************************************
3803 * WM_SETCURSOR
3806 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3808 if (LOWORD(lParam) == HTCLIENT) {
3809 SetCursor16(LoadCursor16(0, IDC_IBEAM));
3810 return -1;
3811 } else
3812 return 0;
3816 /*********************************************************************
3818 * WM_SETFOCUS
3821 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam)
3823 INT32 s;
3824 INT32 e;
3825 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3827 es->eState |= EF_FOCUSED;
3828 EDIT_GetSel(wndPtr, &s, &e);
3829 CreateCaret32(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
3830 EDIT_SetSel(wndPtr, s, e);
3831 if(!(wndPtr->dwStyle & ES_NOHIDESEL))
3832 EDIT_InvalidateText(wndPtr, s, e);
3833 ShowCaret32(wndPtr->hwndSelf);
3834 dprintf_edit(stddeb, "edit: notification EN_SETFOCUS sent\n");
3835 EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
3836 return 0;
3840 /*********************************************************************
3842 * WM_SETFONT
3845 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3847 TEXTMETRIC32A tm;
3848 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3849 INT32 s;
3850 INT32 e;
3851 HDC32 hdc;
3852 HFONT32 oldFont = 0;
3854 EDIT_GetSel(wndPtr, &s, &e);
3855 es->hFont = (HFONT32)wParam;
3856 hdc = GetDC32(wndPtr->hwndSelf);
3857 if (es->hFont) oldFont = SelectObject32(hdc, es->hFont);
3858 GetTextMetrics32A(hdc, &tm);
3859 es->LineHeight = tm.tmHeight;
3860 es->AveCharWidth = tm.tmAveCharWidth;
3861 if (es->hFont) SelectObject32(hdc, oldFont);
3862 ReleaseDC32(wndPtr->hwndSelf, hdc);
3863 EDIT_BuildLineDefs(wndPtr);
3864 if ((BOOL32)lParam && !IsNoRedraw(wndPtr))
3865 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
3866 if (es->eState & EF_FOCUSED) {
3867 DestroyCaret32();
3868 CreateCaret32(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
3869 EDIT_SetSel(wndPtr, s, e);
3870 ShowCaret32(wndPtr->hwndSelf);
3872 return 0;
3876 /*********************************************************************
3878 * WM_SETREDRAW
3881 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam)
3883 if( wParam )
3884 wndPtr->flags &= ~WIN_NO_REDRAW;
3885 else
3886 wndPtr->flags |= WIN_NO_REDRAW;
3887 return 0;
3891 /*********************************************************************
3893 * WM_SETTEXT
3896 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3898 EDIT_EM_SetSel(wndPtr, 0, -1);
3899 if (lParam)
3901 dprintf_edit(stddeb,"\t'%s'\n", (char*)lParam );
3902 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, lParam);
3904 EDIT_EM_SetModify(wndPtr, TRUE);
3905 EDIT_EM_ScrollCaret(wndPtr);
3906 return 1;
3910 /*********************************************************************
3912 * WM_SIZE
3914 * FIXME: What about that FormatRect ???
3917 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3919 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3920 INT32 e;
3922 EDIT_GetSel(wndPtr, 0, &e);
3923 GetClientRect32(wndPtr->hwndSelf, &es->FormatRect);
3924 if (!IsNoRedraw(wndPtr) &&
3925 ((wParam == SIZE_MAXIMIZED) ||
3926 (wParam == SIZE_RESTORED))) {
3927 if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
3928 EDIT_BuildLineDefs(wndPtr);
3929 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
3931 return 0;
3935 /*********************************************************************
3937 * WM_SYSKEYDOWN
3940 static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3942 if ((wParam == VK_BACK) && (lParam & 0x2000) &&
3943 (BOOL32)EDIT_EM_CanUndo(wndPtr))
3944 EDIT_EM_Undo(wndPtr);
3945 else if( wParam == VK_UP || wParam == VK_DOWN )
3946 EDIT_CheckCombo( wndPtr, WM_SYSKEYDOWN, wParam, lParam );
3947 return 0;
3951 /*********************************************************************
3953 * WM_TIMER
3956 static LRESULT EDIT_WM_Timer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3959 * FIXME: gotta do some scrolling here, like
3960 * EDIT_EM_LineScroll(wndPtr, 0, 1);
3962 return 0;
3966 /*********************************************************************
3968 * WM_VSCROLL
3970 * FIXME: scrollbar code itself is broken, so this one is a hack.
3973 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3975 INT32 lc, fv;
3976 INT32 dy = 0;
3977 BOOL32 not = TRUE;
3978 LRESULT ret = 0;
3980 switch (wParam) {
3981 case SB_LINEUP:
3982 case SB_LINEDOWN:
3983 case SB_PAGEUP:
3984 case SB_PAGEDOWN:
3985 EDIT_EM_Scroll( wndPtr, wParam );
3986 return ret;
3987 default:
3988 lc = (INT32)EDIT_EM_GetLineCount(wndPtr);
3989 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr);
3990 switch( wParam ) {
3991 case SB_TOP:
3992 dy = -fv;
3993 break;
3994 case SB_BOTTOM:
3995 dy = lc - 1 - fv;
3996 break;
3997 case SB_THUMBTRACK:
3998 not = FALSE;
3999 /* fall through */
4000 case SB_THUMBPOSITION:
4001 dy = HIWORD(wParam) * (lc - 1) / 100 - fv;
4002 break;
4003 /* The next two are undocumented ! */
4004 case EM_GETTHUMB16:
4005 ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0;
4006 break;
4007 case EM_LINESCROLL16:
4008 dy = (INT16)LOWORD(lParam);
4009 break;
4010 case SB_ENDSCROLL:
4011 /* nothing to do */
4014 if (dy) {
4015 EDIT_EM_LineScroll(wndPtr, 0, dy);
4016 if (not) {
4017 dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
4018 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
4021 return ret;