4 * Copyright David W. Metcalfe, 1994
9 static char Copyright
[] = "Copyright David W. Metcalfe, 1994";
20 #define EDIT_HEAP_ALLOC(size) USER_HEAP_ALLOC(GMEM_MOVEABLE,size)
21 #define EDIT_HEAP_REALLOC(handle,size) USER_HEAP_REALLOC(handle,size,\
23 #define EDIT_HEAP_ADDR(handle) USER_HEAP_ADDR(handle)
24 #define EDIT_HEAP_FREE(handle) USER_HEAP_FREE(handle)
26 /* #define DEBUG_EDIT /* */
28 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
29 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
30 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
32 #define MAXTEXTLEN 30000 /* maximum text buffer length */
33 #define EDITLEN 1024 /* starting length for multi-line control */
34 #define ENTRYLEN 256 /* starting length for single line control */
35 #define GROWLENGTH 64 /* buffers grow by this much */
37 #define HSCROLLDIM (ClientWidth(wndPtr) / 3)
38 /* "line" dimension for horizontal scroll */
43 int wlines
; /* number of lines of text */
44 int wtop
; /* top line that is displayed */
45 int wleft
; /* left pixel that is displayed */
46 unsigned int textlen
; /* text buffer length */
47 int textwidth
; /* width of longest line in pixels */
48 RECT fmtrc
; /* rectangle in which to format text */
49 int txtht
; /* height of text line in pixels */
50 HANDLE hText
; /* handle to text buffer */
51 HANDLE hCharWidths
; /* widths of chars in font */
52 HANDLE hTextPtrs
; /* list of line offsets */
53 HANDLE hBlankLine
; /* to fill blank lines quickly */
54 int CurrCol
; /* current column */
55 int CurrLine
; /* current line */
56 int WndCol
; /* current window column */
57 int WndRow
; /* current window row */
58 BOOL TextChanged
; /* TRUE if text has changed */
59 BOOL PaintBkgd
; /* paint control background */
60 unsigned int MaxTextLen
; /* maximum text buffer length */
61 int SelBegLine
; /* beginning line of selection */
62 int SelBegCol
; /* beginning column of selection */
63 int SelEndLine
; /* ending line of selection */
64 int SelEndCol
; /* ending column of selection */
65 HFONT hFont
; /* handle of current font (if not default) */
66 HANDLE hDeletedText
; /* handle to deleted txet buffer for undo */
67 int DeletedLength
; /* length of deleted text */
68 int DeletedCurrLine
; /* starting line from which text was deleted */
69 int DeletedCurrCol
; /* starting col from which text was deleted */
70 int NumTabStops
; /* number of tab stops in buffer hTabStops */
71 HANDLE hTabStops
; /* handle of tab stops buffer */
75 #define ClientWidth(wndPtr) (wndPtr->rectClient.right - \
76 wndPtr->rectClient.left)
77 #define ClientHeight(wndPtr, es) ((wndPtr->rectClient.bottom - \
78 wndPtr->rectClient.top) / es->txtht)
79 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
81 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
82 #define SelMarked(es) (es->SelBegLine != 0 || es->SelBegCol != 0 || \
83 es->SelEndLine != 0 || es->SelEndCol != 0)
84 #define ROUNDUP(numer, denom) (((numer) % (denom)) \
85 ? ((((numer) + (denom)) / (denom)) * (denom)) \
88 /* macros to access window styles */
89 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
90 #define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
91 #define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
92 #define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
93 #define IsHScrollBar() (wndPtr->dwStyle & WS_HSCROLL)
95 /* internal variables */
96 static BOOL TextMarking
; /* TRUE if text marking in progress */
97 static BOOL ButtonDown
; /* TRUE if left mouse button down */
98 static int ButtonRow
; /* row in text buffer when button pressed */
99 static int ButtonCol
; /* col in text buffer when button pressed */
100 static BOOL Print
= FALSE
;
103 LONG
EditWndProc(HWND hWnd
, WORD uMsg
, WORD wParam
, LONG lParam
);
104 long EDIT_NCCreateMsg(HWND hwnd
, LONG lParam
);
105 long EDIT_CreateMsg(HWND hwnd
, LONG lParam
);
106 void EDIT_ClearTextPointers(HWND hwnd
);
107 void EDIT_BuildTextPointers(HWND hwnd
);
108 void EDIT_ModTextPointers(HWND hwnd
, int lineno
, int var
);
109 void EDIT_PaintMsg(HWND hwnd
);
110 HANDLE
EDIT_GetTextLine(HWND hwnd
, int selection
);
111 char *EDIT_TextLine(HWND hwnd
, int sel
);
112 int EDIT_StrLength(HWND hwnd
, char *str
, int len
, int pcol
);
113 int EDIT_LineLength(HWND hwnd
, int num
);
114 void EDIT_WriteTextLine(HWND hwnd
, RECT
*rc
, int y
);
115 void EDIT_WriteText(HWND hwnd
, char *lp
, int off
, int len
, int row
,
116 int col
, RECT
*rc
, BOOL blank
, BOOL reverse
);
117 HANDLE
EDIT_GetStr(HWND hwnd
, char *lp
, int off
, int len
, int *diff
);
118 void EDIT_CharMsg(HWND hwnd
, WORD wParam
);
119 void EDIT_KeyTyped(HWND hwnd
, short ch
);
120 int EDIT_CharWidth(HWND hwnd
, short ch
, int pcol
);
121 int EDIT_GetNextTabStop(HWND hwnd
, int pcol
);
122 void EDIT_Forward(HWND hwnd
);
123 void EDIT_Downward(HWND hwnd
);
124 void EDIT_Upward(HWND hwnd
);
125 void EDIT_Backward(HWND hwnd
);
126 void EDIT_End(HWND hwnd
);
127 void EDIT_Home(HWND hwnd
);
128 void EDIT_StickEnd(HWND hwnd
);
129 void EDIT_KeyDownMsg(HWND hwnd
, WORD wParam
);
130 void EDIT_KeyHScroll(HWND hwnd
, WORD opt
);
131 void EDIT_KeyVScrollLine(HWND hwnd
, WORD opt
);
132 void EDIT_KeyVScrollPage(HWND hwnd
, WORD opt
);
133 void EDIT_KeyVScrollDoc(HWND hwnd
, WORD opt
);
134 int EDIT_ComputeVScrollPos(HWND hwnd
);
135 int EDIT_ComputeHScrollPos(HWND hwnd
);
136 void EDIT_DelKey(HWND hwnd
);
137 void EDIT_VScrollMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
138 void EDIT_VScrollLine(HWND hwnd
, WORD opt
);
139 void EDIT_VScrollPage(HWND hwnd
, WORD opt
);
140 void EDIT_HScrollMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
141 void EDIT_SizeMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
142 void EDIT_LButtonDownMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
143 void EDIT_MouseMoveMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
144 int EDIT_PixelToChar(HWND hwnd
, int row
, int *pixel
);
145 LONG
EDIT_SetTextMsg(HWND hwnd
, LONG lParam
);
146 void EDIT_ClearText(HWND hwnd
);
147 void EDIT_SetSelMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
148 void EDIT_GetLineCol(HWND hwnd
, int off
, int *line
, int *col
);
149 void EDIT_DeleteSel(HWND hwnd
);
150 void EDIT_ClearSel(HWND hwnd
);
151 int EDIT_TextLineNumber(HWND hwnd
, char *lp
);
152 void EDIT_SetAnchor(HWND hwnd
, int row
, int col
);
153 void EDIT_ExtendSel(HWND hwnd
, int x
, int y
);
154 void EDIT_WriteSel(HWND hwnd
, int y
, int start
, int end
);
155 void EDIT_StopMarking(HWND hwnd
);
156 LONG
EDIT_GetLineMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
157 LONG
EDIT_GetSelMsg(HWND hwnd
);
158 void EDIT_ReplaceSel(HWND hwnd
, LONG lParam
);
159 void EDIT_InsertText(HWND hwnd
, char *str
, int len
);
160 LONG
EDIT_LineFromCharMsg(HWND hwnd
, WORD wParam
);
161 LONG
EDIT_LineIndexMsg(HWND hwnd
, WORD wParam
);
162 LONG
EDIT_LineLengthMsg(HWND hwnd
, WORD wParam
);
163 void EDIT_SetFont(HWND hwnd
, WORD wParam
, LONG lParam
);
164 void EDIT_SaveDeletedText(HWND hwnd
, char *deltext
, int len
, int line
,
166 void EDIT_ClearDeletedText(HWND hwnd
);
167 LONG
EDIT_UndoMsg(HWND hwnd
);
168 unsigned int EDIT_HeapAlloc(HWND hwnd
, int bytes
);
169 void *EDIT_HeapAddr(HWND hwnd
, unsigned int handle
);
170 unsigned int EDIT_HeapReAlloc(HWND hwnd
, unsigned int handle
, int bytes
);
171 void EDIT_HeapFree(HWND hwnd
, unsigned int handle
);
172 unsigned int EDIT_HeapSize(HWND hwnd
, unsigned int handle
);
173 void EDIT_SetHandleMsg(HWND hwnd
, WORD wParam
);
174 LONG
EDIT_SetTabStopsMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
175 void swap(int *a
, int *b
);
178 LONG
EditWndProc(HWND hwnd
, WORD uMsg
, WORD wParam
, LONG lParam
)
184 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
186 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
190 lResult
= es
->hDeletedText
;
193 case EM_EMPTYUNDOBUFFER
:
194 EDIT_ClearDeletedText(hwnd
);
198 printf("edit: EM_FMTLINES message received\n");
205 case EM_GETFIRSTVISIBLELINE
:
215 lResult
= EDIT_GetLineMsg(hwnd
, wParam
, lParam
);
220 case EM_GETLINECOUNT
:
222 lResult
= es
->wlines
;
228 lResult
= es
->TextChanged
;
231 case EM_GETPASSWORDCHAR
:
232 printf("edit: cannot process EM_GETPASSWORDCHAR message\n");
236 GetWindowRect(hwnd
, (LPRECT
)lParam
);
240 lResult
= EDIT_GetSelMsg(hwnd
);
243 case EM_GETWORDBREAKPROC
:
244 printf("edit: cannot process EM_GETWORDBREAKPROC message\n");
249 es
->MaxTextLen
= wParam
;
250 else if (IsMultiLine())
251 es
->MaxTextLen
= 65535;
253 es
->MaxTextLen
= 32767;
256 case EM_LINEFROMCHAR
:
257 lResult
= EDIT_LineFromCharMsg(hwnd
, wParam
);
262 lResult
= EDIT_LineIndexMsg(hwnd
, wParam
);
268 lResult
= EDIT_LineLengthMsg(hwnd
, wParam
);
272 printf("edit: cannot process EM_LINESCROLL message\n");
277 EDIT_ReplaceSel(hwnd
, lParam
);
278 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
283 EDIT_SetHandleMsg(hwnd
, wParam
);
287 es
->TextChanged
= wParam
;
290 case EM_SETPASSWORDCHAR
:
291 printf("edit: cannot process EM_SETPASSWORDCHAR message\n");
295 printf("edit: cannot process EM_SETREADONLY message\n");
300 printf("edit: cannot process EM_SETRECT(NP) message\n");
305 EDIT_SetSelMsg(hwnd
, wParam
, lParam
);
306 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
311 lResult
= EDIT_SetTabStopsMsg(hwnd
, wParam
, lParam
);
314 case EM_SETWORDBREAKPROC
:
315 printf("edit: cannot process EM_SETWORDBREAKPROC message\n");
320 lResult
= EDIT_UndoMsg(hwnd
);
321 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
326 EDIT_CharMsg(hwnd
, wParam
);
330 lResult
= EDIT_CreateMsg(hwnd
, lParam
);
334 EDIT_HeapFree(hwnd
, es
->hTextPtrs
);
335 EDIT_HeapFree(hwnd
, es
->hCharWidths
);
336 EDIT_HeapFree(hwnd
, es
->hText
);
337 EDIT_HeapFree(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
341 InvalidateRect(hwnd
, NULL
, FALSE
);
345 textPtr
= EDIT_HeapAddr(hwnd
, es
->hText
);
346 if ((int)wParam
> (len
= strlen(textPtr
)))
348 strcpy((char *)lParam
, textPtr
);
349 lResult
= (DWORD
)len
;
355 case WM_GETTEXTLENGTH
:
356 textPtr
= EDIT_HeapAddr(hwnd
, es
->hText
);
357 lResult
= (DWORD
)strlen(textPtr
);
361 EDIT_HScrollMsg(hwnd
, wParam
, lParam
);
365 EDIT_KeyDownMsg(hwnd
, wParam
);
370 NOTIFY_PARENT(hwnd
, EN_KILLFOCUS
);
376 EDIT_LButtonDownMsg(hwnd
, wParam
, lParam
);
377 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
384 EDIT_StopMarking(hwnd
);
389 EDIT_MouseMoveMsg(hwnd
, wParam
, lParam
);
390 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
399 lResult
= EDIT_NCCreateMsg(hwnd
, lParam
);
407 CreateCaret(hwnd
, 0, 2, es
->txtht
);
408 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
410 NOTIFY_PARENT(hwnd
, EN_SETFOCUS
);
415 EDIT_SetFont(hwnd
, wParam
, lParam
);
416 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
421 EDIT_SetTextMsg(hwnd
, lParam
);
425 EDIT_SizeMsg(hwnd
, wParam
, lParam
);
430 EDIT_VScrollMsg(hwnd
, wParam
, lParam
);
434 lResult
= DefWindowProc(hwnd
, uMsg
, wParam
, lParam
);
443 /*********************************************************************
444 * WM_NCCREATE message function
447 long EDIT_NCCreateMsg(HWND hwnd
, LONG lParam
)
449 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)lParam
;
450 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
452 unsigned int *textPtrs
;
456 /* store pointer to local heap in window structure so that */
457 /* EDITSTATE structure itself can be stored on local heap */
458 (MDESC
**)*(LONG
*)(wndPtr
->wExtra
+ 2) =
459 &HEAP_LocalFindHeap(createStruct
->hInstance
)->free_list
;
461 /* allocate space for state variable structure */
462 (HANDLE
)(*(wndPtr
->wExtra
)) = EDIT_HeapAlloc(hwnd
, sizeof(EDITSTATE
));
463 es
= (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
464 es
->hTextPtrs
= EDIT_HeapAlloc(hwnd
, sizeof(int));
465 textPtrs
= (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
466 es
->hCharWidths
= EDIT_HeapAlloc(hwnd
, 256 * sizeof(short));
468 /* --- text buffer */
469 es
->MaxTextLen
= MAXTEXTLEN
+ 1;
470 if (!(createStruct
->lpszName
))
472 es
->textlen
= EditBufLen(wndPtr
) + 1;
473 es
->hText
= EDIT_HeapAlloc(hwnd
, EditBufLen(wndPtr
) + 2);
474 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
475 memset(text
, 0, es
->textlen
+ 2);
476 EDIT_ClearTextPointers(hwnd
);
480 if (strlen(createStruct
->lpszName
) < EditBufLen(wndPtr
))
482 es
->hText
= EDIT_HeapAlloc(hwnd
, EditBufLen(wndPtr
) + 2);
483 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
484 strcpy(text
, createStruct
->lpszName
);
485 *(text
+ es
->textlen
) = '\0';
486 es
->textlen
= EditBufLen(wndPtr
) + 1;
490 es
->hText
= EDIT_HeapAlloc(hwnd
,
491 strlen(createStruct
->lpszName
) + 2);
492 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
493 strcpy(text
, createStruct
->lpszName
);
494 es
->textlen
= strlen(createStruct
->lpszName
) + 1;
496 *(text
+ es
->textlen
+ 1) = '\0';
497 EDIT_BuildTextPointers(hwnd
);
500 if ((createStruct
->style
& WS_VSCROLL
) ||
501 (createStruct
->style
& WS_HSCROLL
)) NC_CreateScrollBars(hwnd
);
503 /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
504 /* the corresponding WM_* message is set */
505 if (createStruct
->style
& WS_VSCROLL
)
506 wndPtr
->dwStyle
|= ES_AUTOVSCROLL
;
507 if (createStruct
->style
& WS_HSCROLL
)
508 wndPtr
->dwStyle
|= ES_AUTOHSCROLL
;
510 /* remove the WS_CAPTION style if it has been set - this is really a */
511 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
512 if (wndPtr
->dwStyle
& WS_BORDER
&& wndPtr
->dwStyle
& WS_DLGFRAME
)
513 wndPtr
->dwStyle
^= WS_DLGFRAME
;
519 /*********************************************************************
520 * WM_CREATE message function
523 long EDIT_CreateMsg(HWND hwnd
, LONG lParam
)
526 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
528 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
534 /* initialize state variable structure */
535 /* --- char width array */
537 charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
538 memset(charWidths
, 0, 256 * sizeof(short));
539 GetCharWidth(hdc
, 0, 255, charWidths
);
541 /* --- other structure variables */
542 GetTextMetrics(hdc
, &tm
);
543 es
->txtht
= tm
.tmHeight
+ tm
.tmExternalLeading
;
545 es
->wtop
= es
->wleft
= 0;
546 es
->CurrCol
= es
->CurrLine
= 0;
547 es
->WndCol
= es
->WndRow
= 0;
548 es
->TextChanged
= FALSE
;
550 es
->SelBegLine
= es
->SelBegCol
= 0;
551 es
->SelEndLine
= es
->SelEndCol
= 0;
553 es
->hDeletedText
= 0;
554 es
->DeletedLength
= 0;
556 es
->hTabStops
= EDIT_HeapAlloc(hwnd
, sizeof(int));
558 /* allocate space for a line full of blanks to speed up */
560 es
->hBlankLine
= EDIT_HeapAlloc(hwnd
, (ClientWidth(wndPtr
) /
561 charWidths
[32]) + 2);
562 text
= EDIT_HeapAddr(hwnd
, es
->hBlankLine
);
563 memset(text
, ' ', (ClientWidth(wndPtr
) / charWidths
[32]) + 2);
565 /* set up text cursor for edit class */
566 CLASS_FindClassByName("EDIT", &classPtr
);
567 classPtr
->wc
.hCursor
= LoadCursor(0, IDC_IBEAM
);
569 /* paint background on first WM_PAINT */
570 es
->PaintBkgd
= TRUE
;
572 ReleaseDC(hwnd
, hdc
);
577 /*********************************************************************
578 * EDIT_ClearTextPointers
580 * Clear and initialize text line pointer array.
583 void EDIT_ClearTextPointers(HWND hwnd
)
585 unsigned int *textPtrs
;
586 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
588 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
590 es
->hTextPtrs
= EDIT_HeapReAlloc(hwnd
, es
->hTextPtrs
, sizeof(int));
591 textPtrs
= (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
596 /*********************************************************************
597 * EDIT_BuildTextPointers
599 * Build array of pointers to text lines.
602 #define INITLINES 100
604 void EDIT_BuildTextPointers(HWND hwnd
)
606 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
608 int incrs
= INITLINES
;
609 unsigned int off
, len
, temp
;
611 unsigned int *textPtrs
;
614 es
= (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
615 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
616 textPtrs
= (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
617 charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
619 es
->textwidth
= es
->wlines
= 0;
622 /* advance through text buffer */
625 /* increase size of text pointer array */
626 if (incrs
== INITLINES
)
629 es
->hTextPtrs
= EDIT_HeapReAlloc(hwnd
, es
->hTextPtrs
,
630 (es
->wlines
+ INITLINES
) * sizeof(int));
631 textPtrs
= (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
633 off
= (unsigned int)(cp
- text
); /* offset of beginning of line */
634 *(textPtrs
+ es
->wlines
) = off
;
639 /* advance through current line */
640 while (*cp
&& *cp
!= '\n')
642 len
+= EDIT_CharWidth(hwnd
, *cp
, len
);
643 /* width of line in pixels */
646 es
->textwidth
= max(es
->textwidth
, len
);
648 cp
++; /* skip '\n' */
651 off
= (unsigned int)(cp
- text
);
652 *(textPtrs
+ es
->wlines
) = off
;
656 /*********************************************************************
657 * EDIT_ModTextPointers
659 * Modify text pointers from a specified position.
662 void EDIT_ModTextPointers(HWND hwnd
, int lineno
, int var
)
664 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
666 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
667 unsigned int *textPtrs
=
668 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
670 while (lineno
< es
->wlines
)
671 *(textPtrs
+ lineno
++) += var
;
675 /*********************************************************************
676 * WM_PAINT message function
679 void EDIT_PaintMsg(HWND hwnd
)
685 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
687 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
689 hdc
= BeginPaint(hwnd
, &ps
);
693 printf("WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc
.left
, rc
.top
,
694 rc
.right
, rc
.bottom
);
698 FillWindow(GetParent(hwnd
), hwnd
, hdc
, CTLCOLOR_EDIT
);
700 for (y
= (rc
.top
/ es
->txtht
); y
<= (rc
.bottom
/ es
->txtht
); y
++)
702 if (y
< es
->wlines
- es
->wtop
)
703 EDIT_WriteTextLine(hwnd
, &rc
, y
+ es
->wtop
);
710 /*********************************************************************
713 * Get a copy of the text in the specified line.
716 HANDLE
EDIT_GetTextLine(HWND hwnd
, int selection
)
724 printf("GetTextLine %d\n", selection
);
726 cp
= cp1
= EDIT_TextLine(hwnd
, selection
);
727 /* advance through line */
728 while (*cp
&& *cp
!= '\n')
734 /* store selected line and return handle */
735 hLine
= EDIT_HeapAlloc(hwnd
, len
+ 6);
736 line
= (char *)EDIT_HeapAddr(hwnd
, hLine
);
737 memmove(line
, cp1
, len
);
743 /*********************************************************************
746 * Return a pointer to the text in the specified line.
749 char *EDIT_TextLine(HWND hwnd
, int sel
)
751 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
753 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
754 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
755 unsigned int *textPtrs
=
756 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
758 return (text
+ *(textPtrs
+ sel
));
762 /*********************************************************************
765 * Return length of string _str_ of length _len_ characters in pixels.
766 * The current column offset in pixels _pcol_ is required to calculate
767 * the width of a tab.
770 int EDIT_StrLength(HWND hwnd
, char *str
, int len
, int pcol
)
773 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
775 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
777 for (i
= 0; i
< len
; i
++)
778 plen
+= EDIT_CharWidth(hwnd
, *(str
+ i
), pcol
+ plen
);
781 printf("EDIT_StrLength: returning %d\n", plen
);
787 /*********************************************************************
790 * Return length of line _num_ in characters.
793 int EDIT_LineLength(HWND hwnd
, int num
)
795 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
797 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
798 char *cp
= EDIT_TextLine(hwnd
, num
);
801 cp1
= strchr(cp
, '\n');
802 return cp1
? (int)(cp1
- cp
) : strlen(cp
);
806 /*********************************************************************
809 * Write the line of text at offset _y_ in text buffer to a window.
812 void EDIT_WriteTextLine(HWND hwnd
, RECT
*rect
, int y
)
815 unsigned char line
[200];
820 int sbl
, sel
, sbc
, sec
;
823 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
825 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
827 /* initialize rectangle if NULL, else copy */
831 GetClientRect(hwnd
, &rc
);
834 printf("WriteTextLine %d\n", y
);
837 /* make sure y is inside the window */
838 if (y
< es
->wtop
|| y
> (es
->wtop
+ ClientHeight(wndPtr
, es
)))
841 printf("EDIT_WriteTextLine: y (%d) is not a displayed line\n", y
);
846 /* make sure rectangle is within window */
847 if (rc
.left
>= ClientWidth(wndPtr
) - 1)
850 printf("EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
858 printf("EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
863 if (y
- es
->wtop
< (rc
.top
/ es
->txtht
) ||
864 y
- es
->wtop
> (rc
.bottom
/ es
->txtht
))
867 printf("EDIT_WriteTextLine: y (%d) is outside window\n", y
);
872 /* get the text and length of line */
873 if ((hLine
= EDIT_GetTextLine(hwnd
, y
)) == 0)
875 lp
= (unsigned char *)EDIT_HeapAddr(hwnd
, hLine
);
876 lnlen
= EDIT_StrLength(hwnd
, lp
, strlen(lp
), 0);
879 /* build the line to display */
880 if (lnlen
< es
->wleft
)
888 lnlen
= lnlen1
- off
;
889 len
= min(lnlen
, rc
.right
- rc
.left
);
894 sbl
= es
->SelBegLine
;
895 sel
= es
->SelEndLine
;
899 /* put lowest marker first */
905 if (sbl
== sel
&& sbc
> sec
)
908 if (y
< sbl
|| y
> sel
)
909 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
911 else if (y
> sbl
&& y
< sel
)
912 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
916 col
= EDIT_StrLength(hwnd
, lp
, sbc
, 0);
917 if (col
> (es
->wleft
+ rc
.left
))
919 len
= min(col
- off
, rc
.right
- off
);
920 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
921 rc
.left
, &rc
, FALSE
, FALSE
);
926 col
= EDIT_StrLength(hwnd
, lp
, sec
, 0);
927 if (col
< (es
->wleft
+ rc
.right
))
929 len
= min(col
- off
, rc
.right
- off
);
930 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
931 off
- es
->wleft
, &rc
, FALSE
, TRUE
);
933 len
= min(lnlen
- off
, rc
.right
- off
);
934 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
935 off
- es
->wleft
, &rc
, TRUE
, FALSE
);
939 len
= min(lnlen
- off
, rc
.right
- off
);
940 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
941 off
- es
->wleft
, &rc
, TRUE
, TRUE
);
946 len
= min(lnlen
- off
, rc
.right
- off
);
947 if (col
< (es
->wleft
+ rc
.right
))
948 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
949 off
- es
->wleft
, &rc
, TRUE
, TRUE
);
954 col
= EDIT_StrLength(hwnd
, lp
, sec
, 0);
955 if (col
< (es
->wleft
+ rc
.right
))
957 len
= min(col
- off
, rc
.right
- off
);
958 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
959 off
- es
->wleft
, &rc
, FALSE
, TRUE
);
961 len
= min(lnlen
- off
, rc
.right
- off
);
962 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
963 off
- es
->wleft
, &rc
, TRUE
, FALSE
);
968 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
971 EDIT_HeapFree(hwnd
, hLine
);
975 /*********************************************************************
978 * Write text to a window
980 * off - offset in text line (in pixels)
981 * len - length from off (in pixels)
982 * row - line in window
983 * col - column in window
984 * rc - rectangle in which to display line
985 * blank - blank remainder of line?
986 * reverse - reverse color of line?
989 void EDIT_WriteText(HWND hwnd
, char *lp
, int off
, int len
, int row
,
990 int col
, RECT
*rc
, BOOL blank
, BOOL reverse
)
994 char *str
, *cp
, *cp1
;
995 int diff
, num_spaces
, tabwidth
, scol
;
997 COLORREF oldTextColor
, oldBkgdColor
;
999 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1001 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1002 short *charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
1003 char *blanks
= (char *)EDIT_HeapAddr(hwnd
, es
->hBlankLine
);
1006 printf("EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp
, off
, len
, row
, col
, reverse
);
1010 hStr
= EDIT_GetStr(hwnd
, lp
, off
, len
, &diff
);
1011 str
= (char *)EDIT_HeapAddr(hwnd
, hStr
);
1012 hrgnClip
= CreateRectRgnIndirect(rc
);
1013 SelectClipRgn(hdc
, hrgnClip
);
1016 oldfont
= (HFONT
)SelectObject(hdc
, (HANDLE
)es
->hFont
);
1018 SendMessage(GetParent(hwnd
), WM_CTLCOLOR
, (WORD
)hdc
,
1019 MAKELPARAM(hwnd
, CTLCOLOR_EDIT
));
1023 oldBkgdColor
= GetBkColor(hdc
);
1024 oldTextColor
= GetTextColor(hdc
);
1025 SetBkColor(hdc
, oldTextColor
);
1026 SetTextColor(hdc
, oldBkgdColor
);
1029 if (!(cp
= strchr(str
, VK_TAB
)))
1030 TextOut(hdc
, col
- diff
, row
* es
->txtht
, str
, strlen(str
));
1033 TextOut(hdc
, col
- diff
, row
* es
->txtht
, str
, (int)(cp
- str
));
1034 scol
= EDIT_StrLength(hwnd
, str
, (int)(cp
- str
), 0);
1035 tabwidth
= EDIT_CharWidth(hwnd
, VK_TAB
, scol
);
1036 num_spaces
= tabwidth
/ charWidths
[32] + 1;
1037 TextOut(hdc
, scol
, row
* es
->txtht
, blanks
, num_spaces
);
1041 while (cp1
= strchr(cp
, VK_TAB
))
1043 TextOut(hdc
, scol
, row
* es
->txtht
, cp
, (int)(cp1
- cp
));
1044 scol
+= EDIT_StrLength(hwnd
, cp
, (int)(cp1
- cp
), scol
);
1045 tabwidth
= EDIT_CharWidth(hwnd
, VK_TAB
, scol
);
1046 num_spaces
= tabwidth
/ charWidths
[32] + 1;
1047 TextOut(hdc
, scol
, row
* es
->txtht
, blanks
, num_spaces
);
1052 TextOut(hdc
, scol
, row
* es
->txtht
, cp
, strlen(cp
));
1057 SetBkColor(hdc
, oldBkgdColor
);
1058 SetTextColor(hdc
, oldTextColor
);
1061 /* blank out remainder of line if appropriate */
1064 if ((rc
->right
- col
) > len
)
1066 num_spaces
= (rc
->right
- col
- len
) / charWidths
[32];
1067 TextOut(hdc
, col
+ len
, row
* es
->txtht
, blanks
, num_spaces
);
1072 SelectObject(hdc
, (HANDLE
)oldfont
);
1074 EDIT_HeapFree(hwnd
, hStr
);
1075 ReleaseDC(hwnd
, hdc
);
1079 /*********************************************************************
1082 * Return sub-string starting at pixel _off_ of length _len_ pixels.
1083 * If _off_ is part way through a character, the negative offset of
1084 * the beginning of the character is returned in _diff_, else _diff_
1088 HANDLE
EDIT_GetStr(HWND hwnd
, char *lp
, int off
, int len
, int *diff
)
1092 int ch
= 0, i
= 0, j
, s_i
;
1094 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1096 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1099 printf("EDIT_GetStr %s %d %d\n", lp
, off
, len
);
1105 i
+= EDIT_CharWidth(hwnd
, *(lp
+ ch
), i
);
1109 /* if stepped past _off_, go back a character */
1118 while (i
< len
+ off
)
1120 i
+= EDIT_CharWidth(hwnd
, *(lp
+ ch
), i
);
1124 hStr
= EDIT_HeapAlloc(hwnd
, ch
- ch1
+ 3);
1125 str
= (char *)EDIT_HeapAddr(hwnd
, hStr
);
1126 for (i
= ch1
, j
= 0; i
< ch
; i
++, j
++)
1130 printf("EDIT_GetStr: returning %s\n", str
);
1136 /*********************************************************************
1137 * WM_CHAR message function
1140 void EDIT_CharMsg(HWND hwnd
, WORD wParam
)
1142 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1144 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1147 printf("EDIT_CharMsg: wParam=%c\n", (char)wParam
);
1157 EDIT_KeyTyped(hwnd
, wParam
);
1163 EDIT_KeyTyped(hwnd
, wParam
);
1167 if (wParam
>= 20 && wParam
<= 126)
1168 EDIT_KeyTyped(hwnd
, wParam
);
1174 /*********************************************************************
1177 * Process keystrokes that produce displayable characters.
1180 void EDIT_KeyTyped(HWND hwnd
, short ch
)
1182 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1184 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1185 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1186 char *currchar
= CurrChar
;
1188 BOOL FullPaint
= FALSE
;
1191 printf("EDIT_KeyTyped: ch=%c\n", (char)ch
);
1194 /* delete selected text (if any) */
1196 EDIT_DeleteSel(hwnd
);
1198 /* test for typing at end of maximum buffer size */
1199 if (currchar
== text
+ es
->MaxTextLen
)
1201 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1205 if (*currchar
== '\0' && IsMultiLine())
1207 /* insert a newline at end of text */
1209 *(currchar
+ 1) = '\0';
1210 EDIT_BuildTextPointers(hwnd
);
1213 /* insert the typed character */
1214 if (text
[es
->textlen
- 1] != '\0')
1216 /* current text buffer is full */
1217 if (es
->textlen
== es
->MaxTextLen
)
1219 /* text buffer is at maximum size */
1220 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1224 /* increase the text buffer size */
1225 es
->textlen
+= GROWLENGTH
;
1226 /* but not above maximum size */
1227 if (es
->textlen
> es
->MaxTextLen
)
1228 es
->textlen
= es
->MaxTextLen
;
1229 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, es
->textlen
+ 2);
1231 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1232 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1233 text
[es
->textlen
- 1] = '\0';
1234 currchar
= CurrChar
;
1236 /* make space for new character and put char in buffer */
1237 memmove(currchar
+ 1, currchar
, strlen(currchar
) + 1);
1239 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, 1);
1240 es
->TextChanged
= TRUE
;
1241 NOTIFY_PARENT(hwnd
, EN_UPDATE
);
1243 /* re-adjust textwidth, if necessary, and redraw line */
1245 if (IsMultiLine() && es
->wlines
> 1)
1247 es
->textwidth
= max(es
->textwidth
,
1248 EDIT_StrLength(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
1249 (int)(EDIT_TextLine(hwnd
, es
->CurrLine
+ 1) -
1250 EDIT_TextLine(hwnd
, es
->CurrLine
)), 0));
1253 es
->textwidth
= max(es
->textwidth
,
1254 EDIT_StrLength(hwnd
, text
, strlen(text
), 0));
1255 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ es
->WndRow
);
1262 EDIT_BuildTextPointers(hwnd
);
1266 /* invalidate rest of window */
1267 GetClientRect(hwnd
, &rc
);
1269 rc
.top
= es
->WndRow
* es
->txtht
;
1270 InvalidateRect(hwnd
, &rc
, FALSE
);
1272 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1275 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1279 /* test end of window */
1280 if (es
->WndCol
>= ClientWidth(wndPtr
) -
1281 EDIT_CharWidth(hwnd
, ch
, es
->WndCol
+ es
->wleft
))
1283 /* TODO:- Word wrap to be handled here */
1285 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1286 EDIT_KeyHScroll(hwnd
, SB_LINEDOWN
);
1288 es
->WndCol
+= EDIT_CharWidth(hwnd
, ch
, es
->WndCol
+ es
->wleft
);
1290 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1292 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1296 /*********************************************************************
1299 * Return the width of the given character in pixels.
1300 * The current column offset in pixels _pcol_ is required to calculate
1301 * the width of a tab.
1304 int EDIT_CharWidth(HWND hwnd
, short ch
, int pcol
)
1306 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1308 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1309 short *charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
1312 return (charWidths
[ch
]);
1314 return (EDIT_GetNextTabStop(hwnd
, pcol
) - pcol
);
1318 /*********************************************************************
1319 * EDIT_GetNextTabStop
1321 * Return the next tab stop beyond _pcol_.
1324 int EDIT_GetNextTabStop(HWND hwnd
, int pcol
)
1327 int baseUnitWidth
= LOWORD(GetDialogBaseUnits());
1328 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1330 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1331 unsigned short *tabstops
= EDIT_HeapAddr(hwnd
, es
->hTabStops
);
1333 if (es
->NumTabStops
== 0)
1334 return ROUNDUP(pcol
, 8 * baseUnitWidth
);
1335 else if (es
->NumTabStops
== 1)
1336 return ROUNDUP(pcol
, *tabstops
* baseUnitWidth
/ 4);
1339 for (i
= 0; i
< es
->NumTabStops
; i
++)
1341 if (*(tabstops
+ i
) * baseUnitWidth
/ 4 >= pcol
)
1342 return (*(tabstops
+ i
) * baseUnitWidth
/ 4);
1349 /*********************************************************************
1352 * Cursor right key: move right one character position.
1355 void EDIT_Forward(HWND hwnd
)
1357 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1359 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1360 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1362 if (*CurrChar
== '\0')
1365 if (*CurrChar
== '\n')
1368 EDIT_Downward(hwnd
);
1372 es
->WndCol
+= EDIT_CharWidth(hwnd
, *CurrChar
, es
->WndCol
+ es
->wleft
);
1374 if (es
->WndCol
>= ClientWidth(wndPtr
))
1375 EDIT_KeyHScroll(hwnd
, SB_LINEDOWN
);
1381 /*********************************************************************
1384 * Cursor down key: move down one line.
1387 void EDIT_Downward(HWND hwnd
)
1389 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1391 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1394 printf("EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n", es
->WndRow
, es
->wtop
, es
->wlines
);
1397 if (IsMultiLine() && (es
->WndRow
+ es
->wtop
+ 1 < es
->wlines
))
1400 if (es
->WndRow
== ClientHeight(wndPtr
, es
) - 1)
1403 EDIT_KeyVScrollLine(hwnd
, SB_LINEDOWN
);
1407 EDIT_StickEnd(hwnd
);
1412 /*********************************************************************
1415 * Cursor up key: move up one line.
1418 void EDIT_Upward(HWND hwnd
)
1420 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1422 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1424 if (IsMultiLine() && es
->CurrLine
!= 0)
1427 if (es
->WndRow
== 0)
1430 EDIT_KeyVScrollLine(hwnd
, SB_LINEUP
);
1434 EDIT_StickEnd(hwnd
);
1439 /*********************************************************************
1442 * Cursor left key: move left one character position.
1445 void EDIT_Backward(HWND hwnd
)
1447 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1449 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1450 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1455 if (*CurrChar
== VK_TAB
)
1456 es
->WndCol
-= EDIT_CharWidth(hwnd
, *CurrChar
,
1457 EDIT_StrLength(hwnd
,
1458 EDIT_TextLine(hwnd
, es
->CurrLine
),
1461 es
->WndCol
-= EDIT_CharWidth(hwnd
, *CurrChar
, 0);
1463 EDIT_KeyHScroll(hwnd
, SB_LINEUP
);
1465 else if (IsMultiLine() && es
->CurrLine
!= 0)
1473 /*********************************************************************
1476 * End key: move to end of line.
1479 void EDIT_End(HWND hwnd
)
1482 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1484 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1485 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1487 while (*CurrChar
&& *CurrChar
!= '\n')
1489 es
->WndCol
+= EDIT_CharWidth(hwnd
, *CurrChar
, es
->WndCol
+ es
->wleft
);
1493 if (es
->WndCol
>= ClientWidth(wndPtr
))
1495 es
->wleft
= es
->WndCol
- ClientWidth(wndPtr
) + HSCROLLDIM
;
1496 es
->WndCol
-= es
->wleft
;
1497 InvalidateRect(hwnd
, NULL
, FALSE
);
1503 /*********************************************************************
1506 * Home key: move to beginning of line.
1509 void EDIT_Home(HWND hwnd
)
1512 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1514 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1516 es
->CurrCol
= es
->WndCol
= 0;
1520 InvalidateRect(hwnd
, NULL
, FALSE
);
1526 /*********************************************************************
1529 * Stick the cursor to the end of the line.
1532 void EDIT_StickEnd(HWND hwnd
)
1534 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1536 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1537 int len
= EDIT_LineLength(hwnd
, es
->CurrLine
);
1538 char *cp
= EDIT_TextLine(hwnd
, es
->CurrLine
);
1541 es
->CurrCol
= min(len
, es
->CurrCol
);
1542 es
->WndCol
= min(EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
, es
->WndCol
);
1543 currpel
= EDIT_StrLength(hwnd
, cp
, es
->CurrCol
, 0);
1545 if (es
->wleft
> currpel
)
1547 es
->wleft
= max(0, currpel
- 20);
1548 es
->WndCol
= currpel
- es
->wleft
;
1551 else if (currpel
- es
->wleft
>= ClientWidth(wndPtr
))
1553 es
->wleft
= currpel
- (ClientWidth(wndPtr
) - 5);
1554 es
->WndCol
= currpel
- es
->wleft
;
1560 /*********************************************************************
1561 * WM_KEYDOWN message function
1564 void EDIT_KeyDownMsg(HWND hwnd
, WORD wParam
)
1566 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1568 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1571 printf("EDIT_KeyDownMsg: key=%x\n", wParam
);
1579 EDIT_ClearSel(hwnd
);
1583 EDIT_Backward(hwnd
);
1588 EDIT_ClearSel(hwnd
);
1590 EDIT_Downward(hwnd
);
1597 EDIT_ClearSel(hwnd
);
1603 EDIT_ClearSel(hwnd
);
1604 EDIT_Backward(hwnd
);
1609 EDIT_ClearSel(hwnd
);
1615 EDIT_ClearSel(hwnd
);
1623 EDIT_ClearSel(hwnd
);
1624 EDIT_KeyVScrollPage(hwnd
, SB_PAGEUP
);
1632 EDIT_ClearSel(hwnd
);
1633 EDIT_KeyVScrollPage(hwnd
, SB_PAGEDOWN
);
1639 EDIT_DeleteSel(hwnd
);
1642 if (es
->CurrCol
== 0 && es
->CurrLine
== 0)
1644 EDIT_Backward(hwnd
);
1651 EDIT_DeleteSel(hwnd
);
1657 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1662 /*********************************************************************
1665 * Scroll text horizontally using cursor keys.
1668 void EDIT_KeyHScroll(HWND hwnd
, WORD opt
)
1672 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1674 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1676 if (opt
== SB_LINEDOWN
)
1678 es
->wleft
+= HSCROLLDIM
;
1679 es
->WndCol
-= HSCROLLDIM
;
1685 if (es
->wleft
- HSCROLLDIM
< 0)
1687 es
->WndCol
+= es
->wleft
;
1692 es
->wleft
-= HSCROLLDIM
;
1693 es
->WndCol
+= HSCROLLDIM
;
1697 InvalidateRect(hwnd
, NULL
, FALSE
);
1702 hscrollpos
= EDIT_ComputeHScrollPos(hwnd
);
1703 SetScrollPos(hwnd
, SB_HORZ
, hscrollpos
, TRUE
);
1708 /*********************************************************************
1709 * EDIT_KeyVScrollLine
1711 * Scroll text vertically by one line using keyboard.
1714 void EDIT_KeyVScrollLine(HWND hwnd
, WORD opt
)
1718 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1720 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1725 if (opt
== SB_LINEDOWN
)
1727 /* move down one line */
1728 if (es
->wtop
+ ClientHeight(wndPtr
, es
) >= es
->wlines
)
1734 /* move up one line */
1740 if (IsWindowVisible(hwnd
))
1742 /* adjust client bottom to nearest whole line */
1743 GetClientRect(hwnd
, &rc
);
1744 rc
.bottom
= (rc
.bottom
/ es
->txtht
) * es
->txtht
;
1746 if (opt
== SB_LINEUP
)
1748 /* move up one line (scroll window down) */
1749 ScrollWindow(hwnd
, 0, es
->txtht
, &rc
, &rc
);
1750 /* write top line */
1751 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
);
1756 /* move down one line (scroll window up) */
1757 ScrollWindow(hwnd
, 0, -(es
->txtht
), &rc
, &rc
);
1758 /* write bottom line */
1759 y
= (((rc
.bottom
- rc
.top
) / es
->txtht
) - 1);
1760 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ y
);
1765 /* reset the vertical scroll bar */
1768 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1769 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1774 /*********************************************************************
1775 * EDIT_KeyVScrollPage
1777 * Scroll text vertically by one page using keyboard.
1780 void EDIT_KeyVScrollPage(HWND hwnd
, WORD opt
)
1784 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1786 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1790 if (opt
== SB_PAGEUP
)
1793 es
->wtop
-= ClientHeight(wndPtr
, es
);
1797 if (es
->wtop
+ ClientHeight(wndPtr
, es
) < es
->wlines
)
1799 es
->wtop
+= ClientHeight(wndPtr
, es
);
1800 if (es
->wtop
> es
->wlines
- ClientHeight(wndPtr
, es
))
1801 es
->wtop
= es
->wlines
- ClientHeight(wndPtr
, es
);
1807 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
1808 EDIT_StickEnd(hwnd
);
1809 InvalidateRect(hwnd
, NULL
, TRUE
);
1812 /* reset the vertical scroll bar */
1815 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1816 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1822 /*********************************************************************
1823 * EDIT_KeyVScrollDoc
1825 * Scroll text to top and bottom of document using keyboard.
1828 void EDIT_KeyVScrollDoc(HWND hwnd
, WORD opt
)
1832 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1834 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1840 es
->wtop
= es
->wleft
= 0;
1841 else if (es
->wtop
+ ClientHeight(wndPtr
, es
) < es
->wlines
)
1843 es
->wtop
= es
->wlines
- ClientHeight(wndPtr
, es
);
1847 es
->CurrLine
= es
->wlines
;
1848 es
->WndRow
= es
->wlines
- es
->wtop
;
1850 InvalidateRect(hwnd
, NULL
, TRUE
);
1853 /* reset the vertical scroll bar */
1856 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1857 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1862 /*********************************************************************
1863 * EDIT_ComputeVScrollPos
1865 * Compute the vertical scroll bar position from the window
1866 * position and text width.
1869 int EDIT_ComputeVScrollPos(HWND hwnd
)
1872 short minpos
, maxpos
;
1873 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1875 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1877 GetScrollRange(hwnd
, SB_VERT
, &minpos
, &maxpos
);
1879 if (es
->wlines
> ClientHeight(wndPtr
, es
))
1880 vscrollpos
= (double)(es
->wtop
) / (double)(es
->wlines
-
1881 ClientHeight(wndPtr
, es
)) * (maxpos
- minpos
);
1883 vscrollpos
= minpos
;
1889 /*********************************************************************
1890 * EDIT_ComputeHScrollPos
1892 * Compute the horizontal scroll bar position from the window
1893 * position and text width.
1896 int EDIT_ComputeHScrollPos(HWND hwnd
)
1899 short minpos
, maxpos
;
1900 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1902 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1904 GetScrollRange(hwnd
, SB_HORZ
, &minpos
, &maxpos
);
1906 if (es
->textwidth
> ClientWidth(wndPtr
))
1907 hscrollpos
= (double)(es
->wleft
) / (double)(es
->textwidth
-
1908 ClientWidth(wndPtr
)) * (maxpos
- minpos
);
1910 hscrollpos
= minpos
;
1916 /*********************************************************************
1919 * Delete character to right of cursor.
1922 void EDIT_DelKey(HWND hwnd
)
1925 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1927 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1928 char *currchar
= CurrChar
;
1929 BOOL repaint
= *currchar
== '\n';
1931 if (IsMultiLine() && *currchar
== '\n' && *(currchar
+ 1) == '\0')
1933 strcpy(currchar
, currchar
+ 1);
1934 NOTIFY_PARENT(hwnd
, EN_UPDATE
);
1938 EDIT_BuildTextPointers(hwnd
);
1939 GetClientRect(hwnd
, &rc
);
1940 rc
.top
= es
->WndRow
* es
->txtht
;
1941 InvalidateRect(hwnd
, &rc
, FALSE
);
1946 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, -1);
1947 EDIT_WriteTextLine(hwnd
, NULL
, es
->WndRow
+ es
->wtop
);
1950 es
->TextChanged
= TRUE
;
1951 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1954 /*********************************************************************
1955 * WM_VSCROLL message function
1958 void EDIT_VScrollMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
1960 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1962 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1972 EDIT_VScrollLine(hwnd
, wParam
);
1977 EDIT_VScrollPage(hwnd
, wParam
);
1982 SetCaretPos(es
->WndCol
, es
->WndRow
);
1987 /*********************************************************************
1990 * Scroll text vertically by one line using scrollbars.
1993 void EDIT_VScrollLine(HWND hwnd
, WORD opt
)
1997 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1999 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2002 printf("EDIT_VScrollLine: direction=%d\n", opt
);
2005 if (opt
== SB_LINEDOWN
)
2007 /* move down one line */
2008 if (es
->wtop
+ ClientHeight(wndPtr
, es
) >= es
->wlines
)
2014 /* move up one line */
2020 if (IsWindowVisible(hwnd
))
2022 /* adjust client bottom to nearest whole line */
2023 GetClientRect(hwnd
, &rc
);
2024 rc
.bottom
= (rc
.bottom
/ es
->txtht
) * es
->txtht
;
2026 if (opt
== SB_LINEUP
)
2028 /* move up one line (scroll window down) */
2029 ScrollWindow(hwnd
, 0, es
->txtht
, &rc
, &rc
);
2030 /* write top line */
2031 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
);
2036 /* move down one line (scroll window up) */
2037 ScrollWindow(hwnd
, 0, -(es
->txtht
), &rc
, &rc
);
2038 /* write bottom line */
2039 y
= ((rc
.bottom
- rc
.top
/ es
->txtht
) - 1);
2040 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ y
);
2047 /*********************************************************************
2050 * Scroll text vertically by one page using keyboard.
2053 void EDIT_VScrollPage(HWND hwnd
, WORD opt
)
2057 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2059 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2061 if (opt
== SB_PAGEUP
)
2064 es
->wtop
-= ClientHeight(wndPtr
, es
);
2068 if (es
->wtop
+ ClientHeight(wndPtr
, es
) < es
->wlines
)
2070 es
->wtop
+= ClientHeight(wndPtr
, es
);
2071 if (es
->wtop
> es
->wlines
- ClientHeight(wndPtr
, es
))
2072 es
->wtop
= es
->wlines
- ClientHeight(wndPtr
, es
);
2078 InvalidateRect(hwnd
, NULL
, TRUE
);
2081 /* reset the vertical scroll bar */
2084 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
2085 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
2090 /*********************************************************************
2091 * WM_HSCROLL message function
2094 void EDIT_HScrollMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2096 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2098 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2106 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2113 /*********************************************************************
2114 * WM_SIZE message function
2117 void EDIT_SizeMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2120 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2122 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2124 if (wParam
!= SIZE_MAXIMIZED
&& wParam
!= SIZE_RESTORED
) return;
2126 InvalidateRect(hwnd
, NULL
, TRUE
);
2127 es
->PaintBkgd
= TRUE
;
2132 /*********************************************************************
2133 * WM_LBUTTONDOWN message function
2136 void EDIT_LButtonDownMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2141 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2143 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2146 EDIT_ClearSel(hwnd
);
2148 es
->WndRow
= HIWORD(lParam
) / es
->txtht
;
2149 if (es
->WndRow
> es
->wlines
- es
->wtop
- 1)
2152 es
->WndRow
= es
->wlines
- es
->wtop
- 1;
2157 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
2159 cp
= EDIT_TextLine(hwnd
, es
->CurrLine
);
2160 len
= EDIT_LineLength(hwnd
, es
->CurrLine
);
2161 es
->WndCol
= LOWORD(lParam
);
2162 if (es
->WndCol
> EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
|| end
)
2163 es
->WndCol
= EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
;
2164 es
->CurrCol
= EDIT_PixelToChar(hwnd
, es
->CurrLine
, &(es
->WndCol
));
2167 ButtonRow
= es
->CurrLine
;
2168 ButtonCol
= es
->CurrCol
;
2172 /*********************************************************************
2173 * WM_MOUSEMOVE message function
2176 void EDIT_MouseMoveMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2178 if (wParam
!= MK_LBUTTON
)
2183 EDIT_SetAnchor(hwnd
, ButtonRow
, ButtonCol
);
2189 EDIT_ExtendSel(hwnd
, LOWORD(lParam
), HIWORD(lParam
));
2193 /*********************************************************************
2196 * Convert a pixel offset in the given row to a character offset,
2197 * adjusting the pixel offset to the nearest whole character if
2201 int EDIT_PixelToChar(HWND hwnd
, int row
, int *pixel
)
2203 int ch
= 0, i
= 0, s_i
;
2205 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2207 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2210 printf("EDIT_PixelToChar: row=%d, pixel=%d\n", row
, *pixel
);
2213 text
= EDIT_TextLine(hwnd
, row
);
2217 i
+= EDIT_CharWidth(hwnd
, *(text
+ ch
), i
);
2221 /* if stepped past _pixel_, go back a character */
2232 /*********************************************************************
2233 * WM_SETTEXT message function
2236 LONG
EDIT_SetTextMsg(HWND hwnd
, LONG lParam
)
2241 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2243 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2245 if (strlen((char *)lParam
) <= es
->MaxTextLen
)
2247 len
= strlen((char *)lParam
);
2248 EDIT_ClearText(hwnd
);
2250 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, len
+ 3);
2251 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2252 strcpy(text
, (char *)lParam
);
2253 text
[len
+ 1] = '\0';
2254 text
[len
+ 2] = '\0';
2255 EDIT_BuildTextPointers(hwnd
);
2256 InvalidateRect(hwnd
, NULL
, TRUE
);
2257 es
->PaintBkgd
= TRUE
;
2258 es
->TextChanged
= TRUE
;
2266 /*********************************************************************
2269 * Clear text from text buffer.
2272 void EDIT_ClearText(HWND hwnd
)
2274 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2276 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2277 unsigned int blen
= EditBufLen(wndPtr
) + 2;
2280 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, blen
);
2281 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2282 memset(text
, 0, blen
);
2285 es
->CurrLine
= es
->CurrCol
= 0;
2286 es
->WndRow
= es
->WndCol
= 0;
2287 es
->wleft
= es
->wtop
= 0;
2289 es
->TextChanged
= FALSE
;
2290 EDIT_ClearTextPointers(hwnd
);
2294 /*********************************************************************
2295 * EM_SETSEL message function
2298 void EDIT_SetSelMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2301 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2303 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2305 so
= LOWORD(lParam
);
2306 eo
= HIWORD(lParam
);
2308 if (so
== -1) /* if so == -1, clear selection */
2310 EDIT_ClearSel(hwnd
);
2314 if (so
== eo
) /* if so == eo, set caret only */
2316 EDIT_GetLineCol(hwnd
, so
, &(es
->CurrLine
), &(es
->CurrCol
));
2317 es
->WndRow
= es
->CurrLine
- es
->wtop
;
2321 if (es
->WndRow
< 0 || es
->WndRow
> ClientHeight(wndPtr
, es
))
2323 es
->wtop
= es
->CurrLine
;
2326 es
->WndCol
= EDIT_StrLength(hwnd
,
2327 EDIT_TextLine(hwnd
, es
->CurrLine
),
2328 es
->CurrCol
, 0) - es
->wleft
;
2329 if (es
->WndCol
> ClientWidth(wndPtr
))
2331 es
->wleft
= es
->WndCol
;
2334 else if (es
->WndCol
< 0)
2336 es
->wleft
+= es
->WndCol
;
2341 else /* otherwise set selection */
2346 EDIT_GetLineCol(hwnd
, so
, &(es
->SelBegLine
), &(es
->SelBegCol
));
2347 EDIT_GetLineCol(hwnd
, eo
, &(es
->SelEndLine
), &(es
->SelEndCol
));
2348 es
->CurrLine
= es
->SelEndLine
;
2349 es
->CurrCol
= es
->SelEndCol
;
2350 es
->WndRow
= es
->SelEndLine
- es
->wtop
;
2352 if (!wParam
) /* don't suppress scrolling of text */
2356 es
->wtop
= es
->SelEndLine
;
2359 else if (es
->WndRow
> ClientHeight(wndPtr
, es
))
2361 es
->wtop
+= es
->WndRow
- ClientHeight(wndPtr
, es
);
2362 es
->WndRow
= ClientHeight(wndPtr
, es
);
2364 es
->WndCol
= EDIT_StrLength(hwnd
,
2365 EDIT_TextLine(hwnd
, es
->SelEndLine
),
2366 es
->SelEndCol
, 0) - es
->wleft
;
2367 if (es
->WndCol
> ClientWidth(wndPtr
))
2369 es
->wleft
+= es
->WndCol
- ClientWidth(wndPtr
);
2370 es
->WndCol
= ClientWidth(wndPtr
);
2372 else if (es
->WndCol
< 0)
2374 es
->wleft
+= es
->WndCol
;
2379 InvalidateRect(hwnd
, NULL
, TRUE
);
2385 /*********************************************************************
2388 * Return line and column in text buffer from character offset.
2391 void EDIT_GetLineCol(HWND hwnd
, int off
, int *line
, int *col
)
2395 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2397 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2398 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2399 unsigned int *textPtrs
=
2400 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2402 /* check for (0,0) */
2410 if (off
> strlen(text
)) off
= strlen(text
);
2412 for (lineno
= 0; lineno
< es
->wlines
; lineno
++)
2414 cp
= text
+ *(textPtrs
+ lineno
);
2415 if (off
== (int)(cp
- text
))
2421 if (off
< (int)(cp
- text
))
2426 *col
= off
- (int)(cp1
- text
);
2428 if (*(text
+ *col
) == '\0')
2434 /*********************************************************************
2437 * Delete the current selected text (if any)
2440 void EDIT_DeleteSel(HWND hwnd
)
2444 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2446 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2447 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2451 bbl
= EDIT_TextLine(hwnd
, es
->SelBegLine
) + es
->SelBegCol
;
2452 bel
= EDIT_TextLine(hwnd
, es
->SelEndLine
) + es
->SelEndCol
;
2453 len
= (int)(bel
- bbl
);
2454 EDIT_SaveDeletedText(hwnd
, bbl
, len
, es
->SelBegLine
, es
->SelBegCol
);
2455 es
->TextChanged
= TRUE
;
2458 es
->CurrLine
= es
->SelBegLine
;
2459 es
->CurrCol
= es
->SelBegCol
;
2460 es
->WndRow
= es
->SelBegLine
- es
->wtop
;
2463 es
->wtop
= es
->SelBegLine
;
2466 es
->WndCol
= EDIT_StrLength(hwnd
, bbl
- es
->SelBegCol
,
2467 es
->SelBegCol
, 0) - es
->wleft
;
2469 EDIT_BuildTextPointers(hwnd
);
2470 es
->PaintBkgd
= TRUE
;
2471 EDIT_ClearSel(hwnd
);
2476 /*********************************************************************
2479 * Clear the current selection.
2482 void EDIT_ClearSel(HWND hwnd
)
2484 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2486 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2488 es
->SelBegLine
= es
->SelBegCol
= 0;
2489 es
->SelEndLine
= es
->SelEndCol
= 0;
2491 InvalidateRect(hwnd
, NULL
, TRUE
);
2496 /*********************************************************************
2497 * EDIT_TextLineNumber
2499 * Return the line number in the text buffer of the supplied
2500 * character pointer.
2503 int EDIT_TextLineNumber(HWND hwnd
, char *lp
)
2507 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2509 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2510 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2511 unsigned int *textPtrs
=
2512 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2514 for (lineno
= 0; lineno
< es
->wlines
; lineno
++)
2516 cp
= text
+ *(textPtrs
+ lineno
);
2526 /*********************************************************************
2529 * Set down anchor for text marking.
2532 void EDIT_SetAnchor(HWND hwnd
, int row
, int col
)
2535 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2537 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2541 EDIT_ClearSel(hwnd
);
2542 es
->SelBegLine
= es
->SelEndLine
= row
;
2543 es
->SelBegCol
= es
->SelEndCol
= col
;
2546 InvalidateRect(hwnd
, NULL
, FALSE
);
2552 /*********************************************************************
2555 * Extend selection to the given screen co-ordinates.
2558 void EDIT_ExtendSel(HWND hwnd
, int x
, int y
)
2560 int bbl
, bel
, bbc
, bec
;
2564 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2566 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2569 printf("EDIT_ExtendSel: x=%d, y=%d\n", x
, y
);
2572 bbl
= es
->SelEndLine
;
2573 bbc
= es
->SelEndCol
;
2574 cp
= EDIT_TextLine(hwnd
, es
->wtop
+ y
/ es
->txtht
);
2575 len
= EDIT_LineLength(hwnd
, es
->wtop
+ y
/ es
->txtht
);
2577 es
->WndRow
= y
/ es
->txtht
;
2578 if (es
->WndRow
> es
->wlines
- es
->wtop
- 1)
2581 es
->WndRow
= es
->wlines
- es
->wtop
- 1;
2586 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
2587 es
->SelEndLine
= es
->CurrLine
;
2590 if (es
->WndCol
> EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
|| end
)
2591 es
->WndCol
= EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
;
2592 es
->CurrCol
= EDIT_PixelToChar(hwnd
, es
->CurrLine
, &(es
->WndCol
));
2593 es
->SelEndCol
= es
->CurrCol
- 1;
2595 bel
= es
->SelEndLine
;
2596 bec
= es
->SelEndCol
;
2598 /* return if no new characters to mark */
2599 if (bbl
== bel
&& bbc
== bec
)
2602 /* put lowest marker first */
2608 if (bbl
== bel
&& bbc
> bec
)
2611 for (y
= bbl
; y
<= bel
; y
++)
2613 if (y
== bbl
&& y
== bel
)
2614 EDIT_WriteSel(hwnd
, y
, bbc
, bec
);
2616 EDIT_WriteSel(hwnd
, y
, bbc
, -1);
2618 EDIT_WriteSel(hwnd
, y
, 0, bec
);
2620 EDIT_WriteSel(hwnd
, y
, 0, -1);
2625 /*********************************************************************
2628 * Display selection by reversing pixels in selected text.
2629 * If end == -1, selection applies to end of line.
2632 void EDIT_WriteSel(HWND hwnd
, int y
, int start
, int end
)
2638 HBRUSH hbrush
, holdbrush
;
2640 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2642 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2645 printf("EDIT_WriteSel: y=%d start=%d end=%d\n", y
, start
, end
);
2647 GetClientRect(hwnd
, &rc
);
2649 /* make sure y is within the window */
2650 if (y
< es
->wtop
|| y
> (es
->wtop
+ ClientHeight(wndPtr
, es
)))
2653 /* get pointer to text */
2654 cp
= EDIT_TextLine(hwnd
, y
);
2656 /* get length of line if end == -1 */
2658 end
= EDIT_LineLength(hwnd
, y
);
2660 scol
= EDIT_StrLength(hwnd
, cp
, start
, 0);
2661 if (scol
> rc
.right
) return;
2662 if (scol
< rc
.left
) scol
= rc
.left
;
2663 ecol
= EDIT_StrLength(hwnd
, cp
, end
, 0);
2664 if (ecol
< rc
.left
) return;
2665 if (ecol
> rc
.right
) ecol
= rc
.right
;
2668 hbrush
= GetStockObject(BLACK_BRUSH
);
2669 holdbrush
= (HBRUSH
)SelectObject(hdc
, (HANDLE
)hbrush
);
2670 olddm
= SetROP2(hdc
, R2_XORPEN
);
2671 Rectangle(hdc
, scol
, y
* es
->txtht
, ecol
, (y
+ 1) * es
->txtht
);
2672 SetROP2(hdc
, olddm
);
2673 SelectObject(hdc
, (HANDLE
)holdbrush
);
2674 ReleaseDC(hwnd
, hdc
);
2678 /*********************************************************************
2681 * Stop text marking (selection).
2684 void EDIT_StopMarking(HWND hwnd
)
2686 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2688 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2690 TextMarking
= FALSE
;
2691 if (es
->SelBegLine
> es
->SelEndLine
)
2693 swap(&(es
->SelBegLine
), &(es
->SelEndLine
));
2694 swap(&(es
->SelBegCol
), &(es
->SelEndCol
));
2696 if (es
->SelBegLine
== es
->SelEndLine
&& es
->SelBegCol
> es
->SelEndCol
)
2697 swap(&(es
->SelBegCol
), &(es
->SelEndCol
));
2701 /*********************************************************************
2702 * EM_GETLINE message function
2705 LONG
EDIT_GetLineMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2709 char *buffer
= (char *)lParam
;
2710 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2712 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2714 cp
= EDIT_TextLine(hwnd
, wParam
);
2715 cp1
= EDIT_TextLine(hwnd
, wParam
+ 1);
2716 len
= min((int)(cp1
- cp
), (WORD
)(*buffer
));
2717 strncpy(buffer
, cp
, len
);
2723 /*********************************************************************
2724 * EM_GETSEL message function
2727 LONG
EDIT_GetSelMsg(HWND hwnd
)
2730 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2732 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2733 unsigned int *textPtrs
=
2734 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2736 so
= *(textPtrs
+ es
->SelBegLine
) + es
->SelBegCol
;
2737 eo
= *(textPtrs
+ es
->SelEndLine
) + es
->SelEndCol
;
2739 return MAKELONG(so
, eo
);
2743 /*********************************************************************
2744 * EM_REPLACESEL message function
2747 void EDIT_ReplaceSel(HWND hwnd
, LONG lParam
)
2749 EDIT_DeleteSel(hwnd
);
2750 EDIT_InsertText(hwnd
, (char *)lParam
, strlen((char *)lParam
));
2751 InvalidateRect(hwnd
, NULL
, TRUE
);
2756 /*********************************************************************
2759 * Insert text at current line and column.
2762 void EDIT_InsertText(HWND hwnd
, char *str
, int len
)
2765 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2767 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2768 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2770 plen
= strlen(text
) + len
;
2771 if (plen
+ 1 > es
->textlen
)
2773 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, es
->textlen
+ len
);
2774 es
->textlen
= plen
+ 1;
2776 memmove(CurrChar
+ len
, CurrChar
, strlen(CurrChar
) + 1);
2777 memcpy(CurrChar
, str
, len
);
2779 EDIT_BuildTextPointers(hwnd
);
2780 es
->PaintBkgd
= TRUE
;
2781 es
->TextChanged
= TRUE
;
2783 EDIT_GetLineCol(hwnd
, (int)((CurrChar
+ len
) - text
), &(es
->CurrLine
),
2785 es
->WndRow
= es
->CurrLine
- es
->wtop
;
2786 es
->WndCol
= EDIT_StrLength(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
2787 es
->CurrCol
, 0) - es
->wleft
;
2791 /*********************************************************************
2792 * EM_LINEFROMCHAR message function
2795 LONG
EDIT_LineFromCharMsg(HWND hwnd
, WORD wParam
)
2798 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2800 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2802 if (wParam
== (WORD
)-1)
2803 return (LONG
)(es
->SelBegLine
);
2805 EDIT_GetLineCol(hwnd
, wParam
, &row
, &col
);
2811 /*********************************************************************
2812 * EM_LINEINDEX message function
2815 LONG
EDIT_LineIndexMsg(HWND hwnd
, WORD wParam
)
2817 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2819 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2820 unsigned int *textPtrs
=
2821 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2823 if (wParam
== (WORD
)-1)
2824 wParam
= es
->CurrLine
;
2826 return (LONG
)(*(textPtrs
+ wParam
));
2830 /*********************************************************************
2831 * EM_LINELENGTH message function
2834 LONG
EDIT_LineLengthMsg(HWND hwnd
, WORD wParam
)
2837 int sbl
, sbc
, sel
, sec
;
2838 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2840 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2841 unsigned int *textPtrs
=
2842 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2844 if (wParam
== (WORD
)-1)
2848 sbl
= es
->SelBegLine
;
2849 sbc
= es
->SelBegCol
;
2850 sel
= es
->SelEndLine
;
2851 sec
= es
->SelEndCol
;
2858 if (sbl
== sel
&& sbc
> sec
)
2863 len
= *(textPtrs
+ sbl
+ 1) - *(textPtrs
+ sbl
) - 1;
2864 return len
- sec
- sbc
;
2867 len
= *(textPtrs
+ sel
+ 1) - *(textPtrs
+ sel
) - sec
- 1;
2870 else /* no selection marked */
2872 len
= *(textPtrs
+ es
->CurrLine
+ 1) -
2873 *(textPtrs
+ es
->CurrLine
) - 1;
2877 else /* line number specified */
2879 EDIT_GetLineCol(hwnd
, wParam
, &row
, &col
);
2880 len
= *(textPtrs
+ row
+ 1) - *(textPtrs
+ row
);
2886 /*********************************************************************
2887 * WM_SETFONT message function
2890 void EDIT_SetFont(HWND hwnd
, WORD wParam
, LONG lParam
)
2895 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2897 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2898 short *charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
2902 oldfont
= (HFONT
)SelectObject(hdc
, (HANDLE
)es
->hFont
);
2903 GetCharWidth(hdc
, 0, 255, charWidths
);
2904 GetTextMetrics(hdc
, &tm
);
2905 es
->txtht
= tm
.tmHeight
+ tm
.tmExternalLeading
;
2906 SelectObject(hdc
, (HANDLE
)oldfont
);
2907 ReleaseDC(hwnd
, hdc
);
2909 es
->WndRow
= (es
->CurrLine
- es
->wtop
) / es
->txtht
;
2910 es
->WndCol
= EDIT_StrLength(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
2911 es
->CurrCol
, 0) - es
->wleft
;
2913 InvalidateRect(hwnd
, NULL
, TRUE
);
2914 es
->PaintBkgd
= TRUE
;
2915 if (lParam
) UpdateWindow(hwnd
);
2919 /*********************************************************************
2920 * EDIT_SaveDeletedText
2922 * Save deleted text in deleted text buffer.
2925 void EDIT_SaveDeletedText(HWND hwnd
, char *deltext
, int len
,
2929 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2931 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2933 es
->hDeletedText
= GlobalReAlloc(es
->hDeletedText
, len
, GMEM_MOVEABLE
);
2934 if (!es
->hDeletedText
) return;
2935 text
= (char *)GlobalLock(es
->hDeletedText
);
2936 memcpy(text
, deltext
, len
);
2937 GlobalUnlock(es
->hDeletedText
);
2938 es
->DeletedLength
= len
;
2939 es
->DeletedCurrLine
= line
;
2940 es
->DeletedCurrCol
= col
;
2944 /*********************************************************************
2945 * EDIT_ClearDeletedText
2947 * Clear deleted text buffer.
2950 void EDIT_ClearDeletedText(HWND hwnd
)
2952 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2954 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2956 GlobalFree(es
->hDeletedText
);
2957 es
->hDeletedText
= 0;
2958 es
->DeletedLength
= 0;
2962 /*********************************************************************
2963 * EM_UNDO message function
2966 LONG
EDIT_UndoMsg(HWND hwnd
)
2969 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2971 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2973 if (es
->hDeletedText
)
2975 text
= (char *)GlobalLock(es
->hDeletedText
);
2976 es
->CurrLine
= es
->DeletedCurrLine
;
2977 es
->CurrCol
= es
->DeletedCurrCol
;
2978 EDIT_InsertText(hwnd
, text
, es
->DeletedLength
);
2979 GlobalUnlock(es
->hDeletedText
);
2980 EDIT_ClearDeletedText(hwnd
);
2982 es
->SelBegLine
= es
->CurrLine
;
2983 es
->SelBegCol
= es
->CurrCol
;
2984 EDIT_GetLineCol(hwnd
, (int)((CurrChar
+ es
->DeletedLength
) - text
),
2985 &(es
->CurrLine
), &(es
->CurrCol
));
2986 es
->WndRow
= es
->CurrLine
- es
->wtop
;
2987 es
->WndCol
= EDIT_StrLength(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
2988 es
->CurrCol
, 0) - es
->wleft
;
2989 es
->SelEndLine
= es
->CurrLine
;
2990 es
->SelEndCol
= es
->CurrCol
;
2992 InvalidateRect(hwnd
, NULL
, TRUE
);
3001 /*********************************************************************
3004 * Allocate the specified number of bytes on the specified local heap.
3007 unsigned int EDIT_HeapAlloc(HWND hwnd
, int bytes
)
3009 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3011 return ((unsigned int)HEAP_Alloc((MDESC
**)
3012 *(LONG
*)(wndPtr
->wExtra
+ 2),
3013 GMEM_MOVEABLE
, bytes
) & 0xffff);
3017 /*********************************************************************
3020 * Return the address of the memory pointed to by the handle.
3023 void *EDIT_HeapAddr(HWND hwnd
, unsigned int handle
)
3025 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3027 return ((void *)((handle
) ? ((handle
) | ((unsigned int)
3028 (*(MDESC
**)*(LONG
*)(wndPtr
->wExtra
+ 2))
3029 & 0xffff0000)) : 0));
3033 /*********************************************************************
3036 * Reallocate the memory pointed to by the handle.
3039 unsigned int EDIT_HeapReAlloc(HWND hwnd
, unsigned int handle
, int bytes
)
3041 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3043 return ((unsigned int)HEAP_ReAlloc((MDESC
**)
3044 *(LONG
*)(wndPtr
->wExtra
+ 2),
3045 EDIT_HeapAddr(hwnd
, handle
),
3046 bytes
, GMEM_MOVEABLE
) & 0xffff);
3050 /*********************************************************************
3053 * Frees the memory pointed to by the handle.
3056 void EDIT_HeapFree(HWND hwnd
, unsigned int handle
)
3058 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3060 HEAP_Free((MDESC
**)*(LONG
*)(wndPtr
->wExtra
+ 2),
3061 EDIT_HeapAddr(hwnd
, handle
));
3065 /*********************************************************************
3068 * Return the size of the given object on the local heap.
3071 unsigned int EDIT_HeapSize(HWND hwnd
, unsigned int handle
)
3073 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3075 return HEAP_LocalSize((MDESC
**)*(LONG
*)(wndPtr
->wExtra
+ 2), handle
);
3079 /*********************************************************************
3080 * EM_SETHANDLE message function
3083 void EDIT_SetHandleMsg(HWND hwnd
, WORD wParam
)
3086 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3088 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
3093 es
->MaxTextLen
= EDIT_HeapSize(hwnd
, es
->hText
);
3095 es
->wtop
= es
->wleft
= 0;
3096 es
->CurrLine
= es
->CurrCol
= 0;
3097 es
->WndRow
= es
->WndCol
= 0;
3098 es
->TextChanged
= FALSE
;
3100 es
->SelBegLine
= es
->SelBegCol
= 0;
3101 es
->SelEndLine
= es
->SelEndCol
= 0;
3103 es
->PaintBkgd
= TRUE
;
3104 InvalidateRect(hwnd
, NULL
, TRUE
);
3110 /*********************************************************************
3111 * EM_SETTABSTOPS message function
3114 LONG
EDIT_SetTabStopsMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
3116 unsigned short *tabstops
;
3117 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3119 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
3121 es
->NumTabStops
= wParam
;
3123 es
->hTabStops
= EDIT_HeapReAlloc(hwnd
, es
->hTabStops
, 1);
3124 else if (wParam
== 1)
3126 es
->hTabStops
= EDIT_HeapReAlloc(hwnd
, es
->hTabStops
, 1);
3127 tabstops
= (unsigned short *)EDIT_HeapAddr(hwnd
, es
->hTabStops
);
3128 *tabstops
= (unsigned short)lParam
;
3132 es
->hTabStops
= EDIT_HeapReAlloc(hwnd
, es
->hTabStops
, wParam
);
3133 tabstops
= (unsigned short *)EDIT_HeapAddr(hwnd
, es
->hTabStops
);
3134 memcpy(tabstops
, (unsigned short *)lParam
, wParam
);
3140 /*********************************************************************
3144 void swap(int *a
, int *b
)