Release 950319
[wine/multimedia.git] / controls / edit.c
blob5a42a133d57e822314d6b564dad63353c14ec0f8
1 /*
2 * Edit control
4 * Copyright David W. Metcalfe, 1994
6 * Release 3, July 1994
8 static char Copyright[] = "Copyright David W. Metcalfe, 1994";
9 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <windows.h>
15 #include "local.h"
16 #include "win.h"
17 #include "class.h"
18 #include "user.h"
19 #include "stddebug.h"
20 /* #define DEBUG_EDIT */
21 /* #undef DEBUG_EDIT */
22 #include "debug.h"
25 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
26 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
27 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
29 #define MAXTEXTLEN 30000 /* maximum text buffer length */
30 #define EDITLEN 1024 /* starting length for multi-line control */
31 #define ENTRYLEN 256 /* starting length for single line control */
32 #define GROWLENGTH 64 /* buffers grow by this much */
34 #define HSCROLLDIM (ClientWidth(wndPtr) / 3)
35 /* "line" dimension for horizontal scroll */
37 typedef struct
39 int wlines; /* number of lines of text */
40 int wtop; /* top line that is displayed */
41 int wleft; /* left pixel that is displayed */
42 unsigned int textlen; /* text buffer length */
43 int textwidth; /* width of longest line in pixels */
44 RECT fmtrc; /* rectangle in which to format text */
45 int txtht; /* height of text line in pixels */
46 HANDLE hText; /* handle to text buffer */
47 HANDLE hCharWidths; /* widths of chars in font */
48 HANDLE hTextPtrs; /* list of line offsets */
49 HANDLE hBlankLine; /* to fill blank lines quickly */
50 int CurrCol; /* current column */
51 int CurrLine; /* current line */
52 int WndCol; /* current window column */
53 int WndRow; /* current window row */
54 BOOL TextChanged; /* TRUE if text has changed */
55 BOOL PaintBkgd; /* paint control background */
56 unsigned int MaxTextLen; /* maximum text buffer length */
57 int SelBegLine; /* beginning line of selection */
58 int SelBegCol; /* beginning column of selection */
59 int SelEndLine; /* ending line of selection */
60 int SelEndCol; /* ending column of selection */
61 HFONT hFont; /* handle of current font (if not default) */
62 HANDLE hDeletedText; /* handle to deleted txet buffer for undo */
63 int DeletedLength; /* length of deleted text */
64 int DeletedCurrLine; /* starting line from which text was deleted */
65 int DeletedCurrCol; /* starting col from which text was deleted */
66 int NumTabStops; /* number of tab stops in buffer hTabStops */
67 HANDLE hTabStops; /* handle of tab stops buffer */
68 } EDITSTATE;
71 #define ClientWidth(wndPtr) \
72 (wndPtr->rectClient.right > wndPtr->rectClient.left ? \
73 wndPtr->rectClient.right - wndPtr->rectClient.left : 0)
74 #define ClientHeight(wndPtr, es) \
75 (wndPtr->rectClient.bottom > wndPtr->rectClient.top ? \
76 (wndPtr->rectClient.bottom - wndPtr->rectClient.top) / es->txtht : 0)
77 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
78 ? EDITLEN : ENTRYLEN)
79 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
80 #define SelMarked(es) (es->SelBegLine != 0 || es->SelBegCol != 0 || \
81 es->SelEndLine != 0 || es->SelEndCol != 0)
82 #define ROUNDUP(numer, denom) (((numer) % (denom)) \
83 ? ((((numer) + (denom)) / (denom)) * (denom)) \
84 : (numer) + (denom))
86 /* macros to access window styles */
87 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
88 #define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
89 #define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
90 #define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
91 #define IsHScrollBar() (wndPtr->dwStyle & WS_HSCROLL)
93 /* internal variables */
94 static BOOL TextMarking; /* TRUE if text marking in progress */
95 static BOOL ButtonDown; /* TRUE if left mouse button down */
96 static int ButtonRow; /* row in text buffer when button pressed */
97 static int ButtonCol; /* col in text buffer when button pressed */
100 LONG EditWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
101 long EDIT_NCCreateMsg(HWND hwnd, LONG lParam);
102 long EDIT_CreateMsg(HWND hwnd, LONG lParam);
103 void EDIT_ClearTextPointers(HWND hwnd);
104 void EDIT_BuildTextPointers(HWND hwnd);
105 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var);
106 void EDIT_PaintMsg(HWND hwnd);
107 HANDLE EDIT_GetTextLine(HWND hwnd, int selection);
108 char *EDIT_TextLine(HWND hwnd, int sel);
109 int EDIT_StrLength(HWND hwnd, unsigned char *str, int len, int pcol);
110 int EDIT_LineLength(HWND hwnd, int num);
111 void EDIT_WriteTextLine(HWND hwnd, RECT *rc, int y);
112 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
113 int col, RECT *rc, BOOL blank, BOOL reverse);
114 HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff);
115 void EDIT_CharMsg(HWND hwnd, WORD wParam);
116 void EDIT_KeyTyped(HWND hwnd, short ch);
117 int EDIT_CharWidth(HWND hwnd, short ch, int pcol);
118 int EDIT_GetNextTabStop(HWND hwnd, int pcol);
119 void EDIT_Forward(HWND hwnd);
120 void EDIT_Downward(HWND hwnd);
121 void EDIT_Upward(HWND hwnd);
122 void EDIT_Backward(HWND hwnd);
123 void EDIT_End(HWND hwnd);
124 void EDIT_Home(HWND hwnd);
125 void EDIT_StickEnd(HWND hwnd);
126 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam);
127 void EDIT_KeyHScroll(HWND hwnd, WORD opt);
128 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt);
129 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt);
130 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt);
131 int EDIT_ComputeVScrollPos(HWND hwnd);
132 int EDIT_ComputeHScrollPos(HWND hwnd);
133 void EDIT_DelKey(HWND hwnd);
134 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
135 void EDIT_VScrollLine(HWND hwnd, WORD opt);
136 void EDIT_VScrollPage(HWND hwnd, WORD opt);
137 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
138 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam);
139 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam);
140 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam);
141 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel);
142 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam);
143 void EDIT_ClearText(HWND hwnd);
144 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam);
145 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col);
146 void EDIT_DeleteSel(HWND hwnd);
147 void EDIT_ClearSel(HWND hwnd);
148 int EDIT_TextLineNumber(HWND hwnd, char *lp);
149 void EDIT_SetAnchor(HWND hwnd, int row, int col);
150 void EDIT_ExtendSel(HWND hwnd, int x, int y);
151 void EDIT_WriteSel(HWND hwnd, int y, int start, int end);
152 void EDIT_StopMarking(HWND hwnd);
153 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
154 LONG EDIT_GetSelMsg(HWND hwnd);
155 void EDIT_ReplaceSel(HWND hwnd, LONG lParam);
156 void EDIT_InsertText(HWND hwnd, char *str, int len);
157 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam);
158 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam);
159 LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam);
160 void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam);
161 void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len, int line,
162 int col);
163 void EDIT_ClearDeletedText(HWND hwnd);
164 LONG EDIT_UndoMsg(HWND hwnd);
165 unsigned int EDIT_HeapAlloc(HWND hwnd, int bytes);
166 void *EDIT_HeapAddr(HWND hwnd, unsigned int handle);
167 unsigned int EDIT_HeapReAlloc(HWND hwnd, unsigned int handle, int bytes);
168 void EDIT_HeapFree(HWND hwnd, unsigned int handle);
169 unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle);
170 void EDIT_SetHandleMsg(HWND hwnd, WORD wParam);
171 LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam);
172 void EDIT_CopyToClipboard(HWND hwnd);
173 void EDIT_PasteMsg(HWND hwnd);
174 void swap(int *a, int *b);
177 LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
179 LONG lResult = 0L;
180 char *textPtr;
181 int len;
182 WND *wndPtr = WIN_FindWndPtr(hwnd);
183 EDITSTATE *es =
184 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
186 switch (uMsg) {
187 case EM_CANUNDO:
188 lResult = es->hDeletedText;
189 break;
191 case EM_EMPTYUNDOBUFFER:
192 EDIT_ClearDeletedText(hwnd);
193 break;
195 case EM_FMTLINES:
196 fprintf(stdnimp,"edit: EM_FMTLINES message received\n");
197 if (!wParam)
198 lResult = 1L;
199 else
200 lResult = 0L;
201 break;
203 case EM_GETFIRSTVISIBLELINE:
204 lResult = es->wtop;
205 break;
207 case EM_GETHANDLE:
208 lResult = es->hText;
209 break;
211 case EM_GETLINE:
212 if (IsMultiLine())
213 lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
214 else
215 lResult = 0L;
216 break;
218 case EM_GETLINECOUNT:
219 if (IsMultiLine())
220 lResult = es->wlines;
221 else
222 lResult = 0L;
223 break;
225 case EM_GETMODIFY:
226 lResult = es->TextChanged;
227 break;
229 case EM_GETPASSWORDCHAR:
230 fprintf(stdnimp,"edit: cannot process EM_GETPASSWORDCHAR message\n");
231 break;
233 case EM_GETRECT:
234 GetWindowRect(hwnd, (LPRECT)PTR_SEG_TO_LIN(lParam));
235 break;
237 case EM_GETSEL:
238 lResult = EDIT_GetSelMsg(hwnd);
239 break;
241 case EM_GETWORDBREAKPROC:
242 fprintf(stdnimp,"edit: cannot process EM_GETWORDBREAKPROC message\n");
243 break;
245 case EM_LIMITTEXT:
246 if (wParam)
247 es->MaxTextLen = wParam;
248 else if (IsMultiLine())
249 es->MaxTextLen = 65535;
250 else
251 es->MaxTextLen = 32767;
252 break;
254 case EM_LINEFROMCHAR:
255 lResult = EDIT_LineFromCharMsg(hwnd, wParam);
256 break;
258 case EM_LINEINDEX:
259 if (IsMultiLine())
260 lResult = EDIT_LineIndexMsg(hwnd, wParam);
261 else
262 lResult = 0L;
263 break;
265 case EM_LINELENGTH:
266 lResult = EDIT_LineLengthMsg(hwnd, wParam);
267 break;
269 case EM_LINESCROLL:
270 fprintf(stdnimp,"edit: cannot process EM_LINESCROLL message\n");
271 break;
273 case EM_REPLACESEL:
274 HideCaret(hwnd);
275 EDIT_ReplaceSel(hwnd, lParam);
276 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
277 ShowCaret(hwnd);
278 break;
280 case EM_SETHANDLE:
281 HideCaret(hwnd);
282 EDIT_SetHandleMsg(hwnd, wParam);
283 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
284 ShowCaret(hwnd);
285 break;
287 case EM_SETMODIFY:
288 es->TextChanged = wParam;
289 break;
291 case EM_SETPASSWORDCHAR:
292 fprintf(stdnimp,"edit: cannot process EM_SETPASSWORDCHAR message\n");
293 break;
295 case EM_SETREADONLY:
296 fprintf(stdnimp,"edit: cannot process EM_SETREADONLY message\n");
297 break;
299 case EM_SETRECT:
300 case EM_SETRECTNP:
301 fprintf(stdnimp,"edit: cannot process EM_SETRECT(NP) message\n");
302 break;
304 case EM_SETSEL:
305 HideCaret(hwnd);
306 EDIT_SetSelMsg(hwnd, wParam, lParam);
307 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
308 ShowCaret(hwnd);
309 break;
311 case EM_SETTABSTOPS:
312 lResult = EDIT_SetTabStopsMsg(hwnd, wParam, lParam);
313 break;
315 case EM_SETWORDBREAKPROC:
316 fprintf(stdnimp,"edit: cannot process EM_SETWORDBREAKPROC message\n");
317 break;
319 case EM_UNDO:
320 HideCaret(hwnd);
321 lResult = EDIT_UndoMsg(hwnd);
322 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
323 ShowCaret(hwnd);
324 break;
326 case WM_GETDLGCODE:
327 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
329 case WM_CHAR:
330 EDIT_CharMsg(hwnd, wParam);
331 break;
333 case WM_COPY:
334 EDIT_CopyToClipboard(hwnd);
335 EDIT_ClearSel(hwnd);
336 break;
338 case WM_CREATE:
339 lResult = EDIT_CreateMsg(hwnd, lParam);
340 break;
342 case WM_CUT:
343 EDIT_CopyToClipboard(hwnd);
344 EDIT_DeleteSel(hwnd);
345 break;
347 case WM_DESTROY:
348 EDIT_HeapFree(hwnd, es->hTextPtrs);
349 EDIT_HeapFree(hwnd, es->hCharWidths);
350 EDIT_HeapFree(hwnd, es->hText);
351 EDIT_HeapFree(hwnd, (HANDLE)(*(wndPtr->wExtra)));
352 break;
354 case WM_ENABLE:
355 InvalidateRect(hwnd, NULL, FALSE);
356 break;
358 case WM_GETTEXT:
359 textPtr = EDIT_HeapAddr(hwnd, es->hText);
360 if ((int)wParam > (len = strlen(textPtr)))
362 strcpy((char *)PTR_SEG_TO_LIN(lParam), textPtr);
363 lResult = (DWORD)len ;
365 else
366 lResult = 0L;
367 break;
369 case WM_GETTEXTLENGTH:
370 textPtr = EDIT_HeapAddr(hwnd, es->hText);
371 lResult = (DWORD)strlen(textPtr);
372 break;
374 case WM_HSCROLL:
375 EDIT_HScrollMsg(hwnd, wParam, lParam);
376 break;
378 case WM_KEYDOWN:
379 EDIT_KeyDownMsg(hwnd, wParam);
380 break;
382 case WM_KILLFOCUS:
383 DestroyCaret();
384 NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
385 break;
387 case WM_LBUTTONDOWN:
388 HideCaret(hwnd);
389 SetFocus(hwnd);
390 EDIT_LButtonDownMsg(hwnd, wParam, lParam);
391 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
392 ShowCaret(hwnd);
393 break;
395 case WM_LBUTTONUP:
396 ButtonDown = FALSE;
397 if (TextMarking)
398 EDIT_StopMarking(hwnd);
399 break;
401 case WM_MOUSEMOVE:
402 HideCaret(hwnd);
403 EDIT_MouseMoveMsg(hwnd, wParam, lParam);
404 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
405 ShowCaret(hwnd);
406 break;
408 case WM_MOVE:
409 lResult = 0;
410 break;
412 case WM_NCCREATE:
413 lResult = EDIT_NCCreateMsg(hwnd, lParam);
414 break;
416 case WM_PAINT:
417 EDIT_PaintMsg(hwnd);
418 break;
420 case WM_PASTE:
421 EDIT_PasteMsg(hwnd);
422 break;
424 case WM_SETFOCUS:
425 CreateCaret(hwnd, 0, 2, es->txtht);
426 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
427 ShowCaret(hwnd);
428 NOTIFY_PARENT(hwnd, EN_SETFOCUS);
429 break;
431 case WM_SETFONT:
432 HideCaret(hwnd);
433 EDIT_SetFont(hwnd, wParam, lParam);
434 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
435 ShowCaret(hwnd);
436 break;
437 #if 0
438 case WM_SETREDRAW:
439 dprintf_edit(stddeb, "WM_SETREDRAW: hwnd=%d, wParam=%x\n",
440 hwnd, wParam);
441 lResult = 0;
442 break;
443 #endif
444 case WM_SETTEXT:
445 EDIT_SetTextMsg(hwnd, lParam);
446 break;
448 case WM_SIZE:
449 EDIT_SizeMsg(hwnd, wParam, lParam);
450 lResult = 0;
451 break;
453 case WM_VSCROLL:
454 EDIT_VScrollMsg(hwnd, wParam, lParam);
455 break;
457 default:
458 lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
459 break;
462 return lResult;
466 /*********************************************************************
467 * WM_NCCREATE message function
470 long EDIT_NCCreateMsg(HWND hwnd, LONG lParam)
472 CREATESTRUCT *createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
473 WND *wndPtr = WIN_FindWndPtr(hwnd);
474 EDITSTATE *es;
475 unsigned int *textPtrs;
476 char *text;
478 /* store pointer to local or global heap in window structure so that */
479 /* EDITSTATE structure itself can be stored on local heap */
480 #if 0
481 if (HEAP_LocalFindHeap(createStruct->hInstance)!=NULL)
482 (MDESC **)*(LONG *)(wndPtr->wExtra + 2) =
483 &HEAP_LocalFindHeap(createStruct->hInstance)->free_list;
484 else
486 (MDESC **)*(LONG *)(wndPtr->wExtra + 2) =
487 GlobalLock(createStruct->hInstance);
488 /* GlobalUnlock(createStruct->hInstance); */
490 #endif
491 /* allocate space for state variable structure */
492 (HANDLE)(*(wndPtr->wExtra)) = EDIT_HeapAlloc(hwnd, sizeof(EDITSTATE));
493 es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
494 es->hTextPtrs = EDIT_HeapAlloc(hwnd, sizeof(int));
495 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
496 es->hCharWidths = EDIT_HeapAlloc(hwnd, 256 * sizeof(short));
498 /* --- text buffer */
499 es->MaxTextLen = MAXTEXTLEN + 1;
500 if (!(createStruct->lpszName))
502 es->textlen = EditBufLen(wndPtr) + 1;
503 es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
504 text = EDIT_HeapAddr(hwnd, es->hText);
505 memset(text, 0, es->textlen + 2);
506 es->wlines = 0;
507 es->textwidth = 0;
508 EDIT_ClearTextPointers(hwnd);
510 else
512 char *windowName = (char *)PTR_SEG_TO_LIN( createStruct->lpszName );
513 if (strlen(windowName) < EditBufLen(wndPtr))
515 es->textlen = EditBufLen(wndPtr) + 1;
516 es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
517 text = EDIT_HeapAddr(hwnd, es->hText);
518 strcpy(text, windowName);
519 *(text + es->textlen) = '\0';
521 else
523 es->hText = EDIT_HeapAlloc(hwnd, strlen(windowName) + 2);
524 text = EDIT_HeapAddr(hwnd, es->hText);
525 strcpy(text, windowName);
526 es->textlen = strlen(windowName) + 1;
528 *(text + es->textlen + 1) = '\0';
529 EDIT_BuildTextPointers(hwnd);
532 /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
533 /* the corresponding WS_* style is set */
534 if (createStruct->style & WS_VSCROLL)
535 wndPtr->dwStyle |= ES_AUTOVSCROLL;
536 if (createStruct->style & WS_HSCROLL)
537 wndPtr->dwStyle |= ES_AUTOHSCROLL;
539 /* remove the WS_CAPTION style if it has been set - this is really a */
540 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
541 if (wndPtr->dwStyle & WS_BORDER && wndPtr->dwStyle & WS_DLGFRAME)
542 wndPtr->dwStyle ^= WS_DLGFRAME;
544 return 1;
548 /*********************************************************************
549 * WM_CREATE message function
552 long EDIT_CreateMsg(HWND hwnd, LONG lParam)
554 HDC hdc;
555 WND *wndPtr = WIN_FindWndPtr(hwnd);
556 EDITSTATE *es =
557 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
558 CLASS *classPtr;
559 short *charWidths;
560 TEXTMETRIC tm;
561 char *text;
563 /* initialize state variable structure */
564 hdc = GetDC(hwnd);
566 /* --- char width array */
567 /* only initialise chars <= 32 as X returns strange widths */
568 /* for other chars */
569 charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
570 memset(charWidths, 0, 256 * sizeof(short));
571 GetCharWidth(hdc, 32, 254, &charWidths[32]);
573 /* --- other structure variables */
574 GetTextMetrics(hdc, &tm);
575 es->txtht = tm.tmHeight + tm.tmExternalLeading;
576 es->wtop = es->wleft = 0;
577 es->CurrCol = es->CurrLine = 0;
578 es->WndCol = es->WndRow = 0;
579 es->TextChanged = FALSE;
580 es->SelBegLine = es->SelBegCol = 0;
581 es->SelEndLine = es->SelEndCol = 0;
582 es->hFont = 0;
583 es->hDeletedText = 0;
584 es->DeletedLength = 0;
585 es->NumTabStops = 0;
586 es->hTabStops = EDIT_HeapAlloc(hwnd, sizeof(int));
588 /* allocate space for a line full of blanks to speed up */
589 /* line filling */
590 es->hBlankLine = EDIT_HeapAlloc(hwnd, (ClientWidth(wndPtr) /
591 charWidths[32]) + 2);
592 text = EDIT_HeapAddr(hwnd, es->hBlankLine);
593 memset(text, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
595 /* set up text cursor for edit class */
596 CLASS_FindClassByName("EDIT", 0, &classPtr);
597 classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);
599 /* paint background on first WM_PAINT */
600 es->PaintBkgd = TRUE;
602 ReleaseDC(hwnd, hdc);
603 return 0L;
607 /*********************************************************************
608 * EDIT_ClearTextPointers
610 * Clear and initialize text line pointer array.
613 void EDIT_ClearTextPointers(HWND hwnd)
615 unsigned int *textPtrs;
616 WND *wndPtr = WIN_FindWndPtr(hwnd);
617 EDITSTATE *es =
618 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
620 es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs, sizeof(int));
621 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
622 *textPtrs = 0;
626 /*********************************************************************
627 * EDIT_BuildTextPointers
629 * Build array of pointers to text lines.
632 #define INITLINES 100
634 void EDIT_BuildTextPointers(HWND hwnd)
636 WND *wndPtr = WIN_FindWndPtr(hwnd);
637 char *text, *cp;
638 int incrs = INITLINES;
639 unsigned int off, len;
640 EDITSTATE *es;
641 unsigned int *textPtrs;
642 short *charWidths;
644 es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
645 text = EDIT_HeapAddr(hwnd, es->hText);
646 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
647 charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
649 es->textwidth = es->wlines = 0;
650 cp = text;
652 /* advance through text buffer */
653 while (*cp)
655 /* increase size of text pointer array */
656 if (incrs == INITLINES)
658 incrs = 0;
659 es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs,
660 (es->wlines + INITLINES) * sizeof(int));
661 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
663 off = (unsigned int)(cp - text); /* offset of beginning of line */
664 *(textPtrs + es->wlines) = off;
665 es->wlines++;
666 incrs++;
667 len = 0;
669 /* advance through current line */
670 while (*cp && *cp != '\n')
672 len += EDIT_CharWidth(hwnd, (BYTE)*cp, len);
673 /* width of line in pixels */
674 cp++;
676 es->textwidth = max(es->textwidth, len);
677 if (*cp)
678 cp++; /* skip '\n' */
681 off = (unsigned int)(cp - text);
682 *(textPtrs + es->wlines) = off;
686 /*********************************************************************
687 * EDIT_ModTextPointers
689 * Modify text pointers from a specified position.
692 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
694 WND *wndPtr = WIN_FindWndPtr(hwnd);
695 EDITSTATE *es =
696 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
697 unsigned int *textPtrs =
698 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
700 while (lineno < es->wlines)
701 *(textPtrs + lineno++) += var;
705 /*********************************************************************
706 * WM_PAINT message function
709 void EDIT_PaintMsg(HWND hwnd)
711 PAINTSTRUCT ps;
712 HDC hdc;
713 int y;
714 RECT rc;
715 WND *wndPtr = WIN_FindWndPtr(hwnd);
716 EDITSTATE *es =
717 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
719 hdc = BeginPaint(hwnd, &ps);
720 rc = ps.rcPaint;
722 dprintf_edit(stddeb,"WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc.left, rc.top,
723 rc.right, rc.bottom);
725 if (es->PaintBkgd)
726 FillWindow(GetParent(hwnd), hwnd, hdc, CTLCOLOR_EDIT);
728 for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
730 if (y < es->wlines - es->wtop)
731 EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
734 EndPaint(hwnd, &ps);
738 /*********************************************************************
739 * EDIT_GetTextLine
741 * Get a copy of the text in the specified line.
744 HANDLE EDIT_GetTextLine(HWND hwnd, int selection)
746 char *line;
747 HANDLE hLine;
748 int len = 0;
749 char *cp, *cp1;
751 dprintf_edit(stddeb,"GetTextLine %d\n", selection);
752 cp = cp1 = EDIT_TextLine(hwnd, selection);
753 /* advance through line */
754 while (*cp && *cp != '\r')
756 len++;
757 cp++;
760 /* store selected line and return handle */
761 hLine = EDIT_HeapAlloc(hwnd, len + 6);
762 line = (char *)EDIT_HeapAddr(hwnd, hLine);
763 memmove(line, cp1, len);
764 line[len] = '\0';
765 return hLine;
769 /*********************************************************************
770 * EDIT_TextLine
772 * Return a pointer to the text in the specified line.
775 char *EDIT_TextLine(HWND hwnd, int sel)
777 WND *wndPtr = WIN_FindWndPtr(hwnd);
778 EDITSTATE *es =
779 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
780 char *text = EDIT_HeapAddr(hwnd, es->hText);
781 unsigned int *textPtrs =
782 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
784 if(sel>es->wlines)return NULL;
785 return (text + *(textPtrs + sel));
789 /*********************************************************************
790 * EDIT_StrLength
792 * Return length of string _str_ of length _len_ characters in pixels.
793 * The current column offset in pixels _pcol_ is required to calculate
794 * the width of a tab.
797 int EDIT_StrLength(HWND hwnd, unsigned char *str, int len, int pcol)
799 int i, plen = 0;
801 for (i = 0; i < len; i++)
802 plen += EDIT_CharWidth(hwnd, (BYTE)(*(str + i)), pcol + plen);
804 dprintf_edit(stddeb,"EDIT_StrLength: returning %d\n", plen);
805 return plen;
809 /*********************************************************************
810 * EDIT_LineLength
812 * Return length of line _num_ in characters.
815 int EDIT_LineLength(HWND hwnd, int num)
817 char *cp = EDIT_TextLine(hwnd, num);
818 char *cp1;
820 if(!cp)return 0;
821 cp1 = strchr(cp, '\r');
822 return cp1 ? (int)(cp1 - cp) : strlen(cp);
826 /*********************************************************************
827 * EDIT_WriteTextLine
829 * Write the line of text at offset _y_ in text buffer to a window.
832 void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
834 int len = 0;
835 HANDLE hLine;
836 unsigned char *lp;
837 int lnlen, lnlen1;
838 int col, off = 0;
839 int sbl, sel, sbc, sec;
840 RECT rc;
841 WND *wndPtr = WIN_FindWndPtr(hwnd);
842 EDITSTATE *es =
843 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
845 /* initialize rectangle if NULL, else copy */
846 if (rect)
847 CopyRect(&rc, rect);
848 else
849 GetClientRect(hwnd, &rc);
851 dprintf_edit(stddeb,"WriteTextLine %d\n", y);
853 /* make sure y is inside the window */
854 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
856 dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
857 return;
860 /* make sure rectangle is within window */
861 if (rc.left >= ClientWidth(wndPtr) - 1)
863 dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
864 rc.left);
865 return;
867 if (rc.right <= 0)
869 dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
870 rc.right);
871 return;
873 if (y - es->wtop < (rc.top / es->txtht) ||
874 y - es->wtop > (rc.bottom / es->txtht))
876 dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is outside window\n", y);
877 return;
880 /* get the text and length of line */
881 if ((hLine = EDIT_GetTextLine(hwnd, y)) == 0)
882 return;
883 lp = (unsigned char *)EDIT_HeapAddr(hwnd, hLine);
884 lnlen = EDIT_StrLength(hwnd, lp, strlen(lp), 0);
885 lnlen1 = lnlen;
887 /* build the line to display */
888 if (lnlen < es->wleft)
889 lnlen = 0;
890 else
891 off += es->wleft;
893 if (lnlen > rc.left)
895 off += rc.left;
896 lnlen = lnlen1 - off;
897 len = min(lnlen, rc.right - rc.left);
900 if (SelMarked(es))
902 sbl = es->SelBegLine;
903 sel = es->SelEndLine;
904 sbc = es->SelBegCol;
905 sec = es->SelEndCol;
907 /* put lowest marker first */
908 if (sbl > sel)
910 swap(&sbl, &sel);
911 swap(&sbc, &sec);
913 if (sbl == sel && sbc > sec)
914 swap(&sbc, &sec);
916 if (y < sbl || y > sel)
917 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
918 TRUE, FALSE);
919 else if (y > sbl && y < sel)
920 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
921 TRUE, TRUE);
922 else if (y == sbl)
924 col = EDIT_StrLength(hwnd, lp, sbc, 0);
925 if (col > (es->wleft + rc.left))
927 len = min(col - off, rc.right - off);
928 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
929 rc.left, &rc, FALSE, FALSE);
930 off = col;
932 if (y == sel)
934 col = EDIT_StrLength(hwnd, lp, sec, 0);
935 if (col < (es->wleft + rc.right))
937 len = min(col - off, rc.right - off);
938 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
939 off - es->wleft, &rc, FALSE, TRUE);
940 off = col;
941 len = min(lnlen - off, rc.right - off);
942 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
943 off - es->wleft, &rc, TRUE, FALSE);
945 else
947 len = min(lnlen - off, rc.right - off);
948 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
949 off - es->wleft, &rc, TRUE, TRUE);
952 else
954 len = min(lnlen - off, rc.right - off);
955 if (col < (es->wleft + rc.right))
956 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
957 off - es->wleft, &rc, TRUE, TRUE);
960 else if (y == sel)
962 col = EDIT_StrLength(hwnd, lp, sec, 0);
963 if (col < (es->wleft + rc.right))
965 len = min(col - off, rc.right - off);
966 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
967 off - es->wleft, &rc, FALSE, TRUE);
968 off = col;
969 len = min(lnlen - off, rc.right - off);
970 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
971 off - es->wleft, &rc, TRUE, FALSE);
975 else
976 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
977 TRUE, FALSE);
979 EDIT_HeapFree(hwnd, hLine);
983 /*********************************************************************
984 * EDIT_WriteText
986 * Write text to a window
987 * lp - text line
988 * off - offset in text line (in pixels)
989 * len - length from off (in pixels)
990 * row - line in window
991 * col - column in window
992 * rc - rectangle in which to display line
993 * blank - blank remainder of line?
994 * reverse - reverse color of line?
997 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
998 int col, RECT *rc, BOOL blank, BOOL reverse)
1000 HDC hdc;
1001 HANDLE hStr;
1002 char *str, *cp, *cp1;
1003 int diff=0, num_spaces, tabwidth, scol;
1004 HRGN hrgnClip;
1005 COLORREF oldTextColor, oldBkgdColor;
1006 HFONT oldfont;
1007 WND *wndPtr = WIN_FindWndPtr(hwnd);
1008 EDITSTATE *es =
1009 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1010 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
1011 char *blanks = (char *)EDIT_HeapAddr(hwnd, es->hBlankLine);
1013 dprintf_edit(stddeb,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
1015 if( off < 0 ) {
1016 len += off;
1017 col -= off;
1018 off = 0;
1021 hdc = GetDC(hwnd);
1022 hStr = EDIT_GetStr(hwnd, lp, off, len, &diff);
1023 str = (char *)EDIT_HeapAddr(hwnd, hStr);
1024 hrgnClip = CreateRectRgnIndirect(rc);
1025 SelectClipRgn(hdc, hrgnClip);
1027 if (es->hFont)
1028 oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
1030 SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
1031 MAKELPARAM(hwnd, CTLCOLOR_EDIT));
1033 if (reverse)
1035 oldBkgdColor = GetBkColor(hdc);
1036 oldTextColor = GetTextColor(hdc);
1037 SetBkColor(hdc, oldTextColor);
1038 SetTextColor(hdc, oldBkgdColor);
1041 if (strlen(blanks) < (ClientWidth(wndPtr) / charWidths[32]) + 2)
1043 es->hBlankLine = EDIT_HeapReAlloc(hwnd, es->hBlankLine,
1044 (ClientWidth(wndPtr) / charWidths[32]) + 2);
1045 blanks = EDIT_HeapAddr(hwnd, es->hBlankLine);
1046 memset(blanks, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
1049 if (!(cp = strchr(str, VK_TAB)))
1050 TextOut(hdc, col - diff, row * es->txtht, str, strlen(str));
1051 else
1053 TextOut(hdc, col - diff, row * es->txtht, str, (int)(cp - str));
1054 scol = EDIT_StrLength(hwnd, str, (int)(cp - str), 0);
1055 tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
1056 num_spaces = tabwidth / charWidths[32] + 1;
1057 TextOut(hdc, scol, row * es->txtht, blanks, num_spaces);
1058 cp++;
1059 scol += tabwidth;
1061 while ((cp1 = strchr(cp, VK_TAB)))
1063 TextOut(hdc, scol, row * es->txtht, cp, (int)(cp1 - cp));
1064 scol += EDIT_StrLength(hwnd, cp, (int)(cp1 - cp), scol);
1065 tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
1066 num_spaces = tabwidth / charWidths[32] + 1;
1067 TextOut(hdc, scol, row * es->txtht, blanks, num_spaces);
1068 cp = ++cp1;
1069 scol += tabwidth;
1072 TextOut(hdc, scol, row * es->txtht, cp, strlen(cp));
1075 if (reverse)
1077 SetBkColor(hdc, oldBkgdColor);
1078 SetTextColor(hdc, oldTextColor);
1081 /* blank out remainder of line if appropriate */
1082 if (blank)
1084 if ((rc->right - col) > len)
1086 num_spaces = (rc->right - col - len) / charWidths[32];
1087 TextOut(hdc, col + len, row * es->txtht, blanks, num_spaces);
1091 if (es->hFont)
1092 SelectObject(hdc, (HANDLE)oldfont);
1094 EDIT_HeapFree(hwnd, hStr);
1095 ReleaseDC(hwnd, hdc);
1099 /*********************************************************************
1100 * EDIT_GetStr
1102 * Return sub-string starting at pixel _off_ of length _len_ pixels.
1103 * If _off_ is part way through a character, the negative offset of
1104 * the beginning of the character is returned in _diff_, else _diff_
1105 * will be zero.
1108 HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff)
1110 HANDLE hStr;
1111 char *str;
1112 int ch = 0, i = 0, j, s_i=0;
1113 int ch1;
1115 dprintf_edit(stddeb,"EDIT_GetStr lp='%s' off=%d len=%d\n", lp, off, len);
1117 if (off < 0) off = 0;
1118 while (i < off)
1120 s_i = i;
1121 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
1122 ch++;
1124 /* if stepped past _off_, go back a character */
1125 if (i - off)
1127 i = s_i;
1128 ch--;
1130 *diff = off - i;
1131 ch1 = ch;
1132 while (i < len + off)
1134 if (*(lp + ch) == '\r' || *(lp + ch) == '\n')
1135 break;
1136 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
1137 ch++;
1140 hStr = EDIT_HeapAlloc(hwnd, ch - ch1 + 3);
1141 str = (char *)EDIT_HeapAddr(hwnd, hStr);
1142 for (i = ch1, j = 0; i < ch; i++, j++)
1143 str[j] = lp[i];
1144 str[++j] = '\0';
1145 dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str);
1146 return hStr;
1150 /*********************************************************************
1151 * WM_CHAR message function
1154 void EDIT_CharMsg(HWND hwnd, WORD wParam)
1156 WND *wndPtr = WIN_FindWndPtr(hwnd);
1158 dprintf_edit(stddeb,"EDIT_CharMsg: wParam=%c\n", (char)wParam);
1160 switch (wParam)
1162 case '\r':
1163 case '\n':
1164 if (!IsMultiLine())
1165 break;
1166 wParam = '\n';
1167 EDIT_KeyTyped(hwnd, wParam);
1168 break;
1170 case VK_TAB:
1171 if (!IsMultiLine())
1172 break;
1173 EDIT_KeyTyped(hwnd, wParam);
1174 break;
1176 default:
1177 if (wParam >= 20 && wParam <= 254 && wParam != 127 )
1178 EDIT_KeyTyped(hwnd, wParam);
1179 break;
1184 /*********************************************************************
1185 * EDIT_KeyTyped
1187 * Process keystrokes that produce displayable characters.
1190 void EDIT_KeyTyped(HWND hwnd, short ch)
1192 WND *wndPtr = WIN_FindWndPtr(hwnd);
1193 EDITSTATE *es =
1194 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1195 char *text = EDIT_HeapAddr(hwnd, es->hText);
1196 char *currchar = CurrChar;
1197 RECT rc;
1198 BOOL FullPaint = FALSE;
1200 dprintf_edit(stddeb,"EDIT_KeyTyped: ch=%c\n", (char)ch);
1202 /* delete selected text (if any) */
1203 if (SelMarked(es))
1204 EDIT_DeleteSel(hwnd);
1206 /* test for typing at end of maximum buffer size */
1207 if (currchar == text + es->MaxTextLen)
1209 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1210 return;
1213 if (*currchar == '\0' && IsMultiLine())
1215 /* insert a newline at end of text */
1216 *currchar = '\r';
1217 *(currchar + 1) = '\n';
1218 *(currchar + 2) = '\0';
1219 EDIT_BuildTextPointers(hwnd);
1222 /* insert the typed character */
1223 if (text[es->textlen - 1] != '\0')
1225 /* current text buffer is full */
1226 if (es->textlen == es->MaxTextLen)
1228 /* text buffer is at maximum size */
1229 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1230 return;
1233 /* increase the text buffer size */
1234 es->textlen += GROWLENGTH;
1235 /* but not above maximum size */
1236 if (es->textlen > es->MaxTextLen)
1237 es->textlen = es->MaxTextLen;
1238 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + 2);
1239 if (!es->hText)
1240 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1241 text = EDIT_HeapAddr(hwnd, es->hText);
1242 text[es->textlen - 1] = '\0';
1243 currchar = CurrChar;
1245 /* make space for new character and put char in buffer */
1246 if (ch == '\n')
1248 memmove(currchar + 2, currchar, strlen(currchar) + 1);
1249 *currchar = '\r';
1250 *(currchar + 1) = '\n';
1251 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 2);
1253 else
1255 memmove(currchar + 1, currchar, strlen(currchar) + 1);
1256 *currchar = ch;
1257 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
1259 es->TextChanged = TRUE;
1260 NOTIFY_PARENT(hwnd, EN_UPDATE);
1262 /* re-adjust textwidth, if necessary, and redraw line */
1263 HideCaret(hwnd);
1264 if (IsMultiLine() && es->wlines > 1)
1266 es->textwidth = max(es->textwidth,
1267 EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
1268 (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) -
1269 EDIT_TextLine(hwnd, es->CurrLine)), 0));
1271 else
1272 es->textwidth = max(es->textwidth,
1273 EDIT_StrLength(hwnd, text, strlen(text), 0));
1274 EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
1276 if (ch == '\n')
1278 if (es->wleft > 0)
1279 FullPaint = TRUE;
1280 es->wleft = 0;
1281 EDIT_BuildTextPointers(hwnd);
1282 EDIT_End(hwnd);
1283 EDIT_Forward(hwnd);
1285 /* invalidate rest of window */
1286 GetClientRect(hwnd, &rc);
1287 if (!FullPaint)
1288 rc.top = es->WndRow * es->txtht;
1289 InvalidateRect(hwnd, &rc, FALSE);
1291 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1292 ShowCaret(hwnd);
1293 UpdateWindow(hwnd);
1294 NOTIFY_PARENT(hwnd, EN_CHANGE);
1295 return;
1298 /* test end of window */
1299 if (es->WndCol >= ClientWidth(wndPtr) -
1300 EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft))
1302 /* TODO:- Word wrap to be handled here */
1304 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1305 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1307 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft);
1308 es->CurrCol++;
1309 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1310 ShowCaret(hwnd);
1311 NOTIFY_PARENT(hwnd, EN_CHANGE);
1315 /*********************************************************************
1316 * EDIT_CharWidth
1318 * Return the width of the given character in pixels.
1319 * The current column offset in pixels _pcol_ is required to calculate
1320 * the width of a tab.
1323 int EDIT_CharWidth(HWND hwnd, short ch, int pcol)
1325 WND *wndPtr = WIN_FindWndPtr(hwnd);
1326 EDITSTATE *es =
1327 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1328 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
1330 if (ch != VK_TAB)
1331 return (charWidths[ch]);
1332 else
1333 return (EDIT_GetNextTabStop(hwnd, pcol) - pcol);
1337 /*********************************************************************
1338 * EDIT_GetNextTabStop
1340 * Return the next tab stop beyond _pcol_.
1343 int EDIT_GetNextTabStop(HWND hwnd, int pcol)
1345 int i;
1346 int baseUnitWidth = LOWORD(GetDialogBaseUnits());
1347 WND *wndPtr = WIN_FindWndPtr(hwnd);
1348 EDITSTATE *es =
1349 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1350 unsigned short *tabstops = EDIT_HeapAddr(hwnd, es->hTabStops);
1352 if (es->NumTabStops == 0)
1353 return ROUNDUP(pcol, 8 * baseUnitWidth);
1354 else if (es->NumTabStops == 1)
1355 return ROUNDUP(pcol, *tabstops * baseUnitWidth / 4);
1356 else
1358 for (i = 0; i < es->NumTabStops; i++)
1360 if (*(tabstops + i) * baseUnitWidth / 4 >= pcol)
1361 return (*(tabstops + i) * baseUnitWidth / 4);
1363 return pcol;
1368 /*********************************************************************
1369 * EDIT_Forward
1371 * Cursor right key: move right one character position.
1374 void EDIT_Forward(HWND hwnd)
1376 WND *wndPtr = WIN_FindWndPtr(hwnd);
1377 EDITSTATE *es =
1378 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1380 if (*CurrChar == '\0')
1381 return;
1383 if (*CurrChar == '\r')
1385 EDIT_Home(hwnd);
1386 EDIT_Downward(hwnd);
1388 else
1390 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
1391 es->CurrCol++;
1392 if (es->WndCol >= ClientWidth(wndPtr))
1393 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1399 /*********************************************************************
1400 * EDIT_Downward
1402 * Cursor down key: move down one line.
1405 void EDIT_Downward(HWND hwnd)
1407 WND *wndPtr = WIN_FindWndPtr(hwnd);
1408 EDITSTATE *es =
1409 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1411 dprintf_edit(stddeb,"EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n",
1412 es->WndRow, es->wtop, es->wlines);
1414 if (IsMultiLine() && (es->WndRow + es->wtop + 1 < es->wlines))
1416 es->CurrLine++;
1417 if (es->WndRow == ClientHeight(wndPtr, es) - 1)
1419 es->WndRow++;
1420 EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
1422 else
1423 es->WndRow++;
1424 EDIT_StickEnd(hwnd);
1429 /*********************************************************************
1430 * EDIT_Upward
1432 * Cursor up key: move up one line.
1435 void EDIT_Upward(HWND hwnd)
1437 WND *wndPtr = WIN_FindWndPtr(hwnd);
1438 EDITSTATE *es =
1439 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1441 if (IsMultiLine() && es->CurrLine != 0)
1443 --es->CurrLine;
1444 if (es->WndRow == 0)
1446 --es->WndRow;
1447 EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
1449 else
1450 --es->WndRow;
1451 EDIT_StickEnd(hwnd);
1456 /*********************************************************************
1457 * EDIT_Backward
1459 * Cursor left key: move left one character position.
1462 void EDIT_Backward(HWND hwnd)
1464 WND *wndPtr = WIN_FindWndPtr(hwnd);
1465 EDITSTATE *es =
1466 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1468 if (es->CurrCol)
1470 --es->CurrCol;
1471 if (*CurrChar == VK_TAB)
1472 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar),
1473 EDIT_StrLength(hwnd,
1474 EDIT_TextLine(hwnd, es->CurrLine),
1475 es->CurrCol, 0));
1476 else
1477 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), 0);
1478 if (es->WndCol < 0)
1479 EDIT_KeyHScroll(hwnd, SB_LINEUP);
1481 else if (IsMultiLine() && es->CurrLine != 0)
1483 EDIT_Upward(hwnd);
1484 EDIT_End(hwnd);
1489 /*********************************************************************
1490 * EDIT_End
1492 * End key: move to end of line.
1495 void EDIT_End(HWND hwnd)
1497 WND *wndPtr = WIN_FindWndPtr(hwnd);
1498 EDITSTATE *es =
1499 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1501 while (*CurrChar && *CurrChar != '\r')
1503 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
1504 es->CurrCol++;
1507 if (es->WndCol >= ClientWidth(wndPtr))
1509 es->wleft = es->WndCol - ClientWidth(wndPtr) + HSCROLLDIM;
1510 es->WndCol -= es->wleft;
1511 InvalidateRect(hwnd, NULL, FALSE);
1512 UpdateWindow(hwnd);
1517 /*********************************************************************
1518 * EDIT_Home
1520 * Home key: move to beginning of line.
1523 void EDIT_Home(HWND hwnd)
1525 WND *wndPtr = WIN_FindWndPtr(hwnd);
1526 EDITSTATE *es =
1527 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1529 es->CurrCol = es->WndCol = 0;
1530 if (es->wleft != 0)
1532 es->wleft = 0;
1533 InvalidateRect(hwnd, NULL, FALSE);
1534 UpdateWindow(hwnd);
1539 /*********************************************************************
1540 * EDIT_StickEnd
1542 * Stick the cursor to the end of the line.
1545 void EDIT_StickEnd(HWND hwnd)
1547 WND *wndPtr = WIN_FindWndPtr(hwnd);
1548 EDITSTATE *es =
1549 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1550 int len = EDIT_LineLength(hwnd, es->CurrLine);
1551 char *cp = EDIT_TextLine(hwnd, es->CurrLine);
1552 char currpel;
1554 es->CurrCol = min(len, es->CurrCol);
1555 es->WndCol = min(EDIT_StrLength(hwnd, cp, len, 0) - es->wleft, es->WndCol);
1556 currpel = EDIT_StrLength(hwnd, cp, es->CurrCol, 0);
1558 if (es->wleft > currpel)
1560 es->wleft = max(0, currpel - 20);
1561 es->WndCol = currpel - es->wleft;
1562 UpdateWindow(hwnd);
1564 else if (currpel - es->wleft >= ClientWidth(wndPtr))
1566 es->wleft = currpel - (ClientWidth(wndPtr) - 5);
1567 es->WndCol = currpel - es->wleft;
1568 UpdateWindow(hwnd);
1573 /*********************************************************************
1574 * WM_KEYDOWN message function
1577 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam)
1579 WND *wndPtr = WIN_FindWndPtr(hwnd);
1580 EDITSTATE *es =
1581 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1583 dprintf_edit(stddeb,"EDIT_KeyDownMsg: key=%x\n", wParam);
1585 HideCaret(hwnd);
1586 switch (wParam)
1588 case VK_UP:
1589 if (SelMarked(es))
1590 EDIT_ClearSel(hwnd);
1591 if (IsMultiLine())
1592 EDIT_Upward(hwnd);
1593 else
1594 EDIT_Backward(hwnd);
1595 break;
1597 case VK_DOWN:
1598 if (SelMarked(es))
1599 EDIT_ClearSel(hwnd);
1600 if (IsMultiLine())
1601 EDIT_Downward(hwnd);
1602 else
1603 EDIT_Forward(hwnd);
1604 break;
1606 case VK_RIGHT:
1607 if (SelMarked(es))
1608 EDIT_ClearSel(hwnd);
1609 EDIT_Forward(hwnd);
1610 break;
1612 case VK_LEFT:
1613 if (SelMarked(es))
1614 EDIT_ClearSel(hwnd);
1615 EDIT_Backward(hwnd);
1616 break;
1618 case VK_HOME:
1619 if (SelMarked(es))
1620 EDIT_ClearSel(hwnd);
1621 EDIT_Home(hwnd);
1622 break;
1624 case VK_END:
1625 if (SelMarked(es))
1626 EDIT_ClearSel(hwnd);
1627 EDIT_End(hwnd);
1628 break;
1630 case VK_PRIOR:
1631 if (IsMultiLine())
1633 if (SelMarked(es))
1634 EDIT_ClearSel(hwnd);
1635 EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
1637 break;
1639 case VK_NEXT:
1640 if (IsMultiLine())
1642 if (SelMarked(es))
1643 EDIT_ClearSel(hwnd);
1644 EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
1646 break;
1648 case VK_BACK:
1649 if (SelMarked(es))
1650 EDIT_DeleteSel(hwnd);
1651 else
1653 if (es->CurrCol == 0 && es->CurrLine == 0)
1654 break;
1655 EDIT_Backward(hwnd);
1656 EDIT_DelKey(hwnd);
1658 break;
1660 case VK_DELETE:
1661 if (SelMarked(es))
1662 EDIT_DeleteSel(hwnd);
1663 else
1664 EDIT_DelKey(hwnd);
1665 break;
1668 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1669 ShowCaret(hwnd);
1673 /*********************************************************************
1674 * EDIT_KeyHScroll
1676 * Scroll text horizontally using cursor keys.
1679 void EDIT_KeyHScroll(HWND hwnd, WORD opt)
1681 int hscrollpos;
1682 WND *wndPtr = WIN_FindWndPtr(hwnd);
1683 EDITSTATE *es =
1684 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1686 if (opt == SB_LINEDOWN)
1688 es->wleft += HSCROLLDIM;
1689 es->WndCol -= HSCROLLDIM;
1691 else
1693 if (es->wleft == 0)
1694 return;
1695 if (es->wleft - HSCROLLDIM < 0)
1697 es->WndCol += es->wleft;
1698 es->wleft = 0;
1700 else
1702 es->wleft -= HSCROLLDIM;
1703 es->WndCol += HSCROLLDIM;
1707 InvalidateRect(hwnd, NULL, FALSE);
1708 UpdateWindow(hwnd);
1710 if (IsHScrollBar())
1712 hscrollpos = EDIT_ComputeHScrollPos(hwnd);
1713 SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE);
1718 /*********************************************************************
1719 * EDIT_KeyVScrollLine
1721 * Scroll text vertically by one line using keyboard.
1724 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt)
1726 RECT rc;
1727 int y, vscrollpos;
1728 WND *wndPtr = WIN_FindWndPtr(hwnd);
1729 EDITSTATE *es =
1730 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1732 if (!IsMultiLine())
1733 return;
1735 if (opt == SB_LINEDOWN)
1737 /* move down one line */
1738 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1739 return;
1740 es->wtop++;
1742 else
1744 /* move up one line */
1745 if (es->wtop == 0)
1746 return;
1747 --es->wtop;
1750 if (IsWindowVisible(hwnd))
1752 /* adjust client bottom to nearest whole line */
1753 GetClientRect(hwnd, &rc);
1754 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1756 if (opt == SB_LINEUP)
1758 /* move up one line (scroll window down) */
1759 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1760 /* write top line */
1761 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1762 es->WndRow++;
1764 else
1766 /* move down one line (scroll window up) */
1767 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1768 /* write bottom line */
1769 y = (((rc.bottom - rc.top) / es->txtht) - 1);
1770 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1771 --es->WndRow;
1775 /* reset the vertical scroll bar */
1776 if (IsVScrollBar())
1778 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1779 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1784 /*********************************************************************
1785 * EDIT_KeyVScrollPage
1787 * Scroll text vertically by one page using keyboard.
1790 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
1792 int vscrollpos;
1793 WND *wndPtr = WIN_FindWndPtr(hwnd);
1794 EDITSTATE *es =
1795 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1797 if (IsMultiLine())
1799 if (opt == SB_PAGEUP)
1801 if (es->wtop)
1802 es->wtop -= ClientHeight(wndPtr, es);
1804 else
1806 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1808 es->wtop += ClientHeight(wndPtr, es);
1809 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1810 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1813 if (es->wtop < 0)
1814 es->wtop = 0;
1816 es->CurrLine = es->wtop + es->WndRow;
1817 EDIT_StickEnd(hwnd);
1818 InvalidateRect(hwnd, NULL, TRUE);
1819 UpdateWindow(hwnd);
1821 /* reset the vertical scroll bar */
1822 if (IsVScrollBar())
1824 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1825 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1831 /*********************************************************************
1832 * EDIT_KeyVScrollDoc
1834 * Scroll text to top and bottom of document using keyboard.
1837 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt)
1839 int vscrollpos;
1840 WND *wndPtr = WIN_FindWndPtr(hwnd);
1841 EDITSTATE *es =
1842 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1844 if (!IsMultiLine())
1845 return;
1847 if (opt == SB_TOP)
1848 es->wtop = es->wleft = 0;
1849 else if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1851 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1852 es->wleft = 0;
1855 es->CurrLine = es->wlines;
1856 es->WndRow = es->wlines - es->wtop;
1857 EDIT_End(hwnd);
1858 InvalidateRect(hwnd, NULL, TRUE);
1859 UpdateWindow(hwnd);
1861 /* reset the vertical scroll bar */
1862 if (IsVScrollBar())
1864 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1865 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1870 /*********************************************************************
1871 * EDIT_ComputeVScrollPos
1873 * Compute the vertical scroll bar position from the window
1874 * position and text width.
1877 int EDIT_ComputeVScrollPos(HWND hwnd)
1879 int vscrollpos;
1880 short minpos, maxpos;
1881 WND *wndPtr = WIN_FindWndPtr(hwnd);
1882 EDITSTATE *es =
1883 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1885 GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos);
1887 if (es->wlines > ClientHeight(wndPtr, es))
1888 vscrollpos = (double)(es->wtop) / (double)(es->wlines -
1889 ClientHeight(wndPtr, es)) * (maxpos - minpos);
1890 else
1891 vscrollpos = minpos;
1893 return vscrollpos;
1897 /*********************************************************************
1898 * EDIT_ComputeHScrollPos
1900 * Compute the horizontal scroll bar position from the window
1901 * position and text width.
1904 int EDIT_ComputeHScrollPos(HWND hwnd)
1906 int hscrollpos;
1907 short minpos, maxpos;
1908 WND *wndPtr = WIN_FindWndPtr(hwnd);
1909 EDITSTATE *es =
1910 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1912 GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos);
1914 if (es->textwidth > ClientWidth(wndPtr))
1915 hscrollpos = (double)(es->wleft) / (double)(es->textwidth -
1916 ClientWidth(wndPtr)) * (maxpos - minpos);
1917 else
1918 hscrollpos = minpos;
1920 return hscrollpos;
1924 /*********************************************************************
1925 * EDIT_DelKey
1927 * Delete character to right of cursor.
1930 void EDIT_DelKey(HWND hwnd)
1932 RECT rc;
1933 WND *wndPtr = WIN_FindWndPtr(hwnd);
1934 EDITSTATE *es =
1935 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1936 char *currchar = CurrChar;
1937 BOOL repaint = *currchar == '\n';
1939 if (IsMultiLine() && *currchar == '\n' && *(currchar + 1) == '\0')
1940 return;
1941 strcpy(currchar, currchar + 1);
1942 NOTIFY_PARENT(hwnd, EN_UPDATE);
1944 if (repaint)
1946 EDIT_BuildTextPointers(hwnd);
1947 GetClientRect(hwnd, &rc);
1948 rc.top = es->WndRow * es->txtht;
1949 InvalidateRect(hwnd, &rc, FALSE);
1950 UpdateWindow(hwnd);
1952 else
1954 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1);
1955 EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop);
1958 es->TextChanged = TRUE;
1959 NOTIFY_PARENT(hwnd, EN_CHANGE);
1962 /*********************************************************************
1963 * WM_VSCROLL message function
1966 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1968 WND *wndPtr = WIN_FindWndPtr(hwnd);
1969 EDITSTATE *es =
1970 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1972 if (IsMultiLine())
1974 HideCaret(hwnd);
1976 switch (wParam)
1978 case SB_LINEUP:
1979 case SB_LINEDOWN:
1980 EDIT_VScrollLine(hwnd, wParam);
1981 break;
1983 case SB_PAGEUP:
1984 case SB_PAGEDOWN:
1985 EDIT_VScrollPage(hwnd, wParam);
1986 break;
1990 SetCaretPos(es->WndCol, es->WndRow);
1991 ShowCaret(hwnd);
1995 /*********************************************************************
1996 * EDIT_VScrollLine
1998 * Scroll text vertically by one line using scrollbars.
2001 void EDIT_VScrollLine(HWND hwnd, WORD opt)
2003 RECT rc;
2004 int y;
2005 WND *wndPtr = WIN_FindWndPtr(hwnd);
2006 EDITSTATE *es =
2007 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2009 dprintf_edit(stddeb,"EDIT_VScrollLine: direction=%d\n", opt);
2011 if (opt == SB_LINEDOWN)
2013 /* move down one line */
2014 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
2015 return;
2016 es->wtop++;
2018 else
2020 /* move up one line */
2021 if (es->wtop == 0)
2022 return;
2023 --es->wtop;
2026 if (IsWindowVisible(hwnd))
2028 /* adjust client bottom to nearest whole line */
2029 GetClientRect(hwnd, &rc);
2030 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
2032 if (opt == SB_LINEUP)
2034 /* move up one line (scroll window down) */
2035 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
2036 /* write top line */
2037 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
2038 es->WndRow++;
2040 else
2042 /* move down one line (scroll window up) */
2043 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
2044 /* write bottom line */
2045 y = ((rc.bottom - rc.top / es->txtht) - 1);
2046 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
2047 --es->WndRow;
2053 /*********************************************************************
2054 * EDIT_VScrollPage
2056 * Scroll text vertically by one page using keyboard.
2059 void EDIT_VScrollPage(HWND hwnd, WORD opt)
2061 int vscrollpos;
2062 WND *wndPtr = WIN_FindWndPtr(hwnd);
2063 EDITSTATE *es =
2064 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2066 if (opt == SB_PAGEUP)
2068 if (es->wtop)
2069 es->wtop -= ClientHeight(wndPtr, es);
2071 else
2073 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
2075 es->wtop += ClientHeight(wndPtr, es);
2076 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
2077 es->wtop = es->wlines - ClientHeight(wndPtr, es);
2080 if (es->wtop < 0)
2081 es->wtop = 0;
2083 InvalidateRect(hwnd, NULL, TRUE);
2084 UpdateWindow(hwnd);
2086 /* reset the vertical scroll bar */
2087 if (IsVScrollBar())
2089 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
2090 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
2095 /*********************************************************************
2096 * WM_HSCROLL message function
2099 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
2101 WND *wndPtr = WIN_FindWndPtr(hwnd);
2102 EDITSTATE *es =
2103 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2105 switch (wParam)
2107 case SB_LINEUP:
2108 case SB_LINEDOWN:
2109 HideCaret(hwnd);
2111 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2112 ShowCaret(hwnd);
2113 break;
2118 /*********************************************************************
2119 * WM_SIZE message function
2122 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam)
2124 WND *wndPtr = WIN_FindWndPtr(hwnd);
2125 EDITSTATE *es =
2126 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2128 if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return;
2130 InvalidateRect(hwnd, NULL, TRUE);
2131 es->PaintBkgd = TRUE;
2132 UpdateWindow(hwnd);
2136 /*********************************************************************
2137 * WM_LBUTTONDOWN message function
2140 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam)
2142 char *cp;
2143 int len;
2144 BOOL end = FALSE;
2145 WND *wndPtr = WIN_FindWndPtr(hwnd);
2146 EDITSTATE *es =
2147 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2149 if (SelMarked(es))
2150 EDIT_ClearSel(hwnd);
2152 es->WndRow = HIWORD(lParam) / es->txtht;
2153 if (es->WndRow > es->wlines - es->wtop - 1)
2155 if (es->wlines)
2156 es->WndRow = es->wlines - es->wtop - 1;
2157 else
2158 es->WndRow = 0;
2159 end = TRUE;
2161 es->CurrLine = es->wtop + es->WndRow;
2163 cp = EDIT_TextLine(hwnd, es->CurrLine);
2164 len = EDIT_LineLength(hwnd, es->CurrLine);
2165 es->WndCol = LOWORD(lParam);
2166 if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
2167 es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
2168 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2170 ButtonDown = TRUE;
2171 ButtonRow = es->CurrLine;
2172 ButtonCol = es->CurrCol;
2176 /*********************************************************************
2177 * WM_MOUSEMOVE message function
2180 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
2182 if (wParam != MK_LBUTTON)
2183 return;
2185 if (ButtonDown)
2187 EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
2188 TextMarking = TRUE;
2189 ButtonDown = FALSE;
2192 if (TextMarking)
2193 EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
2197 /*********************************************************************
2198 * EDIT_PixelToChar
2200 * Convert a pixel offset in the given row to a character offset,
2201 * adjusting the pixel offset to the nearest whole character if
2202 * necessary.
2205 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
2207 int ch = 0, i = 0, s_i = 0;
2208 char *text;
2210 dprintf_edit(stddeb,"EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
2212 text = EDIT_TextLine(hwnd, row);
2213 while (i < *pixel)
2215 s_i = i;
2216 i += EDIT_CharWidth(hwnd, (BYTE)(*(text + ch)), i);
2217 ch++;
2220 /* if stepped past _pixel_, go back a character */
2221 if (i - *pixel)
2223 i = s_i;
2224 --ch;
2226 *pixel = i;
2227 return ch;
2231 /*********************************************************************
2232 * WM_SETTEXT message function
2235 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam)
2237 int len;
2238 char *text;
2239 WND *wndPtr = WIN_FindWndPtr(hwnd);
2240 EDITSTATE *es =
2241 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2243 if (strlen((char *)PTR_SEG_TO_LIN(lParam)) <= es->MaxTextLen)
2245 len = ( lParam? strlen((char *)PTR_SEG_TO_LIN(lParam)) : 0 );
2246 EDIT_ClearText(hwnd);
2247 es->textlen = len;
2248 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, len + 3);
2249 text = EDIT_HeapAddr(hwnd, es->hText);
2250 if (lParam)
2251 strcpy(text, (char *)PTR_SEG_TO_LIN(lParam));
2252 text[len] = '\0';
2253 text[len + 1] = '\0';
2254 text[len + 2] = '\0';
2255 EDIT_BuildTextPointers(hwnd);
2256 InvalidateRect(hwnd, NULL, TRUE);
2257 es->PaintBkgd = TRUE;
2258 es->TextChanged = TRUE;
2259 return 0L;
2261 else
2262 return EN_ERRSPACE;
2266 /*********************************************************************
2267 * EDIT_ClearText
2269 * Clear text from text buffer.
2272 void EDIT_ClearText(HWND hwnd)
2274 WND *wndPtr = WIN_FindWndPtr(hwnd);
2275 EDITSTATE *es =
2276 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2277 unsigned int blen = EditBufLen(wndPtr) + 2;
2278 char *text;
2280 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, blen);
2281 text = EDIT_HeapAddr(hwnd, es->hText);
2282 memset(text, 0, blen);
2283 es->textlen = 0;
2284 es->wlines = 0;
2285 es->CurrLine = es->CurrCol = 0;
2286 es->WndRow = es->WndCol = 0;
2287 es->wleft = es->wtop = 0;
2288 es->textwidth = 0;
2289 es->TextChanged = FALSE;
2290 EDIT_ClearTextPointers(hwnd);
2294 /*********************************************************************
2295 * EM_SETSEL message function
2298 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
2300 int so, eo;
2301 WND *wndPtr = WIN_FindWndPtr(hwnd);
2302 EDITSTATE *es =
2303 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2305 so = LOWORD(lParam);
2306 eo = HIWORD(lParam);
2308 if (so == -1) /* if so == -1, clear selection */
2310 EDIT_ClearSel(hwnd);
2311 return;
2314 if (so == eo) /* if so == eo, set caret only */
2316 EDIT_GetLineCol(hwnd, so, &(es->CurrLine), &(es->CurrCol));
2317 es->WndRow = es->CurrLine - es->wtop;
2319 if (!wParam)
2321 if (es->WndRow < 0 || es->WndRow > ClientHeight(wndPtr, es))
2323 es->wtop = es->CurrLine;
2324 es->WndRow = 0;
2326 es->WndCol = EDIT_StrLength(hwnd,
2327 EDIT_TextLine(hwnd, es->CurrLine),
2328 es->CurrCol, 0) - es->wleft;
2329 if (es->WndCol > ClientWidth(wndPtr))
2331 es->wleft = es->WndCol;
2332 es->WndCol = 0;
2334 else if (es->WndCol < 0)
2336 es->wleft += es->WndCol;
2337 es->WndCol = 0;
2341 else /* otherwise set selection */
2343 if (so > eo)
2344 swap(&so, &eo);
2346 EDIT_GetLineCol(hwnd, so, &(es->SelBegLine), &(es->SelBegCol));
2347 EDIT_GetLineCol(hwnd, eo, &(es->SelEndLine), &(es->SelEndCol));
2348 es->CurrLine = es->SelEndLine;
2349 es->CurrCol = es->SelEndCol;
2350 es->WndRow = es->SelEndLine - es->wtop;
2352 if (!wParam) /* don't suppress scrolling of text */
2354 if (es->WndRow < 0)
2356 es->wtop = es->SelEndLine;
2357 es->WndRow = 0;
2359 else if (es->WndRow > ClientHeight(wndPtr, es))
2361 es->wtop += es->WndRow - ClientHeight(wndPtr, es);
2362 es->WndRow = ClientHeight(wndPtr, es);
2364 es->WndCol = EDIT_StrLength(hwnd,
2365 EDIT_TextLine(hwnd, es->SelEndLine),
2366 es->SelEndCol, 0) - es->wleft;
2367 if (es->WndCol > ClientWidth(wndPtr))
2369 es->wleft += es->WndCol - ClientWidth(wndPtr);
2370 es->WndCol = ClientWidth(wndPtr);
2372 else if (es->WndCol < 0)
2374 es->wleft += es->WndCol;
2375 es->WndCol = 0;
2379 InvalidateRect(hwnd, NULL, TRUE);
2380 UpdateWindow(hwnd);
2385 /*********************************************************************
2386 * EDIT_GetLineCol
2388 * Return line and column in text buffer from character offset.
2391 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
2393 int lineno;
2394 char *cp, *cp1;
2395 WND *wndPtr = WIN_FindWndPtr(hwnd);
2396 EDITSTATE *es =
2397 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2398 char *text = EDIT_HeapAddr(hwnd, es->hText);
2399 unsigned int *textPtrs =
2400 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2402 /* check for (0,0) */
2403 if (!off || !es->wlines)
2405 *line = 0;
2406 *col = 0;
2407 return;
2410 if (off > strlen(text)) off = strlen(text);
2411 cp1 = text;
2412 for (lineno = 0; lineno < es->wlines; lineno++)
2414 cp = text + *(textPtrs + lineno);
2415 if (off == (int)(cp - text))
2417 *line = lineno;
2418 *col = 0;
2419 return;
2421 if (off < (int)(cp - text))
2422 break;
2423 cp1 = cp;
2425 *line = lineno - 1;
2426 *col = off - (int)(cp1 - text);
2427 #if 0
2428 if (*(text + *col) == '\0')
2429 (*col)--;
2430 #endif
2434 /*********************************************************************
2435 * EDIT_DeleteSel
2437 * Delete the current selected text (if any)
2440 void EDIT_DeleteSel(HWND hwnd)
2442 char *bbl, *bel;
2443 int len;
2444 WND *wndPtr = WIN_FindWndPtr(hwnd);
2445 EDITSTATE *es =
2446 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2448 if (SelMarked(es))
2450 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
2451 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
2452 len = (int)(bel - bbl);
2453 EDIT_SaveDeletedText(hwnd, bbl, len, es->SelBegLine, es->SelBegCol);
2454 es->TextChanged = TRUE;
2455 strcpy(bbl, bel);
2457 es->CurrLine = es->SelBegLine;
2458 es->CurrCol = es->SelBegCol;
2459 es->WndRow = es->SelBegLine - es->wtop;
2460 if (es->WndRow < 0)
2462 es->wtop = es->SelBegLine;
2463 es->WndRow = 0;
2465 es->WndCol = EDIT_StrLength(hwnd, bbl - es->SelBegCol,
2466 es->SelBegCol, 0) - es->wleft;
2468 EDIT_BuildTextPointers(hwnd);
2469 es->PaintBkgd = TRUE;
2470 EDIT_ClearSel(hwnd);
2475 /*********************************************************************
2476 * EDIT_ClearSel
2478 * Clear the current selection.
2481 void EDIT_ClearSel(HWND hwnd)
2483 WND *wndPtr = WIN_FindWndPtr(hwnd);
2484 EDITSTATE *es =
2485 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2487 es->SelBegLine = es->SelBegCol = 0;
2488 es->SelEndLine = es->SelEndCol = 0;
2490 InvalidateRect(hwnd, NULL, TRUE);
2491 UpdateWindow(hwnd);
2495 /*********************************************************************
2496 * EDIT_TextLineNumber
2498 * Return the line number in the text buffer of the supplied
2499 * character pointer.
2502 int EDIT_TextLineNumber(HWND hwnd, char *lp)
2504 int lineno;
2505 char *cp;
2506 WND *wndPtr = WIN_FindWndPtr(hwnd);
2507 EDITSTATE *es =
2508 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2509 char *text = EDIT_HeapAddr(hwnd, es->hText);
2510 unsigned int *textPtrs =
2511 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2513 for (lineno = 0; lineno < es->wlines; lineno++)
2515 cp = text + *(textPtrs + lineno);
2516 if (cp == lp)
2517 return lineno;
2518 if (cp > lp)
2519 break;
2521 return lineno - 1;
2525 /*********************************************************************
2526 * EDIT_SetAnchor
2528 * Set down anchor for text marking.
2531 void EDIT_SetAnchor(HWND hwnd, int row, int col)
2533 BOOL sel = FALSE;
2534 WND *wndPtr = WIN_FindWndPtr(hwnd);
2535 EDITSTATE *es =
2536 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2538 if (SelMarked(es))
2539 sel = TRUE;
2540 EDIT_ClearSel(hwnd);
2541 es->SelBegLine = es->SelEndLine = row;
2542 es->SelBegCol = es->SelEndCol = col;
2543 if (sel)
2545 InvalidateRect(hwnd, NULL, FALSE);
2546 UpdateWindow(hwnd);
2551 /*********************************************************************
2552 * EDIT_ExtendSel
2554 * Extend selection to the given screen co-ordinates.
2557 void EDIT_ExtendSel(HWND hwnd, int x, int y)
2559 int bbl, bel, bbc, bec;
2560 char *cp;
2561 int len, line;
2562 BOOL end = FALSE;
2563 WND *wndPtr = WIN_FindWndPtr(hwnd);
2564 EDITSTATE *es =
2565 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2567 dprintf_edit(stddeb,"EDIT_ExtendSel: x=%d, y=%d\n", x, y);
2569 bbl = es->SelEndLine;
2570 bbc = es->SelEndCol;
2571 line = es->wtop + y / es->txtht;
2572 if (line > es->wlines)
2573 line = es->wlines;
2574 cp = EDIT_TextLine(hwnd, line);
2575 len = EDIT_LineLength(hwnd, line);
2577 es->WndRow = y / es->txtht;
2578 if (es->WndRow > es->wlines - es->wtop - 1)
2580 if (es->wlines)
2581 es->WndRow = es->wlines - es->wtop - 1;
2582 else
2583 es->WndRow = 0;
2584 end = TRUE;
2586 es->CurrLine = es->wtop + es->WndRow;
2587 es->SelEndLine = es->CurrLine;
2589 es->WndCol = x;
2590 if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
2591 es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
2592 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2593 es->SelEndCol = es->CurrCol;
2595 bel = es->SelEndLine;
2596 bec = es->SelEndCol;
2598 /* return if no new characters to mark */
2599 if (bbl == bel && bbc == bec)
2600 return;
2602 /* put lowest marker first */
2603 if (bbl > bel)
2605 swap(&bbl, &bel);
2606 swap(&bbc, &bec);
2608 if (bbl == bel && bbc > bec)
2609 swap(&bbc, &bec);
2611 for (y = bbl; y <= bel; y++)
2613 if (y == bbl && y == bel)
2614 EDIT_WriteSel(hwnd, y, bbc, bec);
2615 else if (y == bbl)
2616 EDIT_WriteSel(hwnd, y, bbc, -1);
2617 else if (y == bel)
2618 EDIT_WriteSel(hwnd, y, 0, bec);
2619 else
2620 EDIT_WriteSel(hwnd, y, 0, -1);
2625 /*********************************************************************
2626 * EDIT_WriteSel
2628 * Display selection by reversing pixels in selected text.
2629 * If end == -1, selection applies to end of line.
2632 void EDIT_WriteSel(HWND hwnd, int y, int start, int end)
2634 RECT rc;
2635 int scol, ecol;
2636 char *cp;
2637 HDC hdc;
2638 HBRUSH hbrush, holdbrush;
2639 int olddm;
2640 WND *wndPtr = WIN_FindWndPtr(hwnd);
2641 EDITSTATE *es =
2642 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2644 dprintf_edit(stddeb,"EDIT_WriteSel: y=%d start=%d end=%d\n", y, start,end);
2645 GetClientRect(hwnd, &rc);
2647 /* make sure y is within the window */
2648 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
2649 return;
2651 /* get pointer to text */
2652 cp = EDIT_TextLine(hwnd, y);
2654 /* get length of line if end == -1 */
2655 if (end == -1)
2656 end = EDIT_LineLength(hwnd, y);
2658 /* For some reason Rectangle, when called with R2_XORPEN filling,
2659 * appears to leave a 2 pixel gap between characters and between
2660 * lines. I have kludged this by adding on two pixels to ecol and
2661 * to the line height in the call to Rectangle.
2663 scol = EDIT_StrLength(hwnd, cp, start, 0);
2664 if (scol > rc.right) return;
2665 if (scol < rc.left) scol = rc.left;
2666 ecol = EDIT_StrLength(hwnd, cp, end, 0) + 2; /* ??? */
2667 if (ecol < rc.left) return;
2668 if (ecol > rc.right) ecol = rc.right;
2670 hdc = GetDC(hwnd);
2671 hbrush = GetStockObject(BLACK_BRUSH);
2672 holdbrush = (HBRUSH)SelectObject(hdc, (HANDLE)hbrush);
2673 olddm = SetROP2(hdc, R2_XORPEN);
2674 Rectangle(hdc, scol, y * es->txtht, ecol, (y + 1) * es->txtht + 2);
2675 SetROP2(hdc, olddm);
2676 SelectObject(hdc, (HANDLE)holdbrush);
2677 ReleaseDC(hwnd, hdc);
2681 /*********************************************************************
2682 * EDIT_StopMarking
2684 * Stop text marking (selection).
2687 void EDIT_StopMarking(HWND hwnd)
2689 WND *wndPtr = WIN_FindWndPtr(hwnd);
2690 EDITSTATE *es =
2691 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2693 TextMarking = FALSE;
2694 if (es->SelBegLine > es->SelEndLine)
2696 swap(&(es->SelBegLine), &(es->SelEndLine));
2697 swap(&(es->SelBegCol), &(es->SelEndCol));
2699 if (es->SelBegLine == es->SelEndLine && es->SelBegCol > es->SelEndCol)
2700 swap(&(es->SelBegCol), &(es->SelEndCol));
2704 /*********************************************************************
2705 * EM_GETLINE message function
2708 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam)
2710 char *cp, *cp1;
2711 int len;
2712 char *buffer = (char *)lParam;
2714 cp = EDIT_TextLine(hwnd, wParam);
2715 cp1 = EDIT_TextLine(hwnd, wParam + 1);
2716 len = min((int)(cp1 - cp), (WORD)(*buffer));
2717 strncpy(buffer, cp, len);
2719 return (LONG)len;
2723 /*********************************************************************
2724 * EM_GETSEL message function
2727 LONG EDIT_GetSelMsg(HWND hwnd)
2729 int so, eo;
2730 WND *wndPtr = WIN_FindWndPtr(hwnd);
2731 EDITSTATE *es =
2732 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2733 unsigned int *textPtrs =
2734 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2736 so = *(textPtrs + es->SelBegLine) + es->SelBegCol;
2737 eo = *(textPtrs + es->SelEndLine) + es->SelEndCol;
2739 return MAKELONG(so, eo);
2743 /*********************************************************************
2744 * EM_REPLACESEL message function
2747 void EDIT_ReplaceSel(HWND hwnd, LONG lParam)
2749 EDIT_DeleteSel(hwnd);
2750 EDIT_InsertText(hwnd, (char *)PTR_SEG_TO_LIN(lParam),
2751 strlen((char *)PTR_SEG_TO_LIN(lParam)));
2752 InvalidateRect(hwnd, NULL, TRUE);
2753 UpdateWindow(hwnd);
2757 /*********************************************************************
2758 * EDIT_InsertText
2760 * Insert text at current line and column.
2763 void EDIT_InsertText(HWND hwnd, char *str, int len)
2765 int plen;
2766 WND *wndPtr = WIN_FindWndPtr(hwnd);
2767 EDITSTATE *es =
2768 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2769 char *text = EDIT_HeapAddr(hwnd, es->hText);
2771 plen = strlen(text) + len;
2772 if (plen + 1 > es->textlen)
2774 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + len);
2775 es->textlen = plen + 1;
2777 memmove(CurrChar + len, CurrChar, strlen(CurrChar) + 1);
2778 memcpy(CurrChar, str, len);
2780 EDIT_BuildTextPointers(hwnd);
2781 es->PaintBkgd = TRUE;
2782 es->TextChanged = TRUE;
2784 EDIT_GetLineCol(hwnd, (int)((CurrChar + len) - text), &(es->CurrLine),
2785 &(es->CurrCol));
2786 es->WndRow = es->CurrLine - es->wtop;
2787 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2788 es->CurrCol, 0) - es->wleft;
2792 /*********************************************************************
2793 * EM_LINEFROMCHAR message function
2796 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam)
2798 int row, col;
2799 WND *wndPtr = WIN_FindWndPtr(hwnd);
2800 EDITSTATE *es =
2801 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2803 if (wParam == (WORD)-1)
2804 return (LONG)(es->SelBegLine);
2805 else
2806 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2808 return (LONG)row;
2812 /*********************************************************************
2813 * EM_LINEINDEX message function
2816 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam)
2818 WND *wndPtr = WIN_FindWndPtr(hwnd);
2819 EDITSTATE *es =
2820 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2821 unsigned int *textPtrs =
2822 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2824 if (wParam == (WORD)-1)
2825 wParam = es->CurrLine;
2827 return (LONG)(*(textPtrs + wParam));
2831 /*********************************************************************
2832 * EM_LINELENGTH message function
2835 LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam)
2837 int row, col, len;
2838 int sbl, sbc, sel, sec;
2839 WND *wndPtr = WIN_FindWndPtr(hwnd);
2840 EDITSTATE *es =
2841 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2842 unsigned int *textPtrs =
2843 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2845 if (wParam == (WORD)-1)
2847 if (SelMarked(es))
2849 sbl = es->SelBegLine;
2850 sbc = es->SelBegCol;
2851 sel = es->SelEndLine;
2852 sec = es->SelEndCol;
2854 if (sbl > sel)
2856 swap(&sbl, &sel);
2857 swap(&sbc, &sec);
2859 if (sbl == sel && sbc > sec)
2860 swap(&sbc, &sec);
2862 if (sbc == sel)
2864 len = *(textPtrs + sbl + 1) - *(textPtrs + sbl) - 1;
2865 return len - sec - sbc;
2868 len = *(textPtrs + sel + 1) - *(textPtrs + sel) - sec - 1;
2869 return len + sbc;
2871 else /* no selection marked */
2873 len = *(textPtrs + es->CurrLine + 1) -
2874 *(textPtrs + es->CurrLine) - 1;
2875 return len;
2878 else /* line number specified */
2880 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2881 len = *(textPtrs + row + 1) - *(textPtrs + row);
2882 return len;
2887 /*********************************************************************
2888 * WM_SETFONT message function
2891 void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam)
2893 HDC hdc;
2894 TEXTMETRIC tm;
2895 HFONT oldfont;
2896 WND *wndPtr = WIN_FindWndPtr(hwnd);
2897 EDITSTATE *es =
2898 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2899 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
2901 es->hFont = wParam;
2902 hdc = GetDC(hwnd);
2903 oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
2904 GetCharWidth(hdc, 0, 255, charWidths);
2905 GetTextMetrics(hdc, &tm);
2906 es->txtht = tm.tmHeight + tm.tmExternalLeading;
2907 SelectObject(hdc, (HANDLE)oldfont);
2908 ReleaseDC(hwnd, hdc);
2910 es->WndRow = (es->CurrLine - es->wtop) / es->txtht;
2911 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2912 es->CurrCol, 0) - es->wleft;
2914 InvalidateRect(hwnd, NULL, TRUE);
2915 es->PaintBkgd = TRUE;
2916 if (lParam) UpdateWindow(hwnd);
2920 /*********************************************************************
2921 * EDIT_SaveDeletedText
2923 * Save deleted text in deleted text buffer.
2926 void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len,
2927 int line, int col)
2929 char *text;
2930 WND *wndPtr = WIN_FindWndPtr(hwnd);
2931 EDITSTATE *es =
2932 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2934 es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE);
2935 if (!es->hDeletedText) return;
2936 text = (char *)GlobalLock(es->hDeletedText);
2937 memcpy(text, deltext, len);
2938 GlobalUnlock(es->hDeletedText);
2939 es->DeletedLength = len;
2940 es->DeletedCurrLine = line;
2941 es->DeletedCurrCol = col;
2945 /*********************************************************************
2946 * EDIT_ClearDeletedText
2948 * Clear deleted text buffer.
2951 void EDIT_ClearDeletedText(HWND hwnd)
2953 WND *wndPtr = WIN_FindWndPtr(hwnd);
2954 EDITSTATE *es =
2955 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2957 GlobalFree(es->hDeletedText);
2958 es->hDeletedText = 0;
2959 es->DeletedLength = 0;
2963 /*********************************************************************
2964 * EM_UNDO message function
2967 LONG EDIT_UndoMsg(HWND hwnd)
2969 char *text;
2970 WND *wndPtr = WIN_FindWndPtr(hwnd);
2971 EDITSTATE *es =
2972 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2974 if (es->hDeletedText)
2976 text = (char *)GlobalLock(es->hDeletedText);
2977 es->CurrLine = es->DeletedCurrLine;
2978 es->CurrCol = es->DeletedCurrCol;
2979 EDIT_InsertText(hwnd, text, es->DeletedLength);
2980 GlobalUnlock(es->hDeletedText);
2981 EDIT_ClearDeletedText(hwnd);
2983 es->SelBegLine = es->CurrLine;
2984 es->SelBegCol = es->CurrCol;
2985 EDIT_GetLineCol(hwnd, (int)((CurrChar + es->DeletedLength) - text),
2986 &(es->CurrLine), &(es->CurrCol));
2987 es->WndRow = es->CurrLine - es->wtop;
2988 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2989 es->CurrCol, 0) - es->wleft;
2990 es->SelEndLine = es->CurrLine;
2991 es->SelEndCol = es->CurrCol;
2993 InvalidateRect(hwnd, NULL, TRUE);
2994 UpdateWindow(hwnd);
2995 return 1;
2997 else
2998 return 0;
3002 /*********************************************************************
3003 * EDIT_HeapAlloc
3005 * Allocate the specified number of bytes on the specified local heap.
3008 unsigned int EDIT_HeapAlloc(HWND hwnd, int bytes)
3010 WND *wndPtr = WIN_FindWndPtr(hwnd);
3011 unsigned int ret;
3013 ret = LOCAL_Alloc( wndPtr->hInstance, LMEM_FIXED, bytes );
3014 if (ret == 0)
3015 printf("EDIT_HeapAlloc: Out of heap-memory\n");
3016 return ret;
3020 /*********************************************************************
3021 * EDIT_HeapAddr
3023 * Return the address of the memory pointed to by the handle.
3026 void *EDIT_HeapAddr(HWND hwnd, unsigned int handle)
3028 WND *wndPtr = WIN_FindWndPtr(hwnd);
3029 return handle ? PTR_SEG_OFF_TO_LIN( wndPtr->hInstance, handle ) : 0;
3033 /*********************************************************************
3034 * EDIT_HeapReAlloc
3036 * Reallocate the memory pointed to by the handle.
3039 unsigned int EDIT_HeapReAlloc(HWND hwnd, unsigned int handle, int bytes)
3041 WND *wndPtr = WIN_FindWndPtr(hwnd);
3043 return LOCAL_ReAlloc( wndPtr->hInstance, handle, bytes, LMEM_FIXED );
3047 /*********************************************************************
3048 * EDIT_HeapFree
3050 * Frees the memory pointed to by the handle.
3053 void EDIT_HeapFree(HWND hwnd, unsigned int handle)
3055 WND *wndPtr = WIN_FindWndPtr(hwnd);
3057 LOCAL_Free( wndPtr->hInstance, handle );
3061 /*********************************************************************
3062 * EDIT_HeapSize
3064 * Return the size of the given object on the local heap.
3067 unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle)
3069 WND *wndPtr = WIN_FindWndPtr(hwnd);
3071 #if 0
3072 return HEAP_LocalSize((MDESC **)*(LONG *)(wndPtr->wExtra + 2), handle);
3073 #endif
3074 return LOCAL_Size( wndPtr->hInstance, handle );
3078 /*********************************************************************
3079 * EM_SETHANDLE message function
3082 void EDIT_SetHandleMsg(HWND hwnd, WORD wParam)
3084 WND *wndPtr = WIN_FindWndPtr(hwnd);
3085 EDITSTATE *es =
3086 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3088 if (IsMultiLine())
3090 es->hText = wParam;
3091 es->textlen = EDIT_HeapSize(hwnd, es->hText);
3092 es->wlines = 0;
3093 es->wtop = es->wleft = 0;
3094 es->CurrLine = es->CurrCol = 0;
3095 es->WndRow = es->WndCol = 0;
3096 es->TextChanged = FALSE;
3097 es->textwidth = 0;
3098 es->SelBegLine = es->SelBegCol = 0;
3099 es->SelEndLine = es->SelEndCol = 0;
3100 dprintf_edit(stddeb, "EDIT_SetHandleMsg: textlen=%d\n",
3101 es->textlen);
3103 EDIT_BuildTextPointers(hwnd);
3104 es->PaintBkgd = TRUE;
3105 InvalidateRect(hwnd, NULL, TRUE);
3106 UpdateWindow(hwnd);
3111 /*********************************************************************
3112 * EM_SETTABSTOPS message function
3115 LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam)
3117 unsigned short *tabstops;
3118 WND *wndPtr = WIN_FindWndPtr(hwnd);
3119 EDITSTATE *es =
3120 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3122 es->NumTabStops = wParam;
3123 if (wParam == 0)
3124 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, 1);
3125 else if (wParam == 1)
3127 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, 1);
3128 tabstops = (unsigned short *)EDIT_HeapAddr(hwnd, es->hTabStops);
3129 *tabstops = (unsigned short)lParam;
3131 else
3133 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, wParam);
3134 tabstops = (unsigned short *)EDIT_HeapAddr(hwnd, es->hTabStops);
3135 memcpy(tabstops, (unsigned short *)lParam, wParam);
3137 return 0L;
3141 /*********************************************************************
3142 * EDIT_CopyToClipboard
3144 * Copy the specified text to the clipboard.
3147 void EDIT_CopyToClipboard(HWND hwnd)
3149 HANDLE hMem;
3150 char *lpMem;
3151 int i, len;
3152 char *bbl, *bel;
3153 WND *wndPtr = WIN_FindWndPtr(hwnd);
3154 EDITSTATE *es =
3155 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3157 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
3158 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
3159 len = (int)(bel - bbl);
3161 hMem = GlobalAlloc(GHND, (DWORD)(len + 1));
3162 lpMem = GlobalLock(hMem);
3164 for (i = 0; i < len; i++)
3165 *lpMem++ = *bbl++;
3167 GlobalUnlock(hMem);
3168 OpenClipboard(hwnd);
3169 EmptyClipboard();
3170 SetClipboardData(CF_TEXT, hMem);
3171 CloseClipboard();
3175 /*********************************************************************
3176 * WM_PASTE message function
3179 void EDIT_PasteMsg(HWND hwnd)
3181 HANDLE hClipMem;
3182 char *lpClipMem;
3184 OpenClipboard(hwnd);
3185 if (!(hClipMem = GetClipboardData(CF_TEXT)))
3187 /* no text in clipboard */
3188 CloseClipboard();
3189 return;
3191 lpClipMem = GlobalLock(hClipMem);
3192 EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem));
3193 GlobalUnlock(hClipMem);
3194 CloseClipboard();
3195 InvalidateRect(hwnd, NULL, TRUE);
3196 UpdateWindow(hwnd);
3200 /*********************************************************************
3201 * Utility functions
3204 void swap(int *a, int *b)
3206 int x;
3208 x = *a;
3209 *a = *b;
3210 *b = x;