Release 961023
[wine/multimedia.git] / controls / edit.c
blobf37c058825ae1f108a5d883bc160d14afb03e1b0
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 UINT EDIT_GetTextWidth(WND *wndPtr);
123 static UINT EDIT_GetVisibleLineCount(WND *wndPtr);
124 static UINT EDIT_GetWndWidth(WND *wndPtr);
125 static UINT EDIT_GetXOffset(WND *wndPtr);
126 static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end);
127 static UINT EDIT_LineFromWndY(WND *wndPtr, INT y);
128 static BOOL EDIT_MakeFit(WND *wndPtr, UINT size);
129 static void EDIT_MoveBackward(WND *wndPtr, BOOL extend);
130 static void EDIT_MoveDownward(WND *wndPtr, BOOL extend);
131 static void EDIT_MoveEnd(WND *wndPtr, BOOL extend);
132 static void EDIT_MoveForward(WND *wndPtr, BOOL extend);
133 static void EDIT_MoveHome(WND *wndPtr, BOOL extend);
134 static void EDIT_MovePageDown(WND *wndPtr, BOOL extend);
135 static void EDIT_MovePageUp(WND *wndPtr, BOOL extend);
136 static void EDIT_MoveUpward(WND *wndPtr, BOOL extend);
137 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend);
138 static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend);
139 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, UINT line, BOOL rev);
140 static UINT EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev);
141 static void EDIT_ReleasePointer(WND *wndPtr);
142 static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
143 static void EDIT_ScrollIntoView(WND *wndPtr);
144 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col);
145 static INT EDIT_WndYFromLine(WND *wndPtr, UINT line);
146 static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action);
148 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
149 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
150 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
151 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
152 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
153 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
154 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
155 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
156 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
157 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
158 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
159 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
160 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
161 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
162 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
163 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
164 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
165 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
166 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
167 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
168 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
169 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
170 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
171 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
172 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
173 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
174 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
175 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
176 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
177 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
179 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
180 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
181 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
182 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
183 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
184 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
185 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
186 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
187 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
188 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
189 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
190 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
191 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
192 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
193 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
194 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
195 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
196 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
197 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
198 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
199 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
200 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
201 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
202 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
203 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
204 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
205 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
206 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
209 /*********************************************************************
211 * General shortcuts for variable names:
213 * UINT l; line
214 * UINT c; column
215 * UINT s; offset of selection start
216 * UINT e; offset of selection end
217 * UINT sl; line on which the selection starts
218 * UINT el; line on which the selection ends
219 * UINT sc; column on which the selection starts
220 * UINT ec; column on which the selection ends
221 * UINT li; line index (offset)
222 * UINT fv; first visible line
223 * UINT vlc; vissible line count
224 * UINT lc; line count
225 * UINT lh; line height (in pixels)
226 * UINT tw; text width (in pixels)
227 * UINT ww; window width (in pixels)
228 * UINT cw; character width (average, in pixels)
233 /*********************************************************************
235 * EditWndProc()
238 LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM16 wParam, LPARAM lParam)
240 LRESULT lResult = 0L;
241 WND *wndPtr = WIN_FindWndPtr(hwnd);
243 if ((!EDITSTATEPTR(wndPtr)) && (msg != WM_CREATE))
244 return DefWindowProc16(hwnd, msg, wParam, lParam);
246 switch (msg) {
247 case EM_CANUNDO:
248 DPRINTF_EDIT_MSG("EM_CANUNDO");
249 lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
250 break;
251 case EM_EMPTYUNDOBUFFER:
252 DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER");
253 lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
254 break;
255 case EM_FMTLINES:
256 DPRINTF_EDIT_MSG("EM_FMTLINES");
257 lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
258 break;
259 case EM_GETFIRSTVISIBLELINE:
260 DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE");
261 lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
262 break;
263 case EM_GETHANDLE:
264 DPRINTF_EDIT_MSG("EM_GETHANDLE");
265 lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
266 break;
267 case EM_GETLINE:
268 DPRINTF_EDIT_MSG("EM_GETLINE");
269 lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
270 break;
271 case EM_GETLINECOUNT:
272 DPRINTF_EDIT_MSG("EM_GETLINECOUNT");
273 lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
274 break;
275 case EM_GETMODIFY:
276 DPRINTF_EDIT_MSG("EM_GETMODIFY");
277 lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
278 break;
279 case EM_GETPASSWORDCHAR:
280 DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR");
281 lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
282 break;
283 case EM_GETRECT:
284 DPRINTF_EDIT_MSG("EM_GETRECT");
285 lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
286 break;
287 case EM_GETSEL:
288 DPRINTF_EDIT_MSG("EM_GETSEL");
289 lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
290 break;
291 case EM_GETTHUMB:
292 DPRINTF_EDIT_MSG("EM_GETTHUMB");
293 lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
294 break;
295 case EM_GETWORDBREAKPROC:
296 DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC");
297 lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
298 break;
299 case EM_LIMITTEXT:
300 DPRINTF_EDIT_MSG("EM_LIMITTEXT");
301 lResult = EDIT_EM_LimitText(wndPtr, wParam, lParam);
302 break;
303 case EM_LINEFROMCHAR:
304 DPRINTF_EDIT_MSG("EM_LINEFROMCHAR");
305 lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
306 break;
307 case EM_LINEINDEX:
308 DPRINTF_EDIT_MSG("EM_LINEINDEX");
309 lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
310 break;
311 case EM_LINELENGTH:
312 DPRINTF_EDIT_MSG("EM_LINELENGTH");
313 lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
314 break;
315 case EM_LINESCROLL:
316 DPRINTF_EDIT_MSG("EM_LINESCROLL");
317 lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
318 break;
319 case EM_REPLACESEL:
320 DPRINTF_EDIT_MSG("EM_REPLACESEL");
321 lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
322 break;
323 case EM_SCROLL:
324 DPRINTF_EDIT_MSG("EM_SCROLL");
325 lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
326 break;
327 case EM_SETHANDLE:
328 DPRINTF_EDIT_MSG("EM_SETHANDLE");
329 lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
330 break;
331 case EM_SETMODIFY:
332 DPRINTF_EDIT_MSG("EM_SETMODIFY");
333 lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
334 break;
335 case EM_SETPASSWORDCHAR:
336 DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR");
337 lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
338 break;
339 case EM_SETREADONLY:
340 DPRINTF_EDIT_MSG("EM_SETREADONLY");
341 lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
342 break;
343 case EM_SETRECT:
344 DPRINTF_EDIT_MSG("EM_SETRECT");
345 lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
346 break;
347 case EM_SETRECTNP:
348 DPRINTF_EDIT_MSG("EM_SETRECTNP");
349 lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
350 break;
351 case EM_SETSEL:
352 DPRINTF_EDIT_MSG("EM_SETSEL");
353 lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
354 break;
355 case EM_SETTABSTOPS:
356 DPRINTF_EDIT_MSG("EM_SETTABSTOPS");
357 lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
358 break;
359 case EM_SETWORDBREAKPROC:
360 DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC");
361 lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
362 break;
363 case EM_UNDO:
364 case WM_UNDO:
365 DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO");
366 lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
367 break;
368 case WM_GETDLGCODE:
369 DPRINTF_EDIT_MSG("WM_GETDLGCODE");
370 lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
371 break;
372 case WM_CHAR:
373 DPRINTF_EDIT_MSG("WM_CHAR");
374 lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
375 break;
376 case WM_CLEAR:
377 DPRINTF_EDIT_MSG("WM_CLEAR");
378 lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
379 break;
380 case WM_COPY:
381 DPRINTF_EDIT_MSG("WM_COPY");
382 lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
383 break;
384 case WM_CREATE:
385 DPRINTF_EDIT_MSG("WM_CREATE");
386 lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
387 break;
388 case WM_CUT:
389 DPRINTF_EDIT_MSG("WM_CUT");
390 lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
391 break;
392 case WM_DESTROY:
393 DPRINTF_EDIT_MSG("WM_DESTROY");
394 lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
395 break;
396 case WM_ENABLE:
397 DPRINTF_EDIT_MSG("WM_ENABLE");
398 lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
399 break;
400 case WM_ERASEBKGND:
401 DPRINTF_EDIT_MSG("WM_ERASEBKGND");
402 lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
403 break;
404 case WM_GETFONT:
405 DPRINTF_EDIT_MSG("WM_GETFONT");
406 lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
407 break;
408 case WM_GETTEXT:
409 DPRINTF_EDIT_MSG("WM_GETTEXT");
410 lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
411 break;
412 case WM_GETTEXTLENGTH:
413 DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH");
414 lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
415 break;
416 case WM_HSCROLL:
417 DPRINTF_EDIT_MSG("WM_HSCROLL");
418 lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
419 break;
420 case WM_KEYDOWN:
421 DPRINTF_EDIT_MSG("WM_KEYDOWN");
422 lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
423 break;
424 case WM_KILLFOCUS:
425 DPRINTF_EDIT_MSG("WM_KILLFOCUS");
426 lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
427 break;
428 case WM_LBUTTONDBLCLK:
429 DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK");
430 lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
431 break;
432 case WM_LBUTTONDOWN:
433 DPRINTF_EDIT_MSG("WM_LBUTTONDOWN");
434 lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
435 break;
436 case WM_LBUTTONUP:
437 DPRINTF_EDIT_MSG("WM_LBUTTONUP");
438 lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
439 break;
440 case WM_MOUSEMOVE:
442 * DPRINTF_EDIT_MSG("WM_MOUSEMOVE");
444 lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
445 break;
446 case WM_PAINT:
447 DPRINTF_EDIT_MSG("WM_PAINT");
448 lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
449 break;
450 case WM_PASTE:
451 DPRINTF_EDIT_MSG("WM_PASTE");
452 lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
453 break;
454 case WM_SETCURSOR:
456 * DPRINTF_EDIT_MSG("WM_SETCURSOR");
458 lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
459 break;
460 case WM_SETFOCUS:
461 DPRINTF_EDIT_MSG("WM_SETFOCUS");
462 lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
463 break;
464 case WM_SETFONT:
465 DPRINTF_EDIT_MSG("WM_SETFONT");
466 lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
467 break;
468 case WM_SETREDRAW:
469 DPRINTF_EDIT_MSG("WM_SETREDRAW");
470 lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
471 break;
472 case WM_SETTEXT:
473 DPRINTF_EDIT_MSG("WM_SETTEXT");
474 lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
475 break;
476 case WM_SIZE:
477 DPRINTF_EDIT_MSG("WM_SIZE");
478 lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
479 break;
480 case WM_VSCROLL:
481 DPRINTF_EDIT_MSG("WM_VSCROLL");
482 lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
483 break;
484 default:
485 /* Some programs pass messages obtained through
486 * RegisterWindowMessage() (>= 0xc000); we just ignore them
488 if ((msg >= WM_USER) && (msg < 0xc000))
489 fprintf(stdnimp, "edit: undocumented message %d >= WM_USER, please report.\n", msg);
490 lResult = DefWindowProc16(hwnd, msg, wParam, lParam);
491 break;
493 EDIT_ReleasePointer(wndPtr);
494 return lResult;
498 /*********************************************************************
500 * EDIT_BuildLineDefs
502 * Build array of pointers to text lines.
503 * Lines can end with '\0' (last line), nothing (if it is too long),
504 * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
507 static void EDIT_BuildLineDefs(WND *wndPtr)
509 EDITSTATE *es = EDITSTATEPTR(wndPtr);
510 char *text = EDIT_GetPasswordPointer(wndPtr);
511 int ww = EDIT_GetWndWidth(wndPtr);
512 HDC32 hdc;
513 HFONT16 hFont;
514 HFONT16 oldFont = 0;
515 char *start, *cp;
516 int prev, next;
517 int width;
518 int length;
519 LINE_END ending;
521 hdc = GetDC32(wndPtr->hwndSelf);
522 hFont = (HFONT16)EDIT_WM_GetFont(wndPtr, 0, 0L);
523 if (hFont)
524 oldFont = SelectObject(hdc, hFont);
526 if (!IsMultiLine(wndPtr)) {
527 es->LineCount = 1;
528 es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
529 es->LineDefs[0].offset = 0;
530 es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
531 es->LineDefs[0].ending = END_0;
532 es->TextWidth = LOWORD(GetTabbedTextExtent(hdc, text,
533 es->LineDefs[0].length,
534 es->NumTabStops, es->TabStops));
535 } else {
536 es->LineCount = 0;
537 start = text;
538 do {
539 if (!(cp = strstr(start, "\r\n"))) {
540 ending = END_0;
541 length = strlen(start);
542 } else if ((cp > start) && (*(cp - 1) == '\r')) {
543 ending = END_SOFT;
544 length = cp - start - 1;
545 } else {
546 ending = END_HARD;
547 length = cp - start;
549 width = LOWORD(GetTabbedTextExtent(hdc, start, length,
550 es->NumTabStops, es->TabStops));
552 if (IsWordWrap(wndPtr) && (width > ww)) {
553 next = 0;
554 do {
555 prev = next;
556 next = EDIT_CallWordBreakProc(wndPtr, start,
557 prev + 1, length, WB_RIGHT);
558 width = LOWORD(GetTabbedTextExtent(hdc, start, next,
559 es->NumTabStops, es->TabStops));
560 } while (width <= ww);
561 if (!prev) {
562 next = 0;
563 do {
564 prev = next;
565 next++;
566 width = LOWORD(GetTabbedTextExtent(hdc, start, next,
567 es->NumTabStops, es->TabStops));
568 } while (width <= ww);
569 if(!prev) prev = 1;
571 length = prev;
572 if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
573 length, WB_ISDELIMITER)) {
574 length--;
575 ending = END_DELIMIT;
576 } else
577 ending = END_NONE;
578 width = LOWORD(GetTabbedTextExtent(hdc, start, length,
579 es->NumTabStops, es->TabStops));
582 es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF));
583 es->LineDefs[es->LineCount].offset = start - text;
584 es->LineDefs[es->LineCount].length = length;
585 es->LineDefs[es->LineCount].ending = ending;
586 es->LineCount++;
587 es->TextWidth = MAX(es->TextWidth, width);
589 start += length;
590 switch (ending) {
591 case END_SOFT:
592 start += 3;
593 break;
594 case END_HARD:
595 start += 2;
596 break;
597 case END_DELIMIT:
598 start++;
599 break;
600 default:
601 break;
603 } while (*start || (ending == END_SOFT) || (ending == END_HARD));
605 if (hFont)
606 SelectObject(hdc, oldFont);
607 ReleaseDC32(wndPtr->hwndSelf, hdc);
609 free(text);
613 /*********************************************************************
615 * EDIT_CallWordBreakProc
617 * Call appropriate WordBreakProc (internal or external).
620 static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action)
622 EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0L);
624 if (!wbp) return EDIT_WordBreakProc(s, index, count, action);
625 else
627 /* We need a SEGPTR here */
629 EDITSTATE *es = EDITSTATEPTR(wndPtr);
630 SEGPTR ptr = LOCAL_LockSegptr( wndPtr->hInstance, es->hBuf ) +
631 (UINT16)(s - EDIT_GetPointer(wndPtr));
632 INT ret = CallWordBreakProc( (FARPROC16)wbp, ptr,
633 index, count, action);
634 LOCAL_Unlock( wndPtr->hInstance, es->hBuf );
635 return ret;
640 /*********************************************************************
642 * EDIT_ColFromWndX
644 * Calculates, for a given line and X-coordinate on the screen, the column.
647 static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x)
649 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
650 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
651 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
652 UINT i;
654 line = MAX(0, MIN(line, lc - 1));
655 for (i = 0 ; i < ll ; i++)
656 if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
657 break;
658 return i;
662 /*********************************************************************
664 * EDIT_DelEnd
666 * Delete all characters on this line to right of cursor.
669 static void EDIT_DelEnd(WND *wndPtr)
671 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
672 EDIT_MoveEnd(wndPtr, TRUE);
673 EDIT_WM_Clear(wndPtr, 0, 0L);
677 /*********************************************************************
679 * EDIT_DelLeft
681 * Delete character to left of cursor.
684 static void EDIT_DelLeft(WND *wndPtr)
686 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
687 EDIT_MoveBackward(wndPtr, TRUE);
688 EDIT_WM_Clear(wndPtr, 0, 0L);
692 /*********************************************************************
694 * EDIT_DelRight
696 * Delete character to right of cursor.
699 static void EDIT_DelRight(WND *wndPtr)
701 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
702 EDIT_MoveForward(wndPtr, TRUE);
703 EDIT_WM_Clear(wndPtr, 0, 0L);
707 /*********************************************************************
709 * EDIT_GetAveCharWidth
712 static UINT EDIT_GetAveCharWidth(WND *wndPtr)
714 EDITSTATE *es = EDITSTATEPTR(wndPtr);
716 return es->AveCharWidth;
720 /*********************************************************************
722 * EDIT_GetLineHeight
725 static UINT EDIT_GetLineHeight(WND *wndPtr)
727 EDITSTATE *es = EDITSTATEPTR(wndPtr);
729 return es->LineHeight;
733 /*********************************************************************
735 * EDIT_GetLineRect
737 * Calculates the bounding rectangle for a line from a starting
738 * column to an ending column.
741 static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc)
743 rc->top = EDIT_WndYFromLine(wndPtr, line);
744 rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
745 rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
746 rc->right = ((INT)ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
747 EDIT_WndXFromCol(wndPtr, line, ecol);
751 /*********************************************************************
753 * EDIT_GetPointer
755 * This acts as a LOCAL_Lock(), but it locks only once. This way
756 * you can call it whenever you like, without unlocking.
759 static char *EDIT_GetPointer(WND *wndPtr)
761 EDITSTATE *es = EDITSTATEPTR(wndPtr);
763 if (!es->text && es->hBuf)
764 es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf);
765 return es->text;
769 /*********************************************************************
771 * EDIT_GetPasswordPointer
775 static char *EDIT_GetPasswordPointer(WND *wndPtr)
777 EDITSTATE *es = EDITSTATEPTR(wndPtr);
778 char *text = xstrdup(EDIT_GetPointer(wndPtr));
779 char *p;
781 if(es->PasswordChar) {
782 p = text;
783 while(*p != '\0') {
784 if(*p != '\r' && *p != '\n')
785 *p = es->PasswordChar;
786 p++;
789 return text;
793 /*********************************************************************
795 * EDIT_GetRect
797 * Beware: This is not the function called on EM_GETRECT.
798 * It expects a (LPRECT) in lParam, not a (SEGPTR).
799 * It is used internally, as if there were no pointer difficulties.
802 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
804 GetClientRect16( wndPtr->hwndSelf, (LPRECT16)lParam );
805 return 0L;
809 /*********************************************************************
811 * EDIT_GetRedraw
814 static BOOL EDIT_GetRedraw(WND *wndPtr)
816 EDITSTATE *es = EDITSTATEPTR(wndPtr);
818 return es->Redraw;
822 /*********************************************************************
824 * EDIT_GetTextWidth
827 static UINT EDIT_GetTextWidth(WND *wndPtr)
829 EDITSTATE *es = EDITSTATEPTR(wndPtr);
831 return es->TextWidth;
835 /*********************************************************************
837 * EDIT_GetVisibleLineCount
840 static UINT EDIT_GetVisibleLineCount(WND *wndPtr)
842 RECT16 rc;
844 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
845 return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
849 /*********************************************************************
851 * EDIT_GetWndWidth
854 static UINT EDIT_GetWndWidth(WND *wndPtr)
856 RECT16 rc;
858 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
859 return rc.right - rc.left;
863 /*********************************************************************
865 * EDIT_GetXOffset
868 static UINT EDIT_GetXOffset(WND *wndPtr)
870 EDITSTATE *es = EDITSTATEPTR(wndPtr);
872 return es->XOffset;
876 /*********************************************************************
878 * EDIT_InvalidateText
880 * Invalidate the text from offset start upto, but not including,
881 * offset end. Useful for (re)painting the selection.
882 * Regions outside the linewidth are not invalidated.
883 * end == -1 means end == TextLength.
884 * start and end need not be ordered.
887 static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end)
889 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
890 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
891 UINT sl;
892 UINT el;
893 UINT sc;
894 UINT ec;
895 RECT16 rcWnd;
896 RECT16 rcLine;
897 RECT16 rcUpdate;
898 UINT l;
900 if (end == start )
901 return;
903 if ((INT)end == -1)
904 end = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
905 ORDER_UINT(start, end);
906 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, start, 0L);
907 el = (UINT)EDIT_EM_LineFromChar(wndPtr, end, 0L);
908 if ((el < fv) || (sl > fv + vlc))
909 return;
911 sc = start - (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L);
912 ec = end - (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
913 if (sl < fv) {
914 sl = fv;
915 sc = 0;
917 if (el > fv + vlc) {
918 el = fv + vlc;
919 ec = (UINT)EDIT_EM_LineLength(wndPtr,
920 (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L), 0L);
922 EDIT_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
923 if (sl == el) {
924 EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
925 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
926 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
927 } else {
928 EDIT_GetLineRect(wndPtr, sl, sc,
929 (UINT)EDIT_EM_LineLength(wndPtr,
930 (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L), 0L),
931 &rcLine);
932 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
933 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
934 for (l = sl + 1 ; l < el ; l++) {
935 EDIT_GetLineRect(wndPtr, l, 0,
936 (UINT)EDIT_EM_LineLength(wndPtr,
937 (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L), 0L),
938 &rcLine);
939 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
940 InvalidateRect16(wndPtr->hwndSelf, &rcUpdate, FALSE);
942 EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
943 if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
944 InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
949 /*********************************************************************
951 * EDIT_LineFromWndY
953 * Calculates, for a given Y-coordinate on the screen, the line.
956 static UINT EDIT_LineFromWndY(WND *wndPtr, INT y)
958 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
959 UINT lh = EDIT_GetLineHeight(wndPtr);
960 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
962 return MAX(0, MIN(lc - 1, y / lh + fv));
966 /*********************************************************************
968 * EDIT_MakeFit
970 * Try to fit size + 1 bytes in the buffer. Constrain to limits.
973 static BOOL EDIT_MakeFit(WND *wndPtr, UINT size)
975 EDITSTATE *es = EDITSTATEPTR(wndPtr);
977 if (size <= es->BufSize)
978 return TRUE;
979 if (size > es->BufLimit)
980 return FALSE;
981 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
982 if (size > es->BufLimit)
983 size = es->BufLimit;
985 dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
987 if (LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, size + 1, LMEM_MOVEABLE)) {
988 es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1, es->BufLimit);
989 return TRUE;
990 } else
991 return FALSE;
995 /*********************************************************************
997 * EDIT_MoveBackward
1000 static void EDIT_MoveBackward(WND *wndPtr, BOOL extend)
1002 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1003 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1004 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1005 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1007 if (e - li == 0) {
1008 if (l) {
1009 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
1010 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1012 } else
1013 e--;
1014 if (!extend)
1015 s = e;
1016 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1020 /*********************************************************************
1022 * EDIT_MoveDownward
1025 static void EDIT_MoveDownward(WND *wndPtr, BOOL extend)
1027 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1028 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1029 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1030 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1031 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1032 INT x;
1034 if (l < lc - 1) {
1035 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1036 l++;
1037 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1038 EDIT_ColFromWndX(wndPtr, l, x);
1040 if (!extend)
1041 s = e;
1042 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1046 /*********************************************************************
1048 * EDIT_MoveEnd
1051 static void EDIT_MoveEnd(WND *wndPtr, BOOL extend)
1053 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1054 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1055 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1056 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1057 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1059 e = li + ll;
1060 if (!extend)
1061 s = e;
1062 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1066 /*********************************************************************
1068 * EDIT_MoveForward
1071 static void EDIT_MoveForward(WND *wndPtr, BOOL extend)
1073 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1074 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1075 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1076 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1077 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1078 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1080 if (e - li == ll) {
1081 if (l != lc - 1)
1082 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1083 } else
1084 e++;
1085 if (!extend)
1086 s = e;
1087 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1091 /*********************************************************************
1093 * EDIT_MoveHome
1095 * Home key: move to beginning of line.
1098 static void EDIT_MoveHome(WND *wndPtr, BOOL extend)
1100 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1101 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1102 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1103 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1105 e = li;
1106 if (!extend)
1107 s = e;
1108 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1112 /*********************************************************************
1114 * EDIT_MovePageDown
1117 static void EDIT_MovePageDown(WND *wndPtr, BOOL extend)
1119 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1120 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1121 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1122 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1123 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1124 INT x;
1126 if (l < lc - 1) {
1127 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1128 l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
1129 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1130 EDIT_ColFromWndX(wndPtr, l, x);
1132 if (!extend)
1133 s = e;
1134 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1138 /*********************************************************************
1140 * EDIT_MovePageUp
1143 static void EDIT_MovePageUp(WND *wndPtr, BOOL extend)
1145 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1146 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1147 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1148 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1149 INT x;
1151 if (l) {
1152 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1153 l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
1154 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1155 EDIT_ColFromWndX(wndPtr, l, x);
1157 if (!extend)
1158 s = e;
1159 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1163 /*********************************************************************
1165 * EDIT_MoveUpward
1168 static void EDIT_MoveUpward(WND *wndPtr, BOOL extend)
1170 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1171 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1172 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1173 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1174 INT x;
1176 if (l) {
1177 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1178 l--;
1179 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1180 EDIT_ColFromWndX(wndPtr, l, x);
1182 if (!extend)
1183 s = e;
1184 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1188 /*********************************************************************
1190 * EDIT_MoveWordBackward
1193 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend)
1195 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1196 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1197 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1198 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1199 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1200 char *text;
1202 if (e - li == 0) {
1203 if (l) {
1204 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
1205 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1207 } else {
1208 text = EDIT_GetPointer(wndPtr);
1209 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1210 text + li, e - li, ll, WB_LEFT);
1212 if (!extend)
1213 s = e;
1214 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1218 /*********************************************************************
1220 * EDIT_MoveWordForward
1223 static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend)
1225 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1226 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1227 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1228 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1229 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1230 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1231 char *text;
1233 if (e - li == ll) {
1234 if (l != lc - 1)
1235 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1236 } else {
1237 text = EDIT_GetPointer(wndPtr);
1238 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1239 text + li, e - li + 1, ll, WB_RIGHT);
1241 if (!extend)
1242 s = e;
1243 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1247 /*********************************************************************
1249 * EDIT_PaintLine
1252 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, UINT line, BOOL rev)
1254 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1255 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1256 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1257 UINT li;
1258 UINT ll;
1259 UINT s;
1260 UINT e;
1261 INT x;
1262 INT y;
1264 if ((line < fv) || (line > fv + vlc) || (line >= lc))
1265 return;
1267 dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
1269 x = EDIT_WndXFromCol(wndPtr, line, 0);
1270 y = EDIT_WndYFromLine(wndPtr, line);
1271 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1272 ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1273 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1274 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1275 ORDER_UINT(s, e);
1276 s = MIN(li + ll, MAX(li, s));
1277 e = MIN(li + ll, MAX(li, e));
1278 if (rev && (s != e) &&
1279 ((GetFocus32() == wndPtr->hwndSelf) ||
1280 (wndPtr->dwStyle & ES_NOHIDESEL))) {
1281 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
1282 x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
1283 x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
1284 } else
1285 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
1289 /*********************************************************************
1291 * EDIT_PaintText
1294 static UINT EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev)
1296 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1297 COLORREF BkColor;
1298 COLORREF TextColor;
1299 UINT ret;
1300 char *text;
1301 UINT li;
1302 UINT xoff;
1304 if (!count)
1305 return 0;
1306 BkColor = GetBkColor(hdc);
1307 TextColor = GetTextColor(hdc);
1308 if (rev) {
1309 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1310 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1312 text = EDIT_GetPasswordPointer(wndPtr);
1313 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1314 xoff = EDIT_GetXOffset(wndPtr);
1315 ret = LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
1316 es->NumTabStops, es->TabStops, -xoff));
1317 free(text);
1318 if (rev) {
1319 SetBkColor(hdc, BkColor);
1320 SetTextColor(hdc, TextColor);
1322 return ret;
1326 /*********************************************************************
1328 * EDIT_ReleasePointer
1330 * This is the only helper function that can be called with es = NULL.
1331 * It is called at the end of EditWndProc() to unlock the buffer.
1334 static void EDIT_ReleasePointer(WND *wndPtr)
1336 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1338 if (!es)
1339 return;
1340 if (es->text && es->hBuf)
1341 LOCAL_Unlock(wndPtr->hInstance, es->hBuf);
1342 es->text = NULL;
1346 /*********************************************************************
1348 * EDIT_ReplaceSel
1350 * Beware: This is not the function called on EM_REPLACESEL.
1351 * It expects a (char *) in lParam, not a (SEGPTR).
1352 * It is used internally, as if there were no pointer difficulties.
1355 static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1357 const char *str = (char *)lParam;
1358 int strl = strlen(str);
1359 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1360 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1361 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1362 int i;
1363 char *p;
1364 char *text;
1365 BOOL redraw;
1367 ORDER_UINT(s,e);
1368 if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
1369 EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
1370 return 0L;
1372 redraw = EDIT_GetRedraw(wndPtr);
1373 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
1374 EDIT_WM_Clear(wndPtr, 0, 0L);
1375 tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1376 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1377 text = EDIT_GetPointer(wndPtr);
1378 for (p = text + tl ; p >= text + e ; p--)
1379 p[strl] = p[0];
1380 for (i = 0 , p = text + e ; i < strl ; i++)
1381 p[i] = str[i];
1382 if(IsUpper(wndPtr))
1383 AnsiUpperBuff(p, strl);
1384 else if(IsLower(wndPtr))
1385 AnsiLowerBuff(p, strl);
1386 EDIT_BuildLineDefs(wndPtr);
1387 e += strl;
1388 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(e, e));
1389 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
1390 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
1391 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
1392 if (redraw) {
1393 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
1394 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
1396 return 0L;
1400 /*********************************************************************
1402 * EDIT_ScrollIntoView
1404 * Makes sure the caret is visible.
1407 static void EDIT_ScrollIntoView(WND *wndPtr)
1409 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1410 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1411 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1412 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1413 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1414 UINT ww = EDIT_GetWndWidth(wndPtr);
1415 UINT cw = EDIT_GetAveCharWidth(wndPtr);
1416 INT x = EDIT_WndXFromCol(wndPtr, l, e - li);
1417 int dy = 0;
1418 int dx = 0;
1420 if (l >= fv + vlc)
1421 dy = l - vlc + 1 - fv;
1422 if (l < fv)
1423 dy = l - fv;
1424 if (x < 0)
1425 dx = x - ww / HSCROLL_FRACTION / cw * cw;
1426 if (x > ww)
1427 dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
1428 if (dy || dx) {
1429 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, dx));
1430 if (dy)
1431 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
1432 if (dx)
1433 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
1438 /*********************************************************************
1440 * EDIT_WndXFromCol
1442 * Calculates, for a given line and column, the X-coordinate on the screen.
1445 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col)
1447 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1448 char *text = EDIT_GetPasswordPointer(wndPtr);
1449 INT ret;
1450 HDC32 hdc;
1451 HFONT16 hFont;
1452 HFONT16 oldFont = 0;
1453 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1454 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1455 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1456 UINT xoff = EDIT_GetXOffset(wndPtr);
1458 hdc = GetDC32(wndPtr->hwndSelf);
1459 hFont = (HFONT16)EDIT_WM_GetFont(wndPtr, 0, 0L);
1460 if (hFont)
1461 oldFont = SelectObject(hdc, hFont);
1462 line = MAX(0, MIN(line, lc - 1));
1463 col = MIN(col, ll);
1464 ret = LOWORD(GetTabbedTextExtent(hdc,
1465 text + li, col,
1466 es->NumTabStops, es->TabStops)) - xoff;
1467 if (hFont)
1468 SelectObject(hdc, oldFont);
1469 ReleaseDC32(wndPtr->hwndSelf, hdc);
1470 free(text);
1471 return ret;
1475 /*********************************************************************
1477 * EDIT_WndYFromLine
1479 * Calculates, for a given line, the Y-coordinate on the screen.
1482 static INT EDIT_WndYFromLine(WND *wndPtr, UINT line)
1484 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1485 UINT lh = EDIT_GetLineHeight(wndPtr);
1487 return (line - fv) * lh;
1491 /*********************************************************************
1493 * EDIT_WordBreakProc
1495 * Find the beginning of words.
1496 * Note: unlike the specs for a WordBreakProc, this function only
1497 * allows to be called without linebreaks between s[0] upto
1498 * s[count - 1]. Remember it is only called
1499 * internally, so we can decide this for ourselves.
1502 static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action)
1504 INT ret = 0;
1506 dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%d"
1507 ", count=%d, action=%d\n", s, index, count, action);
1509 switch (action) {
1510 case WB_LEFT:
1511 if (!count)
1512 break;
1513 if (index)
1514 index--;
1515 if (s[index] == ' ') {
1516 while (index && (s[index] == ' '))
1517 index--;
1518 if (index) {
1519 while (index && (s[index] != ' '))
1520 index--;
1521 if (s[index] == ' ')
1522 index++;
1524 } else {
1525 while (index && (s[index] != ' '))
1526 index--;
1527 if (s[index] == ' ')
1528 index++;
1530 ret = index;
1531 break;
1532 case WB_RIGHT:
1533 if (!count)
1534 break;
1535 if (index)
1536 index--;
1537 if (s[index] == ' ')
1538 while ((index < count) && (s[index] == ' ')) index++;
1539 else {
1540 while (s[index] && (s[index] != ' ') && (index < count))
1541 index++;
1542 while ((s[index] == ' ') && (index < count)) index++;
1544 ret = index;
1545 break;
1546 case WB_ISDELIMITER:
1547 ret = (s[index] == ' ');
1548 break;
1549 default:
1550 fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
1551 break;
1553 return ret;
1557 /*********************************************************************
1559 * EM_CANUNDO
1562 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1564 return 0L;
1568 /*********************************************************************
1570 * EM_EMPTYUNDOBUFFER
1573 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1575 return 0L;
1579 /*********************************************************************
1581 * EM_FMTLINES
1584 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1586 fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented.\n");
1587 return wParam ? -1L : 0L;
1591 /*********************************************************************
1593 * EM_GETFIRSTVISIBLELINE
1596 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1598 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1600 return (LRESULT)es->FirstVisibleLine;
1604 /*********************************************************************
1606 * EM_GETHANDLE
1609 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1611 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1613 return (LRESULT)es->hBuf;
1617 /*********************************************************************
1619 * EM_GETLINE
1622 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1624 char *text;
1625 char *src;
1626 char *dst;
1627 UINT len;
1628 UINT i;
1629 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1631 if (!IsMultiLine(wndPtr))
1632 wParam = 0;
1633 if ((UINT)wParam >= lc)
1634 return 0L;
1635 text = EDIT_GetPointer(wndPtr);
1636 src = text + (UINT)EDIT_EM_LineIndex(wndPtr, wParam, 0L);
1637 dst = (char *)PTR_SEG_TO_LIN(lParam);
1638 len = MIN(*(WORD *)dst, (UINT)EDIT_EM_LineLength(wndPtr, wParam, 0L));
1639 for (i = 0 ; i < len ; i++) {
1640 *dst = *src;
1641 src++;
1642 dst++;
1644 return (LRESULT)len;
1648 /*********************************************************************
1650 * EM_GETLINECOUNT
1653 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1655 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1657 return (LRESULT)es->LineCount;
1661 /*********************************************************************
1663 * EM_GETMODIFY
1666 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1668 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1670 return (LRESULT)es->TextChanged;
1674 /*********************************************************************
1676 * EM_GETPASSWORDCHAR
1679 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1681 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1683 return (LRESULT)es->PasswordChar;
1687 /*********************************************************************
1689 * EM_GETRECT
1692 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1694 return EDIT_GetRect(wndPtr, wParam, (LPARAM)PTR_SEG_TO_LIN(lParam));
1698 /*********************************************************************
1700 * EM_GETSEL
1703 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1705 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1707 return MAKELONG(es->SelStart, es->SelEnd);
1711 /*********************************************************************
1713 * EM_GETTHUMB
1715 * FIXME: undocumented: is this right ?
1718 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1720 return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L),
1721 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L));
1725 /*********************************************************************
1727 * EM_GETWORDBREAKPROC
1730 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1732 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1734 return (LRESULT)es->WordBreakProc;
1738 /*********************************************************************
1740 * EM_LIMITTEXT
1743 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1745 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1747 if (IsMultiLine(wndPtr)) {
1748 if (wParam)
1749 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_MULTI);
1750 else
1751 es->BufLimit = BUFLIMIT_MULTI;
1752 } else {
1753 if (wParam)
1754 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_SINGLE);
1755 else
1756 es->BufLimit = BUFLIMIT_SINGLE;
1758 return 0L;
1762 /*********************************************************************
1764 * EM_LINEFROMCHAR
1767 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1769 UINT l;
1771 if (!IsMultiLine(wndPtr))
1772 return 0L;
1773 if ((INT)wParam == -1)
1774 wParam = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1775 l = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
1776 while ((UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam)
1777 l--;
1778 return (LRESULT)l;
1782 /*********************************************************************
1784 * EM_LINEINDEX
1787 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1789 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1790 UINT e;
1791 UINT l;
1792 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1794 if ((INT)wParam == -1) {
1795 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1796 l = lc - 1;
1797 while (es->LineDefs[l].offset > e)
1798 l--;
1799 return (LRESULT)es->LineDefs[l].offset;
1801 if ((UINT)wParam >= lc)
1802 return -1L;
1803 return (LRESULT)es->LineDefs[(UINT)wParam].offset;
1807 /*********************************************************************
1809 * EM_LINELENGTH
1812 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1814 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1815 UINT s;
1816 UINT e;
1817 UINT sl;
1818 UINT el;
1820 if (!IsMultiLine(wndPtr))
1821 return (LRESULT)es->LineDefs[0].length;
1822 if ((INT)wParam == -1) {
1823 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1824 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1825 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, s, 0L);
1826 el = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1827 return (LRESULT)(s - es->LineDefs[sl].offset +
1828 es->LineDefs[el].offset +
1829 es->LineDefs[el].length - e);
1831 return (LRESULT)es->LineDefs[(UINT)EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length;
1835 /*********************************************************************
1837 * EM_LINESCROLL
1840 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1842 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1843 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1844 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1845 UINT nfv = MAX(0, fv + (INT)LOWORD(lParam));
1846 UINT xoff = EDIT_GetXOffset(wndPtr);
1847 UINT nxoff = MAX(0, xoff + (INT)HIWORD(lParam));
1848 UINT tw = EDIT_GetTextWidth(wndPtr);
1849 INT dx;
1850 INT dy;
1851 POINT16 pos;
1853 if (nfv >= lc)
1854 nfv = lc - 1;
1856 if (nxoff >= tw)
1857 nxoff = tw;
1858 dx = xoff - nxoff;
1859 dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
1860 if (dx || dy) {
1861 if (wndPtr->hwndSelf == GetFocus32())
1862 HideCaret(wndPtr->hwndSelf);
1863 if (EDIT_GetRedraw(wndPtr))
1864 ScrollWindow(wndPtr->hwndSelf, dx, dy, NULL, NULL);
1865 es->FirstVisibleLine = nfv;
1866 es->XOffset = nxoff;
1867 if (IsVScrollBar(wndPtr))
1868 SetScrollPos32(wndPtr->hwndSelf, SB_VERT,
1869 EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1870 if (IsHScrollBar(wndPtr))
1871 SetScrollPos32(wndPtr->hwndSelf, SB_HORZ,
1872 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1873 if (wndPtr->hwndSelf == GetFocus32()) {
1874 GetCaretPos16(&pos);
1875 SetCaretPos(pos.x + dx, pos.y + dy);
1876 ShowCaret(wndPtr->hwndSelf);
1879 return -1L;
1883 /*********************************************************************
1885 * EM_REPLACESEL
1888 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1890 return (LRESULT)EDIT_ReplaceSel(wndPtr, wParam,
1891 (LPARAM)(char *)PTR_SEG_TO_LIN(lParam));
1895 /*********************************************************************
1897 * EM_SCROLL
1899 * FIXME: undocumented message.
1902 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1904 fprintf(stdnimp, "edit: EM_SCROLL: message not implemented (undocumented), please report.\n");
1905 return 0L;
1909 /*********************************************************************
1911 * EM_SETHANDLE
1914 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1916 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1918 if (IsMultiLine(wndPtr)) {
1919 EDIT_ReleasePointer(wndPtr);
1921 * old buffer is freed by caller
1923 es->hBuf = (HLOCAL16)wParam;
1924 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
1925 es->LineCount = 0;
1926 es->FirstVisibleLine = 0;
1927 es->SelStart = es->SelEnd = 0;
1928 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
1929 EDIT_EM_SetModify(wndPtr, FALSE, 0L);
1930 EDIT_BuildLineDefs(wndPtr);
1931 if (EDIT_GetRedraw(wndPtr))
1932 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
1933 EDIT_ScrollIntoView(wndPtr);
1935 return 0L;
1939 /*********************************************************************
1941 * EM_SETMODIFY
1944 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1946 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1948 es->TextChanged = (BOOL)wParam;
1949 return 0L;
1953 /*********************************************************************
1955 * EM_SETPASSWORDCHAR
1958 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1960 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1962 es->PasswordChar = (char)wParam;
1963 return 0L;
1967 /*********************************************************************
1969 * EM_SETREADONLY
1972 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1974 if ((BOOL)wParam)
1975 wndPtr->dwStyle |= ES_READONLY;
1976 else
1977 wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
1978 return 0L;
1982 /*********************************************************************
1984 * EM_SETRECT
1987 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1989 fprintf(stdnimp,"edit: EM_SETRECT: message not implemented, please report.\n");
1990 return 0L;
1994 /*********************************************************************
1996 * EM_SETRECTNP
1999 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2001 fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented, please report.\n");
2002 return 0L;
2006 /*********************************************************************
2008 * EM_SETSEL
2011 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2013 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2014 UINT ns = LOWORD(lParam);
2015 UINT ne = HIWORD(lParam);
2016 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2017 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2018 UINT el;
2019 UINT eli;
2020 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
2022 if ((INT)ns == -1) {
2023 ns = e;
2024 ne = e;
2026 else {
2027 ns = MIN(ns, tl);
2028 ne = MIN(ne, tl);
2030 es->SelStart = ns;
2031 es->SelEnd = ne;
2032 if (wndPtr->hwndSelf == GetFocus32()) {
2033 el = (UINT)EDIT_EM_LineFromChar(wndPtr, ne, 0L);
2034 eli = (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
2035 SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - eli),
2036 EDIT_WndYFromLine(wndPtr, el));
2038 if (!wParam)
2039 EDIT_ScrollIntoView(wndPtr);
2040 if (EDIT_GetRedraw(wndPtr)) {
2041 ORDER_UINT(s, e);
2042 ORDER_UINT(s, ns);
2043 ORDER_UINT(s, ne);
2044 ORDER_UINT(e, ns);
2045 ORDER_UINT(e, ne);
2046 ORDER_UINT(ns, ne);
2047 if (e != ns) {
2048 EDIT_InvalidateText(wndPtr, s, e);
2049 EDIT_InvalidateText(wndPtr, ns, ne);
2050 } else
2051 EDIT_InvalidateText(wndPtr, s, ne);
2053 return -1L;
2057 /*********************************************************************
2059 * EM_SETTABSTOPS
2062 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2064 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2066 if (!IsMultiLine(wndPtr))
2067 return 0L;
2068 if (es->TabStops)
2069 free(es->TabStops);
2070 es->NumTabStops = (UINT)wParam;
2071 if (!wParam)
2072 es->TabStops = NULL;
2073 else {
2074 es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
2075 memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam),
2076 (UINT)wParam * sizeof(INT16));
2078 return 1L;
2082 /*********************************************************************
2084 * EM_SETWORDBREAKPROC
2087 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2089 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2091 es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
2092 return 0L;
2096 /*********************************************************************
2098 * EM_UNDO
2101 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2103 return 0L;
2107 /*********************************************************************
2109 * WM_CHAR
2112 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2114 char str[2];
2115 unsigned char c = (unsigned char)wParam;
2117 switch (c) {
2118 case '\r':
2119 case '\n':
2120 if (IsMultiLine(wndPtr)) {
2121 if (IsReadOnly(wndPtr)) {
2122 EDIT_MoveHome(wndPtr, FALSE);
2123 EDIT_MoveDownward(wndPtr, FALSE);
2124 } else
2125 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n");
2127 break;
2128 case '\t':
2129 if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
2130 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\t");
2131 break;
2132 default:
2133 if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
2134 str[0] = c;
2135 str[1] = '\0';
2136 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)str);
2138 break;
2140 return 0L;
2144 /*********************************************************************
2146 * WM_CLEAR
2149 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2151 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2152 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2153 char *text;
2154 BOOL redraw;
2156 if (s != e) {
2157 redraw = EDIT_GetRedraw(wndPtr);
2158 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
2159 ORDER_UINT(s, e);
2160 text = EDIT_GetPointer(wndPtr);
2161 strcpy(text + s, text + e);
2162 EDIT_BuildLineDefs(wndPtr);
2163 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, s));
2164 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2165 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2166 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
2167 if (redraw) {
2168 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2169 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2172 return -1L;
2176 /*********************************************************************
2178 * WM_COPY
2181 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2183 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2184 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2185 HGLOBAL16 hdst;
2186 char *text;
2187 char *dst;
2188 char *src;
2189 int i;
2191 if (e == s)
2192 return -1L;
2193 ORDER_UINT(s, e);
2194 hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
2195 dst = GlobalLock16(hdst);
2196 text = EDIT_GetPointer(wndPtr);
2197 src = text + s;
2198 for (i = 0 ; i < e - s ; i++)
2199 *dst++ = *src++;
2200 *dst = '\0';
2201 GlobalUnlock16(hdst);
2202 OpenClipboard(wndPtr->hwndSelf);
2203 EmptyClipboard();
2204 SetClipboardData(CF_TEXT, hdst);
2205 CloseClipboard();
2206 return -1L;
2210 /*********************************************************************
2212 * WM_CREATE
2215 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2217 CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
2218 EDITSTATE *es;
2219 char *text;
2221 es = xmalloc(sizeof(EDITSTATE));
2222 memset(es, 0, sizeof(EDITSTATE));
2223 *(EDITSTATE **)wndPtr->wExtra = es;
2225 if (cs->style & WS_VSCROLL)
2226 cs->style |= ES_AUTOVSCROLL;
2227 if (cs->style & WS_HSCROLL)
2228 cs->style |= ES_AUTOHSCROLL;
2230 /* remove the WS_CAPTION style if it has been set - this is really a */
2231 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
2232 if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
2233 cs->style ^= WS_DLGFRAME;
2235 if (IsMultiLine(wndPtr)) {
2236 es->BufSize = BUFSTART_MULTI;
2237 es->BufLimit = BUFLIMIT_MULTI;
2238 es->PasswordChar = '\0';
2239 } else {
2240 es->BufSize = BUFSTART_SINGLE;
2241 es->BufLimit = BUFLIMIT_SINGLE;
2242 es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
2244 if (!LOCAL_HeapSize(wndPtr->hInstance)) {
2245 if (!LocalInit(wndPtr->hInstance, 0,
2246 GlobalSize16(wndPtr->hInstance))) {
2247 fprintf(stderr, "edit: WM_CREATE: could not initialize local heap\n");
2248 return -1L;
2250 dprintf_edit(stddeb, "edit: WM_CREATE: local heap initialized\n");
2252 if (!(es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1))) {
2253 fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
2254 return -1L;
2256 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
2257 text = EDIT_GetPointer(wndPtr);
2258 *text = '\0';
2259 EDIT_BuildLineDefs(wndPtr);
2260 EDIT_WM_SetFont(wndPtr, 0, 0L);
2261 if (cs->lpszName && *(char *)PTR_SEG_TO_LIN(cs->lpszName) != '\0')
2262 EDIT_EM_ReplaceSel(wndPtr, FALSE, (LPARAM)cs->lpszName);
2263 EDIT_WM_SetRedraw(wndPtr, TRUE, 0L);
2264 return 0L;
2268 /*********************************************************************
2270 * WM_CUT
2273 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2275 EDIT_WM_Copy(wndPtr, 0, 0L);
2276 EDIT_WM_Clear(wndPtr, 0, 0L);
2277 return -1L;
2281 /*********************************************************************
2283 * WM_DESTROY
2286 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2288 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2290 free(es->LineDefs);
2291 if (es->TabStops)
2292 free(es->TabStops);
2293 EDIT_ReleasePointer(wndPtr);
2294 LOCAL_Free(wndPtr->hInstance, es->hBuf);
2295 free(es);
2296 *(EDITSTATE **)&wndPtr->wExtra = NULL;
2297 return 0L;
2301 /*********************************************************************
2303 * WM_ENABLE
2306 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2308 EDIT_InvalidateText(wndPtr, 0, -1);
2309 return 0L;
2313 /*********************************************************************
2315 * WM_ERASEBKGND
2318 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2320 HBRUSH16 hBrush;
2321 RECT16 rc;
2323 hBrush = (HBRUSH16)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
2324 if (!hBrush)
2325 hBrush = (HBRUSH16)GetStockObject(WHITE_BRUSH);
2327 GetClientRect16(wndPtr->hwndSelf, &rc);
2328 IntersectClipRect((HDC16)wParam, rc.left, rc.top, rc.right, rc.bottom);
2329 GetClipBox16((HDC16)wParam, &rc);
2331 * FIXME: specs say that we should UnrealizeObject() the brush,
2332 * but the specs of UnrealizeObject() say that we shouldn't
2333 * unrealize a stock object. The default brush that
2334 * DefWndProc() returns is ... a stock object.
2336 FillRect16((HDC16)wParam, &rc, hBrush);
2337 return -1L;
2341 /*********************************************************************
2343 * WM_GETDLGCODE
2346 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2348 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
2352 /*********************************************************************
2354 * WM_GETFONT
2357 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2359 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2361 return (LRESULT)es->hFont;
2365 /*********************************************************************
2367 * WM_GETTEXT
2370 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2372 char *text = EDIT_GetPointer(wndPtr);
2373 int len;
2374 LRESULT lResult = 0L;
2376 len = strlen(text);
2377 if ((UINT)wParam > len) {
2378 strcpy((char *)PTR_SEG_TO_LIN(lParam), text);
2379 lResult = (LRESULT)len ;
2381 return lResult;
2385 /*********************************************************************
2387 * WM_GETTEXTLENGTH
2390 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2392 char *text = EDIT_GetPointer(wndPtr);
2394 return (LRESULT)strlen(text);
2398 /*********************************************************************
2400 * WM_HSCROLL
2402 * FIXME: scrollbar code itself is broken, so this one is a hack.
2405 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2407 UINT ww = EDIT_GetWndWidth(wndPtr);
2408 UINT tw = EDIT_GetTextWidth(wndPtr);
2409 UINT cw = EDIT_GetAveCharWidth(wndPtr);
2410 UINT xoff = EDIT_GetXOffset(wndPtr);
2411 INT dx = 0;
2412 BOOL not = TRUE;
2413 LRESULT ret = 0L;
2415 switch (wParam) {
2416 case SB_LINELEFT:
2417 dx = -cw;
2418 break;
2419 case SB_LINERIGHT:
2420 dx = cw;
2421 break;
2422 case SB_PAGELEFT:
2423 dx = -ww / HSCROLL_FRACTION / cw * cw;
2424 break;
2425 case SB_PAGERIGHT:
2426 dx = ww / HSCROLL_FRACTION / cw * cw;
2427 break;
2428 case SB_LEFT:
2429 dx = -xoff;
2430 break;
2431 case SB_RIGHT:
2432 dx = tw - xoff;
2433 break;
2434 case SB_THUMBTRACK:
2436 * not = FALSE;
2438 case SB_THUMBPOSITION:
2439 dx = LOWORD(lParam) * tw / 100 - xoff;
2440 break;
2441 /* The next two are undocumented ! */
2442 case EM_GETTHUMB:
2443 ret = tw ? MAKELONG(xoff * 100 / tw, 0) : 0;
2444 break;
2445 case EM_LINESCROLL:
2446 dx = LOWORD(lParam);
2447 break;
2448 case SB_ENDSCROLL:
2449 default:
2450 break;
2452 if (dx) {
2453 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(0, dx));
2454 if (not)
2455 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
2457 return ret;
2461 /*********************************************************************
2463 * WM_KEYDOWN
2465 * Handling of special keys that don't produce a WM_CHAR
2466 * (i.e. non-printable keys) & Backspace & Delete
2469 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2471 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2472 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2473 BOOL shift;
2474 BOOL control;
2476 if (GetKeyState(VK_MENU) & 0x8000)
2477 return 0L;
2479 shift = GetKeyState(VK_SHIFT) & 0x8000;
2480 control = GetKeyState(VK_CONTROL) & 0x8000;
2482 switch (wParam) {
2483 case VK_LEFT:
2484 case VK_UP:
2485 if (IsMultiLine(wndPtr) && (wParam == VK_UP))
2486 EDIT_MoveUpward(wndPtr, shift);
2487 else
2488 if (control)
2489 EDIT_MoveWordBackward(wndPtr, shift);
2490 else
2491 EDIT_MoveBackward(wndPtr, shift);
2492 break;
2493 case VK_RIGHT:
2494 case VK_DOWN:
2495 if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
2496 EDIT_MoveDownward(wndPtr, shift);
2497 else if (control)
2498 EDIT_MoveWordForward(wndPtr, shift);
2499 else
2500 EDIT_MoveForward(wndPtr, shift);
2501 break;
2502 case VK_HOME:
2503 EDIT_MoveHome(wndPtr, shift);
2504 break;
2505 case VK_END:
2506 EDIT_MoveEnd(wndPtr, shift);
2507 break;
2508 case VK_PRIOR:
2509 if (IsMultiLine(wndPtr))
2510 EDIT_MovePageUp(wndPtr, shift);
2511 break;
2512 case VK_NEXT:
2513 if (IsMultiLine(wndPtr))
2514 EDIT_MovePageDown(wndPtr, shift);
2515 break;
2516 case VK_BACK:
2517 if (!IsReadOnly(wndPtr) && !control)
2518 if (e != s)
2519 EDIT_WM_Clear(wndPtr, 0, 0L);
2520 else
2521 EDIT_DelLeft(wndPtr);
2522 break;
2523 case VK_DELETE:
2524 if (!IsReadOnly(wndPtr) && !(shift && control))
2525 if (e != s) {
2526 if (shift)
2527 EDIT_WM_Cut(wndPtr, 0, 0L);
2528 else
2529 EDIT_WM_Clear(wndPtr, 0, 0L);
2530 } else {
2531 if (shift)
2532 EDIT_DelLeft(wndPtr);
2533 else if (control)
2534 EDIT_DelEnd(wndPtr);
2535 else
2536 EDIT_DelRight(wndPtr);
2538 break;
2539 case VK_INSERT:
2540 if (shift) {
2541 if (!IsReadOnly(wndPtr))
2542 EDIT_WM_Paste(wndPtr, 0, 0L);
2543 } else if (control)
2544 EDIT_WM_Copy(wndPtr, 0, 0L);
2545 break;
2547 return 0L;
2551 /*********************************************************************
2553 * WM_KILLFOCUS
2556 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2558 UINT s;
2559 UINT e;
2561 DestroyCaret();
2562 if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
2563 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2564 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2565 EDIT_InvalidateText(wndPtr, s, e);
2567 EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
2568 return 0L;
2572 /*********************************************************************
2574 * WM_LBUTTONDBLCLK
2576 * The caret position has been set on the WM_LBUTTONDOWN message
2579 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2581 UINT s;
2582 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2583 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
2584 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2585 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
2586 char *text = EDIT_GetPointer(wndPtr);
2588 s = li + EDIT_CallWordBreakProc (wndPtr, text + li, e - li, ll, WB_LEFT);
2589 e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
2590 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2591 return 0L;
2595 /*********************************************************************
2597 * WM_LBUTTONDOWN
2600 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2602 INT x = (INT)LOWORD(lParam);
2603 INT y = (INT)HIWORD(lParam);
2604 UINT l = EDIT_LineFromWndY(wndPtr, y);
2605 UINT c;
2606 UINT s;
2607 UINT e;
2608 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2609 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2610 UINT li;
2612 SetFocus32(wndPtr->hwndSelf);
2613 SetCapture32(wndPtr->hwndSelf);
2614 l = MIN(fv + vlc - 1, MAX(fv, l));
2615 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
2616 c = EDIT_ColFromWndX(wndPtr, l, x);
2617 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2618 e = li + c;
2619 if (GetKeyState(VK_SHIFT) & 0x8000)
2620 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2621 else
2622 s = e;
2623 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2624 return 0L;
2628 /*********************************************************************
2630 * WM_LBUTTONUP
2633 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2635 if (GetCapture32() == wndPtr->hwndSelf)
2636 ReleaseCapture();
2637 return 0L;
2641 /*********************************************************************
2643 * WM_MOUSEMOVE
2646 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2648 INT x;
2649 INT y;
2650 UINT l;
2651 UINT c;
2652 UINT s;
2653 UINT fv;
2654 UINT vlc;
2655 UINT li;
2657 if (GetCapture32() == wndPtr->hwndSelf) {
2658 x = (INT)LOWORD(lParam);
2659 y = (INT)HIWORD(lParam);
2660 fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2661 vlc = EDIT_GetVisibleLineCount(wndPtr);
2662 l = EDIT_LineFromWndY(wndPtr, y);
2663 l = MIN(fv + vlc - 1, MAX(fv, l));
2664 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
2665 c = EDIT_ColFromWndX(wndPtr, l, x);
2666 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2667 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2668 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, li + c));
2670 return 0L;
2674 /*********************************************************************
2676 * WM_PAINT
2679 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2681 PAINTSTRUCT16 ps;
2682 UINT i;
2683 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2684 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2685 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2686 HDC16 hdc;
2687 HFONT16 hFont;
2688 HFONT16 oldFont = 0;
2689 RECT16 rc;
2690 RECT16 rcLine;
2691 RECT16 rcRgn;
2692 BOOL rev = IsWindowEnabled(wndPtr->hwndSelf) &&
2693 ((GetFocus32() == wndPtr->hwndSelf) ||
2694 (wndPtr->dwStyle & ES_NOHIDESEL));
2696 hdc = BeginPaint16(wndPtr->hwndSelf, &ps);
2697 GetClientRect16(wndPtr->hwndSelf, &rc);
2698 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
2699 hFont = EDIT_WM_GetFont(wndPtr, 0, 0L);
2700 if (hFont)
2701 oldFont = SelectObject(hdc, hFont);
2702 EDIT_SEND_CTLCOLOR(wndPtr, hdc);
2703 if (!IsWindowEnabled(wndPtr->hwndSelf))
2704 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
2705 GetClipBox16(hdc, &rcRgn);
2706 for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
2707 EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
2708 if (IntersectRect16(&rc, &rcRgn, &rcLine))
2709 EDIT_PaintLine(wndPtr, hdc, i, rev);
2711 if (hFont)
2712 SelectObject(hdc, oldFont);
2713 EndPaint16(wndPtr->hwndSelf, &ps);
2714 return 0L;
2718 /*********************************************************************
2720 * WM_PASTE
2723 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2725 HGLOBAL16 hsrc;
2726 char *src;
2728 OpenClipboard(wndPtr->hwndSelf);
2729 if ((hsrc = GetClipboardData(CF_TEXT))) {
2730 src = (char *)GlobalLock16(hsrc);
2731 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)src);
2732 GlobalUnlock16(hsrc);
2734 CloseClipboard();
2735 return -1L;
2739 /*********************************************************************
2741 * WM_SETCURSOR
2744 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2746 if (LOWORD(lParam) == HTCLIENT) {
2747 SetCursor(LoadCursor16(0, IDC_IBEAM));
2748 return -1L;
2749 } else
2750 return 0L;
2754 /*********************************************************************
2756 * WM_SETFOCUS
2759 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2761 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2762 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2764 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2765 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, e));
2766 if(!(wndPtr->dwStyle & ES_NOHIDESEL))
2767 EDIT_InvalidateText(wndPtr, s, e);
2768 ShowCaret(wndPtr->hwndSelf);
2769 EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
2770 return 0L;
2774 /*********************************************************************
2776 * WM_SETFONT
2779 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2781 TEXTMETRIC16 tm;
2782 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2783 LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L);
2784 HDC32 hdc;
2785 HFONT16 oldFont = 0;
2787 es->hFont = (HFONT16)wParam;
2788 hdc = GetDC32(wndPtr->hwndSelf);
2789 if (es->hFont)
2790 oldFont = SelectObject(hdc, es->hFont);
2791 GetTextMetrics16(hdc, &tm);
2792 es->LineHeight = HIWORD(GetTextExtent(hdc, "X", 1));
2793 es->AveCharWidth = tm.tmAveCharWidth;
2794 if (es->hFont)
2795 SelectObject(hdc, oldFont);
2796 ReleaseDC32(wndPtr->hwndSelf, hdc);
2797 EDIT_BuildLineDefs(wndPtr);
2798 if ((BOOL)lParam && EDIT_GetRedraw(wndPtr))
2799 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2800 if (wndPtr->hwndSelf == GetFocus32()) {
2801 DestroyCaret();
2802 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2803 EDIT_EM_SetSel(wndPtr, 1, sel);
2804 ShowCaret(wndPtr->hwndSelf);
2806 return 0L;
2810 /*********************************************************************
2812 * WM_SETREDRAW
2815 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2817 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2819 es->Redraw = (BOOL)wParam;
2820 return 0L;
2824 /*********************************************************************
2826 * WM_SETTEXT
2829 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2831 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(0, -1));
2832 EDIT_WM_Clear(wndPtr, 0, 0L);
2833 if (lParam)
2834 EDIT_EM_ReplaceSel(wndPtr, 0, lParam);
2835 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
2836 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2837 EDIT_ScrollIntoView(wndPtr);
2838 return 0L;
2842 /*********************************************************************
2844 * WM_SIZE
2847 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2849 if (EDIT_GetRedraw(wndPtr) &&
2850 ((wParam == SIZE_MAXIMIZED) ||
2851 (wParam == SIZE_RESTORED))) {
2852 if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
2853 EDIT_BuildLineDefs(wndPtr);
2854 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2856 return 0L;
2860 /*********************************************************************
2862 * WM_VSCROLL
2864 * FIXME: scrollbar code itself is broken, so this one is a hack.
2867 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2869 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2870 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2871 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2872 INT dy = 0;
2873 BOOL not = TRUE;
2874 LRESULT ret = 0L;
2876 switch (wParam) {
2877 case SB_LINEUP:
2878 dy = -1;
2879 break;
2880 case SB_LINEDOWN:
2881 dy = 1;
2882 break;
2883 case SB_PAGEUP:
2884 dy = -vlc;
2885 break;
2886 case SB_PAGEDOWN:
2887 dy = vlc;
2888 break;
2889 case SB_TOP:
2890 dy = -fv;
2891 break;
2892 case SB_BOTTOM:
2893 dy = lc - 1 - fv;
2894 break;
2895 case SB_THUMBTRACK:
2897 * not = FALSE;
2899 case SB_THUMBPOSITION:
2900 dy = LOWORD(lParam) * (lc - 1) / 100 - fv;
2901 break;
2902 /* The next two are undocumented ! */
2903 case EM_GETTHUMB:
2904 ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0L;
2905 break;
2906 case EM_LINESCROLL:
2907 dy = LOWORD(lParam);
2908 break;
2909 case SB_ENDSCROLL:
2910 default:
2911 break;
2913 if (dy) {
2914 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, 0));
2915 if (not)
2916 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
2918 return ret;