Release 970202
[wine/multimedia.git] / controls / edit.c
blobb333222d022dfb8c61d5c74788f43444d0092d95
1 /*
2 * Edit control
4 * Copyright David W. Metcalfe, 1994
5 * Copyright William Magro, 1995, 1996
6 * Copyright Frans van Dorsselaer, 1996, 1997
8 */
11 * please read EDIT.TODO (and update it when you change things)
12 * It also contains a discussion about the 16 to 32 bit transition.
17 #define NO_TRANSITION_TYPES /* This file is Win32-clean */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "windows.h"
22 #include "win.h"
23 #include "local.h"
24 #include "resource.h"
25 #include "stddebug.h"
26 #include "debug.h"
27 #include "xmalloc.h"
29 #include "callback.h"
32 #define BUFLIMIT_MULTI 65534 /* maximum text buffer length (not including '\0') */
33 /* FIXME: BTW, new specs say 65535 (do you dare ???) */
34 #define BUFLIMIT_SINGLE 32766
35 #define BUFSTART_MULTI 1024 /* starting length for multi-line control */
36 #define BUFSTART_SINGLE 256 /* starting length for single line control */
37 #define GROWLENGTH 64 /* buffers grow by this much */
38 #define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */
40 typedef enum
42 END_0 = 0,
43 END_DELIMIT,
44 END_NONE,
45 END_HARD,
46 END_SOFT,
47 } LINE_END;
49 typedef struct {
50 INT32 offset;
51 INT32 length;
52 LINE_END ending;
53 } LINEDEF;
55 typedef struct
57 HLOCAL16 hBuf16; /* For when a 16-bit multiline edit
58 * control gets a EM_GETHANDLE (which
59 * should return 16-bit local heap).
60 * From that point on we _have_ to keep
61 * using 16-bit local heap (apps rely
62 * on that ... bummer).
64 HLOCAL32 hBuf32; /* Don't worry about 'LOCAL'. LOCAL32 is
65 * identical to GLOBAL32, which is
66 * essentially a HANDLE32 created with
67 * HeapAlloc(GetProcessHeap(), ...) plus
68 * a global32 (and thus local32)
69 * descriptor, which we can return upon
70 * EM_GETHANDLE32.
71 * It is 32-bit linear addressing, so
72 * everything is fine.
74 LPSTR text; /* Depending on the fact that we are a
75 * 16 or 32 bit control, this is the
76 * pointer that we get after
77 * LocalLock32(hBuf23) (which is a typecast :-)
78 * or LOCAL_Lock(hBuf16).
79 * This is always a 32-bit linear pointer.
81 HFONT32 hFont;
82 LINEDEF *LineDefs; /* Internal table for (soft) linebreaks */
83 INT32 TextWidth; /* width of the widest line in pixels */
84 INT32 XOffset; /* offset of the viewport in pixels */
85 INT32 FirstVisibleLine;
86 INT32 LineCount;
87 INT32 LineHeight; /* height of a screen line in pixels */
88 INT32 AveCharWidth; /* average character width in pixels */
89 INT32 BufLimit;
90 INT32 BufSize;
91 BOOL32 TextChanged;
92 INT32 UndoInsertLen;
93 INT32 UndoPos;
94 INT32 UndoBufSize;
95 HLOCAL32 hUndoBuf;
96 LPSTR UndoText;
97 BOOL32 Redraw;
98 INT32 SelStart; /* offset of selection start, == SelEnd if no selection */
99 INT32 SelEnd; /* offset of selection end == current caret position */
100 INT32 NumTabStops;
101 LPINT16 TabStops;
103 * FIXME: The following should probably be a (VOID *) that is
104 * typecast to either 16- or 32-bit callback when used,
105 * depending on the type of edit control (16 or 32 bit).
107 * EDITWORDBREAKPROC WordBreakProc;
109 * For now: no more application specific wordbreaking.
110 * (Internal wordbreak function still works)
112 CHAR PasswordChar;
113 INT32 LeftMargin;
114 INT32 RightMargin;
115 RECT32 FormatRect;
116 } EDITSTATE;
119 #define SWAP_INT32(x,y) do { INT32 temp = (INT32)(x); (x) = (INT32)(y); (y) = temp; } while(0)
120 #define ORDER_INT32(x,y) do { if ((INT32)(y) < (INT32)(x)) SWAP_INT32((x),(y)); } while(0)
122 /* macros to access window styles */
123 #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
124 #define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL)
125 #define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL)
126 #define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY)
127 #define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0)
128 #define IsPassword(wndPtr) ((wndPtr)->dwStyle & ES_PASSWORD)
129 #define IsLower(wndPtr) ((wndPtr)->dwStyle & ES_LOWERCASE)
130 #define IsUpper(wndPtr) ((wndPtr)->dwStyle & ES_UPPERCASE)
132 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
134 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
135 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
136 (WPARAM32)(hdc), (LPARAM)(wndPtr)->hwndSelf ))
137 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
138 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_COMMAND, \
139 MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
140 (LPARAM)(wndPtr)->hwndSelf ))
141 #define DPRINTF_EDIT_MSG16(str) \
142 dprintf_edit(stddeb, \
143 "edit: 16 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
144 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
145 #define DPRINTF_EDIT_MSG32(str) \
146 dprintf_edit(stddeb, \
147 "edit: 32 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
148 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
151 /*********************************************************************
153 * Declarations
155 * Files like these should really be kept in alphabetical order.
158 LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam);
160 static void EDIT_BuildLineDefs(WND *wndPtr);
161 static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action);
162 static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x);
163 static void EDIT_DelEnd(WND *wndPtr);
164 static void EDIT_DelLeft(WND *wndPtr);
165 static void EDIT_DelRight(WND *wndPtr);
166 static INT32 EDIT_GetAveCharWidth(WND *wndPtr);
167 static INT32 EDIT_GetLineHeight(WND *wndPtr);
168 static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc);
169 static LPSTR EDIT_GetPointer(WND *wndPtr);
170 static LPSTR EDIT_GetPasswordPointer(WND *wndPtr);
171 static BOOL32 EDIT_GetRedraw(WND *wndPtr);
172 static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e);
173 static INT32 EDIT_GetTextWidth(WND *wndPtr);
174 static LPSTR EDIT_GetUndoPointer(WND *wndPtr);
175 static INT32 EDIT_GetVisibleLineCount(WND *wndPtr);
176 static INT32 EDIT_GetWndWidth(WND *wndPtr);
177 static INT32 EDIT_GetXOffset(WND *wndPtr);
178 static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end);
179 static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y);
180 static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size);
181 static BOOL32 EDIT_MakeUndoFit(WND *wndPtr, INT32 size);
182 static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend);
183 static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend);
184 static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend);
185 static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend);
186 static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend);
187 static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend);
188 static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend);
189 static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend);
190 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend);
191 static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend);
192 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev);
193 static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev);
194 static void EDIT_ReleasePointer(WND *wndPtr);
195 static void EDIT_ReleaseUndoPointer(WND *wndPtr);
196 static void EDIT_SetSel(WND *wndPtr, INT32 ns, INT32 ne);
197 static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col);
198 static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line);
199 static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action);
201 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
202 static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
203 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
204 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
205 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
206 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
207 static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
208 static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
209 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
210 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
211 static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
212 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
213 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
214 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
215 static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
216 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
217 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
218 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
219 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
220 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
221 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
222 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
223 static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
224 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
225 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
226 static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
227 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
228 static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
229 static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
230 static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
231 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
232 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
233 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
234 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
235 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
236 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
237 static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
238 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
239 static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
240 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
241 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
243 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
244 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
245 static LRESULT EDIT_WM_Command(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
246 static LRESULT EDIT_WM_ContextMenu(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
247 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
248 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
249 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
250 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
251 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
252 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
253 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
254 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
255 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
256 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
257 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
258 static LRESULT EDIT_WM_InitMenuPopup(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
259 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
260 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
261 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
262 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
263 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
264 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
265 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
266 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
267 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
268 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
269 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
270 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
271 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
272 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
273 static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
274 static LRESULT EDIT_WM_Timer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
275 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
278 /*********************************************************************
280 * General shortcuts for variable names:
282 * INT32 l; line
283 * INT32 c; column
284 * INT32 s; offset of selection start
285 * INT32 e; offset of selection end
286 * INT32 sl; line on which the selection starts
287 * INT32 el; line on which the selection ends
288 * INT32 sc; column on which the selection starts
289 * INT32 ec; column on which the selection ends
290 * INT32 li; line index (offset)
291 * INT32 fv; first visible line
292 * INT32 vlc; vissible line count
293 * INT32 lc; line count
294 * INT32 lh; line height (in pixels)
295 * INT32 tw; text width (in pixels)
296 * INT32 ww; window width (in pixels)
297 * INT32 cw; character width (average, in pixels)
302 /*********************************************************************
304 * EditWndProc()
306 * The messages are in the order of the actual integer values
307 * (which can be found in include/windows.h)
308 * Whereever possible the 16 bit versions are converted to
309 * the 32 bit ones, so that we can 'fall through' to the
310 * helper functions. These are mostly 32 bit (with a few
311 * exceptions, clearly indicated by a '16' extension to their
312 * names).
315 LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
317 LRESULT lResult = 0;
318 WND *wndPtr = WIN_FindWndPtr(hwnd);
320 if ((!EDITSTATEPTR(wndPtr)) && (msg != WM_CREATE))
321 return DefWindowProc32A(hwnd, msg, wParam, lParam);
323 switch (msg) {
324 case EM_GETSEL16:
325 DPRINTF_EDIT_MSG16("EM_GETSEL");
326 wParam = 0;
327 lParam = 0;
328 /* fall through */
329 case EM_GETSEL32:
330 DPRINTF_EDIT_MSG32("EM_GETSEL");
331 lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
332 break;
334 case EM_SETSEL16:
335 DPRINTF_EDIT_MSG16("EM_SETSEL");
336 lResult = EDIT_EM_SetSel16(wndPtr, wParam, lParam);
337 break;
338 case EM_SETSEL32:
339 DPRINTF_EDIT_MSG32("EM_SETSEL");
340 lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
341 break;
343 case EM_GETRECT16:
344 DPRINTF_EDIT_MSG16("EM_GETRECT");
345 lResult = EDIT_EM_GetRect16(wndPtr, wParam, lParam);
346 break;
347 case EM_GETRECT32:
348 DPRINTF_EDIT_MSG32("EM_GETRECT");
349 lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
350 break;
352 case EM_SETRECT16:
353 DPRINTF_EDIT_MSG16("EM_SETRECT");
354 /* fall through */
355 case EM_SETRECT32:
356 DPRINTF_EDIT_MSG32("EM_SETRECT");
357 lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
358 break;
360 case EM_SETRECTNP16:
361 DPRINTF_EDIT_MSG16("EM_SETRECTNP");
362 /* fall through */
363 case EM_SETRECTNP32:
364 DPRINTF_EDIT_MSG32("EM_SETRECTNP");
365 lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
366 break;
368 case EM_SCROLL16:
369 DPRINTF_EDIT_MSG16("EM_SCROLL");
370 /* fall through */
371 case EM_SCROLL32:
372 DPRINTF_EDIT_MSG32("EM_SCROLL");
373 lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
374 break;
376 case EM_LINESCROLL16:
377 DPRINTF_EDIT_MSG16("EM_LINESCROLL");
378 wParam = (WPARAM32)(INT32)(INT16)HIWORD(lParam);
379 lParam = (LPARAM)(INT32)(INT16)LOWORD(lParam);
380 /* fall through */
381 case EM_LINESCROLL32:
382 DPRINTF_EDIT_MSG32("EM_LINESCROLL");
383 lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
384 break;
386 case EM_SCROLLCARET16:
387 DPRINTF_EDIT_MSG16("EM_SCROLLCARET");
388 /* fall through */
389 case EM_SCROLLCARET32:
390 DPRINTF_EDIT_MSG32("EM_SCROLLCARET");
391 lResult = EDIT_EM_ScrollCaret(wndPtr, wParam, lParam);
392 break;
394 case EM_GETMODIFY16:
395 DPRINTF_EDIT_MSG16("EM_GETMODIFY");
396 /* fall through */
397 case EM_GETMODIFY32:
398 DPRINTF_EDIT_MSG32("EM_GETMODIFY");
399 lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
400 break;
402 case EM_SETMODIFY16:
403 DPRINTF_EDIT_MSG16("EM_SETMODIFY");
404 /* fall through */
405 case EM_SETMODIFY32:
406 DPRINTF_EDIT_MSG32("EM_SETMODIFY");
407 lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
408 break;
410 case EM_GETLINECOUNT16:
411 DPRINTF_EDIT_MSG16("EM_GETLINECOUNT");
412 /* fall through */
413 case EM_GETLINECOUNT32:
414 DPRINTF_EDIT_MSG32("EM_GETLINECOUNT");
415 lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
416 break;
418 case EM_LINEINDEX16:
419 DPRINTF_EDIT_MSG16("EM_LINEINDEX");
420 /* fall through */
421 case EM_LINEINDEX32:
422 DPRINTF_EDIT_MSG32("EM_LINEINDEX");
423 lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
424 break;
426 case EM_SETHANDLE16:
427 DPRINTF_EDIT_MSG16("EM_SETHANDLE");
428 lResult = EDIT_EM_SetHandle16(wndPtr, wParam, lParam);
429 break;
430 case EM_SETHANDLE32:
431 DPRINTF_EDIT_MSG32("EM_SETHANDLE");
432 lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
433 break;
435 case EM_GETHANDLE16:
436 DPRINTF_EDIT_MSG16("EM_GETHANDLE");
437 lResult = EDIT_EM_GetHandle16(wndPtr, wParam, lParam);
438 break;
439 case EM_GETHANDLE32:
440 DPRINTF_EDIT_MSG32("EM_GETHANDLE");
441 lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
442 break;
444 case EM_GETTHUMB16:
445 DPRINTF_EDIT_MSG16("EM_GETTHUMB");
446 /* fall through */
447 case EM_GETTHUMB32:
448 DPRINTF_EDIT_MSG32("EM_GETTHUMB");
449 lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
450 break;
452 /* messages 0x00bf and 0x00c0 missing from specs */
454 case WM_USER+15:
455 DPRINTF_EDIT_MSG16("undocumented WM_USER+15, please report");
456 /* fall through */
457 case 0x00bf:
458 DPRINTF_EDIT_MSG32("undocumented 0x00bf, please report");
459 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
460 break;
462 case WM_USER+16:
463 DPRINTF_EDIT_MSG16("undocumented WM_USER+16, please report");
464 /* fall through */
465 case 0x00c0:
466 DPRINTF_EDIT_MSG32("undocumented 0x00c0, please report");
467 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
468 break;
470 case EM_LINELENGTH16:
471 DPRINTF_EDIT_MSG16("EM_LINELENGTH");
472 /* fall through */
473 case EM_LINELENGTH32:
474 DPRINTF_EDIT_MSG32("EM_LINELENGTH");
475 lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
476 break;
478 case EM_REPLACESEL16:
479 DPRINTF_EDIT_MSG16("EM_REPLACESEL");
480 lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
481 /* fall through */
482 case EM_REPLACESEL32:
483 DPRINTF_EDIT_MSG32("EM_REPLACESEL");
484 lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
485 break;
487 /* message 0x00c3 missing from specs */
489 case WM_USER+19:
490 DPRINTF_EDIT_MSG16("undocumented WM_USER+19, please report");
491 /* fall through */
492 case 0x00c3:
493 DPRINTF_EDIT_MSG32("undocumented 0x00c3, please report");
494 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
495 break;
497 case EM_GETLINE16:
498 DPRINTF_EDIT_MSG16("EM_GETLINE");
499 lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
500 /* fall through */
501 case EM_GETLINE32:
502 DPRINTF_EDIT_MSG32("EM_GETLINE");
503 lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
504 break;
506 case EM_LIMITTEXT16:
507 DPRINTF_EDIT_MSG16("EM_LIMITTEXT");
508 /* fall through */
509 case EM_SETLIMITTEXT32:
510 DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT");
511 lResult = EDIT_EM_SetLimitText(wndPtr, wParam, lParam);
512 break;
514 case EM_CANUNDO16:
515 DPRINTF_EDIT_MSG16("EM_CANUNDO");
516 /* fall through */
517 case EM_CANUNDO32:
518 DPRINTF_EDIT_MSG32("EM_CANUNDO");
519 lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
520 break;
522 case EM_UNDO16:
523 DPRINTF_EDIT_MSG16("EM_UNDO");
524 /* fall through */
525 case EM_UNDO32:
526 /* fall through */
527 case WM_UNDO:
528 DPRINTF_EDIT_MSG32("EM_UNDO / WM_UNDO");
529 lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
530 break;
532 case EM_FMTLINES16:
533 DPRINTF_EDIT_MSG16("EM_FMTLINES");
534 /* fall through */
535 case EM_FMTLINES32:
536 DPRINTF_EDIT_MSG32("EM_FMTLINES");
537 lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
538 break;
540 case EM_LINEFROMCHAR16:
541 DPRINTF_EDIT_MSG16("EM_LINEFROMCHAR");
542 /* fall through */
543 case EM_LINEFROMCHAR32:
544 DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR");
545 lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
546 break;
548 /* message 0x00ca missing from specs */
550 case WM_USER+26:
551 DPRINTF_EDIT_MSG16("undocumented WM_USER+26, please report");
552 /* fall through */
553 case 0x00ca:
554 DPRINTF_EDIT_MSG32("undocumented 0x00ca, please report");
555 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
556 break;
558 case EM_SETTABSTOPS16:
559 DPRINTF_EDIT_MSG16("EM_SETTABSTOPS");
560 lResult = EDIT_EM_SetTabStops16(wndPtr, wParam, lParam);
561 break;
562 case EM_SETTABSTOPS32:
563 DPRINTF_EDIT_MSG32("EM_SETTABSTOPS");
564 lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
565 break;
567 case EM_SETPASSWORDCHAR16:
568 DPRINTF_EDIT_MSG16("EM_SETPASSWORDCHAR");
569 /* fall through */
570 case EM_SETPASSWORDCHAR32:
571 DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR");
572 lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
573 break;
575 case EM_EMPTYUNDOBUFFER16:
576 DPRINTF_EDIT_MSG16("EM_EMPTYUNDOBUFFER");
577 /* fall through */
578 case EM_EMPTYUNDOBUFFER32:
579 DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER");
580 lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
581 break;
583 case EM_GETFIRSTVISIBLELINE16:
584 DPRINTF_EDIT_MSG16("EM_GETFIRSTVISIBLELINE");
585 /* fall through */
586 case EM_GETFIRSTVISIBLELINE32:
587 DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE");
588 lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
589 break;
591 case EM_SETREADONLY16:
592 DPRINTF_EDIT_MSG16("EM_SETREADONLY");
593 /* fall through */
594 case EM_SETREADONLY32:
595 DPRINTF_EDIT_MSG32("EM_SETREADONLY");
596 lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
597 break;
599 case EM_SETWORDBREAKPROC16:
600 DPRINTF_EDIT_MSG16("EM_SETWORDBREAKPROC");
601 /* fall through */
602 case EM_SETWORDBREAKPROC32:
603 DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC");
604 lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
605 break;
607 case EM_GETWORDBREAKPROC16:
608 DPRINTF_EDIT_MSG16("EM_GETWORDBREAKPROC");
609 /* fall through */
610 case EM_GETWORDBREAKPROC32:
611 DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC");
612 lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
613 break;
615 case EM_GETPASSWORDCHAR16:
616 DPRINTF_EDIT_MSG16("EM_GETPASSWORDCHAR");
617 /* fall through */
618 case EM_GETPASSWORDCHAR32:
619 DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR");
620 lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
621 break;
623 /* The following EM_xxx are new to win95 and don't exist for 16 bit */
625 case EM_SETMARGINS32:
626 DPRINTF_EDIT_MSG16("EM_SETMARGINS");
627 lResult = EDIT_EM_SetMargins(wndPtr, wParam, lParam);
628 break;
630 case EM_GETMARGINS32:
631 DPRINTF_EDIT_MSG16("EM_GETMARGINS");
632 lResult = EDIT_EM_GetMargins(wndPtr, wParam, lParam);
633 break;
635 case EM_GETLIMITTEXT32:
636 DPRINTF_EDIT_MSG16("EM_GETLIMITTEXT");
637 lResult = EDIT_EM_GetLimitText(wndPtr, wParam, lParam);
638 break;
640 case EM_POSFROMCHAR32:
641 DPRINTF_EDIT_MSG16("EM_POSFROMCHAR");
642 lResult = EDIT_EM_PosFromChar(wndPtr, wParam, lParam);
643 break;
645 case EM_CHARFROMPOS32:
646 DPRINTF_EDIT_MSG16("EM_CHARFROMPOS");
647 lResult = EDIT_EM_CharFromPos(wndPtr, wParam, lParam);
648 break;
650 case WM_GETDLGCODE:
651 DPRINTF_EDIT_MSG32("WM_GETDLGCODE");
652 lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
653 break;
655 case WM_CHAR:
656 DPRINTF_EDIT_MSG32("WM_CHAR");
657 lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
658 break;
660 case WM_CLEAR:
661 DPRINTF_EDIT_MSG32("WM_CLEAR");
662 lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
663 break;
665 case WM_COMMAND:
666 DPRINTF_EDIT_MSG32("WM_COMMAND");
667 lResult = EDIT_WM_Command(wndPtr, wParam, lParam);
668 break;
671 * FIXME: when this one is added to WINE, change RBUTTONUP to CONTEXTMENU
672 * Furthermore, coordinate conversion should no longer be required
674 * case WM_CONTEXTMENU:
676 case WM_RBUTTONUP:
677 DPRINTF_EDIT_MSG32("WM_RBUTTONUP");
678 ClientToScreen16(wndPtr->hwndSelf, (LPPOINT16)&lParam);
679 lResult = EDIT_WM_ContextMenu(wndPtr, wParam, lParam);
680 break;
682 case WM_COPY:
683 DPRINTF_EDIT_MSG32("WM_COPY");
684 lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
685 break;
687 case WM_CREATE:
688 DPRINTF_EDIT_MSG32("WM_CREATE");
689 lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
690 break;
692 case WM_CUT:
693 DPRINTF_EDIT_MSG32("WM_CUT");
694 lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
695 break;
697 case WM_DESTROY:
698 DPRINTF_EDIT_MSG32("WM_DESTROY");
699 lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
700 break;
702 case WM_ENABLE:
703 DPRINTF_EDIT_MSG32("WM_ENABLE");
704 lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
705 break;
707 case WM_ERASEBKGND:
708 DPRINTF_EDIT_MSG32("WM_ERASEBKGND");
709 lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
710 break;
712 case WM_GETFONT:
713 DPRINTF_EDIT_MSG32("WM_GETFONT");
714 lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
715 break;
717 case WM_GETTEXT:
718 DPRINTF_EDIT_MSG32("WM_GETTEXT");
719 lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
720 break;
722 case WM_GETTEXTLENGTH:
723 DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH");
724 lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
725 break;
727 case WM_HSCROLL:
728 DPRINTF_EDIT_MSG32("WM_HSCROLL");
729 lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
730 break;
732 case WM_INITMENUPOPUP:
733 DPRINTF_EDIT_MSG32("WM_INITMENUPOPUP");
734 lResult = EDIT_WM_InitMenuPopup(wndPtr, wParam, lParam);
735 break;
737 case WM_KEYDOWN:
738 DPRINTF_EDIT_MSG32("WM_KEYDOWN");
739 lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
740 break;
742 case WM_KILLFOCUS:
743 DPRINTF_EDIT_MSG32("WM_KILLFOCUS");
744 lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
745 break;
747 case WM_LBUTTONDBLCLK:
748 DPRINTF_EDIT_MSG32("WM_LBUTTONDBLCLK");
749 lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
750 break;
752 case WM_LBUTTONDOWN:
753 DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN");
754 lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
755 break;
757 case WM_LBUTTONUP:
758 DPRINTF_EDIT_MSG32("WM_LBUTTONUP");
759 lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
760 break;
762 case WM_MOUSEMOVE:
764 * DPRINTF_EDIT_MSG32("WM_MOUSEMOVE");
766 lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
767 break;
769 case WM_PAINT:
770 DPRINTF_EDIT_MSG32("WM_PAINT");
771 lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
772 break;
774 case WM_PASTE:
775 DPRINTF_EDIT_MSG32("WM_PASTE");
776 lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
777 break;
779 case WM_SETCURSOR:
781 * DPRINTF_EDIT_MSG32("WM_SETCURSOR");
783 lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
784 break;
786 case WM_SETFOCUS:
787 DPRINTF_EDIT_MSG32("WM_SETFOCUS");
788 lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
789 break;
791 case WM_SETFONT:
792 DPRINTF_EDIT_MSG32("WM_SETFONT");
793 lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
794 break;
796 case WM_SETREDRAW:
797 DPRINTF_EDIT_MSG32("WM_SETREDRAW");
798 lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
799 break;
801 case WM_SETTEXT:
802 DPRINTF_EDIT_MSG32("WM_SETTEXT");
803 lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
804 break;
806 case WM_SIZE:
807 DPRINTF_EDIT_MSG32("WM_SIZE");
808 lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
809 break;
811 case WM_SYSKEYDOWN:
812 DPRINTF_EDIT_MSG32("WM_SYSKEYDOWN");
813 lResult = EDIT_WM_SysKeyDown(wndPtr, wParam, lParam);
814 break;
816 case WM_TIMER:
817 DPRINTF_EDIT_MSG32("WM_TIMER");
818 lResult = EDIT_WM_Timer(wndPtr, wParam, lParam);
819 break;
821 case WM_VSCROLL:
822 DPRINTF_EDIT_MSG32("WM_VSCROLL");
823 lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
824 break;
826 default:
827 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
828 break;
830 EDIT_ReleasePointer(wndPtr);
831 return lResult;
835 /*********************************************************************
837 * EDIT_BuildLineDefs
839 * Build array of pointers to text lines.
840 * Lines can end with '\0' (last line), nothing (if it is too long),
841 * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
844 static void EDIT_BuildLineDefs(WND *wndPtr)
846 EDITSTATE *es = EDITSTATEPTR(wndPtr);
847 LPSTR text = EDIT_GetPasswordPointer(wndPtr);
848 INT32 ww = EDIT_GetWndWidth(wndPtr);
849 HDC32 hdc;
850 HFONT32 hFont;
851 HFONT32 oldFont = 0;
852 LPSTR start, cp;
853 INT32 prev, next;
854 INT32 width;
855 INT32 length;
856 LINE_END ending;
858 hdc = GetDC32(wndPtr->hwndSelf);
859 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
860 if (hFont) oldFont = SelectObject32(hdc, hFont);
862 if (!IsMultiLine(wndPtr)) {
863 es->LineCount = 1;
864 es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
865 es->LineDefs[0].offset = 0;
866 es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0);
867 es->LineDefs[0].ending = END_0;
868 es->TextWidth = (INT32)LOWORD(GetTabbedTextExtent(hdc, text,
869 es->LineDefs[0].length,
870 es->NumTabStops, es->TabStops));
871 } else {
872 es->LineCount = 0;
873 start = text;
874 do {
875 if (!(cp = strstr(start, "\r\n"))) {
876 ending = END_0;
877 length = lstrlen32A(start);
878 } else if ((cp > start) && (*(cp - 1) == '\r')) {
879 ending = END_SOFT;
880 length = cp - start - 1;
881 } else {
882 ending = END_HARD;
883 length = cp - start;
885 width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, length,
886 es->NumTabStops, es->TabStops));
888 if (IsWordWrap(wndPtr) && (width > ww)) {
889 next = 0;
890 do {
891 prev = next;
892 next = EDIT_CallWordBreakProc(wndPtr, start,
893 prev + 1, length, WB_RIGHT);
894 width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, next,
895 es->NumTabStops, es->TabStops));
896 } while (width <= ww);
897 if (!prev) {
898 next = 0;
899 do {
900 prev = next;
901 next++;
902 width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, next,
903 es->NumTabStops, es->TabStops));
904 } while (width <= ww);
905 if(!prev) prev = 1;
907 length = prev;
908 if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
909 length, WB_ISDELIMITER)) {
910 length--;
911 ending = END_DELIMIT;
912 } else
913 ending = END_NONE;
914 width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, length,
915 es->NumTabStops, es->TabStops));
918 es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF));
919 es->LineDefs[es->LineCount].offset = start - text;
920 es->LineDefs[es->LineCount].length = length;
921 es->LineDefs[es->LineCount].ending = ending;
922 es->LineCount++;
923 es->TextWidth = MAX(es->TextWidth, width);
925 start += length;
926 switch (ending) {
927 case END_SOFT:
928 start += 3;
929 break;
930 case END_HARD:
931 start += 2;
932 break;
933 case END_DELIMIT:
934 start++;
935 break;
936 default:
937 break;
939 } while (*start || (ending == END_SOFT) || (ending == END_HARD));
941 if (hFont) SelectObject32(hdc, oldFont);
942 ReleaseDC32(wndPtr->hwndSelf, hdc);
944 free(text);
948 /*********************************************************************
950 * EDIT_CallWordBreakProc
952 * Call appropriate WordBreakProc (internal or external).
954 * FIXME: Heavily broken now that we have a LOCAL32 buffer.
955 * External wordbreak functions have been disabled in
956 * EM_SETWORDBREAKPROC.
959 static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action)
961 return EDIT_WordBreakProc(s, index, count, action);
963 * EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0);
965 * if (!wbp) return EDIT_WordBreakProc(s, index, count, action);
966 * else {
967 * EDITSTATE *es = EDITSTATEPTR(wndPtr);
968 * SEGPTR ptr = LOCAL_LockSegptr( wndPtr->hInstance, es->hBuf16 ) +
969 * (INT16)(s - EDIT_GetPointer(wndPtr));
970 * INT ret = CallWordBreakProc( (FARPROC16)wbp, ptr,
971 * index, count, action);
972 * LOCAL_Unlock( wndPtr->hInstance, es->hBuf16 );
973 * return ret;
979 /*********************************************************************
981 * EDIT_ColFromWndX
983 * Calculates, for a given line and X-coordinate on the screen, the column.
986 static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x)
988 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
989 INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
990 INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
991 INT32 i;
993 line = MAX(0, MIN(line, lc - 1));
994 for (i = 0 ; i < ll ; i++)
995 if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
996 break;
997 return i;
1001 /*********************************************************************
1003 * EDIT_DelEnd
1005 * Delete all characters on this line to right of cursor.
1008 static void EDIT_DelEnd(WND *wndPtr)
1010 EDIT_EM_SetSel(wndPtr, -1, 0);
1011 EDIT_MoveEnd(wndPtr, TRUE);
1012 EDIT_WM_Clear(wndPtr, 0, 0);
1016 /*********************************************************************
1018 * EDIT_DelLeft
1020 * Delete character to left of cursor.
1023 static void EDIT_DelLeft(WND *wndPtr)
1025 EDIT_EM_SetSel(wndPtr, -1, 0);
1026 EDIT_MoveBackward(wndPtr, TRUE);
1027 EDIT_WM_Clear(wndPtr, 0, 0);
1031 /*********************************************************************
1033 * EDIT_DelRight
1035 * Delete character to right of cursor.
1038 static void EDIT_DelRight(WND *wndPtr)
1040 EDIT_EM_SetSel(wndPtr, -1, 0);
1041 EDIT_MoveForward(wndPtr, TRUE);
1042 EDIT_WM_Clear(wndPtr, 0, 0);
1046 /*********************************************************************
1048 * EDIT_GetAveCharWidth
1051 static INT32 EDIT_GetAveCharWidth(WND *wndPtr)
1053 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1055 return es->AveCharWidth;
1059 /*********************************************************************
1061 * EDIT_GetLineHeight
1064 static INT32 EDIT_GetLineHeight(WND *wndPtr)
1066 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1068 return es->LineHeight;
1072 /*********************************************************************
1074 * EDIT_GetLineRect
1076 * Calculates the bounding rectangle for a line from a starting
1077 * column to an ending column.
1080 static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc)
1082 rc->top = EDIT_WndYFromLine(wndPtr, line);
1083 rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
1084 rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
1085 rc->right = (ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
1086 EDIT_WndXFromCol(wndPtr, line, ecol);
1090 /*********************************************************************
1092 * EDIT_GetPointer
1094 * This acts as a LOCAL_Lock(), but it locks only once. This way
1095 * you can call it whenever you like, without unlocking.
1098 static LPSTR EDIT_GetPointer(WND *wndPtr)
1100 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1102 if (!es->text && (es->hBuf32 || es->hBuf16)) {
1103 if (es->hBuf32)
1104 es->text = (LPSTR)LocalLock32(es->hBuf32);
1105 else
1106 es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf16);
1108 return es->text;
1112 /*********************************************************************
1114 * EDIT_GetPasswordPointer
1118 static LPSTR EDIT_GetPasswordPointer(WND *wndPtr)
1120 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1121 LPSTR text = xstrdup(EDIT_GetPointer(wndPtr));
1122 LPSTR p;
1124 if(es->PasswordChar) {
1125 p = text;
1126 while(*p != '\0') {
1127 if(*p != '\r' && *p != '\n')
1128 *p = es->PasswordChar;
1129 p++;
1132 return text;
1136 /*********************************************************************
1138 * EDIT_GetRedraw
1141 static BOOL32 EDIT_GetRedraw(WND *wndPtr)
1143 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1145 return es->Redraw;
1149 /*********************************************************************
1151 * EDIT_GetSel
1153 * Beware: This is not the function called on EM_GETSEL.
1154 * This is the unordered version used internally
1155 * (s can be > e). No return value either.
1158 static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e)
1160 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1162 if (s)
1163 *s = es->SelStart;
1164 if (e)
1165 *e = es->SelEnd;
1169 /*********************************************************************
1171 * EDIT_GetTextWidth
1174 static INT32 EDIT_GetTextWidth(WND *wndPtr)
1176 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1178 return es->TextWidth;
1182 /*********************************************************************
1184 * EDIT_GetUndoPointer
1186 * This acts as a LocalLock32(), but it locks only once. This way
1187 * you can call it whenever you like, without unlocking.
1190 static LPSTR EDIT_GetUndoPointer(WND *wndPtr)
1192 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1194 if (!es->UndoText && es->hUndoBuf)
1195 es->UndoText = (LPSTR)LocalLock32(es->hUndoBuf);
1196 return es->UndoText;
1200 /*********************************************************************
1202 * EDIT_GetVisibleLineCount
1205 static INT32 EDIT_GetVisibleLineCount(WND *wndPtr)
1207 RECT32 rc;
1209 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
1210 return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
1214 /*********************************************************************
1216 * EDIT_GetWndWidth
1219 static INT32 EDIT_GetWndWidth(WND *wndPtr)
1221 RECT32 rc;
1223 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
1224 return rc.right - rc.left;
1228 /*********************************************************************
1230 * EDIT_GetXOffset
1233 static INT32 EDIT_GetXOffset(WND *wndPtr)
1235 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1237 return es->XOffset;
1241 /*********************************************************************
1243 * EDIT_InvalidateText
1245 * Invalidate the text from offset start upto, but not including,
1246 * offset end. Useful for (re)painting the selection.
1247 * Regions outside the linewidth are not invalidated.
1248 * end == -1 means end == TextLength.
1249 * start and end need not be ordered.
1252 static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end)
1254 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1255 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
1256 INT32 sl;
1257 INT32 el;
1258 INT32 sc;
1259 INT32 ec;
1260 RECT32 rcWnd;
1261 RECT32 rcLine;
1262 RECT32 rcUpdate;
1263 INT32 l;
1265 if (end == start)
1266 return;
1268 if (end == -1)
1269 end = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
1270 ORDER_INT32(start, end);
1271 sl = (INT32)EDIT_EM_LineFromChar(wndPtr, start, 0);
1272 el = (INT32)EDIT_EM_LineFromChar(wndPtr, end, 0);
1273 if ((el < fv) || (sl > fv + vlc))
1274 return;
1276 sc = start - (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0);
1277 ec = end - (INT32)EDIT_EM_LineIndex(wndPtr, el, 0);
1278 if (sl < fv) {
1279 sl = fv;
1280 sc = 0;
1282 if (el > fv + vlc) {
1283 el = fv + vlc;
1284 ec = (INT32)EDIT_EM_LineLength(wndPtr,
1285 (INT32)EDIT_EM_LineIndex(wndPtr, el, 0), 0);
1287 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
1288 if (sl == el) {
1289 EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
1290 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1291 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1292 } else {
1293 EDIT_GetLineRect(wndPtr, sl, sc,
1294 (INT32)EDIT_EM_LineLength(wndPtr,
1295 (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0), 0),
1296 &rcLine);
1297 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1298 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1299 for (l = sl + 1 ; l < el ; l++) {
1300 EDIT_GetLineRect(wndPtr, l, 0,
1301 (INT32)EDIT_EM_LineLength(wndPtr,
1302 (INT32)EDIT_EM_LineIndex(wndPtr, l, 0), 0),
1303 &rcLine);
1304 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1305 InvalidateRect32(wndPtr->hwndSelf, &rcUpdate, FALSE);
1307 EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
1308 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1309 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1314 /*********************************************************************
1316 * EDIT_LineFromWndY
1318 * Calculates, for a given Y-coordinate on the screen, the line.
1321 static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y)
1323 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1324 INT32 lh = EDIT_GetLineHeight(wndPtr);
1325 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
1327 return MAX(0, MIN(lc - 1, y / lh + fv));
1331 /*********************************************************************
1333 * EDIT_MakeFit
1335 * Try to fit size + 1 bytes in the buffer. Constrain to limits.
1338 static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size)
1340 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1341 HLOCAL32 hNew32;
1342 HLOCAL16 hNew16;
1344 if (size <= es->BufSize)
1345 return TRUE;
1346 if (size > es->BufLimit) {
1347 dprintf_edit(stddeb, "edit: notification EN_MAXTEXT sent\n");
1348 EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
1349 return FALSE;
1351 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
1352 if (size > es->BufLimit)
1353 size = es->BufLimit;
1355 dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
1357 EDIT_ReleasePointer(wndPtr);
1358 if (es->hBuf32) {
1359 if ((hNew32 = LocalReAlloc32(es->hBuf32, size + 1, 0))) {
1360 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 32 bit handle %08x, new handle %08x\n", es->hBuf32, hNew32);
1361 es->hBuf32 = hNew32;
1362 es->BufSize = MIN(LocalSize32(es->hBuf32) - 1, es->BufLimit);
1363 if (es->BufSize < size) {
1364 dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize);
1365 dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n");
1366 EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE);
1367 return FALSE;
1369 dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
1370 return TRUE;
1372 } else {
1373 if ((hNew16 = LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf16, size + 1, LMEM_MOVEABLE))) {
1374 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 16 bit handle %08x, new handle %08x\n", es->hBuf16, hNew16);
1375 es->hBuf16 = hNew16;
1376 es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1, es->BufLimit);
1377 if (es->BufSize < size) {
1378 dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize);
1379 dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n");
1380 EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE);
1381 return FALSE;
1383 dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
1384 return TRUE;
1387 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Reallocation failed\n");
1388 dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n");
1389 EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE);
1390 return FALSE;
1394 /*********************************************************************
1396 * EDIT_MakeUndoFit
1398 * Try to fit size + 1 bytes in the undo buffer.
1401 static BOOL32 EDIT_MakeUndoFit(WND *wndPtr, INT32 size)
1403 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1404 HLOCAL32 hNew;
1406 if (size <= es->UndoBufSize)
1407 return TRUE;
1408 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
1410 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: trying to ReAlloc to %d+1\n", size);
1412 EDIT_ReleaseUndoPointer(wndPtr);
1413 if ((hNew = LocalReAlloc32(es->hUndoBuf, size + 1, 0))) {
1414 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: Old handle %08x, new handle %08x\n", es->hUndoBuf, hNew);
1415 es->hUndoBuf = hNew;
1416 es->UndoBufSize = LocalSize32(es->hUndoBuf) - 1;
1417 if (es->UndoBufSize < size) {
1418 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: FAILED ! We now have %d+1\n", es->UndoBufSize);
1419 return FALSE;
1421 dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: We now have %d+1\n", es->UndoBufSize);
1422 return TRUE;
1424 return FALSE;
1428 /*********************************************************************
1430 * EDIT_MoveBackward
1433 static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend)
1435 INT32 s;
1436 INT32 e;
1437 INT32 l;
1438 INT32 li;
1440 EDIT_GetSel(wndPtr, &s, &e);
1441 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1442 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1443 if (e - li == 0) {
1444 if (l) {
1445 li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
1446 e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1448 } else
1449 e--;
1450 if (!extend)
1451 s = e;
1452 EDIT_SetSel(wndPtr, s, e);
1453 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1457 /*********************************************************************
1459 * EDIT_MoveDownward
1462 static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend)
1464 INT32 s;
1465 INT32 e;
1466 INT32 l;
1467 INT32 lc;
1468 INT32 li;
1469 INT32 x;
1471 EDIT_GetSel(wndPtr, &s, &e);
1472 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1473 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1474 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1475 if (l < lc - 1) {
1476 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1477 l++;
1478 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1479 EDIT_ColFromWndX(wndPtr, l, x);
1481 if (!extend)
1482 s = e;
1483 EDIT_SetSel(wndPtr, s, e);
1484 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1488 /*********************************************************************
1490 * EDIT_MoveEnd
1493 static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend)
1495 INT32 s;
1496 INT32 e;
1497 INT32 l;
1498 INT32 ll;
1499 INT32 li;
1501 EDIT_GetSel(wndPtr, &s, &e);
1502 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1503 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1504 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1505 e = li + ll;
1506 if (!extend)
1507 s = e;
1508 EDIT_SetSel(wndPtr, s, e);
1509 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1513 /*********************************************************************
1515 * EDIT_MoveForward
1518 static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend)
1520 INT32 s;
1521 INT32 e;
1522 INT32 l;
1523 INT32 lc;
1524 INT32 ll;
1525 INT32 li;
1527 EDIT_GetSel(wndPtr, &s, &e);
1528 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1529 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1530 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1531 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1532 if (e - li == ll) {
1533 if (l != lc - 1)
1534 e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
1535 } else
1536 e++;
1537 if (!extend)
1538 s = e;
1539 EDIT_SetSel(wndPtr, s, e);
1540 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1544 /*********************************************************************
1546 * EDIT_MoveHome
1548 * Home key: move to beginning of line.
1551 static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend)
1553 INT32 s;
1554 INT32 e;
1555 INT32 l;
1556 INT32 li;
1558 EDIT_GetSel(wndPtr, &s, &e);
1559 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1560 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1561 e = li;
1562 if (!extend)
1563 s = e;
1564 EDIT_SetSel(wndPtr, s, e);
1565 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1569 /*********************************************************************
1571 * EDIT_MovePageDown
1574 static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend)
1576 INT32 s;
1577 INT32 e;
1578 INT32 l;
1579 INT32 lc;
1580 INT32 li;
1581 INT32 x;
1583 EDIT_GetSel(wndPtr, &s, &e);
1584 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1585 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1586 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1587 if (l < lc - 1) {
1588 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1589 l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
1590 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1591 EDIT_ColFromWndX(wndPtr, l, x);
1593 if (!extend)
1594 s = e;
1595 EDIT_SetSel(wndPtr, s, e);
1596 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1600 /*********************************************************************
1602 * EDIT_MovePageUp
1605 static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend)
1607 INT32 s;
1608 INT32 e;
1609 INT32 l;
1610 INT32 li;
1611 INT32 x;
1613 EDIT_GetSel(wndPtr, &s, &e);
1614 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1615 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1616 if (l) {
1617 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1618 l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
1619 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1620 EDIT_ColFromWndX(wndPtr, l, x);
1622 if (!extend)
1623 s = e;
1624 EDIT_SetSel(wndPtr, s, e);
1625 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1629 /*********************************************************************
1631 * EDIT_MoveUpward
1634 static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend)
1636 INT32 s;
1637 INT32 e;
1638 INT32 l;
1639 INT32 li;
1640 INT32 x;
1642 EDIT_GetSel(wndPtr, &s, &e);
1643 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1644 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1645 if (l) {
1646 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1647 l--;
1648 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1649 EDIT_ColFromWndX(wndPtr, l, x);
1651 if (!extend)
1652 s = e;
1653 EDIT_SetSel(wndPtr, s, e);
1654 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1658 /*********************************************************************
1660 * EDIT_MoveWordBackward
1663 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend)
1665 INT32 s;
1666 INT32 e;
1667 INT32 l;
1668 INT32 ll;
1669 INT32 li;
1670 LPSTR text;
1672 EDIT_GetSel(wndPtr, &s, &e);
1673 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1674 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1675 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1676 if (e - li == 0) {
1677 if (l) {
1678 li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
1679 e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1681 } else {
1682 text = EDIT_GetPointer(wndPtr);
1683 e = li + (INT32)EDIT_CallWordBreakProc(wndPtr,
1684 text + li, e - li, ll, WB_LEFT);
1686 if (!extend)
1687 s = e;
1688 EDIT_SetSel(wndPtr, s, e);
1689 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1693 /*********************************************************************
1695 * EDIT_MoveWordForward
1698 static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend)
1700 INT32 s;
1701 INT32 e;
1702 INT32 l;
1703 INT32 lc;
1704 INT32 ll;
1705 INT32 li;
1706 LPSTR text;
1708 EDIT_GetSel(wndPtr, &s, &e);
1709 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1710 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1711 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1712 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1713 if (e - li == ll) {
1714 if (l != lc - 1)
1715 e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
1716 } else {
1717 text = EDIT_GetPointer(wndPtr);
1718 e = li + EDIT_CallWordBreakProc(wndPtr,
1719 text + li, e - li + 1, ll, WB_RIGHT);
1721 if (!extend)
1722 s = e;
1723 EDIT_SetSel(wndPtr, s, e);
1724 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1728 /*********************************************************************
1730 * EDIT_PaintLine
1733 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev)
1735 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1736 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
1737 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
1738 INT32 li;
1739 INT32 ll;
1740 INT32 s;
1741 INT32 e;
1742 INT32 x;
1743 INT32 y;
1745 if ((line < fv) || (line > fv + vlc) || (line >= lc))
1746 return;
1748 dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
1750 x = EDIT_WndXFromCol(wndPtr, line, 0);
1751 y = EDIT_WndYFromLine(wndPtr, line);
1752 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
1753 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1754 EDIT_GetSel(wndPtr, &s, &e);
1755 ORDER_INT32(s, e);
1756 s = MIN(li + ll, MAX(li, s));
1757 e = MIN(li + ll, MAX(li, e));
1758 if (rev && (s != e) &&
1759 ((GetFocus32() == wndPtr->hwndSelf) ||
1760 (wndPtr->dwStyle & ES_NOHIDESEL))) {
1761 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
1762 x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
1763 x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
1764 } else
1765 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
1769 /*********************************************************************
1771 * EDIT_PaintText
1774 static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev)
1776 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1777 COLORREF BkColor;
1778 COLORREF TextColor;
1779 INT32 ret;
1780 LPSTR text;
1781 INT32 li;
1782 INT32 xoff;
1784 if (!count)
1785 return 0;
1786 BkColor = GetBkColor32(hdc);
1787 TextColor = GetTextColor32(hdc);
1788 if (rev) {
1789 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1790 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1792 text = EDIT_GetPasswordPointer(wndPtr);
1793 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
1794 xoff = EDIT_GetXOffset(wndPtr);
1795 ret = (INT32)LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
1796 es->NumTabStops, es->TabStops, -xoff));
1797 free(text);
1798 if (rev) {
1799 SetBkColor(hdc, BkColor);
1800 SetTextColor(hdc, TextColor);
1802 return ret;
1806 /*********************************************************************
1808 * EDIT_ReleasePointer
1810 * This is the only helper function that can be called with es = NULL.
1811 * It is called at the end of EditWndProc() to unlock the buffer.
1814 static void EDIT_ReleasePointer(WND *wndPtr)
1816 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1818 if (!es)
1819 return;
1820 if (es->text && (es->hBuf32 || es->hBuf16)) {
1821 if (es->hBuf32)
1822 LocalUnlock32(es->hBuf32);
1823 else
1824 LOCAL_Unlock(wndPtr->hInstance, es->hBuf16);
1826 es->text = NULL;
1830 /*********************************************************************
1832 * EDIT_ReleaseUndoPointer
1834 * This is the only helper function that can be called with es = NULL.
1835 * It is called at the end of EditWndProc() to unlock the buffer.
1838 static void EDIT_ReleaseUndoPointer(WND *wndPtr)
1840 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1842 if (!es)
1843 return;
1844 if (es->UndoText && es->hUndoBuf)
1845 LocalUnlock32(es->hUndoBuf);
1846 es->UndoText = NULL;
1850 /*********************************************************************
1852 * EDIT_SetSel
1854 * Beware: This is not the function called on EM_SETSEL.
1855 * This is the unordered version used internally
1856 * (s can be > e). Doesn't accept -1 parameters either.
1857 * No range checking.
1860 static void EDIT_SetSel(WND *wndPtr, INT32 ns, INT32 ne)
1862 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1863 LRESULT pos;
1864 INT32 s;
1865 INT32 e;
1867 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
1868 es->SelStart = ns;
1869 es->SelEnd = ne;
1870 if (EDIT_GetRedraw(wndPtr)) {
1871 if (wndPtr->hwndSelf == GetFocus32()) {
1872 pos = EDIT_EM_PosFromChar(wndPtr, ne, 0);
1873 SetCaretPos((INT16)LOWORD(pos), (INT16)HIWORD(pos));
1875 ORDER_INT32(s, ns);
1876 ORDER_INT32(s, ne);
1877 ORDER_INT32(e, ns);
1878 ORDER_INT32(e, ne);
1879 ORDER_INT32(ns, ne);
1880 if (e != ns) {
1881 EDIT_InvalidateText(wndPtr, s, e);
1882 EDIT_InvalidateText(wndPtr, ns, ne);
1883 } else
1884 EDIT_InvalidateText(wndPtr, s, ne);
1889 /*********************************************************************
1891 * EDIT_WndXFromCol
1893 * Calculates, for a given line and column, the X-coordinate on the screen.
1896 static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col)
1898 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1899 LPSTR text = EDIT_GetPasswordPointer(wndPtr);
1900 INT32 ret;
1901 HDC32 hdc;
1902 HFONT32 hFont;
1903 HFONT32 oldFont = 0;
1904 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
1905 INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
1906 INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1907 INT32 xoff = EDIT_GetXOffset(wndPtr);
1909 hdc = GetDC32(wndPtr->hwndSelf);
1910 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
1911 if (hFont) oldFont = SelectObject32(hdc, hFont);
1912 line = MAX(0, MIN(line, lc - 1));
1913 col = MIN(col, ll);
1914 ret = (INT32)LOWORD(GetTabbedTextExtent(hdc,
1915 text + li, col,
1916 es->NumTabStops, es->TabStops)) - xoff;
1917 if (hFont) SelectObject32(hdc, oldFont);
1918 ReleaseDC32(wndPtr->hwndSelf, hdc);
1919 free(text);
1920 return ret;
1924 /*********************************************************************
1926 * EDIT_WndYFromLine
1928 * Calculates, for a given line, the Y-coordinate on the screen.
1931 static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line)
1933 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1934 INT32 lh = EDIT_GetLineHeight(wndPtr);
1936 return (line - fv) * lh;
1940 /*********************************************************************
1942 * EDIT_WordBreakProc
1944 * Find the beginning of words.
1945 * Note: unlike the specs for a WordBreakProc, this function only
1946 * allows to be called without linebreaks between s[0] upto
1947 * s[count - 1]. Remember it is only called
1948 * internally, so we can decide this for ourselves.
1951 static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action)
1953 INT32 ret = 0;
1955 dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%u"
1956 ", count=%u, action=%d\n", s, index, count, action);
1958 switch (action) {
1959 case WB_LEFT:
1960 if (!count)
1961 break;
1962 if (index)
1963 index--;
1964 if (s[index] == ' ') {
1965 while (index && (s[index] == ' '))
1966 index--;
1967 if (index) {
1968 while (index && (s[index] != ' '))
1969 index--;
1970 if (s[index] == ' ')
1971 index++;
1973 } else {
1974 while (index && (s[index] != ' '))
1975 index--;
1976 if (s[index] == ' ')
1977 index++;
1979 ret = index;
1980 break;
1981 case WB_RIGHT:
1982 if (!count)
1983 break;
1984 if (index)
1985 index--;
1986 if (s[index] == ' ')
1987 while ((index < count) && (s[index] == ' ')) index++;
1988 else {
1989 while (s[index] && (s[index] != ' ') && (index < count))
1990 index++;
1991 while ((s[index] == ' ') && (index < count)) index++;
1993 ret = index;
1994 break;
1995 case WB_ISDELIMITER:
1996 ret = (s[index] == ' ');
1997 break;
1998 default:
1999 fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
2000 break;
2002 return ret;
2006 /*********************************************************************
2008 * EM_CANUNDO
2011 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2013 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2015 return (LRESULT)(es->UndoInsertLen || lstrlen32A(EDIT_GetUndoPointer(wndPtr)));
2019 /*********************************************************************
2021 * EM_CHARFROMPOS
2023 * FIXME: do the specs mean LineIndex or LineNumber (li v.s. l) ???
2025 static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2027 POINT32 pt;
2028 RECT32 rc;
2029 INT32 l;
2030 INT32 li;
2031 INT32 c;
2033 pt.x = LOWORD(lParam);
2034 pt.y = HIWORD(lParam);
2035 GetClientRect32(wndPtr->hwndSelf, &rc);
2037 if (!PtInRect32(&rc, pt))
2038 return -1;
2040 l = EDIT_LineFromWndY(wndPtr, pt.y);
2041 li = EDIT_EM_LineIndex(wndPtr, l, 0);
2042 c = EDIT_ColFromWndX(wndPtr, l, pt.x);
2044 return (LRESULT)MAKELONG(li + c, li);
2048 /*********************************************************************
2050 * EM_EMPTYUNDOBUFFER
2053 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2055 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2057 es->UndoInsertLen = 0;
2058 *EDIT_GetUndoPointer(wndPtr) = '\0';
2059 return 0;
2063 /*********************************************************************
2065 * EM_FMTLINES
2068 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2070 fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented\n");
2071 return wParam ? TRUE : FALSE;
2075 /*********************************************************************
2077 * EM_GETFIRSTVISIBLELINE
2080 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2082 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2084 if (IsMultiLine(wndPtr))
2085 return (LRESULT)es->FirstVisibleLine;
2086 else
2087 return (LRESULT)EDIT_ColFromWndX(wndPtr, 0, 0);
2091 /*********************************************************************
2093 * EM_GETHANDLE
2096 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2098 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2100 if (!IsMultiLine(wndPtr))
2101 return 0;
2103 if (es->hBuf32)
2104 return (LRESULT)es->hBuf32;
2105 else
2106 return (LRESULT)es->hBuf16;
2110 /*********************************************************************
2112 * EM_GETHANDLE16
2114 * Hopefully this won't fire back at us.
2115 * We always start with a buffer in 32 bit linear memory.
2116 * However, with this message a 16 bit application requests
2117 * a handle of 16 bit local heap memory, where it expects to find
2118 * the text.
2119 * It's a pitty that from this moment on we have to use this
2120 * local heap, because applications may rely on the handle
2121 * in the future.
2123 * In this function we'll try to switch to local heap.
2125 static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2127 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2128 LPSTR text;
2129 HLOCAL16 newBuf;
2130 LPSTR newText;
2131 INT16 newSize;
2133 if (!IsMultiLine(wndPtr))
2134 return 0;
2136 if (es->hBuf16)
2137 return (LRESULT)es->hBuf16;
2139 if (!LOCAL_HeapSize(wndPtr->hInstance)) {
2140 if (!LocalInit(wndPtr->hInstance, 0,
2141 GlobalSize16(wndPtr->hInstance))) {
2142 fprintf(stderr, "edit: EM_GETHANDLE: could not initialize local heap\n");
2143 return 0;
2145 dprintf_edit(stddeb, "edit: EM_GETHANDLE: local heap initialized\n");
2147 if (!(newBuf = LOCAL_Alloc(wndPtr->hInstance,
2148 EDIT_WM_GetTextLength(wndPtr, 0, 0) + 1,
2149 LMEM_MOVEABLE))) {
2150 fprintf(stderr, "edit: EM_GETHANDLE: could not allocate new 16 bit buffer\n");
2151 return 0;
2153 newSize = MIN(LOCAL_Size(wndPtr->hInstance, newBuf) - 1, es->BufLimit);
2154 if (!(newText = LOCAL_Lock(wndPtr->hInstance, newBuf))) {
2155 fprintf(stderr, "edit: EM_GETHANDLE: could not lock new 16 bit buffer\n");
2156 LOCAL_Free(wndPtr->hInstance, newBuf);
2157 return 0;
2159 text = EDIT_GetPointer(wndPtr);
2160 lstrcpy32A(newText, text);
2161 EDIT_ReleasePointer(wndPtr);
2162 GlobalFree32(es->hBuf32);
2163 es->hBuf32 = (HLOCAL32)NULL;
2164 es->hBuf16 = newBuf;
2165 es->BufSize = newSize;
2166 es->text = newText;
2167 dprintf_edit(stddeb, "edit: EM_GETHANDLE: switched to 16 bit buffer\n");
2169 return (LRESULT)es->hBuf16;
2173 /*********************************************************************
2175 * EM_GETLIMITTEXT
2178 static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2180 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2182 return es->BufLimit;
2186 /*********************************************************************
2188 * EM_GETLINE
2191 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2193 LPSTR text;
2194 LPSTR src;
2195 LPSTR dst;
2196 INT32 len;
2197 INT32 i;
2198 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
2200 if (!IsMultiLine(wndPtr))
2201 wParam = 0;
2202 if ((INT32)wParam >= lc)
2203 return 0;
2204 text = EDIT_GetPointer(wndPtr);
2205 src = text + (INT32)EDIT_EM_LineIndex(wndPtr, wParam, 0);
2206 dst = (LPSTR)lParam;
2207 len = MIN(*(WORD *)dst, (INT32)EDIT_EM_LineLength(wndPtr, wParam, 0));
2208 for (i = 0 ; i < len ; i++) {
2209 *dst = *src;
2210 src++;
2211 dst++;
2213 return (LRESULT)len;
2217 /*********************************************************************
2219 * EM_GETLINECOUNT
2222 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2224 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2226 return (LRESULT)es->LineCount;
2230 /*********************************************************************
2232 * EM_GETMARGINS
2235 static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2237 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2239 return (LRESULT)MAKELONG(es->LeftMargin, es->RightMargin);
2243 /*********************************************************************
2245 * EM_GETMODIFY
2248 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2250 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2252 return (LRESULT)es->TextChanged;
2256 /*********************************************************************
2258 * EM_GETPASSWORDCHAR
2261 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2263 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2265 return (LRESULT)es->PasswordChar;
2269 /*********************************************************************
2271 * EM_GETRECT
2274 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2276 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2278 CopyRect32((LPRECT32)lParam, &es->FormatRect);
2279 return 0;
2283 /*********************************************************************
2285 * EM_GETRECT16
2288 static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2290 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2292 CONV_RECT32TO16(&es->FormatRect, (LPRECT16)PTR_SEG_TO_LIN((SEGPTR)lParam));
2293 return 0;
2297 /*********************************************************************
2299 * EM_GETSEL
2301 * Returns the ordered selection range so that
2302 * LOWORD(result) < HIWORD(result)
2305 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2307 INT32 s;
2308 INT32 e;
2310 EDIT_GetSel(wndPtr, &s, &e);
2311 ORDER_INT32(s, e);
2312 if (wParam)
2313 *(LPINT32)wParam = s;
2314 if (lParam)
2315 *(LPINT32)lParam = e;
2316 return MAKELONG((INT16)s, (INT16)e);
2320 /*********************************************************************
2322 * EM_GETTHUMB
2324 * FIXME: is this right ? (or should it be only HSCROLL)
2325 * (and maybe only for edit controls that really have their
2326 * own scrollbars) (and maybe only for multiline controls ?)
2327 * All in all: very poorly documented
2330 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2332 return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0),
2333 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0));
2337 /*********************************************************************
2339 * EM_GETWORDBREAKPROC
2341 * FIXME: Application defined WordBreakProc should be returned
2344 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2347 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2349 return (LRESULT)es->WordBreakProc;
2351 return 0;
2355 /*********************************************************************
2357 * EM_LINEFROMCHAR
2360 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2362 INT32 l;
2364 if (!IsMultiLine(wndPtr))
2365 return 0;
2366 if ((INT32)wParam == -1)
2367 EDIT_EM_GetSel(wndPtr, (WPARAM32)&wParam, 0); /* intentional (looks weird, doesn't it ?) */
2368 l = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0) - 1;
2369 while ((INT32)EDIT_EM_LineIndex(wndPtr, l, 0) > (INT32)wParam)
2370 l--;
2371 return (LRESULT)l;
2375 /*********************************************************************
2377 * EM_LINEINDEX
2380 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2382 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2383 INT32 e;
2384 INT32 l;
2385 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
2387 if ((INT32)wParam == -1) {
2388 EDIT_GetSel(wndPtr, NULL, &e);
2389 l = lc - 1;
2390 while (es->LineDefs[l].offset > e)
2391 l--;
2392 return (LRESULT)es->LineDefs[l].offset;
2394 if ((INT32)wParam >= lc)
2395 return -1;
2396 return (LRESULT)es->LineDefs[(INT32)wParam].offset;
2400 /*********************************************************************
2402 * EM_LINELENGTH
2405 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2407 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2408 INT32 s;
2409 INT32 e;
2410 INT32 sl;
2411 INT32 el;
2413 if (!IsMultiLine(wndPtr))
2414 return (LRESULT)es->LineDefs[0].length;
2415 if ((INT32)wParam == -1) {
2416 EDIT_GetSel(wndPtr, &s, &e);
2417 sl = (INT32)EDIT_EM_LineFromChar(wndPtr, s, 0);
2418 el = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
2419 return (LRESULT)(s - es->LineDefs[sl].offset +
2420 es->LineDefs[el].offset +
2421 es->LineDefs[el].length - e);
2423 return (LRESULT)es->LineDefs[(INT32)EDIT_EM_LineFromChar(wndPtr, wParam, 0)].length;
2427 /*********************************************************************
2429 * EM_LINESCROLL
2431 * FIXME: is wParam in pixels or in average character widths ???
2432 * FIXME: we use this internally to scroll single line controls as well
2433 * (specs are vague about whether this message is valid or not for
2434 * single line controls)
2437 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2439 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2440 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
2441 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
2442 INT32 nfv = MAX(0, fv + (INT32)lParam);
2443 INT32 xoff = EDIT_GetXOffset(wndPtr);
2444 INT32 nxoff = MAX(0, xoff + (INT32)wParam);
2445 INT32 tw = EDIT_GetTextWidth(wndPtr);
2446 INT32 dx;
2447 INT32 dy;
2449 if (nfv >= lc)
2450 nfv = lc - 1;
2452 if (nxoff >= tw)
2453 nxoff = tw;
2454 dx = xoff - nxoff;
2455 dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
2456 if (dx || dy) {
2457 if (EDIT_GetRedraw(wndPtr))
2458 ScrollWindow32(wndPtr->hwndSelf, dx, dy, NULL, NULL);
2459 es->FirstVisibleLine = nfv;
2460 es->XOffset = nxoff;
2461 if (IsVScrollBar(wndPtr))
2462 SetScrollPos32(wndPtr->hwndSelf, SB_VERT,
2463 EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
2464 if (IsHScrollBar(wndPtr))
2465 SetScrollPos32(wndPtr->hwndSelf, SB_HORZ,
2466 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
2468 if (IsMultiLine(wndPtr))
2469 return TRUE;
2470 else
2471 return FALSE;
2475 /*********************************************************************
2477 * EM_POSFROMCHAR
2480 static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2482 INT32 len = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
2483 INT32 l;
2484 INT32 li;
2486 wParam = MIN(wParam, len);
2487 l = EDIT_EM_LineFromChar(wndPtr, wParam, 0);
2488 li = EDIT_EM_LineIndex(wndPtr, l, 0);
2489 return (LRESULT)MAKELONG(EDIT_WndXFromCol(wndPtr, l, wParam - li),
2490 EDIT_WndYFromLine(wndPtr, l));
2494 /*********************************************************************
2496 * EM_REPLACESEL
2499 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2501 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2502 LPCSTR str = (LPCSTR)lParam;
2503 INT32 strl = lstrlen32A(str);
2504 INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
2505 INT32 utl;
2506 INT32 s;
2507 INT32 e;
2508 INT32 i;
2509 LPSTR p;
2510 LPSTR text;
2511 LPSTR utext;
2512 BOOL32 redraw;
2514 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
2516 if ((s == e) && !strl)
2517 return 0;
2519 if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl))
2520 return 0;
2522 text = EDIT_GetPointer(wndPtr);
2523 utext = EDIT_GetUndoPointer(wndPtr);
2524 if (e != s) {
2525 /* there is something to be deleted */
2526 if ((BOOL32)wParam) {
2527 /* we have to be able to undo */
2528 utl = lstrlen32A(utext);
2529 if (!es->UndoInsertLen && (*utext && (s == es->UndoPos))) {
2530 /* undo-buffer is extended to the right */
2531 EDIT_MakeUndoFit(wndPtr, utl + e - s);
2532 lstrcpyn32A(utext + utl, text + s, e - s + 1);
2533 } else if (!es->UndoInsertLen && (*utext && (e == es->UndoPos))) {
2534 /* undo-buffer is extended to the left */
2535 EDIT_MakeUndoFit(wndPtr, utl + e - s);
2536 for (p = utext + utl ; p >= utext ; p--)
2537 p[e - s] = p[0];
2538 for (i = 0 , p = utext ; i < e - s ; i++)
2539 p[i] = (text + s)[i];
2540 es->UndoPos = s;
2541 } else {
2542 /* new undo-buffer */
2543 EDIT_MakeUndoFit(wndPtr, e - s);
2544 lstrcpyn32A(utext, text + s, e - s + 1);
2545 es->UndoPos = s;
2547 /* any deletion makes the old insertion-undo invalid */
2548 es->UndoInsertLen = 0;
2549 } else
2550 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2552 /* now delete */
2553 lstrcpy32A(text + s, text + e);
2555 if (strl) {
2556 /* there is an insertion */
2557 if ((BOOL32)wParam) {
2558 /* we have to be able to undo */
2559 if ((s == es->UndoPos) ||
2560 ((es->UndoInsertLen) &&
2561 (s == es->UndoPos + es->UndoInsertLen)))
2563 * insertion is new and at delete position or
2564 * an extension to either left or right
2566 es->UndoInsertLen += strl;
2567 else {
2568 /* new insertion undo */
2569 es->UndoPos = s;
2570 es->UndoInsertLen = strl;
2571 /* new insertion makes old delete-buffer invalid */
2572 *utext = '\0';
2574 } else
2575 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2577 /* now insert */
2578 tl = lstrlen32A(text);
2579 for (p = text + tl ; p >= text + s ; p--)
2580 p[strl] = p[0];
2581 for (i = 0 , p = text + s ; i < strl ; i++)
2582 p[i] = str[i];
2583 if(IsUpper(wndPtr))
2584 CharUpperBuff32A(p, strl);
2585 else if(IsLower(wndPtr))
2586 CharLowerBuff32A(p, strl);
2587 s += strl;
2589 redraw = EDIT_GetRedraw(wndPtr);
2590 EDIT_WM_SetRedraw(wndPtr, FALSE, 0);
2591 EDIT_BuildLineDefs(wndPtr);
2592 EDIT_EM_SetSel(wndPtr, s, s);
2593 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2594 EDIT_EM_SetModify(wndPtr, TRUE, 0);
2595 dprintf_edit(stddeb, "edit: notification EN_UPDATE sent\n");
2596 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2597 EDIT_WM_SetRedraw(wndPtr, redraw, 0);
2598 if (redraw) {
2599 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2600 dprintf_edit(stddeb, "edit: notification EN_CHANGE sent\n");
2601 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2603 return 0;
2607 /*********************************************************************
2609 * EM_SCROLL
2611 * FIXME: Scroll what ??? And where ???
2614 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2616 fprintf(stdnimp, "edit: EM_SCROLL: message not implemented\n");
2617 return 0;
2621 /*********************************************************************
2623 * EM_SCROLLCARET
2625 * Makes sure the caret is visible.
2626 * FIXME: We use EM_LINESCROLL, but may we do that for single line
2627 * controls ???
2630 static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2632 INT32 e;
2633 INT32 l;
2634 INT32 li;
2635 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
2636 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
2637 INT32 ww = EDIT_GetWndWidth(wndPtr);
2638 INT32 cw = EDIT_GetAveCharWidth(wndPtr);
2639 INT32 x;
2640 INT32 dy = 0;
2641 INT32 dx = 0;
2643 EDIT_GetSel(wndPtr, NULL, &e);
2644 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
2645 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
2646 x = EDIT_WndXFromCol(wndPtr, l, e - li);
2647 if (l >= fv + vlc)
2648 dy = l - vlc + 1 - fv;
2649 if (l < fv)
2650 dy = l - fv;
2651 if (x < 0)
2652 dx = x - ww / HSCROLL_FRACTION / cw * cw;
2653 if (x > ww)
2654 dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
2655 if (dy || dx) {
2656 EDIT_EM_LineScroll(wndPtr, dx, dy);
2657 if (dy) {
2658 dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
2659 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
2661 if (dx) {
2662 dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
2663 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
2666 return TRUE;
2670 /*********************************************************************
2672 * EM_SETHANDLE
2675 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2677 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2679 if (IsMultiLine(wndPtr)) {
2680 EDIT_ReleasePointer(wndPtr);
2682 * old buffer is freed by caller
2684 es->hBuf16 = (HLOCAL16)NULL;
2685 es->hBuf32 = (HLOCAL32)wParam;
2686 es->BufSize = LocalSize32(es->hBuf32) - 1;
2687 es->LineCount = 0;
2688 es->FirstVisibleLine = 0;
2689 es->SelStart = es->SelEnd = 0;
2690 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2691 EDIT_EM_SetModify(wndPtr, FALSE, 0);
2692 EDIT_BuildLineDefs(wndPtr);
2693 if (EDIT_GetRedraw(wndPtr))
2694 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2695 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2697 return 0;
2701 /*********************************************************************
2703 * EM_SETHANDLE16
2706 static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2708 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2710 if (IsMultiLine(wndPtr)) {
2711 EDIT_ReleasePointer(wndPtr);
2713 * old buffer is freed by caller
2715 es->hBuf16 = (HLOCAL16)wParam;
2716 es->hBuf32 = (HLOCAL32)NULL;
2717 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1;
2718 es->LineCount = 0;
2719 es->FirstVisibleLine = 0;
2720 es->SelStart = es->SelEnd = 0;
2721 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2722 EDIT_EM_SetModify(wndPtr, FALSE, 0);
2723 EDIT_BuildLineDefs(wndPtr);
2724 if (EDIT_GetRedraw(wndPtr))
2725 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2726 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2728 return 0;
2732 /*********************************************************************
2734 * EM_SETLIMITTEXT
2736 * FIXME: in WinNT maxsize is 0x7FFFFFFF / 0xFFFFFFFF
2737 * However, the windows version is not complied to yet in all of edit.c
2740 static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2742 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2744 if (IsMultiLine(wndPtr)) {
2745 if (wParam)
2746 es->BufLimit = MIN((INT32)wParam, BUFLIMIT_MULTI);
2747 else
2748 es->BufLimit = BUFLIMIT_MULTI;
2749 } else {
2750 if (wParam)
2751 es->BufLimit = MIN((INT32)wParam, BUFLIMIT_SINGLE);
2752 else
2753 es->BufLimit = BUFLIMIT_SINGLE;
2755 return 0;
2759 /*********************************************************************
2761 * EM_SETMARGINS
2763 * FIXME: We let the margins be set, but we don't use them yet !?!
2766 static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2768 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2770 if (wParam & EC_USEFONTINFO) {
2771 if (IsMultiLine(wndPtr)) {
2773 * FIXME: do some GetABCCharWidth, or so
2774 * This is just preliminary
2776 es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
2777 } else
2778 es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
2779 return 0;
2781 if (wParam & EC_LEFTMARGIN)
2782 es->LeftMargin = LOWORD(lParam);
2783 if (wParam & EC_RIGHTMARGIN)
2784 es->RightMargin = HIWORD(lParam);
2785 return 0;
2789 /*********************************************************************
2791 * EM_SETMODIFY
2794 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2796 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2798 es->TextChanged = (BOOL32)wParam;
2799 return 0;
2803 /*********************************************************************
2805 * EM_SETPASSWORDCHAR
2807 * FIXME: This imlementation is way too simple
2810 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2812 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2814 es->PasswordChar = (CHAR)wParam;
2815 return 0;
2819 /*********************************************************************
2821 * EM_SETREADONLY
2824 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2826 if ((BOOL32)wParam)
2827 wndPtr->dwStyle |= ES_READONLY;
2828 else
2829 wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
2830 return TRUE;
2834 /*********************************************************************
2836 * EM_SETRECT
2839 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2841 fprintf(stdnimp,"edit: EM_SETRECT: message not implemented\n");
2842 return 0;
2846 /*********************************************************************
2848 * EM_SETRECTNP
2851 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2853 fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented\n");
2854 return 0;
2858 /*********************************************************************
2860 * EM_SETSEL
2863 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2865 INT32 ns = (INT32)wParam;
2866 INT32 ne = (INT32)lParam;
2867 INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
2869 if (ns == -1) {
2870 EDIT_GetSel(wndPtr, NULL, &ne);
2871 ns = ne;
2872 } else if ((!ns) && (ne == -1))
2873 ne = tl;
2874 else {
2875 ns = MAX(0, MIN(ns, tl));
2876 ne = MAX(0, MIN(ne, tl));
2877 ORDER_INT32(ns, ne);
2879 EDIT_SetSel(wndPtr, ns, ne);
2880 return -1;
2884 /*********************************************************************
2886 * EM_SETSEL16
2889 static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2891 INT32 ns = (INT32)LOWORD(lParam);
2892 INT32 ne = (INT32)HIWORD(lParam);
2894 if ((INT16)LOWORD(lParam) == -1)
2895 ns = -1;
2896 if ((!ns) && ((INT16)HIWORD(lParam) == -1))
2897 ne = -1;
2898 EDIT_EM_SetSel(wndPtr, ns, ne);
2899 if (!wParam)
2900 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2901 return -1;
2905 /*********************************************************************
2907 * EM_SETTABSTOPS
2910 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2912 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2913 INT32 i;
2915 if (!IsMultiLine(wndPtr))
2916 return FALSE;
2917 if (es->TabStops)
2918 free(es->TabStops);
2919 es->NumTabStops = (INT32)wParam;
2920 if (!wParam)
2921 es->TabStops = NULL;
2922 else {
2923 es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
2924 for ( i = 0 ; i < (INT32)wParam ; i++ )
2925 es->TabStops[i] = (INT16)((LPINT32)lParam)[i];
2927 return TRUE;
2931 /*********************************************************************
2933 * EM_SETTABSTOPS16
2936 static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2938 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2940 if (!IsMultiLine(wndPtr))
2941 return FALSE;
2942 if (es->TabStops)
2943 free(es->TabStops);
2944 es->NumTabStops = (INT32)wParam;
2945 if (!wParam)
2946 es->TabStops = NULL;
2947 else {
2948 es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
2949 memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam),
2950 (INT32)wParam * sizeof(INT16));
2952 return TRUE;
2956 /*********************************************************************
2958 * EM_SETWORDBREAKPROC
2961 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2964 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2966 es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
2968 return 0;
2972 /*********************************************************************
2974 * EM_UNDO / WM_UNDO
2977 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2979 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2980 LPSTR utext = xstrdup(EDIT_GetUndoPointer(wndPtr));
2982 dprintf_edit(stddeb, "edit: before UNDO:insertion length = %d, deletion buffer = %s\n",
2983 es->UndoInsertLen, utext);
2985 EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen);
2986 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2987 EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)utext);
2988 EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen);
2989 free(utext);
2991 dprintf_edit(stddeb, "edit: after UNDO: insertion length = %d, deletion buffer = %s\n",
2992 es->UndoInsertLen, EDIT_GetUndoPointer(wndPtr));
2994 return TRUE;
2998 /*********************************************************************
3000 * WM_CHAR
3003 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3005 char str[2];
3006 unsigned char c = (unsigned char)wParam;
3008 switch (c) {
3009 case '\r':
3010 case '\n':
3011 if (IsMultiLine(wndPtr)) {
3012 if (IsReadOnly(wndPtr)) {
3013 EDIT_MoveHome(wndPtr, FALSE);
3014 EDIT_MoveDownward(wndPtr, FALSE);
3015 } else
3016 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)"\r\n");
3018 break;
3019 case '\t':
3020 if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
3021 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)"\t");
3022 break;
3023 default:
3024 if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
3025 str[0] = c;
3026 str[1] = '\0';
3027 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)str);
3029 break;
3031 return 0;
3035 /*********************************************************************
3037 * WM_CLEAR
3040 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3042 EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)"");
3044 return -1;
3048 /*********************************************************************
3050 * WM_COMMAND
3053 static LRESULT EDIT_WM_Command(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3055 if (HIWORD(wParam))
3056 return 0;
3058 switch (LOWORD(wParam)) {
3059 case EM_UNDO32:
3060 EDIT_EM_Undo(wndPtr, 0, 0);
3061 break;
3062 case WM_CUT:
3063 EDIT_WM_Cut(wndPtr, 0, 0);
3064 break;
3065 case WM_COPY:
3066 EDIT_WM_Copy(wndPtr, 0, 0);
3067 break;
3068 case WM_PASTE:
3069 EDIT_WM_Paste(wndPtr, 0, 0);
3070 break;
3071 case WM_CLEAR:
3072 EDIT_WM_Clear(wndPtr, 0, 0);
3073 break;
3074 case EM_SETSEL32:
3075 EDIT_EM_SetSel(wndPtr, 0, -1);
3076 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3077 break;
3078 default:
3079 dprintf_edit(stddeb, "edit: unknown menu item, please report\n");
3080 break;
3082 return -1;
3086 /*********************************************************************
3088 * WM_CONTEXTMENU
3090 * Note: the resource files resource/sysres_??.rc cannot define a
3091 * single popup menu. Hence we use a (dummy) menubar
3092 * containing the single popup menu as its first item.
3095 static LRESULT EDIT_WM_ContextMenu(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3097 HMENU32 hMenu = LoadMenuIndirect32A(SYSRES_GetResPtr(SYSRES_MENU_EDITMENU));
3098 HMENU32 hPopup = GetSubMenu32(hMenu, 0);
3100 TrackPopupMenu32(hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, LOWORD(lParam),
3101 HIWORD(lParam), 0, wndPtr->hwndSelf, NULL);
3102 DestroyMenu32(hMenu);
3103 return 0;
3107 /*********************************************************************
3109 * WM_COPY
3112 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3114 INT32 s;
3115 INT32 e;
3116 HGLOBAL16 hdst;
3117 LPSTR text;
3118 LPSTR dst;
3120 EDIT_GetSel(wndPtr, &s, &e);
3121 if (e == s)
3122 return -1;
3123 ORDER_INT32(s, e);
3124 hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
3125 dst = GlobalLock16(hdst);
3126 text = EDIT_GetPointer(wndPtr);
3127 lstrcpyn32A(dst, text + s, e - s + 1);
3128 GlobalUnlock16(hdst);
3129 OpenClipboard(wndPtr->hwndSelf);
3130 EmptyClipboard();
3131 SetClipboardData(CF_TEXT, hdst);
3132 CloseClipboard();
3133 return -1;
3137 /*********************************************************************
3139 * WM_CREATE
3142 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3144 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
3145 EDITSTATE *es;
3146 LPSTR text;
3148 es = xmalloc(sizeof(EDITSTATE));
3149 memset(es, 0, sizeof(EDITSTATE));
3150 *(EDITSTATE **)wndPtr->wExtra = es;
3152 if (cs->style & WS_VSCROLL)
3153 cs->style |= ES_AUTOVSCROLL;
3154 if (cs->style & WS_HSCROLL)
3155 cs->style |= ES_AUTOHSCROLL;
3157 /* remove the WS_CAPTION style if it has been set - this is really a */
3158 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
3159 if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
3160 cs->style ^= WS_DLGFRAME;
3162 if (IsMultiLine(wndPtr)) {
3163 es->BufSize = BUFSTART_MULTI;
3164 es->BufLimit = BUFLIMIT_MULTI;
3165 es->PasswordChar = '\0';
3166 } else {
3167 es->BufSize = BUFSTART_SINGLE;
3168 es->BufLimit = BUFLIMIT_SINGLE;
3169 es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
3171 if (!(es->hBuf32 = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) {
3172 fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
3173 return -1;
3175 if (!(es->hUndoBuf = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) {
3176 fprintf(stderr, "edit: WM_CREATE: unable to allocate undo buffer\n");
3177 LocalFree32(es->hBuf32);
3178 es->hBuf32 = (HLOCAL32)NULL;
3179 return -1;
3181 es->BufSize = LocalSize32(es->hBuf32) - 1;
3182 es->UndoBufSize = LocalSize32(es->hUndoBuf) - 1;
3183 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
3184 text = EDIT_GetPointer(wndPtr);
3185 *text = '\0';
3186 EDIT_BuildLineDefs(wndPtr);
3187 EDIT_WM_SetFont(wndPtr, 0, 0);
3188 if (cs->lpszName && *(cs->lpszName) != '\0')
3189 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, (LPARAM)cs->lpszName);
3190 EDIT_WM_SetRedraw(wndPtr, TRUE, 0);
3191 return 0;
3195 /*********************************************************************
3197 * WM_CUT
3200 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3202 EDIT_WM_Copy(wndPtr, 0, 0);
3203 EDIT_WM_Clear(wndPtr, 0, 0);
3204 return -1;
3208 /*********************************************************************
3210 * WM_DESTROY
3213 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3215 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3217 free(es->LineDefs);
3218 if (es->TabStops)
3219 free(es->TabStops);
3220 EDIT_ReleaseUndoPointer(wndPtr);
3221 LocalFree32(es->hUndoBuf);
3222 EDIT_ReleasePointer(wndPtr);
3223 if (es->hBuf32)
3224 LocalFree32(es->hBuf32);
3225 else
3226 LOCAL_Free(wndPtr->hInstance, es->hBuf16);
3227 free(es);
3228 *(EDITSTATE **)&wndPtr->wExtra = NULL;
3229 return 0;
3233 /*********************************************************************
3235 * WM_ENABLE
3238 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3240 EDIT_InvalidateText(wndPtr, 0, -1);
3241 return 0;
3245 /*********************************************************************
3247 * WM_ERASEBKGND
3250 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3252 HBRUSH32 hBrush;
3253 RECT32 rc;
3255 hBrush = (HBRUSH32)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
3256 if (!hBrush) hBrush = (HBRUSH32)GetStockObject32(WHITE_BRUSH);
3258 GetClientRect32(wndPtr->hwndSelf, &rc);
3259 IntersectClipRect32((HDC32)wParam, rc.left, rc.top,
3260 rc.right, rc.bottom);
3261 GetClipBox32((HDC32)wParam, &rc);
3263 * FIXME: specs say that we should UnrealizeObject() the brush,
3264 * but the specs of UnrealizeObject() say that we shouldn't
3265 * unrealize a stock object. The default brush that
3266 * DefWndProc() returns is ... a stock object.
3268 FillRect32((HDC32)wParam, &rc, hBrush);
3269 return -1;
3273 /*********************************************************************
3275 * WM_GETDLGCODE
3278 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3280 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
3284 /*********************************************************************
3286 * WM_GETFONT
3289 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3291 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3293 return (LRESULT)es->hFont;
3297 /*********************************************************************
3299 * WM_GETTEXT
3302 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3304 LPSTR text = EDIT_GetPointer(wndPtr);
3305 INT32 len;
3306 LRESULT lResult = 0;
3308 len = lstrlen32A(text);
3309 if ((INT32)wParam > len) {
3310 lstrcpy32A((LPSTR)lParam, text);
3311 lResult = (LRESULT)len + 1;
3313 return lResult;
3317 /*********************************************************************
3319 * WM_GETTEXTLENGTH
3322 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3324 LPSTR text = EDIT_GetPointer(wndPtr);
3326 return (LRESULT)lstrlen32A(text);
3330 /*********************************************************************
3332 * WM_HSCROLL
3334 * FIXME: scrollbar code itself is broken, so this one is a hack.
3337 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3339 INT32 ww = EDIT_GetWndWidth(wndPtr);
3340 INT32 tw = EDIT_GetTextWidth(wndPtr);
3341 INT32 cw = EDIT_GetAveCharWidth(wndPtr);
3342 INT32 xoff = EDIT_GetXOffset(wndPtr);
3343 INT32 dx = 0;
3344 BOOL32 not = TRUE;
3345 LRESULT ret = 0;
3347 switch (wParam) {
3348 case SB_LINELEFT:
3349 dx = -cw;
3350 break;
3351 case SB_LINERIGHT:
3352 dx = cw;
3353 break;
3354 case SB_PAGELEFT:
3355 dx = -ww / HSCROLL_FRACTION / cw * cw;
3356 break;
3357 case SB_PAGERIGHT:
3358 dx = ww / HSCROLL_FRACTION / cw * cw;
3359 break;
3360 case SB_LEFT:
3361 dx = -xoff;
3362 break;
3363 case SB_RIGHT:
3364 dx = tw - xoff;
3365 break;
3366 case SB_THUMBTRACK:
3368 * not = FALSE;
3370 case SB_THUMBPOSITION:
3371 dx = HIWORD(wParam) * tw / 100 - xoff;
3372 break;
3373 /* The next two are undocumented ! */
3374 case EM_GETTHUMB16:
3375 ret = tw ? xoff * 100 / tw : 0;
3376 break;
3377 case EM_LINESCROLL16:
3378 dx = (INT16)HIWORD(wParam);
3379 break;
3380 case SB_ENDSCROLL:
3381 default:
3382 break;
3384 if (dx) {
3385 EDIT_EM_LineScroll(wndPtr, dx, 0);
3386 if (not) {
3387 dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
3388 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
3391 return ret;
3395 /*********************************************************************
3397 * WM_INITMENUPOPUP
3399 * FIXME: the message identifiers have been chosen arbitrarily,
3400 * hence we use MF_BYPOSITION.
3401 * We might as well use the "real" values (anybody knows ?)
3402 * The menu definition is in resources/sysres_??.rc.
3403 * Once these are OK, we better use MF_BYCOMMAND here
3404 * (as we do in EDIT_WM_Command()).
3407 static LRESULT EDIT_WM_InitMenuPopup(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3409 HMENU32 hPopup = (HMENU32)wParam;
3410 INT32 s;
3411 INT32 e;
3413 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
3415 /* undo */
3416 EnableMenuItem32(hPopup, 0, MF_BYPOSITION |
3417 (EDIT_EM_CanUndo(wndPtr, 0, 0) ? MF_ENABLED : MF_GRAYED));
3418 /* cut */
3419 EnableMenuItem32(hPopup, 2, MF_BYPOSITION |
3420 ((e - s) && !IsPassword(wndPtr) ? MF_ENABLED : MF_GRAYED));
3421 /* copy */
3422 EnableMenuItem32(hPopup, 3, MF_BYPOSITION |
3423 ((e - s) && !IsPassword(wndPtr) ? MF_ENABLED : MF_GRAYED));
3424 /* paste */
3425 EnableMenuItem32(hPopup, 4, MF_BYPOSITION |
3426 (IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED));
3427 /* delete */
3428 EnableMenuItem32(hPopup, 5, MF_BYPOSITION |
3429 ((e - s) ? MF_ENABLED : MF_GRAYED));
3430 /* select all */
3431 EnableMenuItem32(hPopup, 7, MF_BYPOSITION |
3432 (s || (e != EDIT_WM_GetTextLength(wndPtr, 0, 0)) ? MF_ENABLED : MF_GRAYED));
3434 return 0;
3438 /*********************************************************************
3440 * WM_KEYDOWN
3442 * Handling of special keys that don't produce a WM_CHAR
3443 * (i.e. non-printable keys) & Backspace & Delete
3446 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3448 INT32 s;
3449 INT32 e;
3450 BOOL32 shift;
3451 BOOL32 control;
3453 if (GetKeyState32(VK_MENU) & 0x8000)
3454 return 0;
3456 shift = GetKeyState32(VK_SHIFT) & 0x8000;
3457 control = GetKeyState32(VK_CONTROL) & 0x8000;
3459 EDIT_GetSel(wndPtr, &s, &e);
3460 switch (wParam) {
3461 case VK_LEFT:
3462 case VK_UP:
3463 if (IsMultiLine(wndPtr) && (wParam == VK_UP))
3464 EDIT_MoveUpward(wndPtr, shift);
3465 else
3466 if (control)
3467 EDIT_MoveWordBackward(wndPtr, shift);
3468 else
3469 EDIT_MoveBackward(wndPtr, shift);
3470 break;
3471 case VK_RIGHT:
3472 case VK_DOWN:
3473 if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
3474 EDIT_MoveDownward(wndPtr, shift);
3475 else if (control)
3476 EDIT_MoveWordForward(wndPtr, shift);
3477 else
3478 EDIT_MoveForward(wndPtr, shift);
3479 break;
3480 case VK_HOME:
3481 EDIT_MoveHome(wndPtr, shift);
3482 break;
3483 case VK_END:
3484 EDIT_MoveEnd(wndPtr, shift);
3485 break;
3486 case VK_PRIOR:
3487 if (IsMultiLine(wndPtr))
3488 EDIT_MovePageUp(wndPtr, shift);
3489 break;
3490 case VK_NEXT:
3491 if (IsMultiLine(wndPtr))
3492 EDIT_MovePageDown(wndPtr, shift);
3493 break;
3494 case VK_BACK:
3495 if (!IsReadOnly(wndPtr) && !control)
3496 if (e != s)
3497 EDIT_WM_Clear(wndPtr, 0, 0);
3498 else
3499 EDIT_DelLeft(wndPtr);
3500 break;
3501 case VK_DELETE:
3502 if (!IsReadOnly(wndPtr) && !(shift && control))
3503 if (e != s) {
3504 if (shift)
3505 EDIT_WM_Cut(wndPtr, 0, 0);
3506 else
3507 EDIT_WM_Clear(wndPtr, 0, 0);
3508 } else {
3509 if (shift)
3510 EDIT_DelLeft(wndPtr);
3511 else if (control)
3512 EDIT_DelEnd(wndPtr);
3513 else
3514 EDIT_DelRight(wndPtr);
3516 break;
3517 case VK_INSERT:
3518 if (shift) {
3519 if (!IsReadOnly(wndPtr))
3520 EDIT_WM_Paste(wndPtr, 0, 0);
3521 } else if (control)
3522 EDIT_WM_Copy(wndPtr, 0, 0);
3523 break;
3525 return 0;
3529 /*********************************************************************
3531 * WM_KILLFOCUS
3534 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3536 INT32 s;
3537 INT32 e;
3539 DestroyCaret();
3540 if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
3541 EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e);
3542 EDIT_InvalidateText(wndPtr, s, e);
3544 dprintf_edit(stddeb, "edit: notification EN_KILLFOCUS sent\n");
3545 EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
3546 return 0;
3550 /*********************************************************************
3552 * WM_LBUTTONDBLCLK
3554 * The caret position has been set on the WM_LBUTTONDOWN message
3557 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3559 INT32 s;
3560 INT32 e;
3561 INT32 l;
3562 INT32 li;
3563 INT32 ll;
3564 LPSTR text = EDIT_GetPointer(wndPtr);
3566 EDIT_GetSel(wndPtr, NULL, &e);
3567 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
3568 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
3569 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
3570 s = li + EDIT_CallWordBreakProc (wndPtr, text + li, e - li, ll, WB_LEFT);
3571 e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
3572 EDIT_EM_SetSel(wndPtr, s, e);
3573 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3574 return 0;
3578 /*********************************************************************
3580 * WM_LBUTTONDOWN
3583 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3585 INT32 x = (INT32)(INT16)LOWORD(lParam);
3586 INT32 y = (INT32)(INT16)HIWORD(lParam);
3587 INT32 l = EDIT_LineFromWndY(wndPtr, y);
3588 INT32 c;
3589 INT32 s;
3590 INT32 e;
3591 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3592 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3593 INT32 li;
3595 SetFocus32(wndPtr->hwndSelf);
3596 SetCapture32(wndPtr->hwndSelf);
3597 l = MIN(fv + vlc - 1, MAX(fv, l));
3598 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
3599 c = EDIT_ColFromWndX(wndPtr, l, x);
3600 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
3601 e = li + c;
3602 if (GetKeyState32(VK_SHIFT) & 0x8000)
3603 EDIT_GetSel(wndPtr, &s, NULL);
3604 else
3605 s = e;
3606 EDIT_SetSel(wndPtr, s, e);
3607 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3608 SetTimer32(wndPtr->hwndSelf, 0, 100, NULL);
3609 return 0;
3613 /*********************************************************************
3615 * WM_LBUTTONUP
3618 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3620 if (GetCapture32() == wndPtr->hwndSelf) {
3621 KillTimer32(wndPtr->hwndSelf, 0);
3622 ReleaseCapture();
3624 return 0;
3628 /*********************************************************************
3630 * WM_MOUSEMOVE
3633 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3635 INT32 x;
3636 INT32 y;
3637 INT32 l;
3638 INT32 c;
3639 INT32 s;
3640 INT32 fv;
3641 INT32 vlc;
3642 INT32 li;
3644 if (GetCapture32() == wndPtr->hwndSelf) {
3645 x = (INT32)(INT16)LOWORD(lParam);
3646 y = (INT32)(INT16)HIWORD(lParam);
3647 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3648 vlc = EDIT_GetVisibleLineCount(wndPtr);
3649 l = EDIT_LineFromWndY(wndPtr, y);
3650 l = MIN(fv + vlc - 1, MAX(fv, l));
3651 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
3652 c = EDIT_ColFromWndX(wndPtr, l, x);
3653 EDIT_GetSel(wndPtr, &s, NULL);
3654 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
3655 EDIT_SetSel(wndPtr, s, li + c);
3658 * FIXME: gotta do some scrolling if outside client (format ?)
3659 * area. Maybe reset the timer ?
3661 return 0;
3665 /*********************************************************************
3667 * WM_PAINT
3670 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3672 PAINTSTRUCT32 ps;
3673 INT32 i;
3674 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3675 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3676 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
3677 HDC32 hdc;
3678 HFONT32 hFont;
3679 HFONT32 oldFont = 0;
3680 RECT32 rc;
3681 RECT32 rcLine;
3682 RECT32 rcRgn;
3683 LRESULT pos;
3684 INT32 e;
3685 BOOL32 rev = IsWindowEnabled32(wndPtr->hwndSelf) &&
3686 ((GetFocus32() == wndPtr->hwndSelf) ||
3687 (wndPtr->dwStyle & ES_NOHIDESEL));
3689 hdc = BeginPaint32(wndPtr->hwndSelf, &ps);
3690 GetClientRect32(wndPtr->hwndSelf, &rc);
3691 IntersectClipRect32( hdc, rc.left, rc.top, rc.right, rc.bottom );
3692 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
3693 if (hFont)
3694 oldFont = (HFONT32)SelectObject32(hdc, hFont);
3695 EDIT_SEND_CTLCOLOR(wndPtr, hdc);
3696 if (!IsWindowEnabled32(wndPtr->hwndSelf))
3697 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
3698 GetClipBox32(hdc, &rcRgn);
3699 for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
3700 EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
3701 if (IntersectRect32(&rc, &rcRgn, &rcLine))
3702 EDIT_PaintLine(wndPtr, hdc, i, rev);
3704 if (hFont) SelectObject32(hdc, oldFont);
3705 if (wndPtr->hwndSelf == GetFocus32()) {
3706 EDIT_GetSel(wndPtr, NULL, &e);
3707 pos = EDIT_EM_PosFromChar(wndPtr, e, 0);
3708 SetCaretPos((INT16)LOWORD(pos), (INT16)HIWORD(pos));
3710 EndPaint32(wndPtr->hwndSelf, &ps);
3711 return 0;
3715 /*********************************************************************
3717 * WM_PASTE
3720 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3722 HGLOBAL16 hsrc;
3723 LPSTR src;
3725 OpenClipboard(wndPtr->hwndSelf);
3726 if ((hsrc = GetClipboardData(CF_TEXT))) {
3727 src = (LPSTR)GlobalLock16(hsrc);
3728 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)src);
3729 GlobalUnlock16(hsrc);
3731 CloseClipboard();
3732 return -1;
3736 /*********************************************************************
3738 * WM_SETCURSOR
3741 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3743 if (LOWORD(lParam) == HTCLIENT) {
3744 SetCursor(LoadCursor16(0, IDC_IBEAM));
3745 return -1;
3746 } else
3747 return 0;
3751 /*********************************************************************
3753 * WM_SETFOCUS
3756 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3758 INT32 s;
3759 INT32 e;
3761 EDIT_GetSel(wndPtr, &s, &e);
3762 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
3763 EDIT_SetSel(wndPtr, s, e);
3764 if(!(wndPtr->dwStyle & ES_NOHIDESEL))
3765 EDIT_InvalidateText(wndPtr, s, e);
3766 ShowCaret(wndPtr->hwndSelf);
3767 dprintf_edit(stddeb, "edit: notification EN_SETFOCUS sent\n");
3768 EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
3769 return 0;
3773 /*********************************************************************
3775 * WM_SETFONT
3778 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3780 TEXTMETRIC32A tm;
3781 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3782 INT32 s;
3783 INT32 e;
3784 HDC32 hdc;
3785 HFONT32 oldFont = 0;
3787 EDIT_GetSel(wndPtr, &s, &e);
3788 es->hFont = (HFONT32)wParam;
3789 hdc = GetDC32(wndPtr->hwndSelf);
3790 if (es->hFont) oldFont = SelectObject32(hdc, es->hFont);
3791 GetTextMetrics32A(hdc, &tm);
3792 es->LineHeight = tm.tmHeight;
3793 es->AveCharWidth = tm.tmAveCharWidth;
3794 if (es->hFont) SelectObject32(hdc, oldFont);
3795 ReleaseDC32(wndPtr->hwndSelf, hdc);
3796 EDIT_BuildLineDefs(wndPtr);
3797 if ((BOOL32)lParam && EDIT_GetRedraw(wndPtr))
3798 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
3799 if (wndPtr->hwndSelf == GetFocus32()) {
3800 DestroyCaret();
3801 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
3802 EDIT_SetSel(wndPtr, s, e);
3803 ShowCaret(wndPtr->hwndSelf);
3805 return 0;
3809 /*********************************************************************
3811 * WM_SETREDRAW
3814 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3816 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3818 es->Redraw = (BOOL32)wParam;
3819 return 0;
3823 /*********************************************************************
3825 * WM_SETTEXT
3828 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3830 EDIT_EM_SetSel(wndPtr, 0, -1);
3831 if (lParam)
3832 EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, lParam);
3833 EDIT_EM_SetModify(wndPtr, TRUE, 0);
3834 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3835 return 1;
3839 /*********************************************************************
3841 * WM_SIZE
3843 * FIXME: What about that FormatRect ???
3846 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3848 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3849 INT32 e;
3851 EDIT_GetSel(wndPtr, 0, &e);
3852 GetClientRect32(wndPtr->hwndSelf, &es->FormatRect);
3853 if (EDIT_GetRedraw(wndPtr) &&
3854 ((wParam == SIZE_MAXIMIZED) ||
3855 (wParam == SIZE_RESTORED))) {
3856 if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
3857 EDIT_BuildLineDefs(wndPtr);
3858 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
3860 return 0;
3864 /*********************************************************************
3866 * WM_SYSKEYDOWN
3869 static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3871 if ((wParam == VK_BACK) && (lParam & 0x2000) &&
3872 (BOOL32)EDIT_EM_CanUndo(wndPtr, 0, 0))
3873 EDIT_EM_Undo(wndPtr, 0, 0);
3874 return 0;
3878 /*********************************************************************
3880 * WM_TIMER
3883 static LRESULT EDIT_WM_Timer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3886 * FIXME: gotta do some scrolling here, like
3887 * EDIT_EM_LineScroll(wndPtr, 0, 1);
3889 return 0;
3893 /*********************************************************************
3895 * WM_VSCROLL
3897 * FIXME: scrollbar code itself is broken, so this one is a hack.
3900 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3902 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
3903 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3904 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3905 INT32 dy = 0;
3906 BOOL32 not = TRUE;
3907 LRESULT ret = 0;
3909 switch (wParam) {
3910 case SB_LINEUP:
3911 dy = -1;
3912 break;
3913 case SB_LINEDOWN:
3914 dy = 1;
3915 break;
3916 case SB_PAGEUP:
3917 dy = -vlc;
3918 break;
3919 case SB_PAGEDOWN:
3920 dy = vlc;
3921 break;
3922 case SB_TOP:
3923 dy = -fv;
3924 break;
3925 case SB_BOTTOM:
3926 dy = lc - 1 - fv;
3927 break;
3928 case SB_THUMBTRACK:
3929 not = FALSE;
3930 /* fall through */
3931 case SB_THUMBPOSITION:
3932 dy = HIWORD(wParam) * (lc - 1) / 100 - fv;
3933 break;
3934 /* The next two are undocumented ! */
3935 case EM_GETTHUMB16:
3936 ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0;
3937 break;
3938 case EM_LINESCROLL16:
3939 dy = (INT16)LOWORD(lParam);
3940 break;
3941 case SB_ENDSCROLL:
3942 default:
3943 break;
3945 if (dy) {
3946 EDIT_EM_LineScroll(wndPtr, 0, dy);
3947 if (not) {
3948 dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
3949 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
3952 return ret;