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
)