4 * Copyright David W. Metcalfe, 1994
6 * Release 1, April 1994
9 static char Copyright[] = "Copyright David W. Metcalfe, 1994";
22 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
23 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
24 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
26 #define MAXTEXTLEN 32000 /* maximum text buffer length */
27 #define EDITLEN 1024 /* starting length for multi-line control */
28 #define ENTRYLEN 256 /* starting length for single line control */
29 #define GROWLENGTH 64 /* buffers grow by this much */
31 #define HSCROLLDIM (ClientWidth(wndPtr) / 3)
32 /* "line" dimension for horizontal scroll */
34 #define EDIT_HEAP_ALLOC(size) USER_HEAP_ALLOC(GMEM_MOVEABLE,size)
35 #define EDIT_HEAP_REALLOC(handle,size) USER_HEAP_REALLOC(handle,size,\
37 #define EDIT_HEAP_ADDR(handle) USER_HEAP_ADDR(handle)
38 #define EDIT_HEAP_FREE(handle) USER_HEAP_FREE(handle)
42 int wlines; /* number of lines of text */
43 int wtop; /* top line that is displayed */
44 int wleft; /* left pixel that is displayed */
45 unsigned int textlen; /* text buffer length */
46 int textwidth; /* width of longest line in pixels */
47 RECT fmtrc; /* rectangle in which to format text */
48 int txtht; /* height of text line in pixels */
49 HANDLE hText; /* handle to text buffer */
50 HANDLE hCharWidths; /* widths of chars in font */
51 HANDLE hTextPtrs; /* list of line offsets */
52 HANDLE hBlankLine; /* to fill blank lines quickly */
53 int CurrCol; /* current column */
54 int CurrLine; /* current line */
55 int WndCol; /* current window column */
56 int WndRow; /* current window row */
57 BOOL TextChanged; /* TRUE if text has changed */
58 BOOL PaintBkgd; /* paint control background */
59 unsigned int MaxTextLen; /* maximum text buffer length */
60 int SelBegLine; /* beginning line of selection */
61 int SelBegCol; /* beginning column of selection */
62 int SelEndLine; /* ending line of selection */
63 int SelEndCol; /* ending column of selection */
67 #define ClientWidth(wndPtr) (wndPtr->rectClient.right - \
68 wndPtr->rectClient.left)
69 #define ClientHeight(wndPtr, es) ((wndPtr->rectClient.bottom - \
70 wndPtr->rectClient.top) / es->txtht)
71 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
73 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
74 #define SelMarked(es) (es->SelBegLine != -1 && es->SelBegCol != -1 && \
75 es->SelEndLine != -1 && es->SelEndCol != -1)
77 /* macros to access window styles */
78 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
79 #define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
80 #define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
81 #define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
82 #define IsHScrollBar() (wndPtr->dwStyle & WS_HSCROLL)
84 /* internal variables */
85 static BOOL TextMarking; /* TRUE if text marking in progress */
86 static BOOL ButtonDown; /* TRUE if left mouse button down */
87 static int ButtonRow; /* row in text buffer when button pressed */
88 static int ButtonCol; /* col in text buffer when button pressed */
89 static BOOL Print = FALSE;
92 LONG EditWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
93 long EDIT_CreateMsg(HWND hwnd, LONG lParam);
94 void EDIT_ClearTextPointers(HWND hwnd);
95 void EDIT_BuildTextPointers(HWND hwnd);
96 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var);
97 void EDIT_PaintMsg(HWND hwnd);
98 HANDLE EDIT_GetTextLine(HWND hwnd, int selection);
99 char *EDIT_TextLine(HWND hwnd, int sel);
100 int EDIT_LineLength(EDITSTATE *es, char *str, int len);
101 void EDIT_WriteTextLine(HWND hwnd, RECT *rc, int y);
102 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
103 int col, RECT *rc, BOOL blank, BOOL reverse);
104 HANDLE EDIT_GetStr(EDITSTATE *es, char *lp, int off, int len, int *diff);
105 void EDIT_CharMsg(HWND hwnd, WORD wParam);
106 void EDIT_KeyTyped(HWND hwnd, short ch);
107 int EDIT_CharWidth(EDITSTATE *es, short ch);
108 void EDIT_Forward(HWND hwnd);
109 void EDIT_Downward(HWND hwnd);
110 void EDIT_Upward(HWND hwnd);
111 void EDIT_Backward(HWND hwnd);
112 void EDIT_End(HWND hwnd);
113 void EDIT_Home(HWND hwnd);
114 void EDIT_StickEnd(HWND hwnd);
115 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam);
116 void EDIT_KeyHScroll(HWND hwnd, WORD opt);
117 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt);
118 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt);
119 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt);
120 int EDIT_ComputeVScrollPos(HWND hwnd);
121 int EDIT_ComputeHScrollPos(HWND hwnd);
122 void EDIT_DelKey(HWND hwnd);
123 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
124 void EDIT_VScrollLine(HWND hwnd, WORD opt);
125 void EDIT_VScrollPage(HWND hwnd, WORD opt);
126 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
127 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam);
128 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam);
129 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam);
130 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel);
131 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam);
132 void EDIT_ClearText(HWND hwnd);
133 void EDIT_SetSelMsg(HWND hwnd, LONG lParam);
134 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col);
135 void EDIT_DeleteSel(HWND hwnd);
136 void EDIT_ClearSel(HWND hwnd);
137 int EDIT_TextLineNumber(HWND hwnd, char *lp);
138 void EDIT_SetAnchor(HWND hwnd, int row, int col);
139 void EDIT_ExtendSel(HWND hwnd, int x, int y);
140 void EDIT_StopMarking(HWND hwnd);
141 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
142 LONG EDIT_GetSelMsg(HWND hwnd);
143 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam);
144 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam);
145 void swap(int *a, int *b);
148 LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
154 WND *wndPtr = WIN_FindWndPtr(hwnd);
155 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
159 /* cannot process undo message */
164 printf("edit: cannot process EM_FMTLINES message\n");
168 case EM_GETFIRSTVISIBLELINE:
173 printf("edit: cannot process EM_GETHANDLE message\n");
178 lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
183 case EM_GETLINECOUNT:
185 lResult = es->wlines;
191 lResult = es->TextChanged;
194 case EM_GETPASSWORDCHAR:
195 printf("edit: cannot process EM_GETPASSWORDCHAR message\n");
199 GetWindowRect(hwnd, (LPRECT)lParam);
203 lResult = EDIT_GetSelMsg(hwnd);
206 case EM_GETWORDBREAKPROC:
207 printf("edit: cannot process EM_GETWORDBREAKPROC message\n");
211 es->MaxTextLen = wParam;
214 case EM_LINEFROMCHAR:
215 lResult = EDIT_LineFromCharMsg(hwnd, wParam);
220 lResult = EDIT_LineIndexMsg(hwnd, wParam);
226 printf("edit: cannot process EM_LINELENGTH message\n");
230 printf("edit: cannot process EM_LINESCROLL message\n");
234 printf("edit: cannot process EM_REPLACESEL message\n");
238 printf("edit: cannot process EM_SETHANDLE message\n");
242 es->TextChanged = wParam;
245 case EM_SETPASSWORDCHAR:
246 printf("edit: cannot process EM_SETPASSWORDCHAR message\n");
250 printf("edit: cannot process EM_SETREADONLY message\n");
255 printf("edit: cannot process EM_SETRECT(NP) message\n");
260 EDIT_SetSelMsg(hwnd, lParam);
261 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
266 printf("edit: cannot process EM_SETTABSTOPS message\n");
269 case EM_SETWORDBREAKPROC:
270 printf("edit: cannot process EM_SETWORDBREAKPROC message\n");
274 EDIT_CharMsg(hwnd, wParam);
278 lResult = EDIT_CreateMsg(hwnd, lParam);
282 EDIT_HEAP_FREE(es->hTextPtrs);
283 EDIT_HEAP_FREE(es->hCharWidths);
284 EDIT_HEAP_FREE((HANDLE)(*(wndPtr->wExtra)));
288 InvalidateRect(hwnd, NULL, FALSE);
292 textPtr = (LPSTR)EDIT_HEAP_ADDR(es->hText);
293 if ((int)wParam > (len = strlen(textPtr)))
295 strcpy((char *)lParam, textPtr);
296 lResult = (DWORD)len;
302 case WM_GETTEXTLENGTH:
303 textPtr = (LPSTR)EDIT_HEAP_ADDR(es->hText);
304 lResult = (DWORD)strlen(textPtr);
308 EDIT_HScrollMsg(hwnd, wParam, lParam);
312 printf("EDIT WM_KEYDOWN w=%04X !\n", wParam);
313 EDIT_KeyDownMsg(hwnd, wParam);
318 NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
324 EDIT_LButtonDownMsg(hwnd, wParam, lParam);
325 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
332 EDIT_StopMarking(hwnd);
337 EDIT_MouseMoveMsg(hwnd, wParam, lParam);
338 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
351 es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
352 CreateCaret(hwnd, 0, 2, es->txtht);
353 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
355 NOTIFY_PARENT(hwnd, EN_SETFOCUS);
362 EDIT_SetTextMsg(hwnd, lParam);
366 EDIT_SizeMsg(hwnd, wParam, lParam);
371 EDIT_VScrollMsg(hwnd, wParam, lParam);
375 lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
384 /*********************************************************************
385 * WM_CREATE message function
388 long EDIT_CreateMsg(HWND hwnd, LONG lParam)
391 WND *wndPtr = WIN_FindWndPtr(hwnd);
397 unsigned int *textPtrs;
399 /* allocate space for state variable structure */
400 (HANDLE)(*(wndPtr->wExtra)) =
401 EDIT_HEAP_ALLOC(sizeof(EDITSTATE));
402 es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
403 es->hTextPtrs = EDIT_HEAP_ALLOC(sizeof(int));
404 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
405 es->hCharWidths = EDIT_HEAP_ALLOC(256 * sizeof(short));
407 /* initialize state variable structure */
408 /* --- char width array */
410 charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
411 memset(charWidths, 0, 256 * sizeof(short));
412 GetCharWidth(hdc, 0, 255, charWidths);
414 /* --- text buffer */
415 es->MaxTextLen = MAXTEXTLEN + 1;
416 if (!(wndPtr->hText))
418 es->textlen = EditBufLen(wndPtr);
419 es->hText = EDIT_HEAP_ALLOC(EditBufLen(wndPtr) + 2);
420 text = (LPSTR)EDIT_HEAP_ADDR(es->hText);
421 memset(text, 0, es->textlen + 2);
422 EDIT_ClearTextPointers(hwnd);
426 es->hText = wndPtr->hText;
428 es->textlen = GetWindowTextLength(hwnd) + 1;
429 EDIT_BuildTextPointers(hwnd);
432 /* --- other structure variables */
433 GetTextMetrics(hdc, &tm);
434 es->txtht = tm.tmHeight + tm.tmExternalLeading;
436 es->wtop = es->wleft = 0;
437 es->CurrCol = es->CurrLine = 0;
438 es->WndCol = es->WndRow = 0;
439 es->TextChanged = FALSE;
441 es->SelBegLine = es->SelBegCol = -1;
442 es->SelEndLine = es->SelEndCol = -1;
444 /* allocate space for a line full of blanks to speed up */
446 es->hBlankLine = EDIT_HEAP_ALLOC((ClientWidth(wndPtr) /
447 charWidths[32]) + 2);
448 text = EDIT_HEAP_ADDR(es->hBlankLine);
449 memset(text, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
451 /* set up text cursor for edit class */
452 CLASS_FindClassByName("EDIT", &classPtr);
453 classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);
455 /* paint background on first WM_PAINT */
456 es->PaintBkgd = TRUE;
458 ReleaseDC(hwnd, hdc);
463 /*********************************************************************
464 * EDIT_ClearTextPointers
466 * Clear and initialize text line pointer array.
469 void EDIT_ClearTextPointers(HWND hwnd)
471 unsigned int *textPtrs;
472 WND *wndPtr = WIN_FindWndPtr(hwnd);
473 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
475 es->hTextPtrs = EDIT_HEAP_REALLOC(es->hTextPtrs, sizeof(int));
476 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
481 /*********************************************************************
482 * EDIT_BuildTextPointers
484 * Build array of pointers to text lines.
487 #define INITLINES 100
489 void EDIT_BuildTextPointers(HWND hwnd)
491 WND *wndPtr = WIN_FindWndPtr(hwnd);
493 int incrs = INITLINES;
494 unsigned int off, len, temp;
496 unsigned int *textPtrs;
499 es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
500 text = (char *)EDIT_HEAP_ADDR(es->hText);
501 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
502 charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
504 es->textwidth = es->wlines = 0;
507 /* advance through text buffer */
510 /* increase size of text pointer array */
511 if (incrs == INITLINES)
514 es->hTextPtrs = EDIT_HEAP_REALLOC(es->hTextPtrs,
515 (es->wlines + INITLINES) * sizeof(int));
516 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
518 off = (unsigned int)(cp - text); /* offset of beginning of line */
519 *(textPtrs + es->wlines) = off;
524 /* advance through current line */
525 while (*cp && *cp != '\n')
527 len += charWidths[*cp]; /* width of line in pixels */
530 es->textwidth = max(es->textwidth, len);
532 cp++; /* skip '\n' */
534 off = (unsigned int)(cp - text); /* offset of beginning of line */
535 *(textPtrs + es->wlines) = off;
539 /*********************************************************************
540 * EDIT_ModTextPointers
542 * Modify text pointers from a specified position.
545 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
547 WND *wndPtr = WIN_FindWndPtr(hwnd);
548 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
549 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
551 while (lineno < es->wlines)
552 *(textPtrs + lineno++) += var;
556 /*********************************************************************
557 * WM_PAINT message function
560 void EDIT_PaintMsg(HWND hwnd)
566 WND *wndPtr = WIN_FindWndPtr(hwnd);
567 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
569 hdc = BeginPaint(hwnd, &ps);
573 printf("WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc.left, rc.top,
574 rc.right, rc.bottom);
578 FillWindow(GetParent(hwnd), hwnd, hdc, CTLCOLOR_EDIT);
580 for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
582 if (y < es->wlines - es->wtop)
583 EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
590 /*********************************************************************
593 * Get a copy of the text in the specified line.
596 HANDLE EDIT_GetTextLine(HWND hwnd, int selection)
604 printf("GetTextLine %d\n", selection);
606 cp = cp1 = EDIT_TextLine(hwnd, selection);
607 /* advance through line */
608 while (*cp && *cp != '\n')
614 /* store selected line and return handle */
615 hLine = EDIT_HEAP_ALLOC(len + 6);
616 line = (char *)EDIT_HEAP_ADDR(hLine);
617 memmove(line, cp1, len);
623 /*********************************************************************
626 * Return a pointer to the text in the specified line.
629 char *EDIT_TextLine(HWND hwnd, int sel)
631 WND *wndPtr = WIN_FindWndPtr(hwnd);
632 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
633 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
634 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
636 return (text + *(textPtrs + sel));
640 /*********************************************************************
643 * Return length of line _str_ of length _len_ characters in pixels.
646 int EDIT_LineLength(EDITSTATE *es, char *str, int len)
649 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
651 for (i = 0; i < len; i++)
652 plen += charWidths[*(str + i)];
655 printf("EDIT_LineLength: returning %d\n", plen);
661 /*********************************************************************
664 * Write the line of text at offset _y_ in text buffer to a window.
667 void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
670 unsigned char line[200];
675 int sbl, sel, sbc, sec;
679 WND *wndPtr = WIN_FindWndPtr(hwnd);
680 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
682 /* initialize rectangle if NULL, else copy */
686 GetClientRect(hwnd, &rc);
689 printf("WriteTextLine %d\n", y);
692 /* make sure y is inside the window */
693 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
696 printf("EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
701 /* make sure rectangle is within window */
702 if (rc.left >= ClientWidth(wndPtr) - 1)
705 printf("EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
713 printf("EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
718 if (y - es->wtop < (rc.top / es->txtht) ||
719 y - es->wtop > (rc.bottom / es->txtht))
722 printf("EDIT_WriteTextLine: y (%d) is outside window\n", y);
727 /* get the text and length of line */
728 if ((hLine = EDIT_GetTextLine(hwnd, y)) == 0)
730 lp = (unsigned char *)EDIT_HEAP_ADDR(hLine);
731 lnlen = EDIT_LineLength(es, lp, strlen(lp));
734 /* build the line to display */
735 if (lnlen < es->wleft)
743 lnlen = lnlen1 - off;
744 len = min(lnlen, rc.right - rc.left);
749 sbl = es->SelBegLine;
750 sel = es->SelEndLine;
754 /* put lowest marker first */
760 if (sbl == sel && sbc > sec)
763 if (y < sbl || y > sel)
764 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
766 else if (y > sbl && y < sel)
767 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
771 col = EDIT_LineLength(es, lp, sbc);
772 if (col > (es->wleft + rc.left))
774 len = min(col - off, rc.right - off);
775 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
776 rc.left, &rc, FALSE, FALSE);
781 col = EDIT_LineLength(es, lp, sec);
782 if (col < (es->wleft + rc.right))
784 len = min(col - off, rc.right - off);
785 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
786 off - es->wleft, &rc, FALSE, TRUE);
788 len = min(lnlen - off, rc.right - off);
789 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
790 off - es->wleft, &rc, TRUE, FALSE);
794 len = min(lnlen - off, rc.right - off);
795 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
796 off - es->wleft, &rc, TRUE, TRUE);
801 len = min(lnlen - off, rc.right - off);
802 if (col < (es->wleft + rc.right))
803 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
804 off - es->wleft, &rc, TRUE, TRUE);
809 col = EDIT_LineLength(es, lp, sec);
810 if (col < (es->wleft + rc.right))
812 len = min(col - off, rc.right - off);
813 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
814 off - es->wleft, &rc, FALSE, TRUE);
816 len = min(lnlen - off, rc.right - off);
817 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
818 off - es->wleft, &rc, TRUE, FALSE);
823 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
826 EDIT_HEAP_FREE(hLine);
830 /*********************************************************************
833 * Write text to a window
835 * off - offset in text line (in pixels)
836 * len - length from off (in pixels)
837 * row - line in window
838 * col - column in window
839 * rc - rectangle in which to display line
840 * blank - blank remainder of line?
841 * reverse - reverse color of line?
844 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
845 int col, RECT *rc, BOOL blank, BOOL reverse)
850 int diff, num_spaces;
852 COLORREF oldTextColor, oldBkgdColor;
853 WND *wndPtr = WIN_FindWndPtr(hwnd);
854 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
855 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
858 printf("EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
862 hStr = EDIT_GetStr(es, lp, off, len, &diff);
863 str = (char *)EDIT_HEAP_ADDR(hStr);
864 hrgnClip = CreateRectRgnIndirect(rc);
865 SelectClipRgn(hdc, hrgnClip);
867 SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
868 MAKELPARAM(hwnd, CTLCOLOR_EDIT));
872 oldBkgdColor = GetBkColor(hdc);
873 oldTextColor = GetTextColor(hdc);
874 SetBkColor(hdc, oldTextColor);
875 SetTextColor(hdc, oldBkgdColor);
878 TextOut(hdc, col - diff, row * es->txtht, str, strlen(str));
882 SetBkColor(hdc, oldBkgdColor);
883 SetTextColor(hdc, oldTextColor);
886 /* blank out remainder of line if appropriate */
889 if ((rc->right - col) > len)
891 blanks = EDIT_HEAP_ADDR(es->hBlankLine);
892 num_spaces = (rc->right - col - len) / charWidths[32];
893 TextOut(hdc, col + len, row * es->txtht, blanks, num_spaces);
897 EDIT_HEAP_FREE(hStr);
898 ReleaseDC(hwnd, hdc);
902 /*********************************************************************
905 * Return sub-string starting at pixel _off_ of length _len_ pixels.
906 * If _off_ is part way through a character, the negative offset of
907 * the beginning of the character is returned in _diff_, else _diff_
911 HANDLE EDIT_GetStr(EDITSTATE *es, char *lp, int off, int len, int *diff)
915 int ch = 0, i = 0, j, tmp;
917 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
920 printf("EDIT_GetStr %s %d %d\n", lp, off, len);
925 i += charWidths[*(lp + ch)];
929 /* if stepped past _off_, go back a character */
931 i -= charWidths[*(lp + --ch)];
935 while (i < len + off)
937 i += charWidths[*(lp + ch)];
941 hStr = EDIT_HEAP_ALLOC(ch - ch1 + 3);
942 str = (char *)EDIT_HEAP_ADDR(hStr);
943 for (i = ch1, j = 0; i < ch; i++, j++)
947 printf("EDIT_GetStr: returning %s\n", str);
953 /*********************************************************************
954 * WM_CHAR message function
957 void EDIT_CharMsg(HWND hwnd, WORD wParam)
959 WND *wndPtr = WIN_FindWndPtr(hwnd);
960 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
963 printf("EDIT_CharMsg: wParam=%c\n", (char)wParam);
973 EDIT_KeyTyped(hwnd, wParam);
977 if (wParam >= 20 && wParam <= 126)
978 EDIT_KeyTyped(hwnd, wParam);
984 /*********************************************************************
987 * Process keystrokes that produce displayable characters.
990 void EDIT_KeyTyped(HWND hwnd, short ch)
992 WND *wndPtr = WIN_FindWndPtr(hwnd);
993 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
994 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
995 char *currchar = CurrChar;
997 BOOL FullPaint = FALSE;
1000 printf("EDIT_KeyTyped: ch=%c\n", (char)ch);
1003 /* delete selected text (if any) */
1005 EDIT_DeleteSel(hwnd);
1007 /* test for typing at end of maximum buffer size */
1008 if (currchar == text + es->MaxTextLen)
1010 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1014 if (*currchar == '\0')
1016 /* insert a newline at end of text */
1018 *(currchar + 1) = '\0';
1019 EDIT_BuildTextPointers(hwnd);
1022 /* insert the typed character */
1023 if (text[es->textlen - 1] != '\0')
1025 /* current text buffer is full */
1026 if (es->textlen == es->MaxTextLen)
1028 /* text buffer is at maximum size */
1029 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1033 /* increase the text buffer size */
1034 es->textlen += GROWLENGTH;
1035 /* but not above maximum size */
1036 if (es->textlen > es->MaxTextLen)
1037 es->textlen = es->MaxTextLen;
1038 es->hText = EDIT_HEAP_REALLOC(es->hText, es->textlen + 2);
1040 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1041 text = (char *)EDIT_HEAP_ADDR(es->hText);
1042 text[es->textlen - 1] = '\0';
1043 currchar = CurrChar;
1045 /* make space for new character and put char in buffer */
1046 memmove(currchar + 1, currchar, strlen(currchar) + 1);
1048 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
1049 es->TextChanged = TRUE;
1050 NOTIFY_PARENT(hwnd, EN_UPDATE);
1052 /* re-adjust textwidth, if necessary, and redraw line */
1054 if (IsMultiLine() && es->wlines > 1)
1056 es->textwidth = max(es->textwidth,
1057 EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine),
1058 (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) -
1059 EDIT_TextLine(hwnd, es->CurrLine))));
1062 es->textwidth = max(es->textwidth,
1063 EDIT_LineLength(es, text, strlen(text)));
1064 EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
1071 EDIT_BuildTextPointers(hwnd);
1075 /* invalidate rest of window */
1076 GetClientRect(hwnd, &rc);
1078 rc.top = es->WndRow * es->txtht;
1079 InvalidateRect(hwnd, &rc, FALSE);
1081 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1084 NOTIFY_PARENT(hwnd, EN_CHANGE);
1088 /* test end of window */
1089 if (es->WndCol >= ClientWidth(wndPtr) - EDIT_CharWidth(es, ch))
1091 /* TODO:- Word wrap to be handled here */
1093 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1094 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1096 es->WndCol += EDIT_CharWidth(es, ch);
1098 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1100 NOTIFY_PARENT(hwnd, EN_CHANGE);
1104 /*********************************************************************
1107 * Return the width of the given character in pixels.
1110 int EDIT_CharWidth(EDITSTATE *es, short ch)
1112 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
1114 return (charWidths[ch]);
1118 /*********************************************************************
1121 * Cursor right key: move right one character position.
1124 void EDIT_Forward(HWND hwnd)
1126 WND *wndPtr = WIN_FindWndPtr(hwnd);
1127 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1128 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
1129 char *cc = CurrChar + 1;
1134 if (*CurrChar == '\n')
1137 EDIT_Downward(hwnd);
1141 es->WndCol += EDIT_CharWidth(es, *CurrChar);
1143 if (es->WndCol >= ClientWidth(wndPtr))
1144 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1150 /*********************************************************************
1153 * Cursor down key: move down one line.
1156 void EDIT_Downward(HWND hwnd)
1158 WND *wndPtr = WIN_FindWndPtr(hwnd);
1159 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1162 printf("EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n", es->WndRow, es->wtop, es->wlines);
1165 if (IsMultiLine() && (es->WndRow + es->wtop + 1 < es->wlines))
1168 if (es->WndRow == ClientHeight(wndPtr, es) - 1)
1171 EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
1175 EDIT_StickEnd(hwnd);
1180 /*********************************************************************
1183 * Cursor up key: move up one line.
1186 void EDIT_Upward(HWND hwnd)
1188 WND *wndPtr = WIN_FindWndPtr(hwnd);
1189 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1191 if (IsMultiLine() && es->CurrLine != 0)
1194 if (es->WndRow == 0)
1197 EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
1201 EDIT_StickEnd(hwnd);
1206 /*********************************************************************
1209 * Cursor left key: move left one character position.
1212 void EDIT_Backward(HWND hwnd)
1214 WND *wndPtr = WIN_FindWndPtr(hwnd);
1215 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1216 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
1221 es->WndCol -= EDIT_CharWidth(es, *CurrChar);
1223 EDIT_KeyHScroll(hwnd, SB_LINEUP);
1225 else if (IsMultiLine() && es->CurrLine != 0)
1233 /*********************************************************************
1236 * End key: move to end of line.
1239 void EDIT_End(HWND hwnd)
1242 WND *wndPtr = WIN_FindWndPtr(hwnd);
1243 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1244 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
1246 while (*CurrChar && *CurrChar != '\n')
1248 es->WndCol += EDIT_CharWidth(es, *CurrChar);
1252 if (es->WndCol >= ClientWidth(wndPtr))
1254 es->wleft = es->WndCol - ClientWidth(wndPtr) + HSCROLLDIM;
1255 es->WndCol -= es->wleft;
1256 InvalidateRect(hwnd, NULL, FALSE);
1262 /*********************************************************************
1265 * Home key: move to beginning of line.
1268 void EDIT_Home(HWND hwnd)
1271 WND *wndPtr = WIN_FindWndPtr(hwnd);
1272 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1274 es->CurrCol = es->WndCol = 0;
1278 InvalidateRect(hwnd, NULL, FALSE);
1284 /*********************************************************************
1287 * Stick the cursor to the end of the line.
1290 void EDIT_StickEnd(HWND hwnd)
1292 WND *wndPtr = WIN_FindWndPtr(hwnd);
1293 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1296 char *cp = EDIT_TextLine(hwnd, es->CurrLine);
1297 char *cp1 = strchr(cp, '\n');
1298 int len = cp1 ? (int)(cp1 - cp) : 0;
1300 es->CurrCol = min(len, es->CurrCol);
1301 es->WndCol = min(EDIT_LineLength(es, cp, len) - es->wleft, es->WndCol);
1302 currpel = EDIT_LineLength(es, cp, es->CurrCol);
1304 if (es->wleft > currpel)
1306 es->wleft = max(0, currpel - 20);
1307 es->WndCol = currpel - es->wleft;
1310 else if (currpel - es->wleft >= ClientWidth(wndPtr))
1312 es->wleft = currpel - (ClientWidth(wndPtr) - 5);
1313 es->WndCol = currpel - es->wleft;
1319 /*********************************************************************
1320 * WM_KEYDOWN message function
1323 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam)
1325 WND *wndPtr = WIN_FindWndPtr(hwnd);
1326 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1329 printf("EDIT_KeyDownMsg: key=%x\n", wParam);
1337 EDIT_ClearSel(hwnd);
1341 EDIT_Backward(hwnd);
1346 EDIT_ClearSel(hwnd);
1348 EDIT_Downward(hwnd);
1355 EDIT_ClearSel(hwnd);
1361 EDIT_ClearSel(hwnd);
1362 EDIT_Backward(hwnd);
1367 EDIT_ClearSel(hwnd);
1373 EDIT_ClearSel(hwnd);
1381 EDIT_ClearSel(hwnd);
1382 EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
1390 EDIT_ClearSel(hwnd);
1391 EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
1397 EDIT_DeleteSel(hwnd);
1400 if (es->CurrCol == 0 && es->CurrLine == 0)
1402 EDIT_Backward(hwnd);
1409 EDIT_DeleteSel(hwnd);
1415 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1420 /*********************************************************************
1423 * Scroll text horizontally using cursor keys.
1426 void EDIT_KeyHScroll(HWND hwnd, WORD opt)
1430 WND *wndPtr = WIN_FindWndPtr(hwnd);
1431 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1433 if (opt == SB_LINEDOWN)
1435 es->wleft += HSCROLLDIM;
1436 es->WndCol -= HSCROLLDIM;
1442 if (es->wleft - HSCROLLDIM < 0)
1444 es->WndCol += es->wleft;
1449 es->wleft -= HSCROLLDIM;
1450 es->WndCol += HSCROLLDIM;
1454 InvalidateRect(hwnd, NULL, FALSE);
1459 hscrollpos = EDIT_ComputeHScrollPos(hwnd);
1460 SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE);
1465 /*********************************************************************
1466 * EDIT_KeyVScrollLine
1468 * Scroll text vertically by one line using keyboard.
1471 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt)
1475 WND *wndPtr = WIN_FindWndPtr(hwnd);
1476 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1481 if (opt == SB_LINEDOWN)
1483 /* move down one line */
1484 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1490 /* move up one line */
1496 if (IsWindowVisible(hwnd))
1498 /* adjust client bottom to nearest whole line */
1499 GetClientRect(hwnd, &rc);
1500 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1502 if (opt == SB_LINEUP)
1504 /* move up one line (scroll window down) */
1505 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1506 /* write top line */
1507 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1512 /* move down one line (scroll window up) */
1513 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1514 /* write bottom line */
1515 y = (((rc.bottom - rc.top) / es->txtht) - 1);
1516 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1521 /* reset the vertical scroll bar */
1524 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1525 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1530 /*********************************************************************
1531 * EDIT_KeyVScrollPage
1533 * Scroll text vertically by one page using keyboard.
1536 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
1540 WND *wndPtr = WIN_FindWndPtr(hwnd);
1541 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1545 if (opt == SB_PAGEUP)
1548 es->wtop -= ClientHeight(wndPtr, es);
1552 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1554 es->wtop += ClientHeight(wndPtr, es);
1555 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1556 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1562 es->CurrLine = es->wtop + es->WndRow;
1563 EDIT_StickEnd(hwnd);
1564 InvalidateRect(hwnd, NULL, TRUE);
1567 /* reset the vertical scroll bar */
1570 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1571 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1577 /*********************************************************************
1578 * EDIT_KeyVScrollDoc
1580 * Scroll text to top and bottom of document using keyboard.
1583 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt)
1587 WND *wndPtr = WIN_FindWndPtr(hwnd);
1588 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1594 es->wtop = es->wleft = 0;
1595 else if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1597 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1601 es->CurrLine = es->wlines;
1602 es->WndRow = es->wlines - es->wtop;
1604 InvalidateRect(hwnd, NULL, TRUE);
1607 /* reset the vertical scroll bar */
1610 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1611 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1616 /*********************************************************************
1617 * EDIT_ComputeVScrollPos
1619 * Compute the vertical scroll bar position from the window
1620 * position and text width.
1623 int EDIT_ComputeVScrollPos(HWND hwnd)
1626 short minpos, maxpos;
1627 WND *wndPtr = WIN_FindWndPtr(hwnd);
1628 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1630 GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos);
1632 if (es->wlines > ClientHeight(wndPtr, es))
1633 vscrollpos = (double)(es->wtop) / (double)(es->wlines -
1634 ClientHeight(wndPtr, es)) * (maxpos - minpos);
1636 vscrollpos = minpos;
1642 /*********************************************************************
1643 * EDIT_ComputeHScrollPos
1645 * Compute the horizontal scroll bar position from the window
1646 * position and text width.
1649 int EDIT_ComputeHScrollPos(HWND hwnd)
1652 short minpos, maxpos;
1653 WND *wndPtr = WIN_FindWndPtr(hwnd);
1654 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1656 GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos);
1658 if (es->textwidth > ClientWidth(wndPtr))
1659 hscrollpos = (double)(es->wleft) / (double)(es->textwidth -
1660 ClientWidth(wndPtr)) * (maxpos - minpos);
1662 hscrollpos = minpos;
1668 /*********************************************************************
1671 * Delete character to right of cursor.
1674 void EDIT_DelKey(HWND hwnd)
1677 WND *wndPtr = WIN_FindWndPtr(hwnd);
1678 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1679 char *currchar = CurrChar;
1680 BOOL repaint = *currchar == '\n';
1682 if (IsMultiLine() && *currchar == '\n' && *(currchar + 1) == '\0')
1684 strcpy(currchar, currchar + 1);
1685 NOTIFY_PARENT(hwnd, EN_UPDATE);
1689 EDIT_BuildTextPointers(hwnd);
1690 GetClientRect(hwnd, &rc);
1691 rc.top = es->WndRow * es->txtht;
1692 InvalidateRect(hwnd, &rc, FALSE);
1697 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1);
1698 EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop);
1701 es->TextChanged = TRUE;
1702 NOTIFY_PARENT(hwnd, EN_CHANGE);
1705 /*********************************************************************
1706 * WM_VSCROLL message function
1709 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1711 WND *wndPtr = WIN_FindWndPtr(hwnd);
1712 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1722 EDIT_VScrollLine(hwnd, wParam);
1727 EDIT_VScrollPage(hwnd, wParam);
1732 SetCaretPos(es->WndCol, es->WndRow);
1737 /*********************************************************************
1740 * Scroll text vertically by one line using scrollbars.
1743 void EDIT_VScrollLine(HWND hwnd, WORD opt)
1747 WND *wndPtr = WIN_FindWndPtr(hwnd);
1748 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1751 printf("EDIT_VScrollLine: direction=%d\n", opt);
1754 if (opt == SB_LINEDOWN)
1756 /* move down one line */
1757 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1760 printf("Scroll line down: wtop=%d\n", es->wtop);
1764 /* move up one line */
1768 printf("Scroll line up: wtop=%d\n", es->wtop);
1771 if (IsWindowVisible(hwnd))
1773 /* adjust client bottom to nearest whole line */
1774 GetClientRect(hwnd, &rc);
1775 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1777 if (opt == SB_LINEUP)
1779 /* move up one line (scroll window down) */
1780 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1781 /* write top line */
1782 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1787 /* move down one line (scroll window up) */
1788 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1789 /* write bottom line */
1790 y = ((rc.bottom - rc.top / es->txtht) - 1);
1791 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1798 /*********************************************************************
1801 * Scroll text vertically by one page using keyboard.
1804 void EDIT_VScrollPage(HWND hwnd, WORD opt)
1808 WND *wndPtr = WIN_FindWndPtr(hwnd);
1809 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1811 if (opt == SB_PAGEUP)
1814 es->wtop -= ClientHeight(wndPtr, es);
1818 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1820 es->wtop += ClientHeight(wndPtr, es);
1821 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1822 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1828 InvalidateRect(hwnd, NULL, TRUE);
1831 /* reset the vertical scroll bar */
1834 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1835 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1840 /*********************************************************************
1841 * WM_HSCROLL message function
1844 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1846 WND *wndPtr = WIN_FindWndPtr(hwnd);
1847 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1855 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1862 /*********************************************************************
1863 * WM_SIZE message function
1866 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam)
1869 WND *wndPtr = WIN_FindWndPtr(hwnd);
1870 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1872 if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return;
1874 InvalidateRect(hwnd, NULL, TRUE);
1875 es->PaintBkgd = TRUE;
1880 /*********************************************************************
1881 * WM_LBUTTONDOWN message function
1884 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam)
1889 WND *wndPtr = WIN_FindWndPtr(hwnd);
1890 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1893 EDIT_ClearSel(hwnd);
1895 es->WndRow = HIWORD(lParam) / es->txtht;
1896 if (es->WndRow > es->wlines - es->wtop - 1)
1899 es->WndRow = es->wlines - es->wtop - 1;
1904 es->CurrLine = es->wtop + es->WndRow;
1906 cp = EDIT_TextLine(hwnd, es->CurrLine);
1907 cp1 = strchr(cp, '\n');
1908 len = cp1 ? (int)(cp1 - cp) : 0;
1910 es->WndCol = LOWORD(lParam);
1911 if (es->WndCol > EDIT_LineLength(es, cp, len) - es->wleft || end)
1912 es->WndCol = EDIT_LineLength(es, cp, len) - es->wleft;
1913 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
1916 ButtonRow = es->CurrLine;
1917 ButtonCol = es->CurrCol;
1921 /*********************************************************************
1922 * WM_MOUSEMOVE message function
1925 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
1927 if (wParam != MK_LBUTTON)
1932 EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
1938 EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
1942 /*********************************************************************
1945 * Convert a pixel offset in the given row to a character offset,
1946 * adjusting the pixel offset to the nearest whole character if
1950 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
1954 WND *wndPtr = WIN_FindWndPtr(hwnd);
1955 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1956 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
1959 printf("EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
1962 text = EDIT_TextLine(hwnd, row);
1965 i += charWidths[*(text + ch)];
1969 /* if stepped past _pixel_, go back a character */
1971 i -= charWidths[*(text + ch)];
1977 /*********************************************************************
1978 * WM_SETTEXT message function
1981 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam)
1986 WND *wndPtr = WIN_FindWndPtr(hwnd);
1987 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1989 if (strlen((char *)lParam) <= es->MaxTextLen)
1991 len = strlen((char *)lParam);
1992 EDIT_ClearText(hwnd);
1994 es->hText = EDIT_HEAP_REALLOC(es->hText, len + 3);
1995 text = EDIT_HEAP_ADDR(es->hText);
1996 strcpy(text, (char *)lParam);
1998 text[len + 1] = '\0';
1999 text[len + 2] = '\0';
2000 EDIT_BuildTextPointers(hwnd);
2001 InvalidateRect(hwnd, NULL, TRUE);
2002 es->PaintBkgd = TRUE;
2003 es->TextChanged = TRUE;
2011 /*********************************************************************
2014 * Clear text from text buffer.
2017 void EDIT_ClearText(HWND hwnd)
2019 WND *wndPtr = WIN_FindWndPtr(hwnd);
2020 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2021 unsigned int blen = EditBufLen(wndPtr) + 2;
2024 es->hText = EDIT_HEAP_REALLOC(es->hText, blen);
2025 text = EDIT_HEAP_ADDR(es->hText);
2026 memset(text, 0, blen);
2029 es->CurrLine = es->CurrCol = 0;
2030 es->WndRow = es->WndCol = 0;
2031 es->wleft = es->wtop = 0;
2033 es->TextChanged = FALSE;
2034 EDIT_ClearTextPointers(hwnd);
2038 /*********************************************************************
2039 * EM_SETSEL message function
2042 void EDIT_SetSelMsg(HWND hwnd, LONG lParam)
2045 WND *wndPtr = WIN_FindWndPtr(hwnd);
2046 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2048 so = LOWORD(lParam);
2049 eo = HIWORD(lParam);
2053 EDIT_GetLineCol(hwnd, so, &(es->SelBegLine), &(es->SelBegCol));
2054 EDIT_GetLineCol(hwnd, eo, &(es->SelEndLine), &(es->SelEndCol));
2056 es->CurrLine = es->SelEndLine;
2057 es->CurrCol = es->SelEndCol;
2058 es->WndRow = es->SelEndLine - es->wtop;
2061 es->wtop = es->SelEndLine;
2064 es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->SelEndLine),
2065 es->SelEndCol) - es->wleft;
2067 InvalidateRect(hwnd, NULL, TRUE);
2072 /*********************************************************************
2075 * Return line and column in text buffer from character offset.
2078 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
2082 WND *wndPtr = WIN_FindWndPtr(hwnd);
2083 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2084 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
2085 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2087 if (off > strlen(text)) off = strlen(text);
2088 for (lineno = 0; lineno < es->wlines; lineno++)
2090 cp = text + *(textPtrs + lineno);
2091 if (off == (int)(cp - text))
2097 if (off < (int)(cp - text))
2102 *col = off - (int)(cp1 - text);
2103 if (*(text + *col) == '\0')
2108 /*********************************************************************
2111 * Delete the current selected text (if any)
2114 void EDIT_DeleteSel(HWND hwnd)
2118 WND *wndPtr = WIN_FindWndPtr(hwnd);
2119 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2120 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
2124 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
2125 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
2126 len = (int)(bel - bbl);
2127 es->TextChanged = TRUE;
2130 es->CurrLine = es->SelBegLine;
2131 es->CurrCol = es->SelBegCol;
2132 es->WndRow = es->SelBegLine - es->wtop;
2135 es->wtop = es->SelBegLine;
2138 es->WndCol = EDIT_LineLength(es, bbl - es->SelBegCol,
2139 es->SelBegCol) - es->wleft;
2141 EDIT_BuildTextPointers(hwnd);
2142 es->PaintBkgd = TRUE;
2143 EDIT_ClearSel(hwnd);
2148 /*********************************************************************
2151 * Clear the current selection.
2154 void EDIT_ClearSel(HWND hwnd)
2156 WND *wndPtr = WIN_FindWndPtr(hwnd);
2157 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2159 es->SelBegLine = es->SelBegCol = -1;
2160 es->SelEndLine = es->SelEndCol = -1;
2162 InvalidateRect(hwnd, NULL, TRUE);
2167 /*********************************************************************
2168 * EDIT_TextLineNumber
2170 * Return the line number in the text buffer of the supplied
2171 * character pointer.
2174 int EDIT_TextLineNumber(HWND hwnd, char *lp)
2178 WND *wndPtr = WIN_FindWndPtr(hwnd);
2179 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2180 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
2181 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2183 for (lineno = 0; lineno < es->wlines; lineno++)
2185 cp = text + *(textPtrs + lineno);
2195 /*********************************************************************
2198 * Set down anchor for text marking.
2201 void EDIT_SetAnchor(HWND hwnd, int row, int col)
2203 WND *wndPtr = WIN_FindWndPtr(hwnd);
2204 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2206 EDIT_ClearSel(hwnd);
2207 es->SelBegLine = es->SelEndLine = row;
2208 es->SelBegCol = es->SelEndCol = col;
2209 InvalidateRect(hwnd, NULL, FALSE);
2214 /*********************************************************************
2217 * Extend selection to the given screen co-ordinates.
2220 void EDIT_ExtendSel(HWND hwnd, int x, int y)
2227 WND *wndPtr = WIN_FindWndPtr(hwnd);
2228 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2231 printf("EDIT_ExtendSel: x=%d, y=%d\n", x, y);
2234 ptop = min(es->SelBegLine, es->SelEndLine);
2235 pbot = max(es->SelBegLine, es->SelEndLine);
2236 cp = EDIT_TextLine(hwnd, es->wtop + y / es->txtht);
2237 cp1 = strchr(cp, '\n');
2238 len = cp1 ? (int)(cp1 - cp) : 0;
2240 es->WndRow = y / es->txtht;
2241 if (es->WndRow > es->wlines - es->wtop - 1)
2244 es->WndRow = es->wlines - es->wtop - 1;
2249 es->CurrLine = es->wtop + es->WndRow;
2250 es->SelEndLine = es->CurrLine;
2253 if (es->WndCol > EDIT_LineLength(es, cp, len) - es->wleft || end)
2254 es->WndCol = EDIT_LineLength(es, cp, len) - es->wleft;
2255 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2256 es->SelEndCol = es->CurrCol;
2258 bbl = min(es->SelBegLine, es->SelEndLine);
2259 bel = max(es->SelBegLine, es->SelEndLine);
2262 EDIT_WriteTextLine(hwnd, NULL, ptop);
2265 for (y = bbl; y <= bel; y++)
2266 EDIT_WriteTextLine(hwnd, NULL, y);
2269 EDIT_WriteTextLine(hwnd, NULL, pbot);
2275 /*********************************************************************
2278 * Stop text marking (selection).
2281 void EDIT_StopMarking(HWND hwnd)
2283 WND *wndPtr = WIN_FindWndPtr(hwnd);
2284 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2286 TextMarking = FALSE;
2287 if (es->SelBegLine > es->SelEndLine)
2289 swap(&(es->SelBegLine), &(es->SelEndLine));
2290 swap(&(es->SelBegCol), &(es->SelEndCol));
2292 if (es->SelBegLine == es->SelEndLine && es->SelBegCol > es->SelEndCol)
2293 swap(&(es->SelBegCol), &(es->SelEndCol));
2297 /*********************************************************************
2298 * EM_GETLINE message function
2301 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam)
2305 char *buffer = (char *)lParam;
2306 WND *wndPtr = WIN_FindWndPtr(hwnd);
2307 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2309 cp = EDIT_TextLine(hwnd, wParam);
2310 cp1 = EDIT_TextLine(hwnd, wParam + 1);
2311 len = min((int)(cp1 - cp), (WORD)(*buffer));
2312 strncpy(buffer, cp, len);
2318 /*********************************************************************
2319 * EM_GETSEL message function
2322 LONG EDIT_GetSelMsg(HWND hwnd)
2325 WND *wndPtr = WIN_FindWndPtr(hwnd);
2326 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2327 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2329 so = *(textPtrs + es->SelBegLine) + es->SelBegCol;
2330 eo = *(textPtrs + es->SelEndLine) + es->SelEndCol;
2332 return MAKELONG(so, eo);
2336 /*********************************************************************
2337 * EM_LINEFROMCHAR message function
2340 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam)
2343 WND *wndPtr = WIN_FindWndPtr(hwnd);
2344 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2346 if (wParam == (WORD)-1)
2347 return (LONG)(es->SelBegLine);
2349 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2355 /*********************************************************************
2356 * EM_LINEINDEX message function
2359 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam)
2361 WND *wndPtr = WIN_FindWndPtr(hwnd);
2362 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2363 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2365 if (wParam == (WORD)-1)
2366 wParam = es->CurrLine;
2368 return (LONG)(*(textPtrs + wParam));
2372 /*********************************************************************
2376 void swap(int *a, int *b)