Release 970305
[wine/multimedia.git] / controls / edit.c
blob3187698a9f8b258fef24dd5721781d66f6a23ebd
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.
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include "windows.h"
20 #include "win.h"
21 #include "local.h"
22 #include "resource.h"
23 #include "stddebug.h"
24 #include "debug.h"
25 #include "xmalloc.h"
27 #include "callback.h"
30 #define BUFLIMIT_MULTI 65534 /* maximum text buffer length (not including '\0') */
31 /* FIXME: BTW, new specs say 65535 (do you dare ???) */
32 #define BUFLIMIT_SINGLE 32766
33 #define BUFSTART_MULTI 1024 /* starting length for multi-line control */
34 #define BUFSTART_SINGLE 256 /* starting length for single line control */
35 #define GROWLENGTH 64 /* buffers grow by this much */
36 #define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */
38 typedef enum
40 END_0 = 0,
41 END_DELIMIT,
42 END_NONE,
43 END_HARD,
44 END_SOFT,
45 } LINE_END;
47 typedef struct {
48 INT32 offset;
49 INT32 length;
50 LINE_END ending;
51 } LINEDEF;
53 typedef struct
55 HLOCAL16 hBuf16; /* For when a 16-bit multiline edit
56 * control gets a EM_GETHANDLE (which
57 * should return 16-bit local heap).
58 * From that point on we _have_ to keep
59 * using 16-bit local heap (apps rely
60 * on that ... bummer).
62 HLOCAL32 hBuf32; /* Don't worry about 'LOCAL'. LOCAL32 is
63 * identical to GLOBAL32, which is
64 * essentially a HANDLE32 created with
65 * HeapAlloc(GetProcessHeap(), ...) plus
66 * a global32 (and thus local32)
67 * descriptor, which we can return upon
68 * EM_GETHANDLE32.
69 * It is 32-bit linear addressing, so
70 * everything is fine.
72 LPSTR text; /* Depending on the fact that we are a
73 * 16 or 32 bit control, this is the
74 * pointer that we get after
75 * LocalLock32(hBuf23) (which is a typecast :-)
76 * or LOCAL_Lock(hBuf16).
77 * This is always a 32-bit linear pointer.
79 HFONT32 hFont;
80 LINEDEF *LineDefs; /* Internal table for (soft) linebreaks */
81 INT32 TextWidth; /* width of the widest line in pixels */
82 INT32 XOffset; /* offset of the viewport in pixels */
83 INT32 FirstVisibleLine;
84 INT32 LineCount;
85 INT32 LineHeight; /* height of a screen line in pixels */
86 INT32 AveCharWidth; /* average character width in pixels */
87 INT32 BufLimit;
88 INT32 BufSize;
89 BOOL32 TextChanged;
90 INT32 UndoInsertLen;
91 INT32 UndoPos;
92 INT32 UndoBufSize;
93 HLOCAL32 hUndoBuf;
94 LPSTR UndoText;
95 BOOL32 Redraw;
96 INT32 SelStart; /* offset of selection start, == SelEnd if no selection */
97 INT32 SelEnd; /* offset of selection end == current caret position */
98 INT32 NumTabStops;
99 LPINT32 TabStops;
101 * FIXME: The following should probably be a (VOID *) that is
102 * typecast to either 16- or 32-bit callback when used,
103 * depending on the type of edit control (16 or 32 bit).
105 * EDITWORDBREAKPROC WordBreakProc;
107 * For now: no more application specific wordbreaking.
108 * (Internal wordbreak function still works)
110 CHAR PasswordChar;
111 INT32 LeftMargin;
112 INT32 RightMargin;
113 RECT32 FormatRect;
114 } EDITSTATE;
117 #define SWAP_INT32(x,y) do { INT32 temp = (INT32)(x); (x) = (INT32)(y); (y) = temp; } while(0)
118 #define ORDER_INT32(x,y) do { if ((INT32)(y) < (INT32)(x)) SWAP_INT32((x),(y)); } while(0)
120 /* macros to access window styles */
121 #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
122 #define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL)
123 #define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL)
124 #define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY)
125 #define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0)
126 #define IsPassword(wndPtr) ((wndPtr)->dwStyle & ES_PASSWORD)
127 #define IsLower(wndPtr) ((wndPtr)->dwStyle & ES_LOWERCASE)
128 #define IsUpper(wndPtr) ((wndPtr)->dwStyle & ES_UPPERCASE)
130 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
132 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
133 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
134 (WPARAM32)(hdc), (LPARAM)(wndPtr)->hwndSelf ))
135 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
136 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_COMMAND, \
137 MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
138 (LPARAM)(wndPtr)->hwndSelf ))
139 #define DPRINTF_EDIT_MSG16(str) \
140 dprintf_edit(stddeb, \
141 "edit: 16 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
142 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
143 #define DPRINTF_EDIT_MSG32(str) \
144 dprintf_edit(stddeb, \
145 "edit: 32 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
146 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
149 /*********************************************************************
151 * Declarations
153 * Files like these should really be kept in alphabetical order.
156 LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam);
158 static void EDIT_BuildLineDefs(WND *wndPtr);
159 static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action);
160 static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x);
161 static void EDIT_DelEnd(WND *wndPtr);
162 static void EDIT_DelLeft(WND *wndPtr);
163 static void EDIT_DelRight(WND *wndPtr);
164 static INT32 EDIT_GetAveCharWidth(WND *wndPtr);
165 static INT32 EDIT_GetLineHeight(WND *wndPtr);
166 static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc);
167 static LPSTR EDIT_GetPointer(WND *wndPtr);
168 static LPSTR EDIT_GetPasswordPointer(WND *wndPtr);
169 static BOOL32 EDIT_GetRedraw(WND *wndPtr);
170 static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e);
171 static INT32 EDIT_GetTextWidth(WND *wndPtr);
172 static LPSTR EDIT_GetUndoPointer(WND *wndPtr);
173 static INT32 EDIT_GetVisibleLineCount(WND *wndPtr);
174 static INT32 EDIT_GetWndWidth(WND *wndPtr);
175 static INT32 EDIT_GetXOffset(WND *wndPtr);
176 static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end);
177 static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y);
178 static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size);
179 static BOOL32 EDIT_MakeUndoFit(WND *wndPtr, INT32 size);
180 static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend);
181 static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend);
182 static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend);
183 static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend);
184 static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend);
185 static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend);
186 static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend);
187 static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend);
188 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend);
189 static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend);
190 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev);
191 static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev);
192 static void EDIT_ReleasePointer(WND *wndPtr);
193 static void EDIT_ReleaseUndoPointer(WND *wndPtr);
194 static void EDIT_SetSel(WND *wndPtr, INT32 ns, INT32 ne);
195 static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col);
196 static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line);
197 static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action);
199 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
200 static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
201 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
202 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
203 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
204 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
205 static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
206 static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
207 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
208 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
209 static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
210 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
211 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
212 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
213 static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
214 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
215 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
216 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
217 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
218 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
219 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
220 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
221 static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
222 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
223 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
224 static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
225 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
226 static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
227 static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
228 static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
229 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
230 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
231 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
232 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
233 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
234 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
235 static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
236 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
237 static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
238 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
239 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
241 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
242 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
243 static LRESULT EDIT_WM_Command(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
244 static LRESULT EDIT_WM_ContextMenu(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
245 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
246 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
247 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
248 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
249 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
250 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
251 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
252 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
253 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
254 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
255 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
256 static LRESULT EDIT_WM_InitMenuPopup(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
257 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
258 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
259 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
260 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
261 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
262 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
263 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
264 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
265 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
266 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
267 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
268 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
269 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
270 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
271 static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
272 static LRESULT EDIT_WM_Timer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
273 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
276 /*********************************************************************
278 * General shortcuts for variable names:
280 * INT32 l; line
281 * INT32 c; column
282 * INT32 s; offset of selection start
283 * INT32 e; offset of selection end
284 * INT32 sl; line on which the selection starts
285 * INT32 el; line on which the selection ends
286 * INT32 sc; column on which the selection starts
287 * INT32 ec; column on which the selection ends
288 * INT32 li; line index (offset)
289 * INT32 fv; first visible line
290 * INT32 vlc; vissible line count
291 * INT32 lc; line count
292 * INT32 lh; line height (in pixels)
293 * INT32 tw; text width (in pixels)
294 * INT32 ww; window width (in pixels)
295 * INT32 cw; character width (average, in pixels)
300 /*********************************************************************
302 * EditWndProc()
304 * The messages are in the order of the actual integer values
305 * (which can be found in include/windows.h)
306 * Whereever possible the 16 bit versions are converted to
307 * the 32 bit ones, so that we can 'fall through' to the
308 * helper functions. These are mostly 32 bit (with a few
309 * exceptions, clearly indicated by a '16' extension to their
310 * names).
313 LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
315 LRESULT lResult = 0;
316 WND *wndPtr = WIN_FindWndPtr(hwnd);
318 if ((!EDITSTATEPTR(wndPtr)) && (msg != WM_CREATE))
319 return DefWindowProc32A(hwnd, msg, wParam, lParam);
321 switch (msg) {
322 case EM_GETSEL16:
323 DPRINTF_EDIT_MSG16("EM_GETSEL");
324 wParam = 0;
325 lParam = 0;
326 /* fall through */
327 case EM_GETSEL32:
328 DPRINTF_EDIT_MSG32("EM_GETSEL");
329 lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
330 break;
332 case EM_SETSEL16:
333 DPRINTF_EDIT_MSG16("EM_SETSEL");
334 lResult = EDIT_EM_SetSel16(wndPtr, wParam, lParam);
335 break;
336 case EM_SETSEL32:
337 DPRINTF_EDIT_MSG32("EM_SETSEL");
338 lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
339 break;
341 case EM_GETRECT16:
342 DPRINTF_EDIT_MSG16("EM_GETRECT");
343 lResult = EDIT_EM_GetRect16(wndPtr, wParam, lParam);
344 break;
345 case EM_GETRECT32:
346 DPRINTF_EDIT_MSG32("EM_GETRECT");
347 lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
348 break;
350 case EM_SETRECT16:
351 DPRINTF_EDIT_MSG16("EM_SETRECT");
352 /* fall through */
353 case EM_SETRECT32:
354 DPRINTF_EDIT_MSG32("EM_SETRECT");
355 lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
356 break;
358 case EM_SETRECTNP16:
359 DPRINTF_EDIT_MSG16("EM_SETRECTNP");
360 /* fall through */
361 case EM_SETRECTNP32:
362 DPRINTF_EDIT_MSG32("EM_SETRECTNP");
363 lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
364 break;
366 case EM_SCROLL16:
367 DPRINTF_EDIT_MSG16("EM_SCROLL");
368 /* fall through */
369 case EM_SCROLL32:
370 DPRINTF_EDIT_MSG32("EM_SCROLL");
371 lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
372 break;
374 case EM_LINESCROLL16:
375 DPRINTF_EDIT_MSG16("EM_LINESCROLL");
376 wParam = (WPARAM32)(INT32)(INT16)HIWORD(lParam);
377 lParam = (LPARAM)(INT32)(INT16)LOWORD(lParam);
378 /* fall through */
379 case EM_LINESCROLL32:
380 DPRINTF_EDIT_MSG32("EM_LINESCROLL");
381 lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
382 break;
384 case EM_SCROLLCARET16:
385 DPRINTF_EDIT_MSG16("EM_SCROLLCARET");
386 /* fall through */
387 case EM_SCROLLCARET32:
388 DPRINTF_EDIT_MSG32("EM_SCROLLCARET");
389 lResult = EDIT_EM_ScrollCaret(wndPtr, wParam, lParam);
390 break;
392 case EM_GETMODIFY16:
393 DPRINTF_EDIT_MSG16("EM_GETMODIFY");
394 /* fall through */
395 case EM_GETMODIFY32:
396 DPRINTF_EDIT_MSG32("EM_GETMODIFY");
397 lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
398 break;
400 case EM_SETMODIFY16:
401 DPRINTF_EDIT_MSG16("EM_SETMODIFY");
402 /* fall through */
403 case EM_SETMODIFY32:
404 DPRINTF_EDIT_MSG32("EM_SETMODIFY");
405 lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
406 break;
408 case EM_GETLINECOUNT16:
409 DPRINTF_EDIT_MSG16("EM_GETLINECOUNT");
410 /* fall through */
411 case EM_GETLINECOUNT32:
412 DPRINTF_EDIT_MSG32("EM_GETLINECOUNT");
413 lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
414 break;
416 case EM_LINEINDEX16:
417 DPRINTF_EDIT_MSG16("EM_LINEINDEX");
418 /* fall through */
419 case EM_LINEINDEX32:
420 DPRINTF_EDIT_MSG32("EM_LINEINDEX");
421 lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
422 break;
424 case EM_SETHANDLE16:
425 DPRINTF_EDIT_MSG16("EM_SETHANDLE");
426 lResult = EDIT_EM_SetHandle16(wndPtr, wParam, lParam);
427 break;
428 case EM_SETHANDLE32:
429 DPRINTF_EDIT_MSG32("EM_SETHANDLE");
430 lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
431 break;
433 case EM_GETHANDLE16:
434 DPRINTF_EDIT_MSG16("EM_GETHANDLE");
435 lResult = EDIT_EM_GetHandle16(wndPtr, wParam, lParam);
436 break;
437 case EM_GETHANDLE32:
438 DPRINTF_EDIT_MSG32("EM_GETHANDLE");
439 lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
440 break;
442 case EM_GETTHUMB16:
443 DPRINTF_EDIT_MSG16("EM_GETTHUMB");
444 /* fall through */
445 case EM_GETTHUMB32:
446 DPRINTF_EDIT_MSG32("EM_GETTHUMB");
447 lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
448 break;
450 /* messages 0x00bf and 0x00c0 missing from specs */
452 case WM_USER+15:
453 DPRINTF_EDIT_MSG16("undocumented WM_USER+15, please report");
454 /* fall through */
455 case 0x00bf:
456 DPRINTF_EDIT_MSG32("undocumented 0x00bf, please report");
457 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
458 break;
460 case WM_USER+16:
461 DPRINTF_EDIT_MSG16("undocumented WM_USER+16, please report");
462 /* fall through */
463 case 0x00c0:
464 DPRINTF_EDIT_MSG32("undocumented 0x00c0, please report");
465 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
466 break;
468 case EM_LINELENGTH16:
469 DPRINTF_EDIT_MSG16("EM_LINELENGTH");
470 /* fall through */
471 case EM_LINELENGTH32:
472 DPRINTF_EDIT_MSG32("EM_LINELENGTH");
473 lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
474 break;
476 case EM_REPLACESEL16:
477 DPRINTF_EDIT_MSG16("EM_REPLACESEL");
478 lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
479 /* fall through */
480 case EM_REPLACESEL32:
481 DPRINTF_EDIT_MSG32("EM_REPLACESEL");
482 lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
483 break;
485 /* message 0x00c3 missing from specs */
487 case WM_USER+19:
488 DPRINTF_EDIT_MSG16("undocumented WM_USER+19, please report");
489 /* fall through */
490 case 0x00c3:
491 DPRINTF_EDIT_MSG32("undocumented 0x00c3, please report");
492 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
493 break;
495 case EM_GETLINE16:
496 DPRINTF_EDIT_MSG16("EM_GETLINE");
497 lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
498 /* fall through */
499 case EM_GETLINE32:
500 DPRINTF_EDIT_MSG32("EM_GETLINE");
501 lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
502 break;
504 case EM_LIMITTEXT16:
505 DPRINTF_EDIT_MSG16("EM_LIMITTEXT");
506 /* fall through */
507 case EM_SETLIMITTEXT32:
508 DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT");
509 lResult = EDIT_EM_SetLimitText(wndPtr, wParam, lParam);
510 break;
512 case EM_CANUNDO16:
513 DPRINTF_EDIT_MSG16("EM_CANUNDO");
514 /* fall through */
515 case EM_CANUNDO32:
516 DPRINTF_EDIT_MSG32("EM_CANUNDO");
517 lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
518 break;
520 case EM_UNDO16:
521 DPRINTF_EDIT_MSG16("EM_UNDO");
522 /* fall through */
523 case EM_UNDO32:
524 /* fall through */
525 case WM_UNDO:
526 DPRINTF_EDIT_MSG32("EM_UNDO / WM_UNDO");
527 lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
528 break;
530 case EM_FMTLINES16:
531 DPRINTF_EDIT_MSG16("EM_FMTLINES");
532 /* fall through */
533 case EM_FMTLINES32:
534 DPRINTF_EDIT_MSG32("EM_FMTLINES");
535 lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
536 break;
538 case EM_LINEFROMCHAR16:
539 DPRINTF_EDIT_MSG16("EM_LINEFROMCHAR");
540 /* fall through */
541 case EM_LINEFROMCHAR32:
542 DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR");
543 lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
544 break;
546 /* message 0x00ca missing from specs */
548 case WM_USER+26:
549 DPRINTF_EDIT_MSG16("undocumented WM_USER+26, please report");
550 /* fall through */
551 case 0x00ca:
552 DPRINTF_EDIT_MSG32("undocumented 0x00ca, please report");
553 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
554 break;
556 case EM_SETTABSTOPS16:
557 DPRINTF_EDIT_MSG16("EM_SETTABSTOPS");
558 lResult = EDIT_EM_SetTabStops16(wndPtr, wParam, lParam);
559 break;
560 case EM_SETTABSTOPS32:
561 DPRINTF_EDIT_MSG32("EM_SETTABSTOPS");
562 lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
563 break;
565 case EM_SETPASSWORDCHAR16:
566 DPRINTF_EDIT_MSG16("EM_SETPASSWORDCHAR");
567 /* fall through */
568 case EM_SETPASSWORDCHAR32:
569 DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR");
570 lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
571 break;
573 case EM_EMPTYUNDOBUFFER16:
574 DPRINTF_EDIT_MSG16("EM_EMPTYUNDOBUFFER");
575 /* fall through */
576 case EM_EMPTYUNDOBUFFER32:
577 DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER");
578 lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
579 break;
581 case EM_GETFIRSTVISIBLELINE16:
582 DPRINTF_EDIT_MSG16("EM_GETFIRSTVISIBLELINE");
583 /* fall through */
584 case EM_GETFIRSTVISIBLELINE32:
585 DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE");
586 lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
587 break;
589 case EM_SETREADONLY16:
590 DPRINTF_EDIT_MSG16("EM_SETREADONLY");
591 /* fall through */
592 case EM_SETREADONLY32:
593 DPRINTF_EDIT_MSG32("EM_SETREADONLY");
594 lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
595 break;
597 case EM_SETWORDBREAKPROC16:
598 DPRINTF_EDIT_MSG16("EM_SETWORDBREAKPROC");
599 /* fall through */
600 case EM_SETWORDBREAKPROC32:
601 DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC");
602 lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
603 break;
605 case EM_GETWORDBREAKPROC16:
606 DPRINTF_EDIT_MSG16("EM_GETWORDBREAKPROC");
607 /* fall through */
608 case EM_GETWORDBREAKPROC32:
609 DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC");
610 lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
611 break;
613 case EM_GETPASSWORDCHAR16:
614 DPRINTF_EDIT_MSG16("EM_GETPASSWORDCHAR");
615 /* fall through */
616 case EM_GETPASSWORDCHAR32:
617 DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR");
618 lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
619 break;
621 /* The following EM_xxx are new to win95 and don't exist for 16 bit */
623 case EM_SETMARGINS32:
624 DPRINTF_EDIT_MSG16("EM_SETMARGINS");
625 lResult = EDIT_EM_SetMargins(wndPtr, wParam, lParam);
626 break;
628 case EM_GETMARGINS32:
629 DPRINTF_EDIT_MSG16("EM_GETMARGINS");
630 lResult = EDIT_EM_GetMargins(wndPtr, wParam, lParam);
631 break;
633 case EM_GETLIMITTEXT32:
634 DPRINTF_EDIT_MSG16("EM_GETLIMITTEXT");
635 lResult = EDIT_EM_GetLimitText(wndPtr, wParam, lParam);
636 break;
638 case EM_POSFROMCHAR32:
639 DPRINTF_EDIT_MSG16("EM_POSFROMCHAR");
640 lResult = EDIT_EM_PosFromChar(wndPtr, wParam, lParam);
641 break;
643 case EM_CHARFROMPOS32:
644 DPRINTF_EDIT_MSG16("EM_CHARFROMPOS");
645 lResult = EDIT_EM_CharFromPos(wndPtr, wParam, lParam);
646 break;
648 case WM_GETDLGCODE:
649 DPRINTF_EDIT_MSG32("WM_GETDLGCODE");
650 lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
651 break;
653 case WM_CHAR:
654 DPRINTF_EDIT_MSG32("WM_CHAR");
655 lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
656 break;
658 case WM_CLEAR:
659 DPRINTF_EDIT_MSG32("WM_CLEAR");
660 lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
661 break;
663 case WM_COMMAND:
664 DPRINTF_EDIT_MSG32("WM_COMMAND");
665 lResult = EDIT_WM_Command(wndPtr, wParam, lParam);
666 break;
668 case WM_CONTEXTMENU:
669 DPRINTF_EDIT_MSG32("WM_CONTEXTMENU");
670 lResult = EDIT_WM_ContextMenu(wndPtr, wParam, lParam);
671 break;
673 case WM_COPY:
674 DPRINTF_EDIT_MSG32("WM_COPY");
675 lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
676 break;
678 case WM_CREATE:
679 DPRINTF_EDIT_MSG32("WM_CREATE");
680 lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
681 break;
683 case WM_CUT:
684 DPRINTF_EDIT_MSG32("WM_CUT");
685 lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
686 break;
688 case WM_DESTROY:
689 DPRINTF_EDIT_MSG32("WM_DESTROY");
690 lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
691 break;
693 case WM_ENABLE:
694 DPRINTF_EDIT_MSG32("WM_ENABLE");
695 lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
696 break;
698 case WM_ERASEBKGND:
699 DPRINTF_EDIT_MSG32("WM_ERASEBKGND");
700 lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
701 break;
703 case WM_GETFONT:
704 DPRINTF_EDIT_MSG32("WM_GETFONT");
705 lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
706 break;
708 case WM_GETTEXT:
709 DPRINTF_EDIT_MSG32("WM_GETTEXT");
710 lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
711 break;
713 case WM_GETTEXTLENGTH:
714 DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH");
715 lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
716 break;
718 case WM_HSCROLL:
719 DPRINTF_EDIT_MSG32("WM_HSCROLL");
720 lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
721 break;
723 case WM_INITMENUPOPUP:
724 DPRINTF_EDIT_MSG32("WM_INITMENUPOPUP");
725 lResult = EDIT_WM_InitMenuPopup(wndPtr, wParam, lParam);
726 break;
728 case WM_KEYDOWN:
729 DPRINTF_EDIT_MSG32("WM_KEYDOWN");
730 lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
731 break;
733 case WM_KILLFOCUS:
734 DPRINTF_EDIT_MSG32("WM_KILLFOCUS");
735 lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
736 break;
738 case WM_LBUTTONDBLCLK:
739 DPRINTF_EDIT_MSG32("WM_LBUTTONDBLCLK");
740 lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
741 break;
743 case WM_LBUTTONDOWN:
744 DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN");
745 lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
746 break;
748 case WM_LBUTTONUP:
749 DPRINTF_EDIT_MSG32("WM_LBUTTONUP");
750 lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
751 break;
753 case WM_MOUSEMOVE:
755 * DPRINTF_EDIT_MSG32("WM_MOUSEMOVE");
757 lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
758 break;
760 case WM_PAINT:
761 DPRINTF_EDIT_MSG32("WM_PAINT");
762 lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
763 break;
765 case WM_PASTE:
766 DPRINTF_EDIT_MSG32("WM_PASTE");
767 lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
768 break;
770 case WM_SETCURSOR:
772 * DPRINTF_EDIT_MSG32("WM_SETCURSOR");
774 lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
775 break;
777 case WM_SETFOCUS:
778 DPRINTF_EDIT_MSG32("WM_SETFOCUS");
779 lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
780 break;
782 case WM_SETFONT:
783 DPRINTF_EDIT_MSG32("WM_SETFONT");
784 lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
785 break;
787 case WM_SETREDRAW:
788 DPRINTF_EDIT_MSG32("WM_SETREDRAW");
789 lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
790 break;
792 case WM_SETTEXT:
793 DPRINTF_EDIT_MSG32("WM_SETTEXT");
794 lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
795 break;
797 case WM_SIZE:
798 DPRINTF_EDIT_MSG32("WM_SIZE");
799 lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
800 break;
802 case WM_SYSKEYDOWN:
803 DPRINTF_EDIT_MSG32("WM_SYSKEYDOWN");
804 lResult = EDIT_WM_SysKeyDown(wndPtr, wParam, lParam);
805 break;
807 case WM_TIMER:
808 DPRINTF_EDIT_MSG32("WM_TIMER");
809 lResult = EDIT_WM_Timer(wndPtr, wParam, lParam);
810 break;
812 case WM_VSCROLL:
813 DPRINTF_EDIT_MSG32("WM_VSCROLL");
814 lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
815 break;
817 default:
818 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
819 break;
821 EDIT_ReleasePointer(wndPtr);
822 return lResult;
826 /*********************************************************************
828 * EDIT_BuildLineDefs
830 * Build array of pointers to text lines.
831 * Lines can end with '\0' (last line), nothing (if it is too long),
832 * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
835 static void EDIT_BuildLineDefs(WND *wndPtr)
837 EDITSTATE *es = EDITSTATEPTR(wndPtr);
838 LPSTR text = EDIT_GetPasswordPointer(wndPtr);
839 INT32 ww = EDIT_GetWndWidth(wndPtr);
840 HDC32 hdc;
841 HFONT32 hFont;
842 HFONT32 oldFont = 0;
843 LPSTR start, cp;
844 INT32 prev, next;
845 INT32 width;
846 INT32 length;
847 LINE_END ending;
849 hdc = GetDC32(wndPtr->hwndSelf);
850 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
851 if (hFont) oldFont = SelectObject32(hdc, hFont);
853 if (!IsMultiLine(wndPtr)) {
854 es->LineCount = 1;
855 es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
856 es->LineDefs[0].offset = 0;
857 es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0);
858 es->LineDefs[0].ending = END_0;
859 es->TextWidth = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, text,
860 es->LineDefs[0].length,
861 es->NumTabStops, es->TabStops));
862 } else {
863 es->LineCount = 0;
864 start = text;
865 do {
866 if (!(cp = strstr(start, "\r\n"))) {
867 ending = END_0;
868 length = lstrlen32A(start);
869 } else if ((cp > start) && (*(cp - 1) == '\r')) {
870 ending = END_SOFT;
871 length = cp - start - 1;
872 } else {
873 ending = END_HARD;
874 length = cp - start;
876 width = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, start, length,
877 es->NumTabStops, es->TabStops));
879 if (IsWordWrap(wndPtr) && (width > ww)) {
880 next = 0;
881 do {
882 prev = next;
883 next = EDIT_CallWordBreakProc(wndPtr, start,
884 prev + 1, length, WB_RIGHT);
885 width = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, start, next,
886 es->NumTabStops, es->TabStops));
887 } while (width <= ww);
888 if (!prev) {
889 next = 0;
890 do {
891 prev = next;
892 next++;
893 width = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, start, next,
894 es->NumTabStops, es->TabStops));
895 } while (width <= ww);
896 if(!prev) prev = 1;
898 length = prev;
899 if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
900 length, WB_ISDELIMITER)) {
901 length--;
902 ending = END_DELIMIT;
903 } else
904 ending = END_NONE;
905 width = (INT32)LOWORD(GetTabbedTextExtent32A(hdc, start, length,
906 es->NumTabStops, es->TabStops));
909 es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF));
910 es->LineDefs[es->LineCount].offset = start - text;
911 es->LineDefs[es->LineCount].length = length;
912 es->LineDefs[es->LineCount].ending = ending;
913 es->LineCount++;
914 es->TextWidth = MAX(es->TextWidth, width);
916 start += length;
917 switch (ending) {
918 case END_SOFT:
919 start += 3;
920 break;
921 case END_HARD:
922 start += 2;
923 break;
924 case END_DELIMIT:
925 start++;
926 break;
927 default:
928 break;
930 } while (*start || (ending == END_SOFT) || (ending == END_HARD));
932 if (hFont) SelectObject32(hdc, oldFont);
933 ReleaseDC32(wndPtr->hwndSelf, hdc);
935 free(text);
939 /*********************************************************************
941 * EDIT_CallWordBreakProc
943 * Call appropriate WordBreakProc (internal or external).
945 * FIXME: Heavily broken now that we have a LOCAL32 buffer.
946 * External wordbreak functions have been disabled in
947 * EM_SETWORDBREAKPROC.
950 static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action)
952 return EDIT_WordBreakProc(s, index, count, action);
954 * EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0);
956 * if (!wbp) return EDIT_WordBreakProc(s, index, count, action);
957 * else {
958 * EDITSTATE *es = EDITSTATEPTR(wndPtr);
959 * SEGPTR ptr = LOCAL_LockSegptr( wndPtr->hInstance, es->hBuf16 ) +
960 * (INT16)(s - EDIT_GetPointer(wndPtr));
961 * INT ret = CallWordBreakProc( (FARPROC16)wbp, ptr,
962 * index, count, action);
963 * LOCAL_Unlock( wndPtr->hInstance, es->hBuf16 );
964 * return ret;
970 /*********************************************************************
972 * EDIT_ColFromWndX
974 * Calculates, for a given line and X-coordinate on the screen, the column.
977 static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x)
979 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
980 INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
981 INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
982 INT32 i;
984 line = MAX(0, MIN(line, lc - 1));
985 for (i = 0 ; i < ll ; i++)
986 if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
987 break;
988 return i;
992 /*********************************************************************
994 * EDIT_DelEnd
996 * Delete all characters on this line to right of cursor.
999 static void EDIT_DelEnd(WND *wndPtr)
1001 EDIT_EM_SetSel(wndPtr, -1, 0);
1002 EDIT_MoveEnd(wndPtr, TRUE);
1003 EDIT_WM_Clear(wndPtr, 0, 0);
1007 /*********************************************************************
1009 * EDIT_DelLeft
1011 * Delete character to left of cursor.
1014 static void EDIT_DelLeft(WND *wndPtr)
1016 EDIT_EM_SetSel(wndPtr, -1, 0);
1017 EDIT_MoveBackward(wndPtr, TRUE);
1018 EDIT_WM_Clear(wndPtr, 0, 0);
1022 /*********************************************************************
1024 * EDIT_DelRight
1026 * Delete character to right of cursor.
1029 static void EDIT_DelRight(WND *wndPtr)
1031 EDIT_EM_SetSel(wndPtr, -1, 0);
1032 EDIT_MoveForward(wndPtr, TRUE);
1033 EDIT_WM_Clear(wndPtr, 0, 0);
1037 /*********************************************************************
1039 * EDIT_GetAveCharWidth
1042 static INT32 EDIT_GetAveCharWidth(WND *wndPtr)
1044 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1046 return es->AveCharWidth;
1050 /*********************************************************************
1052 * EDIT_GetLineHeight
1055 static INT32 EDIT_GetLineHeight(WND *wndPtr)
1057 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1059 return es->LineHeight;
1063 /*********************************************************************
1065 * EDIT_GetLineRect
1067 * Calculates the bounding rectangle for a line from a starting
1068 * column to an ending column.
1071 static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc)
1073 rc->top = EDIT_WndYFromLine(wndPtr, line);
1074 rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
1075 rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
1076 rc->right = (ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
1077 EDIT_WndXFromCol(wndPtr, line, ecol);
1081 /*********************************************************************
1083 * EDIT_GetPointer
1085 * This acts as a LOCAL_Lock(), but it locks only once. This way
1086 * you can call it whenever you like, without unlocking.
1089 static LPSTR EDIT_GetPointer(WND *wndPtr)
1091 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1093 if (!es->text && (es->hBuf32 || es->hBuf16)) {
1094 if (es->hBuf32)
1095 es->text = (LPSTR)LocalLock32(es->hBuf32);
1096 else
1097 es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf16);
1099 return es->text;
1103 /*********************************************************************
1105 * EDIT_GetPasswordPointer
1109 static LPSTR EDIT_GetPasswordPointer(WND *wndPtr)
1111 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1112 LPSTR text = xstrdup(EDIT_GetPointer(wndPtr));
1113 LPSTR p;
1115 if(es->PasswordChar) {
1116 p = text;
1117 while(*p != '\0') {
1118 if(*p != '\r' && *p != '\n')
1119 *p = es->PasswordChar;
1120 p++;
1123 return text;
1127 /*********************************************************************
1129 * EDIT_GetRedraw
1132 static BOOL32 EDIT_GetRedraw(WND *wndPtr)
1134 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1136 return es->Redraw;
1140 /*********************************************************************
1142 * EDIT_GetSel
1144 * Beware: This is not the function called on EM_GETSEL.
1145 * This is the unordered version used internally
1146 * (s can be > e). No return value either.
1149 static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e)
1151 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1153 if (s)
1154 *s = es->SelStart;
1155 if (e)
1156 *e = es->SelEnd;
1160 /*********************************************************************
1162 * EDIT_GetTextWidth
1165 static INT32 EDIT_GetTextWidth(WND *wndPtr)
1167 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1169 return es->TextWidth;
1173 /*********************************************************************
1175 * EDIT_GetUndoPointer
1177 * This acts as a LocalLock32(), but it locks only once. This way
1178 * you can call it whenever you like, without unlocking.
1181 static LPSTR EDIT_GetUndoPointer(WND *wndPtr)
1183 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1185 if (!es->UndoText && es->hUndoBuf)
1186 es->UndoText = (LPSTR)LocalLock32(es->hUndoBuf);
1187 return es->UndoText;
1191 /*********************************************************************
1193 * EDIT_GetVisibleLineCount
1196 static INT32 EDIT_GetVisibleLineCount(WND *wndPtr)
1198 RECT32 rc;
1200 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
1201 return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
1205 /*********************************************************************
1207 * EDIT_GetWndWidth
1210 static INT32 EDIT_GetWndWidth(WND *wndPtr)
1212 RECT32 rc;
1214 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
1215 return rc.right - rc.left;
1219 /*********************************************************************
1221 * EDIT_GetXOffset
1224 static INT32 EDIT_GetXOffset(WND *wndPtr)
1226 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1228 return es->XOffset;
1232 /*********************************************************************
1234 * EDIT_InvalidateText
1236 * Invalidate the text from offset start upto, but not including,
1237 * offset end. Useful for (re)painting the selection.
1238 * Regions outside the linewidth are not invalidated.
1239 * end == -1 means end == TextLength.
1240 * start and end need not be ordered.
1243 static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end)
1245 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1246 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
1247 INT32 sl;
1248 INT32 el;
1249 INT32 sc;
1250 INT32 ec;
1251 RECT32 rcWnd;
1252 RECT32 rcLine;
1253 RECT32 rcUpdate;
1254 INT32 l;
1256 if (end == start)
1257 return;
1259 if (end == -1)
1260 end = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
1261 ORDER_INT32(start, end);
1262 sl = (INT32)EDIT_EM_LineFromChar(wndPtr, start, 0);
1263 el = (INT32)EDIT_EM_LineFromChar(wndPtr, end, 0);
1264 if ((el < fv) || (sl > fv + vlc))
1265 return;
1267 sc = start - (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0);
1268 ec = end - (INT32)EDIT_EM_LineIndex(wndPtr, el, 0);
1269 if (sl < fv) {
1270 sl = fv;
1271 sc = 0;
1273 if (el > fv + vlc) {
1274 el = fv + vlc;
1275 ec = (INT32)EDIT_EM_LineLength(wndPtr,
1276 (INT32)EDIT_EM_LineIndex(wndPtr, el, 0), 0);
1278 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
1279 if (sl == el) {
1280 EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
1281 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1282 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1283 } else {
1284 EDIT_GetLineRect(wndPtr, sl, sc,
1285 (INT32)EDIT_EM_LineLength(wndPtr,
1286 (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0), 0),
1287 &rcLine);
1288 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1289 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1290 for (l = sl + 1 ; l < el ; l++) {
1291 EDIT_GetLineRect(wndPtr, l, 0,
1292 (INT32)EDIT_EM_LineLength(wndPtr,
1293 (INT32)EDIT_EM_LineIndex(wndPtr, l, 0), 0),
1294 &rcLine);
1295 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1296 InvalidateRect32(wndPtr->hwndSelf, &rcUpdate, FALSE);
1298 EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
1299 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1300 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1305 /*********************************************************************
1307 * EDIT_LineFromWndY
1309 * Calculates, for a given Y-coordinate on the screen, the line.
1312 static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y)
1314 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1315 INT32 lh = EDIT_GetLineHeight(wndPtr);
1316 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
1318 return MAX(0, MIN(lc - 1, y / lh + fv));
1322 /*********************************************************************
1324 * EDIT_MakeFit
1326 * Try to fit size + 1 bytes in the buffer. Constrain to limits.
1329 static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size)
1331 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1332 HLOCAL32 hNew32;
1333 HLOCAL16 hNew16;
1335 if (size <= es->BufSize)
1336 return TRUE;
1337 if (size > es->BufLimit) {
1338 dprintf_edit(stddeb, "edit: notification EN_MAXTEXT sent\n");
1339 EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
1340 return FALSE;
1342 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
1343 if (size > es->BufLimit)
1344 size = es->BufLimit;
1346 dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
1348 EDIT_ReleasePointer(wndPtr);
1349 if (es->hBuf32) {
1350 if ((hNew32 = LocalReAlloc32(es->hBuf32, size + 1, 0))) {
1351 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 32 bit handle %08x, new handle %08x\n", es->hBuf32, hNew32);
1352 es->hBuf32 = hNew32;
1353 es->BufSize = MIN(LocalSize32(es->hBuf32) - 1, es->BufLimit);
1354 if (es->BufSize < size) {
1355 dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize);
1356 dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n");
1357 EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE);
1358 return FALSE;
1360 dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
1361 return TRUE;
1363 } else {
1364 if ((hNew16 = LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf16, size + 1, LMEM_MOVEABLE))) {
1365 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 16 bit handle %08x, new handle %08x\n", es->hBuf16, hNew16);
1366 es->hBuf16 = hNew16;
1367 es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1, es->BufLimit);
1368 if (es->BufSize < size) {
1369 dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize);
1370 dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n");
1371 EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE);
1372 return FALSE;
1374 dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
1375 return TRUE;
1378 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Reallocation failed\n");
1379 dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n");
1380 EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE);
1381 return FALSE;
1385 /*********************************************************************
1387 * EDIT_MakeUndoFit
1389 * Try to fit size + 1 bytes in the undo buffer.
1392 static BOOL32 EDIT_MakeUndoFit(WND *wndPtr, INT32 size)
1394 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1395 HLOCAL32 hNew;
1397 if (size <= es->UndoBufSize)
1398 return TRUE;
1399 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
1401 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: trying to ReAlloc to %d+1\n", size);
1403 EDIT_ReleaseUndoPointer(wndPtr);
1404 if ((hNew = LocalReAlloc32(es->hUndoBuf, size + 1, 0))) {
1405 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: Old handle %08x, new handle %08x\n", es->hUndoBuf, hNew);
1406 es->hUndoBuf = hNew;
1407 es->UndoBufSize = LocalSize32(es->hUndoBuf) - 1;
1408 if (es->UndoBufSize < size) {
1409 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: FAILED ! We now have %d+1\n", es->UndoBufSize);
1410 return FALSE;
1412 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: We now have %d+1\n", es->UndoBufSize);
1413 return TRUE;
1415 return FALSE;
1419 /*********************************************************************
1421 * EDIT_MoveBackward
1424 static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend)
1426 INT32 s;
1427 INT32 e;
1428 INT32 l;
1429 INT32 li;
1431 EDIT_GetSel(wndPtr, &s, &e);
1432 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1433 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1434 if (e - li == 0) {
1435 if (l) {
1436 li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
1437 e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1439 } else
1440 e--;
1441 if (!extend)
1442 s = e;
1443 EDIT_SetSel(wndPtr, s, e);
1444 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1448 /*********************************************************************
1450 * EDIT_MoveDownward
1453 static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend)
1455 INT32 s;
1456 INT32 e;
1457 INT32 l;
1458 INT32 lc;
1459 INT32 li;
1460 INT32 x;
1462 EDIT_GetSel(wndPtr, &s, &e);
1463 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1464 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1465 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1466 if (l < lc - 1) {
1467 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1468 l++;
1469 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1470 EDIT_ColFromWndX(wndPtr, l, x);
1472 if (!extend)
1473 s = e;
1474 EDIT_SetSel(wndPtr, s, e);
1475 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1479 /*********************************************************************
1481 * EDIT_MoveEnd
1484 static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend)
1486 INT32 s;
1487 INT32 e;
1488 INT32 l;
1489 INT32 ll;
1490 INT32 li;
1492 EDIT_GetSel(wndPtr, &s, &e);
1493 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1494 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1495 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1496 e = li + ll;
1497 if (!extend)
1498 s = e;
1499 EDIT_SetSel(wndPtr, s, e);
1500 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1504 /*********************************************************************
1506 * EDIT_MoveForward
1509 static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend)
1511 INT32 s;
1512 INT32 e;
1513 INT32 l;
1514 INT32 lc;
1515 INT32 ll;
1516 INT32 li;
1518 EDIT_GetSel(wndPtr, &s, &e);
1519 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1520 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1521 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1522 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1523 if (e - li == ll) {
1524 if (l != lc - 1)
1525 e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
1526 } else
1527 e++;
1528 if (!extend)
1529 s = e;
1530 EDIT_SetSel(wndPtr, s, e);
1531 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1535 /*********************************************************************
1537 * EDIT_MoveHome
1539 * Home key: move to beginning of line.
1542 static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend)
1544 INT32 s;
1545 INT32 e;
1546 INT32 l;
1547 INT32 li;
1549 EDIT_GetSel(wndPtr, &s, &e);
1550 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1551 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1552 e = li;
1553 if (!extend)
1554 s = e;
1555 EDIT_SetSel(wndPtr, s, e);
1556 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1560 /*********************************************************************
1562 * EDIT_MovePageDown
1565 static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend)
1567 INT32 s;
1568 INT32 e;
1569 INT32 l;
1570 INT32 lc;
1571 INT32 li;
1572 INT32 x;
1574 EDIT_GetSel(wndPtr, &s, &e);
1575 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1576 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1577 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1578 if (l < lc - 1) {
1579 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1580 l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
1581 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1582 EDIT_ColFromWndX(wndPtr, l, x);
1584 if (!extend)
1585 s = e;
1586 EDIT_SetSel(wndPtr, s, e);
1587 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1591 /*********************************************************************
1593 * EDIT_MovePageUp
1596 static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend)
1598 INT32 s;
1599 INT32 e;
1600 INT32 l;
1601 INT32 li;
1602 INT32 x;
1604 EDIT_GetSel(wndPtr, &s, &e);
1605 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1606 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1607 if (l) {
1608 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1609 l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
1610 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1611 EDIT_ColFromWndX(wndPtr, l, x);
1613 if (!extend)
1614 s = e;
1615 EDIT_SetSel(wndPtr, s, e);
1616 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1620 /*********************************************************************
1622 * EDIT_MoveUpward
1625 static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend)
1627 INT32 s;
1628 INT32 e;
1629 INT32 l;
1630 INT32 li;
1631 INT32 x;
1633 EDIT_GetSel(wndPtr, &s, &e);
1634 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1635 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1636 if (l) {
1637 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1638 l--;
1639 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1640 EDIT_ColFromWndX(wndPtr, l, x);
1642 if (!extend)
1643 s = e;
1644 EDIT_SetSel(wndPtr, s, e);
1645 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1649 /*********************************************************************
1651 * EDIT_MoveWordBackward
1654 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend)
1656 INT32 s;
1657 INT32 e;
1658 INT32 l;
1659 INT32 ll;
1660 INT32 li;
1661 LPSTR text;
1663 EDIT_GetSel(wndPtr, &s, &e);
1664 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1665 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1666 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1667 if (e - li == 0) {
1668 if (l) {
1669 li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
1670 e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1672 } else {
1673 text = EDIT_GetPointer(wndPtr);
1674 e = li + (INT32)EDIT_CallWordBreakProc(wndPtr,
1675 text + li, e - li, ll, WB_LEFT);
1677 if (!extend)
1678 s = e;
1679 EDIT_SetSel(wndPtr, s, e);
1680 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1684 /*********************************************************************
1686 * EDIT_MoveWordForward
1689 static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend)
1691 INT32 s;
1692 INT32 e;
1693 INT32 l;
1694 INT32 lc;
1695 INT32 ll;
1696 INT32 li;
1697 LPSTR text;
1699 EDIT_GetSel(wndPtr, &s, &e);
1700 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1701 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1702 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1703 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1704 if (e - li == ll) {
1705 if (l != lc - 1)
1706 e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
1707 } else {
1708 text = EDIT_GetPointer(wndPtr);
1709 e = li + EDIT_CallWordBreakProc(wndPtr,
1710 text + li, e - li + 1, ll, WB_RIGHT);
1712 if (!extend)
1713 s = e;
1714 EDIT_SetSel(wndPtr, s, e);
1715 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1719 /*********************************************************************
1721 * EDIT_PaintLine
1724 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev)
1726 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1727 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
1728 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
1729 INT32 li;
1730 INT32 ll;
1731 INT32 s;
1732 INT32 e;
1733 INT32 x;
1734 INT32 y;
1736 if ((line < fv) || (line > fv + vlc) || (line >= lc))
1737 return;
1739 dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
1741 x = EDIT_WndXFromCol(wndPtr, line, 0);
1742 y = EDIT_WndYFromLine(wndPtr, line);
1743 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
1744 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1745 EDIT_GetSel(wndPtr, &s, &e);
1746 ORDER_INT32(s, e);
1747 s = MIN(li + ll, MAX(li, s));
1748 e = MIN(li + ll, MAX(li, e));
1749 if (rev && (s != e) &&
1750 ((GetFocus32() == wndPtr->hwndSelf) ||
1751 (wndPtr->dwStyle & ES_NOHIDESEL))) {
1752 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
1753 x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
1754 x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
1755 } else
1756 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
1760 /*********************************************************************
1762 * EDIT_PaintText
1765 static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev)
1767 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1768 COLORREF BkColor;
1769 COLORREF TextColor;
1770 INT32 ret;
1771 LPSTR text;
1772 INT32 li;
1773 INT32 xoff;
1775 if (!count)
1776 return 0;
1777 BkColor = GetBkColor32(hdc);
1778 TextColor = GetTextColor32(hdc);
1779 if (rev)
1781 SetBkColor32(hdc, GetSysColor32(COLOR_HIGHLIGHT));
1782 SetTextColor32(hdc, GetSysColor32(COLOR_HIGHLIGHTTEXT));
1784 text = EDIT_GetPasswordPointer(wndPtr);
1785 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
1786 xoff = EDIT_GetXOffset(wndPtr);
1787 ret = (INT32)LOWORD(TabbedTextOut32A(hdc, x, y, text + li + col, count,
1788 es->NumTabStops, es->TabStops, -xoff));
1789 free(text);
1790 if (rev)
1792 SetBkColor32(hdc, BkColor);
1793 SetTextColor32(hdc, TextColor);
1795 return ret;
1799 /*********************************************************************
1801 * EDIT_ReleasePointer
1803 * This is the only helper function that can be called with es = NULL.
1804 * It is called at the end of EditWndProc() to unlock the buffer.
1807 static void EDIT_ReleasePointer(WND *wndPtr)
1809 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1811 if (!es)
1812 return;
1813 if (es->text && (es->hBuf32 || es->hBuf16)) {
1814 if (es->hBuf32)
1815 LocalUnlock32(es->hBuf32);
1816 else
1817 LOCAL_Unlock(wndPtr->hInstance, es->hBuf16);
1819 es->text = NULL;
1823 /*********************************************************************
1825 * EDIT_ReleaseUndoPointer
1827 * This is the only helper function that can be called with es = NULL.
1828 * It is called at the end of EditWndProc() to unlock the buffer.
1831 static void EDIT_ReleaseUndoPointer(WND *wndPtr)
1833 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1835 if (!es)
1836 return;
1837 if (es->UndoText && es->hUndoBuf)
1838 LocalUnlock32(es->hUndoBuf);
1839 es->UndoText = NULL;
1843 /*********************************************************************
1845 * EDIT_SetSel
1847 * Beware: This is not the function called on EM_SETSEL.
1848 * This is the unordered version used internally
1849 * (s can be > e). Doesn't accept -1 parameters either.
1850 * No range checking.
1853 static void EDIT_SetSel(WND *wndPtr, INT32 ns, INT32 ne)
1855 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1856 LRESULT pos;
1857 INT32 s;
1858 INT32 e;
1860 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
1861 es->SelStart = ns;
1862 es->SelEnd = ne;
1863 if (EDIT_GetRedraw(wndPtr)) {
1864 if (wndPtr->hwndSelf == GetFocus32()) {
1865 pos = EDIT_EM_PosFromChar(wndPtr, ne, 0);
1866 SetCaretPos16((INT16)LOWORD(pos), (INT16)HIWORD(pos));
1868 ORDER_INT32(s, ns);
1869 ORDER_INT32(s, ne);
1870 ORDER_INT32(e, ns);
1871 ORDER_INT32(e, ne);
1872 ORDER_INT32(ns, ne);
1873 if (e != ns) {
1874 EDIT_InvalidateText(wndPtr, s, e);
1875 EDIT_InvalidateText(wndPtr, ns, ne);
1876 } else
1877 EDIT_InvalidateText(wndPtr, s, ne);
1882 /*********************************************************************
1884 * EDIT_WndXFromCol
1886 * Calculates, for a given line and column, the X-coordinate on the screen.
1889 static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col)
1891 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1892 LPSTR text = EDIT_GetPasswordPointer(wndPtr);
1893 INT32 ret;
1894 HDC32 hdc;
1895 HFONT32 hFont;
1896 HFONT32 oldFont = 0;
1897 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
1898 INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
1899 INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1900 INT32 xoff = EDIT_GetXOffset(wndPtr);
1902 hdc = GetDC32(wndPtr->hwndSelf);
1903 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
1904 if (hFont) oldFont = SelectObject32(hdc, hFont);
1905 line = MAX(0, MIN(line, lc - 1));
1906 col = MIN(col, ll);
1907 ret = (INT32)LOWORD(GetTabbedTextExtent32A(hdc,
1908 text + li, col,
1909 es->NumTabStops, es->TabStops)) - xoff;
1910 if (hFont) SelectObject32(hdc, oldFont);
1911 ReleaseDC32(wndPtr->hwndSelf, hdc);
1912 free(text);
1913 return ret;
1917 /*********************************************************************
1919 * EDIT_WndYFromLine
1921 * Calculates, for a given line, the Y-coordinate on the screen.
1924 static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line)
1926 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1927 INT32 lh = EDIT_GetLineHeight(wndPtr);
1929 return (line - fv) * lh;
1933 /*********************************************************************
1935 * EDIT_WordBreakProc
1937 * Find the beginning of words.
1938 * Note: unlike the specs for a WordBreakProc, this function only
1939 * allows to be called without linebreaks between s[0] upto
1940 * s[count - 1]. Remember it is only called
1941 * internally, so we can decide this for ourselves.
1944 static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action)
1946 INT32 ret = 0;
1948 dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%u"
1949 ", count=%u, action=%d\n", s, index, count, action);
1951 switch (action) {
1952 case WB_LEFT:
1953 if (!count)
1954 break;
1955 if (index)
1956 index--;
1957 if (s[index] == ' ') {
1958 while (index && (s[index] == ' '))
1959 index--;
1960 if (index) {
1961 while (index && (s[index] != ' '))
1962 index--;
1963 if (s[index] == ' ')
1964 index++;
1966 } else {
1967 while (index && (s[index] != ' '))
1968 index--;
1969 if (s[index] == ' ')
1970 index++;
1972 ret = index;
1973 break;
1974 case WB_RIGHT:
1975 if (!count)
1976 break;
1977 if (index)
1978 index--;
1979 if (s[index] == ' ')
1980 while ((index < count) && (s[index] == ' ')) index++;
1981 else {
1982 while (s[index] && (s[index] != ' ') && (index < count))
1983 index++;
1984 while ((s[index] == ' ') && (index < count)) index++;
1986 ret = index;
1987 break;
1988 case WB_ISDELIMITER:
1989 ret = (s[index] == ' ');
1990 break;
1991 default:
1992 fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
1993 break;
1995 return ret;
1999 /*********************************************************************
2001 * EM_CANUNDO
2004 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2006 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2008 return (LRESULT)(es->UndoInsertLen || lstrlen32A(EDIT_GetUndoPointer(wndPtr)));
2012 /*********************************************************************
2014 * EM_CHARFROMPOS
2016 * FIXME: do the specs mean LineIndex or LineNumber (li v.s. l) ???
2018 static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2020 POINT32 pt;
2021 RECT32 rc;
2022 INT32 l;
2023 INT32 li;
2024 INT32 c;
2026 pt.x = LOWORD(lParam);
2027 pt.y = HIWORD(lParam);
2028 GetClientRect32(wndPtr->hwndSelf, &rc);
2030 if (!PtInRect32(&rc, pt))
2031 return -1;
2033 l = EDIT_LineFromWndY(wndPtr, pt.y);
2034 li = EDIT_EM_LineIndex(wndPtr, l, 0);
2035 c = EDIT_ColFromWndX(wndPtr, l, pt.x);
2037 return (LRESULT)MAKELONG(li + c, li);
2041 /*********************************************************************
2043 * EM_EMPTYUNDOBUFFER
2046 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2048 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2050 es->UndoInsertLen = 0;
2051 *EDIT_GetUndoPointer(wndPtr) = '\0';
2052 return 0;
2056 /*********************************************************************
2058 * EM_FMTLINES
2061 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2063 fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented\n");
2064 return wParam ? TRUE : FALSE;
2068 /*********************************************************************
2070 * EM_GETFIRSTVISIBLELINE
2073 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2075 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2077 if (IsMultiLine(wndPtr))
2078 return (LRESULT)es->FirstVisibleLine;
2079 else
2080 return (LRESULT)EDIT_ColFromWndX(wndPtr, 0, 0);
2084 /*********************************************************************
2086 * EM_GETHANDLE
2089 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2091 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2093 if (!IsMultiLine(wndPtr))
2094 return 0;
2096 if (es->hBuf32)
2097 return (LRESULT)es->hBuf32;
2098 else
2099 return (LRESULT)es->hBuf16;
2103 /*********************************************************************
2105 * EM_GETHANDLE16
2107 * Hopefully this won't fire back at us.
2108 * We always start with a buffer in 32 bit linear memory.
2109 * However, with this message a 16 bit application requests
2110 * a handle of 16 bit local heap memory, where it expects to find
2111 * the text.
2112 * It's a pitty that from this moment on we have to use this
2113 * local heap, because applications may rely on the handle
2114 * in the future.
2116 * In this function we'll try to switch to local heap.
2118 static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2120 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2121 LPSTR text;
2122 HLOCAL16 newBuf;
2123 LPSTR newText;
2124 INT16 newSize;
2126 if (!IsMultiLine(wndPtr))
2127 return 0;
2129 if (es->hBuf16)
2130 return (LRESULT)es->hBuf16;
2132 if (!LOCAL_HeapSize(wndPtr->hInstance)) {
2133 if (!LocalInit(wndPtr->hInstance, 0,
2134 GlobalSize16(wndPtr->hInstance))) {
2135 fprintf(stderr, "edit: EM_GETHANDLE: could not initialize local heap\n");
2136 return 0;
2138 dprintf_edit(stddeb, "edit: EM_GETHANDLE: local heap initialized\n");
2140 if (!(newBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE,
2141 EDIT_WM_GetTextLength(wndPtr, 0, 0) + 1)))
2143 fprintf(stderr, "edit: EM_GETHANDLE: could not allocate new 16 bit buffer\n");
2144 return 0;
2146 newSize = MIN(LOCAL_Size(wndPtr->hInstance, newBuf) - 1, es->BufLimit);
2147 if (!(newText = LOCAL_Lock(wndPtr->hInstance, newBuf))) {
2148 fprintf(stderr, "edit: EM_GETHANDLE: could not lock new 16 bit buffer\n");
2149 LOCAL_Free(wndPtr->hInstance, newBuf);
2150 return 0;
2152 text = EDIT_GetPointer(wndPtr);
2153 lstrcpy32A(newText, text);
2154 EDIT_ReleasePointer(wndPtr);
2155 GlobalFree32(es->hBuf32);
2156 es->hBuf32 = (HLOCAL32)NULL;
2157 es->hBuf16 = newBuf;
2158 es->BufSize = newSize;
2159 es->text = newText;
2160 dprintf_edit(stddeb, "edit: EM_GETHANDLE: switched to 16 bit buffer\n");
2162 return (LRESULT)es->hBuf16;
2166 /*********************************************************************
2168 * EM_GETLIMITTEXT
2171 static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2173 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2175 return es->BufLimit;
2179 /*********************************************************************
2181 * EM_GETLINE
2184 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2186 LPSTR text;
2187 LPSTR src;
2188 LPSTR dst;
2189 INT32 len;
2190 INT32 i;
2191 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
2193 if (!IsMultiLine(wndPtr))
2194 wParam = 0;
2195 if ((INT32)wParam >= lc)
2196 return 0;
2197 text = EDIT_GetPointer(wndPtr);
2198 src = text + (INT32)EDIT_EM_LineIndex(wndPtr, wParam, 0);
2199 dst = (LPSTR)lParam;
2200 len = MIN(*(WORD *)dst, (INT32)EDIT_EM_LineLength(wndPtr, wParam, 0));
2201 for (i = 0 ; i < len ; i++) {
2202 *dst = *src;
2203 src++;
2204 dst++;
2206 return (LRESULT)len;
2210 /*********************************************************************
2212 * EM_GETLINECOUNT
2215 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2217 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2219 return (LRESULT)es->LineCount;
2223 /*********************************************************************
2225 * EM_GETMARGINS
2228 static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2230 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2232 return (LRESULT)MAKELONG(es->LeftMargin, es->RightMargin);
2236 /*********************************************************************
2238 * EM_GETMODIFY
2241 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2243 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2245 return (LRESULT)es->TextChanged;
2249 /*********************************************************************
2251 * EM_GETPASSWORDCHAR
2254 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2256 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2258 return (LRESULT)es->PasswordChar;
2262 /*********************************************************************
2264 * EM_GETRECT
2267 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2269 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2271 CopyRect32((LPRECT32)lParam, &es->FormatRect);
2272 return 0;
2276 /*********************************************************************
2278 * EM_GETRECT16
2281 static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2283 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2285 CONV_RECT32TO16(&es->FormatRect, (LPRECT16)PTR_SEG_TO_LIN((SEGPTR)lParam));
2286 return 0;
2290 /*********************************************************************
2292 * EM_GETSEL
2294 * Returns the ordered selection range so that
2295 * LOWORD(result) < HIWORD(result)
2298 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2300 INT32 s;
2301 INT32 e;
2303 EDIT_GetSel(wndPtr, &s, &e);
2304 ORDER_INT32(s, e);
2305 if (wParam)
2306 *(LPINT32)wParam = s;
2307 if (lParam)
2308 *(LPINT32)lParam = e;
2309 return MAKELONG((INT16)s, (INT16)e);
2313 /*********************************************************************
2315 * EM_GETTHUMB
2317 * FIXME: is this right ? (or should it be only HSCROLL)
2318 * (and maybe only for edit controls that really have their
2319 * own scrollbars) (and maybe only for multiline controls ?)
2320 * All in all: very poorly documented
2323 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2325 return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0),
2326 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0));
2330 /*********************************************************************
2332 * EM_GETWORDBREAKPROC
2334 * FIXME: Application defined WordBreakProc should be returned
2337 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2340 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2342 return (LRESULT)es->WordBreakProc;
2344 return 0;
2348 /*********************************************************************
2350 * EM_LINEFROMCHAR
2353 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2355 INT32 l;
2357 if (!IsMultiLine(wndPtr))
2358 return 0;
2359 if ((INT32)wParam == -1)
2360 EDIT_EM_GetSel(wndPtr, (WPARAM32)&wParam, 0); /* intentional (looks weird, doesn't it ?) */
2361 l = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0) - 1;
2362 while ((INT32)EDIT_EM_LineIndex(wndPtr, l, 0) > (INT32)wParam)
2363 l--;
2364 return (LRESULT)l;
2368 /*********************************************************************
2370 * EM_LINEINDEX
2373 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2375 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2376 INT32 e;
2377 INT32 l;
2378 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
2380 if ((INT32)wParam == -1) {
2381 EDIT_GetSel(wndPtr, NULL, &e);
2382 l = lc - 1;
2383 while (es->LineDefs[l].offset > e)
2384 l--;
2385 return (LRESULT)es->LineDefs[l].offset;
2387 if ((INT32)wParam >= lc)
2388 return -1;
2389 return (LRESULT)es->LineDefs[(INT32)wParam].offset;
2393 /*********************************************************************
2395 * EM_LINELENGTH
2398 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2400 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2401 INT32 s;
2402 INT32 e;
2403 INT32 sl;
2404 INT32 el;
2406 if (!IsMultiLine(wndPtr))
2407 return (LRESULT)es->LineDefs[0].length;
2408 if ((INT32)wParam == -1) {
2409 EDIT_GetSel(wndPtr, &s, &e);
2410 sl = (INT32)EDIT_EM_LineFromChar(wndPtr, s, 0);
2411 el = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
2412 return (LRESULT)(s - es->LineDefs[sl].offset +
2413 es->LineDefs[el].offset +
2414 es->LineDefs[el].length - e);
2416 return (LRESULT)es->LineDefs[(INT32)EDIT_EM_LineFromChar(wndPtr, wParam, 0)].length;
2420 /*********************************************************************
2422 * EM_LINESCROLL
2424 * FIXME: is wParam in pixels or in average character widths ???
2425 * FIXME: we use this internally to scroll single line controls as well
2426 * (specs are vague about whether this message is valid or not for
2427 * single line controls)
2430 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2432 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2433 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
2434 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
2435 INT32 nfv = MAX(0, fv + (INT32)lParam);
2436 INT32 xoff = EDIT_GetXOffset(wndPtr);
2437 INT32 nxoff = MAX(0, xoff + (INT32)wParam);
2438 INT32 tw = EDIT_GetTextWidth(wndPtr);
2439 INT32 dx;
2440 INT32 dy;
2442 if (nfv >= lc)
2443 nfv = lc - 1;
2445 if (nxoff >= tw)
2446 nxoff = tw;
2447 dx = xoff - nxoff;
2448 dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
2449 if (dx || dy) {
2450 if (EDIT_GetRedraw(wndPtr))
2451 ScrollWindow32(wndPtr->hwndSelf, dx, dy, NULL, NULL);
2452 es->FirstVisibleLine = nfv;
2453 es->XOffset = nxoff;
2454 if (IsVScrollBar(wndPtr))
2455 SetScrollPos32(wndPtr->hwndSelf, SB_VERT,
2456 EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
2457 if (IsHScrollBar(wndPtr))
2458 SetScrollPos32(wndPtr->hwndSelf, SB_HORZ,
2459 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
2461 if (IsMultiLine(wndPtr))
2462 return TRUE;
2463 else
2464 return FALSE;
2468 /*********************************************************************
2470 * EM_POSFROMCHAR
2473 static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2475 INT32 len = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
2476 INT32 l;
2477 INT32 li;
2479 wParam = MIN(wParam, len);
2480 l = EDIT_EM_LineFromChar(wndPtr, wParam, 0);
2481 li = EDIT_EM_LineIndex(wndPtr, l, 0);
2482 return (LRESULT)MAKELONG(EDIT_WndXFromCol(wndPtr, l, wParam - li),
2483 EDIT_WndYFromLine(wndPtr, l));
2487 /*********************************************************************
2489 * EM_REPLACESEL
2492 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2494 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2495 LPCSTR str = (LPCSTR)lParam;
2496 INT32 strl = lstrlen32A(str);
2497 INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
2498 INT32 utl;
2499 INT32 s;
2500 INT32 e;
2501 INT32 i;
2502 LPSTR p;
2503 LPSTR text;
2504 LPSTR utext;
2505 BOOL32 redraw;
2507 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
2509 if ((s == e) && !strl)
2510 return 0;
2512 if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl))
2513 return 0;
2515 text = EDIT_GetPointer(wndPtr);
2516 utext = EDIT_GetUndoPointer(wndPtr);
2517 if (e != s) {
2518 /* there is something to be deleted */
2519 if ((BOOL32)wParam) {
2520 /* we have to be able to undo */
2521 utl = lstrlen32A(utext);
2522 if (!es->UndoInsertLen && (*utext && (s == es->UndoPos))) {
2523 /* undo-buffer is extended to the right */
2524 EDIT_MakeUndoFit(wndPtr, utl + e - s);
2525 lstrcpyn32A(utext + utl, text + s, e - s + 1);
2526 } else if (!es->UndoInsertLen && (*utext && (e == es->UndoPos))) {
2527 /* undo-buffer is extended to the left */
2528 EDIT_MakeUndoFit(wndPtr, utl + e - s);
2529 for (p = utext + utl ; p >= utext ; p--)
2530 p[e - s] = p[0];
2531 for (i = 0 , p = utext ; i < e - s ; i++)
2532 p[i] = (text + s)[i];
2533 es->UndoPos = s;
2534 } else {
2535 /* new undo-buffer */
2536 EDIT_MakeUndoFit(wndPtr, e - s);
2537 lstrcpyn32A(utext, text + s, e - s + 1);
2538 es->UndoPos = s;
2540 /* any deletion makes the old insertion-undo invalid */
2541 es->UndoInsertLen = 0;
2542 } else
2543 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2545 /* now delete */
2546 lstrcpy32A(text + s, text + e);
2548 if (strl) {
2549 /* there is an insertion */
2550 if ((BOOL32)wParam) {
2551 /* we have to be able to undo */
2552 if ((s == es->UndoPos) ||
2553 ((es->UndoInsertLen) &&
2554 (s == es->UndoPos + es->UndoInsertLen)))
2556 * insertion is new and at delete position or
2557 * an extension to either left or right
2559 es->UndoInsertLen += strl;
2560 else {
2561 /* new insertion undo */
2562 es->UndoPos = s;
2563 es->UndoInsertLen = strl;
2564 /* new insertion makes old delete-buffer invalid */
2565 *utext = '\0';
2567 } else
2568 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2570 /* now insert */
2571 tl = lstrlen32A(text);
2572 for (p = text + tl ; p >= text + s ; p--)
2573 p[strl] = p[0];
2574 for (i = 0 , p = text + s ; i < strl ; i++)
2575 p[i] = str[i];
2576 if(IsUpper(wndPtr))
2577 CharUpperBuff32A(p, strl);
2578 else if(IsLower(wndPtr))
2579 CharLowerBuff32A(p, strl);
2580 s += strl;
2582 redraw = EDIT_GetRedraw(wndPtr);
2583 EDIT_WM_SetRedraw(wndPtr, FALSE, 0);
2584 EDIT_BuildLineDefs(wndPtr);
2585 EDIT_EM_SetSel(wndPtr, s, s);
2586 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2587 EDIT_EM_SetModify(wndPtr, TRUE, 0);
2588 dprintf_edit(stddeb, "edit: notification EN_UPDATE sent\n");
2589 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2590 EDIT_WM_SetRedraw(wndPtr, redraw, 0);
2591 if (redraw) {
2592 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2593 dprintf_edit(stddeb, "edit: notification EN_CHANGE sent\n");
2594 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2596 return 0;
2600 /*********************************************************************
2602 * EM_SCROLL
2604 * FIXME: Scroll what ??? And where ???
2607 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2609 fprintf(stdnimp, "edit: EM_SCROLL: message not implemented\n");
2610 return 0;
2614 /*********************************************************************
2616 * EM_SCROLLCARET
2618 * Makes sure the caret is visible.
2619 * FIXME: We use EM_LINESCROLL, but may we do that for single line
2620 * controls ???
2623 static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2625 INT32 e;
2626 INT32 l;
2627 INT32 li;
2628 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
2629 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
2630 INT32 ww = EDIT_GetWndWidth(wndPtr);
2631 INT32 cw = EDIT_GetAveCharWidth(wndPtr);
2632 INT32 x;
2633 INT32 dy = 0;
2634 INT32 dx = 0;
2636 EDIT_GetSel(wndPtr, NULL, &e);
2637 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
2638 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
2639 x = EDIT_WndXFromCol(wndPtr, l, e - li);
2640 if (l >= fv + vlc)
2641 dy = l - vlc + 1 - fv;
2642 if (l < fv)
2643 dy = l - fv;
2644 if (x < 0)
2645 dx = x - ww / HSCROLL_FRACTION / cw * cw;
2646 if (x > ww)
2647 dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
2648 if (dy || dx) {
2649 EDIT_EM_LineScroll(wndPtr, dx, dy);
2650 if (dy) {
2651 dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
2652 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
2654 if (dx) {
2655 dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
2656 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
2659 return TRUE;
2663 /*********************************************************************
2665 * EM_SETHANDLE
2668 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2670 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2672 if (IsMultiLine(wndPtr)) {
2673 EDIT_ReleasePointer(wndPtr);
2675 * old buffer is freed by caller
2677 es->hBuf16 = (HLOCAL16)NULL;
2678 es->hBuf32 = (HLOCAL32)wParam;
2679 es->BufSize = LocalSize32(es->hBuf32) - 1;
2680 es->LineCount = 0;
2681 es->FirstVisibleLine = 0;
2682 es->SelStart = es->SelEnd = 0;
2683 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2684 EDIT_EM_SetModify(wndPtr, FALSE, 0);
2685 EDIT_BuildLineDefs(wndPtr);
2686 if (EDIT_GetRedraw(wndPtr))
2687 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2688 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2690 return 0;
2694 /*********************************************************************
2696 * EM_SETHANDLE16
2699 static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2701 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2703 if (IsMultiLine(wndPtr)) {
2704 EDIT_ReleasePointer(wndPtr);
2706 * old buffer is freed by caller
2708 es->hBuf16 = (HLOCAL16)wParam;
2709 es->hBuf32 = (HLOCAL32)NULL;
2710 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1;
2711 es->LineCount = 0;
2712 es->FirstVisibleLine = 0;
2713 es->SelStart = es->SelEnd = 0;
2714 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2715 EDIT_EM_SetModify(wndPtr, FALSE, 0);
2716 EDIT_BuildLineDefs(wndPtr);
2717 if (EDIT_GetRedraw(wndPtr))
2718 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2719 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2721 return 0;
2725 /*********************************************************************
2727 * EM_SETLIMITTEXT
2729 * FIXME: in WinNT maxsize is 0x7FFFFFFF / 0xFFFFFFFF
2730 * However, the windows version is not complied to yet in all of edit.c
2733 static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2735 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2737 if (IsMultiLine(wndPtr)) {
2738 if (wParam)
2739 es->BufLimit = MIN((INT32)wParam, BUFLIMIT_MULTI);
2740 else
2741 es->BufLimit = BUFLIMIT_MULTI;
2742 } else {
2743 if (wParam)
2744 es->BufLimit = MIN((INT32)wParam, BUFLIMIT_SINGLE);
2745 else
2746 es->BufLimit = BUFLIMIT_SINGLE;
2748 return 0;
2752 /*********************************************************************
2754 * EM_SETMARGINS
2756 * FIXME: We let the margins be set, but we don't use them yet !?!
2759 static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2761 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2763 if (wParam & EC_USEFONTINFO) {
2764 if (IsMultiLine(wndPtr)) {
2766 * FIXME: do some GetABCCharWidth, or so
2767 * This is just preliminary
2769 es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
2770 } else
2771 es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
2772 return 0;
2774 if (wParam & EC_LEFTMARGIN)
2775 es->LeftMargin = LOWORD(lParam);
2776 if (wParam & EC_RIGHTMARGIN)
2777 es->RightMargin = HIWORD(lParam);
2778 return 0;
2782 /*********************************************************************
2784 * EM_SETMODIFY
2787 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2789 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2791 es->TextChanged = (BOOL32)wParam;
2792 return 0;
2796 /*********************************************************************
2798 * EM_SETPASSWORDCHAR
2800 * FIXME: This imlementation is way too simple
2803 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2805 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2807 es->PasswordChar = (CHAR)wParam;
2808 return 0;
2812 /*********************************************************************
2814 * EM_SETREADONLY
2817 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2819 if ((BOOL32)wParam)
2820 wndPtr->dwStyle |= ES_READONLY;
2821 else
2822 wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
2823 return TRUE;
2827 /*********************************************************************
2829 * EM_SETRECT
2832 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2834 fprintf(stdnimp,"edit: EM_SETRECT: message not implemented\n");
2835 return 0;
2839 /*********************************************************************
2841 * EM_SETRECTNP
2844 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2846 fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented\n");
2847 return 0;
2851 /*********************************************************************
2853 * EM_SETSEL
2856 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2858 INT32 ns = (INT32)wParam;
2859 INT32 ne = (INT32)lParam;
2860 INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
2862 if (ns == -1) {
2863 EDIT_GetSel(wndPtr, NULL, &ne);
2864 ns = ne;
2865 } else if ((!ns) && (ne == -1))
2866 ne = tl;
2867 else {
2868 ns = MAX(0, MIN(ns, tl));
2869 ne = MAX(0, MIN(ne, tl));
2870 ORDER_INT32(ns, ne);
2872 EDIT_SetSel(wndPtr, ns, ne);
2873 return -1;
2877 /*********************************************************************
2879 * EM_SETSEL16
2882 static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2884 INT32 ns = (INT32)LOWORD(lParam);
2885 INT32 ne = (INT32)HIWORD(lParam);
2887 if ((INT16)LOWORD(lParam) == -1)
2888 ns = -1;
2889 if ((!ns) && ((INT16)HIWORD(lParam) == -1))
2890 ne = -1;
2891 EDIT_EM_SetSel(wndPtr, ns, ne);
2892 if (!wParam)
2893 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2894 return -1;
2898 /*********************************************************************
2900 * EM_SETTABSTOPS
2903 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2905 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2907 if (!IsMultiLine(wndPtr))
2908 return FALSE;
2909 if (es->TabStops)
2910 free(es->TabStops);
2911 es->NumTabStops = (INT32)wParam;
2912 if (!wParam)
2913 es->TabStops = NULL;
2914 else {
2915 es->TabStops = (LPINT32)xmalloc(wParam * sizeof(INT32));
2916 memcpy( es->TabStops, (LPINT32)lParam,
2917 (INT32)wParam * sizeof(INT32) );
2919 return TRUE;
2923 /*********************************************************************
2925 * EM_SETTABSTOPS16
2928 static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2930 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2931 INT32 i;
2933 if (!IsMultiLine(wndPtr))
2934 return FALSE;
2935 if (es->TabStops)
2936 free(es->TabStops);
2937 es->NumTabStops = (INT32)wParam;
2938 if (!wParam)
2939 es->TabStops = NULL;
2940 else
2942 LPINT16 p = (LPINT16)PTR_SEG_TO_LIN(lParam);
2943 es->TabStops = (LPINT32)xmalloc(wParam * sizeof(INT32));
2944 for ( i = 0 ; i < (INT32)wParam ; i++) es->TabStops[i] = *p++;
2946 return TRUE;
2950 /*********************************************************************
2952 * EM_SETWORDBREAKPROC
2955 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2958 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2960 es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
2962 return 0;
2966 /*********************************************************************
2968 * EM_UNDO / WM_UNDO
2971 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2973 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2974 LPSTR utext = xstrdup(EDIT_GetUndoPointer(wndPtr));
2976 dprintf_edit(stddeb, "edit: before UNDO:insertion length = %d, deletion buffer = %s\n",
2977 es->UndoInsertLen, utext);
2979 EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen);
2980 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2981 EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)utext);
2982 EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen);
2983 free(utext);
2985 dprintf_edit(stddeb, "edit: after UNDO: insertion length = %d, deletion buffer = %s\n",
2986 es->UndoInsertLen, EDIT_GetUndoPointer(wndPtr));
2988 return TRUE;
2992 /*********************************************************************
2994 * WM_CHAR
2997 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2999 char str[2];
3000 unsigned char c = (unsigned char)wParam;
3002 switch (c) {
3003 case '\r':
3004 case '\n':
3005 if (IsMultiLine(wndPtr)) {
3006 if (IsReadOnly(wndPtr)) {
3007 EDIT_MoveHome(wndPtr, FALSE);
3008 EDIT_MoveDownward(wndPtr, FALSE);
3009 } else
3010 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)"\r\n");
3012 break;
3013 case '\t':
3014 if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
3015 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)"\t");
3016 break;
3017 default:
3018 if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
3019 str[0] = c;
3020 str[1] = '\0';
3021 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)str);
3023 break;
3025 return 0;
3029 /*********************************************************************
3031 * WM_CLEAR
3034 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3036 EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)"");
3038 return -1;
3042 /*********************************************************************
3044 * WM_COMMAND
3047 static LRESULT EDIT_WM_Command(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3049 if (HIWORD(wParam))
3050 return 0;
3052 switch (LOWORD(wParam)) {
3053 case EM_UNDO32:
3054 EDIT_EM_Undo(wndPtr, 0, 0);
3055 break;
3056 case WM_CUT:
3057 EDIT_WM_Cut(wndPtr, 0, 0);
3058 break;
3059 case WM_COPY:
3060 EDIT_WM_Copy(wndPtr, 0, 0);
3061 break;
3062 case WM_PASTE:
3063 EDIT_WM_Paste(wndPtr, 0, 0);
3064 break;
3065 case WM_CLEAR:
3066 EDIT_WM_Clear(wndPtr, 0, 0);
3067 break;
3068 case EM_SETSEL32:
3069 EDIT_EM_SetSel(wndPtr, 0, -1);
3070 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3071 break;
3072 default:
3073 dprintf_edit(stddeb, "edit: unknown menu item, please report\n");
3074 break;
3076 return -1;
3080 /*********************************************************************
3082 * WM_CONTEXTMENU
3084 * Note: the resource files resource/sysres_??.rc cannot define a
3085 * single popup menu. Hence we use a (dummy) menubar
3086 * containing the single popup menu as its first item.
3089 static LRESULT EDIT_WM_ContextMenu(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3091 HMENU32 hMenu = LoadMenuIndirect32A(SYSRES_GetResPtr(SYSRES_MENU_EDITMENU));
3092 HMENU32 hPopup = GetSubMenu32(hMenu, 0);
3094 TrackPopupMenu32(hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, LOWORD(lParam),
3095 HIWORD(lParam), 0, wndPtr->hwndSelf, NULL);
3096 DestroyMenu32(hMenu);
3097 return 0;
3101 /*********************************************************************
3103 * WM_COPY
3106 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3108 INT32 s;
3109 INT32 e;
3110 HGLOBAL16 hdst;
3111 LPSTR text;
3112 LPSTR dst;
3114 EDIT_GetSel(wndPtr, &s, &e);
3115 if (e == s)
3116 return -1;
3117 ORDER_INT32(s, e);
3118 hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
3119 dst = GlobalLock16(hdst);
3120 text = EDIT_GetPointer(wndPtr);
3121 lstrcpyn32A(dst, text + s, e - s + 1);
3122 GlobalUnlock16(hdst);
3123 OpenClipboard32(wndPtr->hwndSelf);
3124 EmptyClipboard32();
3125 SetClipboardData16(CF_TEXT, hdst);
3126 CloseClipboard32();
3127 return -1;
3131 /*********************************************************************
3133 * WM_CREATE
3136 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3138 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
3139 EDITSTATE *es;
3140 LPSTR text;
3142 es = xmalloc(sizeof(EDITSTATE));
3143 memset(es, 0, sizeof(EDITSTATE));
3144 *(EDITSTATE **)wndPtr->wExtra = es;
3146 if (cs->style & WS_VSCROLL)
3147 cs->style |= ES_AUTOVSCROLL;
3148 if (cs->style & WS_HSCROLL)
3149 cs->style |= ES_AUTOHSCROLL;
3151 /* remove the WS_CAPTION style if it has been set - this is really a */
3152 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
3153 if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
3154 cs->style ^= WS_DLGFRAME;
3156 if (IsMultiLine(wndPtr)) {
3157 es->BufSize = BUFSTART_MULTI;
3158 es->BufLimit = BUFLIMIT_MULTI;
3159 es->PasswordChar = '\0';
3160 } else {
3161 es->BufSize = BUFSTART_SINGLE;
3162 es->BufLimit = BUFLIMIT_SINGLE;
3163 es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
3165 if (!(es->hBuf32 = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) {
3166 fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
3167 return -1;
3169 if (!(es->hUndoBuf = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) {
3170 fprintf(stderr, "edit: WM_CREATE: unable to allocate undo buffer\n");
3171 LocalFree32(es->hBuf32);
3172 es->hBuf32 = (HLOCAL32)NULL;
3173 return -1;
3175 es->BufSize = LocalSize32(es->hBuf32) - 1;
3176 es->UndoBufSize = LocalSize32(es->hUndoBuf) - 1;
3177 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
3178 text = EDIT_GetPointer(wndPtr);
3179 *text = '\0';
3180 EDIT_BuildLineDefs(wndPtr);
3181 EDIT_WM_SetFont(wndPtr, 0, 0);
3182 if (cs->lpszName && *(cs->lpszName) != '\0')
3183 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, (LPARAM)cs->lpszName);
3184 EDIT_WM_SetRedraw(wndPtr, TRUE, 0);
3185 return 0;
3189 /*********************************************************************
3191 * WM_CUT
3194 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3196 EDIT_WM_Copy(wndPtr, 0, 0);
3197 EDIT_WM_Clear(wndPtr, 0, 0);
3198 return -1;
3202 /*********************************************************************
3204 * WM_DESTROY
3207 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3209 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3211 free(es->LineDefs);
3212 if (es->TabStops)
3213 free(es->TabStops);
3214 EDIT_ReleaseUndoPointer(wndPtr);
3215 LocalFree32(es->hUndoBuf);
3216 EDIT_ReleasePointer(wndPtr);
3217 if (es->hBuf32)
3218 LocalFree32(es->hBuf32);
3219 else
3220 LOCAL_Free(wndPtr->hInstance, es->hBuf16);
3221 free(es);
3222 *(EDITSTATE **)&wndPtr->wExtra = NULL;
3223 return 0;
3227 /*********************************************************************
3229 * WM_ENABLE
3232 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3234 EDIT_InvalidateText(wndPtr, 0, -1);
3235 return 0;
3239 /*********************************************************************
3241 * WM_ERASEBKGND
3244 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3246 HBRUSH32 hBrush;
3247 RECT32 rc;
3249 hBrush = (HBRUSH32)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
3250 if (!hBrush) hBrush = (HBRUSH32)GetStockObject32(WHITE_BRUSH);
3252 GetClientRect32(wndPtr->hwndSelf, &rc);
3253 IntersectClipRect32((HDC32)wParam, rc.left, rc.top,
3254 rc.right, rc.bottom);
3255 GetClipBox32((HDC32)wParam, &rc);
3257 * FIXME: specs say that we should UnrealizeObject() the brush,
3258 * but the specs of UnrealizeObject() say that we shouldn't
3259 * unrealize a stock object. The default brush that
3260 * DefWndProc() returns is ... a stock object.
3262 FillRect32((HDC32)wParam, &rc, hBrush);
3263 return -1;
3267 /*********************************************************************
3269 * WM_GETDLGCODE
3272 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3274 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
3278 /*********************************************************************
3280 * WM_GETFONT
3283 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3285 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3287 return (LRESULT)es->hFont;
3291 /*********************************************************************
3293 * WM_GETTEXT
3296 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3298 LPSTR text = EDIT_GetPointer(wndPtr);
3299 INT32 len;
3300 LRESULT lResult = 0;
3302 len = lstrlen32A(text);
3303 if ((INT32)wParam > len) {
3304 lstrcpy32A((LPSTR)lParam, text);
3305 lResult = (LRESULT)len + 1;
3307 return lResult;
3311 /*********************************************************************
3313 * WM_GETTEXTLENGTH
3316 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3318 LPSTR text = EDIT_GetPointer(wndPtr);
3320 return (LRESULT)lstrlen32A(text);
3324 /*********************************************************************
3326 * WM_HSCROLL
3328 * FIXME: scrollbar code itself is broken, so this one is a hack.
3331 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3333 INT32 ww = EDIT_GetWndWidth(wndPtr);
3334 INT32 tw = EDIT_GetTextWidth(wndPtr);
3335 INT32 cw = EDIT_GetAveCharWidth(wndPtr);
3336 INT32 xoff = EDIT_GetXOffset(wndPtr);
3337 INT32 dx = 0;
3338 BOOL32 not = TRUE;
3339 LRESULT ret = 0;
3341 switch (wParam) {
3342 case SB_LINELEFT:
3343 dx = -cw;
3344 break;
3345 case SB_LINERIGHT:
3346 dx = cw;
3347 break;
3348 case SB_PAGELEFT:
3349 dx = -ww / HSCROLL_FRACTION / cw * cw;
3350 break;
3351 case SB_PAGERIGHT:
3352 dx = ww / HSCROLL_FRACTION / cw * cw;
3353 break;
3354 case SB_LEFT:
3355 dx = -xoff;
3356 break;
3357 case SB_RIGHT:
3358 dx = tw - xoff;
3359 break;
3360 case SB_THUMBTRACK:
3362 * not = FALSE;
3364 case SB_THUMBPOSITION:
3365 dx = HIWORD(wParam) * tw / 100 - xoff;
3366 break;
3367 /* The next two are undocumented ! */
3368 case EM_GETTHUMB16:
3369 ret = tw ? xoff * 100 / tw : 0;
3370 break;
3371 case EM_LINESCROLL16:
3372 dx = (INT16)HIWORD(wParam);
3373 break;
3374 case SB_ENDSCROLL:
3375 default:
3376 break;
3378 if (dx) {
3379 EDIT_EM_LineScroll(wndPtr, dx, 0);
3380 if (not) {
3381 dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
3382 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
3385 return ret;
3389 /*********************************************************************
3391 * WM_INITMENUPOPUP
3393 * FIXME: the message identifiers have been chosen arbitrarily,
3394 * hence we use MF_BYPOSITION.
3395 * We might as well use the "real" values (anybody knows ?)
3396 * The menu definition is in resources/sysres_??.rc.
3397 * Once these are OK, we better use MF_BYCOMMAND here
3398 * (as we do in EDIT_WM_Command()).
3401 static LRESULT EDIT_WM_InitMenuPopup(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3403 HMENU32 hPopup = (HMENU32)wParam;
3404 INT32 s;
3405 INT32 e;
3407 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
3409 /* undo */
3410 EnableMenuItem32(hPopup, 0, MF_BYPOSITION |
3411 (EDIT_EM_CanUndo(wndPtr, 0, 0) ? MF_ENABLED : MF_GRAYED));
3412 /* cut */
3413 EnableMenuItem32(hPopup, 2, MF_BYPOSITION |
3414 ((e - s) && !IsPassword(wndPtr) ? MF_ENABLED : MF_GRAYED));
3415 /* copy */
3416 EnableMenuItem32(hPopup, 3, MF_BYPOSITION |
3417 ((e - s) && !IsPassword(wndPtr) ? MF_ENABLED : MF_GRAYED));
3418 /* paste */
3419 EnableMenuItem32(hPopup, 4, MF_BYPOSITION |
3420 (IsClipboardFormatAvailable32(CF_TEXT) ? MF_ENABLED : MF_GRAYED));
3421 /* delete */
3422 EnableMenuItem32(hPopup, 5, MF_BYPOSITION |
3423 ((e - s) ? MF_ENABLED : MF_GRAYED));
3424 /* select all */
3425 EnableMenuItem32(hPopup, 7, MF_BYPOSITION |
3426 (s || (e != EDIT_WM_GetTextLength(wndPtr, 0, 0)) ? MF_ENABLED : MF_GRAYED));
3428 return 0;
3432 /*********************************************************************
3434 * WM_KEYDOWN
3436 * Handling of special keys that don't produce a WM_CHAR
3437 * (i.e. non-printable keys) & Backspace & Delete
3440 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3442 INT32 s;
3443 INT32 e;
3444 BOOL32 shift;
3445 BOOL32 control;
3447 if (GetKeyState32(VK_MENU) & 0x8000)
3448 return 0;
3450 shift = GetKeyState32(VK_SHIFT) & 0x8000;
3451 control = GetKeyState32(VK_CONTROL) & 0x8000;
3453 EDIT_GetSel(wndPtr, &s, &e);
3454 switch (wParam) {
3455 case VK_LEFT:
3456 case VK_UP:
3457 if (IsMultiLine(wndPtr) && (wParam == VK_UP))
3458 EDIT_MoveUpward(wndPtr, shift);
3459 else
3460 if (control)
3461 EDIT_MoveWordBackward(wndPtr, shift);
3462 else
3463 EDIT_MoveBackward(wndPtr, shift);
3464 break;
3465 case VK_RIGHT:
3466 case VK_DOWN:
3467 if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
3468 EDIT_MoveDownward(wndPtr, shift);
3469 else if (control)
3470 EDIT_MoveWordForward(wndPtr, shift);
3471 else
3472 EDIT_MoveForward(wndPtr, shift);
3473 break;
3474 case VK_HOME:
3475 EDIT_MoveHome(wndPtr, shift);
3476 break;
3477 case VK_END:
3478 EDIT_MoveEnd(wndPtr, shift);
3479 break;
3480 case VK_PRIOR:
3481 if (IsMultiLine(wndPtr))
3482 EDIT_MovePageUp(wndPtr, shift);
3483 break;
3484 case VK_NEXT:
3485 if (IsMultiLine(wndPtr))
3486 EDIT_MovePageDown(wndPtr, shift);
3487 break;
3488 case VK_BACK:
3489 if (!IsReadOnly(wndPtr) && !control)
3490 if (e != s)
3491 EDIT_WM_Clear(wndPtr, 0, 0);
3492 else
3493 EDIT_DelLeft(wndPtr);
3494 break;
3495 case VK_DELETE:
3496 if (!IsReadOnly(wndPtr) && !(shift && control))
3497 if (e != s) {
3498 if (shift)
3499 EDIT_WM_Cut(wndPtr, 0, 0);
3500 else
3501 EDIT_WM_Clear(wndPtr, 0, 0);
3502 } else {
3503 if (shift)
3504 EDIT_DelLeft(wndPtr);
3505 else if (control)
3506 EDIT_DelEnd(wndPtr);
3507 else
3508 EDIT_DelRight(wndPtr);
3510 break;
3511 case VK_INSERT:
3512 if (shift) {
3513 if (!IsReadOnly(wndPtr))
3514 EDIT_WM_Paste(wndPtr, 0, 0);
3515 } else if (control)
3516 EDIT_WM_Copy(wndPtr, 0, 0);
3517 break;
3519 return 0;
3523 /*********************************************************************
3525 * WM_KILLFOCUS
3528 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3530 INT32 s;
3531 INT32 e;
3533 DestroyCaret32();
3534 if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
3535 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
3536 EDIT_InvalidateText(wndPtr, s, e);
3538 dprintf_edit(stddeb, "edit: notification EN_KILLFOCUS sent\n");
3539 EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
3540 return 0;
3544 /*********************************************************************
3546 * WM_LBUTTONDBLCLK
3548 * The caret position has been set on the WM_LBUTTONDOWN message
3551 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3553 INT32 s;
3554 INT32 e;
3555 INT32 l;
3556 INT32 li;
3557 INT32 ll;
3558 LPSTR text = EDIT_GetPointer(wndPtr);
3560 EDIT_GetSel(wndPtr, NULL, &e);
3561 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
3562 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
3563 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
3564 s = li + EDIT_CallWordBreakProc (wndPtr, text + li, e - li, ll, WB_LEFT);
3565 e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
3566 EDIT_EM_SetSel(wndPtr, s, e);
3567 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3568 return 0;
3572 /*********************************************************************
3574 * WM_LBUTTONDOWN
3577 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3579 INT32 x = (INT32)(INT16)LOWORD(lParam);
3580 INT32 y = (INT32)(INT16)HIWORD(lParam);
3581 INT32 l = EDIT_LineFromWndY(wndPtr, y);
3582 INT32 c;
3583 INT32 s;
3584 INT32 e;
3585 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3586 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3587 INT32 li;
3589 SetFocus32(wndPtr->hwndSelf);
3590 SetCapture32(wndPtr->hwndSelf);
3591 l = MIN(fv + vlc - 1, MAX(fv, l));
3592 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
3593 c = EDIT_ColFromWndX(wndPtr, l, x);
3594 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
3595 e = li + c;
3596 if (GetKeyState32(VK_SHIFT) & 0x8000)
3597 EDIT_GetSel(wndPtr, &s, NULL);
3598 else
3599 s = e;
3600 EDIT_SetSel(wndPtr, s, e);
3601 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3602 SetTimer32(wndPtr->hwndSelf, 0, 100, NULL);
3603 return 0;
3607 /*********************************************************************
3609 * WM_LBUTTONUP
3612 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3614 if (GetCapture32() == wndPtr->hwndSelf) {
3615 KillTimer32(wndPtr->hwndSelf, 0);
3616 ReleaseCapture();
3618 return 0;
3622 /*********************************************************************
3624 * WM_MOUSEMOVE
3627 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3629 INT32 x;
3630 INT32 y;
3631 INT32 l;
3632 INT32 c;
3633 INT32 s;
3634 INT32 fv;
3635 INT32 vlc;
3636 INT32 li;
3638 if (GetCapture32() == wndPtr->hwndSelf) {
3639 x = (INT32)(INT16)LOWORD(lParam);
3640 y = (INT32)(INT16)HIWORD(lParam);
3641 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3642 vlc = EDIT_GetVisibleLineCount(wndPtr);
3643 l = EDIT_LineFromWndY(wndPtr, y);
3644 l = MIN(fv + vlc - 1, MAX(fv, l));
3645 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
3646 c = EDIT_ColFromWndX(wndPtr, l, x);
3647 EDIT_GetSel(wndPtr, &s, NULL);
3648 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
3649 EDIT_SetSel(wndPtr, s, li + c);
3652 * FIXME: gotta do some scrolling if outside client (format ?)
3653 * area. Maybe reset the timer ?
3655 return 0;
3659 /*********************************************************************
3661 * WM_PAINT
3664 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3666 PAINTSTRUCT32 ps;
3667 INT32 i;
3668 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3669 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3670 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
3671 HDC32 hdc;
3672 HFONT32 hFont;
3673 HFONT32 oldFont = 0;
3674 RECT32 rc;
3675 RECT32 rcLine;
3676 RECT32 rcRgn;
3677 LRESULT pos;
3678 INT32 e;
3679 BOOL32 rev = IsWindowEnabled32(wndPtr->hwndSelf) &&
3680 ((GetFocus32() == wndPtr->hwndSelf) ||
3681 (wndPtr->dwStyle & ES_NOHIDESEL));
3683 hdc = BeginPaint32(wndPtr->hwndSelf, &ps);
3684 GetClientRect32(wndPtr->hwndSelf, &rc);
3685 IntersectClipRect32( hdc, rc.left, rc.top, rc.right, rc.bottom );
3686 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
3687 if (hFont)
3688 oldFont = (HFONT32)SelectObject32(hdc, hFont);
3689 EDIT_SEND_CTLCOLOR(wndPtr, hdc);
3690 if (!IsWindowEnabled32(wndPtr->hwndSelf))
3691 SetTextColor32(hdc, GetSysColor32(COLOR_GRAYTEXT));
3692 GetClipBox32(hdc, &rcRgn);
3693 for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
3694 EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
3695 if (IntersectRect32(&rc, &rcRgn, &rcLine))
3696 EDIT_PaintLine(wndPtr, hdc, i, rev);
3698 if (hFont) SelectObject32(hdc, oldFont);
3699 if (wndPtr->hwndSelf == GetFocus32()) {
3700 EDIT_GetSel(wndPtr, NULL, &e);
3701 pos = EDIT_EM_PosFromChar(wndPtr, e, 0);
3702 SetCaretPos16( (INT16)LOWORD(pos), (INT16)HIWORD(pos) );
3704 EndPaint32(wndPtr->hwndSelf, &ps);
3705 return 0;
3709 /*********************************************************************
3711 * WM_PASTE
3714 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3716 HGLOBAL16 hsrc;
3717 LPSTR src;
3719 OpenClipboard32(wndPtr->hwndSelf);
3720 if ((hsrc = GetClipboardData16(CF_TEXT)))
3722 src = (LPSTR)GlobalLock16(hsrc);
3723 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)src);
3724 GlobalUnlock16(hsrc);
3726 CloseClipboard32();
3727 return -1;
3731 /*********************************************************************
3733 * WM_SETCURSOR
3736 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3738 if (LOWORD(lParam) == HTCLIENT) {
3739 SetCursor16(LoadCursor16(0, IDC_IBEAM));
3740 return -1;
3741 } else
3742 return 0;
3746 /*********************************************************************
3748 * WM_SETFOCUS
3751 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3753 INT32 s;
3754 INT32 e;
3756 EDIT_GetSel(wndPtr, &s, &e);
3757 CreateCaret32( wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr) );
3758 EDIT_SetSel(wndPtr, s, e);
3759 if(!(wndPtr->dwStyle & ES_NOHIDESEL))
3760 EDIT_InvalidateText(wndPtr, s, e);
3761 ShowCaret32(wndPtr->hwndSelf);
3762 dprintf_edit(stddeb, "edit: notification EN_SETFOCUS sent\n");
3763 EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
3764 return 0;
3768 /*********************************************************************
3770 * WM_SETFONT
3773 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3775 TEXTMETRIC32A tm;
3776 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3777 INT32 s;
3778 INT32 e;
3779 HDC32 hdc;
3780 HFONT32 oldFont = 0;
3782 EDIT_GetSel(wndPtr, &s, &e);
3783 es->hFont = (HFONT32)wParam;
3784 hdc = GetDC32(wndPtr->hwndSelf);
3785 if (es->hFont) oldFont = SelectObject32(hdc, es->hFont);
3786 GetTextMetrics32A(hdc, &tm);
3787 es->LineHeight = tm.tmHeight;
3788 es->AveCharWidth = tm.tmAveCharWidth;
3789 if (es->hFont) SelectObject32(hdc, oldFont);
3790 ReleaseDC32(wndPtr->hwndSelf, hdc);
3791 EDIT_BuildLineDefs(wndPtr);
3792 if ((BOOL32)lParam && EDIT_GetRedraw(wndPtr))
3793 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
3794 if (wndPtr->hwndSelf == GetFocus32()) {
3795 DestroyCaret32();
3796 CreateCaret32( wndPtr->hwndSelf, 0,
3797 2, EDIT_GetLineHeight(wndPtr) );
3798 EDIT_SetSel(wndPtr, s, e);
3799 ShowCaret32(wndPtr->hwndSelf);
3801 return 0;
3805 /*********************************************************************
3807 * WM_SETREDRAW
3810 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3812 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3814 es->Redraw = (BOOL32)wParam;
3815 return 0;
3819 /*********************************************************************
3821 * WM_SETTEXT
3824 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3826 EDIT_EM_SetSel(wndPtr, 0, -1);
3827 if (lParam)
3828 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, lParam);
3829 EDIT_EM_SetModify(wndPtr, TRUE, 0);
3830 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3831 return 1;
3835 /*********************************************************************
3837 * WM_SIZE
3839 * FIXME: What about that FormatRect ???
3842 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3844 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3845 INT32 e;
3847 EDIT_GetSel(wndPtr, 0, &e);
3848 GetClientRect32(wndPtr->hwndSelf, &es->FormatRect);
3849 if (EDIT_GetRedraw(wndPtr) &&
3850 ((wParam == SIZE_MAXIMIZED) ||
3851 (wParam == SIZE_RESTORED))) {
3852 if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
3853 EDIT_BuildLineDefs(wndPtr);
3854 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
3856 return 0;
3860 /*********************************************************************
3862 * WM_SYSKEYDOWN
3865 static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3867 if ((wParam == VK_BACK) && (lParam & 0x2000) &&
3868 (BOOL32)EDIT_EM_CanUndo(wndPtr, 0, 0))
3869 EDIT_EM_Undo(wndPtr, 0, 0);
3870 return 0;
3874 /*********************************************************************
3876 * WM_TIMER
3879 static LRESULT EDIT_WM_Timer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3882 * FIXME: gotta do some scrolling here, like
3883 * EDIT_EM_LineScroll(wndPtr, 0, 1);
3885 return 0;
3889 /*********************************************************************
3891 * WM_VSCROLL
3893 * FIXME: scrollbar code itself is broken, so this one is a hack.
3896 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3898 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
3899 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3900 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3901 INT32 dy = 0;
3902 BOOL32 not = TRUE;
3903 LRESULT ret = 0;
3905 switch (wParam) {
3906 case SB_LINEUP:
3907 dy = -1;
3908 break;
3909 case SB_LINEDOWN:
3910 dy = 1;
3911 break;
3912 case SB_PAGEUP:
3913 dy = -vlc;
3914 break;
3915 case SB_PAGEDOWN:
3916 dy = vlc;
3917 break;
3918 case SB_TOP:
3919 dy = -fv;
3920 break;
3921 case SB_BOTTOM:
3922 dy = lc - 1 - fv;
3923 break;
3924 case SB_THUMBTRACK:
3925 not = FALSE;
3926 /* fall through */
3927 case SB_THUMBPOSITION:
3928 dy = HIWORD(wParam) * (lc - 1) / 100 - fv;
3929 break;
3930 /* The next two are undocumented ! */
3931 case EM_GETTHUMB16:
3932 ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0;
3933 break;
3934 case EM_LINESCROLL16:
3935 dy = (INT16)LOWORD(lParam);
3936 break;
3937 case SB_ENDSCROLL:
3938 default:
3939 break;
3941 if (dy) {
3942 EDIT_EM_LineScroll(wndPtr, 0, dy);
3943 if (not) {
3944 dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
3945 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
3948 return ret;