4 * Copyright David W. Metcalfe, 1994
6 * Release 1, April 1994
9 static char Copyright[] = "Copyright David W. Metcalfe, 1994";
18 #define DEBUG_EDIT /* */
20 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
21 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
22 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
24 #define MAXTEXTLEN 32000 /* maximum text buffer length */
25 #define EDITLEN 1024 /* starting length for multi-line control */
26 #define ENTRYLEN 256 /* starting length for single line control */
27 #define GROWLENGTH 64 /* buffers grow by this much */
29 #define HSCROLLDIM (ClientWidth(wndPtr) / 3)
30 /* "line" dimension for horizontal scroll */
32 #define EDIT_HEAP_ALLOC(size) USER_HEAP_ALLOC(GMEM_MOVEABLE,size)
33 #define EDIT_HEAP_REALLOC(handle,size) USER_HEAP_REALLOC(handle,size,\
35 #define EDIT_HEAP_ADDR(handle) USER_HEAP_ADDR(handle)
36 #define EDIT_HEAP_FREE(handle) USER_HEAP_FREE(handle)
40 int wlines; /* number of lines of text */
41 int wtop; /* top line that is displayed */
42 int wleft; /* left pixel that is displayed */
43 unsigned int textlen; /* text buffer length */
44 int textwidth; /* width of longest line in pixels */
45 RECT fmtrc; /* rectangle in which to format text */
46 int txtht; /* height of text line in pixels */
47 HANDLE hText; /* handle to text buffer */
48 HANDLE hCharWidths; /* widths of chars in font */
49 HANDLE hTextPtrs; /* list of line offsets */
50 HANDLE hBlankLine; /* to fill blank lines quickly */
51 int CurrCol; /* current column */
52 int CurrLine; /* current line */
53 int WndCol; /* current window column */
54 int WndRow; /* current window row */
55 BOOL TextChanged; /* TRUE if text has changed */
56 BOOL PaintBkgd; /* paint control background */
57 unsigned int MaxTextLen; /* maximum text buffer length */
58 int SelBegLine; /* beginning line of selection */
59 int SelBegCol; /* beginning column of selection */
60 int SelEndLine; /* ending line of selection */
61 int SelEndCol; /* ending column of selection */
65 #define ClientWidth(wndPtr) (wndPtr->rectClient.right - \
66 wndPtr->rectClient.left)
67 #define ClientHeight(wndPtr, es) ((wndPtr->rectClient.bottom - \
68 wndPtr->rectClient.top) / es->txtht)
69 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
71 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
72 #define SelMarked(es) (es->SelBegLine != -1 && es->SelBegCol != -1 && \
73 es->SelEndLine != -1 && es->SelEndCol != -1)
75 /* macros to access window styles */
76 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
77 #define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
78 #define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
79 #define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
80 #define IsHScrollBar() (wndPtr->dwStyle & WS_HSCROLL)
82 /* internal variables */
83 static BOOL TextMarking; /* TRUE if text marking in progress */
84 static BOOL ButtonDown; /* TRUE if left mouse button down */
85 static int ButtonRow; /* row in text buffer when button pressed */
86 static int ButtonCol; /* col in text buffer when button pressed */
87 static BOOL Print = FALSE;
90 LONG EditWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
91 long EDIT_CreateMsg(HWND hwnd, LONG lParam);
92 void EDIT_ClearTextPointers(HWND hwnd);
93 void EDIT_BuildTextPointers(HWND hwnd);
94 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var);
95 void EDIT_PaintMsg(HWND hwnd);
96 HANDLE EDIT_GetTextLine(HWND hwnd, int selection);
97 char *EDIT_TextLine(HWND hwnd, int sel);
98 int EDIT_LineLength(EDITSTATE *es, char *str, int len);
99 void EDIT_WriteTextLine(HWND hwnd, RECT *rc, int y);
100 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
101 int col, RECT *rc, BOOL blank, BOOL reverse);
102 HANDLE EDIT_GetStr(EDITSTATE *es, char *lp, int off, int len, int *diff);
103 void EDIT_CharMsg(HWND hwnd, WORD wParam);
104 void EDIT_KeyTyped(HWND hwnd, short ch);
105 int EDIT_CharWidth(EDITSTATE *es, short ch);
106 void EDIT_Forward(HWND hwnd);
107 void EDIT_Downward(HWND hwnd);
108 void EDIT_Upward(HWND hwnd);
109 void EDIT_Backward(HWND hwnd);
110 void EDIT_End(HWND hwnd);
111 void EDIT_Home(HWND hwnd);
112 void EDIT_StickEnd(HWND hwnd);
113 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam);
114 void EDIT_KeyHScroll(HWND hwnd, WORD opt);
115 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt);
116 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt);
117 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt);
118 int EDIT_ComputeVScrollPos(HWND hwnd);
119 int EDIT_ComputeHScrollPos(HWND hwnd);
120 void EDIT_DelKey(HWND hwnd);
121 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
122 void EDIT_VScrollLine(HWND hwnd, WORD opt);
123 void EDIT_VScrollPage(HWND hwnd, WORD opt);
124 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
125 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam);
126 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam);
127 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam);
128 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel);
129 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam);
130 void EDIT_ClearText(HWND hwnd);
131 void EDIT_SetSelMsg(HWND hwnd, LONG lParam);
132 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col);
133 void EDIT_DeleteSel(HWND hwnd);
134 void EDIT_ClearSel(HWND hwnd);
135 int EDIT_TextLineNumber(HWND hwnd, char *lp);
136 void EDIT_SetAnchor(HWND hwnd, int row, int col);
137 void EDIT_ExtendSel(HWND hwnd, int x, int y);
138 void EDIT_StopMarking(HWND hwnd);
139 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
140 LONG EDIT_GetSelMsg(HWND hwnd);
141 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam);
142 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam);
143 void swap(int *a, int *b);
146 LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
152 WND *wndPtr = WIN_FindWndPtr(hwnd);
153 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
157 /* cannot process undo message */
162 printf("edit: cannot process EM_FMTLINES message\n");
166 case EM_GETFIRSTVISIBLELINE:
171 printf("edit: cannot process EM_GETHANDLE message\n");
176 lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
181 case EM_GETLINECOUNT:
183 lResult = es->wlines;
189 lResult = es->TextChanged;
192 case EM_GETPASSWORDCHAR:
193 printf("edit: cannot process EM_GETPASSWORDCHAR message\n");
197 GetWindowRect(hwnd, (LPRECT)lParam);
201 lResult = EDIT_GetSelMsg(hwnd);
204 case EM_GETWORDBREAKPROC:
205 printf("edit: cannot process EM_GETWORDBREAKPROC message\n");
209 es->MaxTextLen = wParam;
212 case EM_LINEFROMCHAR:
213 lResult = EDIT_LineFromCharMsg(hwnd, wParam);
218 lResult = EDIT_LineIndexMsg(hwnd, wParam);
224 printf("edit: cannot process EM_LINELENGTH message\n");
228 printf("edit: cannot process EM_LINESCROLL message\n");
232 printf("edit: cannot process EM_REPLACESEL message\n");
236 printf("edit: cannot process EM_SETHANDLE message\n");
240 es->TextChanged = wParam;
243 case EM_SETPASSWORDCHAR:
244 printf("edit: cannot process EM_SETPASSWORDCHAR message\n");
248 printf("edit: cannot process EM_SETREADONLY message\n");
253 printf("edit: cannot process EM_SETRECT(NP) message\n");
258 EDIT_SetSelMsg(hwnd, lParam);
259 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
264 printf("edit: cannot process EM_SETTABSTOPS message\n");
267 case EM_SETWORDBREAKPROC:
268 printf("edit: cannot process EM_SETWORDBREAKPROC message\n");
272 EDIT_CharMsg(hwnd, wParam);
276 lResult = EDIT_CreateMsg(hwnd, lParam);
280 EDIT_HEAP_FREE(es->hTextPtrs);
281 EDIT_HEAP_FREE(es->hCharWidths);
282 EDIT_HEAP_FREE((HANDLE)(*(wndPtr->wExtra)));
286 InvalidateRect(hwnd, NULL, FALSE);
290 textPtr = (LPSTR)EDIT_HEAP_ADDR(es->hText);
291 if ((int)wParam > (len = strlen(textPtr)))
293 strcpy((char *)lParam, textPtr);
294 lResult = (DWORD)len;
300 case WM_GETTEXTLENGTH:
301 textPtr = (LPSTR)EDIT_HEAP_ADDR(es->hText);
302 lResult = (DWORD)strlen(textPtr);
306 EDIT_HScrollMsg(hwnd, wParam, lParam);
310 EDIT_KeyDownMsg(hwnd, wParam);
315 NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
321 EDIT_LButtonDownMsg(hwnd, wParam, lParam);
322 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
329 EDIT_StopMarking(hwnd);
334 EDIT_MouseMoveMsg(hwnd, wParam, lParam);
335 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
348 es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
349 CreateCaret(hwnd, 0, 2, es->txtht);
350 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
352 NOTIFY_PARENT(hwnd, EN_SETFOCUS);
359 EDIT_SetTextMsg(hwnd, lParam);
363 EDIT_SizeMsg(hwnd, wParam, lParam);
368 EDIT_VScrollMsg(hwnd, wParam, lParam);
372 lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
381 /*********************************************************************
382 * WM_CREATE message function
385 long EDIT_CreateMsg(HWND hwnd, LONG lParam)
388 WND *wndPtr = WIN_FindWndPtr(hwnd);
394 unsigned int *textPtrs;
396 /* allocate space for state variable structure */
397 (HANDLE)(*(wndPtr->wExtra)) =
398 EDIT_HEAP_ALLOC(sizeof(EDITSTATE));
399 es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
400 es->hTextPtrs = EDIT_HEAP_ALLOC(sizeof(int));
401 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
402 es->hCharWidths = EDIT_HEAP_ALLOC(256 * sizeof(short));
404 /* initialize state variable structure */
405 /* --- char width array */
407 charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
408 memset(charWidths, 0, 256 * sizeof(short));
409 GetCharWidth(hdc, 0, 255, charWidths);
411 /* --- text buffer */
412 es->MaxTextLen = MAXTEXTLEN + 1;
413 if (!(wndPtr->hText))
415 es->textlen = EditBufLen(wndPtr);
416 es->hText = EDIT_HEAP_ALLOC(EditBufLen(wndPtr) + 2);
417 text = (LPSTR)EDIT_HEAP_ADDR(es->hText);
418 memset(text, 0, es->textlen + 2);
419 EDIT_ClearTextPointers(hwnd);
423 es->hText = wndPtr->hText;
425 es->textlen = GetWindowTextLength(hwnd) + 1;
426 EDIT_BuildTextPointers(hwnd);
429 /* --- other structure variables */
430 GetTextMetrics(hdc, &tm);
431 es->txtht = tm.tmHeight + tm.tmExternalLeading;
433 es->wtop = es->wleft = 0;
434 es->CurrCol = es->CurrLine = 0;
435 es->WndCol = es->WndRow = 0;
436 es->TextChanged = FALSE;
438 es->SelBegLine = es->SelBegCol = -1;
439 es->SelEndLine = es->SelEndCol = -1;
441 /* allocate space for a line full of blanks to speed up */
443 es->hBlankLine = EDIT_HEAP_ALLOC((ClientWidth(wndPtr) /
444 charWidths[32]) + 2);
445 text = EDIT_HEAP_ADDR(es->hBlankLine);
446 memset(text, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
448 /* set up text cursor for edit class */
449 CLASS_FindClassByName("EDIT", &classPtr);
450 classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);
452 /* paint background on first WM_PAINT */
453 es->PaintBkgd = TRUE;
455 ReleaseDC(hwnd, hdc);
460 /*********************************************************************
461 * EDIT_ClearTextPointers
463 * Clear and initialize text line pointer array.
466 void EDIT_ClearTextPointers(HWND hwnd)
468 unsigned int *textPtrs;
469 WND *wndPtr = WIN_FindWndPtr(hwnd);
470 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
472 es->hTextPtrs = EDIT_HEAP_REALLOC(es->hTextPtrs, sizeof(int));
473 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
478 /*********************************************************************
479 * EDIT_BuildTextPointers
481 * Build array of pointers to text lines.
484 #define INITLINES 100
486 void EDIT_BuildTextPointers(HWND hwnd)
488 WND *wndPtr = WIN_FindWndPtr(hwnd);
490 int incrs = INITLINES;
491 unsigned int off, len, temp;
493 unsigned int *textPtrs;
496 es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
497 text = (char *)EDIT_HEAP_ADDR(es->hText);
498 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
499 charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
501 es->textwidth = es->wlines = 0;
504 /* advance through text buffer */
507 /* increase size of text pointer array */
508 if (incrs == INITLINES)
511 es->hTextPtrs = EDIT_HEAP_REALLOC(es->hTextPtrs,
512 (es->wlines + INITLINES) * sizeof(int));
513 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
515 off = (unsigned int)(cp - text); /* offset of beginning of line */
516 *(textPtrs + es->wlines) = off;
521 /* advance through current line */
522 while (*cp && *cp != '\n')
524 len += charWidths[*cp]; /* width of line in pixels */
527 es->textwidth = max(es->textwidth, len);
529 cp++; /* skip '\n' */
531 off = (unsigned int)(cp - text); /* offset of beginning of line */
532 *(textPtrs + es->wlines) = off;
536 /*********************************************************************
537 * EDIT_ModTextPointers
539 * Modify text pointers from a specified position.
542 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
544 WND *wndPtr = WIN_FindWndPtr(hwnd);
545 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
546 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
548 while (lineno < es->wlines)
549 *(textPtrs + lineno++) += var;
553 /*********************************************************************
554 * WM_PAINT message function
557 void EDIT_PaintMsg(HWND hwnd)
563 WND *wndPtr = WIN_FindWndPtr(hwnd);
564 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
566 hdc = BeginPaint(hwnd, &ps);
570 printf("WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc.left, rc.top,
571 rc.right, rc.bottom);
575 FillWindow(GetParent(hwnd), hwnd, hdc, CTLCOLOR_EDIT);
577 for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
579 if (y < es->wlines - es->wtop)
580 EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
587 /*********************************************************************
590 * Get a copy of the text in the specified line.
593 HANDLE EDIT_GetTextLine(HWND hwnd, int selection)
601 printf("GetTextLine %d\n", selection);
603 cp = cp1 = EDIT_TextLine(hwnd, selection);
604 /* advance through line */
605 while (*cp && *cp != '\n')
611 /* store selected line and return handle */
612 hLine = EDIT_HEAP_ALLOC(len + 6);
613 line = (char *)EDIT_HEAP_ADDR(hLine);
614 memmove(line, cp1, len);
620 /*********************************************************************
623 * Return a pointer to the text in the specified line.
626 char *EDIT_TextLine(HWND hwnd, int sel)
628 WND *wndPtr = WIN_FindWndPtr(hwnd);
629 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
630 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
631 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
633 return (text + *(textPtrs + sel));
637 /*********************************************************************
640 * Return length of line _str_ of length _len_ characters in pixels.
643 int EDIT_LineLength(EDITSTATE *es, char *str, int len)
646 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
648 for (i = 0; i < len; i++)
649 plen += charWidths[*(str + i)];
652 printf("EDIT_LineLength: returning %d\n", plen);
658 /*********************************************************************
661 * Write the line of text at offset _y_ in text buffer to a window.
664 void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
667 unsigned char line[200];
672 int sbl, sel, sbc, sec;
676 WND *wndPtr = WIN_FindWndPtr(hwnd);
677 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
679 /* initialize rectangle if NULL, else copy */
683 GetClientRect(hwnd, &rc);
686 printf("WriteTextLine %d\n", y);
689 /* make sure y is inside the window */
690 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
693 printf("EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
698 /* make sure rectangle is within window */
699 if (rc.left >= ClientWidth(wndPtr) - 1)
702 printf("EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
710 printf("EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
715 if (y - es->wtop < (rc.top / es->txtht) ||
716 y - es->wtop > (rc.bottom / es->txtht))
719 printf("EDIT_WriteTextLine: y (%d) is outside window\n", y);
724 /* get the text and length of line */
725 if ((hLine = EDIT_GetTextLine(hwnd, y)) == 0)
727 lp = (unsigned char *)EDIT_HEAP_ADDR(hLine);
728 lnlen = EDIT_LineLength(es, lp, strlen(lp));
731 /* build the line to display */
732 if (lnlen < es->wleft)
740 lnlen = lnlen1 - off;
741 len = min(lnlen, rc.right - rc.left);
746 sbl = es->SelBegLine;
747 sel = es->SelEndLine;
751 /* put lowest marker first */
757 if (sbl == sel && sbc > sec)
760 if (y < sbl || y > sel)
761 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
763 else if (y > sbl && y < sel)
764 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
768 col = EDIT_LineLength(es, lp, sbc);
769 if (col > (es->wleft + rc.left))
771 len = min(col - off, rc.right - off);
772 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
773 rc.left, &rc, FALSE, FALSE);
778 col = EDIT_LineLength(es, lp, sec);
779 if (col < (es->wleft + rc.right))
781 len = min(col - off, rc.right - off);
782 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
783 off - es->wleft, &rc, FALSE, TRUE);
785 len = min(lnlen - off, rc.right - off);
786 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
787 off - es->wleft, &rc, TRUE, FALSE);
791 len = min(lnlen - off, rc.right - off);
792 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
793 off - es->wleft, &rc, TRUE, TRUE);
798 len = min(lnlen - off, rc.right - off);
799 if (col < (es->wleft + rc.right))
800 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
801 off - es->wleft, &rc, TRUE, TRUE);
806 col = EDIT_LineLength(es, lp, sec);
807 if (col < (es->wleft + rc.right))
809 len = min(col - off, rc.right - off);
810 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
811 off - es->wleft, &rc, FALSE, TRUE);
813 len = min(lnlen - off, rc.right - off);
814 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
815 off - es->wleft, &rc, TRUE, FALSE);
820 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
823 EDIT_HEAP_FREE(hLine);
827 /*********************************************************************
830 * Write text to a window
832 * off - offset in text line (in pixels)
833 * len - length from off (in pixels)
834 * row - line in window
835 * col - column in window
836 * rc - rectangle in which to display line
837 * blank - blank remainder of line?
838 * reverse - reverse color of line?
841 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
842 int col, RECT *rc, BOOL blank, BOOL reverse)
847 int diff, num_spaces;
849 COLORREF oldTextColor, oldBkgdColor;
850 WND *wndPtr = WIN_FindWndPtr(hwnd);
851 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
852 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
855 printf("EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
859 hStr = EDIT_GetStr(es, lp, off, len, &diff);
860 str = (char *)EDIT_HEAP_ADDR(hStr);
861 hrgnClip = CreateRectRgnIndirect(rc);
862 SelectClipRgn(hdc, hrgnClip);
864 SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
865 MAKELPARAM(hwnd, CTLCOLOR_EDIT));
869 oldBkgdColor = GetBkColor(hdc);
870 oldTextColor = GetTextColor(hdc);
871 SetBkColor(hdc, oldTextColor);
872 SetTextColor(hdc, oldBkgdColor);
875 TextOut(hdc, col - diff, row * es->txtht, str, strlen(str));
879 SetBkColor(hdc, oldBkgdColor);
880 SetTextColor(hdc, oldTextColor);
883 /* blank out remainder of line if appropriate */
886 if ((rc->right - col) > len)
888 blanks = EDIT_HEAP_ADDR(es->hBlankLine);
889 num_spaces = (rc->right - col - len) / charWidths[32];
890 TextOut(hdc, col + len, row * es->txtht, blanks, num_spaces);
894 EDIT_HEAP_FREE(hStr);
895 ReleaseDC(hwnd, hdc);
899 /*********************************************************************
902 * Return sub-string starting at pixel _off_ of length _len_ pixels.
903 * If _off_ is part way through a character, the negative offset of
904 * the beginning of the character is returned in _diff_, else _diff_
908 HANDLE EDIT_GetStr(EDITSTATE *es, char *lp, int off, int len, int *diff)
912 int ch = 0, i = 0, j, tmp;
914 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
917 printf("EDIT_GetStr %s %d %d\n", lp, off, len);
922 i += charWidths[*(lp + ch)];
926 /* if stepped past _off_, go back a character */
928 i -= charWidths[*(lp + --ch)];
932 while (i < len + off)
934 i += charWidths[*(lp + ch)];
938 hStr = EDIT_HEAP_ALLOC(ch - ch1 + 3);
939 str = (char *)EDIT_HEAP_ADDR(hStr);
940 for (i = ch1, j = 0; i < ch; i++, j++)
944 printf("EDIT_GetStr: returning %s\n", str);
950 /*********************************************************************
951 * WM_CHAR message function
954 void EDIT_CharMsg(HWND hwnd, WORD wParam)
956 WND *wndPtr = WIN_FindWndPtr(hwnd);
957 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
960 printf("EDIT_CharMsg: wParam=%c\n", (char)wParam);
970 EDIT_KeyTyped(hwnd, wParam);
974 if (wParam >= 20 && wParam <= 126)
975 EDIT_KeyTyped(hwnd, wParam);
981 /*********************************************************************
984 * Process keystrokes that produce displayable characters.
987 void EDIT_KeyTyped(HWND hwnd, short ch)
989 WND *wndPtr = WIN_FindWndPtr(hwnd);
990 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
991 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
992 char *currchar = CurrChar;
994 BOOL FullPaint = FALSE;
997 printf("EDIT_KeyTyped: ch=%c\n", (char)ch);
1000 /* delete selected text (if any) */
1002 EDIT_DeleteSel(hwnd);
1004 /* test for typing at end of maximum buffer size */
1005 if (currchar == text + es->MaxTextLen)
1007 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1011 if (*currchar == '\0')
1013 /* insert a newline at end of text */
1015 *(currchar + 1) = '\0';
1016 EDIT_BuildTextPointers(hwnd);
1019 /* insert the typed character */
1020 if (text[es->textlen - 1] != '\0')
1022 /* current text buffer is full */
1023 if (es->textlen == es->MaxTextLen)
1025 /* text buffer is at maximum size */
1026 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1030 /* increase the text buffer size */
1031 es->textlen += GROWLENGTH;
1032 /* but not above maximum size */
1033 if (es->textlen > es->MaxTextLen)
1034 es->textlen = es->MaxTextLen;
1035 es->hText = EDIT_HEAP_REALLOC(es->hText, es->textlen + 2);
1037 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1038 text = (char *)EDIT_HEAP_ADDR(es->hText);
1039 text[es->textlen - 1] = '\0';
1040 currchar = CurrChar;
1042 /* make space for new character and put char in buffer */
1043 memmove(currchar + 1, currchar, strlen(currchar) + 1);
1045 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
1046 es->TextChanged = TRUE;
1047 NOTIFY_PARENT(hwnd, EN_UPDATE);
1049 /* re-adjust textwidth, if necessary, and redraw line */
1051 if (IsMultiLine() && es->wlines > 1)
1053 es->textwidth = max(es->textwidth,
1054 EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine),
1055 (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) -
1056 EDIT_TextLine(hwnd, es->CurrLine))));
1059 es->textwidth = max(es->textwidth,
1060 EDIT_LineLength(es, text, strlen(text)));
1061 EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
1068 EDIT_BuildTextPointers(hwnd);
1072 /* invalidate rest of window */
1073 GetClientRect(hwnd, &rc);
1075 rc.top = es->WndRow * es->txtht;
1076 InvalidateRect(hwnd, &rc, FALSE);
1078 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1081 NOTIFY_PARENT(hwnd, EN_CHANGE);
1085 /* test end of window */
1086 if (es->WndCol >= ClientWidth(wndPtr) - EDIT_CharWidth(es, ch))
1088 /* TODO:- Word wrap to be handled here */
1090 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1091 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1093 es->WndCol += EDIT_CharWidth(es, ch);
1095 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1097 NOTIFY_PARENT(hwnd, EN_CHANGE);
1101 /*********************************************************************
1104 * Return the width of the given character in pixels.
1107 int EDIT_CharWidth(EDITSTATE *es, short ch)
1109 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
1111 return (charWidths[ch]);
1115 /*********************************************************************
1118 * Cursor right key: move right one character position.
1121 void EDIT_Forward(HWND hwnd)
1123 WND *wndPtr = WIN_FindWndPtr(hwnd);
1124 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1125 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
1126 char *cc = CurrChar + 1;
1131 if (*CurrChar == '\n')
1134 EDIT_Downward(hwnd);
1138 es->WndCol += EDIT_CharWidth(es, *CurrChar);
1140 if (es->WndCol >= ClientWidth(wndPtr))
1141 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1147 /*********************************************************************
1150 * Cursor down key: move down one line.
1153 void EDIT_Downward(HWND hwnd)
1155 WND *wndPtr = WIN_FindWndPtr(hwnd);
1156 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1159 printf("EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n", es->WndRow, es->wtop, es->wlines);
1162 if (IsMultiLine() && (es->WndRow + es->wtop + 1 < es->wlines))
1165 if (es->WndRow == ClientHeight(wndPtr, es) - 1)
1168 EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
1172 EDIT_StickEnd(hwnd);
1177 /*********************************************************************
1180 * Cursor up key: move up one line.
1183 void EDIT_Upward(HWND hwnd)
1185 WND *wndPtr = WIN_FindWndPtr(hwnd);
1186 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1188 if (IsMultiLine() && es->CurrLine != 0)
1191 if (es->WndRow == 0)
1194 EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
1198 EDIT_StickEnd(hwnd);
1203 /*********************************************************************
1206 * Cursor left key: move left one character position.
1209 void EDIT_Backward(HWND hwnd)
1211 WND *wndPtr = WIN_FindWndPtr(hwnd);
1212 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1213 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
1218 es->WndCol -= EDIT_CharWidth(es, *CurrChar);
1220 EDIT_KeyHScroll(hwnd, SB_LINEUP);
1222 else if (IsMultiLine() && es->CurrLine != 0)
1230 /*********************************************************************
1233 * End key: move to end of line.
1236 void EDIT_End(HWND hwnd)
1239 WND *wndPtr = WIN_FindWndPtr(hwnd);
1240 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1241 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
1243 while (*CurrChar && *CurrChar != '\n')
1245 es->WndCol += EDIT_CharWidth(es, *CurrChar);
1249 if (es->WndCol >= ClientWidth(wndPtr))
1251 es->wleft = es->WndCol - ClientWidth(wndPtr) + HSCROLLDIM;
1252 es->WndCol -= es->wleft;
1253 InvalidateRect(hwnd, NULL, FALSE);
1259 /*********************************************************************
1262 * Home key: move to beginning of line.
1265 void EDIT_Home(HWND hwnd)
1268 WND *wndPtr = WIN_FindWndPtr(hwnd);
1269 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1271 es->CurrCol = es->WndCol = 0;
1275 InvalidateRect(hwnd, NULL, FALSE);
1281 /*********************************************************************
1284 * Stick the cursor to the end of the line.
1287 void EDIT_StickEnd(HWND hwnd)
1289 WND *wndPtr = WIN_FindWndPtr(hwnd);
1290 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1293 char *cp = EDIT_TextLine(hwnd, es->CurrLine);
1294 char *cp1 = strchr(cp, '\n');
1295 int len = cp1 ? (int)(cp1 - cp) : 0;
1297 es->CurrCol = min(len, es->CurrCol);
1298 es->WndCol = min(EDIT_LineLength(es, cp, len) - es->wleft, es->WndCol);
1299 currpel = EDIT_LineLength(es, cp, es->CurrCol);
1301 if (es->wleft > currpel)
1303 es->wleft = max(0, currpel - 20);
1304 es->WndCol = currpel - es->wleft;
1307 else if (currpel - es->wleft >= ClientWidth(wndPtr))
1309 es->wleft = currpel - (ClientWidth(wndPtr) - 5);
1310 es->WndCol = currpel - es->wleft;
1316 /*********************************************************************
1317 * WM_KEYDOWN message function
1320 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam)
1322 WND *wndPtr = WIN_FindWndPtr(hwnd);
1323 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1326 printf("EDIT_KeyDownMsg: key=%x\n", wParam);
1334 EDIT_ClearSel(hwnd);
1338 EDIT_Backward(hwnd);
1343 EDIT_ClearSel(hwnd);
1345 EDIT_Downward(hwnd);
1352 EDIT_ClearSel(hwnd);
1358 EDIT_ClearSel(hwnd);
1359 EDIT_Backward(hwnd);
1364 EDIT_ClearSel(hwnd);
1370 EDIT_ClearSel(hwnd);
1378 EDIT_ClearSel(hwnd);
1379 EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
1387 EDIT_ClearSel(hwnd);
1388 EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
1394 EDIT_DeleteSel(hwnd);
1397 if (es->CurrCol == 0 && es->CurrLine == 0)
1399 EDIT_Backward(hwnd);
1406 EDIT_DeleteSel(hwnd);
1412 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1417 /*********************************************************************
1420 * Scroll text horizontally using cursor keys.
1423 void EDIT_KeyHScroll(HWND hwnd, WORD opt)
1427 WND *wndPtr = WIN_FindWndPtr(hwnd);
1428 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1430 if (opt == SB_LINEDOWN)
1432 es->wleft += HSCROLLDIM;
1433 es->WndCol -= HSCROLLDIM;
1439 if (es->wleft - HSCROLLDIM < 0)
1441 es->WndCol += es->wleft;
1446 es->wleft -= HSCROLLDIM;
1447 es->WndCol += HSCROLLDIM;
1451 InvalidateRect(hwnd, NULL, FALSE);
1456 hscrollpos = EDIT_ComputeHScrollPos(hwnd);
1457 SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE);
1462 /*********************************************************************
1463 * EDIT_KeyVScrollLine
1465 * Scroll text vertically by one line using keyboard.
1468 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt)
1472 WND *wndPtr = WIN_FindWndPtr(hwnd);
1473 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1478 if (opt == SB_LINEDOWN)
1480 /* move down one line */
1481 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1487 /* move up one line */
1493 if (IsWindowVisible(hwnd))
1495 /* adjust client bottom to nearest whole line */
1496 GetClientRect(hwnd, &rc);
1497 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1499 if (opt == SB_LINEUP)
1501 /* move up one line (scroll window down) */
1502 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1503 /* write top line */
1504 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1509 /* move down one line (scroll window up) */
1510 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1511 /* write bottom line */
1512 y = (((rc.bottom - rc.top) / es->txtht) - 1);
1513 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1518 /* reset the vertical scroll bar */
1521 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1522 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1527 /*********************************************************************
1528 * EDIT_KeyVScrollPage
1530 * Scroll text vertically by one page using keyboard.
1533 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
1537 WND *wndPtr = WIN_FindWndPtr(hwnd);
1538 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1542 if (opt == SB_PAGEUP)
1545 es->wtop -= ClientHeight(wndPtr, es);
1549 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1551 es->wtop += ClientHeight(wndPtr, es);
1552 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1553 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1559 es->CurrLine = es->wtop + es->WndRow;
1560 EDIT_StickEnd(hwnd);
1561 InvalidateRect(hwnd, NULL, TRUE);
1564 /* reset the vertical scroll bar */
1567 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1568 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1574 /*********************************************************************
1575 * EDIT_KeyVScrollDoc
1577 * Scroll text to top and bottom of document using keyboard.
1580 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt)
1584 WND *wndPtr = WIN_FindWndPtr(hwnd);
1585 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1591 es->wtop = es->wleft = 0;
1592 else if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1594 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1598 es->CurrLine = es->wlines;
1599 es->WndRow = es->wlines - es->wtop;
1601 InvalidateRect(hwnd, NULL, TRUE);
1604 /* reset the vertical scroll bar */
1607 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1608 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1613 /*********************************************************************
1614 * EDIT_ComputeVScrollPos
1616 * Compute the vertical scroll bar position from the window
1617 * position and text width.
1620 int EDIT_ComputeVScrollPos(HWND hwnd)
1623 short minpos, maxpos;
1624 WND *wndPtr = WIN_FindWndPtr(hwnd);
1625 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1627 GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos);
1629 if (es->wlines > ClientHeight(wndPtr, es))
1630 vscrollpos = (double)(es->wtop) / (double)(es->wlines -
1631 ClientHeight(wndPtr, es)) * (maxpos - minpos);
1633 vscrollpos = minpos;
1639 /*********************************************************************
1640 * EDIT_ComputeHScrollPos
1642 * Compute the horizontal scroll bar position from the window
1643 * position and text width.
1646 int EDIT_ComputeHScrollPos(HWND hwnd)
1649 short minpos, maxpos;
1650 WND *wndPtr = WIN_FindWndPtr(hwnd);
1651 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1653 GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos);
1655 if (es->textwidth > ClientWidth(wndPtr))
1656 hscrollpos = (double)(es->wleft) / (double)(es->textwidth -
1657 ClientWidth(wndPtr)) * (maxpos - minpos);
1659 hscrollpos = minpos;
1665 /*********************************************************************
1668 * Delete character to right of cursor.
1671 void EDIT_DelKey(HWND hwnd)
1674 WND *wndPtr = WIN_FindWndPtr(hwnd);
1675 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1676 char *currchar = CurrChar;
1677 BOOL repaint = *currchar == '\n';
1679 if (IsMultiLine() && *currchar == '\n' && *(currchar + 1) == '\0')
1681 strcpy(currchar, currchar + 1);
1682 NOTIFY_PARENT(hwnd, EN_UPDATE);
1686 EDIT_BuildTextPointers(hwnd);
1687 GetClientRect(hwnd, &rc);
1688 rc.top = es->WndRow * es->txtht;
1689 InvalidateRect(hwnd, &rc, FALSE);
1694 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1);
1695 EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop);
1698 es->TextChanged = TRUE;
1699 NOTIFY_PARENT(hwnd, EN_CHANGE);
1702 /*********************************************************************
1703 * WM_VSCROLL message function
1706 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1708 WND *wndPtr = WIN_FindWndPtr(hwnd);
1709 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1719 EDIT_VScrollLine(hwnd, wParam);
1724 EDIT_VScrollPage(hwnd, wParam);
1729 SetCaretPos(es->WndCol, es->WndRow);
1734 /*********************************************************************
1737 * Scroll text vertically by one line using scrollbars.
1740 void EDIT_VScrollLine(HWND hwnd, WORD opt)
1744 WND *wndPtr = WIN_FindWndPtr(hwnd);
1745 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1748 printf("EDIT_VScrollLine: direction=%d\n", opt);
1751 if (opt == SB_LINEDOWN)
1753 /* move down one line */
1754 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1757 printf("Scroll line down: wtop=%d\n", es->wtop);
1761 /* move up one line */
1765 printf("Scroll line up: wtop=%d\n", es->wtop);
1768 if (IsWindowVisible(hwnd))
1770 /* adjust client bottom to nearest whole line */
1771 GetClientRect(hwnd, &rc);
1772 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1774 if (opt == SB_LINEUP)
1776 /* move up one line (scroll window down) */
1777 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1778 /* write top line */
1779 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1784 /* move down one line (scroll window up) */
1785 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1786 /* write bottom line */
1787 y = ((rc.bottom - rc.top / es->txtht) - 1);
1788 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1795 /*********************************************************************
1798 * Scroll text vertically by one page using keyboard.
1801 void EDIT_VScrollPage(HWND hwnd, WORD opt)
1805 WND *wndPtr = WIN_FindWndPtr(hwnd);
1806 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1808 if (opt == SB_PAGEUP)
1811 es->wtop -= ClientHeight(wndPtr, es);
1815 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1817 es->wtop += ClientHeight(wndPtr, es);
1818 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1819 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1825 InvalidateRect(hwnd, NULL, TRUE);
1828 /* reset the vertical scroll bar */
1831 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1832 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1837 /*********************************************************************
1838 * WM_HSCROLL message function
1841 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1843 WND *wndPtr = WIN_FindWndPtr(hwnd);
1844 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1852 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1859 /*********************************************************************
1860 * WM_SIZE message function
1863 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam)
1866 WND *wndPtr = WIN_FindWndPtr(hwnd);
1867 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1869 if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return;
1871 InvalidateRect(hwnd, NULL, TRUE);
1872 es->PaintBkgd = TRUE;
1877 /*********************************************************************
1878 * WM_LBUTTONDOWN message function
1881 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam)
1886 WND *wndPtr = WIN_FindWndPtr(hwnd);
1887 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1890 EDIT_ClearSel(hwnd);
1892 es->WndRow = HIWORD(lParam) / es->txtht;
1893 if (es->WndRow > es->wlines - es->wtop - 1)
1896 es->WndRow = es->wlines - es->wtop - 1;
1901 es->CurrLine = es->wtop + es->WndRow;
1903 cp = EDIT_TextLine(hwnd, es->CurrLine);
1904 cp1 = strchr(cp, '\n');
1905 len = cp1 ? (int)(cp1 - cp) : 0;
1907 es->WndCol = LOWORD(lParam);
1908 if (es->WndCol > EDIT_LineLength(es, cp, len) - es->wleft || end)
1909 es->WndCol = EDIT_LineLength(es, cp, len) - es->wleft;
1910 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
1913 ButtonRow = es->CurrLine;
1914 ButtonCol = es->CurrCol;
1918 /*********************************************************************
1919 * WM_MOUSEMOVE message function
1922 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
1924 if (wParam != MK_LBUTTON)
1929 EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
1935 EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
1939 /*********************************************************************
1942 * Convert a pixel offset in the given row to a character offset,
1943 * adjusting the pixel offset to the nearest whole character if
1947 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
1951 WND *wndPtr = WIN_FindWndPtr(hwnd);
1952 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1953 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
1956 printf("EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
1959 text = EDIT_TextLine(hwnd, row);
1962 i += charWidths[*(text + ch)];
1966 /* if stepped past _pixel_, go back a character */
1968 i -= charWidths[*(text + ch)];
1974 /*********************************************************************
1975 * WM_SETTEXT message function
1978 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam)
1983 WND *wndPtr = WIN_FindWndPtr(hwnd);
1984 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1986 if (strlen((char *)lParam) <= es->MaxTextLen)
1988 len = strlen((char *)lParam);
1989 EDIT_ClearText(hwnd);
1991 es->hText = EDIT_HEAP_REALLOC(es->hText, len + 3);
1992 text = EDIT_HEAP_ADDR(es->hText);
1993 strcpy(text, (char *)lParam);
1994 /* text[len] = '\n'; */ /* Removed by Bob Amstadt */
1995 text[len + 1] = '\0';
1996 text[len + 2] = '\0';
1997 EDIT_BuildTextPointers(hwnd);
1998 InvalidateRect(hwnd, NULL, TRUE);
1999 es->PaintBkgd = TRUE;
2000 es->TextChanged = TRUE;
2008 /*********************************************************************
2011 * Clear text from text buffer.
2014 void EDIT_ClearText(HWND hwnd)
2016 WND *wndPtr = WIN_FindWndPtr(hwnd);
2017 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2018 unsigned int blen = EditBufLen(wndPtr) + 2;
2021 es->hText = EDIT_HEAP_REALLOC(es->hText, blen);
2022 text = EDIT_HEAP_ADDR(es->hText);
2023 memset(text, 0, blen);
2026 es->CurrLine = es->CurrCol = 0;
2027 es->WndRow = es->WndCol = 0;
2028 es->wleft = es->wtop = 0;
2030 es->TextChanged = FALSE;
2031 EDIT_ClearTextPointers(hwnd);
2035 /*********************************************************************
2036 * EM_SETSEL message function
2039 void EDIT_SetSelMsg(HWND hwnd, LONG lParam)
2042 WND *wndPtr = WIN_FindWndPtr(hwnd);
2043 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2045 so = LOWORD(lParam);
2046 eo = HIWORD(lParam);
2050 EDIT_GetLineCol(hwnd, so, &(es->SelBegLine), &(es->SelBegCol));
2051 EDIT_GetLineCol(hwnd, eo, &(es->SelEndLine), &(es->SelEndCol));
2053 es->CurrLine = es->SelEndLine;
2054 es->CurrCol = es->SelEndCol;
2055 es->WndRow = es->SelEndLine - es->wtop;
2058 es->wtop = es->SelEndLine;
2061 es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->SelEndLine),
2062 es->SelEndCol) - es->wleft;
2064 InvalidateRect(hwnd, NULL, TRUE);
2069 /*********************************************************************
2072 * Return line and column in text buffer from character offset.
2075 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
2079 WND *wndPtr = WIN_FindWndPtr(hwnd);
2080 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2081 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
2082 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2084 if (off > strlen(text)) off = strlen(text);
2086 for (lineno = 0; lineno < es->wlines; lineno++)
2088 cp = text + *(textPtrs + lineno);
2089 if (off == (int)(cp - text))
2095 if (off < (int)(cp - text))
2100 *col = off - (int)(cp1 - text);
2101 if (*(text + *col) == '\0')
2106 /*********************************************************************
2109 * Delete the current selected text (if any)
2112 void EDIT_DeleteSel(HWND hwnd)
2116 WND *wndPtr = WIN_FindWndPtr(hwnd);
2117 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2118 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
2122 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
2123 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
2124 len = (int)(bel - bbl);
2125 es->TextChanged = TRUE;
2128 es->CurrLine = es->SelBegLine;
2129 es->CurrCol = es->SelBegCol;
2130 es->WndRow = es->SelBegLine - es->wtop;
2133 es->wtop = es->SelBegLine;
2136 es->WndCol = EDIT_LineLength(es, bbl - es->SelBegCol,
2137 es->SelBegCol) - es->wleft;
2139 EDIT_BuildTextPointers(hwnd);
2140 es->PaintBkgd = TRUE;
2141 EDIT_ClearSel(hwnd);
2146 /*********************************************************************
2149 * Clear the current selection.
2152 void EDIT_ClearSel(HWND hwnd)
2154 WND *wndPtr = WIN_FindWndPtr(hwnd);
2155 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2157 es->SelBegLine = es->SelBegCol = -1;
2158 es->SelEndLine = es->SelEndCol = -1;
2160 InvalidateRect(hwnd, NULL, TRUE);
2165 /*********************************************************************
2166 * EDIT_TextLineNumber
2168 * Return the line number in the text buffer of the supplied
2169 * character pointer.
2172 int EDIT_TextLineNumber(HWND hwnd, char *lp)
2176 WND *wndPtr = WIN_FindWndPtr(hwnd);
2177 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2178 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
2179 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2181 for (lineno = 0; lineno < es->wlines; lineno++)
2183 cp = text + *(textPtrs + lineno);
2193 /*********************************************************************
2196 * Set down anchor for text marking.
2199 void EDIT_SetAnchor(HWND hwnd, int row, int col)
2201 WND *wndPtr = WIN_FindWndPtr(hwnd);
2202 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2204 EDIT_ClearSel(hwnd);
2205 es->SelBegLine = es->SelEndLine = row;
2206 es->SelBegCol = es->SelEndCol = col;
2207 InvalidateRect(hwnd, NULL, FALSE);
2212 /*********************************************************************
2215 * Extend selection to the given screen co-ordinates.
2218 void EDIT_ExtendSel(HWND hwnd, int x, int y)
2225 WND *wndPtr = WIN_FindWndPtr(hwnd);
2226 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2229 printf("EDIT_ExtendSel: x=%d, y=%d\n", x, y);
2232 ptop = min(es->SelBegLine, es->SelEndLine);
2233 pbot = max(es->SelBegLine, es->SelEndLine);
2234 cp = EDIT_TextLine(hwnd, es->wtop + y / es->txtht);
2235 cp1 = strchr(cp, '\n');
2236 len = cp1 ? (int)(cp1 - cp) : 0;
2238 es->WndRow = y / es->txtht;
2239 if (es->WndRow > es->wlines - es->wtop - 1)
2242 es->WndRow = es->wlines - es->wtop - 1;
2247 es->CurrLine = es->wtop + es->WndRow;
2248 es->SelEndLine = es->CurrLine;
2251 if (es->WndCol > EDIT_LineLength(es, cp, len) - es->wleft || end)
2252 es->WndCol = EDIT_LineLength(es, cp, len) - es->wleft;
2253 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2254 es->SelEndCol = es->CurrCol;
2256 bbl = min(es->SelBegLine, es->SelEndLine);
2257 bel = max(es->SelBegLine, es->SelEndLine);
2260 EDIT_WriteTextLine(hwnd, NULL, ptop);
2263 for (y = bbl; y <= bel; y++)
2264 EDIT_WriteTextLine(hwnd, NULL, y);
2267 EDIT_WriteTextLine(hwnd, NULL, pbot);
2273 /*********************************************************************
2276 * Stop text marking (selection).
2279 void EDIT_StopMarking(HWND hwnd)
2281 WND *wndPtr = WIN_FindWndPtr(hwnd);
2282 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2284 TextMarking = FALSE;
2285 if (es->SelBegLine > es->SelEndLine)
2287 swap(&(es->SelBegLine), &(es->SelEndLine));
2288 swap(&(es->SelBegCol), &(es->SelEndCol));
2290 if (es->SelBegLine == es->SelEndLine && es->SelBegCol > es->SelEndCol)
2291 swap(&(es->SelBegCol), &(es->SelEndCol));
2295 /*********************************************************************
2296 * EM_GETLINE message function
2299 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam)
2303 char *buffer = (char *)lParam;
2304 WND *wndPtr = WIN_FindWndPtr(hwnd);
2305 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2307 cp = EDIT_TextLine(hwnd, wParam);
2308 cp1 = EDIT_TextLine(hwnd, wParam + 1);
2309 len = min((int)(cp1 - cp), (WORD)(*buffer));
2310 strncpy(buffer, cp, len);
2316 /*********************************************************************
2317 * EM_GETSEL message function
2320 LONG EDIT_GetSelMsg(HWND hwnd)
2323 WND *wndPtr = WIN_FindWndPtr(hwnd);
2324 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2325 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2327 so = *(textPtrs + es->SelBegLine) + es->SelBegCol;
2328 eo = *(textPtrs + es->SelEndLine) + es->SelEndCol;
2330 return MAKELONG(so, eo);
2334 /*********************************************************************
2335 * EM_LINEFROMCHAR message function
2338 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam)
2341 WND *wndPtr = WIN_FindWndPtr(hwnd);
2342 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2344 if (wParam == (WORD)-1)
2345 return (LONG)(es->SelBegLine);
2347 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2353 /*********************************************************************
2354 * EM_LINEINDEX message function
2357 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam)
2359 WND *wndPtr = WIN_FindWndPtr(hwnd);
2360 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2361 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2363 if (wParam == (WORD)-1)
2364 wParam = es->CurrLine;
2366 return (LONG)(*(textPtrs + wParam));
2370 /*********************************************************************
2374 void swap(int *a, int *b)