Release 961222
[wine/multimedia.git] / controls / edit.c
blob3cb1372b538b9f04af86fba41375d58bec09b9ea
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 "stddebug.h"
21 #include "debug.h"
22 #include "xmalloc.h"
23 #include "callback.h"
25 #define BUFLIMIT_MULTI 65534 /* maximum text buffer length (not including '\0') */
26 #define BUFLIMIT_SINGLE 32766
27 #define BUFSTART_MULTI 1024 /* starting length for multi-line control */
28 #define BUFSTART_SINGLE 256 /* starting length for single line control */
29 #define GROWLENGTH 64 /* buffers grow by this much */
30 #define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */
32 typedef enum
34 END_0 = 0,
35 END_DELIMIT,
36 END_NONE,
37 END_HARD,
38 END_SOFT,
39 } LINE_END;
41 typedef struct {
42 UINT offset;
43 UINT length;
44 LINE_END ending;
45 } LINEDEF;
47 typedef struct
49 UINT TextWidth; /* width of the widest line in pixels */
50 HLOCAL16 hBuf;
51 char *text;
52 HFONT16 hFont;
53 LINEDEF *LineDefs;
54 UINT XOffset; /* offset of the viewport in pixels */
55 UINT FirstVisibleLine;
56 UINT LineCount;
57 UINT LineHeight; /* height of a screen line in pixels */
58 UINT AveCharWidth; /* average character width in pixels */
59 UINT BufLimit;
60 UINT BufSize;
61 BOOL TextChanged;
62 BOOL Redraw;
63 UINT SelStart; /* offset of selection start, == SelEnd if no selection */
64 UINT SelEnd; /* offset of selection end == current caret position */
65 UINT NumTabStops;
66 LPINT16 TabStops;
67 EDITWORDBREAKPROC WordBreakProc;
68 char PasswordChar;
69 } EDITSTATE;
72 #define SWAP_UINT(x,y) do { UINT temp = (UINT)(x); (x) = (UINT)(y); (y) = temp; } while(0)
73 #define ORDER_UINT(x,y) do { if ((UINT)(y) < (UINT)(x)) SWAP_UINT((x),(y)); } while(0)
75 /* macros to access window styles */
76 #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
77 #define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL)
78 #define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL)
79 #define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY)
80 #define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0)
81 #define IsPassword(wndPtr) ((wndPtr)->dwStyle & ES_PASSWORD)
82 #define IsLower(wndPtr) ((wndPtr)->dwStyle & ES_LOWERCASE)
83 #define IsUpper(wndPtr) ((wndPtr)->dwStyle & ES_UPPERCASE)
85 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
87 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
88 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
89 (WPARAM32)(hdc), (LPARAM)(wndPtr)->hwndSelf ))
90 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
91 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_COMMAND, \
92 MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
93 (LPARAM)(wndPtr)->hwndSelf ))
94 #define DPRINTF_EDIT_MSG(str) \
95 dprintf_edit(stddeb, \
96 "edit: " str ": hwnd=%04x, wParam=%04x, lParam=%08x\n", \
97 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
100 /*********************************************************************
102 * Declarations
104 * Files like these should really be kept in alphabetical order.
107 LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM16 wParam, LPARAM lParam);
109 static void EDIT_BuildLineDefs(WND *wndPtr);
110 static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action);
111 static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x);
112 static void EDIT_DelEnd(WND *wndPtr);
113 static void EDIT_DelLeft(WND *wndPtr);
114 static void EDIT_DelRight(WND *wndPtr);
115 static UINT EDIT_GetAveCharWidth(WND *wndPtr);
116 static UINT EDIT_GetLineHeight(WND *wndPtr);
117 static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc);
118 static char * EDIT_GetPointer(WND *wndPtr);
119 static char * EDIT_GetPasswordPointer(WND *wndPtr);
120 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
121 static BOOL EDIT_GetRedraw(WND *wndPtr);
122 static LRESULT EDIT_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
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, HDC32 hdc, UINT line, BOOL rev);
141 static UINT EDIT_PaintText(WND *wndPtr, HDC32 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, WPARAM32 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, WPARAM32 wParam, LPARAM lParam);
150 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
151 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
152 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
153 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
154 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
155 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
156 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
157 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
158 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
159 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
160 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
161 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
162 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
163 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
164 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
165 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
166 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
167 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
168 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
169 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
170 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
171 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
172 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
173 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
174 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
175 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
176 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
177 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
178 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
180 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
181 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
182 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
183 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
184 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
185 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
186 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
187 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
188 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
189 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
190 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
191 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
192 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
193 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
194 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
195 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
196 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
197 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
198 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
199 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
200 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
201 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
202 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
203 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
204 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
205 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
206 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
207 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 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, WPARAM16 wParam, LPARAM lParam)
241 LRESULT lResult = 0L;
242 WND *wndPtr = WIN_FindWndPtr(hwnd);
244 if ((!EDITSTATEPTR(wndPtr)) && (msg != WM_CREATE))
245 return DefWindowProc16(hwnd, msg, wParam, lParam);
247 switch (msg) {
248 case EM_CANUNDO:
249 DPRINTF_EDIT_MSG("EM_CANUNDO");
250 lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
251 break;
252 case EM_EMPTYUNDOBUFFER:
253 DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER");
254 lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
255 break;
256 case EM_FMTLINES:
257 DPRINTF_EDIT_MSG("EM_FMTLINES");
258 lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
259 break;
260 case EM_GETFIRSTVISIBLELINE:
261 DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE");
262 lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
263 break;
264 case EM_GETHANDLE:
265 DPRINTF_EDIT_MSG("EM_GETHANDLE");
266 lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
267 break;
268 case EM_GETLINE:
269 DPRINTF_EDIT_MSG("EM_GETLINE");
270 lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
271 break;
272 case EM_GETLINECOUNT:
273 DPRINTF_EDIT_MSG("EM_GETLINECOUNT");
274 lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
275 break;
276 case EM_GETMODIFY:
277 DPRINTF_EDIT_MSG("EM_GETMODIFY");
278 lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
279 break;
280 case EM_GETPASSWORDCHAR:
281 DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR");
282 lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
283 break;
284 case EM_GETRECT:
285 DPRINTF_EDIT_MSG("EM_GETRECT");
286 lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
287 break;
288 case EM_GETSEL:
289 DPRINTF_EDIT_MSG("EM_GETSEL");
290 lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
291 break;
292 case EM_GETTHUMB:
293 DPRINTF_EDIT_MSG("EM_GETTHUMB");
294 lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
295 break;
296 case EM_GETWORDBREAKPROC:
297 DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC");
298 lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
299 break;
300 case EM_LIMITTEXT:
301 DPRINTF_EDIT_MSG("EM_LIMITTEXT");
302 lResult = EDIT_EM_LimitText(wndPtr, wParam, lParam);
303 break;
304 case EM_LINEFROMCHAR:
305 DPRINTF_EDIT_MSG("EM_LINEFROMCHAR");
306 lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
307 break;
308 case EM_LINEINDEX:
309 DPRINTF_EDIT_MSG("EM_LINEINDEX");
310 lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
311 break;
312 case EM_LINELENGTH:
313 DPRINTF_EDIT_MSG("EM_LINELENGTH");
314 lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
315 break;
316 case EM_LINESCROLL:
317 DPRINTF_EDIT_MSG("EM_LINESCROLL");
318 lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
319 break;
320 case EM_REPLACESEL:
321 DPRINTF_EDIT_MSG("EM_REPLACESEL");
322 lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
323 break;
324 case EM_SCROLL:
325 DPRINTF_EDIT_MSG("EM_SCROLL");
326 lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
327 break;
328 case EM_SETHANDLE:
329 DPRINTF_EDIT_MSG("EM_SETHANDLE");
330 lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
331 break;
332 case EM_SETMODIFY:
333 DPRINTF_EDIT_MSG("EM_SETMODIFY");
334 lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
335 break;
336 case EM_SETPASSWORDCHAR:
337 DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR");
338 lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
339 break;
340 case EM_SETREADONLY:
341 DPRINTF_EDIT_MSG("EM_SETREADONLY");
342 lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
343 break;
344 case EM_SETRECT:
345 DPRINTF_EDIT_MSG("EM_SETRECT");
346 lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
347 break;
348 case EM_SETRECTNP:
349 DPRINTF_EDIT_MSG("EM_SETRECTNP");
350 lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
351 break;
352 case EM_SETSEL:
353 DPRINTF_EDIT_MSG("EM_SETSEL");
354 lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
355 break;
356 case EM_SETTABSTOPS:
357 DPRINTF_EDIT_MSG("EM_SETTABSTOPS");
358 lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
359 break;
360 case EM_SETWORDBREAKPROC:
361 DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC");
362 lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
363 break;
364 case EM_UNDO:
365 case WM_UNDO:
366 DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO");
367 lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
368 break;
369 case WM_GETDLGCODE:
370 DPRINTF_EDIT_MSG("WM_GETDLGCODE");
371 lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
372 break;
373 case WM_CHAR:
374 DPRINTF_EDIT_MSG("WM_CHAR");
375 lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
376 break;
377 case WM_CLEAR:
378 DPRINTF_EDIT_MSG("WM_CLEAR");
379 lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
380 break;
381 case WM_COPY:
382 DPRINTF_EDIT_MSG("WM_COPY");
383 lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
384 break;
385 case WM_CREATE:
386 DPRINTF_EDIT_MSG("WM_CREATE");
387 lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
388 break;
389 case WM_CUT:
390 DPRINTF_EDIT_MSG("WM_CUT");
391 lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
392 break;
393 case WM_DESTROY:
394 DPRINTF_EDIT_MSG("WM_DESTROY");
395 lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
396 break;
397 case WM_ENABLE:
398 DPRINTF_EDIT_MSG("WM_ENABLE");
399 lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
400 break;
401 case WM_ERASEBKGND:
402 DPRINTF_EDIT_MSG("WM_ERASEBKGND");
403 lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
404 break;
405 case WM_GETFONT:
406 DPRINTF_EDIT_MSG("WM_GETFONT");
407 lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
408 break;
409 case WM_GETTEXT:
410 DPRINTF_EDIT_MSG("WM_GETTEXT");
411 lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
412 break;
413 case WM_GETTEXTLENGTH:
414 DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH");
415 lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
416 break;
417 case WM_HSCROLL:
418 DPRINTF_EDIT_MSG("WM_HSCROLL");
419 lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
420 break;
421 case WM_KEYDOWN:
422 DPRINTF_EDIT_MSG("WM_KEYDOWN");
423 lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
424 break;
425 case WM_KILLFOCUS:
426 DPRINTF_EDIT_MSG("WM_KILLFOCUS");
427 lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
428 break;
429 case WM_LBUTTONDBLCLK:
430 DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK");
431 lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
432 break;
433 case WM_LBUTTONDOWN:
434 DPRINTF_EDIT_MSG("WM_LBUTTONDOWN");
435 lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
436 break;
437 case WM_LBUTTONUP:
438 DPRINTF_EDIT_MSG("WM_LBUTTONUP");
439 lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
440 break;
441 case WM_MOUSEMOVE:
443 * DPRINTF_EDIT_MSG("WM_MOUSEMOVE");
445 lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
446 break;
447 case WM_PAINT:
448 DPRINTF_EDIT_MSG("WM_PAINT");
449 lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
450 break;
451 case WM_PASTE:
452 DPRINTF_EDIT_MSG("WM_PASTE");
453 lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
454 break;
455 case WM_SETCURSOR:
457 * DPRINTF_EDIT_MSG("WM_SETCURSOR");
459 lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
460 break;
461 case WM_SETFOCUS:
462 DPRINTF_EDIT_MSG("WM_SETFOCUS");
463 lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
464 break;
465 case WM_SETFONT:
466 DPRINTF_EDIT_MSG("WM_SETFONT");
467 lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
468 break;
469 case WM_SETREDRAW:
470 DPRINTF_EDIT_MSG("WM_SETREDRAW");
471 lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
472 break;
473 case WM_SETTEXT:
474 DPRINTF_EDIT_MSG("WM_SETTEXT");
475 lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
476 break;
477 case WM_SIZE:
478 DPRINTF_EDIT_MSG("WM_SIZE");
479 lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
480 break;
481 case WM_VSCROLL:
482 DPRINTF_EDIT_MSG("WM_VSCROLL");
483 lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
484 break;
485 default:
486 lResult = DefWindowProc16(hwnd, msg, wParam, lParam);
487 break;
489 EDIT_ReleasePointer(wndPtr);
490 return lResult;
494 /*********************************************************************
496 * EDIT_BuildLineDefs
498 * Build array of pointers to text lines.
499 * Lines can end with '\0' (last line), nothing (if it is too long),
500 * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
503 static void EDIT_BuildLineDefs(WND *wndPtr)
505 EDITSTATE *es = EDITSTATEPTR(wndPtr);
506 char *text = EDIT_GetPasswordPointer(wndPtr);
507 int ww = EDIT_GetWndWidth(wndPtr);
508 HDC32 hdc;
509 HFONT16 hFont;
510 HFONT32 oldFont = 0;
511 char *start, *cp;
512 int prev, next;
513 int width;
514 int length;
515 LINE_END ending;
517 hdc = GetDC32(wndPtr->hwndSelf);
518 hFont = (HFONT16)EDIT_WM_GetFont(wndPtr, 0, 0L);
519 if (hFont) oldFont = SelectObject32(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) SelectObject32(hdc, oldFont);
601 ReleaseDC32(wndPtr->hwndSelf, hdc);
603 free(text);
607 /*********************************************************************
609 * EDIT_CallWordBreakProc
611 * Call appropriate WordBreakProc (internal or external).
614 static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action)
616 EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0L);
618 if (!wbp) return EDIT_WordBreakProc(s, index, count, action);
619 else
621 /* We need a SEGPTR here */
623 EDITSTATE *es = EDITSTATEPTR(wndPtr);
624 SEGPTR ptr = LOCAL_LockSegptr( wndPtr->hInstance, es->hBuf ) +
625 (UINT16)(s - EDIT_GetPointer(wndPtr));
626 INT ret = CallWordBreakProc( (FARPROC16)wbp, ptr,
627 index, count, action);
628 LOCAL_Unlock( wndPtr->hInstance, es->hBuf );
629 return ret;
634 /*********************************************************************
636 * EDIT_ColFromWndX
638 * Calculates, for a given line and X-coordinate on the screen, the column.
641 static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x)
643 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
644 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
645 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
646 UINT i;
648 line = MAX(0, MIN(line, lc - 1));
649 for (i = 0 ; i < ll ; i++)
650 if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
651 break;
652 return i;
656 /*********************************************************************
658 * EDIT_DelEnd
660 * Delete all characters on this line to right of cursor.
663 static void EDIT_DelEnd(WND *wndPtr)
665 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
666 EDIT_MoveEnd(wndPtr, TRUE);
667 EDIT_WM_Clear(wndPtr, 0, 0L);
671 /*********************************************************************
673 * EDIT_DelLeft
675 * Delete character to left of cursor.
678 static void EDIT_DelLeft(WND *wndPtr)
680 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
681 EDIT_MoveBackward(wndPtr, TRUE);
682 EDIT_WM_Clear(wndPtr, 0, 0L);
686 /*********************************************************************
688 * EDIT_DelRight
690 * Delete character to right of cursor.
693 static void EDIT_DelRight(WND *wndPtr)
695 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
696 EDIT_MoveForward(wndPtr, TRUE);
697 EDIT_WM_Clear(wndPtr, 0, 0L);
701 /*********************************************************************
703 * EDIT_GetAveCharWidth
706 static UINT EDIT_GetAveCharWidth(WND *wndPtr)
708 EDITSTATE *es = EDITSTATEPTR(wndPtr);
710 return es->AveCharWidth;
714 /*********************************************************************
716 * EDIT_GetLineHeight
719 static UINT EDIT_GetLineHeight(WND *wndPtr)
721 EDITSTATE *es = EDITSTATEPTR(wndPtr);
723 return es->LineHeight;
727 /*********************************************************************
729 * EDIT_GetLineRect
731 * Calculates the bounding rectangle for a line from a starting
732 * column to an ending column.
735 static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc)
737 rc->top = EDIT_WndYFromLine(wndPtr, line);
738 rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
739 rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
740 rc->right = ((INT)ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
741 EDIT_WndXFromCol(wndPtr, line, ecol);
745 /*********************************************************************
747 * EDIT_GetPointer
749 * This acts as a LOCAL_Lock(), but it locks only once. This way
750 * you can call it whenever you like, without unlocking.
753 static char *EDIT_GetPointer(WND *wndPtr)
755 EDITSTATE *es = EDITSTATEPTR(wndPtr);
757 if (!es->text && es->hBuf)
758 es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf);
759 return es->text;
763 /*********************************************************************
765 * EDIT_GetPasswordPointer
769 static char *EDIT_GetPasswordPointer(WND *wndPtr)
771 EDITSTATE *es = EDITSTATEPTR(wndPtr);
772 char *text = xstrdup(EDIT_GetPointer(wndPtr));
773 char *p;
775 if(es->PasswordChar) {
776 p = text;
777 while(*p != '\0') {
778 if(*p != '\r' && *p != '\n')
779 *p = es->PasswordChar;
780 p++;
783 return text;
787 /*********************************************************************
789 * EDIT_GetRect
791 * Beware: This is not the function called on EM_GETRECT.
792 * It expects a (LPRECT) in lParam, not a (SEGPTR).
793 * It is used internally, as if there were no pointer difficulties.
796 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
798 GetClientRect16( wndPtr->hwndSelf, (LPRECT16)lParam );
799 return 0L;
803 /*********************************************************************
805 * EDIT_GetRedraw
808 static BOOL EDIT_GetRedraw(WND *wndPtr)
810 EDITSTATE *es = EDITSTATEPTR(wndPtr);
812 return es->Redraw;
816 /*********************************************************************
818 * EDIT_GetSel
820 * Beware: This is not the function called on EM_GETSEL.
821 * It returns the start in the low word and the end in the high word.
822 * NB s can be greater than e.
825 static LRESULT EDIT_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
827 EDITSTATE *es = EDITSTATEPTR(wndPtr);
829 return MAKELONG(es->SelStart, es->SelEnd);
832 /*********************************************************************
834 * EDIT_GetTextWidth
837 static UINT EDIT_GetTextWidth(WND *wndPtr)
839 EDITSTATE *es = EDITSTATEPTR(wndPtr);
841 return es->TextWidth;
845 /*********************************************************************
847 * EDIT_GetVisibleLineCount
850 static UINT EDIT_GetVisibleLineCount(WND *wndPtr)
852 RECT16 rc;
854 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
855 return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
859 /*********************************************************************
861 * EDIT_GetWndWidth
864 static UINT EDIT_GetWndWidth(WND *wndPtr)
866 RECT16 rc;
868 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
869 return rc.right - rc.left;
873 /*********************************************************************
875 * EDIT_GetXOffset
878 static UINT EDIT_GetXOffset(WND *wndPtr)
880 EDITSTATE *es = EDITSTATEPTR(wndPtr);
882 return es->XOffset;
886 /*********************************************************************
888 * EDIT_InvalidateText
890 * Invalidate the text from offset start upto, but not including,
891 * offset end. Useful for (re)painting the selection.
892 * Regions outside the linewidth are not invalidated.
893 * end == -1 means end == TextLength.
894 * start and end need not be ordered.
897 static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end)
899 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
900 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
901 UINT sl;
902 UINT el;
903 UINT sc;
904 UINT ec;
905 RECT16 rcWnd;
906 RECT16 rcLine;
907 RECT16 rcUpdate;
908 UINT l;
910 if (end == start )
911 return;
913 if ((INT)end == -1)
914 end = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
915 ORDER_UINT(start, end);
916 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, start, 0L);
917 el = (UINT)EDIT_EM_LineFromChar(wndPtr, end, 0L);
918 if ((el < fv) || (sl > fv + vlc))
919 return;
921 sc = start - (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L);
922 ec = end - (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
923 if (sl < fv) {
924 sl = fv;
925 sc = 0;
927 if (el > fv + vlc) {
928 el = fv + vlc;
929 ec = (UINT)EDIT_EM_LineLength(wndPtr,
930 (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L), 0L);
932 EDIT_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
933 if (sl == el) {
934 EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
935 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
936 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
937 } else {
938 EDIT_GetLineRect(wndPtr, sl, sc,
939 (UINT)EDIT_EM_LineLength(wndPtr,
940 (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L), 0L),
941 &rcLine);
942 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
943 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
944 for (l = sl + 1 ; l < el ; l++) {
945 EDIT_GetLineRect(wndPtr, l, 0,
946 (UINT)EDIT_EM_LineLength(wndPtr,
947 (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L), 0L),
948 &rcLine);
949 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
950 InvalidateRect16(wndPtr->hwndSelf, &rcUpdate, FALSE);
952 EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
953 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
954 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
959 /*********************************************************************
961 * EDIT_LineFromWndY
963 * Calculates, for a given Y-coordinate on the screen, the line.
966 static UINT EDIT_LineFromWndY(WND *wndPtr, INT y)
968 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
969 UINT lh = EDIT_GetLineHeight(wndPtr);
970 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
972 return MAX(0, MIN(lc - 1, y / lh + fv));
976 /*********************************************************************
978 * EDIT_MakeFit
980 * Try to fit size + 1 bytes in the buffer. Constrain to limits.
983 static BOOL EDIT_MakeFit(WND *wndPtr, UINT size)
985 EDITSTATE *es = EDITSTATEPTR(wndPtr);
987 if (size <= es->BufSize)
988 return TRUE;
989 if (size > es->BufLimit)
990 return FALSE;
991 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
992 if (size > es->BufLimit)
993 size = es->BufLimit;
995 dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
997 if (LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, size + 1, LMEM_MOVEABLE)) {
998 es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1, es->BufLimit);
999 return TRUE;
1000 } else
1001 return FALSE;
1005 /*********************************************************************
1007 * EDIT_MoveBackward
1010 static void EDIT_MoveBackward(WND *wndPtr, BOOL extend)
1012 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1013 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1014 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1015 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1017 if (e - li == 0) {
1018 if (l) {
1019 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
1020 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1022 } else
1023 e--;
1024 if (!extend)
1025 s = e;
1026 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1030 /*********************************************************************
1032 * EDIT_MoveDownward
1035 static void EDIT_MoveDownward(WND *wndPtr, BOOL extend)
1037 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1038 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1039 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1040 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1041 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1042 INT x;
1044 if (l < lc - 1) {
1045 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1046 l++;
1047 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1048 EDIT_ColFromWndX(wndPtr, l, x);
1050 if (!extend)
1051 s = e;
1052 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1056 /*********************************************************************
1058 * EDIT_MoveEnd
1061 static void EDIT_MoveEnd(WND *wndPtr, BOOL extend)
1063 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1064 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1065 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1066 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1067 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1069 e = li + ll;
1070 if (!extend)
1071 s = e;
1072 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1076 /*********************************************************************
1078 * EDIT_MoveForward
1081 static void EDIT_MoveForward(WND *wndPtr, BOOL extend)
1083 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1084 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1085 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1086 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1087 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1088 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1090 if (e - li == ll) {
1091 if (l != lc - 1)
1092 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1093 } else
1094 e++;
1095 if (!extend)
1096 s = e;
1097 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1101 /*********************************************************************
1103 * EDIT_MoveHome
1105 * Home key: move to beginning of line.
1108 static void EDIT_MoveHome(WND *wndPtr, BOOL extend)
1110 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1111 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1112 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1113 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1115 e = li;
1116 if (!extend)
1117 s = e;
1118 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1122 /*********************************************************************
1124 * EDIT_MovePageDown
1127 static void EDIT_MovePageDown(WND *wndPtr, BOOL extend)
1129 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1130 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1131 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1132 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1133 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1134 INT x;
1136 if (l < lc - 1) {
1137 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1138 l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
1139 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1140 EDIT_ColFromWndX(wndPtr, l, x);
1142 if (!extend)
1143 s = e;
1144 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1148 /*********************************************************************
1150 * EDIT_MovePageUp
1153 static void EDIT_MovePageUp(WND *wndPtr, BOOL extend)
1155 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1156 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1157 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1158 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1159 INT x;
1161 if (l) {
1162 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1163 l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
1164 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1165 EDIT_ColFromWndX(wndPtr, l, x);
1167 if (!extend)
1168 s = e;
1169 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1173 /*********************************************************************
1175 * EDIT_MoveUpward
1178 static void EDIT_MoveUpward(WND *wndPtr, BOOL extend)
1180 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1181 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1182 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1183 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1184 INT x;
1186 if (l) {
1187 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1188 l--;
1189 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1190 EDIT_ColFromWndX(wndPtr, l, x);
1192 if (!extend)
1193 s = e;
1194 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1198 /*********************************************************************
1200 * EDIT_MoveWordBackward
1203 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend)
1205 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1206 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1207 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1208 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1209 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1210 char *text;
1212 if (e - li == 0) {
1213 if (l) {
1214 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
1215 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1217 } else {
1218 text = EDIT_GetPointer(wndPtr);
1219 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1220 text + li, e - li, ll, WB_LEFT);
1222 if (!extend)
1223 s = e;
1224 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1228 /*********************************************************************
1230 * EDIT_MoveWordForward
1233 static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend)
1235 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1236 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1237 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1238 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1239 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1240 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1241 char *text;
1243 if (e - li == ll) {
1244 if (l != lc - 1)
1245 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1246 } else {
1247 text = EDIT_GetPointer(wndPtr);
1248 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1249 text + li, e - li + 1, ll, WB_RIGHT);
1251 if (!extend)
1252 s = e;
1253 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1257 /*********************************************************************
1259 * EDIT_PaintLine
1262 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, UINT line, BOOL rev)
1264 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1265 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1266 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1267 UINT li;
1268 UINT ll;
1269 UINT s;
1270 UINT e;
1271 INT x;
1272 INT y;
1274 if ((line < fv) || (line > fv + vlc) || (line >= lc))
1275 return;
1277 dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
1279 x = EDIT_WndXFromCol(wndPtr, line, 0);
1280 y = EDIT_WndYFromLine(wndPtr, line);
1281 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1282 ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1283 s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1284 e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1285 ORDER_UINT(s, e);
1286 s = MIN(li + ll, MAX(li, s));
1287 e = MIN(li + ll, MAX(li, e));
1288 if (rev && (s != e) &&
1289 ((GetFocus32() == wndPtr->hwndSelf) ||
1290 (wndPtr->dwStyle & ES_NOHIDESEL))) {
1291 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
1292 x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
1293 x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
1294 } else
1295 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
1299 /*********************************************************************
1301 * EDIT_PaintText
1304 static UINT EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev)
1306 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1307 COLORREF BkColor;
1308 COLORREF TextColor;
1309 UINT ret;
1310 char *text;
1311 UINT li;
1312 UINT xoff;
1314 if (!count)
1315 return 0;
1316 BkColor = GetBkColor32(hdc);
1317 TextColor = GetTextColor32(hdc);
1318 if (rev) {
1319 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1320 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1322 text = EDIT_GetPasswordPointer(wndPtr);
1323 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1324 xoff = EDIT_GetXOffset(wndPtr);
1325 ret = LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
1326 es->NumTabStops, es->TabStops, -xoff));
1327 free(text);
1328 if (rev) {
1329 SetBkColor(hdc, BkColor);
1330 SetTextColor(hdc, TextColor);
1332 return ret;
1336 /*********************************************************************
1338 * EDIT_ReleasePointer
1340 * This is the only helper function that can be called with es = NULL.
1341 * It is called at the end of EditWndProc() to unlock the buffer.
1344 static void EDIT_ReleasePointer(WND *wndPtr)
1346 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1348 if (!es)
1349 return;
1350 if (es->text && es->hBuf)
1351 LOCAL_Unlock(wndPtr->hInstance, es->hBuf);
1352 es->text = NULL;
1356 /*********************************************************************
1358 * EDIT_ReplaceSel
1360 * Beware: This is not the function called on EM_REPLACESEL.
1361 * It expects a (char *) in lParam, not a (SEGPTR).
1362 * It is used internally, as if there were no pointer difficulties.
1365 static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1367 const char *str = (char *)lParam;
1368 int strl = strlen(str);
1369 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1370 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1371 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1372 int i;
1373 char *p;
1374 char *text;
1375 BOOL redraw;
1377 ORDER_UINT(s,e);
1378 if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
1379 EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
1380 return 0L;
1382 redraw = EDIT_GetRedraw(wndPtr);
1383 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
1384 EDIT_WM_Clear(wndPtr, 0, 0L);
1385 tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1386 e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1387 text = EDIT_GetPointer(wndPtr);
1388 for (p = text + tl ; p >= text + e ; p--)
1389 p[strl] = p[0];
1390 for (i = 0 , p = text + e ; i < strl ; i++)
1391 p[i] = str[i];
1392 if(IsUpper(wndPtr))
1393 AnsiUpperBuff(p, strl);
1394 else if(IsLower(wndPtr))
1395 AnsiLowerBuff(p, strl);
1396 EDIT_BuildLineDefs(wndPtr);
1397 e += strl;
1398 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(e, e));
1399 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
1400 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
1401 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
1402 if (redraw) {
1403 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
1404 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
1406 return 0L;
1410 /*********************************************************************
1412 * EDIT_ScrollIntoView
1414 * Makes sure the caret is visible.
1417 static void EDIT_ScrollIntoView(WND *wndPtr)
1419 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1420 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1421 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1422 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1423 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1424 UINT ww = EDIT_GetWndWidth(wndPtr);
1425 UINT cw = EDIT_GetAveCharWidth(wndPtr);
1426 INT x = EDIT_WndXFromCol(wndPtr, l, e - li);
1427 int dy = 0;
1428 int dx = 0;
1430 if (l >= fv + vlc)
1431 dy = l - vlc + 1 - fv;
1432 if (l < fv)
1433 dy = l - fv;
1434 if (x < 0)
1435 dx = x - ww / HSCROLL_FRACTION / cw * cw;
1436 if (x > ww)
1437 dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
1438 if (dy || dx) {
1439 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, dx));
1440 if (dy)
1441 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
1442 if (dx)
1443 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
1448 /*********************************************************************
1450 * EDIT_WndXFromCol
1452 * Calculates, for a given line and column, the X-coordinate on the screen.
1455 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col)
1457 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1458 char *text = EDIT_GetPasswordPointer(wndPtr);
1459 INT ret;
1460 HDC32 hdc;
1461 HFONT16 hFont;
1462 HFONT32 oldFont = 0;
1463 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1464 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1465 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1466 UINT xoff = EDIT_GetXOffset(wndPtr);
1468 hdc = GetDC32(wndPtr->hwndSelf);
1469 hFont = (HFONT16)EDIT_WM_GetFont(wndPtr, 0, 0L);
1470 if (hFont) oldFont = SelectObject32(hdc, hFont);
1471 line = MAX(0, MIN(line, lc - 1));
1472 col = MIN(col, ll);
1473 ret = LOWORD(GetTabbedTextExtent(hdc,
1474 text + li, col,
1475 es->NumTabStops, es->TabStops)) - xoff;
1476 if (hFont) SelectObject32(hdc, oldFont);
1477 ReleaseDC32(wndPtr->hwndSelf, hdc);
1478 free(text);
1479 return ret;
1483 /*********************************************************************
1485 * EDIT_WndYFromLine
1487 * Calculates, for a given line, the Y-coordinate on the screen.
1490 static INT EDIT_WndYFromLine(WND *wndPtr, UINT line)
1492 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1493 UINT lh = EDIT_GetLineHeight(wndPtr);
1495 return (line - fv) * lh;
1499 /*********************************************************************
1501 * EDIT_WordBreakProc
1503 * Find the beginning of words.
1504 * Note: unlike the specs for a WordBreakProc, this function only
1505 * allows to be called without linebreaks between s[0] upto
1506 * s[count - 1]. Remember it is only called
1507 * internally, so we can decide this for ourselves.
1510 static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action)
1512 INT ret = 0;
1514 dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%d"
1515 ", count=%d, action=%d\n", s, index, count, action);
1517 switch (action) {
1518 case WB_LEFT:
1519 if (!count)
1520 break;
1521 if (index)
1522 index--;
1523 if (s[index] == ' ') {
1524 while (index && (s[index] == ' '))
1525 index--;
1526 if (index) {
1527 while (index && (s[index] != ' '))
1528 index--;
1529 if (s[index] == ' ')
1530 index++;
1532 } else {
1533 while (index && (s[index] != ' '))
1534 index--;
1535 if (s[index] == ' ')
1536 index++;
1538 ret = index;
1539 break;
1540 case WB_RIGHT:
1541 if (!count)
1542 break;
1543 if (index)
1544 index--;
1545 if (s[index] == ' ')
1546 while ((index < count) && (s[index] == ' ')) index++;
1547 else {
1548 while (s[index] && (s[index] != ' ') && (index < count))
1549 index++;
1550 while ((s[index] == ' ') && (index < count)) index++;
1552 ret = index;
1553 break;
1554 case WB_ISDELIMITER:
1555 ret = (s[index] == ' ');
1556 break;
1557 default:
1558 fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
1559 break;
1561 return ret;
1565 /*********************************************************************
1567 * EM_CANUNDO
1570 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1572 return 0L;
1576 /*********************************************************************
1578 * EM_EMPTYUNDOBUFFER
1581 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1583 return 0L;
1587 /*********************************************************************
1589 * EM_FMTLINES
1592 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1594 fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented.\n");
1595 return wParam ? -1L : 0L;
1599 /*********************************************************************
1601 * EM_GETFIRSTVISIBLELINE
1604 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1606 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1608 return (LRESULT)es->FirstVisibleLine;
1612 /*********************************************************************
1614 * EM_GETHANDLE
1617 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1619 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1621 return (LRESULT)es->hBuf;
1625 /*********************************************************************
1627 * EM_GETLINE
1630 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1632 char *text;
1633 char *src;
1634 char *dst;
1635 UINT len;
1636 UINT i;
1637 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1639 if (!IsMultiLine(wndPtr))
1640 wParam = 0;
1641 if ((UINT)wParam >= lc)
1642 return 0L;
1643 text = EDIT_GetPointer(wndPtr);
1644 src = text + (UINT)EDIT_EM_LineIndex(wndPtr, wParam, 0L);
1645 dst = (char *)PTR_SEG_TO_LIN(lParam);
1646 len = MIN(*(WORD *)dst, (UINT)EDIT_EM_LineLength(wndPtr, wParam, 0L));
1647 for (i = 0 ; i < len ; i++) {
1648 *dst = *src;
1649 src++;
1650 dst++;
1652 return (LRESULT)len;
1656 /*********************************************************************
1658 * EM_GETLINECOUNT
1661 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1663 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1665 return (LRESULT)es->LineCount;
1669 /*********************************************************************
1671 * EM_GETMODIFY
1674 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1676 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1678 return (LRESULT)es->TextChanged;
1682 /*********************************************************************
1684 * EM_GETPASSWORDCHAR
1687 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1689 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1691 return (LRESULT)es->PasswordChar;
1695 /*********************************************************************
1697 * EM_GETRECT
1700 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1702 return EDIT_GetRect(wndPtr, wParam, (LPARAM)PTR_SEG_TO_LIN(lParam));
1706 /*********************************************************************
1708 * EM_GETSEL
1710 * Returns the ordered selection range so that
1711 * LOWORD(result) < HIWORD(result)
1714 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1716 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1717 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1719 ORDER_UINT(s, e);
1720 return MAKELONG(s, e);
1724 /*********************************************************************
1726 * EM_GETTHUMB
1728 * FIXME: undocumented: is this right ?
1731 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1733 return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L),
1734 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L));
1738 /*********************************************************************
1740 * EM_GETWORDBREAKPROC
1743 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1745 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1747 return (LRESULT)es->WordBreakProc;
1751 /*********************************************************************
1753 * EM_LIMITTEXT
1756 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1758 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1760 if (IsMultiLine(wndPtr)) {
1761 if (wParam)
1762 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_MULTI);
1763 else
1764 es->BufLimit = BUFLIMIT_MULTI;
1765 } else {
1766 if (wParam)
1767 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_SINGLE);
1768 else
1769 es->BufLimit = BUFLIMIT_SINGLE;
1771 return 0L;
1775 /*********************************************************************
1777 * EM_LINEFROMCHAR
1780 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1782 UINT l;
1784 if (!IsMultiLine(wndPtr))
1785 return 0L;
1786 if ((INT)wParam == -1)
1787 wParam = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1788 l = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
1789 while ((UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam)
1790 l--;
1791 return (LRESULT)l;
1795 /*********************************************************************
1797 * EM_LINEINDEX
1800 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1802 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1803 UINT e;
1804 UINT l;
1805 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1807 if ((INT)wParam == -1) {
1808 e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1809 l = lc - 1;
1810 while (es->LineDefs[l].offset > e)
1811 l--;
1812 return (LRESULT)es->LineDefs[l].offset;
1814 if ((UINT)wParam >= lc)
1815 return -1L;
1816 return (LRESULT)es->LineDefs[(UINT)wParam].offset;
1820 /*********************************************************************
1822 * EM_LINELENGTH
1825 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1827 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1828 UINT s;
1829 UINT e;
1830 UINT sl;
1831 UINT el;
1833 if (!IsMultiLine(wndPtr))
1834 return (LRESULT)es->LineDefs[0].length;
1835 if ((INT)wParam == -1) {
1836 s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
1837 e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
1838 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, s, 0L);
1839 el = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1840 return (LRESULT)(s - es->LineDefs[sl].offset +
1841 es->LineDefs[el].offset +
1842 es->LineDefs[el].length - e);
1844 return (LRESULT)es->LineDefs[(UINT)EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length;
1848 /*********************************************************************
1850 * EM_LINESCROLL
1853 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1855 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1856 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1857 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1858 UINT nfv = MAX(0, fv + (INT)LOWORD(lParam));
1859 UINT xoff = EDIT_GetXOffset(wndPtr);
1860 UINT nxoff = MAX(0, xoff + (INT)HIWORD(lParam));
1861 UINT tw = EDIT_GetTextWidth(wndPtr);
1862 INT dx;
1863 INT dy;
1864 POINT16 pos;
1866 if (nfv >= lc)
1867 nfv = lc - 1;
1869 if (nxoff >= tw)
1870 nxoff = tw;
1871 dx = xoff - nxoff;
1872 dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
1873 if (dx || dy) {
1874 if (wndPtr->hwndSelf == GetFocus32())
1875 HideCaret(wndPtr->hwndSelf);
1876 if (EDIT_GetRedraw(wndPtr))
1877 ScrollWindow32(wndPtr->hwndSelf, dx, dy, NULL, NULL);
1878 es->FirstVisibleLine = nfv;
1879 es->XOffset = nxoff;
1880 if (IsVScrollBar(wndPtr))
1881 SetScrollPos32(wndPtr->hwndSelf, SB_VERT,
1882 EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1883 if (IsHScrollBar(wndPtr))
1884 SetScrollPos32(wndPtr->hwndSelf, SB_HORZ,
1885 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1886 if (wndPtr->hwndSelf == GetFocus32()) {
1887 GetCaretPos16(&pos);
1888 SetCaretPos(pos.x + dx, pos.y + dy);
1889 ShowCaret(wndPtr->hwndSelf);
1892 return -1L;
1896 /*********************************************************************
1898 * EM_REPLACESEL
1901 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1903 return (LRESULT)EDIT_ReplaceSel(wndPtr, wParam,
1904 (LPARAM)(char *)PTR_SEG_TO_LIN(lParam));
1908 /*********************************************************************
1910 * EM_SCROLL
1912 * FIXME: undocumented message.
1915 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1917 fprintf(stdnimp, "edit: EM_SCROLL: message not implemented (undocumented), please report.\n");
1918 return 0L;
1922 /*********************************************************************
1924 * EM_SETHANDLE
1927 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1929 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1931 if (IsMultiLine(wndPtr)) {
1932 EDIT_ReleasePointer(wndPtr);
1934 * old buffer is freed by caller
1936 es->hBuf = (HLOCAL16)wParam;
1937 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
1938 es->LineCount = 0;
1939 es->FirstVisibleLine = 0;
1940 es->SelStart = es->SelEnd = 0;
1941 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
1942 EDIT_EM_SetModify(wndPtr, FALSE, 0L);
1943 EDIT_BuildLineDefs(wndPtr);
1944 if (EDIT_GetRedraw(wndPtr))
1945 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
1946 EDIT_ScrollIntoView(wndPtr);
1948 return 0L;
1952 /*********************************************************************
1954 * EM_SETMODIFY
1957 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1959 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1961 es->TextChanged = (BOOL)wParam;
1962 return 0L;
1966 /*********************************************************************
1968 * EM_SETPASSWORDCHAR
1971 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1973 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1975 es->PasswordChar = (char)wParam;
1976 return 0L;
1980 /*********************************************************************
1982 * EM_SETREADONLY
1985 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1987 if ((BOOL)wParam)
1988 wndPtr->dwStyle |= ES_READONLY;
1989 else
1990 wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
1991 return 0L;
1995 /*********************************************************************
1997 * EM_SETRECT
2000 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2002 fprintf(stdnimp,"edit: EM_SETRECT: message not implemented, please report.\n");
2003 return 0L;
2007 /*********************************************************************
2009 * EM_SETRECTNP
2012 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2014 fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented, please report.\n");
2015 return 0L;
2019 /*********************************************************************
2021 * EM_SETSEL
2024 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2026 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2027 UINT ns = LOWORD(lParam);
2028 UINT ne = HIWORD(lParam);
2029 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
2030 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
2031 UINT el;
2032 UINT eli;
2033 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
2035 if ((INT)ns == -1) {
2036 ns = e;
2037 ne = e;
2039 else {
2040 ns = MIN(ns, tl);
2041 ne = MIN(ne, tl);
2043 es->SelStart = ns;
2044 es->SelEnd = ne;
2045 if (wndPtr->hwndSelf == GetFocus32()) {
2046 el = (UINT)EDIT_EM_LineFromChar(wndPtr, ne, 0L);
2047 eli = (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
2048 SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - eli),
2049 EDIT_WndYFromLine(wndPtr, el));
2051 if (!wParam)
2052 EDIT_ScrollIntoView(wndPtr);
2053 if (EDIT_GetRedraw(wndPtr)) {
2054 ORDER_UINT(s, e);
2055 ORDER_UINT(s, ns);
2056 ORDER_UINT(s, ne);
2057 ORDER_UINT(e, ns);
2058 ORDER_UINT(e, ne);
2059 ORDER_UINT(ns, ne);
2060 if (e != ns) {
2061 EDIT_InvalidateText(wndPtr, s, e);
2062 EDIT_InvalidateText(wndPtr, ns, ne);
2063 } else
2064 EDIT_InvalidateText(wndPtr, s, ne);
2066 return -1L;
2070 /*********************************************************************
2072 * EM_SETTABSTOPS
2075 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2077 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2079 if (!IsMultiLine(wndPtr))
2080 return 0L;
2081 if (es->TabStops)
2082 free(es->TabStops);
2083 es->NumTabStops = (UINT)wParam;
2084 if (!wParam)
2085 es->TabStops = NULL;
2086 else {
2087 es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
2088 memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam),
2089 (UINT)wParam * sizeof(INT16));
2091 return 1L;
2095 /*********************************************************************
2097 * EM_SETWORDBREAKPROC
2100 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2102 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2104 es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
2105 return 0L;
2109 /*********************************************************************
2111 * EM_UNDO
2114 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2116 return 0L;
2120 /*********************************************************************
2122 * WM_CHAR
2125 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2127 char str[2];
2128 unsigned char c = (unsigned char)wParam;
2130 switch (c) {
2131 case '\r':
2132 case '\n':
2133 if (IsMultiLine(wndPtr)) {
2134 if (IsReadOnly(wndPtr)) {
2135 EDIT_MoveHome(wndPtr, FALSE);
2136 EDIT_MoveDownward(wndPtr, FALSE);
2137 } else
2138 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n");
2140 break;
2141 case '\t':
2142 if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
2143 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\t");
2144 break;
2145 default:
2146 if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
2147 str[0] = c;
2148 str[1] = '\0';
2149 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)str);
2151 break;
2153 return 0L;
2157 /*********************************************************************
2159 * WM_CLEAR
2162 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2164 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
2165 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
2166 char *text;
2167 BOOL redraw;
2169 if (s != e) {
2170 redraw = EDIT_GetRedraw(wndPtr);
2171 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
2172 ORDER_UINT(s, e);
2173 text = EDIT_GetPointer(wndPtr);
2174 strcpy(text + s, text + e);
2175 EDIT_BuildLineDefs(wndPtr);
2176 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, s));
2177 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2178 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2179 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
2180 if (redraw) {
2181 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2182 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2185 return -1L;
2189 /*********************************************************************
2191 * WM_COPY
2194 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2196 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
2197 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
2198 HGLOBAL16 hdst;
2199 char *text;
2200 char *dst;
2201 char *src;
2202 int i;
2204 if (e == s)
2205 return -1L;
2206 ORDER_UINT(s, e);
2207 hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
2208 dst = GlobalLock16(hdst);
2209 text = EDIT_GetPointer(wndPtr);
2210 src = text + s;
2211 for (i = 0 ; i < e - s ; i++)
2212 *dst++ = *src++;
2213 *dst = '\0';
2214 GlobalUnlock16(hdst);
2215 OpenClipboard(wndPtr->hwndSelf);
2216 EmptyClipboard();
2217 SetClipboardData(CF_TEXT, hdst);
2218 CloseClipboard();
2219 return -1L;
2223 /*********************************************************************
2225 * WM_CREATE
2228 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2230 CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
2231 EDITSTATE *es;
2232 char *text;
2234 es = xmalloc(sizeof(EDITSTATE));
2235 memset(es, 0, sizeof(EDITSTATE));
2236 *(EDITSTATE **)wndPtr->wExtra = es;
2238 if (cs->style & WS_VSCROLL)
2239 cs->style |= ES_AUTOVSCROLL;
2240 if (cs->style & WS_HSCROLL)
2241 cs->style |= ES_AUTOHSCROLL;
2243 /* remove the WS_CAPTION style if it has been set - this is really a */
2244 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
2245 if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
2246 cs->style ^= WS_DLGFRAME;
2248 if (IsMultiLine(wndPtr)) {
2249 es->BufSize = BUFSTART_MULTI;
2250 es->BufLimit = BUFLIMIT_MULTI;
2251 es->PasswordChar = '\0';
2252 } else {
2253 es->BufSize = BUFSTART_SINGLE;
2254 es->BufLimit = BUFLIMIT_SINGLE;
2255 es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
2257 if (!LOCAL_HeapSize(wndPtr->hInstance)) {
2258 if (!LocalInit(wndPtr->hInstance, 0,
2259 GlobalSize16(wndPtr->hInstance))) {
2260 fprintf(stderr, "edit: WM_CREATE: could not initialize local heap\n");
2261 return -1L;
2263 dprintf_edit(stddeb, "edit: WM_CREATE: local heap initialized\n");
2265 if (!(es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1))) {
2266 fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
2267 return -1L;
2269 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
2270 text = EDIT_GetPointer(wndPtr);
2271 *text = '\0';
2272 EDIT_BuildLineDefs(wndPtr);
2273 EDIT_WM_SetFont(wndPtr, 0, 0L);
2274 if (cs->lpszName && *(char *)PTR_SEG_TO_LIN(cs->lpszName) != '\0')
2275 EDIT_EM_ReplaceSel(wndPtr, FALSE, (LPARAM)cs->lpszName);
2276 EDIT_WM_SetRedraw(wndPtr, TRUE, 0L);
2277 return 0L;
2281 /*********************************************************************
2283 * WM_CUT
2286 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2288 EDIT_WM_Copy(wndPtr, 0, 0L);
2289 EDIT_WM_Clear(wndPtr, 0, 0L);
2290 return -1L;
2294 /*********************************************************************
2296 * WM_DESTROY
2299 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2301 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2303 free(es->LineDefs);
2304 if (es->TabStops)
2305 free(es->TabStops);
2306 EDIT_ReleasePointer(wndPtr);
2307 LOCAL_Free(wndPtr->hInstance, es->hBuf);
2308 free(es);
2309 *(EDITSTATE **)&wndPtr->wExtra = NULL;
2310 return 0L;
2314 /*********************************************************************
2316 * WM_ENABLE
2319 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2321 EDIT_InvalidateText(wndPtr, 0, -1);
2322 return 0L;
2326 /*********************************************************************
2328 * WM_ERASEBKGND
2331 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2333 HBRUSH32 hBrush;
2334 RECT16 rc;
2336 hBrush = (HBRUSH16)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
2337 if (!hBrush) hBrush = (HBRUSH32)GetStockObject32(WHITE_BRUSH);
2339 GetClientRect16(wndPtr->hwndSelf, &rc);
2340 IntersectClipRect16( (HDC16)wParam, rc.left, rc.top,
2341 rc.right, rc.bottom);
2342 GetClipBox16((HDC16)wParam, &rc);
2344 * FIXME: specs say that we should UnrealizeObject() the brush,
2345 * but the specs of UnrealizeObject() say that we shouldn't
2346 * unrealize a stock object. The default brush that
2347 * DefWndProc() returns is ... a stock object.
2349 FillRect16((HDC16)wParam, &rc, hBrush);
2350 return -1L;
2354 /*********************************************************************
2356 * WM_GETDLGCODE
2359 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2361 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
2365 /*********************************************************************
2367 * WM_GETFONT
2370 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2372 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2374 return (LRESULT)es->hFont;
2378 /*********************************************************************
2380 * WM_GETTEXT
2383 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2385 char *text = EDIT_GetPointer(wndPtr);
2386 int len;
2387 LRESULT lResult = 0L;
2389 len = strlen(text);
2390 if ((UINT)wParam > len) {
2391 strcpy((char *)PTR_SEG_TO_LIN(lParam), text);
2392 lResult = (LRESULT)len ;
2394 return lResult;
2398 /*********************************************************************
2400 * WM_GETTEXTLENGTH
2403 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2405 char *text = EDIT_GetPointer(wndPtr);
2407 return (LRESULT)strlen(text);
2411 /*********************************************************************
2413 * WM_HSCROLL
2415 * FIXME: scrollbar code itself is broken, so this one is a hack.
2418 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2420 UINT ww = EDIT_GetWndWidth(wndPtr);
2421 UINT tw = EDIT_GetTextWidth(wndPtr);
2422 UINT cw = EDIT_GetAveCharWidth(wndPtr);
2423 UINT xoff = EDIT_GetXOffset(wndPtr);
2424 INT dx = 0;
2425 BOOL not = TRUE;
2426 LRESULT ret = 0L;
2428 switch (wParam) {
2429 case SB_LINELEFT:
2430 dx = -cw;
2431 break;
2432 case SB_LINERIGHT:
2433 dx = cw;
2434 break;
2435 case SB_PAGELEFT:
2436 dx = -ww / HSCROLL_FRACTION / cw * cw;
2437 break;
2438 case SB_PAGERIGHT:
2439 dx = ww / HSCROLL_FRACTION / cw * cw;
2440 break;
2441 case SB_LEFT:
2442 dx = -xoff;
2443 break;
2444 case SB_RIGHT:
2445 dx = tw - xoff;
2446 break;
2447 case SB_THUMBTRACK:
2449 * not = FALSE;
2451 case SB_THUMBPOSITION:
2452 dx = LOWORD(lParam) * tw / 100 - xoff;
2453 break;
2454 /* The next two are undocumented ! */
2455 case EM_GETTHUMB:
2456 ret = tw ? MAKELONG(xoff * 100 / tw, 0) : 0;
2457 break;
2458 case EM_LINESCROLL:
2459 dx = LOWORD(lParam);
2460 break;
2461 case SB_ENDSCROLL:
2462 default:
2463 break;
2465 if (dx) {
2466 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(0, dx));
2467 if (not)
2468 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
2470 return ret;
2474 /*********************************************************************
2476 * WM_KEYDOWN
2478 * Handling of special keys that don't produce a WM_CHAR
2479 * (i.e. non-printable keys) & Backspace & Delete
2482 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2484 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
2485 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
2486 BOOL shift;
2487 BOOL control;
2489 if (GetKeyState(VK_MENU) & 0x8000)
2490 return 0L;
2492 shift = GetKeyState(VK_SHIFT) & 0x8000;
2493 control = GetKeyState(VK_CONTROL) & 0x8000;
2495 switch (wParam) {
2496 case VK_LEFT:
2497 case VK_UP:
2498 if (IsMultiLine(wndPtr) && (wParam == VK_UP))
2499 EDIT_MoveUpward(wndPtr, shift);
2500 else
2501 if (control)
2502 EDIT_MoveWordBackward(wndPtr, shift);
2503 else
2504 EDIT_MoveBackward(wndPtr, shift);
2505 break;
2506 case VK_RIGHT:
2507 case VK_DOWN:
2508 if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
2509 EDIT_MoveDownward(wndPtr, shift);
2510 else if (control)
2511 EDIT_MoveWordForward(wndPtr, shift);
2512 else
2513 EDIT_MoveForward(wndPtr, shift);
2514 break;
2515 case VK_HOME:
2516 EDIT_MoveHome(wndPtr, shift);
2517 break;
2518 case VK_END:
2519 EDIT_MoveEnd(wndPtr, shift);
2520 break;
2521 case VK_PRIOR:
2522 if (IsMultiLine(wndPtr))
2523 EDIT_MovePageUp(wndPtr, shift);
2524 break;
2525 case VK_NEXT:
2526 if (IsMultiLine(wndPtr))
2527 EDIT_MovePageDown(wndPtr, shift);
2528 break;
2529 case VK_BACK:
2530 if (!IsReadOnly(wndPtr) && !control)
2531 if (e != s)
2532 EDIT_WM_Clear(wndPtr, 0, 0L);
2533 else
2534 EDIT_DelLeft(wndPtr);
2535 break;
2536 case VK_DELETE:
2537 if (!IsReadOnly(wndPtr) && !(shift && control))
2538 if (e != s) {
2539 if (shift)
2540 EDIT_WM_Cut(wndPtr, 0, 0L);
2541 else
2542 EDIT_WM_Clear(wndPtr, 0, 0L);
2543 } else {
2544 if (shift)
2545 EDIT_DelLeft(wndPtr);
2546 else if (control)
2547 EDIT_DelEnd(wndPtr);
2548 else
2549 EDIT_DelRight(wndPtr);
2551 break;
2552 case VK_INSERT:
2553 if (shift) {
2554 if (!IsReadOnly(wndPtr))
2555 EDIT_WM_Paste(wndPtr, 0, 0L);
2556 } else if (control)
2557 EDIT_WM_Copy(wndPtr, 0, 0L);
2558 break;
2560 return 0L;
2564 /*********************************************************************
2566 * WM_KILLFOCUS
2569 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2571 UINT s;
2572 UINT e;
2574 DestroyCaret();
2575 if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
2576 s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
2577 e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
2578 EDIT_InvalidateText(wndPtr, s, e);
2580 EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
2581 return 0L;
2585 /*********************************************************************
2587 * WM_LBUTTONDBLCLK
2589 * The caret position has been set on the WM_LBUTTONDOWN message
2592 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2594 UINT s;
2595 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
2596 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
2597 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2598 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
2599 char *text = EDIT_GetPointer(wndPtr);
2601 s = li + EDIT_CallWordBreakProc (wndPtr, text + li, e - li, ll, WB_LEFT);
2602 e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
2603 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2604 return 0L;
2608 /*********************************************************************
2610 * WM_LBUTTONDOWN
2613 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2615 INT x = (INT)LOWORD(lParam);
2616 INT y = (INT)HIWORD(lParam);
2617 UINT l = EDIT_LineFromWndY(wndPtr, y);
2618 UINT c;
2619 UINT s;
2620 UINT e;
2621 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2622 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2623 UINT li;
2625 SetFocus32(wndPtr->hwndSelf);
2626 SetCapture32(wndPtr->hwndSelf);
2627 l = MIN(fv + vlc - 1, MAX(fv, l));
2628 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
2629 c = EDIT_ColFromWndX(wndPtr, l, x);
2630 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2631 e = li + c;
2632 if (GetKeyState(VK_SHIFT) & 0x8000)
2633 s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
2634 else
2635 s = e;
2636 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2637 return 0L;
2641 /*********************************************************************
2643 * WM_LBUTTONUP
2646 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2648 if (GetCapture32() == wndPtr->hwndSelf)
2649 ReleaseCapture();
2650 return 0L;
2654 /*********************************************************************
2656 * WM_MOUSEMOVE
2659 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2661 INT x;
2662 INT y;
2663 UINT l;
2664 UINT c;
2665 UINT s;
2666 UINT fv;
2667 UINT vlc;
2668 UINT li;
2670 if (GetCapture32() == wndPtr->hwndSelf) {
2671 x = (INT)LOWORD(lParam);
2672 y = (INT)HIWORD(lParam);
2673 fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2674 vlc = EDIT_GetVisibleLineCount(wndPtr);
2675 l = EDIT_LineFromWndY(wndPtr, y);
2676 l = MIN(fv + vlc - 1, MAX(fv, l));
2677 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
2678 c = EDIT_ColFromWndX(wndPtr, l, x);
2679 s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
2680 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2681 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, li + c));
2683 return 0L;
2687 /*********************************************************************
2689 * WM_PAINT
2692 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2694 PAINTSTRUCT16 ps;
2695 UINT i;
2696 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2697 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2698 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2699 HDC16 hdc;
2700 HFONT16 hFont;
2701 HFONT32 oldFont = 0;
2702 RECT16 rc;
2703 RECT16 rcLine;
2704 RECT16 rcRgn;
2705 BOOL rev = IsWindowEnabled(wndPtr->hwndSelf) &&
2706 ((GetFocus32() == wndPtr->hwndSelf) ||
2707 (wndPtr->dwStyle & ES_NOHIDESEL));
2709 hdc = BeginPaint16(wndPtr->hwndSelf, &ps);
2710 GetClientRect16(wndPtr->hwndSelf, &rc);
2711 IntersectClipRect16( hdc, rc.left, rc.top, rc.right, rc.bottom );
2712 hFont = EDIT_WM_GetFont(wndPtr, 0, 0L);
2713 if (hFont) oldFont = SelectObject32(hdc, hFont);
2714 EDIT_SEND_CTLCOLOR(wndPtr, hdc);
2715 if (!IsWindowEnabled(wndPtr->hwndSelf))
2716 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
2717 GetClipBox16(hdc, &rcRgn);
2718 for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
2719 EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
2720 if (IntersectRect16(&rc, &rcRgn, &rcLine))
2721 EDIT_PaintLine(wndPtr, hdc, i, rev);
2723 if (hFont) SelectObject32(hdc, oldFont);
2724 EndPaint16(wndPtr->hwndSelf, &ps);
2725 return 0L;
2729 /*********************************************************************
2731 * WM_PASTE
2734 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2736 HGLOBAL16 hsrc;
2737 char *src;
2739 OpenClipboard(wndPtr->hwndSelf);
2740 if ((hsrc = GetClipboardData(CF_TEXT))) {
2741 src = (char *)GlobalLock16(hsrc);
2742 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)src);
2743 GlobalUnlock16(hsrc);
2745 CloseClipboard();
2746 return -1L;
2750 /*********************************************************************
2752 * WM_SETCURSOR
2755 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2757 if (LOWORD(lParam) == HTCLIENT) {
2758 SetCursor(LoadCursor16(0, IDC_IBEAM));
2759 return -1L;
2760 } else
2761 return 0L;
2765 /*********************************************************************
2767 * WM_SETFOCUS
2770 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2772 UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
2773 UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
2775 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2776 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, e));
2777 if(!(wndPtr->dwStyle & ES_NOHIDESEL))
2778 EDIT_InvalidateText(wndPtr, s, e);
2779 ShowCaret(wndPtr->hwndSelf);
2780 EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
2781 return 0L;
2785 /*********************************************************************
2787 * WM_SETFONT
2790 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2792 TEXTMETRIC16 tm;
2793 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2794 LPARAM sel = EDIT_GetSel(wndPtr, 0, 0L);
2795 HDC32 hdc;
2796 HFONT32 oldFont = 0;
2798 es->hFont = (HFONT16)wParam;
2799 hdc = GetDC32(wndPtr->hwndSelf);
2800 if (es->hFont) oldFont = SelectObject32(hdc, es->hFont);
2801 GetTextMetrics16(hdc, &tm);
2802 es->LineHeight = HIWORD(GetTextExtent(hdc, "X", 1));
2803 es->AveCharWidth = tm.tmAveCharWidth;
2804 if (es->hFont) SelectObject32(hdc, oldFont);
2805 ReleaseDC32(wndPtr->hwndSelf, hdc);
2806 EDIT_BuildLineDefs(wndPtr);
2807 if ((BOOL)lParam && EDIT_GetRedraw(wndPtr))
2808 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2809 if (wndPtr->hwndSelf == GetFocus32()) {
2810 DestroyCaret();
2811 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2812 EDIT_EM_SetSel(wndPtr, 1, sel);
2813 ShowCaret(wndPtr->hwndSelf);
2815 return 0L;
2819 /*********************************************************************
2821 * WM_SETREDRAW
2824 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2826 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2828 es->Redraw = (BOOL)wParam;
2829 return 0L;
2833 /*********************************************************************
2835 * WM_SETTEXT
2838 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2840 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(0, -1));
2841 EDIT_WM_Clear(wndPtr, 0, 0L);
2842 if (lParam)
2843 EDIT_EM_ReplaceSel(wndPtr, 0, lParam);
2844 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
2845 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2846 EDIT_ScrollIntoView(wndPtr);
2847 return 0L;
2851 /*********************************************************************
2853 * WM_SIZE
2856 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2858 if (EDIT_GetRedraw(wndPtr) &&
2859 ((wParam == SIZE_MAXIMIZED) ||
2860 (wParam == SIZE_RESTORED))) {
2861 if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
2862 EDIT_BuildLineDefs(wndPtr);
2863 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2865 return 0L;
2869 /*********************************************************************
2871 * WM_VSCROLL
2873 * FIXME: scrollbar code itself is broken, so this one is a hack.
2876 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2878 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2879 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2880 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2881 INT dy = 0;
2882 BOOL not = TRUE;
2883 LRESULT ret = 0L;
2885 switch (wParam) {
2886 case SB_LINEUP:
2887 dy = -1;
2888 break;
2889 case SB_LINEDOWN:
2890 dy = 1;
2891 break;
2892 case SB_PAGEUP:
2893 dy = -vlc;
2894 break;
2895 case SB_PAGEDOWN:
2896 dy = vlc;
2897 break;
2898 case SB_TOP:
2899 dy = -fv;
2900 break;
2901 case SB_BOTTOM:
2902 dy = lc - 1 - fv;
2903 break;
2904 case SB_THUMBTRACK:
2906 * not = FALSE;
2908 case SB_THUMBPOSITION:
2909 dy = LOWORD(lParam) * (lc - 1) / 100 - fv;
2910 break;
2911 /* The next two are undocumented ! */
2912 case EM_GETTHUMB:
2913 ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0L;
2914 break;
2915 case EM_LINESCROLL:
2916 dy = LOWORD(lParam);
2917 break;
2918 case SB_ENDSCROLL:
2919 default:
2920 break;
2922 if (dy) {
2923 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, 0));
2924 if (not)
2925 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
2927 return ret;