Release 960528
[wine/gsoc-2012-control.git] / controls / edit.c
blob40182905b9b315825f9cc7fb447d8bc19ebd1f95
1 /*
2 * Edit control
4 * Copyright David W. Metcalfe, 1994
5 * Copyright William Magro, 1995, 1996
6 * Copyright Frans van Dorsselaer, 1996
8 */
11 * UNDER CONSTRUCTION, please read EDIT.TODO
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <windows.h>
18 #include "win.h"
19 #include "local.h"
20 #include "stackframe.h"
21 #include "stddebug.h"
22 #include "debug.h"
23 #include "xmalloc.h"
24 #include "callback.h"
26 #define BUFLIMIT_MULTI 65534 /* maximum text buffer length (not including '\0') */
27 #define BUFLIMIT_SINGLE 32766
28 #define BUFSTART_MULTI 1024 /* starting length for multi-line control */
29 #define BUFSTART_SINGLE 256 /* starting length for single line control */
30 #define GROWLENGTH 64 /* buffers grow by this much */
31 #define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */
33 typedef enum
35 END_0 = 0,
36 END_DELIMIT,
37 END_NONE,
38 END_HARD,
39 END_SOFT,
40 } LINE_END;
42 typedef struct {
43 UINT offset;
44 UINT length;
45 LINE_END ending;
46 } LINEDEF;
48 typedef struct
50 UINT TextWidth; /* width of the widest line in pixels */
51 HLOCAL16 hBuf;
52 char *text;
53 HFONT hFont;
54 LINEDEF *LineDefs;
55 UINT XOffset; /* offset of the viewport in pixels */
56 UINT FirstVisibleLine;
57 UINT LineCount;
58 UINT LineHeight; /* height of a screen line in pixels */
59 UINT AveCharWidth; /* average character width in pixels */
60 UINT BufLimit;
61 UINT BufSize;
62 BOOL TextChanged;
63 BOOL Redraw;
64 UINT SelStart; /* offset of selection start, == SelEnd if no selection */
65 UINT SelEnd; /* offset of selection end == current caret position */
66 UINT NumTabStops;
67 LPINT16 TabStops;
68 EDITWORDBREAKPROC WordBreakProc;
69 char PasswordChar;
70 } EDITSTATE;
73 #define SWAP_UINT(x,y) do { UINT temp = (UINT)(x); (x) = (UINT)(y); (y) = temp; } while(0)
74 #define ORDER_UINT(x,y) do { if ((UINT)(y) < (UINT)(x)) SWAP_UINT((x),(y)); } while(0)
76 /* macros to access window styles */
77 #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
78 #define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL)
79 #define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL)
80 #define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY)
81 #define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0)
83 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
85 #ifdef WINELIB32
86 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
87 SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
88 (WPARAM)(hdc), (LPARAM)(wndPtr)->hwndSelf)
89 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
90 SendMessage32A((wndPtr)->parent->hwndSelf, WM_COMMAND, \
91 MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
92 (LPARAM)(wndPtr)->hwndSelf )
93 #define DPRINTF_EDIT_MSG(str) \
94 dprintf_edit(stddeb, \
95 "edit: " str ": hwnd=%08x, wParam=%08x, lParam=%08lx\n", \
96 (UINT)hwnd, (UINT)wParam, (DWORD)lParam)
97 #else
98 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
99 SendMessage16((wndPtr)->parent->hwndSelf, WM_CTLCOLOR, \
100 (WPARAM)(hdc), MAKELPARAM((wndPtr)->hwndSelf, CTLCOLOR_EDIT))
101 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
102 SendMessage16((wndPtr)->parent->hwndSelf, WM_COMMAND, \
103 (wndPtr)->wIDmenu, \
104 MAKELPARAM((wndPtr)->hwndSelf, wNotifyCode))
105 #define DPRINTF_EDIT_MSG(str) \
106 dprintf_edit(stddeb, \
107 "edit: " str ": hwnd=%04x, wParam=%04x, lParam=%08lx\n", \
108 (UINT)hwnd, (UINT)wParam, (DWORD)lParam)
109 #endif
111 /*********************************************************************
113 * Declarations
115 * Files like these should really be kept in alphabetical order.
118 LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
120 static void EDIT_BuildLineDefs(WND *wndPtr);
121 static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action);
122 static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x);
123 static void EDIT_DelEnd(WND *wndPtr);
124 static void EDIT_DelLeft(WND *wndPtr);
125 static void EDIT_DelRight(WND *wndPtr);
126 static UINT EDIT_GetAveCharWidth(WND *wndPtr);
127 static UINT EDIT_GetLineHeight(WND *wndPtr);
128 static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc);
129 static char * EDIT_GetPointer(WND *wndPtr);
130 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
131 static BOOL EDIT_GetRedraw(WND *wndPtr);
132 static UINT EDIT_GetTextWidth(WND *wndPtr);
133 static UINT EDIT_GetVisibleLineCount(WND *wndPtr);
134 static UINT EDIT_GetWndWidth(WND *wndPtr);
135 static UINT EDIT_GetXOffset(WND *wndPtr);
136 static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end);
137 static UINT EDIT_LineFromWndY(WND *wndPtr, INT y);
138 static BOOL EDIT_MakeFit(WND *wndPtr, UINT size);
139 static void EDIT_MoveBackward(WND *wndPtr, BOOL extend);
140 static void EDIT_MoveDownward(WND *wndPtr, BOOL extend);
141 static void EDIT_MoveEnd(WND *wndPtr, BOOL extend);
142 static void EDIT_MoveForward(WND *wndPtr, BOOL extend);
143 static void EDIT_MoveHome(WND *wndPtr, BOOL extend);
144 static void EDIT_MovePageDown(WND *wndPtr, BOOL extend);
145 static void EDIT_MovePageUp(WND *wndPtr, BOOL extend);
146 static void EDIT_MoveUpward(WND *wndPtr, BOOL extend);
147 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend);
148 static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend);
149 static void EDIT_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev);
150 static UINT EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev);
151 static void EDIT_ReleasePointer(WND *wndPtr);
152 static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
153 static void EDIT_ScrollIntoView(WND *wndPtr);
154 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col);
155 static INT EDIT_WndYFromLine(WND *wndPtr, UINT line);
156 static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action);
158 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam);
159 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam);
160 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam);
161 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam);
162 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam);
163 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam);
164 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam);
165 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam);
166 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
167 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
168 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
169 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam);
170 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam);
171 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
172 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
173 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam);
174 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam);
175 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
176 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
177 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
178 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam);
179 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam);
180 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
181 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam);
182 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
183 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam);
184 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
185 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam);
186 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam);
187 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam);
189 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam);
190 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam);
191 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam);
192 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam);
193 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam);
194 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam);
195 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam);
196 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam);
197 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam);
198 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam);
199 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
200 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam);
201 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
202 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam);
203 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam);
204 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam);
205 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam);
206 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam);
207 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam);
208 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam);
209 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam);
210 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam);
211 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam);
212 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam);
213 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam);
214 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
215 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam);
216 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
219 /*********************************************************************
221 * General shortcuts for variable names:
223 * UINT l; line
224 * UINT c; column
225 * UINT s; offset of selection start
226 * UINT e; offset of selection end
227 * UINT sl; line on which the selection starts
228 * UINT el; line on which the selection ends
229 * UINT sc; column on which the selection starts
230 * UINT ec; column on which the selection ends
231 * UINT li; line index (offset)
232 * UINT fv; first visible line
233 * UINT vlc; vissible line count
234 * UINT lc; line count
235 * UINT lh; line height (in pixels)
236 * UINT tw; text width (in pixels)
237 * UINT ww; window width (in pixels)
238 * UINT cw; character width (average, in pixels)
243 /*********************************************************************
245 * EditWndProc()
248 LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
250 LRESULT lResult = 0L;
251 WND *wndPtr = WIN_FindWndPtr(hwnd);
253 switch (msg) {
254 case EM_CANUNDO:
255 DPRINTF_EDIT_MSG("EM_CANUNDO");
256 lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
257 break;
258 case EM_EMPTYUNDOBUFFER:
259 DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER");
260 lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
261 break;
262 case EM_FMTLINES:
263 DPRINTF_EDIT_MSG("EM_FMTLINES");
264 lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
265 break;
266 case EM_GETFIRSTVISIBLELINE:
267 DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE");
268 lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
269 break;
270 case EM_GETHANDLE:
271 DPRINTF_EDIT_MSG("EM_GETHANDLE");
272 lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
273 break;
274 case EM_GETLINE:
275 DPRINTF_EDIT_MSG("EM_GETLINE");
276 lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
277 break;
278 case EM_GETLINECOUNT:
279 DPRINTF_EDIT_MSG("EM_GETLINECOUNT");
280 lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
281 break;
282 case EM_GETMODIFY:
283 DPRINTF_EDIT_MSG("EM_GETMODIFY");
284 lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
285 break;
286 case EM_GETPASSWORDCHAR:
287 DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR");
288 lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
289 break;
290 case EM_GETRECT:
291 DPRINTF_EDIT_MSG("EM_GETRECT");
292 lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
293 break;
294 case EM_GETSEL:
295 DPRINTF_EDIT_MSG("EM_GETSEL");
296 lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
297 break;
298 case EM_GETTHUMB:
299 DPRINTF_EDIT_MSG("EM_GETTHUMB");
300 lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
301 break;
302 case EM_GETWORDBREAKPROC:
303 DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC");
304 lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
305 break;
306 case EM_LIMITTEXT:
307 DPRINTF_EDIT_MSG("EM_LIMITTEXT");
308 lResult = EDIT_EM_LimitText(wndPtr, wParam, lParam);
309 break;
310 case EM_LINEFROMCHAR:
311 DPRINTF_EDIT_MSG("EM_LINEFROMCHAR");
312 lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
313 break;
314 case EM_LINEINDEX:
315 DPRINTF_EDIT_MSG("EM_LINEINDEX");
316 lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
317 break;
318 case EM_LINELENGTH:
319 DPRINTF_EDIT_MSG("EM_LINELENGTH");
320 lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
321 break;
322 case EM_LINESCROLL:
323 DPRINTF_EDIT_MSG("EM_LINESCROLL");
324 lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
325 break;
326 case EM_REPLACESEL:
327 DPRINTF_EDIT_MSG("EM_REPLACESEL");
328 lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
329 break;
330 case EM_SCROLL:
331 DPRINTF_EDIT_MSG("EM_SCROLL");
332 lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
333 break;
334 case EM_SETHANDLE:
335 DPRINTF_EDIT_MSG("EM_SETHANDLE");
336 lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
337 break;
338 case EM_SETMODIFY:
339 DPRINTF_EDIT_MSG("EM_SETMODIFY");
340 lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
341 break;
342 case EM_SETPASSWORDCHAR:
343 DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR");
344 lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
345 break;
346 case EM_SETREADONLY:
347 DPRINTF_EDIT_MSG("EM_SETREADONLY");
348 lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
349 break;
350 case EM_SETRECT:
351 DPRINTF_EDIT_MSG("EM_SETRECT");
352 lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
353 break;
354 case EM_SETRECTNP:
355 DPRINTF_EDIT_MSG("EM_SETRECTNP");
356 lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
357 break;
358 case EM_SETSEL:
359 DPRINTF_EDIT_MSG("EM_SETSEL");
360 lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
361 break;
362 case EM_SETTABSTOPS:
363 DPRINTF_EDIT_MSG("EM_SETTABSTOPS");
364 lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
365 break;
366 case EM_SETWORDBREAKPROC:
367 DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC");
368 lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
369 break;
370 case EM_UNDO:
371 case WM_UNDO:
372 DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO");
373 lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
374 break;
375 case WM_GETDLGCODE:
376 DPRINTF_EDIT_MSG("WM_GETDLGCODE");
377 lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
378 break;
379 case WM_CHAR:
380 DPRINTF_EDIT_MSG("WM_CHAR");
381 lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
382 break;
383 case WM_CLEAR:
384 DPRINTF_EDIT_MSG("WM_CLEAR");
385 lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
386 break;
387 case WM_COPY:
388 DPRINTF_EDIT_MSG("WM_COPY");
389 lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
390 break;
391 case WM_CREATE:
392 DPRINTF_EDIT_MSG("WM_CREATE");
393 lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
394 break;
395 case WM_CUT:
396 DPRINTF_EDIT_MSG("WM_CUT");
397 lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
398 break;
399 case WM_DESTROY:
400 DPRINTF_EDIT_MSG("WM_DESTROY");
401 lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
402 break;
403 case WM_ENABLE:
404 DPRINTF_EDIT_MSG("WM_ENABLE");
405 lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
406 break;
407 case WM_ERASEBKGND:
408 DPRINTF_EDIT_MSG("WM_ERASEBKGND");
409 lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
410 break;
411 case WM_GETFONT:
412 DPRINTF_EDIT_MSG("WM_GETFONT");
413 lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
414 break;
415 case WM_GETTEXT:
416 DPRINTF_EDIT_MSG("WM_GETTEXT");
417 lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
418 break;
419 case WM_GETTEXTLENGTH:
420 DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH");
421 lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
422 break;
423 case WM_HSCROLL:
424 DPRINTF_EDIT_MSG("WM_HSCROLL");
425 lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
426 break;
427 case WM_KEYDOWN:
428 DPRINTF_EDIT_MSG("WM_KEYDOWN");
429 lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
430 break;
431 case WM_KILLFOCUS:
432 DPRINTF_EDIT_MSG("WM_KILLFOCUS");
433 lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
434 break;
435 case WM_LBUTTONDBLCLK:
436 DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK");
437 lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
438 break;
439 case WM_LBUTTONDOWN:
440 DPRINTF_EDIT_MSG("WM_LBUTTONDOWN");
441 lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
442 break;
443 case WM_LBUTTONUP:
444 DPRINTF_EDIT_MSG("WM_LBUTTONUP");
445 lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
446 break;
447 case WM_MOUSEMOVE:
449 * DPRINTF_EDIT_MSG("WM_MOUSEMOVE");
451 lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
452 break;
453 case WM_PAINT:
454 DPRINTF_EDIT_MSG("WM_PAINT");
455 lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
456 break;
457 case WM_PASTE:
458 DPRINTF_EDIT_MSG("WM_PASTE");
459 lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
460 break;
461 case WM_SETCURSOR:
463 * DPRINTF_EDIT_MSG("WM_SETCURSOR");
465 lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
466 break;
467 case WM_SETFOCUS:
468 DPRINTF_EDIT_MSG("WM_SETFOCUS");
469 lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
470 break;
471 case WM_SETFONT:
472 DPRINTF_EDIT_MSG("WM_SETFONT");
473 lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
474 break;
475 case WM_SETREDRAW:
476 DPRINTF_EDIT_MSG("WM_SETREDRAW");
477 lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
478 break;
479 case WM_SETTEXT:
480 DPRINTF_EDIT_MSG("WM_SETTEXT");
481 lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
482 break;
483 case WM_SIZE:
484 DPRINTF_EDIT_MSG("WM_SIZE");
485 lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
486 break;
487 case WM_VSCROLL:
488 DPRINTF_EDIT_MSG("WM_VSCROLL");
489 lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
490 break;
491 default:
492 if (msg >= WM_USER)
493 fprintf(stdnimp, "edit: undocumented message %d >= WM_USER, please report.\n", msg);
494 lResult = DefWindowProc16(hwnd, msg, wParam, lParam);
495 break;
497 EDIT_ReleasePointer(wndPtr);
498 return lResult;
502 /*********************************************************************
504 * EDIT_BuildLineDefs
506 * Build array of pointers to text lines.
507 * Lines can end with '\0' (last line), nothing (if it is to long),
508 * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
511 static void EDIT_BuildLineDefs(WND *wndPtr)
513 EDITSTATE *es = EDITSTATEPTR(wndPtr);
514 char *text = EDIT_GetPointer(wndPtr);
515 int ww = EDIT_GetWndWidth(wndPtr);
516 HDC hdc;
517 HFONT hFont;
518 HFONT oldFont = 0;
519 char *start, *cp;
520 int prev, next;
521 int width;
522 int length;
523 LINE_END ending;
525 hdc = GetDC(wndPtr->hwndSelf);
526 hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
527 if (hFont)
528 oldFont = SelectObject(hdc, hFont);
530 if (!IsMultiLine(wndPtr)) {
531 es->LineCount = 1;
532 es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
533 es->LineDefs[0].offset = 0;
534 es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
535 es->LineDefs[0].ending = END_0;
536 es->TextWidth = LOWORD(GetTabbedTextExtent(hdc, text,
537 es->LineDefs[0].length,
538 es->NumTabStops, es->TabStops));
539 } else {
540 es->LineCount = 0;
541 start = text;
542 do {
543 if (!(cp = strstr(start, "\r\n"))) {
544 ending = END_0;
545 length = strlen(start);
546 } else if ((cp > start) && (*(cp - 1) == '\r')) {
547 ending = END_SOFT;
548 length = cp - start - 1;
549 } else {
550 ending = END_HARD;
551 length = cp - start;
553 width = LOWORD(GetTabbedTextExtent(hdc, start, length,
554 es->NumTabStops, es->TabStops));
556 if (IsWordWrap(wndPtr) && (width > ww)) {
557 next = 0;
558 do {
559 prev = next;
560 next = EDIT_CallWordBreakProc(wndPtr, start,
561 prev + 1, length, WB_RIGHT);
562 width = LOWORD(GetTabbedTextExtent(hdc, start, next,
563 es->NumTabStops, es->TabStops));
564 } while (width <= ww);
565 if (prev) {
566 length = prev;
567 if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
568 length, WB_ISDELIMITER)) {
569 length--;
570 ending = END_DELIMIT;
571 } else
572 ending = END_NONE;
573 } else {
575 width = LOWORD(GetTabbedTextExtent(hdc, start, length,
576 es->NumTabStops, es->TabStops));
579 es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF));
580 es->LineDefs[es->LineCount].offset = start - text;
581 es->LineDefs[es->LineCount].length = length;
582 es->LineDefs[es->LineCount].ending = ending;
583 es->LineCount++;
584 es->TextWidth = MAX(es->TextWidth, width);
586 start += length;
587 switch (ending) {
588 case END_SOFT:
589 start += 3;
590 break;
591 case END_HARD:
592 start += 2;
593 break;
594 case END_DELIMIT:
595 start++;
596 break;
597 default:
598 break;
600 } while (*start || (ending == END_SOFT) || (ending == END_HARD));
602 if (hFont)
603 SelectObject(hdc, oldFont);
604 ReleaseDC(wndPtr->hwndSelf, hdc);
608 /*********************************************************************
610 * EDIT_CallWordBreakProc
612 * Call appropriate WordBreakProc (internal or external).
615 static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action)
617 EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0L);
619 if (wbp) {
620 return CallWordBreakProc((FARPROC)wbp,
621 (LONG)MAKE_SEGPTR(s), index, count, action);
622 } else
623 return EDIT_WordBreakProc(s, index, count, action);
627 /*********************************************************************
629 * EDIT_ColFromWndX
631 * Calculates, for a given line and X-coordinate on the screen, the column.
634 static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x)
636 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
637 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
638 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
639 UINT i;
641 line = MAX(0, MIN(line, lc - 1));
642 for (i = 0 ; i < ll ; i++)
643 if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
644 break;
645 return i;
649 /*********************************************************************
651 * EDIT_DelEnd
653 * Delete all characters on this line to right of cursor.
656 static void EDIT_DelEnd(WND *wndPtr)
658 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
659 EDIT_MoveEnd(wndPtr, TRUE);
660 EDIT_WM_Clear(wndPtr, 0, 0L);
664 /*********************************************************************
666 * EDIT_DelLeft
668 * Delete character to left of cursor.
671 static void EDIT_DelLeft(WND *wndPtr)
673 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
674 EDIT_MoveBackward(wndPtr, TRUE);
675 EDIT_WM_Clear(wndPtr, 0, 0L);
679 /*********************************************************************
681 * EDIT_DelRight
683 * Delete character to right of cursor.
686 static void EDIT_DelRight(WND *wndPtr)
688 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
689 EDIT_MoveForward(wndPtr, TRUE);
690 EDIT_WM_Clear(wndPtr, 0, 0L);
694 /*********************************************************************
696 * EDIT_GetAveCharWidth
699 static UINT EDIT_GetAveCharWidth(WND *wndPtr)
701 EDITSTATE *es = EDITSTATEPTR(wndPtr);
703 return es->AveCharWidth;
707 /*********************************************************************
709 * EDIT_GetLineHeight
712 static UINT EDIT_GetLineHeight(WND *wndPtr)
714 EDITSTATE *es = EDITSTATEPTR(wndPtr);
716 return es->LineHeight;
720 /*********************************************************************
722 * EDIT_GetLineRect
724 * Calculates the bounding rectangle for a line from a starting
725 * column to an ending column.
728 static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc)
730 rc->top = EDIT_WndYFromLine(wndPtr, line);
731 rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
732 rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
733 rc->right = ((INT)ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
734 EDIT_WndXFromCol(wndPtr, line, ecol);
738 /*********************************************************************
740 * EDIT_GetPointer
742 * This acts as a LOCAL_Lock(), but it locks only once. This way
743 * you can call it whenever you like, without unlocking.
746 static char *EDIT_GetPointer(WND *wndPtr)
748 EDITSTATE *es = EDITSTATEPTR(wndPtr);
750 if (!es->text && es->hBuf)
751 es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf);
752 return es->text;
756 /*********************************************************************
758 * EDIT_GetRect
760 * Beware: This is not the function called on EM_GETRECT.
761 * It expects a (LPRECT) in lParam, not a (SEGPTR).
762 * It is used internally, as if there were no pointer difficulties.
765 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
767 GetClientRect16( wndPtr->hwndSelf, (LPRECT16)lParam );
768 return 0L;
772 /*********************************************************************
774 * EDIT_GetRedraw
777 static BOOL EDIT_GetRedraw(WND *wndPtr)
779 EDITSTATE *es = EDITSTATEPTR(wndPtr);
781 return es->Redraw;
785 /*********************************************************************
787 * EDIT_GetTextWidth
790 static UINT EDIT_GetTextWidth(WND *wndPtr)
792 EDITSTATE *es = EDITSTATEPTR(wndPtr);
794 return es->TextWidth;
798 /*********************************************************************
800 * EDIT_GetVisibleLineCount
803 static UINT EDIT_GetVisibleLineCount(WND *wndPtr)
805 RECT16 rc;
807 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
808 return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
812 /*********************************************************************
814 * EDIT_GetWndWidth
817 static UINT EDIT_GetWndWidth(WND *wndPtr)
819 RECT16 rc;
821 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
822 return rc.right - rc.left;
826 /*********************************************************************
828 * EDIT_GetXOffset
831 static UINT EDIT_GetXOffset(WND *wndPtr)
833 EDITSTATE *es = EDITSTATEPTR(wndPtr);
835 return es->XOffset;
839 /*********************************************************************
841 * EDIT_InvalidateText
843 * Invalidate the text from offset start upto, but not including,
844 * offset end. Useful for (re)painting the selection.
845 * Regions outside the linewidth are not invalidated.
846 * end == -1 means end == TextLength.
847 * start and end need not be ordered.
850 static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end)
852 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
853 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
854 UINT sl;
855 UINT el;
856 UINT sc;
857 UINT ec;
858 RECT16 rcWnd;
859 RECT16 rcLine;
860 RECT16 rcUpdate;
861 UINT l;
863 if (end == start )
864 return;
866 if ((INT)end == -1)
867 end = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
868 ORDER_UINT(start, end);
869 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, start, 0L);
870 el = (UINT)EDIT_EM_LineFromChar(wndPtr, end, 0L);
871 if ((el < fv) || (sl > fv + vlc))
872 return;
874 sc = start - (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L);
875 ec = end - (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
876 if (sl < fv) {
877 sl = fv;
878 sc = 0;
880 if (el > fv + vlc) {
881 el = fv + vlc;
882 ec = (UINT)EDIT_EM_LineLength(wndPtr,
883 (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L), 0L);
885 EDIT_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
886 if (sl == el) {
887 EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
888 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
889 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
890 } else {
891 EDIT_GetLineRect(wndPtr, sl, sc,
892 (UINT)EDIT_EM_LineLength(wndPtr,
893 (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L), 0L),
894 &rcLine);
895 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
896 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
897 for (l = sl + 1 ; l < el ; l++) {
898 EDIT_GetLineRect(wndPtr, l, 0,
899 (UINT)EDIT_EM_LineLength(wndPtr,
900 (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L), 0L),
901 &rcLine);
902 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
903 InvalidateRect16(wndPtr->hwndSelf, &rcUpdate, FALSE);
905 EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
906 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
907 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
912 /*********************************************************************
914 * EDIT_LineFromWndY
916 * Calculates, for a given Y-coordinate on the screen, the line.
919 static UINT EDIT_LineFromWndY(WND *wndPtr, INT y)
921 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
922 UINT lh = EDIT_GetLineHeight(wndPtr);
923 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
925 return MAX(0, MIN(lc - 1, y / lh + fv));
929 /*********************************************************************
931 * EDIT_MakeFit
933 * Try to fit size + 1 bytes in the buffer. Constrain to limits.
936 static BOOL EDIT_MakeFit(WND *wndPtr, UINT size)
938 EDITSTATE *es = EDITSTATEPTR(wndPtr);
940 if (size <= es->BufSize)
941 return TRUE;
942 if (size > es->BufLimit)
943 return FALSE;
944 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
945 if (size > es->BufLimit)
946 size = es->BufLimit;
948 dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
950 if (LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, size + 1, LMEM_MOVEABLE)) {
951 es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1, es->BufLimit);
952 return TRUE;
953 } else
954 return FALSE;
958 /*********************************************************************
960 * EDIT_MoveBackward
963 static void EDIT_MoveBackward(WND *wndPtr, BOOL extend)
965 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
966 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
967 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
968 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
970 if (e - li == 0) {
971 if (l) {
972 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
973 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
975 } else
976 e--;
977 if (!extend)
978 s = e;
979 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
983 /*********************************************************************
985 * EDIT_MoveDownward
988 static void EDIT_MoveDownward(WND *wndPtr, BOOL extend)
990 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
991 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
992 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
993 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
994 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
995 INT x;
997 if (l < lc - 1) {
998 x = EDIT_WndXFromCol(wndPtr, l, e - li);
999 l++;
1000 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1001 EDIT_ColFromWndX(wndPtr, l, x);
1003 if (!extend)
1004 s = e;
1005 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1009 /*********************************************************************
1011 * EDIT_MoveEnd
1014 static void EDIT_MoveEnd(WND *wndPtr, BOOL extend)
1016 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1017 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1018 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1019 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1020 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1022 e = li + ll;
1023 if (!extend)
1024 s = e;
1025 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1029 /*********************************************************************
1031 * EDIT_MoveForward
1034 static void EDIT_MoveForward(WND *wndPtr, BOOL extend)
1036 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1037 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1038 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1039 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1040 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1041 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1043 if (e - li == ll) {
1044 if (l != lc - 1)
1045 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1046 } else
1047 e++;
1048 if (!extend)
1049 s = e;
1050 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1054 /*********************************************************************
1056 * EDIT_MoveHome
1058 * Home key: move to beginning of line.
1061 static void EDIT_MoveHome(WND *wndPtr, BOOL extend)
1063 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1064 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1065 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1066 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1068 e = li;
1069 if (!extend)
1070 s = e;
1071 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1075 /*********************************************************************
1077 * EDIT_MovePageDown
1080 static void EDIT_MovePageDown(WND *wndPtr, BOOL extend)
1082 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1083 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1084 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1085 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1086 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1087 INT x;
1089 if (l < lc - 1) {
1090 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1091 l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
1092 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1093 EDIT_ColFromWndX(wndPtr, l, x);
1095 if (!extend)
1096 s = e;
1097 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1101 /*********************************************************************
1103 * EDIT_MovePageUp
1106 static void EDIT_MovePageUp(WND *wndPtr, BOOL extend)
1108 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1109 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1110 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1111 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1112 INT x;
1114 if (l) {
1115 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1116 l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
1117 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1118 EDIT_ColFromWndX(wndPtr, l, x);
1120 if (!extend)
1121 s = e;
1122 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1126 /*********************************************************************
1128 * EDIT_MoveUpward
1131 static void EDIT_MoveUpward(WND *wndPtr, BOOL extend)
1133 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1134 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1135 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1136 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1137 INT x;
1139 if (l) {
1140 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1141 l--;
1142 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1143 EDIT_ColFromWndX(wndPtr, l, x);
1145 if (!extend)
1146 s = e;
1147 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1151 /*********************************************************************
1153 * EDIT_MoveWordBackward
1156 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend)
1158 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1159 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1160 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1161 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1162 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1163 char *text;
1165 if (e - li == 0) {
1166 if (l) {
1167 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
1168 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1170 } else {
1171 text = EDIT_GetPointer(wndPtr);
1172 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1173 text + li, e - li, ll, WB_LEFT);
1175 if (!extend)
1176 s = e;
1177 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1181 /*********************************************************************
1183 * EDIT_MoveWordForward
1186 static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend)
1188 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1189 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1190 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1191 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1192 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1193 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1194 char *text;
1196 if (e - li == ll) {
1197 if (l != lc - 1)
1198 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1199 } else {
1200 text = EDIT_GetPointer(wndPtr);
1201 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1202 text + li, e - li + 1, ll, WB_RIGHT);
1204 if (!extend)
1205 s = e;
1206 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1210 /*********************************************************************
1212 * EDIT_PaintLine
1215 static void EDIT_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev)
1217 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1218 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1219 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1220 UINT li;
1221 UINT ll;
1222 UINT s;
1223 UINT e;
1224 INT x;
1225 INT y;
1227 if ((line < fv) || (line > fv + vlc) || (line >= lc))
1228 return;
1230 dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
1232 x = EDIT_WndXFromCol(wndPtr, line, 0);
1233 y = EDIT_WndYFromLine(wndPtr, line);
1234 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1235 ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1236 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1237 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1238 ORDER_UINT(s, e);
1239 s = MIN(li + ll, MAX(li, s));
1240 e = MIN(li + ll, MAX(li, e));
1241 if (rev && (s != e) &&
1242 ((GetFocus() == wndPtr->hwndSelf) ||
1243 (wndPtr->dwStyle & ES_NOHIDESEL))) {
1244 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
1245 x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
1246 x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
1247 } else
1248 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
1252 /*********************************************************************
1254 * EDIT_PaintText
1257 static UINT EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev)
1259 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1260 COLORREF BkColor;
1261 COLORREF TextColor;
1262 UINT ret;
1263 char *text;
1264 UINT li;
1265 UINT xoff;
1267 if (!count)
1268 return 0;
1269 BkColor = GetBkColor(hdc);
1270 TextColor = GetTextColor(hdc);
1271 if (rev) {
1272 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1273 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1275 text = EDIT_GetPointer(wndPtr);
1276 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1277 xoff = EDIT_GetXOffset(wndPtr);
1278 ret = LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
1279 es->NumTabStops, es->TabStops, -xoff));
1280 if (rev) {
1281 SetBkColor(hdc, BkColor);
1282 SetTextColor(hdc, TextColor);
1284 return ret;
1288 /*********************************************************************
1290 * EDIT_ReleasePointer
1292 * This is the only helper function that can be called with es = NULL.
1293 * It is called at the end of EditWndProc() to unlock the buffer.
1296 static void EDIT_ReleasePointer(WND *wndPtr)
1298 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1300 if (!es)
1301 return;
1302 if (es->text && es->hBuf)
1303 LOCAL_Unlock(wndPtr->hInstance, es->hBuf);
1304 es->text = NULL;
1308 /*********************************************************************
1310 * EDIT_ReplaceSel
1312 * Beware: This is not the function called on EM_REPLACESEL.
1313 * It expects a (char *) in lParam, not a (SEGPTR).
1314 * It is used internally, as if there were no pointer difficulties.
1317 static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1319 const char *str = (char *)lParam;
1320 int strl = strlen(str);
1321 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1322 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1323 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1324 int i;
1325 char *p;
1326 char *text;
1327 BOOL redraw;
1329 ORDER_UINT(s,e);
1330 if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
1331 EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
1332 return 0L;
1334 redraw = EDIT_GetRedraw(wndPtr);
1335 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
1336 EDIT_WM_Clear(wndPtr, 0, 0L);
1337 tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1338 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1339 text = EDIT_GetPointer(wndPtr);
1340 for (p = text + tl ; p >= text + e ; p--)
1341 p[strl] = p[0];
1342 for (i = 0 , p = text + e ; i < strl ; i++)
1343 p[i] = str[i];
1344 EDIT_BuildLineDefs(wndPtr);
1345 e += strl;
1346 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(e, e));
1347 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
1348 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
1349 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
1350 if (redraw) {
1351 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
1352 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
1354 return 0L;
1358 /*********************************************************************
1360 * EDIT_ScrollIntoView
1362 * Makes sure the caret is visible.
1365 static void EDIT_ScrollIntoView(WND *wndPtr)
1367 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1368 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1369 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1370 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1371 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1372 UINT ww = EDIT_GetWndWidth(wndPtr);
1373 UINT cw = EDIT_GetAveCharWidth(wndPtr);
1374 INT x = EDIT_WndXFromCol(wndPtr, l, e - li);
1375 int dy = 0;
1376 int dx = 0;
1378 if (l >= fv + vlc)
1379 dy = l - vlc + 1 - fv;
1380 if (l < fv)
1381 dy = l - fv;
1382 if (x < 0)
1383 dx = x - ww / HSCROLL_FRACTION / cw * cw;
1384 if (x > ww)
1385 dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
1386 if (dy || dx) {
1387 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, dx));
1388 if (dy)
1389 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
1390 if (dx)
1391 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
1396 /*********************************************************************
1398 * EDIT_WndXFromCol
1400 * Calculates, for a given line and column, the X-coordinate on the screen.
1403 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col)
1405 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1406 char *text = EDIT_GetPointer(wndPtr);
1407 INT ret;
1408 HDC hdc;
1409 HFONT hFont;
1410 HFONT oldFont = 0;
1411 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1412 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1413 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1414 UINT xoff = EDIT_GetXOffset(wndPtr);
1416 hdc = GetDC(wndPtr->hwndSelf);
1417 hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
1418 if (hFont)
1419 oldFont = SelectObject(hdc, hFont);
1420 line = MAX(0, MIN(line, lc - 1));
1421 col = MIN(col, ll);
1422 ret = LOWORD(GetTabbedTextExtent(hdc,
1423 text + li, col,
1424 es->NumTabStops, es->TabStops)) - xoff;
1425 if (hFont)
1426 SelectObject(hdc, oldFont);
1427 ReleaseDC(wndPtr->hwndSelf, hdc);
1428 return ret;
1432 /*********************************************************************
1434 * EDIT_WndYFromLine
1436 * Calculates, for a given line, the Y-coordinate on the screen.
1439 static INT EDIT_WndYFromLine(WND *wndPtr, UINT line)
1441 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1442 UINT lh = EDIT_GetLineHeight(wndPtr);
1444 return (line - fv) * lh;
1448 /*********************************************************************
1450 * EDIT_WordBreakProc
1452 * Find the beginning of words.
1453 * Note: unlike the specs for a WordBreakProc, this function only
1454 * allows to be called without linebreaks between s[0] upto
1455 * s[count - 1]. Remember it is only called
1456 * internally, so we can decide this for ourselves.
1459 static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action)
1461 INT ret = 0;
1463 dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%d"
1464 ", count=%d, action=%d\n", s, index, count, action);
1466 switch (action) {
1467 case WB_LEFT:
1468 if (!count)
1469 break;
1470 if (index)
1471 index--;
1472 if (s[index] == ' ') {
1473 while (index && (s[index] == ' '))
1474 index--;
1475 if (index) {
1476 while (index && (s[index] != ' '))
1477 index--;
1478 if (s[index] == ' ')
1479 index++;
1481 } else {
1482 while (index && (s[index] != ' '))
1483 index--;
1484 if (s[index] == ' ')
1485 index++;
1487 ret = index;
1488 break;
1489 case WB_RIGHT:
1490 if (!count)
1491 break;
1492 if (index)
1493 index--;
1494 if (s[index] == ' ')
1495 while ((index < count) && (s[index] == ' ')) index++;
1496 else {
1497 while (s[index] && (s[index] != ' ') && (index < count))
1498 index++;
1499 while ((s[index] == ' ') && (index < count)) index++;
1501 ret = index;
1502 break;
1503 case WB_ISDELIMITER:
1504 ret = (s[index] == ' ');
1505 break;
1506 default:
1507 fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
1508 break;
1510 return ret;
1514 /*********************************************************************
1516 * EM_CANUNDO
1519 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1521 return 0L;
1525 /*********************************************************************
1527 * EM_EMPTYUNDOBUFFER
1530 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1532 return 0L;
1536 /*********************************************************************
1538 * EM_FMTLINES
1541 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1543 fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented.\n");
1544 return wParam ? -1L : 0L;
1548 /*********************************************************************
1550 * EM_GETFIRSTVISIBLELINE
1553 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1555 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1557 return (LRESULT)es->FirstVisibleLine;
1561 /*********************************************************************
1563 * EM_GETHANDLE
1566 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1568 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1570 return (LRESULT)es->hBuf;
1574 /*********************************************************************
1576 * EM_GETLINE
1579 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1581 char *text;
1582 char *src;
1583 char *dst;
1584 UINT len;
1585 UINT i;
1586 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1588 if (!IsMultiLine(wndPtr))
1589 wParam = 0;
1590 if ((UINT)wParam >= lc)
1591 return 0L;
1592 text = EDIT_GetPointer(wndPtr);
1593 src = text + (UINT)EDIT_EM_LineIndex(wndPtr, wParam, 0L);
1594 dst = (char *)PTR_SEG_TO_LIN(lParam);
1595 len = MIN(*(WORD *)dst, (UINT)EDIT_EM_LineLength(wndPtr, wParam, 0L));
1596 for (i = 0 ; i < len ; i++) {
1597 *dst = *src;
1598 src++;
1599 dst++;
1601 return (LRESULT)len;
1605 /*********************************************************************
1607 * EM_GETLINECOUNT
1610 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1612 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1614 return (LRESULT)es->LineCount;
1618 /*********************************************************************
1620 * EM_GETMODIFY
1623 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1625 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1627 return (LRESULT)es->TextChanged;
1631 /*********************************************************************
1633 * EM_GETPASSWORDCHAR
1636 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1638 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1640 return (LRESULT)es->PasswordChar;
1644 /*********************************************************************
1646 * EM_GETRECT
1649 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1651 return EDIT_GetRect(wndPtr, wParam, (LPARAM)PTR_SEG_TO_LIN(lParam));
1655 /*********************************************************************
1657 * EM_GETSEL
1660 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1662 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1664 return MAKELONG(es->SelStart, es->SelEnd);
1668 /*********************************************************************
1670 * EM_GETTHUMB
1672 * FIXME: undocumented: is this right ?
1675 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1677 return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L),
1678 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L));
1682 /*********************************************************************
1684 * EM_GETWORDBREAKPROC
1687 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1689 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1691 return (LRESULT)es->WordBreakProc;
1695 /*********************************************************************
1697 * EM_LIMITTEXT
1700 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1702 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1704 if (IsMultiLine(wndPtr)) {
1705 if (wParam)
1706 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_MULTI);
1707 else
1708 es->BufLimit = BUFLIMIT_MULTI;
1709 } else {
1710 if (wParam)
1711 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_SINGLE);
1712 else
1713 es->BufLimit = BUFLIMIT_SINGLE;
1715 return 0L;
1719 /*********************************************************************
1721 * EM_LINEFROMCHAR
1724 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1726 UINT l;
1728 if (!IsMultiLine(wndPtr))
1729 return 0L;
1730 if ((INT)wParam == -1)
1731 wParam = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1732 l = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
1733 while ((UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam)
1734 l--;
1735 return (LRESULT)l;
1739 /*********************************************************************
1741 * EM_LINEINDEX
1744 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1746 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1747 UINT e;
1748 UINT l;
1749 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1751 if ((INT)wParam == -1) {
1752 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1753 l = lc - 1;
1754 while (es->LineDefs[l].offset > e)
1755 l--;
1756 return (LRESULT)es->LineDefs[l].offset;
1758 if ((UINT)wParam >= lc)
1759 return -1L;
1760 return (LRESULT)es->LineDefs[(UINT)wParam].offset;
1764 /*********************************************************************
1766 * EM_LINELENGTH
1769 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1771 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1772 UINT s;
1773 UINT e;
1774 UINT sl;
1775 UINT el;
1777 if (!IsMultiLine(wndPtr))
1778 return (LRESULT)es->LineDefs[0].length;
1779 if ((INT)wParam == -1) {
1780 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1781 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1782 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, s, 0L);
1783 el = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1784 return (LRESULT)(s - es->LineDefs[sl].offset +
1785 es->LineDefs[el].offset +
1786 es->LineDefs[el].length - e);
1788 return (LRESULT)es->LineDefs[(UINT)EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length;
1792 /*********************************************************************
1794 * EM_LINESCROLL
1797 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1799 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1800 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1801 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1802 UINT nfv = MAX(0, fv + (INT)LOWORD(lParam));
1803 UINT xoff = EDIT_GetXOffset(wndPtr);
1804 UINT nxoff = MAX(0, xoff + (INT)HIWORD(lParam));
1805 UINT tw = EDIT_GetTextWidth(wndPtr);
1806 INT dx;
1807 INT dy;
1808 POINT16 pos;
1809 HRGN hRgn;
1811 if (nfv >= lc)
1812 nfv = lc - 1;
1814 if (nxoff >= tw)
1815 nxoff = tw;
1816 dx = xoff - nxoff;
1817 dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
1818 if (dx || dy) {
1819 if (wndPtr->hwndSelf == GetFocus())
1820 HideCaret(wndPtr->hwndSelf);
1821 if (EDIT_GetRedraw(wndPtr)) {
1822 hRgn = CreateRectRgn(0, 0, 0, 0);
1823 GetUpdateRgn(wndPtr->hwndSelf, hRgn, FALSE);
1824 ValidateRgn(wndPtr->hwndSelf, 0);
1825 OffsetRgn(hRgn, dx, dy);
1826 InvalidateRgn( wndPtr->hwndSelf, hRgn, TRUE );
1827 DeleteObject(hRgn);
1828 ScrollWindow(wndPtr->hwndSelf, dx, dy, NULL, NULL);
1830 es->FirstVisibleLine = nfv;
1831 es->XOffset = nxoff;
1832 if (IsVScrollBar(wndPtr))
1833 SetScrollPos(wndPtr->hwndSelf, SB_VERT,
1834 EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1835 if (IsHScrollBar(wndPtr))
1836 SetScrollPos(wndPtr->hwndSelf, SB_HORZ,
1837 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1838 if (wndPtr->hwndSelf == GetFocus()) {
1839 GetCaretPos16(&pos);
1840 SetCaretPos(pos.x + dx, pos.y + dy);
1841 ShowCaret(wndPtr->hwndSelf);
1844 return -1L;
1848 /*********************************************************************
1850 * EM_REPLACESEL
1853 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1855 return (LRESULT)EDIT_ReplaceSel(wndPtr, wParam,
1856 (LPARAM)(char *)PTR_SEG_TO_LIN(lParam));
1860 /*********************************************************************
1862 * EM_SCROLL
1864 * FIXME: undocumented message.
1867 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1869 fprintf(stdnimp, "edit: EM_SCROLL: message not implemented (undocumented), please report.\n");
1870 return 0L;
1874 /*********************************************************************
1876 * EM_SETHANDLE
1879 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1881 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1883 if (IsMultiLine(wndPtr)) {
1884 EDIT_ReleasePointer(wndPtr);
1886 * old buffer is freed by caller
1888 es->hBuf = (HLOCAL16)wParam;
1889 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
1890 es->LineCount = 0;
1891 es->FirstVisibleLine = 0;
1892 es->SelStart = es->SelEnd = 0;
1893 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
1894 EDIT_EM_SetModify(wndPtr, FALSE, 0L);
1895 EDIT_BuildLineDefs(wndPtr);
1896 if (EDIT_GetRedraw(wndPtr))
1897 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
1898 EDIT_ScrollIntoView(wndPtr);
1900 return 0L;
1904 /*********************************************************************
1906 * EM_SETMODIFY
1909 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1911 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1913 es->TextChanged = (BOOL)wParam;
1914 return 0L;
1918 /*********************************************************************
1920 * EM_SETPASSWORDCHAR
1923 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1925 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1927 es->PasswordChar = (char)wParam;
1928 return 0L;
1932 /*********************************************************************
1934 * EM_SETREADONLY
1937 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1939 if ((BOOL)wParam)
1940 wndPtr->dwStyle |= ES_READONLY;
1941 else
1942 wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
1943 return 0L;
1947 /*********************************************************************
1949 * EM_SETRECT
1952 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1954 fprintf(stdnimp,"edit: EM_SETRECT: message not implemented, please report.\n");
1955 return 0L;
1959 /*********************************************************************
1961 * EM_SETRECTNP
1964 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1966 fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented, please report.\n");
1967 return 0L;
1971 /*********************************************************************
1973 * EM_SETSEL
1976 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1978 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1979 UINT ns = LOWORD(lParam);
1980 UINT ne = HIWORD(lParam);
1981 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1982 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1983 UINT el;
1984 UINT eli;
1985 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1987 if ((INT)ns == -1) {
1988 ns = e;
1989 ne = e;
1991 else {
1992 ns = MIN(ns, tl);
1993 ne = MIN(ne, tl);
1995 es->SelStart = ns;
1996 es->SelEnd = ne;
1997 if (wndPtr->hwndSelf == GetFocus()) {
1998 el = (UINT)EDIT_EM_LineFromChar(wndPtr, ne, 0L);
1999 eli = (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
2000 SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - eli),
2001 EDIT_WndYFromLine(wndPtr, el));
2003 if (!wParam)
2004 EDIT_ScrollIntoView(wndPtr);
2005 if (EDIT_GetRedraw(wndPtr)) {
2006 ORDER_UINT(s, e);
2007 ORDER_UINT(s, ns);
2008 ORDER_UINT(s, ne);
2009 ORDER_UINT(e, ns);
2010 ORDER_UINT(e, ne);
2011 ORDER_UINT(ns, ne);
2012 if (e != ns) {
2013 EDIT_InvalidateText(wndPtr, s, e);
2014 EDIT_InvalidateText(wndPtr, ns, ne);
2015 } else
2016 EDIT_InvalidateText(wndPtr, s, ne);
2018 return -1L;
2022 /*********************************************************************
2024 * EM_SETTABSTOPS
2027 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2029 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2031 if (!IsMultiLine(wndPtr))
2032 return 0L;
2033 if (es->TabStops)
2034 free(es->TabStops);
2035 es->NumTabStops = (UINT)wParam;
2036 if (!wParam)
2037 es->TabStops = NULL;
2038 else {
2039 es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
2040 memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam),
2041 (UINT)wParam * sizeof(INT16));
2043 return 1L;
2047 /*********************************************************************
2049 * EM_SETWORDBREAKPROC
2052 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2054 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2056 es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
2057 return 0L;
2061 /*********************************************************************
2063 * EM_UNDO
2066 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2068 return 0L;
2072 /*********************************************************************
2074 * WM_CHAR
2077 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2079 char str[2];
2080 char c = (char)wParam;
2082 switch (c) {
2083 case '\r':
2084 case '\n':
2085 if (IsMultiLine(wndPtr)) {
2086 if (IsReadOnly(wndPtr)) {
2087 EDIT_MoveHome(wndPtr, FALSE);
2088 EDIT_MoveDownward(wndPtr, FALSE);
2089 } else
2090 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n");
2092 break;
2093 case '\t':
2094 if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
2095 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\t");
2096 break;
2097 default:
2098 if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
2099 str[0] = c;
2100 str[1] = '\0';
2101 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)str);
2103 break;
2105 return 0L;
2109 /*********************************************************************
2111 * WM_CLEAR
2114 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2116 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2117 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2118 char *text;
2119 BOOL redraw;
2121 if (s != e) {
2122 redraw = EDIT_GetRedraw(wndPtr);
2123 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
2124 ORDER_UINT(s, e);
2125 text = EDIT_GetPointer(wndPtr);
2126 strcpy(text + s, text + e);
2127 EDIT_BuildLineDefs(wndPtr);
2128 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, s));
2129 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2130 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2131 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
2132 if (redraw) {
2133 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2134 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2137 return -1L;
2141 /*********************************************************************
2143 * WM_COPY
2146 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2148 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2149 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2150 HGLOBAL hdst;
2151 char *text;
2152 char *dst;
2153 char *src;
2154 int i;
2156 if (e == s)
2157 return -1L;
2158 ORDER_UINT(s, e);
2159 hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
2160 dst = GlobalLock16(hdst);
2161 text = EDIT_GetPointer(wndPtr);
2162 src = text + s;
2163 for (i = 0 ; i < e - s ; i++)
2164 *dst++ = *src++;
2165 *dst = '\0';
2166 GlobalUnlock16(hdst);
2167 OpenClipboard(wndPtr->hwndSelf);
2168 EmptyClipboard();
2169 SetClipboardData(CF_TEXT, hdst);
2170 CloseClipboard();
2171 return -1L;
2175 /*********************************************************************
2177 * WM_CREATE
2180 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2182 CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
2183 EDITSTATE *es;
2184 char *text;
2186 es = xmalloc(sizeof(EDITSTATE));
2187 memset(es, 0, sizeof(EDITSTATE));
2188 *(EDITSTATE **)wndPtr->wExtra = es;
2190 if (cs->style & WS_VSCROLL)
2191 cs->style |= ES_AUTOVSCROLL;
2192 if (cs->style & WS_HSCROLL)
2193 cs->style |= ES_AUTOHSCROLL;
2195 /* remove the WS_CAPTION style if it has been set - this is really a */
2196 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
2197 if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
2198 cs->style ^= WS_DLGFRAME;
2200 if (IsMultiLine(wndPtr)) {
2201 es->BufSize = BUFSTART_MULTI;
2202 es->BufLimit = BUFLIMIT_MULTI;
2203 es->PasswordChar = '\0';
2204 } else {
2205 es->BufSize = BUFSTART_SINGLE;
2206 es->BufLimit = BUFLIMIT_SINGLE;
2207 es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
2209 if (!LOCAL_HeapSize(wndPtr->hInstance)) {
2210 if (!LocalInit(wndPtr->hInstance, 0,
2211 GlobalSize16(wndPtr->hInstance))) {
2212 fprintf(stderr, "edit: WM_CREATE: could not initialize local heap\n");
2213 return -1L;
2215 dprintf_edit(stddeb, "edit: WM_CREATE: local heap initialized\n");
2217 if (!(es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1))) {
2218 fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
2219 return -1L;
2221 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
2222 text = EDIT_GetPointer(wndPtr);
2223 *text = '\0';
2224 EDIT_BuildLineDefs(wndPtr);
2225 EDIT_WM_SetFont(wndPtr, 0, 0L);
2226 if (cs->lpszName)
2227 EDIT_EM_ReplaceSel(wndPtr, FALSE, (LPARAM)cs->lpszName);
2228 EDIT_WM_SetRedraw(wndPtr, TRUE, 0L);
2229 return 0L;
2233 /*********************************************************************
2235 * WM_CUT
2238 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2240 EDIT_WM_Copy(wndPtr, 0, 0L);
2241 EDIT_WM_Clear(wndPtr, 0, 0L);
2242 return -1L;
2246 /*********************************************************************
2248 * WM_DESTROY
2251 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2253 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2255 free(es->LineDefs);
2256 if (es->TabStops)
2257 free(es->TabStops);
2258 EDIT_ReleasePointer(wndPtr);
2259 LOCAL_Free(wndPtr->hInstance, es->hBuf);
2260 free(es);
2261 *(EDITSTATE **)&wndPtr->wExtra = NULL;
2262 return 0L;
2266 /*********************************************************************
2268 * WM_ENABLE
2271 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2273 EDIT_InvalidateText(wndPtr, 0, -1);
2274 return 0L;
2278 /*********************************************************************
2280 * WM_ERASEBKGND
2283 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2285 HBRUSH hBrush;
2286 RECT16 rc;
2288 hBrush = (HBRUSH)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
2289 if (!hBrush)
2290 hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
2292 GetClientRect16(wndPtr->hwndSelf, &rc);
2293 IntersectClipRect((HDC)wParam, rc.left, rc.top, rc.right, rc.bottom);
2294 GetClipBox16((HDC)wParam, &rc);
2296 * FIXME: specs say that we should UnrealizeObject() the brush,
2297 * but the specs of UnrealizeObject() say that we shouldn't
2298 * unrealize a stock object. The default brush that
2299 * DefWndProc() returns is ... a stock object.
2301 FillRect16((HDC)wParam, &rc, hBrush);
2302 return -1L;
2306 /*********************************************************************
2308 * WM_GETDLGCODE
2311 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2313 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
2317 /*********************************************************************
2319 * WM_GETFONT
2322 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2324 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2326 return (LRESULT)es->hFont;
2330 /*********************************************************************
2332 * WM_GETTEXT
2335 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2337 char *text = EDIT_GetPointer(wndPtr);
2338 int len;
2339 LRESULT lResult = 0L;
2341 len = strlen(text);
2342 if ((UINT)wParam > len) {
2343 strcpy((char *)PTR_SEG_TO_LIN(lParam), text);
2344 lResult = (LRESULT)len ;
2346 return lResult;
2350 /*********************************************************************
2352 * WM_GETTEXTLENGTH
2355 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2357 char *text = EDIT_GetPointer(wndPtr);
2359 return (LRESULT)strlen(text);
2363 /*********************************************************************
2365 * WM_HSCROLL
2367 * FIXME: scrollbar code itself is broken, so this one is a hack.
2370 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2372 UINT ww = EDIT_GetWndWidth(wndPtr);
2373 UINT tw = EDIT_GetTextWidth(wndPtr);
2374 UINT cw = EDIT_GetAveCharWidth(wndPtr);
2375 UINT xoff = EDIT_GetXOffset(wndPtr);
2376 INT dx = 0;
2377 BOOL not = TRUE;
2378 LRESULT ret = 0L;
2380 switch (wParam) {
2381 case SB_LINELEFT:
2382 dx = -cw;
2383 break;
2384 case SB_LINERIGHT:
2385 dx = cw;
2386 break;
2387 case SB_PAGELEFT:
2388 dx = -ww / HSCROLL_FRACTION / cw * cw;
2389 break;
2390 case SB_PAGERIGHT:
2391 dx = ww / HSCROLL_FRACTION / cw * cw;
2392 break;
2393 case SB_LEFT:
2394 dx = -xoff;
2395 break;
2396 case SB_RIGHT:
2397 dx = tw - xoff;
2398 break;
2399 case SB_THUMBTRACK:
2401 * not = FALSE;
2403 case SB_THUMBPOSITION:
2404 dx = LOWORD(lParam) * tw / 100 - xoff;
2405 break;
2406 /* The next two are undocumented ! */
2407 case EM_GETTHUMB:
2408 ret = tw ? MAKELONG(xoff * 100 / tw, 0) : 0;
2409 break;
2410 case EM_LINESCROLL:
2411 dx = LOWORD(lParam);
2412 break;
2413 case SB_ENDSCROLL:
2414 default:
2415 break;
2417 if (dx) {
2418 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(0, dx));
2419 if (not)
2420 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
2422 return ret;
2426 /*********************************************************************
2428 * WM_KEYDOWN
2430 * Handling of special keys that don't produce a WM_CHAR
2431 * (i.e. non-printable keys) & Backspace & Delete
2434 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2436 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2437 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2438 BOOL shift;
2439 BOOL control;
2441 if (GetKeyState(VK_MENU) & 0x8000)
2442 return 0L;
2444 shift = GetKeyState(VK_SHIFT) & 0x8000;
2445 control = GetKeyState(VK_CONTROL) & 0x8000;
2447 switch (wParam) {
2448 case VK_LEFT:
2449 case VK_UP:
2450 if (IsMultiLine(wndPtr) && (wParam == VK_UP))
2451 EDIT_MoveUpward(wndPtr, shift);
2452 else
2453 if (control)
2454 EDIT_MoveWordBackward(wndPtr, shift);
2455 else
2456 EDIT_MoveBackward(wndPtr, shift);
2457 break;
2458 case VK_RIGHT:
2459 case VK_DOWN:
2460 if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
2461 EDIT_MoveDownward(wndPtr, shift);
2462 else if (control)
2463 EDIT_MoveWordForward(wndPtr, shift);
2464 else
2465 EDIT_MoveForward(wndPtr, shift);
2466 break;
2467 case VK_HOME:
2468 EDIT_MoveHome(wndPtr, shift);
2469 break;
2470 case VK_END:
2471 EDIT_MoveEnd(wndPtr, shift);
2472 break;
2473 case VK_PRIOR:
2474 if (IsMultiLine(wndPtr))
2475 EDIT_MovePageUp(wndPtr, shift);
2476 break;
2477 case VK_NEXT:
2478 if (IsMultiLine(wndPtr))
2479 EDIT_MovePageDown(wndPtr, shift);
2480 break;
2481 case VK_BACK:
2482 if (!IsReadOnly(wndPtr) && !control)
2483 if (e != s)
2484 EDIT_WM_Clear(wndPtr, 0, 0L);
2485 else
2486 EDIT_DelLeft(wndPtr);
2487 break;
2488 case VK_DELETE:
2489 if (!IsReadOnly(wndPtr) && !(shift && control))
2490 if (e != s) {
2491 if (shift)
2492 EDIT_WM_Cut(wndPtr, 0, 0L);
2493 else
2494 EDIT_WM_Clear(wndPtr, 0, 0L);
2495 } else {
2496 if (shift)
2497 EDIT_DelLeft(wndPtr);
2498 else if (control)
2499 EDIT_DelEnd(wndPtr);
2500 else
2501 EDIT_DelRight(wndPtr);
2503 break;
2504 case VK_INSERT:
2505 if (shift) {
2506 if (!IsReadOnly(wndPtr))
2507 EDIT_WM_Paste(wndPtr, 0, 0L);
2508 } else if (control)
2509 EDIT_WM_Copy(wndPtr, 0, 0L);
2510 break;
2512 return 0L;
2516 /*********************************************************************
2518 * WM_KILLFOCUS
2521 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2523 UINT s;
2524 UINT e;
2526 DestroyCaret();
2527 if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
2528 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2529 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2530 EDIT_InvalidateText(wndPtr, s, e);
2532 EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
2533 return 0L;
2537 /*********************************************************************
2539 * WM_LBUTTONDBLCLK
2541 * The caret position has been set on the WM_LBUTTONDOWN message
2544 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2546 UINT s;
2547 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2548 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
2549 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2550 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
2551 char *text = EDIT_GetPointer(wndPtr);
2553 s = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_LEFT);
2554 e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
2555 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2556 return 0L;
2560 /*********************************************************************
2562 * WM_LBUTTONDOWN
2565 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2567 INT x = (INT)LOWORD(lParam);
2568 INT y = (INT)HIWORD(lParam);
2569 UINT l = EDIT_LineFromWndY(wndPtr, y);
2570 UINT c;
2571 UINT s;
2572 UINT e;
2573 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2574 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2575 UINT li;
2577 SetFocus(wndPtr->hwndSelf);
2578 SetCapture(wndPtr->hwndSelf);
2579 l = MIN(fv + vlc - 1, MAX(fv, l));
2580 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
2581 c = EDIT_ColFromWndX(wndPtr, l, x);
2582 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2583 e = li + c;
2584 if (GetKeyState(VK_SHIFT) & 0x8000)
2585 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2586 else
2587 s = e;
2588 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2589 return 0L;
2593 /*********************************************************************
2595 * WM_LBUTTONUP
2598 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2600 if (GetCapture() == wndPtr->hwndSelf)
2601 ReleaseCapture();
2602 return 0L;
2606 /*********************************************************************
2608 * WM_MOUSEMOVE
2611 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2613 INT x;
2614 INT y;
2615 UINT l;
2616 UINT c;
2617 UINT s;
2618 UINT fv;
2619 UINT vlc;
2620 UINT li;
2622 if (GetCapture() == wndPtr->hwndSelf) {
2623 x = (INT)LOWORD(lParam);
2624 y = (INT)HIWORD(lParam);
2625 fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2626 vlc = EDIT_GetVisibleLineCount(wndPtr);
2627 l = EDIT_LineFromWndY(wndPtr, y);
2628 l = MIN(fv + vlc - 1, MAX(fv, l));
2629 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
2630 c = EDIT_ColFromWndX(wndPtr, l, x);
2631 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2632 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2633 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, li + c));
2635 return 0L;
2639 /*********************************************************************
2641 * WM_PAINT
2644 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2646 PAINTSTRUCT16 ps;
2647 UINT i;
2648 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2649 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2650 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2651 HDC16 hdc;
2652 HFONT hFont;
2653 HFONT oldFont = 0;
2654 RECT16 rc;
2655 RECT16 rcLine;
2656 RECT16 rcRgn;
2657 BOOL rev = IsWindowEnabled(wndPtr->hwndSelf) &&
2658 ((GetFocus() == wndPtr->hwndSelf) ||
2659 (wndPtr->dwStyle & ES_NOHIDESEL));
2661 hdc = BeginPaint16(wndPtr->hwndSelf, &ps);
2662 GetClientRect16(wndPtr->hwndSelf, &rc);
2663 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
2664 hFont = EDIT_WM_GetFont(wndPtr, 0, 0L);
2665 if (hFont)
2666 oldFont = SelectObject(hdc, hFont);
2667 EDIT_SEND_CTLCOLOR(wndPtr, hdc);
2668 if (!IsWindowEnabled(wndPtr->hwndSelf))
2669 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
2670 GetClipBox16(hdc, &rcRgn);
2671 for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
2672 EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
2673 if (IntersectRect16(&rc, &rcRgn, &rcLine))
2674 EDIT_PaintLine(wndPtr, hdc, i, rev);
2676 if (hFont)
2677 SelectObject(hdc, oldFont);
2678 EndPaint16(wndPtr->hwndSelf, &ps);
2679 return 0L;
2683 /*********************************************************************
2685 * WM_PASTE
2688 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2690 HGLOBAL hsrc;
2691 char *src;
2693 OpenClipboard(wndPtr->hwndSelf);
2694 if ((hsrc = GetClipboardData(CF_TEXT))) {
2695 src = (char *)GlobalLock16(hsrc);
2696 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)src);
2697 GlobalUnlock16(hsrc);
2699 CloseClipboard();
2700 return -1L;
2704 /*********************************************************************
2706 * WM_SETCURSOR
2709 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2711 if (LOWORD(lParam) == HTCLIENT) {
2712 SetCursor(LoadCursor(0, IDC_IBEAM));
2713 return -1L;
2714 } else
2715 return 0L;
2719 /*********************************************************************
2721 * WM_SETFOCUS
2724 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2726 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2727 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2729 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2730 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, e));
2731 if(!(wndPtr->dwStyle & ES_NOHIDESEL))
2732 EDIT_InvalidateText(wndPtr, s, e);
2733 ShowCaret(wndPtr->hwndSelf);
2734 EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
2735 return 0L;
2739 /*********************************************************************
2741 * WM_SETFONT
2744 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2746 TEXTMETRIC tm;
2747 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2748 LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L);
2749 HDC hdc;
2750 HFONT oldFont = 0;
2752 es->hFont = (HFONT)wParam;
2753 hdc = GetDC(wndPtr->hwndSelf);
2754 if (es->hFont)
2755 oldFont = SelectObject(hdc, es->hFont);
2756 GetTextMetrics(hdc, &tm);
2757 es->LineHeight = HIWORD(GetTextExtent(hdc, "X", 1));
2758 es->AveCharWidth = tm.tmAveCharWidth;
2759 if (es->hFont)
2760 SelectObject(hdc, oldFont);
2761 ReleaseDC(wndPtr->hwndSelf, hdc);
2762 EDIT_BuildLineDefs(wndPtr);
2763 if ((BOOL)lParam && EDIT_GetRedraw(wndPtr))
2764 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2765 if (wndPtr->hwndSelf == GetFocus()) {
2766 DestroyCaret();
2767 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2768 EDIT_EM_SetSel(wndPtr, 1, sel);
2769 ShowCaret(wndPtr->hwndSelf);
2771 return 0L;
2775 /*********************************************************************
2777 * WM_SETREDRAW
2780 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2782 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2784 es->Redraw = (BOOL)wParam;
2785 return 0L;
2789 /*********************************************************************
2791 * WM_SETTEXT
2794 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2796 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(0, -1));
2797 EDIT_WM_Clear(wndPtr, 0, 0L);
2798 if (lParam)
2799 EDIT_EM_ReplaceSel(wndPtr, 0, lParam);
2800 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
2801 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2802 EDIT_ScrollIntoView(wndPtr);
2803 return 0L;
2807 /*********************************************************************
2809 * WM_SIZE
2812 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2814 if (EDIT_GetRedraw(wndPtr) &&
2815 ((wParam == SIZE_MAXIMIZED) ||
2816 (wParam == SIZE_RESTORED))) {
2817 if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
2818 EDIT_BuildLineDefs(wndPtr);
2819 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2821 return 0L;
2825 /*********************************************************************
2827 * WM_VSCROLL
2829 * FIXME: scrollbar code itself is broken, so this one is a hack.
2832 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2834 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2835 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2836 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2837 INT dy = 0;
2838 BOOL not = TRUE;
2839 LRESULT ret = 0L;
2841 switch (wParam) {
2842 case SB_LINEUP:
2843 dy = -1;
2844 break;
2845 case SB_LINEDOWN:
2846 dy = 1;
2847 break;
2848 case SB_PAGEUP:
2849 dy = -vlc;
2850 break;
2851 case SB_PAGEDOWN:
2852 dy = vlc;
2853 break;
2854 case SB_TOP:
2855 dy = -fv;
2856 break;
2857 case SB_BOTTOM:
2858 dy = lc - 1 - fv;
2859 break;
2860 case SB_THUMBTRACK:
2862 * not = FALSE;
2864 case SB_THUMBPOSITION:
2865 dy = LOWORD(lParam) * (lc - 1) / 100 - fv;
2866 break;
2867 /* The next two are undocumented ! */
2868 case EM_GETTHUMB:
2869 ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0L;
2870 break;
2871 case EM_LINESCROLL:
2872 dy = LOWORD(lParam);
2873 break;
2874 case SB_ENDSCROLL:
2875 default:
2876 break;
2878 if (dy) {
2879 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, 0));
2880 if (not)
2881 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
2883 return ret;