Release 960717
[wine/multimedia.git] / controls / edit.c
blob5dae7f95837bafde8109df9e0ae82ffa3f5f793e
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)
82 #define IsPassword(wndPtr) ((wndPtr)->dwStyle & ES_PASSWORD)
83 #define IsLower(wndPtr) ((wndPtr)->dwStyle & ES_LOWERCASE)
84 #define IsUpper(wndPtr) ((wndPtr)->dwStyle & ES_UPPERCASE)
86 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
88 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
89 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
90 (WPARAM)(hdc), (LPARAM)(wndPtr)->hwndSelf ))
91 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
92 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_COMMAND, \
93 MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
94 (LPARAM)(wndPtr)->hwndSelf ))
95 #define DPRINTF_EDIT_MSG(str) \
96 dprintf_edit(stddeb, \
97 "edit: " str ": hwnd=%04x, wParam=%04x, lParam=%08x\n", \
98 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
101 /*********************************************************************
103 * Declarations
105 * Files like these should really be kept in alphabetical order.
108 LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
110 static void EDIT_BuildLineDefs(WND *wndPtr);
111 static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action);
112 static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x);
113 static void EDIT_DelEnd(WND *wndPtr);
114 static void EDIT_DelLeft(WND *wndPtr);
115 static void EDIT_DelRight(WND *wndPtr);
116 static UINT EDIT_GetAveCharWidth(WND *wndPtr);
117 static UINT EDIT_GetLineHeight(WND *wndPtr);
118 static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc);
119 static char * EDIT_GetPointer(WND *wndPtr);
120 static char * EDIT_GetPasswordPointer(WND *wndPtr);
121 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
122 static BOOL EDIT_GetRedraw(WND *wndPtr);
123 static UINT EDIT_GetTextWidth(WND *wndPtr);
124 static UINT EDIT_GetVisibleLineCount(WND *wndPtr);
125 static UINT EDIT_GetWndWidth(WND *wndPtr);
126 static UINT EDIT_GetXOffset(WND *wndPtr);
127 static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end);
128 static UINT EDIT_LineFromWndY(WND *wndPtr, INT y);
129 static BOOL EDIT_MakeFit(WND *wndPtr, UINT size);
130 static void EDIT_MoveBackward(WND *wndPtr, BOOL extend);
131 static void EDIT_MoveDownward(WND *wndPtr, BOOL extend);
132 static void EDIT_MoveEnd(WND *wndPtr, BOOL extend);
133 static void EDIT_MoveForward(WND *wndPtr, BOOL extend);
134 static void EDIT_MoveHome(WND *wndPtr, BOOL extend);
135 static void EDIT_MovePageDown(WND *wndPtr, BOOL extend);
136 static void EDIT_MovePageUp(WND *wndPtr, BOOL extend);
137 static void EDIT_MoveUpward(WND *wndPtr, BOOL extend);
138 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend);
139 static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend);
140 static void EDIT_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev);
141 static UINT EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev);
142 static void EDIT_ReleasePointer(WND *wndPtr);
143 static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
144 static void EDIT_ScrollIntoView(WND *wndPtr);
145 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col);
146 static INT EDIT_WndYFromLine(WND *wndPtr, UINT line);
147 static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action);
149 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam);
150 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam);
151 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam);
152 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam);
153 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam);
154 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam);
155 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam);
156 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam);
157 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
158 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
159 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
160 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam);
161 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam);
162 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
163 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
164 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam);
165 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam);
166 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
167 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
168 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
169 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam);
170 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam);
171 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
172 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam);
173 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
174 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam);
175 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
176 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam);
177 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam);
178 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam);
180 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam);
181 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam);
182 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam);
183 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam);
184 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam);
185 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam);
186 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam);
187 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam);
188 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam);
189 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam);
190 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
191 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam);
192 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
193 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam);
194 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam);
195 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam);
196 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam);
197 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam);
198 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam);
199 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam);
200 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam);
201 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam);
202 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam);
203 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam);
204 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam);
205 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
206 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam);
207 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
210 /*********************************************************************
212 * General shortcuts for variable names:
214 * UINT l; line
215 * UINT c; column
216 * UINT s; offset of selection start
217 * UINT e; offset of selection end
218 * UINT sl; line on which the selection starts
219 * UINT el; line on which the selection ends
220 * UINT sc; column on which the selection starts
221 * UINT ec; column on which the selection ends
222 * UINT li; line index (offset)
223 * UINT fv; first visible line
224 * UINT vlc; vissible line count
225 * UINT lc; line count
226 * UINT lh; line height (in pixels)
227 * UINT tw; text width (in pixels)
228 * UINT ww; window width (in pixels)
229 * UINT cw; character width (average, in pixels)
234 /*********************************************************************
236 * EditWndProc()
239 LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
241 LRESULT lResult = 0L;
242 WND *wndPtr = WIN_FindWndPtr(hwnd);
244 switch (msg) {
245 case EM_CANUNDO:
246 DPRINTF_EDIT_MSG("EM_CANUNDO");
247 lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
248 break;
249 case EM_EMPTYUNDOBUFFER:
250 DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER");
251 lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
252 break;
253 case EM_FMTLINES:
254 DPRINTF_EDIT_MSG("EM_FMTLINES");
255 lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
256 break;
257 case EM_GETFIRSTVISIBLELINE:
258 DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE");
259 lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
260 break;
261 case EM_GETHANDLE:
262 DPRINTF_EDIT_MSG("EM_GETHANDLE");
263 lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
264 break;
265 case EM_GETLINE:
266 DPRINTF_EDIT_MSG("EM_GETLINE");
267 lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
268 break;
269 case EM_GETLINECOUNT:
270 DPRINTF_EDIT_MSG("EM_GETLINECOUNT");
271 lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
272 break;
273 case EM_GETMODIFY:
274 DPRINTF_EDIT_MSG("EM_GETMODIFY");
275 lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
276 break;
277 case EM_GETPASSWORDCHAR:
278 DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR");
279 lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
280 break;
281 case EM_GETRECT:
282 DPRINTF_EDIT_MSG("EM_GETRECT");
283 lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
284 break;
285 case EM_GETSEL:
286 DPRINTF_EDIT_MSG("EM_GETSEL");
287 lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
288 break;
289 case EM_GETTHUMB:
290 DPRINTF_EDIT_MSG("EM_GETTHUMB");
291 lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
292 break;
293 case EM_GETWORDBREAKPROC:
294 DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC");
295 lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
296 break;
297 case EM_LIMITTEXT:
298 DPRINTF_EDIT_MSG("EM_LIMITTEXT");
299 lResult = EDIT_EM_LimitText(wndPtr, wParam, lParam);
300 break;
301 case EM_LINEFROMCHAR:
302 DPRINTF_EDIT_MSG("EM_LINEFROMCHAR");
303 lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
304 break;
305 case EM_LINEINDEX:
306 DPRINTF_EDIT_MSG("EM_LINEINDEX");
307 lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
308 break;
309 case EM_LINELENGTH:
310 DPRINTF_EDIT_MSG("EM_LINELENGTH");
311 lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
312 break;
313 case EM_LINESCROLL:
314 DPRINTF_EDIT_MSG("EM_LINESCROLL");
315 lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
316 break;
317 case EM_REPLACESEL:
318 DPRINTF_EDIT_MSG("EM_REPLACESEL");
319 lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
320 break;
321 case EM_SCROLL:
322 DPRINTF_EDIT_MSG("EM_SCROLL");
323 lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
324 break;
325 case EM_SETHANDLE:
326 DPRINTF_EDIT_MSG("EM_SETHANDLE");
327 lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
328 break;
329 case EM_SETMODIFY:
330 DPRINTF_EDIT_MSG("EM_SETMODIFY");
331 lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
332 break;
333 case EM_SETPASSWORDCHAR:
334 DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR");
335 lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
336 break;
337 case EM_SETREADONLY:
338 DPRINTF_EDIT_MSG("EM_SETREADONLY");
339 lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
340 break;
341 case EM_SETRECT:
342 DPRINTF_EDIT_MSG("EM_SETRECT");
343 lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
344 break;
345 case EM_SETRECTNP:
346 DPRINTF_EDIT_MSG("EM_SETRECTNP");
347 lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
348 break;
349 case EM_SETSEL:
350 DPRINTF_EDIT_MSG("EM_SETSEL");
351 lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
352 break;
353 case EM_SETTABSTOPS:
354 DPRINTF_EDIT_MSG("EM_SETTABSTOPS");
355 lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
356 break;
357 case EM_SETWORDBREAKPROC:
358 DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC");
359 lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
360 break;
361 case EM_UNDO:
362 case WM_UNDO:
363 DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO");
364 lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
365 break;
366 case WM_GETDLGCODE:
367 DPRINTF_EDIT_MSG("WM_GETDLGCODE");
368 lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
369 break;
370 case WM_CHAR:
371 DPRINTF_EDIT_MSG("WM_CHAR");
372 lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
373 break;
374 case WM_CLEAR:
375 DPRINTF_EDIT_MSG("WM_CLEAR");
376 lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
377 break;
378 case WM_COPY:
379 DPRINTF_EDIT_MSG("WM_COPY");
380 lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
381 break;
382 case WM_CREATE:
383 DPRINTF_EDIT_MSG("WM_CREATE");
384 lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
385 break;
386 case WM_CUT:
387 DPRINTF_EDIT_MSG("WM_CUT");
388 lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
389 break;
390 case WM_DESTROY:
391 DPRINTF_EDIT_MSG("WM_DESTROY");
392 lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
393 break;
394 case WM_ENABLE:
395 DPRINTF_EDIT_MSG("WM_ENABLE");
396 lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
397 break;
398 case WM_ERASEBKGND:
399 DPRINTF_EDIT_MSG("WM_ERASEBKGND");
400 lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
401 break;
402 case WM_GETFONT:
403 DPRINTF_EDIT_MSG("WM_GETFONT");
404 lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
405 break;
406 case WM_GETTEXT:
407 DPRINTF_EDIT_MSG("WM_GETTEXT");
408 lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
409 break;
410 case WM_GETTEXTLENGTH:
411 DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH");
412 lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
413 break;
414 case WM_HSCROLL:
415 DPRINTF_EDIT_MSG("WM_HSCROLL");
416 lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
417 break;
418 case WM_KEYDOWN:
419 DPRINTF_EDIT_MSG("WM_KEYDOWN");
420 lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
421 break;
422 case WM_KILLFOCUS:
423 DPRINTF_EDIT_MSG("WM_KILLFOCUS");
424 lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
425 break;
426 case WM_LBUTTONDBLCLK:
427 DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK");
428 lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
429 break;
430 case WM_LBUTTONDOWN:
431 DPRINTF_EDIT_MSG("WM_LBUTTONDOWN");
432 lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
433 break;
434 case WM_LBUTTONUP:
435 DPRINTF_EDIT_MSG("WM_LBUTTONUP");
436 lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
437 break;
438 case WM_MOUSEMOVE:
440 * DPRINTF_EDIT_MSG("WM_MOUSEMOVE");
442 lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
443 break;
444 case WM_PAINT:
445 DPRINTF_EDIT_MSG("WM_PAINT");
446 lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
447 break;
448 case WM_PASTE:
449 DPRINTF_EDIT_MSG("WM_PASTE");
450 lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
451 break;
452 case WM_SETCURSOR:
454 * DPRINTF_EDIT_MSG("WM_SETCURSOR");
456 lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
457 break;
458 case WM_SETFOCUS:
459 DPRINTF_EDIT_MSG("WM_SETFOCUS");
460 lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
461 break;
462 case WM_SETFONT:
463 DPRINTF_EDIT_MSG("WM_SETFONT");
464 lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
465 break;
466 case WM_SETREDRAW:
467 DPRINTF_EDIT_MSG("WM_SETREDRAW");
468 lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
469 break;
470 case WM_SETTEXT:
471 DPRINTF_EDIT_MSG("WM_SETTEXT");
472 lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
473 break;
474 case WM_SIZE:
475 DPRINTF_EDIT_MSG("WM_SIZE");
476 lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
477 break;
478 case WM_VSCROLL:
479 DPRINTF_EDIT_MSG("WM_VSCROLL");
480 lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
481 break;
482 default:
483 if (msg >= WM_USER)
484 fprintf(stdnimp, "edit: undocumented message %d >= WM_USER, please report.\n", msg);
485 lResult = DefWindowProc16(hwnd, msg, wParam, lParam);
486 break;
488 EDIT_ReleasePointer(wndPtr);
489 return lResult;
493 /*********************************************************************
495 * EDIT_BuildLineDefs
497 * Build array of pointers to text lines.
498 * Lines can end with '\0' (last line), nothing (if it is too long),
499 * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
502 static void EDIT_BuildLineDefs(WND *wndPtr)
504 EDITSTATE *es = EDITSTATEPTR(wndPtr);
505 char *text = EDIT_GetPasswordPointer(wndPtr);
506 int ww = EDIT_GetWndWidth(wndPtr);
507 HDC hdc;
508 HFONT hFont;
509 HFONT oldFont = 0;
510 char *start, *cp;
511 int prev, next;
512 int width;
513 int length;
514 LINE_END ending;
516 hdc = GetDC(wndPtr->hwndSelf);
517 hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
518 if (hFont)
519 oldFont = SelectObject(hdc, hFont);
521 if (!IsMultiLine(wndPtr)) {
522 es->LineCount = 1;
523 es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
524 es->LineDefs[0].offset = 0;
525 es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
526 es->LineDefs[0].ending = END_0;
527 es->TextWidth = LOWORD(GetTabbedTextExtent(hdc, text,
528 es->LineDefs[0].length,
529 es->NumTabStops, es->TabStops));
530 } else {
531 es->LineCount = 0;
532 start = text;
533 do {
534 if (!(cp = strstr(start, "\r\n"))) {
535 ending = END_0;
536 length = strlen(start);
537 } else if ((cp > start) && (*(cp - 1) == '\r')) {
538 ending = END_SOFT;
539 length = cp - start - 1;
540 } else {
541 ending = END_HARD;
542 length = cp - start;
544 width = LOWORD(GetTabbedTextExtent(hdc, start, length,
545 es->NumTabStops, es->TabStops));
547 if (IsWordWrap(wndPtr) && (width > ww)) {
548 next = 0;
549 do {
550 prev = next;
551 next = EDIT_CallWordBreakProc(wndPtr, start,
552 prev + 1, length, WB_RIGHT);
553 width = LOWORD(GetTabbedTextExtent(hdc, start, next,
554 es->NumTabStops, es->TabStops));
555 } while (width <= ww);
556 if (!prev) {
557 next = 0;
558 do {
559 prev = next;
560 next++;
561 width = LOWORD(GetTabbedTextExtent(hdc, start, next,
562 es->NumTabStops, es->TabStops));
563 } while (width <= ww);
564 if(!prev) prev = 1;
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 width = LOWORD(GetTabbedTextExtent(hdc, start, length,
574 es->NumTabStops, es->TabStops));
577 es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF));
578 es->LineDefs[es->LineCount].offset = start - text;
579 es->LineDefs[es->LineCount].length = length;
580 es->LineDefs[es->LineCount].ending = ending;
581 es->LineCount++;
582 es->TextWidth = MAX(es->TextWidth, width);
584 start += length;
585 switch (ending) {
586 case END_SOFT:
587 start += 3;
588 break;
589 case END_HARD:
590 start += 2;
591 break;
592 case END_DELIMIT:
593 start++;
594 break;
595 default:
596 break;
598 } while (*start || (ending == END_SOFT) || (ending == END_HARD));
600 if (hFont)
601 SelectObject(hdc, oldFont);
602 ReleaseDC(wndPtr->hwndSelf, hdc);
604 free(text);
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((FARPROC16)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_GetPasswordPointer
762 static char *EDIT_GetPasswordPointer(WND *wndPtr)
764 EDITSTATE *es = EDITSTATEPTR(wndPtr);
765 char *text = xstrdup(EDIT_GetPointer(wndPtr));
766 char *p;
768 if(es->PasswordChar) {
769 p = text;
770 while(*p != '\0') {
771 if(*p != '\r' && *p != '\n')
772 *p = es->PasswordChar;
773 p++;
776 return text;
780 /*********************************************************************
782 * EDIT_GetRect
784 * Beware: This is not the function called on EM_GETRECT.
785 * It expects a (LPRECT) in lParam, not a (SEGPTR).
786 * It is used internally, as if there were no pointer difficulties.
789 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
791 GetClientRect16( wndPtr->hwndSelf, (LPRECT16)lParam );
792 return 0L;
796 /*********************************************************************
798 * EDIT_GetRedraw
801 static BOOL EDIT_GetRedraw(WND *wndPtr)
803 EDITSTATE *es = EDITSTATEPTR(wndPtr);
805 return es->Redraw;
809 /*********************************************************************
811 * EDIT_GetTextWidth
814 static UINT EDIT_GetTextWidth(WND *wndPtr)
816 EDITSTATE *es = EDITSTATEPTR(wndPtr);
818 return es->TextWidth;
822 /*********************************************************************
824 * EDIT_GetVisibleLineCount
827 static UINT EDIT_GetVisibleLineCount(WND *wndPtr)
829 RECT16 rc;
831 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
832 return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
836 /*********************************************************************
838 * EDIT_GetWndWidth
841 static UINT EDIT_GetWndWidth(WND *wndPtr)
843 RECT16 rc;
845 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
846 return rc.right - rc.left;
850 /*********************************************************************
852 * EDIT_GetXOffset
855 static UINT EDIT_GetXOffset(WND *wndPtr)
857 EDITSTATE *es = EDITSTATEPTR(wndPtr);
859 return es->XOffset;
863 /*********************************************************************
865 * EDIT_InvalidateText
867 * Invalidate the text from offset start upto, but not including,
868 * offset end. Useful for (re)painting the selection.
869 * Regions outside the linewidth are not invalidated.
870 * end == -1 means end == TextLength.
871 * start and end need not be ordered.
874 static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end)
876 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
877 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
878 UINT sl;
879 UINT el;
880 UINT sc;
881 UINT ec;
882 RECT16 rcWnd;
883 RECT16 rcLine;
884 RECT16 rcUpdate;
885 UINT l;
887 if (end == start )
888 return;
890 if ((INT)end == -1)
891 end = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
892 ORDER_UINT(start, end);
893 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, start, 0L);
894 el = (UINT)EDIT_EM_LineFromChar(wndPtr, end, 0L);
895 if ((el < fv) || (sl > fv + vlc))
896 return;
898 sc = start - (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L);
899 ec = end - (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
900 if (sl < fv) {
901 sl = fv;
902 sc = 0;
904 if (el > fv + vlc) {
905 el = fv + vlc;
906 ec = (UINT)EDIT_EM_LineLength(wndPtr,
907 (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L), 0L);
909 EDIT_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
910 if (sl == el) {
911 EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
912 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
913 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
914 } else {
915 EDIT_GetLineRect(wndPtr, sl, sc,
916 (UINT)EDIT_EM_LineLength(wndPtr,
917 (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L), 0L),
918 &rcLine);
919 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
920 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
921 for (l = sl + 1 ; l < el ; l++) {
922 EDIT_GetLineRect(wndPtr, l, 0,
923 (UINT)EDIT_EM_LineLength(wndPtr,
924 (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L), 0L),
925 &rcLine);
926 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
927 InvalidateRect16(wndPtr->hwndSelf, &rcUpdate, FALSE);
929 EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
930 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
931 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
936 /*********************************************************************
938 * EDIT_LineFromWndY
940 * Calculates, for a given Y-coordinate on the screen, the line.
943 static UINT EDIT_LineFromWndY(WND *wndPtr, INT y)
945 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
946 UINT lh = EDIT_GetLineHeight(wndPtr);
947 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
949 return MAX(0, MIN(lc - 1, y / lh + fv));
953 /*********************************************************************
955 * EDIT_MakeFit
957 * Try to fit size + 1 bytes in the buffer. Constrain to limits.
960 static BOOL EDIT_MakeFit(WND *wndPtr, UINT size)
962 EDITSTATE *es = EDITSTATEPTR(wndPtr);
964 if (size <= es->BufSize)
965 return TRUE;
966 if (size > es->BufLimit)
967 return FALSE;
968 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
969 if (size > es->BufLimit)
970 size = es->BufLimit;
972 dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
974 if (LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, size + 1, LMEM_MOVEABLE)) {
975 es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1, es->BufLimit);
976 return TRUE;
977 } else
978 return FALSE;
982 /*********************************************************************
984 * EDIT_MoveBackward
987 static void EDIT_MoveBackward(WND *wndPtr, BOOL extend)
989 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
990 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
991 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
992 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
994 if (e - li == 0) {
995 if (l) {
996 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
997 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
999 } else
1000 e--;
1001 if (!extend)
1002 s = e;
1003 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1007 /*********************************************************************
1009 * EDIT_MoveDownward
1012 static void EDIT_MoveDownward(WND *wndPtr, BOOL extend)
1014 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1015 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1016 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1017 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1018 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1019 INT x;
1021 if (l < lc - 1) {
1022 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1023 l++;
1024 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1025 EDIT_ColFromWndX(wndPtr, l, x);
1027 if (!extend)
1028 s = e;
1029 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1033 /*********************************************************************
1035 * EDIT_MoveEnd
1038 static void EDIT_MoveEnd(WND *wndPtr, BOOL extend)
1040 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1041 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1042 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1043 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1044 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1046 e = li + ll;
1047 if (!extend)
1048 s = e;
1049 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1053 /*********************************************************************
1055 * EDIT_MoveForward
1058 static void EDIT_MoveForward(WND *wndPtr, BOOL extend)
1060 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1061 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1062 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1063 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1064 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1065 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1067 if (e - li == ll) {
1068 if (l != lc - 1)
1069 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1070 } else
1071 e++;
1072 if (!extend)
1073 s = e;
1074 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1078 /*********************************************************************
1080 * EDIT_MoveHome
1082 * Home key: move to beginning of line.
1085 static void EDIT_MoveHome(WND *wndPtr, BOOL extend)
1087 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1088 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1089 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1090 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1092 e = li;
1093 if (!extend)
1094 s = e;
1095 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1099 /*********************************************************************
1101 * EDIT_MovePageDown
1104 static void EDIT_MovePageDown(WND *wndPtr, BOOL extend)
1106 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1107 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1108 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1109 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1110 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1111 INT x;
1113 if (l < lc - 1) {
1114 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1115 l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
1116 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1117 EDIT_ColFromWndX(wndPtr, l, x);
1119 if (!extend)
1120 s = e;
1121 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1125 /*********************************************************************
1127 * EDIT_MovePageUp
1130 static void EDIT_MovePageUp(WND *wndPtr, BOOL extend)
1132 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1133 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1134 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1135 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1136 INT x;
1138 if (l) {
1139 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1140 l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
1141 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1142 EDIT_ColFromWndX(wndPtr, l, x);
1144 if (!extend)
1145 s = e;
1146 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1150 /*********************************************************************
1152 * EDIT_MoveUpward
1155 static void EDIT_MoveUpward(WND *wndPtr, BOOL extend)
1157 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1158 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1159 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1160 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1161 INT x;
1163 if (l) {
1164 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1165 l--;
1166 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1167 EDIT_ColFromWndX(wndPtr, l, x);
1169 if (!extend)
1170 s = e;
1171 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1175 /*********************************************************************
1177 * EDIT_MoveWordBackward
1180 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend)
1182 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1183 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1184 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1185 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1186 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1187 char *text;
1189 if (e - li == 0) {
1190 if (l) {
1191 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
1192 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1194 } else {
1195 text = EDIT_GetPointer(wndPtr);
1196 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1197 text + li, e - li, ll, WB_LEFT);
1199 if (!extend)
1200 s = e;
1201 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1205 /*********************************************************************
1207 * EDIT_MoveWordForward
1210 static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend)
1212 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1213 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1214 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1215 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1216 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1217 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1218 char *text;
1220 if (e - li == ll) {
1221 if (l != lc - 1)
1222 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1223 } else {
1224 text = EDIT_GetPointer(wndPtr);
1225 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1226 text + li, e - li + 1, ll, WB_RIGHT);
1228 if (!extend)
1229 s = e;
1230 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1234 /*********************************************************************
1236 * EDIT_PaintLine
1239 static void EDIT_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev)
1241 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1242 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1243 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1244 UINT li;
1245 UINT ll;
1246 UINT s;
1247 UINT e;
1248 INT x;
1249 INT y;
1251 if ((line < fv) || (line > fv + vlc) || (line >= lc))
1252 return;
1254 dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
1256 x = EDIT_WndXFromCol(wndPtr, line, 0);
1257 y = EDIT_WndYFromLine(wndPtr, line);
1258 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1259 ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1260 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1261 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1262 ORDER_UINT(s, e);
1263 s = MIN(li + ll, MAX(li, s));
1264 e = MIN(li + ll, MAX(li, e));
1265 if (rev && (s != e) &&
1266 ((GetFocus() == wndPtr->hwndSelf) ||
1267 (wndPtr->dwStyle & ES_NOHIDESEL))) {
1268 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
1269 x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
1270 x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
1271 } else
1272 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
1276 /*********************************************************************
1278 * EDIT_PaintText
1281 static UINT EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev)
1283 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1284 COLORREF BkColor;
1285 COLORREF TextColor;
1286 UINT ret;
1287 char *text;
1288 UINT li;
1289 UINT xoff;
1291 if (!count)
1292 return 0;
1293 BkColor = GetBkColor(hdc);
1294 TextColor = GetTextColor(hdc);
1295 if (rev) {
1296 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1297 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1299 text = EDIT_GetPasswordPointer(wndPtr);
1300 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1301 xoff = EDIT_GetXOffset(wndPtr);
1302 ret = LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
1303 es->NumTabStops, es->TabStops, -xoff));
1304 free(text);
1305 if (rev) {
1306 SetBkColor(hdc, BkColor);
1307 SetTextColor(hdc, TextColor);
1309 return ret;
1313 /*********************************************************************
1315 * EDIT_ReleasePointer
1317 * This is the only helper function that can be called with es = NULL.
1318 * It is called at the end of EditWndProc() to unlock the buffer.
1321 static void EDIT_ReleasePointer(WND *wndPtr)
1323 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1325 if (!es)
1326 return;
1327 if (es->text && es->hBuf)
1328 LOCAL_Unlock(wndPtr->hInstance, es->hBuf);
1329 es->text = NULL;
1333 /*********************************************************************
1335 * EDIT_ReplaceSel
1337 * Beware: This is not the function called on EM_REPLACESEL.
1338 * It expects a (char *) in lParam, not a (SEGPTR).
1339 * It is used internally, as if there were no pointer difficulties.
1342 static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1344 const char *str = (char *)lParam;
1345 int strl = strlen(str);
1346 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1347 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1348 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1349 int i;
1350 char *p;
1351 char *text;
1352 BOOL redraw;
1354 ORDER_UINT(s,e);
1355 if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
1356 EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
1357 return 0L;
1359 redraw = EDIT_GetRedraw(wndPtr);
1360 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
1361 EDIT_WM_Clear(wndPtr, 0, 0L);
1362 tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1363 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1364 text = EDIT_GetPointer(wndPtr);
1365 for (p = text + tl ; p >= text + e ; p--)
1366 p[strl] = p[0];
1367 for (i = 0 , p = text + e ; i < strl ; i++)
1368 p[i] = str[i];
1369 if(IsUpper(wndPtr))
1370 AnsiUpperBuff(p, strl);
1371 else if(IsLower(wndPtr))
1372 AnsiLowerBuff(p, strl);
1373 EDIT_BuildLineDefs(wndPtr);
1374 e += strl;
1375 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(e, e));
1376 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
1377 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
1378 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
1379 if (redraw) {
1380 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
1381 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
1383 return 0L;
1387 /*********************************************************************
1389 * EDIT_ScrollIntoView
1391 * Makes sure the caret is visible.
1394 static void EDIT_ScrollIntoView(WND *wndPtr)
1396 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1397 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1398 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1399 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1400 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1401 UINT ww = EDIT_GetWndWidth(wndPtr);
1402 UINT cw = EDIT_GetAveCharWidth(wndPtr);
1403 INT x = EDIT_WndXFromCol(wndPtr, l, e - li);
1404 int dy = 0;
1405 int dx = 0;
1407 if (l >= fv + vlc)
1408 dy = l - vlc + 1 - fv;
1409 if (l < fv)
1410 dy = l - fv;
1411 if (x < 0)
1412 dx = x - ww / HSCROLL_FRACTION / cw * cw;
1413 if (x > ww)
1414 dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
1415 if (dy || dx) {
1416 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, dx));
1417 if (dy)
1418 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
1419 if (dx)
1420 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
1425 /*********************************************************************
1427 * EDIT_WndXFromCol
1429 * Calculates, for a given line and column, the X-coordinate on the screen.
1432 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col)
1434 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1435 char *text = EDIT_GetPasswordPointer(wndPtr);
1436 INT ret;
1437 HDC hdc;
1438 HFONT hFont;
1439 HFONT oldFont = 0;
1440 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1441 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1442 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1443 UINT xoff = EDIT_GetXOffset(wndPtr);
1445 hdc = GetDC(wndPtr->hwndSelf);
1446 hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
1447 if (hFont)
1448 oldFont = SelectObject(hdc, hFont);
1449 line = MAX(0, MIN(line, lc - 1));
1450 col = MIN(col, ll);
1451 ret = LOWORD(GetTabbedTextExtent(hdc,
1452 text + li, col,
1453 es->NumTabStops, es->TabStops)) - xoff;
1454 if (hFont)
1455 SelectObject(hdc, oldFont);
1456 ReleaseDC(wndPtr->hwndSelf, hdc);
1457 free(text);
1458 return ret;
1462 /*********************************************************************
1464 * EDIT_WndYFromLine
1466 * Calculates, for a given line, the Y-coordinate on the screen.
1469 static INT EDIT_WndYFromLine(WND *wndPtr, UINT line)
1471 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1472 UINT lh = EDIT_GetLineHeight(wndPtr);
1474 return (line - fv) * lh;
1478 /*********************************************************************
1480 * EDIT_WordBreakProc
1482 * Find the beginning of words.
1483 * Note: unlike the specs for a WordBreakProc, this function only
1484 * allows to be called without linebreaks between s[0] upto
1485 * s[count - 1]. Remember it is only called
1486 * internally, so we can decide this for ourselves.
1489 static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action)
1491 INT ret = 0;
1493 dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%d"
1494 ", count=%d, action=%d\n", s, index, count, action);
1496 switch (action) {
1497 case WB_LEFT:
1498 if (!count)
1499 break;
1500 if (index)
1501 index--;
1502 if (s[index] == ' ') {
1503 while (index && (s[index] == ' '))
1504 index--;
1505 if (index) {
1506 while (index && (s[index] != ' '))
1507 index--;
1508 if (s[index] == ' ')
1509 index++;
1511 } else {
1512 while (index && (s[index] != ' '))
1513 index--;
1514 if (s[index] == ' ')
1515 index++;
1517 ret = index;
1518 break;
1519 case WB_RIGHT:
1520 if (!count)
1521 break;
1522 if (index)
1523 index--;
1524 if (s[index] == ' ')
1525 while ((index < count) && (s[index] == ' ')) index++;
1526 else {
1527 while (s[index] && (s[index] != ' ') && (index < count))
1528 index++;
1529 while ((s[index] == ' ') && (index < count)) index++;
1531 ret = index;
1532 break;
1533 case WB_ISDELIMITER:
1534 ret = (s[index] == ' ');
1535 break;
1536 default:
1537 fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
1538 break;
1540 return ret;
1544 /*********************************************************************
1546 * EM_CANUNDO
1549 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1551 return 0L;
1555 /*********************************************************************
1557 * EM_EMPTYUNDOBUFFER
1560 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1562 return 0L;
1566 /*********************************************************************
1568 * EM_FMTLINES
1571 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1573 fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented.\n");
1574 return wParam ? -1L : 0L;
1578 /*********************************************************************
1580 * EM_GETFIRSTVISIBLELINE
1583 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1585 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1587 return (LRESULT)es->FirstVisibleLine;
1591 /*********************************************************************
1593 * EM_GETHANDLE
1596 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1598 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1600 return (LRESULT)es->hBuf;
1604 /*********************************************************************
1606 * EM_GETLINE
1609 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1611 char *text;
1612 char *src;
1613 char *dst;
1614 UINT len;
1615 UINT i;
1616 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1618 if (!IsMultiLine(wndPtr))
1619 wParam = 0;
1620 if ((UINT)wParam >= lc)
1621 return 0L;
1622 text = EDIT_GetPointer(wndPtr);
1623 src = text + (UINT)EDIT_EM_LineIndex(wndPtr, wParam, 0L);
1624 dst = (char *)PTR_SEG_TO_LIN(lParam);
1625 len = MIN(*(WORD *)dst, (UINT)EDIT_EM_LineLength(wndPtr, wParam, 0L));
1626 for (i = 0 ; i < len ; i++) {
1627 *dst = *src;
1628 src++;
1629 dst++;
1631 return (LRESULT)len;
1635 /*********************************************************************
1637 * EM_GETLINECOUNT
1640 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1642 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1644 return (LRESULT)es->LineCount;
1648 /*********************************************************************
1650 * EM_GETMODIFY
1653 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1655 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1657 return (LRESULT)es->TextChanged;
1661 /*********************************************************************
1663 * EM_GETPASSWORDCHAR
1666 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1668 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1670 return (LRESULT)es->PasswordChar;
1674 /*********************************************************************
1676 * EM_GETRECT
1679 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1681 return EDIT_GetRect(wndPtr, wParam, (LPARAM)PTR_SEG_TO_LIN(lParam));
1685 /*********************************************************************
1687 * EM_GETSEL
1690 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1692 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1694 return MAKELONG(es->SelStart, es->SelEnd);
1698 /*********************************************************************
1700 * EM_GETTHUMB
1702 * FIXME: undocumented: is this right ?
1705 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1707 return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L),
1708 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L));
1712 /*********************************************************************
1714 * EM_GETWORDBREAKPROC
1717 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1719 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1721 return (LRESULT)es->WordBreakProc;
1725 /*********************************************************************
1727 * EM_LIMITTEXT
1730 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1732 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1734 if (IsMultiLine(wndPtr)) {
1735 if (wParam)
1736 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_MULTI);
1737 else
1738 es->BufLimit = BUFLIMIT_MULTI;
1739 } else {
1740 if (wParam)
1741 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_SINGLE);
1742 else
1743 es->BufLimit = BUFLIMIT_SINGLE;
1745 return 0L;
1749 /*********************************************************************
1751 * EM_LINEFROMCHAR
1754 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1756 UINT l;
1758 if (!IsMultiLine(wndPtr))
1759 return 0L;
1760 if ((INT)wParam == -1)
1761 wParam = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1762 l = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
1763 while ((UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam)
1764 l--;
1765 return (LRESULT)l;
1769 /*********************************************************************
1771 * EM_LINEINDEX
1774 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1776 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1777 UINT e;
1778 UINT l;
1779 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1781 if ((INT)wParam == -1) {
1782 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1783 l = lc - 1;
1784 while (es->LineDefs[l].offset > e)
1785 l--;
1786 return (LRESULT)es->LineDefs[l].offset;
1788 if ((UINT)wParam >= lc)
1789 return -1L;
1790 return (LRESULT)es->LineDefs[(UINT)wParam].offset;
1794 /*********************************************************************
1796 * EM_LINELENGTH
1799 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1801 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1802 UINT s;
1803 UINT e;
1804 UINT sl;
1805 UINT el;
1807 if (!IsMultiLine(wndPtr))
1808 return (LRESULT)es->LineDefs[0].length;
1809 if ((INT)wParam == -1) {
1810 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1811 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1812 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, s, 0L);
1813 el = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1814 return (LRESULT)(s - es->LineDefs[sl].offset +
1815 es->LineDefs[el].offset +
1816 es->LineDefs[el].length - e);
1818 return (LRESULT)es->LineDefs[(UINT)EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length;
1822 /*********************************************************************
1824 * EM_LINESCROLL
1827 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1829 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1830 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1831 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1832 UINT nfv = MAX(0, fv + (INT)LOWORD(lParam));
1833 UINT xoff = EDIT_GetXOffset(wndPtr);
1834 UINT nxoff = MAX(0, xoff + (INT)HIWORD(lParam));
1835 UINT tw = EDIT_GetTextWidth(wndPtr);
1836 INT dx;
1837 INT dy;
1838 POINT16 pos;
1839 HRGN hRgn;
1841 if (nfv >= lc)
1842 nfv = lc - 1;
1844 if (nxoff >= tw)
1845 nxoff = tw;
1846 dx = xoff - nxoff;
1847 dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
1848 if (dx || dy) {
1849 if (wndPtr->hwndSelf == GetFocus())
1850 HideCaret(wndPtr->hwndSelf);
1851 if (EDIT_GetRedraw(wndPtr)) {
1852 hRgn = CreateRectRgn(0, 0, 0, 0);
1853 GetUpdateRgn(wndPtr->hwndSelf, hRgn, FALSE);
1854 ValidateRgn(wndPtr->hwndSelf, 0);
1855 OffsetRgn(hRgn, dx, dy);
1856 InvalidateRgn( wndPtr->hwndSelf, hRgn, TRUE );
1857 DeleteObject(hRgn);
1858 ScrollWindow(wndPtr->hwndSelf, dx, dy, NULL, NULL);
1860 es->FirstVisibleLine = nfv;
1861 es->XOffset = nxoff;
1862 if (IsVScrollBar(wndPtr))
1863 SetScrollPos(wndPtr->hwndSelf, SB_VERT,
1864 EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1865 if (IsHScrollBar(wndPtr))
1866 SetScrollPos(wndPtr->hwndSelf, SB_HORZ,
1867 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1868 if (wndPtr->hwndSelf == GetFocus()) {
1869 GetCaretPos16(&pos);
1870 SetCaretPos(pos.x + dx, pos.y + dy);
1871 ShowCaret(wndPtr->hwndSelf);
1874 return -1L;
1878 /*********************************************************************
1880 * EM_REPLACESEL
1883 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1885 return (LRESULT)EDIT_ReplaceSel(wndPtr, wParam,
1886 (LPARAM)(char *)PTR_SEG_TO_LIN(lParam));
1890 /*********************************************************************
1892 * EM_SCROLL
1894 * FIXME: undocumented message.
1897 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1899 fprintf(stdnimp, "edit: EM_SCROLL: message not implemented (undocumented), please report.\n");
1900 return 0L;
1904 /*********************************************************************
1906 * EM_SETHANDLE
1909 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1911 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1913 if (IsMultiLine(wndPtr)) {
1914 EDIT_ReleasePointer(wndPtr);
1916 * old buffer is freed by caller
1918 es->hBuf = (HLOCAL16)wParam;
1919 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
1920 es->LineCount = 0;
1921 es->FirstVisibleLine = 0;
1922 es->SelStart = es->SelEnd = 0;
1923 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
1924 EDIT_EM_SetModify(wndPtr, FALSE, 0L);
1925 EDIT_BuildLineDefs(wndPtr);
1926 if (EDIT_GetRedraw(wndPtr))
1927 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
1928 EDIT_ScrollIntoView(wndPtr);
1930 return 0L;
1934 /*********************************************************************
1936 * EM_SETMODIFY
1939 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1941 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1943 es->TextChanged = (BOOL)wParam;
1944 return 0L;
1948 /*********************************************************************
1950 * EM_SETPASSWORDCHAR
1953 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1955 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1957 es->PasswordChar = (char)wParam;
1958 return 0L;
1962 /*********************************************************************
1964 * EM_SETREADONLY
1967 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1969 if ((BOOL)wParam)
1970 wndPtr->dwStyle |= ES_READONLY;
1971 else
1972 wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
1973 return 0L;
1977 /*********************************************************************
1979 * EM_SETRECT
1982 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1984 fprintf(stdnimp,"edit: EM_SETRECT: message not implemented, please report.\n");
1985 return 0L;
1989 /*********************************************************************
1991 * EM_SETRECTNP
1994 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1996 fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented, please report.\n");
1997 return 0L;
2001 /*********************************************************************
2003 * EM_SETSEL
2006 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2008 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2009 UINT ns = LOWORD(lParam);
2010 UINT ne = HIWORD(lParam);
2011 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2012 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2013 UINT el;
2014 UINT eli;
2015 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
2017 if ((INT)ns == -1) {
2018 ns = e;
2019 ne = e;
2021 else {
2022 ns = MIN(ns, tl);
2023 ne = MIN(ne, tl);
2025 es->SelStart = ns;
2026 es->SelEnd = ne;
2027 if (wndPtr->hwndSelf == GetFocus()) {
2028 el = (UINT)EDIT_EM_LineFromChar(wndPtr, ne, 0L);
2029 eli = (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
2030 SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - eli),
2031 EDIT_WndYFromLine(wndPtr, el));
2033 if (!wParam)
2034 EDIT_ScrollIntoView(wndPtr);
2035 if (EDIT_GetRedraw(wndPtr)) {
2036 ORDER_UINT(s, e);
2037 ORDER_UINT(s, ns);
2038 ORDER_UINT(s, ne);
2039 ORDER_UINT(e, ns);
2040 ORDER_UINT(e, ne);
2041 ORDER_UINT(ns, ne);
2042 if (e != ns) {
2043 EDIT_InvalidateText(wndPtr, s, e);
2044 EDIT_InvalidateText(wndPtr, ns, ne);
2045 } else
2046 EDIT_InvalidateText(wndPtr, s, ne);
2048 return -1L;
2052 /*********************************************************************
2054 * EM_SETTABSTOPS
2057 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2059 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2061 if (!IsMultiLine(wndPtr))
2062 return 0L;
2063 if (es->TabStops)
2064 free(es->TabStops);
2065 es->NumTabStops = (UINT)wParam;
2066 if (!wParam)
2067 es->TabStops = NULL;
2068 else {
2069 es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
2070 memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam),
2071 (UINT)wParam * sizeof(INT16));
2073 return 1L;
2077 /*********************************************************************
2079 * EM_SETWORDBREAKPROC
2082 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2084 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2086 es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
2087 return 0L;
2091 /*********************************************************************
2093 * EM_UNDO
2096 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2098 return 0L;
2102 /*********************************************************************
2104 * WM_CHAR
2107 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2109 char str[2];
2110 unsigned char c = (unsigned char)wParam;
2112 switch (c) {
2113 case '\r':
2114 case '\n':
2115 if (IsMultiLine(wndPtr)) {
2116 if (IsReadOnly(wndPtr)) {
2117 EDIT_MoveHome(wndPtr, FALSE);
2118 EDIT_MoveDownward(wndPtr, FALSE);
2119 } else
2120 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n");
2122 break;
2123 case '\t':
2124 if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
2125 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\t");
2126 break;
2127 default:
2128 if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
2129 str[0] = c;
2130 str[1] = '\0';
2131 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)str);
2133 break;
2135 return 0L;
2139 /*********************************************************************
2141 * WM_CLEAR
2144 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2146 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2147 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2148 char *text;
2149 BOOL redraw;
2151 if (s != e) {
2152 redraw = EDIT_GetRedraw(wndPtr);
2153 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
2154 ORDER_UINT(s, e);
2155 text = EDIT_GetPointer(wndPtr);
2156 strcpy(text + s, text + e);
2157 EDIT_BuildLineDefs(wndPtr);
2158 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, s));
2159 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2160 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2161 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
2162 if (redraw) {
2163 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2164 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2167 return -1L;
2171 /*********************************************************************
2173 * WM_COPY
2176 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2178 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2179 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2180 HGLOBAL hdst;
2181 char *text;
2182 char *dst;
2183 char *src;
2184 int i;
2186 if (e == s)
2187 return -1L;
2188 ORDER_UINT(s, e);
2189 hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
2190 dst = GlobalLock16(hdst);
2191 text = EDIT_GetPointer(wndPtr);
2192 src = text + s;
2193 for (i = 0 ; i < e - s ; i++)
2194 *dst++ = *src++;
2195 *dst = '\0';
2196 GlobalUnlock16(hdst);
2197 OpenClipboard(wndPtr->hwndSelf);
2198 EmptyClipboard();
2199 SetClipboardData(CF_TEXT, hdst);
2200 CloseClipboard();
2201 return -1L;
2205 /*********************************************************************
2207 * WM_CREATE
2210 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2212 CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
2213 EDITSTATE *es;
2214 char *text;
2216 es = xmalloc(sizeof(EDITSTATE));
2217 memset(es, 0, sizeof(EDITSTATE));
2218 *(EDITSTATE **)wndPtr->wExtra = es;
2220 if (cs->style & WS_VSCROLL)
2221 cs->style |= ES_AUTOVSCROLL;
2222 if (cs->style & WS_HSCROLL)
2223 cs->style |= ES_AUTOHSCROLL;
2225 /* remove the WS_CAPTION style if it has been set - this is really a */
2226 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
2227 if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
2228 cs->style ^= WS_DLGFRAME;
2230 if (IsMultiLine(wndPtr)) {
2231 es->BufSize = BUFSTART_MULTI;
2232 es->BufLimit = BUFLIMIT_MULTI;
2233 es->PasswordChar = '\0';
2234 } else {
2235 es->BufSize = BUFSTART_SINGLE;
2236 es->BufLimit = BUFLIMIT_SINGLE;
2237 es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
2239 if (!LOCAL_HeapSize(wndPtr->hInstance)) {
2240 if (!LocalInit(wndPtr->hInstance, 0,
2241 GlobalSize16(wndPtr->hInstance))) {
2242 fprintf(stderr, "edit: WM_CREATE: could not initialize local heap\n");
2243 return -1L;
2245 dprintf_edit(stddeb, "edit: WM_CREATE: local heap initialized\n");
2247 if (!(es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1))) {
2248 fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
2249 return -1L;
2251 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
2252 text = EDIT_GetPointer(wndPtr);
2253 *text = '\0';
2254 EDIT_BuildLineDefs(wndPtr);
2255 EDIT_WM_SetFont(wndPtr, 0, 0L);
2256 if (cs->lpszName)
2257 EDIT_EM_ReplaceSel(wndPtr, FALSE, (LPARAM)cs->lpszName);
2258 EDIT_WM_SetRedraw(wndPtr, TRUE, 0L);
2259 return 0L;
2263 /*********************************************************************
2265 * WM_CUT
2268 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2270 EDIT_WM_Copy(wndPtr, 0, 0L);
2271 EDIT_WM_Clear(wndPtr, 0, 0L);
2272 return -1L;
2276 /*********************************************************************
2278 * WM_DESTROY
2281 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2283 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2285 free(es->LineDefs);
2286 if (es->TabStops)
2287 free(es->TabStops);
2288 EDIT_ReleasePointer(wndPtr);
2289 LOCAL_Free(wndPtr->hInstance, es->hBuf);
2290 free(es);
2291 *(EDITSTATE **)&wndPtr->wExtra = NULL;
2292 return 0L;
2296 /*********************************************************************
2298 * WM_ENABLE
2301 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2303 EDIT_InvalidateText(wndPtr, 0, -1);
2304 return 0L;
2308 /*********************************************************************
2310 * WM_ERASEBKGND
2313 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2315 HBRUSH hBrush;
2316 RECT16 rc;
2318 hBrush = (HBRUSH)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
2319 if (!hBrush)
2320 hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
2322 GetClientRect16(wndPtr->hwndSelf, &rc);
2323 IntersectClipRect((HDC)wParam, rc.left, rc.top, rc.right, rc.bottom);
2324 GetClipBox16((HDC)wParam, &rc);
2326 * FIXME: specs say that we should UnrealizeObject() the brush,
2327 * but the specs of UnrealizeObject() say that we shouldn't
2328 * unrealize a stock object. The default brush that
2329 * DefWndProc() returns is ... a stock object.
2331 FillRect16((HDC)wParam, &rc, hBrush);
2332 return -1L;
2336 /*********************************************************************
2338 * WM_GETDLGCODE
2341 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2343 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
2347 /*********************************************************************
2349 * WM_GETFONT
2352 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2354 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2356 return (LRESULT)es->hFont;
2360 /*********************************************************************
2362 * WM_GETTEXT
2365 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2367 char *text = EDIT_GetPointer(wndPtr);
2368 int len;
2369 LRESULT lResult = 0L;
2371 len = strlen(text);
2372 if ((UINT)wParam > len) {
2373 strcpy((char *)PTR_SEG_TO_LIN(lParam), text);
2374 lResult = (LRESULT)len ;
2376 return lResult;
2380 /*********************************************************************
2382 * WM_GETTEXTLENGTH
2385 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2387 char *text = EDIT_GetPointer(wndPtr);
2389 return (LRESULT)strlen(text);
2393 /*********************************************************************
2395 * WM_HSCROLL
2397 * FIXME: scrollbar code itself is broken, so this one is a hack.
2400 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2402 UINT ww = EDIT_GetWndWidth(wndPtr);
2403 UINT tw = EDIT_GetTextWidth(wndPtr);
2404 UINT cw = EDIT_GetAveCharWidth(wndPtr);
2405 UINT xoff = EDIT_GetXOffset(wndPtr);
2406 INT dx = 0;
2407 BOOL not = TRUE;
2408 LRESULT ret = 0L;
2410 switch (wParam) {
2411 case SB_LINELEFT:
2412 dx = -cw;
2413 break;
2414 case SB_LINERIGHT:
2415 dx = cw;
2416 break;
2417 case SB_PAGELEFT:
2418 dx = -ww / HSCROLL_FRACTION / cw * cw;
2419 break;
2420 case SB_PAGERIGHT:
2421 dx = ww / HSCROLL_FRACTION / cw * cw;
2422 break;
2423 case SB_LEFT:
2424 dx = -xoff;
2425 break;
2426 case SB_RIGHT:
2427 dx = tw - xoff;
2428 break;
2429 case SB_THUMBTRACK:
2431 * not = FALSE;
2433 case SB_THUMBPOSITION:
2434 dx = LOWORD(lParam) * tw / 100 - xoff;
2435 break;
2436 /* The next two are undocumented ! */
2437 case EM_GETTHUMB:
2438 ret = tw ? MAKELONG(xoff * 100 / tw, 0) : 0;
2439 break;
2440 case EM_LINESCROLL:
2441 dx = LOWORD(lParam);
2442 break;
2443 case SB_ENDSCROLL:
2444 default:
2445 break;
2447 if (dx) {
2448 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(0, dx));
2449 if (not)
2450 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
2452 return ret;
2456 /*********************************************************************
2458 * WM_KEYDOWN
2460 * Handling of special keys that don't produce a WM_CHAR
2461 * (i.e. non-printable keys) & Backspace & Delete
2464 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2466 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2467 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2468 BOOL shift;
2469 BOOL control;
2471 if (GetKeyState(VK_MENU) & 0x8000)
2472 return 0L;
2474 shift = GetKeyState(VK_SHIFT) & 0x8000;
2475 control = GetKeyState(VK_CONTROL) & 0x8000;
2477 switch (wParam) {
2478 case VK_LEFT:
2479 case VK_UP:
2480 if (IsMultiLine(wndPtr) && (wParam == VK_UP))
2481 EDIT_MoveUpward(wndPtr, shift);
2482 else
2483 if (control)
2484 EDIT_MoveWordBackward(wndPtr, shift);
2485 else
2486 EDIT_MoveBackward(wndPtr, shift);
2487 break;
2488 case VK_RIGHT:
2489 case VK_DOWN:
2490 if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
2491 EDIT_MoveDownward(wndPtr, shift);
2492 else if (control)
2493 EDIT_MoveWordForward(wndPtr, shift);
2494 else
2495 EDIT_MoveForward(wndPtr, shift);
2496 break;
2497 case VK_HOME:
2498 EDIT_MoveHome(wndPtr, shift);
2499 break;
2500 case VK_END:
2501 EDIT_MoveEnd(wndPtr, shift);
2502 break;
2503 case VK_PRIOR:
2504 if (IsMultiLine(wndPtr))
2505 EDIT_MovePageUp(wndPtr, shift);
2506 break;
2507 case VK_NEXT:
2508 if (IsMultiLine(wndPtr))
2509 EDIT_MovePageDown(wndPtr, shift);
2510 break;
2511 case VK_BACK:
2512 if (!IsReadOnly(wndPtr) && !control)
2513 if (e != s)
2514 EDIT_WM_Clear(wndPtr, 0, 0L);
2515 else
2516 EDIT_DelLeft(wndPtr);
2517 break;
2518 case VK_DELETE:
2519 if (!IsReadOnly(wndPtr) && !(shift && control))
2520 if (e != s) {
2521 if (shift)
2522 EDIT_WM_Cut(wndPtr, 0, 0L);
2523 else
2524 EDIT_WM_Clear(wndPtr, 0, 0L);
2525 } else {
2526 if (shift)
2527 EDIT_DelLeft(wndPtr);
2528 else if (control)
2529 EDIT_DelEnd(wndPtr);
2530 else
2531 EDIT_DelRight(wndPtr);
2533 break;
2534 case VK_INSERT:
2535 if (shift) {
2536 if (!IsReadOnly(wndPtr))
2537 EDIT_WM_Paste(wndPtr, 0, 0L);
2538 } else if (control)
2539 EDIT_WM_Copy(wndPtr, 0, 0L);
2540 break;
2542 return 0L;
2546 /*********************************************************************
2548 * WM_KILLFOCUS
2551 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2553 UINT s;
2554 UINT e;
2556 DestroyCaret();
2557 if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
2558 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2559 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2560 EDIT_InvalidateText(wndPtr, s, e);
2562 EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
2563 return 0L;
2567 /*********************************************************************
2569 * WM_LBUTTONDBLCLK
2571 * The caret position has been set on the WM_LBUTTONDOWN message
2574 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2576 UINT s;
2577 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2578 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
2579 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2580 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
2581 char *text = EDIT_GetPointer(wndPtr);
2583 s = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_LEFT);
2584 e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
2585 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2586 return 0L;
2590 /*********************************************************************
2592 * WM_LBUTTONDOWN
2595 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2597 INT x = (INT)LOWORD(lParam);
2598 INT y = (INT)HIWORD(lParam);
2599 UINT l = EDIT_LineFromWndY(wndPtr, y);
2600 UINT c;
2601 UINT s;
2602 UINT e;
2603 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2604 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2605 UINT li;
2607 SetFocus(wndPtr->hwndSelf);
2608 SetCapture(wndPtr->hwndSelf);
2609 l = MIN(fv + vlc - 1, MAX(fv, l));
2610 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
2611 c = EDIT_ColFromWndX(wndPtr, l, x);
2612 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2613 e = li + c;
2614 if (GetKeyState(VK_SHIFT) & 0x8000)
2615 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2616 else
2617 s = e;
2618 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2619 return 0L;
2623 /*********************************************************************
2625 * WM_LBUTTONUP
2628 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2630 if (GetCapture() == wndPtr->hwndSelf)
2631 ReleaseCapture();
2632 return 0L;
2636 /*********************************************************************
2638 * WM_MOUSEMOVE
2641 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2643 INT x;
2644 INT y;
2645 UINT l;
2646 UINT c;
2647 UINT s;
2648 UINT fv;
2649 UINT vlc;
2650 UINT li;
2652 if (GetCapture() == wndPtr->hwndSelf) {
2653 x = (INT)LOWORD(lParam);
2654 y = (INT)HIWORD(lParam);
2655 fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2656 vlc = EDIT_GetVisibleLineCount(wndPtr);
2657 l = EDIT_LineFromWndY(wndPtr, y);
2658 l = MIN(fv + vlc - 1, MAX(fv, l));
2659 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
2660 c = EDIT_ColFromWndX(wndPtr, l, x);
2661 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2662 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2663 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, li + c));
2665 return 0L;
2669 /*********************************************************************
2671 * WM_PAINT
2674 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2676 PAINTSTRUCT16 ps;
2677 UINT i;
2678 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2679 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2680 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2681 HDC16 hdc;
2682 HFONT hFont;
2683 HFONT oldFont = 0;
2684 RECT16 rc;
2685 RECT16 rcLine;
2686 RECT16 rcRgn;
2687 BOOL rev = IsWindowEnabled(wndPtr->hwndSelf) &&
2688 ((GetFocus() == wndPtr->hwndSelf) ||
2689 (wndPtr->dwStyle & ES_NOHIDESEL));
2691 hdc = BeginPaint16(wndPtr->hwndSelf, &ps);
2692 GetClientRect16(wndPtr->hwndSelf, &rc);
2693 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
2694 hFont = EDIT_WM_GetFont(wndPtr, 0, 0L);
2695 if (hFont)
2696 oldFont = SelectObject(hdc, hFont);
2697 EDIT_SEND_CTLCOLOR(wndPtr, hdc);
2698 if (!IsWindowEnabled(wndPtr->hwndSelf))
2699 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
2700 GetClipBox16(hdc, &rcRgn);
2701 for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
2702 EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
2703 if (IntersectRect16(&rc, &rcRgn, &rcLine))
2704 EDIT_PaintLine(wndPtr, hdc, i, rev);
2706 if (hFont)
2707 SelectObject(hdc, oldFont);
2708 EndPaint16(wndPtr->hwndSelf, &ps);
2709 return 0L;
2713 /*********************************************************************
2715 * WM_PASTE
2718 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2720 HGLOBAL hsrc;
2721 char *src;
2723 OpenClipboard(wndPtr->hwndSelf);
2724 if ((hsrc = GetClipboardData(CF_TEXT))) {
2725 src = (char *)GlobalLock16(hsrc);
2726 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)src);
2727 GlobalUnlock16(hsrc);
2729 CloseClipboard();
2730 return -1L;
2734 /*********************************************************************
2736 * WM_SETCURSOR
2739 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2741 if (LOWORD(lParam) == HTCLIENT) {
2742 SetCursor(LoadCursor16(0, IDC_IBEAM));
2743 return -1L;
2744 } else
2745 return 0L;
2749 /*********************************************************************
2751 * WM_SETFOCUS
2754 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2756 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2757 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2759 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2760 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, e));
2761 if(!(wndPtr->dwStyle & ES_NOHIDESEL))
2762 EDIT_InvalidateText(wndPtr, s, e);
2763 ShowCaret(wndPtr->hwndSelf);
2764 EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
2765 return 0L;
2769 /*********************************************************************
2771 * WM_SETFONT
2774 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2776 TEXTMETRIC16 tm;
2777 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2778 LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L);
2779 HDC hdc;
2780 HFONT oldFont = 0;
2782 es->hFont = (HFONT)wParam;
2783 hdc = GetDC(wndPtr->hwndSelf);
2784 if (es->hFont)
2785 oldFont = SelectObject(hdc, es->hFont);
2786 GetTextMetrics16(hdc, &tm);
2787 es->LineHeight = HIWORD(GetTextExtent(hdc, "X", 1));
2788 es->AveCharWidth = tm.tmAveCharWidth;
2789 if (es->hFont)
2790 SelectObject(hdc, oldFont);
2791 ReleaseDC(wndPtr->hwndSelf, hdc);
2792 EDIT_BuildLineDefs(wndPtr);
2793 if ((BOOL)lParam && EDIT_GetRedraw(wndPtr))
2794 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2795 if (wndPtr->hwndSelf == GetFocus()) {
2796 DestroyCaret();
2797 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2798 EDIT_EM_SetSel(wndPtr, 1, sel);
2799 ShowCaret(wndPtr->hwndSelf);
2801 return 0L;
2805 /*********************************************************************
2807 * WM_SETREDRAW
2810 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2812 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2814 es->Redraw = (BOOL)wParam;
2815 return 0L;
2819 /*********************************************************************
2821 * WM_SETTEXT
2824 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2826 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(0, -1));
2827 EDIT_WM_Clear(wndPtr, 0, 0L);
2828 if (lParam)
2829 EDIT_EM_ReplaceSel(wndPtr, 0, lParam);
2830 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
2831 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2832 EDIT_ScrollIntoView(wndPtr);
2833 return 0L;
2837 /*********************************************************************
2839 * WM_SIZE
2842 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2844 if (EDIT_GetRedraw(wndPtr) &&
2845 ((wParam == SIZE_MAXIMIZED) ||
2846 (wParam == SIZE_RESTORED))) {
2847 if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
2848 EDIT_BuildLineDefs(wndPtr);
2849 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2851 return 0L;
2855 /*********************************************************************
2857 * WM_VSCROLL
2859 * FIXME: scrollbar code itself is broken, so this one is a hack.
2862 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2864 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2865 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2866 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2867 INT dy = 0;
2868 BOOL not = TRUE;
2869 LRESULT ret = 0L;
2871 switch (wParam) {
2872 case SB_LINEUP:
2873 dy = -1;
2874 break;
2875 case SB_LINEDOWN:
2876 dy = 1;
2877 break;
2878 case SB_PAGEUP:
2879 dy = -vlc;
2880 break;
2881 case SB_PAGEDOWN:
2882 dy = vlc;
2883 break;
2884 case SB_TOP:
2885 dy = -fv;
2886 break;
2887 case SB_BOTTOM:
2888 dy = lc - 1 - fv;
2889 break;
2890 case SB_THUMBTRACK:
2892 * not = FALSE;
2894 case SB_THUMBPOSITION:
2895 dy = LOWORD(lParam) * (lc - 1) / 100 - fv;
2896 break;
2897 /* The next two are undocumented ! */
2898 case EM_GETTHUMB:
2899 ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0L;
2900 break;
2901 case EM_LINESCROLL:
2902 dy = LOWORD(lParam);
2903 break;
2904 case SB_ENDSCROLL:
2905 default:
2906 break;
2908 if (dy) {
2909 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, 0));
2910 if (not)
2911 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
2913 return ret;