Release 970112
[wine/multimedia.git] / controls / edit.c
blobe53103ef1a3df2b4871fa8e2a7d63ee6479f9530
1 /*
2 * Edit control
4 * Copyright David W. Metcalfe, 1994
5 * Copyright William Magro, 1995, 1996
6 * Copyright Frans van Dorsselaer, 1996, 1997
8 */
11 * please read EDIT.TODO (and update it when you change things)
12 * It also contains a discussion about the 16 to 32 bit transition.
17 #define NO_TRANSITION_TYPES /* This file is Win32-clean */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "windows.h"
22 #include "win.h"
23 #include "local.h"
24 #include "stddebug.h"
25 #include "debug.h"
26 #include "xmalloc.h"
28 #include "callback.h"
31 #define BUFLIMIT_MULTI 65534 /* maximum text buffer length (not including '\0') */
32 /* FIXME: BTW, new specs say 65535 (do you dare ???) */
33 #define BUFLIMIT_SINGLE 32766
34 #define BUFSTART_MULTI 1024 /* starting length for multi-line control */
35 #define BUFSTART_SINGLE 256 /* starting length for single line control */
36 #define GROWLENGTH 64 /* buffers grow by this much */
37 #define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */
39 typedef enum
41 END_0 = 0,
42 END_DELIMIT,
43 END_NONE,
44 END_HARD,
45 END_SOFT,
46 } LINE_END;
48 typedef struct {
49 INT32 offset;
50 INT32 length;
51 LINE_END ending;
52 } LINEDEF;
54 typedef struct
56 HLOCAL16 hBuf16; /* For when a 16-bit multiline edit
57 * control gets a EM_GETHANDLE (which
58 * should return 16-bit local heap).
59 * From that point on we _have_ to keep
60 * using 16-bit local heap (apps rely
61 * on that ... bummer).
63 HLOCAL32 hBuf32; /* Don't worry about 'LOCAL'. LOCAL32 is
64 * identical to GLOBAL32, which is
65 * essentially a HANDLE32 created with
66 * HeapAlloc(GetProcessHeap(), ...) plus
67 * a global32 (and thus local32)
68 * descriptor, which we can return upon
69 * EM_GETHANDLE32.
70 * It is 32-bit linear addressing, so
71 * everything is fine.
73 LPSTR text; /* Depending on the fact that we are a
74 * 16 or 32 bit control, this is the
75 * pointer that we get after
76 * LocalLock32(hBuf23) (which is a typecast :-)
77 * or LOCAL_Lock(hBuf16).
78 * This is always a 32-bit linear pointer.
80 HFONT32 hFont;
81 LINEDEF *LineDefs; /* Internal table for (soft) linebreaks */
82 INT32 TextWidth; /* width of the widest line in pixels */
83 INT32 XOffset; /* offset of the viewport in pixels */
84 INT32 FirstVisibleLine;
85 INT32 LineCount;
86 INT32 LineHeight; /* height of a screen line in pixels */
87 INT32 AveCharWidth; /* average character width in pixels */
88 INT32 BufLimit;
89 INT32 BufSize;
90 BOOL32 TextChanged;
91 BOOL32 CanUndo;
92 BOOL32 Redraw;
93 INT32 SelStart; /* offset of selection start, == SelEnd if no selection */
94 INT32 SelEnd; /* offset of selection end == current caret position */
95 INT32 NumTabStops;
96 LPINT16 TabStops;
98 * FIXME: The following should probably be a (VOID *) that is
99 * typecast to either 16- or 32-bit callback when used,
100 * depending on the type of edit control (16 or 32 bit).
102 * EDITWORDBREAKPROC WordBreakProc;
104 * For now: no more application specific wordbreaking.
105 * (Internal wordbreak function still works)
107 CHAR PasswordChar;
108 INT32 LeftMargin;
109 INT32 RightMargin;
110 RECT32 FormatRect;
111 } EDITSTATE;
114 #define SWAP_INT32(x,y) do { INT32 temp = (INT32)(x); (x) = (INT32)(y); (y) = temp; } while(0)
115 #define ORDER_INT32(x,y) do { if ((INT32)(y) < (INT32)(x)) SWAP_INT32((x),(y)); } while(0)
117 /* macros to access window styles */
118 #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
119 #define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL)
120 #define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL)
121 #define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY)
122 #define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0)
123 #define IsPassword(wndPtr) ((wndPtr)->dwStyle & ES_PASSWORD)
124 #define IsLower(wndPtr) ((wndPtr)->dwStyle & ES_LOWERCASE)
125 #define IsUpper(wndPtr) ((wndPtr)->dwStyle & ES_UPPERCASE)
127 #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
129 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
130 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
131 (WPARAM32)(hdc), (LPARAM)(wndPtr)->hwndSelf ))
132 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
133 (SendMessage32A((wndPtr)->parent->hwndSelf, WM_COMMAND, \
134 MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
135 (LPARAM)(wndPtr)->hwndSelf ))
136 #define DPRINTF_EDIT_MSG16(str) \
137 dprintf_edit(stddeb, \
138 "edit: 16 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n ", \
139 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
140 #define DPRINTF_EDIT_MSG32(str) \
141 dprintf_edit(stddeb, \
142 "edit: 32 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
143 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
146 /*********************************************************************
148 * Declarations
150 * Files like these should really be kept in alphabetical order.
153 LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam);
155 static void EDIT_BuildLineDefs(WND *wndPtr);
156 static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action);
157 static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x);
158 static void EDIT_DelEnd(WND *wndPtr);
159 static void EDIT_DelLeft(WND *wndPtr);
160 static void EDIT_DelRight(WND *wndPtr);
161 static INT32 EDIT_GetAveCharWidth(WND *wndPtr);
162 static INT32 EDIT_GetLineHeight(WND *wndPtr);
163 static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc);
164 static LPSTR EDIT_GetPointer(WND *wndPtr);
165 static LPSTR EDIT_GetPasswordPointer(WND *wndPtr);
166 static BOOL32 EDIT_GetRedraw(WND *wndPtr);
167 static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e);
168 static INT32 EDIT_GetTextWidth(WND *wndPtr);
169 static INT32 EDIT_GetVisibleLineCount(WND *wndPtr);
170 static INT32 EDIT_GetWndWidth(WND *wndPtr);
171 static INT32 EDIT_GetXOffset(WND *wndPtr);
172 static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end);
173 static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y);
174 static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size);
175 static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend);
176 static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend);
177 static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend);
178 static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend);
179 static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend);
180 static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend);
181 static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend);
182 static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend);
183 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend);
184 static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend);
185 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev);
186 static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev);
187 static void EDIT_ReleasePointer(WND *wndPtr);
188 static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col);
189 static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line);
190 static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action);
192 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
193 static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
194 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
195 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
196 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
197 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
198 static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
199 static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
200 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
201 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
202 static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
203 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
204 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
205 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
206 static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
207 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
208 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
209 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
210 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
211 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
212 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
213 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
214 static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
215 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
216 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
217 static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
218 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
219 static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
220 static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
221 static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
222 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
223 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
224 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
225 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
226 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
227 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
228 static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
229 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
230 static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
231 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
232 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
234 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
235 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
236 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
237 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
238 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
239 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
240 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
241 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
242 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
243 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
244 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
245 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
246 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
247 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
248 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
249 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
250 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
251 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
252 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
253 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
254 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
255 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
256 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
257 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
258 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
259 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
260 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
261 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
264 /*********************************************************************
266 * General shortcuts for variable names:
268 * INT32 l; line
269 * INT32 c; column
270 * INT32 s; offset of selection start
271 * INT32 e; offset of selection end
272 * INT32 sl; line on which the selection starts
273 * INT32 el; line on which the selection ends
274 * INT32 sc; column on which the selection starts
275 * INT32 ec; column on which the selection ends
276 * INT32 li; line index (offset)
277 * INT32 fv; first visible line
278 * INT32 vlc; vissible line count
279 * INT32 lc; line count
280 * INT32 lh; line height (in pixels)
281 * INT32 tw; text width (in pixels)
282 * INT32 ww; window width (in pixels)
283 * INT32 cw; character width (average, in pixels)
288 /*********************************************************************
290 * EditWndProc()
292 * The messages are in the order of the actual integer values
293 * (which can be found in include/windows.h)
294 * Whereever possible the 16 bit versions are converted to
295 * the 32 bit ones, so that we can 'fall through' to the
296 * helper functions. These are mostly 32 bit (with a few
297 * exceptions, clearly indicated by a '16' extension to their
298 * names).
301 LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
303 LRESULT lResult = 0;
304 WND *wndPtr = WIN_FindWndPtr(hwnd);
306 if ((!EDITSTATEPTR(wndPtr)) && (msg != WM_CREATE))
307 return DefWindowProc32A(hwnd, msg, wParam, lParam);
309 switch (msg) {
310 case EM_GETSEL16:
311 DPRINTF_EDIT_MSG16("EM_GETSEL");
312 wParam = 0;
313 lParam = 0;
314 /* fall through */
315 case EM_GETSEL32:
316 DPRINTF_EDIT_MSG32("EM_GETSEL");
317 lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
318 break;
320 case EM_SETSEL16:
321 DPRINTF_EDIT_MSG16("EM_SETSEL");
322 lResult = EDIT_EM_SetSel16(wndPtr, wParam, lParam);
323 break;
324 case EM_SETSEL32:
325 DPRINTF_EDIT_MSG32("EM_SETSEL");
326 lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
327 break;
329 case EM_GETRECT16:
330 DPRINTF_EDIT_MSG16("EM_GETRECT");
331 lResult = EDIT_EM_GetRect16(wndPtr, wParam, lParam);
332 break;
333 case EM_GETRECT32:
334 DPRINTF_EDIT_MSG32("EM_GETRECT");
335 lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
336 break;
338 case EM_SETRECT16:
339 DPRINTF_EDIT_MSG16("EM_SETRECT");
340 /* fall through */
341 case EM_SETRECT32:
342 DPRINTF_EDIT_MSG32("EM_SETRECT");
343 lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
344 break;
346 case EM_SETRECTNP16:
347 DPRINTF_EDIT_MSG16("EM_SETRECTNP");
348 /* fall through */
349 case EM_SETRECTNP32:
350 DPRINTF_EDIT_MSG32("EM_SETRECTNP");
351 lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
352 break;
354 case EM_SCROLL16:
355 DPRINTF_EDIT_MSG16("EM_SCROLL");
356 /* fall through */
357 case EM_SCROLL32:
358 DPRINTF_EDIT_MSG32("EM_SCROLL");
359 lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
360 break;
362 case EM_LINESCROLL16:
363 DPRINTF_EDIT_MSG16("EM_LINESCROLL");
364 wParam = (WPARAM32)(INT32)(INT16)HIWORD(lParam);
365 lParam = (LPARAM)(INT32)(INT16)LOWORD(lParam);
366 /* fall through */
367 case EM_LINESCROLL32:
368 DPRINTF_EDIT_MSG32("EM_LINESCROLL");
369 lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
370 break;
372 case EM_SCROLLCARET16:
373 DPRINTF_EDIT_MSG16("EM_SCROLLCARET");
374 /* fall through */
375 case EM_SCROLLCARET32:
376 DPRINTF_EDIT_MSG32("EM_SCROLLCARET");
377 lResult = EDIT_EM_ScrollCaret(wndPtr, wParam, lParam);
378 break;
380 case EM_GETMODIFY16:
381 DPRINTF_EDIT_MSG16("EM_GETMODIFY");
382 /* fall through */
383 case EM_GETMODIFY32:
384 DPRINTF_EDIT_MSG32("EM_GETMODIFY");
385 lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
386 break;
388 case EM_SETMODIFY16:
389 DPRINTF_EDIT_MSG16("EM_SETMODIFY");
390 /* fall through */
391 case EM_SETMODIFY32:
392 DPRINTF_EDIT_MSG32("EM_SETMODIFY");
393 lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
394 break;
396 case EM_GETLINECOUNT16:
397 DPRINTF_EDIT_MSG16("EM_GETLINECOUNT");
398 /* fall through */
399 case EM_GETLINECOUNT32:
400 DPRINTF_EDIT_MSG32("EM_GETLINECOUNT");
401 lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
402 break;
404 case EM_LINEINDEX16:
405 DPRINTF_EDIT_MSG16("EM_LINEINDEX");
406 /* fall through */
407 case EM_LINEINDEX32:
408 DPRINTF_EDIT_MSG32("EM_LINEINDEX");
409 lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
410 break;
412 case EM_SETHANDLE16:
413 DPRINTF_EDIT_MSG16("EM_SETHANDLE");
414 lResult = EDIT_EM_SetHandle16(wndPtr, wParam, lParam);
415 break;
416 case EM_SETHANDLE32:
417 DPRINTF_EDIT_MSG32("EM_SETHANDLE");
418 lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
419 break;
421 case EM_GETHANDLE16:
422 DPRINTF_EDIT_MSG16("EM_GETHANDLE");
423 lResult = EDIT_EM_GetHandle16(wndPtr, wParam, lParam);
424 break;
425 case EM_GETHANDLE32:
426 DPRINTF_EDIT_MSG32("EM_GETHANDLE");
427 lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
428 break;
430 case EM_GETTHUMB16:
431 DPRINTF_EDIT_MSG16("EM_GETTHUMB");
432 /* fall through */
433 case EM_GETTHUMB32:
434 DPRINTF_EDIT_MSG32("EM_GETTHUMB");
435 lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
436 break;
438 /* messages 0x00bf and 0x00c0 missing from specs */
440 case WM_USER+15:
441 DPRINTF_EDIT_MSG16("undocumented WM_USER+15, please report");
442 /* fall through */
443 case 0x00bf:
444 DPRINTF_EDIT_MSG32("undocumented 0x00bf, please report");
445 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
446 break;
448 case WM_USER+16:
449 DPRINTF_EDIT_MSG16("undocumented WM_USER+16, please report");
450 /* fall through */
451 case 0x00c0:
452 DPRINTF_EDIT_MSG32("undocumented 0x00c0, please report");
453 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
454 break;
456 case EM_LINELENGTH16:
457 DPRINTF_EDIT_MSG16("EM_LINELENGTH");
458 /* fall through */
459 case EM_LINELENGTH32:
460 DPRINTF_EDIT_MSG32("EM_LINELENGTH");
461 lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
462 break;
464 case EM_REPLACESEL16:
465 DPRINTF_EDIT_MSG16("EM_REPLACESEL");
466 lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
467 /* fall through */
468 case EM_REPLACESEL32:
469 DPRINTF_EDIT_MSG32("EM_REPLACESEL");
470 lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
471 break;
473 /* message 0x00c3 missing from specs */
475 case WM_USER+19:
476 DPRINTF_EDIT_MSG16("undocumented WM_USER+19, please report");
477 /* fall through */
478 case 0x00c3:
479 DPRINTF_EDIT_MSG32("undocumented 0x00c3, please report");
480 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
481 break;
483 case EM_GETLINE16:
484 DPRINTF_EDIT_MSG16("EM_GETLINE");
485 lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
486 /* fall through */
487 case EM_GETLINE32:
488 DPRINTF_EDIT_MSG32("EM_GETLINE");
489 lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
490 break;
492 case EM_LIMITTEXT16:
493 DPRINTF_EDIT_MSG16("EM_LIMITTEXT");
494 /* fall through */
495 case EM_SETLIMITTEXT32:
496 DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT");
497 lResult = EDIT_EM_SetLimitText(wndPtr, wParam, lParam);
498 break;
500 case EM_CANUNDO16:
501 DPRINTF_EDIT_MSG16("EM_CANUNDO");
502 /* fall through */
503 case EM_CANUNDO32:
504 DPRINTF_EDIT_MSG32("EM_CANUNDO");
505 lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
506 break;
508 case EM_UNDO16:
509 DPRINTF_EDIT_MSG16("EM_UNDO");
510 /* fall through */
511 case EM_UNDO32:
512 /* fall through */
513 case WM_UNDO:
514 DPRINTF_EDIT_MSG32("EM_UNDO / WM_UNDO");
515 lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
516 break;
518 case EM_FMTLINES16:
519 DPRINTF_EDIT_MSG16("EM_FMTLINES");
520 /* fall through */
521 case EM_FMTLINES32:
522 DPRINTF_EDIT_MSG32("EM_FMTLINES");
523 lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
524 break;
526 case EM_LINEFROMCHAR16:
527 DPRINTF_EDIT_MSG16("EM_LINEFROMCHAR");
528 /* fall through */
529 case EM_LINEFROMCHAR32:
530 DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR");
531 lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
532 break;
534 /* message 0x00ca missing from specs */
536 case WM_USER+26:
537 DPRINTF_EDIT_MSG16("undocumented WM_USER+26, please report");
538 /* fall through */
539 case 0x00ca:
540 DPRINTF_EDIT_MSG32("undocumented 0x00ca, please report");
541 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
542 break;
544 case EM_SETTABSTOPS16:
545 DPRINTF_EDIT_MSG16("EM_SETTABSTOPS");
546 lResult = EDIT_EM_SetTabStops16(wndPtr, wParam, lParam);
547 break;
548 case EM_SETTABSTOPS32:
549 DPRINTF_EDIT_MSG32("EM_SETTABSTOPS");
550 lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
551 break;
553 case EM_SETPASSWORDCHAR16:
554 DPRINTF_EDIT_MSG16("EM_SETPASSWORDCHAR");
555 /* fall through */
556 case EM_SETPASSWORDCHAR32:
557 DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR");
558 lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
559 break;
561 case EM_EMPTYUNDOBUFFER16:
562 DPRINTF_EDIT_MSG16("EM_EMPTYUNDOBUFFER");
563 /* fall through */
564 case EM_EMPTYUNDOBUFFER32:
565 DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER");
566 lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
567 break;
569 case EM_GETFIRSTVISIBLELINE16:
570 DPRINTF_EDIT_MSG16("EM_GETFIRSTVISIBLELINE");
571 /* fall through */
572 case EM_GETFIRSTVISIBLELINE32:
573 DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE");
574 lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
575 break;
577 case EM_SETREADONLY16:
578 DPRINTF_EDIT_MSG16("EM_SETREADONLY");
579 /* fall through */
580 case EM_SETREADONLY32:
581 DPRINTF_EDIT_MSG32("EM_SETREADONLY");
582 lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
583 break;
585 case EM_SETWORDBREAKPROC16:
586 DPRINTF_EDIT_MSG16("EM_SETWORDBREAKPROC");
587 /* fall through */
588 case EM_SETWORDBREAKPROC32:
589 DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC");
590 lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
591 break;
593 case EM_GETWORDBREAKPROC16:
594 DPRINTF_EDIT_MSG16("EM_GETWORDBREAKPROC");
595 /* fall through */
596 case EM_GETWORDBREAKPROC32:
597 DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC");
598 lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
599 break;
601 case EM_GETPASSWORDCHAR16:
602 DPRINTF_EDIT_MSG16("EM_GETPASSWORDCHAR");
603 /* fall through */
604 case EM_GETPASSWORDCHAR32:
605 DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR");
606 lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
607 break;
609 /* The following EM_xxx are new to win95 and don't exist for 16 bit */
611 case EM_SETMARGINS32:
612 DPRINTF_EDIT_MSG16("EM_SETMARGINS");
613 lResult = EDIT_EM_SetMargins(wndPtr, wParam, lParam);
614 break;
616 case EM_GETMARGINS32:
617 DPRINTF_EDIT_MSG16("EM_GETMARGINS");
618 lResult = EDIT_EM_GetMargins(wndPtr, wParam, lParam);
619 break;
621 case EM_GETLIMITTEXT32:
622 DPRINTF_EDIT_MSG16("EM_GETLIMITTEXT");
623 lResult = EDIT_EM_GetLimitText(wndPtr, wParam, lParam);
624 break;
626 case EM_POSFROMCHAR32:
627 DPRINTF_EDIT_MSG16("EM_POSFROMCHAR");
628 lResult = EDIT_EM_PosFromChar(wndPtr, wParam, lParam);
629 break;
631 case EM_CHARFROMPOS32:
632 DPRINTF_EDIT_MSG16("EM_CHARFROMPOS");
633 lResult = EDIT_EM_CharFromPos(wndPtr, wParam, lParam);
634 break;
636 case WM_GETDLGCODE:
637 DPRINTF_EDIT_MSG32("WM_GETDLGCODE");
638 lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
639 break;
641 case WM_CHAR:
642 DPRINTF_EDIT_MSG32("WM_CHAR");
643 lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
644 break;
646 case WM_CLEAR:
647 DPRINTF_EDIT_MSG32("WM_CLEAR");
648 lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
649 break;
651 case WM_COPY:
652 DPRINTF_EDIT_MSG32("WM_COPY");
653 lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
654 break;
656 case WM_CREATE:
657 DPRINTF_EDIT_MSG32("WM_CREATE");
658 lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
659 break;
661 case WM_CUT:
662 DPRINTF_EDIT_MSG32("WM_CUT");
663 lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
664 break;
666 case WM_DESTROY:
667 DPRINTF_EDIT_MSG32("WM_DESTROY");
668 lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
669 break;
671 case WM_ENABLE:
672 DPRINTF_EDIT_MSG32("WM_ENABLE");
673 lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
674 break;
676 case WM_ERASEBKGND:
677 DPRINTF_EDIT_MSG32("WM_ERASEBKGND");
678 lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
679 break;
681 case WM_GETFONT:
682 DPRINTF_EDIT_MSG32("WM_GETFONT");
683 lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
684 break;
686 case WM_GETTEXT:
687 DPRINTF_EDIT_MSG32("WM_GETTEXT");
688 lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
689 break;
691 case WM_GETTEXTLENGTH:
692 DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH");
693 lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
694 break;
696 case WM_HSCROLL:
697 DPRINTF_EDIT_MSG32("WM_HSCROLL");
698 lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
699 break;
701 case WM_KEYDOWN:
702 DPRINTF_EDIT_MSG32("WM_KEYDOWN");
703 lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
704 break;
706 case WM_KILLFOCUS:
707 DPRINTF_EDIT_MSG32("WM_KILLFOCUS");
708 lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
709 break;
711 case WM_LBUTTONDBLCLK:
712 DPRINTF_EDIT_MSG32("WM_LBUTTONDBLCLK");
713 lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
714 break;
716 case WM_LBUTTONDOWN:
717 DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN");
718 lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
719 break;
721 case WM_LBUTTONUP:
722 DPRINTF_EDIT_MSG32("WM_LBUTTONUP");
723 lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
724 break;
726 case WM_MOUSEMOVE:
728 * DPRINTF_EDIT_MSG32("WM_MOUSEMOVE");
730 lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
731 break;
733 case WM_PAINT:
734 DPRINTF_EDIT_MSG32("WM_PAINT");
735 lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
736 break;
738 case WM_PASTE:
739 DPRINTF_EDIT_MSG32("WM_PASTE");
740 lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
741 break;
743 case WM_SETCURSOR:
745 * DPRINTF_EDIT_MSG32("WM_SETCURSOR");
747 lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
748 break;
750 case WM_SETFOCUS:
751 DPRINTF_EDIT_MSG32("WM_SETFOCUS");
752 lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
753 break;
755 case WM_SETFONT:
756 DPRINTF_EDIT_MSG32("WM_SETFONT");
757 lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
758 break;
760 case WM_SETREDRAW:
761 DPRINTF_EDIT_MSG32("WM_SETREDRAW");
762 lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
763 break;
765 case WM_SETTEXT:
766 DPRINTF_EDIT_MSG32("WM_SETTEXT");
767 lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
768 break;
770 case WM_SIZE:
771 DPRINTF_EDIT_MSG32("WM_SIZE");
772 lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
773 break;
775 case WM_VSCROLL:
776 DPRINTF_EDIT_MSG32("WM_VSCROLL");
777 lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
778 break;
780 default:
781 lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
782 break;
784 EDIT_ReleasePointer(wndPtr);
785 return lResult;
789 /*********************************************************************
791 * EDIT_BuildLineDefs
793 * Build array of pointers to text lines.
794 * Lines can end with '\0' (last line), nothing (if it is too long),
795 * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
798 static void EDIT_BuildLineDefs(WND *wndPtr)
800 EDITSTATE *es = EDITSTATEPTR(wndPtr);
801 LPSTR text = EDIT_GetPasswordPointer(wndPtr);
802 INT32 ww = EDIT_GetWndWidth(wndPtr);
803 HDC32 hdc;
804 HFONT32 hFont;
805 HFONT32 oldFont = 0;
806 LPSTR start, cp;
807 INT32 prev, next;
808 INT32 width;
809 INT32 length;
810 LINE_END ending;
812 hdc = GetDC32(wndPtr->hwndSelf);
813 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
814 if (hFont) oldFont = SelectObject32(hdc, hFont);
816 if (!IsMultiLine(wndPtr)) {
817 es->LineCount = 1;
818 es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
819 es->LineDefs[0].offset = 0;
820 es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0);
821 es->LineDefs[0].ending = END_0;
822 es->TextWidth = (INT32)LOWORD(GetTabbedTextExtent(hdc, text,
823 es->LineDefs[0].length,
824 es->NumTabStops, es->TabStops));
825 } else {
826 es->LineCount = 0;
827 start = text;
828 do {
829 if (!(cp = strstr(start, "\r\n"))) {
830 ending = END_0;
831 length = lstrlen32A(start);
832 } else if ((cp > start) && (*(cp - 1) == '\r')) {
833 ending = END_SOFT;
834 length = cp - start - 1;
835 } else {
836 ending = END_HARD;
837 length = cp - start;
839 width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, length,
840 es->NumTabStops, es->TabStops));
842 if (IsWordWrap(wndPtr) && (width > ww)) {
843 next = 0;
844 do {
845 prev = next;
846 next = EDIT_CallWordBreakProc(wndPtr, start,
847 prev + 1, length, WB_RIGHT);
848 width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, next,
849 es->NumTabStops, es->TabStops));
850 } while (width <= ww);
851 if (!prev) {
852 next = 0;
853 do {
854 prev = next;
855 next++;
856 width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, next,
857 es->NumTabStops, es->TabStops));
858 } while (width <= ww);
859 if(!prev) prev = 1;
861 length = prev;
862 if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
863 length, WB_ISDELIMITER)) {
864 length--;
865 ending = END_DELIMIT;
866 } else
867 ending = END_NONE;
868 width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, length,
869 es->NumTabStops, es->TabStops));
872 es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF));
873 es->LineDefs[es->LineCount].offset = start - text;
874 es->LineDefs[es->LineCount].length = length;
875 es->LineDefs[es->LineCount].ending = ending;
876 es->LineCount++;
877 es->TextWidth = MAX(es->TextWidth, width);
879 start += length;
880 switch (ending) {
881 case END_SOFT:
882 start += 3;
883 break;
884 case END_HARD:
885 start += 2;
886 break;
887 case END_DELIMIT:
888 start++;
889 break;
890 default:
891 break;
893 } while (*start || (ending == END_SOFT) || (ending == END_HARD));
895 if (hFont) SelectObject32(hdc, oldFont);
896 ReleaseDC32(wndPtr->hwndSelf, hdc);
898 free(text);
902 /*********************************************************************
904 * EDIT_CallWordBreakProc
906 * Call appropriate WordBreakProc (internal or external).
908 * FIXME: Heavily broken now that we have a LOCAL32 buffer.
909 * External wordbreak functions have been disabled in
910 * EM_SETWORDBREAKPROC.
913 static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action)
915 return EDIT_WordBreakProc(s, index, count, action);
917 * EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0);
919 * if (!wbp) return EDIT_WordBreakProc(s, index, count, action);
920 * else {
921 * EDITSTATE *es = EDITSTATEPTR(wndPtr);
922 * SEGPTR ptr = LOCAL_LockSegptr( wndPtr->hInstance, es->hBuf16 ) +
923 * (INT16)(s - EDIT_GetPointer(wndPtr));
924 * INT ret = CallWordBreakProc( (FARPROC16)wbp, ptr,
925 * index, count, action);
926 * LOCAL_Unlock( wndPtr->hInstance, es->hBuf16 );
927 * return ret;
933 /*********************************************************************
935 * EDIT_ColFromWndX
937 * Calculates, for a given line and X-coordinate on the screen, the column.
940 static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x)
942 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
943 INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
944 INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
945 INT32 i;
947 line = MAX(0, MIN(line, lc - 1));
948 for (i = 0 ; i < ll ; i++)
949 if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
950 break;
951 return i;
955 /*********************************************************************
957 * EDIT_DelEnd
959 * Delete all characters on this line to right of cursor.
962 static void EDIT_DelEnd(WND *wndPtr)
964 EDIT_EM_SetSel(wndPtr, -1, 0);
965 EDIT_MoveEnd(wndPtr, TRUE);
966 EDIT_WM_Clear(wndPtr, 0, 0);
970 /*********************************************************************
972 * EDIT_DelLeft
974 * Delete character to left of cursor.
977 static void EDIT_DelLeft(WND *wndPtr)
979 EDIT_EM_SetSel(wndPtr, -1, 0);
980 EDIT_MoveBackward(wndPtr, TRUE);
981 EDIT_WM_Clear(wndPtr, 0, 0);
985 /*********************************************************************
987 * EDIT_DelRight
989 * Delete character to right of cursor.
992 static void EDIT_DelRight(WND *wndPtr)
994 EDIT_EM_SetSel(wndPtr, -1, 0);
995 EDIT_MoveForward(wndPtr, TRUE);
996 EDIT_WM_Clear(wndPtr, 0, 0);
1000 /*********************************************************************
1002 * EDIT_GetAveCharWidth
1005 static INT32 EDIT_GetAveCharWidth(WND *wndPtr)
1007 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1009 return es->AveCharWidth;
1013 /*********************************************************************
1015 * EDIT_GetLineHeight
1018 static INT32 EDIT_GetLineHeight(WND *wndPtr)
1020 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1022 return es->LineHeight;
1026 /*********************************************************************
1028 * EDIT_GetLineRect
1030 * Calculates the bounding rectangle for a line from a starting
1031 * column to an ending column.
1034 static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc)
1036 rc->top = EDIT_WndYFromLine(wndPtr, line);
1037 rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
1038 rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
1039 rc->right = (ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
1040 EDIT_WndXFromCol(wndPtr, line, ecol);
1044 /*********************************************************************
1046 * EDIT_GetPointer
1048 * This acts as a LOCAL_Lock(), but it locks only once. This way
1049 * you can call it whenever you like, without unlocking.
1052 static LPSTR EDIT_GetPointer(WND *wndPtr)
1054 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1056 if (!es->text && (es->hBuf32 || es->hBuf16)) {
1057 if (es->hBuf32)
1058 es->text = (LPSTR)LocalLock32(es->hBuf32);
1059 else
1060 es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf16);
1062 return es->text;
1066 /*********************************************************************
1068 * EDIT_GetPasswordPointer
1072 static LPSTR EDIT_GetPasswordPointer(WND *wndPtr)
1074 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1075 LPSTR text = xstrdup(EDIT_GetPointer(wndPtr));
1076 LPSTR p;
1078 if(es->PasswordChar) {
1079 p = text;
1080 while(*p != '\0') {
1081 if(*p != '\r' && *p != '\n')
1082 *p = es->PasswordChar;
1083 p++;
1086 return text;
1090 /*********************************************************************
1092 * EDIT_GetRedraw
1095 static BOOL32 EDIT_GetRedraw(WND *wndPtr)
1097 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1099 return es->Redraw;
1103 /*********************************************************************
1105 * EDIT_GetSel
1107 * Beware: This is not the function called on EM_GETSEL.
1108 * (because s can be greater than e).
1111 static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e)
1113 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1115 if (s)
1116 *s = es->SelStart;
1117 if (e)
1118 *e = es->SelEnd;
1122 /*********************************************************************
1124 * EDIT_GetTextWidth
1127 static INT32 EDIT_GetTextWidth(WND *wndPtr)
1129 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1131 return es->TextWidth;
1135 /*********************************************************************
1137 * EDIT_GetVisibleLineCount
1140 static INT32 EDIT_GetVisibleLineCount(WND *wndPtr)
1142 RECT32 rc;
1144 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
1145 return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
1149 /*********************************************************************
1151 * EDIT_GetWndWidth
1154 static INT32 EDIT_GetWndWidth(WND *wndPtr)
1156 RECT32 rc;
1158 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
1159 return rc.right - rc.left;
1163 /*********************************************************************
1165 * EDIT_GetXOffset
1168 static INT32 EDIT_GetXOffset(WND *wndPtr)
1170 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1172 return es->XOffset;
1176 /*********************************************************************
1178 * EDIT_InvalidateText
1180 * Invalidate the text from offset start upto, but not including,
1181 * offset end. Useful for (re)painting the selection.
1182 * Regions outside the linewidth are not invalidated.
1183 * end == -1 means end == TextLength.
1184 * start and end need not be ordered.
1187 static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end)
1189 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1190 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
1191 INT32 sl;
1192 INT32 el;
1193 INT32 sc;
1194 INT32 ec;
1195 RECT32 rcWnd;
1196 RECT32 rcLine;
1197 RECT32 rcUpdate;
1198 INT32 l;
1200 if (end == start )
1201 return;
1203 if (end == -1)
1204 end = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
1205 ORDER_INT32(start, end);
1206 sl = (INT32)EDIT_EM_LineFromChar(wndPtr, start, 0);
1207 el = (INT32)EDIT_EM_LineFromChar(wndPtr, end, 0);
1208 if ((el < fv) || (sl > fv + vlc))
1209 return;
1211 sc = start - (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0);
1212 ec = end - (INT32)EDIT_EM_LineIndex(wndPtr, el, 0);
1213 if (sl < fv) {
1214 sl = fv;
1215 sc = 0;
1217 if (el > fv + vlc) {
1218 el = fv + vlc;
1219 ec = (INT32)EDIT_EM_LineLength(wndPtr,
1220 (INT32)EDIT_EM_LineIndex(wndPtr, el, 0), 0);
1222 EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
1223 if (sl == el) {
1224 EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
1225 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1226 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1227 } else {
1228 EDIT_GetLineRect(wndPtr, sl, sc,
1229 (INT32)EDIT_EM_LineLength(wndPtr,
1230 (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0), 0),
1231 &rcLine);
1232 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1233 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1234 for (l = sl + 1 ; l < el ; l++) {
1235 EDIT_GetLineRect(wndPtr, l, 0,
1236 (INT32)EDIT_EM_LineLength(wndPtr,
1237 (INT32)EDIT_EM_LineIndex(wndPtr, l, 0), 0),
1238 &rcLine);
1239 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1240 InvalidateRect32(wndPtr->hwndSelf, &rcUpdate, FALSE);
1242 EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
1243 if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
1244 InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
1249 /*********************************************************************
1251 * EDIT_LineFromWndY
1253 * Calculates, for a given Y-coordinate on the screen, the line.
1256 static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y)
1258 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1259 INT32 lh = EDIT_GetLineHeight(wndPtr);
1260 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
1262 return MAX(0, MIN(lc - 1, y / lh + fv));
1266 /*********************************************************************
1268 * EDIT_MakeFit
1270 * Try to fit size + 1 bytes in the buffer. Constrain to limits.
1273 static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size)
1275 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1276 HLOCAL32 hNew32;
1277 HLOCAL16 hNew16;
1279 if (size <= es->BufSize)
1280 return TRUE;
1281 if (size > es->BufLimit)
1282 return FALSE;
1283 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
1284 if (size > es->BufLimit)
1285 size = es->BufLimit;
1287 dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
1289 EDIT_ReleasePointer(wndPtr);
1290 if (es->hBuf32) {
1291 if ((hNew32 = LocalReAlloc32(es->hBuf32, size + 1, 0))) {
1292 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 32 bit handle %08x, new handle %08x\n", es->hBuf32, hNew32);
1293 es->hBuf32 = hNew32;
1294 es->BufSize = MIN(LocalSize32(es->hBuf32) - 1, es->BufLimit);
1295 if (es->BufSize < size) {
1296 dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize);
1297 return FALSE;
1299 dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
1300 return TRUE;
1302 } else {
1303 if ((hNew16 = LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf16, size + 1, LMEM_MOVEABLE))) {
1304 dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 16 bit handle %08x, new handle %08x\n", es->hBuf16, hNew16);
1305 es->hBuf16 = hNew16;
1306 es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1, es->BufLimit);
1307 if (es->BufSize < size) {
1308 dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize);
1309 return FALSE;
1311 dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
1312 return TRUE;
1315 return FALSE;
1319 /*********************************************************************
1321 * EDIT_MoveBackward
1324 static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend)
1326 INT32 s;
1327 INT32 e;
1328 INT32 l;
1329 INT32 li;
1331 EDIT_GetSel(wndPtr, &s, &e);
1332 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1333 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1334 if (e - li == 0) {
1335 if (l) {
1336 li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
1337 e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1339 } else
1340 e--;
1341 if (!extend)
1342 s = e;
1343 EDIT_EM_SetSel(wndPtr, s, e);
1344 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1348 /*********************************************************************
1350 * EDIT_MoveDownward
1353 static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend)
1355 INT32 s;
1356 INT32 e;
1357 INT32 l;
1358 INT32 lc;
1359 INT32 li;
1360 INT32 x;
1362 EDIT_GetSel(wndPtr, &s, &e);
1363 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1364 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1365 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1366 if (l < lc - 1) {
1367 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1368 l++;
1369 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1370 EDIT_ColFromWndX(wndPtr, l, x);
1372 if (!extend)
1373 s = e;
1374 EDIT_EM_SetSel(wndPtr, s, e);
1375 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1379 /*********************************************************************
1381 * EDIT_MoveEnd
1384 static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend)
1386 INT32 s;
1387 INT32 e;
1388 INT32 l;
1389 INT32 ll;
1390 INT32 li;
1392 EDIT_GetSel(wndPtr, &s, &e);
1393 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1394 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1395 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1396 e = li + ll;
1397 if (!extend)
1398 s = e;
1399 EDIT_EM_SetSel(wndPtr, s, e);
1400 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1404 /*********************************************************************
1406 * EDIT_MoveForward
1409 static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend)
1411 INT32 s;
1412 INT32 e;
1413 INT32 l;
1414 INT32 lc;
1415 INT32 ll;
1416 INT32 li;
1418 EDIT_GetSel(wndPtr, &s, &e);
1419 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1420 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1421 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1422 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1423 if (e - li == ll) {
1424 if (l != lc - 1)
1425 e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
1426 } else
1427 e++;
1428 if (!extend)
1429 s = e;
1430 EDIT_EM_SetSel(wndPtr, s, e);
1431 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1435 /*********************************************************************
1437 * EDIT_MoveHome
1439 * Home key: move to beginning of line.
1442 static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend)
1444 INT32 s;
1445 INT32 e;
1446 INT32 l;
1447 INT32 li;
1449 EDIT_GetSel(wndPtr, &s, &e);
1450 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1451 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1452 e = li;
1453 if (!extend)
1454 s = e;
1455 EDIT_EM_SetSel(wndPtr, s, e);
1456 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1460 /*********************************************************************
1462 * EDIT_MovePageDown
1465 static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend)
1467 INT32 s;
1468 INT32 e;
1469 INT32 l;
1470 INT32 lc;
1471 INT32 li;
1472 INT32 x;
1474 EDIT_GetSel(wndPtr, &s, &e);
1475 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1476 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1477 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1478 if (l < lc - 1) {
1479 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1480 l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
1481 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1482 EDIT_ColFromWndX(wndPtr, l, x);
1484 if (!extend)
1485 s = e;
1486 EDIT_EM_SetSel(wndPtr, s, e);
1487 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1491 /*********************************************************************
1493 * EDIT_MovePageUp
1496 static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend)
1498 INT32 s;
1499 INT32 e;
1500 INT32 l;
1501 INT32 li;
1502 INT32 x;
1504 EDIT_GetSel(wndPtr, &s, &e);
1505 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1506 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1507 if (l) {
1508 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1509 l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
1510 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1511 EDIT_ColFromWndX(wndPtr, l, x);
1513 if (!extend)
1514 s = e;
1515 EDIT_EM_SetSel(wndPtr, s, e);
1516 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1520 /*********************************************************************
1522 * EDIT_MoveUpward
1525 static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend)
1527 INT32 s;
1528 INT32 e;
1529 INT32 l;
1530 INT32 li;
1531 INT32 x;
1533 EDIT_GetSel(wndPtr, &s, &e);
1534 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1535 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1536 if (l) {
1537 x = EDIT_WndXFromCol(wndPtr, l, e - li);
1538 l--;
1539 e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
1540 EDIT_ColFromWndX(wndPtr, l, x);
1542 if (!extend)
1543 s = e;
1544 EDIT_EM_SetSel(wndPtr, s, e);
1545 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1549 /*********************************************************************
1551 * EDIT_MoveWordBackward
1554 static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend)
1556 INT32 s;
1557 INT32 e;
1558 INT32 l;
1559 INT32 ll;
1560 INT32 li;
1561 LPSTR text;
1563 EDIT_GetSel(wndPtr, &s, &e);
1564 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1565 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1566 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1567 if (e - li == 0) {
1568 if (l) {
1569 li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
1570 e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1572 } else {
1573 text = EDIT_GetPointer(wndPtr);
1574 e = li + (INT32)EDIT_CallWordBreakProc(wndPtr,
1575 text + li, e - li, ll, WB_LEFT);
1577 if (!extend)
1578 s = e;
1579 EDIT_EM_SetSel(wndPtr, s, e);
1580 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1584 /*********************************************************************
1586 * EDIT_MoveWordForward
1589 static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend)
1591 INT32 s;
1592 INT32 e;
1593 INT32 l;
1594 INT32 lc;
1595 INT32 ll;
1596 INT32 li;
1597 LPSTR text;
1599 EDIT_GetSel(wndPtr, &s, &e);
1600 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
1601 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
1602 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
1603 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
1604 if (e - li == ll) {
1605 if (l != lc - 1)
1606 e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
1607 } else {
1608 text = EDIT_GetPointer(wndPtr);
1609 e = li + EDIT_CallWordBreakProc(wndPtr,
1610 text + li, e - li + 1, ll, WB_RIGHT);
1612 if (!extend)
1613 s = e;
1614 EDIT_EM_SetSel(wndPtr, s, e);
1615 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
1619 /*********************************************************************
1621 * EDIT_PaintLine
1624 static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev)
1626 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1627 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
1628 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
1629 INT32 li;
1630 INT32 ll;
1631 INT32 s;
1632 INT32 e;
1633 INT32 x;
1634 INT32 y;
1636 if ((line < fv) || (line > fv + vlc) || (line >= lc))
1637 return;
1639 dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
1641 x = EDIT_WndXFromCol(wndPtr, line, 0);
1642 y = EDIT_WndYFromLine(wndPtr, line);
1643 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
1644 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1645 EDIT_GetSel(wndPtr, &s, &e);
1646 ORDER_INT32(s, e);
1647 s = MIN(li + ll, MAX(li, s));
1648 e = MIN(li + ll, MAX(li, e));
1649 if (rev && (s != e) &&
1650 ((GetFocus32() == wndPtr->hwndSelf) ||
1651 (wndPtr->dwStyle & ES_NOHIDESEL))) {
1652 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
1653 x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
1654 x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
1655 } else
1656 x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
1660 /*********************************************************************
1662 * EDIT_PaintText
1665 static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev)
1667 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1668 COLORREF BkColor;
1669 COLORREF TextColor;
1670 INT32 ret;
1671 LPSTR text;
1672 INT32 li;
1673 INT32 xoff;
1675 if (!count)
1676 return 0;
1677 BkColor = GetBkColor32(hdc);
1678 TextColor = GetTextColor32(hdc);
1679 if (rev) {
1680 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1681 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1683 text = EDIT_GetPasswordPointer(wndPtr);
1684 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
1685 xoff = EDIT_GetXOffset(wndPtr);
1686 ret = (INT32)LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
1687 es->NumTabStops, es->TabStops, -xoff));
1688 free(text);
1689 if (rev) {
1690 SetBkColor(hdc, BkColor);
1691 SetTextColor(hdc, TextColor);
1693 return ret;
1697 /*********************************************************************
1699 * EDIT_ReleasePointer
1701 * This is the only helper function that can be called with es = NULL.
1702 * It is called at the end of EditWndProc() to unlock the buffer.
1705 static void EDIT_ReleasePointer(WND *wndPtr)
1707 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1709 if (!es)
1710 return;
1711 if (es->text && (es->hBuf32 || es->hBuf16))
1713 if (es->hBuf32)
1714 LocalUnlock32(es->hBuf32);
1715 else
1716 LOCAL_Unlock(wndPtr->hInstance, es->hBuf16);
1718 es->text = NULL;
1722 /*********************************************************************
1724 * EDIT_WndXFromCol
1726 * Calculates, for a given line and column, the X-coordinate on the screen.
1729 static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col)
1731 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1732 LPSTR text = EDIT_GetPasswordPointer(wndPtr);
1733 INT32 ret;
1734 HDC32 hdc;
1735 HFONT32 hFont;
1736 HFONT32 oldFont = 0;
1737 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
1738 INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
1739 INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
1740 INT32 xoff = EDIT_GetXOffset(wndPtr);
1742 hdc = GetDC32(wndPtr->hwndSelf);
1743 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
1744 if (hFont) oldFont = SelectObject32(hdc, hFont);
1745 line = MAX(0, MIN(line, lc - 1));
1746 col = MIN(col, ll);
1747 ret = (INT32)LOWORD(GetTabbedTextExtent(hdc,
1748 text + li, col,
1749 es->NumTabStops, es->TabStops)) - xoff;
1750 if (hFont) SelectObject32(hdc, oldFont);
1751 ReleaseDC32(wndPtr->hwndSelf, hdc);
1752 free(text);
1753 return ret;
1757 /*********************************************************************
1759 * EDIT_WndYFromLine
1761 * Calculates, for a given line, the Y-coordinate on the screen.
1764 static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line)
1766 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
1767 INT32 lh = EDIT_GetLineHeight(wndPtr);
1769 return (line - fv) * lh;
1773 /*********************************************************************
1775 * EDIT_WordBreakProc
1777 * Find the beginning of words.
1778 * Note: unlike the specs for a WordBreakProc, this function only
1779 * allows to be called without linebreaks between s[0] upto
1780 * s[count - 1]. Remember it is only called
1781 * internally, so we can decide this for ourselves.
1784 static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action)
1786 INT32 ret = 0;
1788 dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%u"
1789 ", count=%u, action=%d\n", s, index, count, action);
1791 switch (action) {
1792 case WB_LEFT:
1793 if (!count)
1794 break;
1795 if (index)
1796 index--;
1797 if (s[index] == ' ') {
1798 while (index && (s[index] == ' '))
1799 index--;
1800 if (index) {
1801 while (index && (s[index] != ' '))
1802 index--;
1803 if (s[index] == ' ')
1804 index++;
1806 } else {
1807 while (index && (s[index] != ' '))
1808 index--;
1809 if (s[index] == ' ')
1810 index++;
1812 ret = index;
1813 break;
1814 case WB_RIGHT:
1815 if (!count)
1816 break;
1817 if (index)
1818 index--;
1819 if (s[index] == ' ')
1820 while ((index < count) && (s[index] == ' ')) index++;
1821 else {
1822 while (s[index] && (s[index] != ' ') && (index < count))
1823 index++;
1824 while ((s[index] == ' ') && (index < count)) index++;
1826 ret = index;
1827 break;
1828 case WB_ISDELIMITER:
1829 ret = (s[index] == ' ');
1830 break;
1831 default:
1832 fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
1833 break;
1835 return ret;
1839 /*********************************************************************
1841 * EM_CANUNDO
1844 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1846 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1848 return (LRESULT)es->CanUndo;
1852 /*********************************************************************
1854 * EM_CHARFROMPOS
1856 * FIXME: do the specs mean LineIndex or LineNumber (li v.s. l) ???
1858 static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1860 POINT32 pt;
1861 RECT32 rc;
1862 INT32 l;
1863 INT32 li;
1864 INT32 c;
1866 pt.x = LOWORD(lParam);
1867 pt.y = HIWORD(lParam);
1868 GetClientRect32(wndPtr->hwndSelf, &rc);
1870 if (!PtInRect32(&rc, pt))
1871 return -1;
1873 l = EDIT_LineFromWndY(wndPtr, pt.y);
1874 li = EDIT_EM_LineIndex(wndPtr, l, 0);
1875 c = EDIT_ColFromWndX(wndPtr, l, pt.x);
1877 return (LRESULT)MAKELONG(li + c, li);
1881 /*********************************************************************
1883 * EM_EMPTYUNDOBUFFER
1886 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1888 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1890 es->CanUndo = FALSE;
1891 return 0;
1895 /*********************************************************************
1897 * EM_FMTLINES
1900 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1902 fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented\n");
1903 return wParam ? TRUE : FALSE;
1907 /*********************************************************************
1909 * EM_GETFIRSTVISIBLELINE
1912 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1914 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1916 if (IsMultiLine(wndPtr))
1917 return (LRESULT)es->FirstVisibleLine;
1918 else
1919 return (LRESULT)EDIT_ColFromWndX(wndPtr, 0, 0);
1923 /*********************************************************************
1925 * EM_GETHANDLE
1928 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1930 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1932 if (!IsMultiLine(wndPtr))
1933 return 0;
1935 if (es->hBuf32)
1936 return (LRESULT)es->hBuf32;
1937 else
1938 return (LRESULT)es->hBuf16;
1942 /*********************************************************************
1944 * EM_GETHANDLE16
1946 * Hopefully this won't fire back at us.
1947 * We always start with a buffer in 32 bit linear memory.
1948 * However, with this message a 16 bit application requests
1949 * a handle of 16 bit local heap memory, where it expects to find
1950 * the text.
1951 * It's a pitty that from this moment on we have to use this
1952 * local heap, because applications may rely on the handle
1953 * in the future.
1955 * In this function we'll try to switch to local heap.
1957 static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1959 EDITSTATE *es = EDITSTATEPTR(wndPtr);
1960 LPSTR text;
1961 HLOCAL16 newBuf;
1962 LPSTR newText;
1963 INT16 newSize;
1965 if (!IsMultiLine(wndPtr))
1966 return 0;
1968 if (es->hBuf16)
1969 return (LRESULT)es->hBuf16;
1971 if (!LOCAL_HeapSize(wndPtr->hInstance)) {
1972 if (!LocalInit(wndPtr->hInstance, 0,
1973 GlobalSize16(wndPtr->hInstance))) {
1974 fprintf(stderr, "edit: EM_GETHANDLE: could not initialize local heap\n");
1975 return 0;
1977 dprintf_edit(stddeb, "edit: EM_GETHANDLE: local heap initialized\n");
1979 if (!(newBuf = LOCAL_Alloc(wndPtr->hInstance,
1980 EDIT_WM_GetTextLength(wndPtr, 0, 0) + 1,
1981 LMEM_MOVEABLE))) {
1982 fprintf(stderr, "edit: EM_GETHANDLE: could not allocate new 16 bit buffer\n");
1983 return 0;
1985 newSize = MIN(LOCAL_Size(wndPtr->hInstance, newBuf) - 1, es->BufLimit);
1986 if (!(newText = LOCAL_Lock(wndPtr->hInstance, newBuf))) {
1987 fprintf(stderr, "edit: EM_GETHANDLE: could not lock new 16 bit buffer\n");
1988 LOCAL_Free(wndPtr->hInstance, newBuf);
1989 return 0;
1991 text = EDIT_GetPointer(wndPtr);
1992 lstrcpy32A(newText, text);
1993 EDIT_ReleasePointer(wndPtr);
1994 GlobalFree32(es->hBuf32);
1995 es->hBuf32 = (HLOCAL32)NULL;
1996 es->hBuf16 = newBuf;
1997 es->BufSize = newSize;
1998 es->text = newText;
1999 dprintf_edit(stddeb, "edit: EM_GETHANDLE: switched to 16 bit buffer\n");
2001 return (LRESULT)es->hBuf16;
2005 /*********************************************************************
2007 * EM_GETLIMITTEXT
2010 static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2012 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2014 return es->BufLimit;
2018 /*********************************************************************
2020 * EM_GETLINE
2023 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2025 LPSTR text;
2026 LPSTR src;
2027 LPSTR dst;
2028 INT32 len;
2029 INT32 i;
2030 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
2032 if (!IsMultiLine(wndPtr))
2033 wParam = 0;
2034 if ((INT32)wParam >= lc)
2035 return 0;
2036 text = EDIT_GetPointer(wndPtr);
2037 src = text + (INT32)EDIT_EM_LineIndex(wndPtr, wParam, 0);
2038 dst = (LPSTR)lParam;
2039 len = MIN(*(WORD *)dst, (INT32)EDIT_EM_LineLength(wndPtr, wParam, 0));
2040 for (i = 0 ; i < len ; i++) {
2041 *dst = *src;
2042 src++;
2043 dst++;
2045 return (LRESULT)len;
2049 /*********************************************************************
2051 * EM_GETLINECOUNT
2054 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2056 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2058 return (LRESULT)es->LineCount;
2062 /*********************************************************************
2064 * EM_GETMARGINS
2067 static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2069 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2071 return (LRESULT)MAKELONG(es->LeftMargin, es->RightMargin);
2075 /*********************************************************************
2077 * EM_GETMODIFY
2080 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2082 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2084 return (LRESULT)es->TextChanged;
2088 /*********************************************************************
2090 * EM_GETPASSWORDCHAR
2093 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2095 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2097 return (LRESULT)es->PasswordChar;
2101 /*********************************************************************
2103 * EM_GETRECT
2106 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2108 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2110 CopyRect32((LPRECT32)lParam, &es->FormatRect);
2111 return 0;
2115 /*********************************************************************
2117 * EM_GETRECT16
2120 static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2122 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2124 CONV_RECT32TO16(&es->FormatRect, (LPRECT16)PTR_SEG_TO_LIN((SEGPTR)lParam));
2125 return 0;
2129 /*********************************************************************
2131 * EM_GETSEL
2133 * Returns the ordered selection range so that
2134 * LOWORD(result) < HIWORD(result)
2137 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2139 INT32 s;
2140 INT32 e;
2142 EDIT_GetSel(wndPtr, &s, &e);
2143 ORDER_INT32(s, e);
2144 if (wParam)
2145 *(LPINT32)wParam = s;
2146 if (lParam)
2147 *(LPINT32)lParam = e;
2148 return MAKELONG((INT16)s, (INT16)e);
2152 /*********************************************************************
2154 * EM_GETTHUMB
2156 * FIXME: is this right ? (or should it be only HSCROLL)
2157 * (and maybe only for edit controls that really have their
2158 * own scrollbars) (and maybe only for multiline controls ?)
2159 * All in all: very poorly documented
2162 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2164 return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0),
2165 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0));
2169 /*********************************************************************
2171 * EM_GETWORDBREAKPROC
2173 * FIXME: Application defined WordBreakProc should be returned
2176 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2179 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2181 return (LRESULT)es->WordBreakProc;
2183 return 0;
2187 /*********************************************************************
2189 * EM_LINEFROMCHAR
2192 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2194 INT32 l;
2196 if (!IsMultiLine(wndPtr))
2197 return 0;
2198 if ((INT32)wParam == -1)
2199 EDIT_EM_GetSel(wndPtr, (WPARAM32)&wParam, 0); /* intentional (looks weird, doesn't it ?) */
2200 l = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0) - 1;
2201 while ((INT32)EDIT_EM_LineIndex(wndPtr, l, 0) > (INT32)wParam)
2202 l--;
2203 return (LRESULT)l;
2207 /*********************************************************************
2209 * EM_LINEINDEX
2212 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2214 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2215 INT32 e;
2216 INT32 l;
2217 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
2219 if ((INT32)wParam == -1) {
2220 EDIT_GetSel(wndPtr, NULL, &e);
2221 l = lc - 1;
2222 while (es->LineDefs[l].offset > e)
2223 l--;
2224 return (LRESULT)es->LineDefs[l].offset;
2226 if ((INT32)wParam >= lc)
2227 return -1;
2228 return (LRESULT)es->LineDefs[(INT32)wParam].offset;
2232 /*********************************************************************
2234 * EM_LINELENGTH
2237 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2239 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2240 INT32 s;
2241 INT32 e;
2242 INT32 sl;
2243 INT32 el;
2245 if (!IsMultiLine(wndPtr))
2246 return (LRESULT)es->LineDefs[0].length;
2247 if ((INT32)wParam == -1) {
2248 EDIT_GetSel(wndPtr, &s, &e);
2249 sl = (INT32)EDIT_EM_LineFromChar(wndPtr, s, 0);
2250 el = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
2251 return (LRESULT)(s - es->LineDefs[sl].offset +
2252 es->LineDefs[el].offset +
2253 es->LineDefs[el].length - e);
2255 return (LRESULT)es->LineDefs[(INT32)EDIT_EM_LineFromChar(wndPtr, wParam, 0)].length;
2259 /*********************************************************************
2261 * EM_LINESCROLL
2263 * FIXME: is wParam in pixels or in average character widths ???
2264 * FIXME: we use this internally to scroll single line controls as well
2265 * (specs are vague about whether this message is valid or not for
2266 * single line controls)
2269 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2271 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2272 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
2273 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
2274 INT32 nfv = MAX(0, fv + (INT32)lParam);
2275 INT32 xoff = EDIT_GetXOffset(wndPtr);
2276 INT32 nxoff = MAX(0, xoff + (INT32)wParam);
2277 INT32 tw = EDIT_GetTextWidth(wndPtr);
2278 INT32 dx;
2279 INT32 dy;
2280 POINT32 pos;
2282 if (nfv >= lc)
2283 nfv = lc - 1;
2285 if (nxoff >= tw)
2286 nxoff = tw;
2287 dx = xoff - nxoff;
2288 dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv);
2289 if (dx || dy) {
2290 if (wndPtr->hwndSelf == GetFocus32())
2291 HideCaret(wndPtr->hwndSelf);
2292 if (EDIT_GetRedraw(wndPtr))
2293 ScrollWindow32(wndPtr->hwndSelf, dx, dy, NULL, NULL);
2294 es->FirstVisibleLine = nfv;
2295 es->XOffset = nxoff;
2296 if (IsVScrollBar(wndPtr))
2297 SetScrollPos32(wndPtr->hwndSelf, SB_VERT,
2298 EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
2299 if (IsHScrollBar(wndPtr))
2300 SetScrollPos32(wndPtr->hwndSelf, SB_HORZ,
2301 EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
2302 if (wndPtr->hwndSelf == GetFocus32()) {
2303 GetCaretPos32(&pos);
2304 SetCaretPos(pos.x + dx, pos.y + dy);
2305 ShowCaret(wndPtr->hwndSelf);
2308 if (IsMultiLine(wndPtr))
2309 return TRUE;
2310 else
2311 return FALSE;
2315 /*********************************************************************
2317 * EM_POSFROMCHAR
2320 static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2322 INT32 len = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
2323 INT32 l;
2324 INT32 li;
2326 wParam = MIN(wParam, len);
2327 l = EDIT_EM_LineFromChar(wndPtr, wParam, 0);
2328 li = EDIT_EM_LineIndex(wndPtr, l, 0);
2329 return (LRESULT)MAKELONG(EDIT_WndXFromCol(wndPtr, l, wParam - li),
2330 EDIT_WndYFromLine(wndPtr, l));
2334 /*********************************************************************
2336 * EM_REPLACESEL
2338 * FIXME: wParam indicates whether we should maintain an undo buffer
2339 * for this operation.
2342 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2344 LPCSTR str = (LPCSTR)lParam;
2345 INT32 strl = lstrlen32A(str);
2346 INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
2347 INT32 s;
2348 INT32 e;
2349 INT32 i;
2350 LPSTR p;
2351 LPSTR text;
2352 BOOL32 redraw;
2354 EDIT_GetSel(wndPtr, &s, &e);
2355 ORDER_INT32(s,e);
2356 if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
2357 dprintf_edit(stddeb, "edit: notification EN_MAXTEXT sent\n");
2358 EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
2359 return 0;
2361 redraw = EDIT_GetRedraw(wndPtr);
2362 EDIT_WM_SetRedraw(wndPtr, FALSE, 0);
2363 EDIT_WM_Clear(wndPtr, 0, 0);
2364 tl = EDIT_WM_GetTextLength(wndPtr, 0, 0);
2365 EDIT_GetSel(wndPtr, NULL, &e);
2366 text = EDIT_GetPointer(wndPtr);
2367 for (p = text + tl ; p >= text + e ; p--)
2368 p[strl] = p[0];
2369 for (i = 0 , p = text + e ; i < strl ; i++)
2370 p[i] = str[i];
2371 if(IsUpper(wndPtr))
2372 CharUpperBuff32A(p, strl);
2373 else if(IsLower(wndPtr))
2374 CharLowerBuff32A(p, strl);
2375 EDIT_BuildLineDefs(wndPtr);
2376 e += strl;
2377 EDIT_EM_SetSel(wndPtr, e, e);
2378 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2379 EDIT_EM_SetModify(wndPtr, TRUE, 0);
2380 dprintf_edit(stddeb, "edit: notification EN_UPDATE sent\n");
2381 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2382 EDIT_WM_SetRedraw(wndPtr, redraw, 0);
2383 if (redraw) {
2384 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2385 dprintf_edit(stddeb, "edit: notification EN_CHANGE sent\n");
2386 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2388 return 0;
2392 /*********************************************************************
2394 * EM_SCROLL
2396 * FIXME: Scroll what ??? And where ???
2399 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2401 fprintf(stdnimp, "edit: EM_SCROLL: message not implemented\n");
2402 return 0;
2406 /*********************************************************************
2408 * EM_SCROLLCARET
2410 * Makes sure the caret is visible.
2411 * FIXME: We use EM_LINESCROLL, but may we do that for single line
2412 * controls ???
2415 static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2417 INT32 e;
2418 INT32 l;
2419 INT32 li;
2420 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
2421 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
2422 INT32 ww = EDIT_GetWndWidth(wndPtr);
2423 INT32 cw = EDIT_GetAveCharWidth(wndPtr);
2424 INT32 x;
2425 INT32 dy = 0;
2426 INT32 dx = 0;
2428 EDIT_GetSel(wndPtr, NULL, &e);
2429 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
2430 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
2431 x = EDIT_WndXFromCol(wndPtr, l, e - li);
2432 if (l >= fv + vlc)
2433 dy = l - vlc + 1 - fv;
2434 if (l < fv)
2435 dy = l - fv;
2436 if (x < 0)
2437 dx = x - ww / HSCROLL_FRACTION / cw * cw;
2438 if (x > ww)
2439 dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
2440 if (dy || dx) {
2441 EDIT_EM_LineScroll(wndPtr, dx, dy);
2442 if (dy) {
2443 dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
2444 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
2446 if (dx) {
2447 dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
2448 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
2451 return TRUE;
2455 /*********************************************************************
2457 * EM_SETHANDLE
2460 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2462 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2464 if (IsMultiLine(wndPtr)) {
2465 EDIT_ReleasePointer(wndPtr);
2467 * old buffer is freed by caller
2469 es->hBuf16 = (HLOCAL16)NULL;
2470 es->hBuf32 = (HLOCAL32)wParam;
2471 es->BufSize = LocalSize32(es->hBuf32) - 1;
2472 es->LineCount = 0;
2473 es->FirstVisibleLine = 0;
2474 es->SelStart = es->SelEnd = 0;
2475 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2476 EDIT_EM_SetModify(wndPtr, FALSE, 0);
2477 EDIT_BuildLineDefs(wndPtr);
2478 if (EDIT_GetRedraw(wndPtr))
2479 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2480 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2482 return 0;
2486 /*********************************************************************
2488 * EM_SETHANDLE16
2491 static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2493 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2495 if (IsMultiLine(wndPtr)) {
2496 EDIT_ReleasePointer(wndPtr);
2498 * old buffer is freed by caller
2500 es->hBuf16 = (HLOCAL16)wParam;
2501 es->hBuf32 = (HLOCAL32)NULL;
2502 es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1;
2503 es->LineCount = 0;
2504 es->FirstVisibleLine = 0;
2505 es->SelStart = es->SelEnd = 0;
2506 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
2507 EDIT_EM_SetModify(wndPtr, FALSE, 0);
2508 EDIT_BuildLineDefs(wndPtr);
2509 if (EDIT_GetRedraw(wndPtr))
2510 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2511 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2513 return 0;
2517 /*********************************************************************
2519 * EM_SETLIMITTEXT
2522 static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2524 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2526 if (IsMultiLine(wndPtr)) {
2527 if (wParam)
2528 es->BufLimit = MIN((INT32)wParam, BUFLIMIT_MULTI);
2529 else
2530 es->BufLimit = BUFLIMIT_MULTI;
2531 } else {
2532 if (wParam)
2533 es->BufLimit = MIN((INT32)wParam, BUFLIMIT_SINGLE);
2534 else
2535 es->BufLimit = BUFLIMIT_SINGLE;
2537 return 0;
2541 /*********************************************************************
2543 * EM_SETMARGINS
2545 * FIXME: We let the margins be set, but we don't use them yet !?!
2548 static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2550 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2552 if (wParam & EC_USEFONTINFO) {
2553 if (IsMultiLine(wndPtr)) {
2555 * FIXME: do some GetABCCharWidth, or so
2556 * This is just preliminary
2558 es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
2559 } else
2560 es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
2561 return 0;
2563 if (wParam & EC_LEFTMARGIN)
2564 es->LeftMargin = LOWORD(lParam);
2565 if (wParam & EC_RIGHTMARGIN)
2566 es->RightMargin = HIWORD(lParam);
2567 return 0;
2571 /*********************************************************************
2573 * EM_SETMODIFY
2576 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2578 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2580 es->TextChanged = (BOOL32)wParam;
2581 return 0;
2585 /*********************************************************************
2587 * EM_SETPASSWORDCHAR
2589 * FIXME: This imlementation is way too simple
2592 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2594 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2596 es->PasswordChar = (CHAR)wParam;
2597 return 0;
2601 /*********************************************************************
2603 * EM_SETREADONLY
2606 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2608 if ((BOOL32)wParam)
2609 wndPtr->dwStyle |= ES_READONLY;
2610 else
2611 wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
2612 return TRUE;
2616 /*********************************************************************
2618 * EM_SETRECT
2621 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2623 fprintf(stdnimp,"edit: EM_SETRECT: message not implemented\n");
2624 return 0;
2628 /*********************************************************************
2630 * EM_SETRECTNP
2633 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2635 fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented\n");
2636 return 0;
2640 /*********************************************************************
2642 * EM_SETSEL
2644 * FIXME: specs state that we should order start and end.
2645 * However, we use internally that this is not the case.
2648 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2650 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2651 INT32 ns = (INT32)wParam;
2652 INT32 ne = (INT32)lParam;
2653 INT32 s;
2654 INT32 e;
2655 INT32 el;
2656 INT32 eli;
2657 INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
2659 EDIT_GetSel(wndPtr, &s, &e);
2660 if (ns == -1) {
2661 ns = e;
2662 ne = e;
2664 if (ne == -1)
2665 ne = e;
2667 ORDER_INT32(ns, ne);
2669 ns = MIN(ns, tl);
2670 ne = MIN(ne, tl);
2671 es->SelStart = ns;
2672 es->SelEnd = ne;
2673 if (wndPtr->hwndSelf == GetFocus32()) {
2674 el = (INT32)EDIT_EM_LineFromChar(wndPtr, ne, 0);
2675 eli = (INT32)EDIT_EM_LineIndex(wndPtr, el, 0);
2676 SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - eli),
2677 EDIT_WndYFromLine(wndPtr, el));
2679 if (EDIT_GetRedraw(wndPtr)) {
2680 ORDER_INT32(s, e);
2681 ORDER_INT32(s, ns);
2682 ORDER_INT32(s, ne);
2683 ORDER_INT32(e, ns);
2684 ORDER_INT32(e, ne);
2685 ORDER_INT32(ns, ne);
2686 if (e != ns) {
2687 EDIT_InvalidateText(wndPtr, s, e);
2688 EDIT_InvalidateText(wndPtr, ns, ne);
2689 } else
2690 EDIT_InvalidateText(wndPtr, s, ne);
2692 return -1;
2696 /*********************************************************************
2698 * EM_SETSEL16
2701 static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2703 INT32 ns = (INT32)LOWORD(lParam);
2704 INT32 ne = (INT32)HIWORD(lParam);
2706 if ((INT16)LOWORD(lParam) == -1)
2707 ns = -1;
2708 if ((INT16)HIWORD(lParam) == -1)
2709 ne = -1;
2710 EDIT_EM_SetSel(wndPtr, ns, ne);
2711 if (!wParam)
2712 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2713 return -1;
2717 /*********************************************************************
2719 * EM_SETTABSTOPS
2722 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2724 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2725 INT32 i;
2727 if (!IsMultiLine(wndPtr))
2728 return FALSE;
2729 if (es->TabStops)
2730 free(es->TabStops);
2731 es->NumTabStops = (INT32)wParam;
2732 if (!wParam)
2733 es->TabStops = NULL;
2734 else {
2735 es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
2736 for ( i = 0 ; i < (INT32)wParam ; i++ )
2737 es->TabStops[i] = (INT16)((LPINT32)lParam)[i];
2739 return TRUE;
2743 /*********************************************************************
2745 * EM_SETTABSTOPS16
2748 static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2750 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2752 if (!IsMultiLine(wndPtr))
2753 return FALSE;
2754 if (es->TabStops)
2755 free(es->TabStops);
2756 es->NumTabStops = (INT32)wParam;
2757 if (!wParam)
2758 es->TabStops = NULL;
2759 else {
2760 es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
2761 memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam),
2762 (INT32)wParam * sizeof(INT16));
2764 return TRUE;
2768 /*********************************************************************
2770 * EM_SETWORDBREAKPROC
2773 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2776 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2778 es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
2780 return 0;
2784 /*********************************************************************
2786 * EM_UNDO
2789 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2791 fprintf(stdnimp,"edit: EM_UNDO: message not implemented\n");
2792 if (IsMultiLine(wndPtr))
2793 return FALSE;
2794 else
2795 return TRUE;
2799 /*********************************************************************
2801 * WM_CHAR
2804 static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2806 char str[2];
2807 unsigned char c = (unsigned char)wParam;
2809 switch (c) {
2810 case '\r':
2811 case '\n':
2812 if (IsMultiLine(wndPtr)) {
2813 if (IsReadOnly(wndPtr)) {
2814 EDIT_MoveHome(wndPtr, FALSE);
2815 EDIT_MoveDownward(wndPtr, FALSE);
2816 } else
2817 EDIT_EM_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n");
2819 break;
2820 case '\t':
2821 if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
2822 EDIT_EM_ReplaceSel(wndPtr, 0, (LPARAM)"\t");
2823 break;
2824 default:
2825 if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
2826 str[0] = c;
2827 str[1] = '\0';
2828 EDIT_EM_ReplaceSel(wndPtr, 0, (LPARAM)str);
2830 break;
2832 return 0;
2836 /*********************************************************************
2838 * WM_CLEAR
2841 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2843 INT32 s;
2844 INT32 e;
2845 LPSTR text;
2846 BOOL32 redraw;
2848 EDIT_GetSel(wndPtr, &s, &e);
2849 if (s != e) {
2850 redraw = EDIT_GetRedraw(wndPtr);
2851 EDIT_WM_SetRedraw(wndPtr, FALSE, 0);
2852 ORDER_INT32(s, e);
2853 text = EDIT_GetPointer(wndPtr);
2854 lstrcpy32A(text + s, text + e);
2855 EDIT_BuildLineDefs(wndPtr);
2856 EDIT_EM_SetSel(wndPtr, s, s);
2857 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
2858 EDIT_EM_SetModify(wndPtr, TRUE, 0);
2859 dprintf_edit(stddeb, "edit: notification EN_UPDATE sent\n");
2860 EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
2861 EDIT_WM_SetRedraw(wndPtr, redraw, 0);
2862 if (redraw) {
2863 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
2864 dprintf_edit(stddeb, "edit: notification EN_CHANGE sent\n");
2865 EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
2868 return -1;
2872 /*********************************************************************
2874 * WM_COPY
2877 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2879 INT32 s;
2880 INT32 e;
2881 HGLOBAL16 hdst;
2882 LPSTR text;
2883 LPSTR dst;
2884 LPSTR src;
2885 INT32 i;
2887 EDIT_GetSel(wndPtr, &s, &e);
2888 if (e == s)
2889 return -1;
2890 ORDER_INT32(s, e);
2891 hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
2892 dst = GlobalLock16(hdst);
2893 text = EDIT_GetPointer(wndPtr);
2894 src = text + s;
2895 for (i = 0 ; i < e - s ; i++)
2896 *dst++ = *src++;
2897 *dst = '\0';
2898 GlobalUnlock16(hdst);
2899 OpenClipboard(wndPtr->hwndSelf);
2900 EmptyClipboard();
2901 SetClipboardData(CF_TEXT, hdst);
2902 CloseClipboard();
2903 return -1;
2907 /*********************************************************************
2909 * WM_CREATE
2912 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2914 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
2915 EDITSTATE *es;
2916 LPSTR text;
2918 es = xmalloc(sizeof(EDITSTATE));
2919 memset(es, 0, sizeof(EDITSTATE));
2920 *(EDITSTATE **)wndPtr->wExtra = es;
2922 if (cs->style & WS_VSCROLL)
2923 cs->style |= ES_AUTOVSCROLL;
2924 if (cs->style & WS_HSCROLL)
2925 cs->style |= ES_AUTOHSCROLL;
2927 /* remove the WS_CAPTION style if it has been set - this is really a */
2928 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
2929 if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
2930 cs->style ^= WS_DLGFRAME;
2932 if (IsMultiLine(wndPtr)) {
2933 es->BufSize = BUFSTART_MULTI;
2934 es->BufLimit = BUFLIMIT_MULTI;
2935 es->PasswordChar = '\0';
2936 } else {
2937 es->BufSize = BUFSTART_SINGLE;
2938 es->BufLimit = BUFLIMIT_SINGLE;
2939 es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
2941 if (!(es->hBuf32 = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) {
2942 fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
2943 return -1;
2945 es->BufSize = LocalSize32(es->hBuf32) - 1;
2946 text = EDIT_GetPointer(wndPtr);
2947 *text = '\0';
2948 EDIT_BuildLineDefs(wndPtr);
2949 EDIT_WM_SetFont(wndPtr, 0, 0);
2950 if (cs->lpszName && *(cs->lpszName) != '\0')
2951 EDIT_EM_ReplaceSel(wndPtr, FALSE, (LPARAM)cs->lpszName);
2952 EDIT_WM_SetRedraw(wndPtr, TRUE, 0);
2953 return 0;
2957 /*********************************************************************
2959 * WM_CUT
2962 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2964 EDIT_WM_Copy(wndPtr, 0, 0);
2965 EDIT_WM_Clear(wndPtr, 0, 0);
2966 return -1;
2970 /*********************************************************************
2972 * WM_DESTROY
2975 static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2977 EDITSTATE *es = EDITSTATEPTR(wndPtr);
2979 free(es->LineDefs);
2980 if (es->TabStops)
2981 free(es->TabStops);
2982 EDIT_ReleasePointer(wndPtr);
2983 if (es->hBuf32)
2984 LocalFree32(es->hBuf32);
2985 else
2986 LOCAL_Free(wndPtr->hInstance, es->hBuf16);
2987 free(es);
2988 *(EDITSTATE **)&wndPtr->wExtra = NULL;
2989 return 0;
2993 /*********************************************************************
2995 * WM_ENABLE
2998 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3000 EDIT_InvalidateText(wndPtr, 0, -1);
3001 return 0;
3005 /*********************************************************************
3007 * WM_ERASEBKGND
3010 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3012 HBRUSH32 hBrush;
3013 RECT32 rc;
3015 hBrush = (HBRUSH32)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
3016 if (!hBrush) hBrush = (HBRUSH32)GetStockObject32(WHITE_BRUSH);
3018 GetClientRect32(wndPtr->hwndSelf, &rc);
3019 IntersectClipRect32((HDC32)wParam, rc.left, rc.top,
3020 rc.right, rc.bottom);
3021 GetClipBox32((HDC32)wParam, &rc);
3023 * FIXME: specs say that we should UnrealizeObject() the brush,
3024 * but the specs of UnrealizeObject() say that we shouldn't
3025 * unrealize a stock object. The default brush that
3026 * DefWndProc() returns is ... a stock object.
3028 FillRect32((HDC32)wParam, &rc, hBrush);
3029 return -1;
3033 /*********************************************************************
3035 * WM_GETDLGCODE
3038 static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3040 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
3044 /*********************************************************************
3046 * WM_GETFONT
3049 static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3051 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3053 return (LRESULT)es->hFont;
3057 /*********************************************************************
3059 * WM_GETTEXT
3062 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3064 LPSTR text = EDIT_GetPointer(wndPtr);
3065 INT32 len;
3066 LRESULT lResult = 0;
3068 len = lstrlen32A(text);
3069 if ((INT32)wParam > len) {
3070 lstrcpy32A((LPSTR)lParam, text);
3071 lResult = (LRESULT)len + 1;
3073 return lResult;
3077 /*********************************************************************
3079 * WM_GETTEXTLENGTH
3082 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3084 LPSTR text = EDIT_GetPointer(wndPtr);
3086 return (LRESULT)lstrlen32A(text);
3090 /*********************************************************************
3092 * WM_HSCROLL
3094 * FIXME: scrollbar code itself is broken, so this one is a hack.
3097 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3099 INT32 ww = EDIT_GetWndWidth(wndPtr);
3100 INT32 tw = EDIT_GetTextWidth(wndPtr);
3101 INT32 cw = EDIT_GetAveCharWidth(wndPtr);
3102 INT32 xoff = EDIT_GetXOffset(wndPtr);
3103 INT32 dx = 0;
3104 BOOL32 not = TRUE;
3105 LRESULT ret = 0;
3107 switch (wParam) {
3108 case SB_LINELEFT:
3109 dx = -cw;
3110 break;
3111 case SB_LINERIGHT:
3112 dx = cw;
3113 break;
3114 case SB_PAGELEFT:
3115 dx = -ww / HSCROLL_FRACTION / cw * cw;
3116 break;
3117 case SB_PAGERIGHT:
3118 dx = ww / HSCROLL_FRACTION / cw * cw;
3119 break;
3120 case SB_LEFT:
3121 dx = -xoff;
3122 break;
3123 case SB_RIGHT:
3124 dx = tw - xoff;
3125 break;
3126 case SB_THUMBTRACK:
3128 * not = FALSE;
3130 case SB_THUMBPOSITION:
3131 dx = HIWORD(wParam) * tw / 100 - xoff;
3132 break;
3133 /* The next two are undocumented ! */
3134 case EM_GETTHUMB16:
3135 ret = tw ? xoff * 100 / tw : 0;
3136 break;
3137 case EM_LINESCROLL16:
3138 dx = (INT16)HIWORD(wParam);
3139 break;
3140 case SB_ENDSCROLL:
3141 default:
3142 break;
3144 if (dx) {
3145 EDIT_EM_LineScroll(wndPtr, dx, 0);
3146 if (not) {
3147 dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
3148 EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
3151 return ret;
3155 /*********************************************************************
3157 * WM_KEYDOWN
3159 * Handling of special keys that don't produce a WM_CHAR
3160 * (i.e. non-printable keys) & Backspace & Delete
3163 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3165 INT32 s;
3166 INT32 e;
3167 BOOL32 shift;
3168 BOOL32 control;
3170 if (GetKeyState(VK_MENU) & 0x8000)
3171 return 0;
3173 shift = GetKeyState(VK_SHIFT) & 0x8000;
3174 control = GetKeyState(VK_CONTROL) & 0x8000;
3176 EDIT_GetSel(wndPtr, &s, &e);
3177 switch (wParam) {
3178 case VK_LEFT:
3179 case VK_UP:
3180 if (IsMultiLine(wndPtr) && (wParam == VK_UP))
3181 EDIT_MoveUpward(wndPtr, shift);
3182 else
3183 if (control)
3184 EDIT_MoveWordBackward(wndPtr, shift);
3185 else
3186 EDIT_MoveBackward(wndPtr, shift);
3187 break;
3188 case VK_RIGHT:
3189 case VK_DOWN:
3190 if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
3191 EDIT_MoveDownward(wndPtr, shift);
3192 else if (control)
3193 EDIT_MoveWordForward(wndPtr, shift);
3194 else
3195 EDIT_MoveForward(wndPtr, shift);
3196 break;
3197 case VK_HOME:
3198 EDIT_MoveHome(wndPtr, shift);
3199 break;
3200 case VK_END:
3201 EDIT_MoveEnd(wndPtr, shift);
3202 break;
3203 case VK_PRIOR:
3204 if (IsMultiLine(wndPtr))
3205 EDIT_MovePageUp(wndPtr, shift);
3206 break;
3207 case VK_NEXT:
3208 if (IsMultiLine(wndPtr))
3209 EDIT_MovePageDown(wndPtr, shift);
3210 break;
3211 case VK_BACK:
3212 if (!IsReadOnly(wndPtr) && !control)
3213 if (e != s)
3214 EDIT_WM_Clear(wndPtr, 0, 0);
3215 else
3216 EDIT_DelLeft(wndPtr);
3217 break;
3218 case VK_DELETE:
3219 if (!IsReadOnly(wndPtr) && !(shift && control))
3220 if (e != s) {
3221 if (shift)
3222 EDIT_WM_Cut(wndPtr, 0, 0);
3223 else
3224 EDIT_WM_Clear(wndPtr, 0, 0);
3225 } else {
3226 if (shift)
3227 EDIT_DelLeft(wndPtr);
3228 else if (control)
3229 EDIT_DelEnd(wndPtr);
3230 else
3231 EDIT_DelRight(wndPtr);
3233 break;
3234 case VK_INSERT:
3235 if (shift) {
3236 if (!IsReadOnly(wndPtr))
3237 EDIT_WM_Paste(wndPtr, 0, 0);
3238 } else if (control)
3239 EDIT_WM_Copy(wndPtr, 0, 0);
3240 break;
3242 return 0;
3246 /*********************************************************************
3248 * WM_KILLFOCUS
3251 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3253 INT32 s;
3254 INT32 e;
3256 DestroyCaret();
3257 if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
3258 EDIT_GetSel(wndPtr, &s, &e);
3259 EDIT_InvalidateText(wndPtr, s, e);
3261 dprintf_edit(stddeb, "edit: notification EN_KILLFOCUS sent\n");
3262 EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
3263 return 0;
3267 /*********************************************************************
3269 * WM_LBUTTONDBLCLK
3271 * The caret position has been set on the WM_LBUTTONDOWN message
3274 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3276 INT32 s;
3277 INT32 e;
3278 INT32 l;
3279 INT32 li;
3280 INT32 ll;
3281 LPSTR text = EDIT_GetPointer(wndPtr);
3283 EDIT_GetSel(wndPtr, NULL, &e);
3284 l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
3285 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
3286 ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
3287 s = li + EDIT_CallWordBreakProc (wndPtr, text + li, e - li, ll, WB_LEFT);
3288 e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
3289 EDIT_EM_SetSel(wndPtr, s, e);
3290 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3291 return 0;
3295 /*********************************************************************
3297 * WM_LBUTTONDOWN
3300 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3302 INT32 x = (INT32)(INT16)LOWORD(lParam);
3303 INT32 y = (INT32)(INT16)HIWORD(lParam);
3304 INT32 l = EDIT_LineFromWndY(wndPtr, y);
3305 INT32 c;
3306 INT32 s;
3307 INT32 e;
3308 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3309 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3310 INT32 li;
3312 SetFocus32(wndPtr->hwndSelf);
3313 SetCapture32(wndPtr->hwndSelf);
3314 l = MIN(fv + vlc - 1, MAX(fv, l));
3315 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
3316 c = EDIT_ColFromWndX(wndPtr, l, x);
3317 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
3318 e = li + c;
3319 if (GetKeyState(VK_SHIFT) & 0x8000)
3320 EDIT_GetSel(wndPtr, &s, NULL);
3321 else
3322 s = e;
3323 EDIT_EM_SetSel(wndPtr, s, e);
3324 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3325 return 0;
3329 /*********************************************************************
3331 * WM_LBUTTONUP
3334 static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3336 if (GetCapture32() == wndPtr->hwndSelf)
3337 ReleaseCapture();
3338 return 0;
3342 /*********************************************************************
3344 * WM_MOUSEMOVE
3347 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3349 INT32 x;
3350 INT32 y;
3351 INT32 l;
3352 INT32 c;
3353 INT32 s;
3354 INT32 fv;
3355 INT32 vlc;
3356 INT32 li;
3358 if (GetCapture32() == wndPtr->hwndSelf) {
3359 x = (INT32)(INT16)LOWORD(lParam);
3360 y = (INT32)(INT16)HIWORD(lParam);
3361 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3362 vlc = EDIT_GetVisibleLineCount(wndPtr);
3363 l = EDIT_LineFromWndY(wndPtr, y);
3364 l = MIN(fv + vlc - 1, MAX(fv, l));
3365 x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
3366 c = EDIT_ColFromWndX(wndPtr, l, x);
3367 EDIT_GetSel(wndPtr, &s, NULL);
3368 li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
3369 EDIT_EM_SetSel(wndPtr, s, li + c);
3371 return 0;
3375 /*********************************************************************
3377 * WM_PAINT
3380 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3382 PAINTSTRUCT32 ps;
3383 INT32 i;
3384 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3385 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3386 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
3387 HDC32 hdc;
3388 HFONT32 hFont;
3389 HFONT32 oldFont = 0;
3390 RECT32 rc;
3391 RECT32 rcLine;
3392 RECT32 rcRgn;
3393 BOOL32 rev = IsWindowEnabled(wndPtr->hwndSelf) &&
3394 ((GetFocus32() == wndPtr->hwndSelf) ||
3395 (wndPtr->dwStyle & ES_NOHIDESEL));
3397 hdc = BeginPaint32(wndPtr->hwndSelf, &ps);
3398 GetClientRect32(wndPtr->hwndSelf, &rc);
3399 IntersectClipRect32( hdc, rc.left, rc.top, rc.right, rc.bottom );
3400 hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
3401 if (hFont)
3402 oldFont = (HFONT32)SelectObject32(hdc, hFont);
3403 EDIT_SEND_CTLCOLOR(wndPtr, hdc);
3404 if (!IsWindowEnabled(wndPtr->hwndSelf))
3405 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
3406 GetClipBox32(hdc, &rcRgn);
3407 for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
3408 EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
3409 if (IntersectRect32(&rc, &rcRgn, &rcLine))
3410 EDIT_PaintLine(wndPtr, hdc, i, rev);
3412 if (hFont) SelectObject32(hdc, oldFont);
3413 EndPaint32(wndPtr->hwndSelf, &ps);
3414 return 0;
3418 /*********************************************************************
3420 * WM_PASTE
3423 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3425 HGLOBAL16 hsrc;
3426 LPSTR src;
3428 OpenClipboard(wndPtr->hwndSelf);
3429 if ((hsrc = GetClipboardData(CF_TEXT))) {
3430 src = (LPSTR)GlobalLock16(hsrc);
3431 EDIT_EM_ReplaceSel(wndPtr, 0, (LPARAM)src);
3432 GlobalUnlock16(hsrc);
3434 CloseClipboard();
3435 return -1;
3439 /*********************************************************************
3441 * WM_SETCURSOR
3444 static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3446 if (LOWORD(lParam) == HTCLIENT) {
3447 SetCursor(LoadCursor16(0, IDC_IBEAM));
3448 return -1;
3449 } else
3450 return 0;
3454 /*********************************************************************
3456 * WM_SETFOCUS
3459 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3461 INT32 s;
3462 INT32 e;
3464 EDIT_GetSel(wndPtr, &s, &e);
3465 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
3466 EDIT_EM_SetSel(wndPtr, s, e);
3467 if(!(wndPtr->dwStyle & ES_NOHIDESEL))
3468 EDIT_InvalidateText(wndPtr, s, e);
3469 ShowCaret(wndPtr->hwndSelf);
3470 dprintf_edit(stddeb, "edit: notification EN_SETFOCUS sent\n");
3471 EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
3472 return 0;
3476 /*********************************************************************
3478 * WM_SETFONT
3481 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3483 TEXTMETRIC32A tm;
3484 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3485 INT32 s;
3486 INT32 e;
3487 HDC32 hdc;
3488 HFONT32 oldFont = 0;
3490 EDIT_GetSel(wndPtr, &s, &e);
3491 es->hFont = (HFONT32)wParam;
3492 hdc = GetDC32(wndPtr->hwndSelf);
3493 if (es->hFont) oldFont = SelectObject32(hdc, es->hFont);
3494 GetTextMetrics32A(hdc, &tm);
3495 es->LineHeight = tm.tmHeight;
3496 es->AveCharWidth = tm.tmAveCharWidth;
3497 if (es->hFont) SelectObject32(hdc, oldFont);
3498 ReleaseDC32(wndPtr->hwndSelf, hdc);
3499 EDIT_BuildLineDefs(wndPtr);
3500 if ((BOOL32)lParam && EDIT_GetRedraw(wndPtr))
3501 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
3502 if (wndPtr->hwndSelf == GetFocus32()) {
3503 DestroyCaret();
3504 CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
3505 EDIT_EM_SetSel16(wndPtr, s, e);
3506 ShowCaret(wndPtr->hwndSelf);
3508 return 0;
3512 /*********************************************************************
3514 * WM_SETREDRAW
3517 static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3519 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3521 es->Redraw = (BOOL32)wParam;
3522 return 0;
3526 /*********************************************************************
3528 * WM_SETTEXT
3531 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3533 EDIT_EM_SetSel(wndPtr, 0, -1);
3534 if (lParam)
3535 EDIT_EM_ReplaceSel(wndPtr, 0, lParam);
3536 else
3537 EDIT_WM_Clear(wndPtr, 0, 0);
3538 EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
3539 EDIT_EM_SetModify(wndPtr, TRUE, 0);
3540 EDIT_EM_ScrollCaret(wndPtr, 0, 0);
3541 return 1;
3545 /*********************************************************************
3547 * WM_SIZE
3549 * FIXME: What about that FormatRect ???
3552 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3554 EDITSTATE *es = EDITSTATEPTR(wndPtr);
3556 GetClientRect32(wndPtr->hwndSelf, &es->FormatRect);
3557 if (EDIT_GetRedraw(wndPtr) &&
3558 ((wParam == SIZE_MAXIMIZED) ||
3559 (wParam == SIZE_RESTORED))) {
3560 if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
3561 EDIT_BuildLineDefs(wndPtr);
3562 InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
3564 return 0;
3568 /*********************************************************************
3570 * WM_VSCROLL
3572 * FIXME: scrollbar code itself is broken, so this one is a hack.
3575 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
3577 INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
3578 INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
3579 INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
3580 INT32 dy = 0;
3581 BOOL32 not = TRUE;
3582 LRESULT ret = 0;
3584 switch (wParam) {
3585 case SB_LINEUP:
3586 dy = -1;
3587 break;
3588 case SB_LINEDOWN:
3589 dy = 1;
3590 break;
3591 case SB_PAGEUP:
3592 dy = -vlc;
3593 break;
3594 case SB_PAGEDOWN:
3595 dy = vlc;
3596 break;
3597 case SB_TOP:
3598 dy = -fv;
3599 break;
3600 case SB_BOTTOM:
3601 dy = lc - 1 - fv;
3602 break;
3603 case SB_THUMBTRACK:
3604 not = FALSE;
3605 /* fall through */
3606 case SB_THUMBPOSITION:
3607 dy = HIWORD(wParam) * (lc - 1) / 100 - fv;
3608 break;
3609 /* The next two are undocumented ! */
3610 case EM_GETTHUMB16:
3611 ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0;
3612 break;
3613 case EM_LINESCROLL16:
3614 dy = (INT16)LOWORD(lParam);
3615 break;
3616 case SB_ENDSCROLL:
3617 default:
3618 break;
3620 if (dy) {
3621 EDIT_EM_LineScroll(wndPtr, 0, dy);
3622 if (not) {
3623 dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
3624 EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
3627 return ret;