4 * Copyright David W. Metcalfe, 1994
5 * Copyright William Magro, 1995, 1996
6 * Copyright Frans van Dorsselaer, 1996
11 * UNDER CONSTRUCTION, please read EDIT.TODO
20 #include "stackframe.h"
26 #define BUFLIMIT_MULTI 65534 /* maximum text buffer length (not including '\0') */
27 #define BUFLIMIT_SINGLE 32766
28 #define BUFSTART_MULTI 1024 /* starting length for multi-line control */
29 #define BUFSTART_SINGLE 256 /* starting length for single line control */
30 #define GROWLENGTH 64 /* buffers grow by this much */
31 #define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */
50 UINT TextWidth; /* width of the widest line in pixels */
55 UINT XOffset; /* offset of the viewport in pixels */
56 UINT FirstVisibleLine;
58 UINT LineHeight; /* height of a screen line in pixels */
59 UINT AveCharWidth; /* average character width in pixels */
64 UINT SelStart; /* offset of selection start, == SelEnd if no selection */
65 UINT SelEnd; /* offset of selection end == current caret position */
68 EDITWORDBREAKPROC WordBreakProc;
73 #define SWAP_UINT(x,y) do { UINT temp = (UINT)(x); (x) = (UINT)(y); (y) = temp; } while(0)
74 #define ORDER_UINT(x,y) do { if ((UINT)(y) < (UINT)(x)) SWAP_UINT((x),(y)); } while(0)
76 /* macros to access window styles */
77 #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
78 #define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL)
79 #define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL)
80 #define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY)
81 #define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0)
83 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
86 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
87 SendMessage((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
88 (WPARAM)(hdc), (LPARAM)(wndPtr)->hwndSelf)
89 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
90 SendMessage((wndPtr)->parent->hwndSelf, WM_COMMAND, \
91 MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
92 (LPARAM)(wndPtr)->hwndSelf )
93 #define DPRINTF_EDIT_MSG(str) \
94 dprintf_edit(stddeb, \
95 "edit: " str ": hwnd=%08x, wParam=%08x, lParam=%08lx\n", \
96 (UINT)hwnd, (UINT)wParam, (DWORD)lParam)
98 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
99 SendMessage((wndPtr)->parent->hwndSelf, WM_CTLCOLOR, \
100 (WPARAM)(hdc), MAKELPARAM((wndPtr)->hwndSelf, CTLCOLOR_EDIT))
101 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
102 SendMessage((wndPtr)->parent->hwndSelf, WM_COMMAND, \
104 MAKELPARAM((wndPtr)->hwndSelf, wNotifyCode))
105 #define DPRINTF_EDIT_MSG(str) \
106 dprintf_edit(stddeb, \
107 "edit: " str ": hwnd=%04x, wParam=%04x, lParam=%08lx\n", \
108 (UINT)hwnd, (UINT)wParam, (DWORD)lParam)
111 /*********************************************************************
115 * Files like these should really be kept in alphabetical order.
118 LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
120 static void EDIT_BuildLineDefs(WND *wndPtr);
121 static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action);
122 static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x);
123 static void EDIT_DelEnd(WND *wndPtr);
124 static void EDIT_DelLeft(WND *wndPtr);
125 static void EDIT_DelRight(WND *wndPtr);
126 static UINT EDIT_GetAveCharWidth(WND *wndPtr);
127 static UINT EDIT_GetLineHeight(WND *wndPtr);
128 static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT rc);
129 static char * EDIT_GetPointer(WND *wndPtr);
130 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
131 static BOOL EDIT_GetRedraw(WND *wndPtr);
132 static UINT EDIT_GetTextWidth(WND *wndPtr);
133 static UINT EDIT_GetVisibleLineCount(WND *wndPtr);
134 static UINT EDIT_GetWndWidth(WND *wndPtr);
135 static UINT EDIT_GetXOffset(WND *wndPtr);
136 static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end);
137 static UINT EDIT_LineFromWndY(WND *wndPtr, INT y);
138 static BOOL EDIT_MakeFit(WND *wndPtr, UINT size);
139 static void EDIT_MoveBackward(WND *wndPtr, BOOL extend);
140 static void EDIT_MoveDownward(WND *wndPtr, BOOL extend);
141 static void EDIT_MoveEnd(WND *wndPtr, BOOL extend);
142 static void EDIT_MoveForward(WND *wndPtr, BOOL extend);
143 static void EDIT_MoveHome(WND *wndPtr, BOOL extend);
144 static void EDIT_MovePageDown(WND *wndPtr, BOOL extend);
145 static void EDIT_MovePageUp(WND *wndPtr, BOOL extend);
146 static void EDIT_MoveUpward(WND *wndPtr, BOOL extend);
147 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend);
148 static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend);
149 static void EDIT_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev);
150 static UINT EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev);
151 static void EDIT_ReleasePointer(WND *wndPtr);
152 static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
153 static void EDIT_ScrollIntoView(WND *wndPtr);
154 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col);
155 static INT EDIT_WndYFromLine(WND *wndPtr, UINT line);
156 static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action);
158 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam);
159 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam);
160 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam);
161 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam);
162 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam);
163 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam);
164 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam);
165 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam);
166 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
167 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
168 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
169 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam);
170 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam);
171 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
172 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
173 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam);
174 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam);
175 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
176 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
177 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
178 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam);
179 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam);
180 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
181 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam);
182 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
183 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam);
184 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
185 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam);
186 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam);
187 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam);
189 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam);
190 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam);
191 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam);
192 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam);
193 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam);
194 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam);
195 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam);
196 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam);
197 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam);
198 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam);
199 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
200 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam);
201 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
202 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam);
203 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam);
204 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam);
205 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam);
206 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam);
207 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam);
208 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam);
209 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam);
210 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam);
211 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam);
212 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam);
213 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam);
214 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
215 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam);
216 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
219 /*********************************************************************
221 * General shortcuts for variable names:
225 * UINT s; offset of selection start
226 * UINT e; offset of selection end
227 * UINT sl; line on which the selection starts
228 * UINT el; line on which the selection ends
229 * UINT sc; column on which the selection starts
230 * UINT ec; column on which the selection ends
231 * UINT li; line index (offset)
232 * UINT fv; first visible line
233 * UINT vlc; vissible line count
234 * UINT lc; line count
235 * UINT lh; line height (in pixels)
236 * UINT tw; text width (in pixels)
237 * UINT ww; window width (in pixels)
238 * UINT cw; character width (average, in pixels)
243 /*********************************************************************
248 LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
250 LRESULT lResult = 0L;
251 WND *wndPtr = WIN_FindWndPtr(hwnd);
255 DPRINTF_EDIT_MSG("EM_CANUNDO");
256 lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
258 case EM_EMPTYUNDOBUFFER:
259 DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER");
260 lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
263 DPRINTF_EDIT_MSG("EM_FMTLINES");
264 lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
266 case EM_GETFIRSTVISIBLELINE:
267 DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE");
268 lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
271 DPRINTF_EDIT_MSG("EM_GETHANDLE");
272 lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
275 DPRINTF_EDIT_MSG("EM_GETLINE");
276 lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
278 case EM_GETLINECOUNT:
279 DPRINTF_EDIT_MSG("EM_GETLINECOUNT");
280 lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
283 DPRINTF_EDIT_MSG("EM_GETMODIFY");
284 lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
286 case EM_GETPASSWORDCHAR:
287 DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR");
288 lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
291 DPRINTF_EDIT_MSG("EM_GETRECT");
292 lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
295 DPRINTF_EDIT_MSG("EM_GETSEL");
296 lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
299 DPRINTF_EDIT_MSG("EM_GETTHUMB");
300 lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
302 case EM_GETWORDBREAKPROC:
303 DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC");
304 lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
307 DPRINTF_EDIT_MSG("EM_LIMITTEXT");
308 lResult = EDIT_EM_LimitText(wndPtr, wParam, lParam);
310 case EM_LINEFROMCHAR:
311 DPRINTF_EDIT_MSG("EM_LINEFROMCHAR");
312 lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
315 DPRINTF_EDIT_MSG("EM_LINEINDEX");
316 lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
319 DPRINTF_EDIT_MSG("EM_LINELENGTH");
320 lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
323 DPRINTF_EDIT_MSG("EM_LINESCROLL");
324 lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
327 DPRINTF_EDIT_MSG("EM_REPLACESEL");
328 lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
331 DPRINTF_EDIT_MSG("EM_SCROLL");
332 lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
335 DPRINTF_EDIT_MSG("EM_SETHANDLE");
336 lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
339 DPRINTF_EDIT_MSG("EM_SETMODIFY");
340 lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
342 case EM_SETPASSWORDCHAR:
343 DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR");
344 lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
347 DPRINTF_EDIT_MSG("EM_SETREADONLY");
348 lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
351 DPRINTF_EDIT_MSG("EM_SETRECT");
352 lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
355 DPRINTF_EDIT_MSG("EM_SETRECTNP");
356 lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
359 DPRINTF_EDIT_MSG("EM_SETSEL");
360 lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
363 DPRINTF_EDIT_MSG("EM_SETTABSTOPS");
364 lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
366 case EM_SETWORDBREAKPROC:
367 DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC");
368 lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
372 DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO");
373 lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
376 DPRINTF_EDIT_MSG("WM_GETDLGCODE");
377 lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
380 DPRINTF_EDIT_MSG("WM_CHAR");
381 lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
384 DPRINTF_EDIT_MSG("WM_CLEAR");
385 lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
388 DPRINTF_EDIT_MSG("WM_COPY");
389 lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
392 DPRINTF_EDIT_MSG("WM_CREATE");
393 lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
396 DPRINTF_EDIT_MSG("WM_CUT");
397 lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
400 DPRINTF_EDIT_MSG("WM_DESTROY");
401 lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
404 DPRINTF_EDIT_MSG("WM_ENABLE");
405 lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
408 DPRINTF_EDIT_MSG("WM_ERASEBKGND");
409 lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
412 DPRINTF_EDIT_MSG("WM_GETFONT");
413 lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
416 DPRINTF_EDIT_MSG("WM_GETTEXT");
417 lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
419 case WM_GETTEXTLENGTH:
420 DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH");
421 lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
424 DPRINTF_EDIT_MSG("WM_HSCROLL");
425 lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
428 DPRINTF_EDIT_MSG("WM_KEYDOWN");
429 lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
432 DPRINTF_EDIT_MSG("WM_KILLFOCUS");
433 lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
435 case WM_LBUTTONDBLCLK:
436 DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK");
437 lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
440 DPRINTF_EDIT_MSG("WM_LBUTTONDOWN");
441 lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
444 DPRINTF_EDIT_MSG("WM_LBUTTONUP");
445 lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
449 * DPRINTF_EDIT_MSG("WM_MOUSEMOVE");
451 lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
454 DPRINTF_EDIT_MSG("WM_PAINT");
455 lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
458 DPRINTF_EDIT_MSG("WM_PASTE");
459 lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
463 * DPRINTF_EDIT_MSG("WM_SETCURSOR");
465 lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
468 DPRINTF_EDIT_MSG("WM_SETFOCUS");
469 lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
472 DPRINTF_EDIT_MSG("WM_SETFONT");
473 lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
476 DPRINTF_EDIT_MSG("WM_SETREDRAW");
477 lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
480 DPRINTF_EDIT_MSG("WM_SETTEXT");
481 lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
484 DPRINTF_EDIT_MSG("WM_SIZE");
485 lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
488 DPRINTF_EDIT_MSG("WM_VSCROLL");
489 lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
493 fprintf(stdnimp, "edit: undocumented message %d >= WM_USER, please report.\n", msg);
494 lResult = DefWindowProc(hwnd, msg, wParam, lParam);
497 EDIT_ReleasePointer(wndPtr);
502 /*********************************************************************
506 * Build array of pointers to text lines.
507 * Lines can end with '\0' (last line), nothing (if it is to long),
508 * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
511 static void EDIT_BuildLineDefs(WND *wndPtr)
513 EDITSTATE *es = EDITSTATEPTR(wndPtr);
514 char *text = EDIT_GetPointer(wndPtr);
515 int ww = EDIT_GetWndWidth(wndPtr);
525 hdc = GetDC(wndPtr->hwndSelf);
526 hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
528 oldFont = SelectObject(hdc, hFont);
530 if (!IsMultiLine(wndPtr)) {
532 es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
533 es->LineDefs[0].offset = 0;
534 es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
535 es->LineDefs[0].ending = END_0;
536 es->TextWidth = LOWORD(GetTabbedTextExtent(hdc, text,
537 es->LineDefs[0].length,
538 es->NumTabStops, es->TabStops));
543 if (!(cp = strstr(start, "\r\n"))) {
545 length = strlen(start);
546 } else if ((cp > start) && (*(cp - 1) == '\r')) {
548 length = cp - start - 1;
553 width = LOWORD(GetTabbedTextExtent(hdc, start, length,
554 es->NumTabStops, es->TabStops));
556 if (IsWordWrap(wndPtr) && (width > ww)) {
560 next = EDIT_CallWordBreakProc(wndPtr, start,
561 prev + 1, length, WB_RIGHT);
562 width = LOWORD(GetTabbedTextExtent(hdc, start, next,
563 es->NumTabStops, es->TabStops));
564 } while (width <= ww);
567 if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
568 length, WB_ISDELIMITER)) {
570 ending = END_DELIMIT;
575 width = LOWORD(GetTabbedTextExtent(hdc, start, length,
576 es->NumTabStops, es->TabStops));
579 es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF));
580 es->LineDefs[es->LineCount].offset = start - text;
581 es->LineDefs[es->LineCount].length = length;
582 es->LineDefs[es->LineCount].ending = ending;
584 es->TextWidth = MAX(es->TextWidth, width);
600 } while (*start || (ending == END_SOFT) || (ending == END_HARD));
603 SelectObject(hdc, oldFont);
604 ReleaseDC(wndPtr->hwndSelf, hdc);
608 /*********************************************************************
610 * EDIT_CallWordBreakProc
612 * Call appropriate WordBreakProc (internal or external).
615 static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action)
617 EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0L);
620 return CallWordBreakProc((FARPROC)wbp,
621 (LONG)MAKE_SEGPTR(s), index, count, action);
623 return EDIT_WordBreakProc(s, index, count, action);
627 /*********************************************************************
631 * Calculates, for a given line and X-coordinate on the screen, the column.
634 static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x)
636 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
637 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
638 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
641 line = MAX(0, MIN(line, lc - 1));
642 for (i = 0 ; i < ll ; i++)
643 if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
649 /*********************************************************************
653 * Delete all characters on this line to right of cursor.
656 static void EDIT_DelEnd(WND *wndPtr)
658 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
659 EDIT_MoveEnd(wndPtr, TRUE);
660 EDIT_WM_Clear(wndPtr, 0, 0L);
664 /*********************************************************************
668 * Delete character to left of cursor.
671 static void EDIT_DelLeft(WND *wndPtr)
673 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
674 EDIT_MoveBackward(wndPtr, TRUE);
675 EDIT_WM_Clear(wndPtr, 0, 0L);
679 /*********************************************************************
683 * Delete character to right of cursor.
686 static void EDIT_DelRight(WND *wndPtr)
688 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
689 EDIT_MoveForward(wndPtr, TRUE);
690 EDIT_WM_Clear(wndPtr, 0, 0L);
694 /*********************************************************************
696 * EDIT_GetAveCharWidth
699 static UINT EDIT_GetAveCharWidth(WND *wndPtr)
701 EDITSTATE *es = EDITSTATEPTR(wndPtr);
703 return es->AveCharWidth;
707 /*********************************************************************
712 static UINT EDIT_GetLineHeight(WND *wndPtr)
714 EDITSTATE *es = EDITSTATEPTR(wndPtr);
716 return es->LineHeight;
720 /*********************************************************************
724 * Calculates the bounding rectangle for a line from a starting
725 * column to an ending column.
728 static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT rc)
730 rc->top = EDIT_WndYFromLine(wndPtr, line);
731 rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
732 rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
733 rc->right = ((INT)ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
734 EDIT_WndXFromCol(wndPtr, line, ecol);
738 /*********************************************************************
742 * This acts as a LOCAL_Lock(), but it locks only once. This way
743 * you can call it whenever you like, without unlocking.
746 static char *EDIT_GetPointer(WND *wndPtr)
748 EDITSTATE *es = EDITSTATEPTR(wndPtr);
750 if (!es->text && es->hBuf)
751 es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf);
756 /*********************************************************************
760 * Beware: This is not the function called on EM_GETRECT.
761 * It expects a (LPRECT) in lParam, not a (SEGPTR).
762 * It is used internally, as if there were no pointer difficulties.
765 static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
767 GetClientRect(wndPtr->hwndSelf, (LPRECT)lParam);
772 /*********************************************************************
777 static BOOL EDIT_GetRedraw(WND *wndPtr)
779 EDITSTATE *es = EDITSTATEPTR(wndPtr);
785 /*********************************************************************
790 static UINT EDIT_GetTextWidth(WND *wndPtr)
792 EDITSTATE *es = EDITSTATEPTR(wndPtr);
794 return es->TextWidth;
798 /*********************************************************************
800 * EDIT_GetVisibleLineCount
803 static UINT EDIT_GetVisibleLineCount(WND *wndPtr)
807 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
808 return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
812 /*********************************************************************
817 static UINT EDIT_GetWndWidth(WND *wndPtr)
821 EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
822 return rc.right - rc.left;
826 /*********************************************************************
831 static UINT EDIT_GetXOffset(WND *wndPtr)
833 EDITSTATE *es = EDITSTATEPTR(wndPtr);
839 /*********************************************************************
841 * EDIT_InvalidateText
843 * Invalidate the text from offset start upto, but not including,
844 * offset end. Useful for (re)painting the selection.
845 * Regions outside the linewidth are not invalidated.
846 * end == -1 means end == TextLength.
847 * start and end need not be ordered.
850 static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end)
852 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
853 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
867 end = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
868 ORDER_UINT(start, end);
869 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, start, 0L);
870 el = (UINT)EDIT_EM_LineFromChar(wndPtr, end, 0L);
871 if ((el < fv) || (sl > fv + vlc))
874 sc = start - (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L);
875 ec = end - (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
882 ec = (UINT)EDIT_EM_LineLength(wndPtr,
883 (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L), 0L);
885 EDIT_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
887 EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
888 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
889 InvalidateRect(wndPtr->hwndSelf, &rcUpdate, FALSE);
891 EDIT_GetLineRect(wndPtr, sl, sc,
892 (UINT)EDIT_EM_LineLength(wndPtr,
893 (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L), 0L),
895 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
896 InvalidateRect(wndPtr->hwndSelf, &rcUpdate, FALSE);
897 for (l = sl + 1 ; l < el ; l++) {
898 EDIT_GetLineRect(wndPtr, l, 0,
899 (UINT)EDIT_EM_LineLength(wndPtr,
900 (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L), 0L),
902 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
903 InvalidateRect(wndPtr->hwndSelf, &rcUpdate, FALSE);
905 EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
906 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
907 InvalidateRect(wndPtr->hwndSelf, &rcUpdate, FALSE);
912 /*********************************************************************
916 * Calculates, for a given Y-coordinate on the screen, the line.
919 static UINT EDIT_LineFromWndY(WND *wndPtr, INT y)
921 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
922 UINT lh = EDIT_GetLineHeight(wndPtr);
923 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
925 return MAX(0, MIN(lc - 1, y / lh + fv));
929 /*********************************************************************
933 * Try to fit size + 1 bytes in the buffer. Constrain to limits.
936 static BOOL EDIT_MakeFit(WND *wndPtr, UINT size)
938 EDITSTATE *es = EDITSTATEPTR(wndPtr);
940 if (size <= es->BufSize)
942 if (size > es->BufLimit)
944 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
945 if (size > es->BufLimit)
948 dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
950 if (LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, size + 1, LMEM_MOVEABLE)) {
951 es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1, es->BufLimit);
958 /*********************************************************************
963 static void EDIT_MoveBackward(WND *wndPtr, BOOL extend)
965 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
966 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
967 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
968 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
972 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
973 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
979 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
983 /*********************************************************************
988 static void EDIT_MoveDownward(WND *wndPtr, BOOL extend)
990 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
991 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
992 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
993 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
994 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
998 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1000 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1001 EDIT_ColFromWndX(wndPtr, l, x);
1005 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1009 /*********************************************************************
1014 static void EDIT_MoveEnd(WND *wndPtr, BOOL extend)
1016 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1017 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1018 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1019 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1020 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1025 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1029 /*********************************************************************
1034 static void EDIT_MoveForward(WND *wndPtr, BOOL extend)
1036 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1037 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1038 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1039 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1040 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1041 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1045 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1050 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1054 /*********************************************************************
1058 * Home key: move to beginning of line.
1061 static void EDIT_MoveHome(WND *wndPtr, BOOL extend)
1063 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1064 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1065 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1066 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1071 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1075 /*********************************************************************
1080 static void EDIT_MovePageDown(WND *wndPtr, BOOL extend)
1082 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1083 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1084 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1085 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1086 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1090 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1091 l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
1092 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1093 EDIT_ColFromWndX(wndPtr, l, x);
1097 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1101 /*********************************************************************
1106 static void EDIT_MovePageUp(WND *wndPtr, BOOL extend)
1108 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1109 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1110 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1111 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1115 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1116 l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
1117 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1118 EDIT_ColFromWndX(wndPtr, l, x);
1122 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1126 /*********************************************************************
1131 static void EDIT_MoveUpward(WND *wndPtr, BOOL extend)
1133 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1134 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1135 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1136 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1140 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1142 e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
1143 EDIT_ColFromWndX(wndPtr, l, x);
1147 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1151 /*********************************************************************
1153 * EDIT_MoveWordBackward
1156 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend)
1158 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1159 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1160 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1161 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1162 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1167 li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
1168 e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1171 text = EDIT_GetPointer(wndPtr);
1172 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1173 text + li, e - li, ll, WB_LEFT);
1177 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1181 /*********************************************************************
1183 * EDIT_MoveWordForward
1186 static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend)
1188 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1189 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1190 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1191 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
1192 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
1193 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1198 e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
1200 text = EDIT_GetPointer(wndPtr);
1201 e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
1202 text + li, e - li + 1, ll, WB_RIGHT);
1206 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
1210 /*********************************************************************
1215 static void EDIT_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev)
1217 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1218 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1219 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1227 if ((line < fv) || (line > fv + vlc) || (line >= lc))
1230 dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
1232 x = EDIT_WndXFromCol(wndPtr, line, 0);
1233 y = EDIT_WndYFromLine(wndPtr, line);
1234 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1235 ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1236 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1237 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1239 s = MIN(li + ll, MAX(li, s));
1240 e = MIN(li + ll, MAX(li, e));
1241 if (rev && (s != e) &&
1242 ((GetFocus() == wndPtr->hwndSelf) ||
1243 (wndPtr->dwStyle & ES_NOHIDESEL))) {
1244 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
1245 x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
1246 x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
1248 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
1252 /*********************************************************************
1257 static UINT EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev)
1259 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1269 BkColor = GetBkColor(hdc);
1270 TextColor = GetTextColor(hdc);
1272 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1273 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1275 text = EDIT_GetPointer(wndPtr);
1276 li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1277 xoff = EDIT_GetXOffset(wndPtr);
1278 ret = LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
1279 es->NumTabStops, es->TabStops, -xoff));
1281 SetBkColor(hdc, BkColor);
1282 SetTextColor(hdc, TextColor);
1288 /*********************************************************************
1290 * EDIT_ReleasePointer
1292 * This is the only helper function that can be called with es = NULL.
1293 * It is called at the end of EditWndProc() to unlock the buffer.
1296 static void EDIT_ReleasePointer(WND *wndPtr)
1298 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1302 if (es->text && es->hBuf)
1303 LOCAL_Unlock(wndPtr->hInstance, es->hBuf);
1308 /*********************************************************************
1312 * Beware: This is not the function called on EM_REPLACESEL.
1313 * It expects a (char *) in lParam, not a (SEGPTR).
1314 * It is used internally, as if there were no pointer difficulties.
1317 static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1319 const char *str = (char *)lParam;
1320 int strl = strlen(str);
1321 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1322 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1323 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1330 if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
1331 EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
1334 redraw = EDIT_GetRedraw(wndPtr);
1335 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
1336 EDIT_WM_Clear(wndPtr, 0, 0L);
1337 tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1338 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1339 text = EDIT_GetPointer(wndPtr);
1340 for (p = text + tl ; p >= text + e ; p--)
1342 for (i = 0 , p = text + e ; i < strl ; i++)
1344 EDIT_BuildLineDefs(wndPtr);
1346 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(e, e));
1347 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
1348 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
1349 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
1351 InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
1352 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
1358 /*********************************************************************
1360 * EDIT_ScrollIntoView
1362 * Makes sure the caret is visible.
1365 static void EDIT_ScrollIntoView(WND *wndPtr)
1367 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1368 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1369 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
1370 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1371 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
1372 UINT ww = EDIT_GetWndWidth(wndPtr);
1373 UINT cw = EDIT_GetAveCharWidth(wndPtr);
1374 INT x = EDIT_WndXFromCol(wndPtr, l, e - li);
1379 dy = l - vlc + 1 - fv;
1383 dx = x - ww / HSCROLL_FRACTION / cw * cw;
1385 dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
1387 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, dx));
1389 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
1391 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
1396 /*********************************************************************
1400 * Calculates, for a given line and column, the X-coordinate on the screen.
1403 static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col)
1405 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1406 char *text = EDIT_GetPointer(wndPtr);
1411 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1412 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
1413 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
1414 UINT xoff = EDIT_GetXOffset(wndPtr);
1416 hdc = GetDC(wndPtr->hwndSelf);
1417 hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
1419 oldFont = SelectObject(hdc, hFont);
1420 line = MAX(0, MIN(line, lc - 1));
1422 ret = LOWORD(GetTabbedTextExtent(hdc,
1424 es->NumTabStops, es->TabStops)) - xoff;
1426 SelectObject(hdc, oldFont);
1427 ReleaseDC(wndPtr->hwndSelf, hdc);
1432 /*********************************************************************
1436 * Calculates, for a given line, the Y-coordinate on the screen.
1439 static INT EDIT_WndYFromLine(WND *wndPtr, UINT line)
1441 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1442 UINT lh = EDIT_GetLineHeight(wndPtr);
1444 return (line - fv) * lh;
1448 /*********************************************************************
1450 * EDIT_WordBreakProc
1452 * Find the beginning of words.
1453 * Note: unlike the specs for a WordBreakProc, this function only
1454 * allows to be called without linebreaks between s[0] upto
1455 * s[count - 1]. Remember it is only called
1456 * internally, so we can decide this for ourselves.
1459 static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action)
1463 dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%d"
1464 ", count=%d, action=%d\n", s, index, count, action);
1472 if (s[index] == ' ') {
1473 while (index && (s[index] == ' '))
1476 while (index && (s[index] != ' '))
1478 if (s[index] == ' ')
1482 while (index && (s[index] != ' '))
1484 if (s[index] == ' ')
1494 if (s[index] == ' ')
1495 while ((index < count) && (s[index] == ' ')) index++;
1497 while (s[index] && (s[index] != ' ') && (index < count))
1499 while ((s[index] == ' ') && (index < count)) index++;
1503 case WB_ISDELIMITER:
1504 ret = (s[index] == ' ');
1507 fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
1514 /*********************************************************************
1519 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1525 /*********************************************************************
1527 * EM_EMPTYUNDOBUFFER
1530 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1536 /*********************************************************************
1541 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1543 fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented.\n");
1544 return wParam ? -1L : 0L;
1548 /*********************************************************************
1550 * EM_GETFIRSTVISIBLELINE
1553 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1555 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1557 return (LRESULT)es->FirstVisibleLine;
1561 /*********************************************************************
1566 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1568 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1570 return (LRESULT)es->hBuf;
1574 /*********************************************************************
1579 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1586 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1588 if (!IsMultiLine(wndPtr))
1590 if ((UINT)wParam >= lc)
1592 text = EDIT_GetPointer(wndPtr);
1593 src = text + (UINT)EDIT_EM_LineIndex(wndPtr, wParam, 0L);
1594 dst = (char *)PTR_SEG_TO_LIN(lParam);
1595 len = MIN(*(WORD *)dst, (UINT)EDIT_EM_LineLength(wndPtr, wParam, 0L));
1596 for (i = 0 ; i < len ; i++) {
1601 return (LRESULT)len;
1605 /*********************************************************************
1610 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1612 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1614 return (LRESULT)es->LineCount;
1618 /*********************************************************************
1623 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1625 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1627 return (LRESULT)es->TextChanged;
1631 /*********************************************************************
1633 * EM_GETPASSWORDCHAR
1636 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1638 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1640 return (LRESULT)es->PasswordChar;
1644 /*********************************************************************
1649 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1651 return EDIT_GetRect(wndPtr, wParam, (LPARAM)PTR_SEG_TO_LIN(lParam));
1655 /*********************************************************************
1660 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1662 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1664 return MAKELONG(es->SelStart, es->SelEnd);
1668 /*********************************************************************
1672 * FIXME: undocumented: is this right ?
1675 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1677 return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L),
1678 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L));
1682 /*********************************************************************
1684 * EM_GETWORDBREAKPROC
1687 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1689 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1691 return (LRESULT)es->WordBreakProc;
1695 /*********************************************************************
1700 static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1702 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1704 if (IsMultiLine(wndPtr)) {
1706 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_MULTI);
1708 es->BufLimit = BUFLIMIT_MULTI;
1711 es->BufLimit = MIN((UINT)wParam, BUFLIMIT_SINGLE);
1713 es->BufLimit = BUFLIMIT_SINGLE;
1719 /*********************************************************************
1724 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1728 if (!IsMultiLine(wndPtr))
1730 if ((INT)wParam == -1)
1731 wParam = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1732 l = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
1733 while ((UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam)
1739 /*********************************************************************
1744 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1746 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1749 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1751 if ((INT)wParam == -1) {
1752 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1754 while (es->LineDefs[l].offset > e)
1756 return (LRESULT)es->LineDefs[l].offset;
1758 if ((UINT)wParam >= lc)
1760 return (LRESULT)es->LineDefs[(UINT)wParam].offset;
1764 /*********************************************************************
1769 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1771 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1777 if (!IsMultiLine(wndPtr))
1778 return (LRESULT)es->LineDefs[0].length;
1779 if ((INT)wParam == -1) {
1780 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1781 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1782 sl = (UINT)EDIT_EM_LineFromChar(wndPtr, s, 0L);
1783 el = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
1784 return (LRESULT)(s - es->LineDefs[sl].offset +
1785 es->LineDefs[el].offset +
1786 es->LineDefs[el].length - e);
1788 return (LRESULT)es->LineDefs[(UINT)EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length;
1792 /*********************************************************************
1797 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1799 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1800 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
1801 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
1802 UINT nfv = MAX(0, fv + (INT)LOWORD(lParam));
1803 UINT xoff = EDIT_GetXOffset(wndPtr);
1804 UINT nxoff = MAX(0, xoff + (INT)HIWORD(lParam));
1805 UINT tw = EDIT_GetTextWidth(wndPtr);
1817 dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
1819 if (wndPtr->hwndSelf == GetFocus())
1820 HideCaret(wndPtr->hwndSelf);
1821 if (EDIT_GetRedraw(wndPtr)) {
1822 hRgn = CreateRectRgn(0, 0, 0, 0);
1823 GetUpdateRgn(wndPtr->hwndSelf, hRgn, FALSE);
1824 ValidateRgn(wndPtr->hwndSelf, 0);
1825 OffsetRgn(hRgn, dx, dy);
1826 InvalidateRgn(wndPtr->hwndSelf, hRgn, TRUE);
1828 ScrollWindow(wndPtr->hwndSelf, dx, dy, NULL, NULL);
1830 es->FirstVisibleLine = nfv;
1831 es->XOffset = nxoff;
1832 if (IsVScrollBar(wndPtr))
1833 SetScrollPos(wndPtr->hwndSelf, SB_VERT,
1834 EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1835 if (IsHScrollBar(wndPtr))
1836 SetScrollPos(wndPtr->hwndSelf, SB_HORZ,
1837 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
1838 if (wndPtr->hwndSelf == GetFocus()) {
1840 SetCaretPos(pos.x + dx, pos.y + dy);
1841 ShowCaret(wndPtr->hwndSelf);
1848 /*********************************************************************
1853 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1855 return (LRESULT)EDIT_ReplaceSel(wndPtr, wParam,
1856 (LPARAM)(char *)PTR_SEG_TO_LIN(lParam));
1860 /*********************************************************************
1864 * FIXME: undocumented message.
1867 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1869 fprintf(stdnimp, "edit: EM_SCROLL: message not implemented (undocumented), please report.\n");
1874 /*********************************************************************
1879 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1881 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1883 if (IsMultiLine(wndPtr)) {
1884 EDIT_ReleasePointer(wndPtr);
1886 * old buffer is freed by caller
1888 es->hBuf = (HLOCAL16)wParam;
1889 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
1891 es->FirstVisibleLine = 0;
1892 es->SelStart = es->SelEnd = 0;
1893 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
1894 EDIT_EM_SetModify(wndPtr, FALSE, 0L);
1895 EDIT_BuildLineDefs(wndPtr);
1896 if (EDIT_GetRedraw(wndPtr))
1897 InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
1898 EDIT_ScrollIntoView(wndPtr);
1904 /*********************************************************************
1909 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1911 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1913 es->TextChanged = (BOOL)wParam;
1918 /*********************************************************************
1920 * EM_SETPASSWORDCHAR
1923 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1925 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1927 es->PasswordChar = (char)wParam;
1932 /*********************************************************************
1937 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1940 wndPtr->dwStyle |= ES_READONLY;
1942 wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
1947 /*********************************************************************
1952 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1954 fprintf(stdnimp,"edit: EM_SETRECT: message not implemented, please report.\n");
1959 /*********************************************************************
1964 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1966 fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented, please report.\n");
1971 /*********************************************************************
1976 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
1978 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1979 UINT ns = LOWORD(lParam);
1980 UINT ne = HIWORD(lParam);
1981 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1982 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
1985 UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
1987 if ((INT)ns == -1) {
1997 if (wndPtr->hwndSelf == GetFocus()) {
1998 el = (UINT)EDIT_EM_LineFromChar(wndPtr, ne, 0L);
1999 eli = (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
2000 SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - eli),
2001 EDIT_WndYFromLine(wndPtr, el));
2004 EDIT_ScrollIntoView(wndPtr);
2005 if (EDIT_GetRedraw(wndPtr)) {
2013 EDIT_InvalidateText(wndPtr, s, e);
2014 EDIT_InvalidateText(wndPtr, ns, ne);
2016 EDIT_InvalidateText(wndPtr, s, ne);
2022 /*********************************************************************
2027 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2029 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2031 if (!IsMultiLine(wndPtr))
2035 es->NumTabStops = (UINT)wParam;
2037 es->TabStops = NULL;
2039 es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
2040 memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam),
2041 (UINT)wParam * sizeof(INT16));
2047 /*********************************************************************
2049 * EM_SETWORDBREAKPROC
2052 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2054 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2056 es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
2061 /*********************************************************************
2066 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2072 /*********************************************************************
2077 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2080 char c = (char)wParam;
2085 if (IsMultiLine(wndPtr)) {
2086 if (IsReadOnly(wndPtr)) {
2087 EDIT_MoveHome(wndPtr, FALSE);
2088 EDIT_MoveDownward(wndPtr, FALSE);
2090 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n");
2094 if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
2095 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\t");
2098 if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
2101 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)str);
2109 /*********************************************************************
2114 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2116 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2117 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2122 redraw = EDIT_GetRedraw(wndPtr);
2123 EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
2125 text = EDIT_GetPointer(wndPtr);
2126 strcpy(text + s, text + e);
2127 EDIT_BuildLineDefs(wndPtr);
2128 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, s));
2129 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2130 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2131 EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
2133 InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
2134 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2141 /*********************************************************************
2146 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2148 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2149 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2159 hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
2160 dst = GlobalLock16(hdst);
2161 text = EDIT_GetPointer(wndPtr);
2163 for (i = 0 ; i < e - s ; i++)
2166 GlobalUnlock16(hdst);
2167 OpenClipboard(wndPtr->hwndSelf);
2169 SetClipboardData(CF_TEXT, hdst);
2175 /*********************************************************************
2180 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2182 CREATESTRUCT *cs = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
2186 es = xmalloc(sizeof(EDITSTATE));
2187 memset(es, 0, sizeof(EDITSTATE));
2188 *(EDITSTATE **)wndPtr->wExtra = es;
2190 if (cs->style & WS_VSCROLL)
2191 cs->style |= ES_AUTOVSCROLL;
2192 if (cs->style & WS_HSCROLL)
2193 cs->style |= ES_AUTOHSCROLL;
2195 /* remove the WS_CAPTION style if it has been set - this is really a */
2196 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
2197 if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
2198 cs->style ^= WS_DLGFRAME;
2200 if (IsMultiLine(wndPtr)) {
2201 es->BufSize = BUFSTART_MULTI;
2202 es->BufLimit = BUFLIMIT_MULTI;
2203 es->PasswordChar = '\0';
2205 es->BufSize = BUFSTART_SINGLE;
2206 es->BufLimit = BUFLIMIT_SINGLE;
2207 es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
2209 if (!LOCAL_HeapSize(wndPtr->hInstance)) {
2210 if (!LocalInit(wndPtr->hInstance, 0, GlobalSize(wndPtr->hInstance))) {
2211 fprintf(stderr, "edit: WM_CREATE: could not initialize local heap\n");
2214 dprintf_edit(stddeb, "edit: WM_CREATE: local heap initialized\n");
2216 if (!(es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1))) {
2217 fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
2220 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
2221 text = EDIT_GetPointer(wndPtr);
2223 EDIT_BuildLineDefs(wndPtr);
2224 EDIT_WM_SetFont(wndPtr, 0, 0L);
2226 EDIT_EM_ReplaceSel(wndPtr, FALSE, (LPARAM)cs->lpszName);
2227 EDIT_WM_SetRedraw(wndPtr, TRUE, 0L);
2232 /*********************************************************************
2237 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2239 EDIT_WM_Copy(wndPtr, 0, 0L);
2240 EDIT_WM_Clear(wndPtr, 0, 0L);
2245 /*********************************************************************
2250 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2252 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2257 EDIT_ReleasePointer(wndPtr);
2258 LOCAL_Free(wndPtr->hInstance, es->hBuf);
2260 *(EDITSTATE **)&wndPtr->wExtra = NULL;
2265 /*********************************************************************
2270 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2272 EDIT_InvalidateText(wndPtr, 0, -1);
2277 /*********************************************************************
2282 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2287 hBrush = (HBRUSH)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
2289 hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
2291 GetClientRect(wndPtr->hwndSelf, &rc);
2292 IntersectClipRect((HDC)wParam, rc.left, rc.top, rc.right, rc.bottom);
2293 GetClipBox((HDC)wParam, &rc);
2295 * FIXME: specs say that we should UnrealizeObject() the brush,
2296 * but the specs of UnrealizeObject() say that we shouldn't
2297 * unrealize a stock object. The default brush that
2298 * DefWndProc() returns is ... a stock object.
2300 FillRect((HDC)wParam, &rc, hBrush);
2305 /*********************************************************************
2310 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2312 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
2316 /*********************************************************************
2321 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2323 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2325 return (LRESULT)es->hFont;
2329 /*********************************************************************
2334 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2336 char *text = EDIT_GetPointer(wndPtr);
2338 LRESULT lResult = 0L;
2341 if ((UINT)wParam > len) {
2342 strcpy((char *)PTR_SEG_TO_LIN(lParam), text);
2343 lResult = (LRESULT)len ;
2349 /*********************************************************************
2354 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2356 char *text = EDIT_GetPointer(wndPtr);
2358 return (LRESULT)strlen(text);
2362 /*********************************************************************
2366 * FIXME: scrollbar code itself is broken, so this one is a hack.
2369 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2371 UINT ww = EDIT_GetWndWidth(wndPtr);
2372 UINT tw = EDIT_GetTextWidth(wndPtr);
2373 UINT cw = EDIT_GetAveCharWidth(wndPtr);
2374 UINT xoff = EDIT_GetXOffset(wndPtr);
2387 dx = -ww / HSCROLL_FRACTION / cw * cw;
2390 dx = ww / HSCROLL_FRACTION / cw * cw;
2402 case SB_THUMBPOSITION:
2403 dx = LOWORD(lParam) * tw / 100 - xoff;
2405 /* The next two are undocumented ! */
2407 ret = tw ? MAKELONG(xoff * 100 / tw, 0) : 0;
2410 dx = LOWORD(lParam);
2417 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(0, dx));
2419 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
2425 /*********************************************************************
2429 * Handling of special keys that don't produce a WM_CHAR
2430 * (i.e. non-printable keys) & Backspace & Delete
2433 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2435 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2436 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2440 if (GetKeyState(VK_MENU) & 0x8000)
2443 shift = GetKeyState(VK_SHIFT) & 0x8000;
2444 control = GetKeyState(VK_CONTROL) & 0x8000;
2449 if (IsMultiLine(wndPtr) && (wParam == VK_UP))
2450 EDIT_MoveUpward(wndPtr, shift);
2453 EDIT_MoveWordBackward(wndPtr, shift);
2455 EDIT_MoveBackward(wndPtr, shift);
2459 if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
2460 EDIT_MoveDownward(wndPtr, shift);
2462 EDIT_MoveWordForward(wndPtr, shift);
2464 EDIT_MoveForward(wndPtr, shift);
2467 EDIT_MoveHome(wndPtr, shift);
2470 EDIT_MoveEnd(wndPtr, shift);
2473 if (IsMultiLine(wndPtr))
2474 EDIT_MovePageUp(wndPtr, shift);
2477 if (IsMultiLine(wndPtr))
2478 EDIT_MovePageDown(wndPtr, shift);
2481 if (!IsReadOnly(wndPtr) && !control)
2483 EDIT_WM_Clear(wndPtr, 0, 0L);
2485 EDIT_DelLeft(wndPtr);
2488 if (!IsReadOnly(wndPtr) && !(shift && control))
2491 EDIT_WM_Cut(wndPtr, 0, 0L);
2493 EDIT_WM_Clear(wndPtr, 0, 0L);
2496 EDIT_DelLeft(wndPtr);
2498 EDIT_DelEnd(wndPtr);
2500 EDIT_DelRight(wndPtr);
2505 if (!IsReadOnly(wndPtr))
2506 EDIT_WM_Paste(wndPtr, 0, 0L);
2508 EDIT_WM_Copy(wndPtr, 0, 0L);
2515 /*********************************************************************
2520 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2526 if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
2527 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2528 e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2529 EDIT_InvalidateText(wndPtr, s, e);
2531 EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
2536 /*********************************************************************
2540 * The caret position has been set on the WM_LBUTTONDOWN message
2543 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2546 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2547 UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
2548 UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2549 UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
2550 char *text = EDIT_GetPointer(wndPtr);
2552 s = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_LEFT);
2553 e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
2554 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2559 /*********************************************************************
2564 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2566 INT x = (INT)LOWORD(lParam);
2567 INT y = (INT)HIWORD(lParam);
2568 UINT l = EDIT_LineFromWndY(wndPtr, y);
2572 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2573 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2576 SetFocus(wndPtr->hwndSelf);
2577 SetCapture(wndPtr->hwndSelf);
2578 l = MIN(fv + vlc - 1, MAX(fv, l));
2579 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
2580 c = EDIT_ColFromWndX(wndPtr, l, x);
2581 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2583 if (GetKeyState(VK_SHIFT) & 0x8000)
2584 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2587 EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
2592 /*********************************************************************
2597 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2599 if (GetCapture() == wndPtr->hwndSelf)
2605 /*********************************************************************
2610 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2621 if (GetCapture() == wndPtr->hwndSelf) {
2622 x = (INT)LOWORD(lParam);
2623 y = (INT)HIWORD(lParam);
2624 fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2625 vlc = EDIT_GetVisibleLineCount(wndPtr);
2626 l = EDIT_LineFromWndY(wndPtr, y);
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 s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2631 li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
2632 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, li + c));
2638 /*********************************************************************
2643 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2647 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2648 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2649 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2656 BOOL rev = IsWindowEnabled(wndPtr->hwndSelf) &&
2657 ((GetFocus() == wndPtr->hwndSelf) ||
2658 (wndPtr->dwStyle & ES_NOHIDESEL));
2660 hdc = BeginPaint(wndPtr->hwndSelf, &ps);
2661 GetClientRect(wndPtr->hwndSelf, &rc);
2662 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
2663 hFont = EDIT_WM_GetFont(wndPtr, 0, 0L);
2665 oldFont = SelectObject(hdc, hFont);
2666 EDIT_SEND_CTLCOLOR(wndPtr, hdc);
2667 if (!IsWindowEnabled(wndPtr->hwndSelf))
2668 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
2669 GetClipBox(hdc, &rcRgn);
2670 for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
2671 EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
2672 if (IntersectRect(&rc, &rcRgn, &rcLine))
2673 EDIT_PaintLine(wndPtr, hdc, i, rev);
2676 SelectObject(hdc, oldFont);
2677 EndPaint(wndPtr->hwndSelf, &ps);
2682 /*********************************************************************
2687 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2692 OpenClipboard(wndPtr->hwndSelf);
2693 if ((hsrc = GetClipboardData(CF_TEXT))) {
2694 src = (char *)GlobalLock16(hsrc);
2695 EDIT_ReplaceSel(wndPtr, 0, (LPARAM)src);
2696 GlobalUnlock16(hsrc);
2703 /*********************************************************************
2708 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2710 if (LOWORD(lParam) == HTCLIENT) {
2711 SetCursor(LoadCursor(0, IDC_IBEAM));
2718 /*********************************************************************
2723 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2725 UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2726 UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
2728 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2729 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, e));
2730 if(!(wndPtr->dwStyle & ES_NOHIDESEL))
2731 EDIT_InvalidateText(wndPtr, s, e);
2732 ShowCaret(wndPtr->hwndSelf);
2733 EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
2738 /*********************************************************************
2743 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2746 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2747 LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L);
2751 es->hFont = (HFONT)wParam;
2752 hdc = GetDC(wndPtr->hwndSelf);
2754 oldFont = SelectObject(hdc, es->hFont);
2755 GetTextMetrics(hdc, &tm);
2756 es->LineHeight = HIWORD(GetTextExtent(hdc, "X", 1));
2757 es->AveCharWidth = tm.tmAveCharWidth;
2759 SelectObject(hdc, oldFont);
2760 ReleaseDC(wndPtr->hwndSelf, hdc);
2761 EDIT_BuildLineDefs(wndPtr);
2762 if ((BOOL)lParam && EDIT_GetRedraw(wndPtr))
2763 InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
2764 if (wndPtr->hwndSelf == GetFocus()) {
2766 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
2767 EDIT_EM_SetSel(wndPtr, 1, sel);
2768 ShowCaret(wndPtr->hwndSelf);
2774 /*********************************************************************
2779 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2781 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2783 es->Redraw = (BOOL)wParam;
2788 /*********************************************************************
2793 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2795 EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(0, -1));
2796 EDIT_WM_Clear(wndPtr, 0, 0L);
2798 EDIT_EM_ReplaceSel(wndPtr, 0, lParam);
2799 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
2800 EDIT_EM_SetModify(wndPtr, TRUE, 0L);
2801 EDIT_ScrollIntoView(wndPtr);
2806 /*********************************************************************
2811 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2813 if (EDIT_GetRedraw(wndPtr) &&
2814 ((wParam == SIZE_MAXIMIZED) ||
2815 (wParam == SIZE_RESTORED))) {
2816 if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
2817 EDIT_BuildLineDefs(wndPtr);
2818 InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
2824 /*********************************************************************
2828 * FIXME: scrollbar code itself is broken, so this one is a hack.
2831 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
2833 UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
2834 UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
2835 UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
2863 case SB_THUMBPOSITION:
2864 dy = LOWORD(lParam) * (lc - 1) / 100 - fv;
2866 /* The next two are undocumented ! */
2868 ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0L;
2871 dy = LOWORD(lParam);
2878 EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, 0));
2880 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);