4 * Copyright David W. Metcalfe, 1994
9 static char Copyright
[] = "Copyright David W. Metcalfe, 1994";
20 /* #define DEBUG_EDIT /* */
22 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
23 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
24 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
26 #define MAXTEXTLEN 30000 /* 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 */
36 int wlines
; /* number of lines of text */
37 int wtop
; /* top line that is displayed */
38 int wleft
; /* left pixel that is displayed */
39 unsigned int textlen
; /* text buffer length */
40 int textwidth
; /* width of longest line in pixels */
41 RECT fmtrc
; /* rectangle in which to format text */
42 int txtht
; /* height of text line in pixels */
43 HANDLE hText
; /* handle to text buffer */
44 HANDLE hCharWidths
; /* widths of chars in font */
45 HANDLE hTextPtrs
; /* list of line offsets */
46 HANDLE hBlankLine
; /* to fill blank lines quickly */
47 int CurrCol
; /* current column */
48 int CurrLine
; /* current line */
49 int WndCol
; /* current window column */
50 int WndRow
; /* current window row */
51 BOOL TextChanged
; /* TRUE if text has changed */
52 BOOL PaintBkgd
; /* paint control background */
53 unsigned int MaxTextLen
; /* maximum text buffer length */
54 int SelBegLine
; /* beginning line of selection */
55 int SelBegCol
; /* beginning column of selection */
56 int SelEndLine
; /* ending line of selection */
57 int SelEndCol
; /* ending column of selection */
58 HFONT hFont
; /* handle of current font (if not default) */
59 HANDLE hDeletedText
; /* handle to deleted txet buffer for undo */
60 int DeletedLength
; /* length of deleted text */
61 int DeletedCurrLine
; /* starting line from which text was deleted */
62 int DeletedCurrCol
; /* starting col from which text was deleted */
63 int NumTabStops
; /* number of tab stops in buffer hTabStops */
64 HANDLE hTabStops
; /* handle of tab stops buffer */
68 #define ClientWidth(wndPtr) (wndPtr->rectClient.right - \
69 wndPtr->rectClient.left)
70 #define ClientHeight(wndPtr, es) ((wndPtr->rectClient.bottom - \
71 wndPtr->rectClient.top) / es->txtht)
72 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
74 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
75 #define SelMarked(es) (es->SelBegLine != 0 || es->SelBegCol != 0 || \
76 es->SelEndLine != 0 || es->SelEndCol != 0)
77 #define ROUNDUP(numer, denom) (((numer) % (denom)) \
78 ? ((((numer) + (denom)) / (denom)) * (denom)) \
81 /* macros to access window styles */
82 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
83 #define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
84 #define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
85 #define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
86 #define IsHScrollBar() (wndPtr->dwStyle & WS_HSCROLL)
88 /* internal variables */
89 static BOOL TextMarking
; /* TRUE if text marking in progress */
90 static BOOL ButtonDown
; /* TRUE if left mouse button down */
91 static int ButtonRow
; /* row in text buffer when button pressed */
92 static int ButtonCol
; /* col in text buffer when button pressed */
93 static BOOL Print
= FALSE
;
96 LONG
EditWndProc(HWND hWnd
, WORD uMsg
, WORD wParam
, LONG lParam
);
97 long EDIT_NCCreateMsg(HWND hwnd
, LONG lParam
);
98 long EDIT_CreateMsg(HWND hwnd
, LONG lParam
);
99 void EDIT_ClearTextPointers(HWND hwnd
);
100 void EDIT_BuildTextPointers(HWND hwnd
);
101 void EDIT_ModTextPointers(HWND hwnd
, int lineno
, int var
);
102 void EDIT_PaintMsg(HWND hwnd
);
103 HANDLE
EDIT_GetTextLine(HWND hwnd
, int selection
);
104 char *EDIT_TextLine(HWND hwnd
, int sel
);
105 int EDIT_StrLength(HWND hwnd
, char *str
, int len
, int pcol
);
106 int EDIT_LineLength(HWND hwnd
, int num
);
107 void EDIT_WriteTextLine(HWND hwnd
, RECT
*rc
, int y
);
108 void EDIT_WriteText(HWND hwnd
, char *lp
, int off
, int len
, int row
,
109 int col
, RECT
*rc
, BOOL blank
, BOOL reverse
);
110 HANDLE
EDIT_GetStr(HWND hwnd
, char *lp
, int off
, int len
, int *diff
);
111 void EDIT_CharMsg(HWND hwnd
, WORD wParam
);
112 void EDIT_KeyTyped(HWND hwnd
, short ch
);
113 int EDIT_CharWidth(HWND hwnd
, short ch
, int pcol
);
114 int EDIT_GetNextTabStop(HWND hwnd
, int pcol
);
115 void EDIT_Forward(HWND hwnd
);
116 void EDIT_Downward(HWND hwnd
);
117 void EDIT_Upward(HWND hwnd
);
118 void EDIT_Backward(HWND hwnd
);
119 void EDIT_End(HWND hwnd
);
120 void EDIT_Home(HWND hwnd
);
121 void EDIT_StickEnd(HWND hwnd
);
122 void EDIT_KeyDownMsg(HWND hwnd
, WORD wParam
);
123 void EDIT_KeyHScroll(HWND hwnd
, WORD opt
);
124 void EDIT_KeyVScrollLine(HWND hwnd
, WORD opt
);
125 void EDIT_KeyVScrollPage(HWND hwnd
, WORD opt
);
126 void EDIT_KeyVScrollDoc(HWND hwnd
, WORD opt
);
127 int EDIT_ComputeVScrollPos(HWND hwnd
);
128 int EDIT_ComputeHScrollPos(HWND hwnd
);
129 void EDIT_DelKey(HWND hwnd
);
130 void EDIT_VScrollMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
131 void EDIT_VScrollLine(HWND hwnd
, WORD opt
);
132 void EDIT_VScrollPage(HWND hwnd
, WORD opt
);
133 void EDIT_HScrollMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
134 void EDIT_SizeMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
135 void EDIT_LButtonDownMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
136 void EDIT_MouseMoveMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
137 int EDIT_PixelToChar(HWND hwnd
, int row
, int *pixel
);
138 LONG
EDIT_SetTextMsg(HWND hwnd
, LONG lParam
);
139 void EDIT_ClearText(HWND hwnd
);
140 void EDIT_SetSelMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
141 void EDIT_GetLineCol(HWND hwnd
, int off
, int *line
, int *col
);
142 void EDIT_DeleteSel(HWND hwnd
);
143 void EDIT_ClearSel(HWND hwnd
);
144 int EDIT_TextLineNumber(HWND hwnd
, char *lp
);
145 void EDIT_SetAnchor(HWND hwnd
, int row
, int col
);
146 void EDIT_ExtendSel(HWND hwnd
, int x
, int y
);
147 void EDIT_WriteSel(HWND hwnd
, int y
, int start
, int end
);
148 void EDIT_StopMarking(HWND hwnd
);
149 LONG
EDIT_GetLineMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
150 LONG
EDIT_GetSelMsg(HWND hwnd
);
151 void EDIT_ReplaceSel(HWND hwnd
, LONG lParam
);
152 void EDIT_InsertText(HWND hwnd
, char *str
, int len
);
153 LONG
EDIT_LineFromCharMsg(HWND hwnd
, WORD wParam
);
154 LONG
EDIT_LineIndexMsg(HWND hwnd
, WORD wParam
);
155 LONG
EDIT_LineLengthMsg(HWND hwnd
, WORD wParam
);
156 void EDIT_SetFont(HWND hwnd
, WORD wParam
, LONG lParam
);
157 void EDIT_SaveDeletedText(HWND hwnd
, char *deltext
, int len
, int line
,
159 void EDIT_ClearDeletedText(HWND hwnd
);
160 LONG
EDIT_UndoMsg(HWND hwnd
);
161 unsigned int EDIT_HeapAlloc(HWND hwnd
, int bytes
);
162 void *EDIT_HeapAddr(HWND hwnd
, unsigned int handle
);
163 unsigned int EDIT_HeapReAlloc(HWND hwnd
, unsigned int handle
, int bytes
);
164 void EDIT_HeapFree(HWND hwnd
, unsigned int handle
);
165 unsigned int EDIT_HeapSize(HWND hwnd
, unsigned int handle
);
166 void EDIT_SetHandleMsg(HWND hwnd
, WORD wParam
);
167 LONG
EDIT_SetTabStopsMsg(HWND hwnd
, WORD wParam
, LONG lParam
);
168 void EDIT_CopyToClipboard(HWND hwnd
);
169 void EDIT_PasteMsg(HWND hwnd
);
170 void swap(int *a
, int *b
);
173 LONG
EditWndProc(HWND hwnd
, WORD uMsg
, WORD wParam
, LONG lParam
)
179 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
181 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
185 lResult
= es
->hDeletedText
;
188 case EM_EMPTYUNDOBUFFER
:
189 EDIT_ClearDeletedText(hwnd
);
193 printf("edit: EM_FMTLINES message received\n");
200 case EM_GETFIRSTVISIBLELINE
:
210 lResult
= EDIT_GetLineMsg(hwnd
, wParam
, lParam
);
215 case EM_GETLINECOUNT
:
217 lResult
= es
->wlines
;
223 lResult
= es
->TextChanged
;
226 case EM_GETPASSWORDCHAR
:
227 printf("edit: cannot process EM_GETPASSWORDCHAR message\n");
231 GetWindowRect(hwnd
, (LPRECT
)lParam
);
235 lResult
= EDIT_GetSelMsg(hwnd
);
238 case EM_GETWORDBREAKPROC
:
239 printf("edit: cannot process EM_GETWORDBREAKPROC message\n");
244 es
->MaxTextLen
= wParam
;
245 else if (IsMultiLine())
246 es
->MaxTextLen
= 65535;
248 es
->MaxTextLen
= 32767;
251 case EM_LINEFROMCHAR
:
252 lResult
= EDIT_LineFromCharMsg(hwnd
, wParam
);
257 lResult
= EDIT_LineIndexMsg(hwnd
, wParam
);
263 lResult
= EDIT_LineLengthMsg(hwnd
, wParam
);
267 printf("edit: cannot process EM_LINESCROLL message\n");
272 EDIT_ReplaceSel(hwnd
, lParam
);
273 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
278 EDIT_SetHandleMsg(hwnd
, wParam
);
282 es
->TextChanged
= wParam
;
285 case EM_SETPASSWORDCHAR
:
286 printf("edit: cannot process EM_SETPASSWORDCHAR message\n");
290 printf("edit: cannot process EM_SETREADONLY message\n");
295 printf("edit: cannot process EM_SETRECT(NP) message\n");
300 EDIT_SetSelMsg(hwnd
, wParam
, lParam
);
301 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
306 lResult
= EDIT_SetTabStopsMsg(hwnd
, wParam
, lParam
);
309 case EM_SETWORDBREAKPROC
:
310 printf("edit: cannot process EM_SETWORDBREAKPROC message\n");
315 lResult
= EDIT_UndoMsg(hwnd
);
316 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
321 EDIT_CharMsg(hwnd
, wParam
);
325 EDIT_CopyToClipboard(hwnd
);
330 lResult
= EDIT_CreateMsg(hwnd
, lParam
);
334 EDIT_CopyToClipboard(hwnd
);
335 EDIT_DeleteSel(hwnd
);
339 EDIT_HeapFree(hwnd
, es
->hTextPtrs
);
340 EDIT_HeapFree(hwnd
, es
->hCharWidths
);
341 EDIT_HeapFree(hwnd
, es
->hText
);
342 EDIT_HeapFree(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
346 InvalidateRect(hwnd
, NULL
, FALSE
);
350 textPtr
= EDIT_HeapAddr(hwnd
, es
->hText
);
351 if ((int)wParam
> (len
= strlen(textPtr
)))
353 strcpy((char *)lParam
, textPtr
);
354 lResult
= (DWORD
)len
;
360 case WM_GETTEXTLENGTH
:
361 textPtr
= EDIT_HeapAddr(hwnd
, es
->hText
);
362 lResult
= (DWORD
)strlen(textPtr
);
366 EDIT_HScrollMsg(hwnd
, wParam
, lParam
);
370 EDIT_KeyDownMsg(hwnd
, wParam
);
375 NOTIFY_PARENT(hwnd
, EN_KILLFOCUS
);
381 EDIT_LButtonDownMsg(hwnd
, wParam
, lParam
);
382 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
389 EDIT_StopMarking(hwnd
);
394 EDIT_MouseMoveMsg(hwnd
, wParam
, lParam
);
395 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
404 lResult
= EDIT_NCCreateMsg(hwnd
, lParam
);
416 CreateCaret(hwnd
, 0, 2, es
->txtht
);
417 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
419 NOTIFY_PARENT(hwnd
, EN_SETFOCUS
);
424 EDIT_SetFont(hwnd
, wParam
, lParam
);
425 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
430 EDIT_SetTextMsg(hwnd
, lParam
);
434 EDIT_SizeMsg(hwnd
, wParam
, lParam
);
439 EDIT_VScrollMsg(hwnd
, wParam
, lParam
);
443 lResult
= DefWindowProc(hwnd
, uMsg
, wParam
, lParam
);
451 /*********************************************************************
452 * WM_NCCREATE message function
455 long EDIT_NCCreateMsg(HWND hwnd
, LONG lParam
)
457 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)lParam
;
458 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
460 unsigned int *textPtrs
;
464 /* store pointer to local heap in window structure so that */
465 /* EDITSTATE structure itself can be stored on local heap */
466 (MDESC
**)*(LONG
*)(wndPtr
->wExtra
+ 2) =
467 &HEAP_LocalFindHeap(createStruct
->hInstance
)->free_list
;
469 /* allocate space for state variable structure */
470 (HANDLE
)(*(wndPtr
->wExtra
)) = EDIT_HeapAlloc(hwnd
, sizeof(EDITSTATE
));
471 es
= (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
472 es
->hTextPtrs
= EDIT_HeapAlloc(hwnd
, sizeof(int));
473 textPtrs
= (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
474 es
->hCharWidths
= EDIT_HeapAlloc(hwnd
, 256 * sizeof(short));
476 /* --- text buffer */
477 es
->MaxTextLen
= MAXTEXTLEN
+ 1;
478 if (!(createStruct
->lpszName
))
480 es
->textlen
= EditBufLen(wndPtr
) + 1;
481 es
->hText
= EDIT_HeapAlloc(hwnd
, EditBufLen(wndPtr
) + 2);
482 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
483 memset(text
, 0, es
->textlen
+ 2);
484 EDIT_ClearTextPointers(hwnd
);
488 if (strlen(createStruct
->lpszName
) < EditBufLen(wndPtr
))
490 es
->textlen
= EditBufLen(wndPtr
) + 1;
491 es
->hText
= EDIT_HeapAlloc(hwnd
, EditBufLen(wndPtr
) + 2);
492 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
493 strcpy(text
, createStruct
->lpszName
);
494 *(text
+ es
->textlen
) = '\0';
498 es
->hText
= EDIT_HeapAlloc(hwnd
,
499 strlen(createStruct
->lpszName
) + 2);
500 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
501 strcpy(text
, createStruct
->lpszName
);
502 es
->textlen
= strlen(createStruct
->lpszName
) + 1;
504 *(text
+ es
->textlen
+ 1) = '\0';
505 EDIT_BuildTextPointers(hwnd
);
508 if ((createStruct
->style
& WS_VSCROLL
) ||
509 (createStruct
->style
& WS_HSCROLL
)) NC_CreateScrollBars(hwnd
);
511 /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
512 /* the corresponding WM_* message is set */
513 if (createStruct
->style
& WS_VSCROLL
)
514 wndPtr
->dwStyle
|= ES_AUTOVSCROLL
;
515 if (createStruct
->style
& WS_HSCROLL
)
516 wndPtr
->dwStyle
|= ES_AUTOHSCROLL
;
518 /* remove the WS_CAPTION style if it has been set - this is really a */
519 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
520 if (wndPtr
->dwStyle
& WS_BORDER
&& wndPtr
->dwStyle
& WS_DLGFRAME
)
521 wndPtr
->dwStyle
^= WS_DLGFRAME
;
527 /*********************************************************************
528 * WM_CREATE message function
531 long EDIT_CreateMsg(HWND hwnd
, LONG lParam
)
534 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
536 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
542 /* initialize state variable structure */
543 /* --- char width array */
545 charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
546 memset(charWidths
, 0, 256 * sizeof(short));
547 GetCharWidth(hdc
, 0, 255, charWidths
);
549 /* --- other structure variables */
550 GetTextMetrics(hdc
, &tm
);
551 es
->txtht
= tm
.tmHeight
+ tm
.tmExternalLeading
;
553 es
->wtop
= es
->wleft
= 0;
554 es
->CurrCol
= es
->CurrLine
= 0;
555 es
->WndCol
= es
->WndRow
= 0;
556 es
->TextChanged
= FALSE
;
558 es
->SelBegLine
= es
->SelBegCol
= 0;
559 es
->SelEndLine
= es
->SelEndCol
= 0;
561 es
->hDeletedText
= 0;
562 es
->DeletedLength
= 0;
564 es
->hTabStops
= EDIT_HeapAlloc(hwnd
, sizeof(int));
566 /* allocate space for a line full of blanks to speed up */
568 es
->hBlankLine
= EDIT_HeapAlloc(hwnd
, (ClientWidth(wndPtr
) /
569 charWidths
[32]) + 2);
570 text
= EDIT_HeapAddr(hwnd
, es
->hBlankLine
);
571 memset(text
, ' ', (ClientWidth(wndPtr
) / charWidths
[32]) + 2);
573 /* set up text cursor for edit class */
574 CLASS_FindClassByName("EDIT", &classPtr
);
575 classPtr
->wc
.hCursor
= LoadCursor(0, IDC_IBEAM
);
577 /* paint background on first WM_PAINT */
578 es
->PaintBkgd
= TRUE
;
580 ReleaseDC(hwnd
, hdc
);
585 /*********************************************************************
586 * EDIT_ClearTextPointers
588 * Clear and initialize text line pointer array.
591 void EDIT_ClearTextPointers(HWND hwnd
)
593 unsigned int *textPtrs
;
594 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
596 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
598 es
->hTextPtrs
= EDIT_HeapReAlloc(hwnd
, es
->hTextPtrs
, sizeof(int));
599 textPtrs
= (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
604 /*********************************************************************
605 * EDIT_BuildTextPointers
607 * Build array of pointers to text lines.
610 #define INITLINES 100
612 void EDIT_BuildTextPointers(HWND hwnd
)
614 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
616 int incrs
= INITLINES
;
617 unsigned int off
, len
, temp
;
619 unsigned int *textPtrs
;
622 es
= (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
623 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
624 textPtrs
= (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
625 charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
627 es
->textwidth
= es
->wlines
= 0;
630 /* advance through text buffer */
633 /* increase size of text pointer array */
634 if (incrs
== INITLINES
)
637 es
->hTextPtrs
= EDIT_HeapReAlloc(hwnd
, es
->hTextPtrs
,
638 (es
->wlines
+ INITLINES
) * sizeof(int));
639 textPtrs
= (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
641 off
= (unsigned int)(cp
- text
); /* offset of beginning of line */
642 *(textPtrs
+ es
->wlines
) = off
;
647 /* advance through current line */
648 while (*cp
&& *cp
!= '\n')
650 len
+= EDIT_CharWidth(hwnd
, *cp
, len
);
651 /* width of line in pixels */
654 es
->textwidth
= max(es
->textwidth
, len
);
656 cp
++; /* skip '\n' */
659 off
= (unsigned int)(cp
- text
);
660 *(textPtrs
+ es
->wlines
) = off
;
664 /*********************************************************************
665 * EDIT_ModTextPointers
667 * Modify text pointers from a specified position.
670 void EDIT_ModTextPointers(HWND hwnd
, int lineno
, int var
)
672 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
674 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
675 unsigned int *textPtrs
=
676 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
678 while (lineno
< es
->wlines
)
679 *(textPtrs
+ lineno
++) += var
;
683 /*********************************************************************
684 * WM_PAINT message function
687 void EDIT_PaintMsg(HWND hwnd
)
693 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
695 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
697 hdc
= BeginPaint(hwnd
, &ps
);
701 printf("WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc
.left
, rc
.top
,
702 rc
.right
, rc
.bottom
);
706 FillWindow(GetParent(hwnd
), hwnd
, hdc
, CTLCOLOR_EDIT
);
708 for (y
= (rc
.top
/ es
->txtht
); y
<= (rc
.bottom
/ es
->txtht
); y
++)
710 if (y
< es
->wlines
- es
->wtop
)
711 EDIT_WriteTextLine(hwnd
, &rc
, y
+ es
->wtop
);
718 /*********************************************************************
721 * Get a copy of the text in the specified line.
724 HANDLE
EDIT_GetTextLine(HWND hwnd
, int selection
)
732 printf("GetTextLine %d\n", selection
);
734 cp
= cp1
= EDIT_TextLine(hwnd
, selection
);
735 /* advance through line */
736 while (*cp
&& *cp
!= '\n')
742 /* store selected line and return handle */
743 hLine
= EDIT_HeapAlloc(hwnd
, len
+ 6);
744 line
= (char *)EDIT_HeapAddr(hwnd
, hLine
);
745 memmove(line
, cp1
, len
);
751 /*********************************************************************
754 * Return a pointer to the text in the specified line.
757 char *EDIT_TextLine(HWND hwnd
, int sel
)
759 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
761 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
762 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
763 unsigned int *textPtrs
=
764 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
766 return (text
+ *(textPtrs
+ sel
));
770 /*********************************************************************
773 * Return length of string _str_ of length _len_ characters in pixels.
774 * The current column offset in pixels _pcol_ is required to calculate
775 * the width of a tab.
778 int EDIT_StrLength(HWND hwnd
, char *str
, int len
, int pcol
)
781 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
783 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
785 for (i
= 0; i
< len
; i
++)
786 plen
+= EDIT_CharWidth(hwnd
, *(str
+ i
), pcol
+ plen
);
789 printf("EDIT_StrLength: returning %d\n", plen
);
795 /*********************************************************************
798 * Return length of line _num_ in characters.
801 int EDIT_LineLength(HWND hwnd
, int num
)
803 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
805 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
806 char *cp
= EDIT_TextLine(hwnd
, num
);
809 cp1
= strchr(cp
, '\n');
810 return cp1
? (int)(cp1
- cp
) : strlen(cp
);
814 /*********************************************************************
817 * Write the line of text at offset _y_ in text buffer to a window.
820 void EDIT_WriteTextLine(HWND hwnd
, RECT
*rect
, int y
)
823 unsigned char line
[200];
828 int sbl
, sel
, sbc
, sec
;
831 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
833 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
835 /* initialize rectangle if NULL, else copy */
839 GetClientRect(hwnd
, &rc
);
842 printf("WriteTextLine %d\n", y
);
845 /* make sure y is inside the window */
846 if (y
< es
->wtop
|| y
> (es
->wtop
+ ClientHeight(wndPtr
, es
)))
849 printf("EDIT_WriteTextLine: y (%d) is not a displayed line\n", y
);
854 /* make sure rectangle is within window */
855 if (rc
.left
>= ClientWidth(wndPtr
) - 1)
858 printf("EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
866 printf("EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
871 if (y
- es
->wtop
< (rc
.top
/ es
->txtht
) ||
872 y
- es
->wtop
> (rc
.bottom
/ es
->txtht
))
875 printf("EDIT_WriteTextLine: y (%d) is outside window\n", y
);
880 /* get the text and length of line */
881 if ((hLine
= EDIT_GetTextLine(hwnd
, y
)) == 0)
883 lp
= (unsigned char *)EDIT_HeapAddr(hwnd
, hLine
);
884 lnlen
= EDIT_StrLength(hwnd
, lp
, strlen(lp
), 0);
887 /* build the line to display */
888 if (lnlen
< es
->wleft
)
896 lnlen
= lnlen1
- off
;
897 len
= min(lnlen
, rc
.right
- rc
.left
);
902 sbl
= es
->SelBegLine
;
903 sel
= es
->SelEndLine
;
907 /* put lowest marker first */
913 if (sbl
== sel
&& sbc
> sec
)
916 if (y
< sbl
|| y
> sel
)
917 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
919 else if (y
> sbl
&& y
< sel
)
920 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
924 col
= EDIT_StrLength(hwnd
, lp
, sbc
, 0);
925 if (col
> (es
->wleft
+ rc
.left
))
927 len
= min(col
- off
, rc
.right
- off
);
928 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
929 rc
.left
, &rc
, FALSE
, FALSE
);
934 col
= EDIT_StrLength(hwnd
, lp
, sec
, 0);
935 if (col
< (es
->wleft
+ rc
.right
))
937 len
= min(col
- off
, rc
.right
- off
);
938 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
939 off
- es
->wleft
, &rc
, FALSE
, TRUE
);
941 len
= min(lnlen
- off
, rc
.right
- off
);
942 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
943 off
- es
->wleft
, &rc
, TRUE
, FALSE
);
947 len
= min(lnlen
- off
, rc
.right
- off
);
948 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
949 off
- es
->wleft
, &rc
, TRUE
, TRUE
);
954 len
= min(lnlen
- off
, rc
.right
- off
);
955 if (col
< (es
->wleft
+ rc
.right
))
956 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
957 off
- es
->wleft
, &rc
, TRUE
, TRUE
);
962 col
= EDIT_StrLength(hwnd
, lp
, sec
, 0);
963 if (col
< (es
->wleft
+ rc
.right
))
965 len
= min(col
- off
, rc
.right
- off
);
966 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
967 off
- es
->wleft
, &rc
, FALSE
, TRUE
);
969 len
= min(lnlen
- off
, rc
.right
- off
);
970 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
971 off
- es
->wleft
, &rc
, TRUE
, FALSE
);
976 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
979 EDIT_HeapFree(hwnd
, hLine
);
983 /*********************************************************************
986 * Write text to a window
988 * off - offset in text line (in pixels)
989 * len - length from off (in pixels)
990 * row - line in window
991 * col - column in window
992 * rc - rectangle in which to display line
993 * blank - blank remainder of line?
994 * reverse - reverse color of line?
997 void EDIT_WriteText(HWND hwnd
, char *lp
, int off
, int len
, int row
,
998 int col
, RECT
*rc
, BOOL blank
, BOOL reverse
)
1002 char *str
, *cp
, *cp1
;
1003 int diff
, num_spaces
, tabwidth
, scol
;
1005 COLORREF oldTextColor
, oldBkgdColor
;
1007 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1009 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1010 short *charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
1011 char *blanks
= (char *)EDIT_HeapAddr(hwnd
, es
->hBlankLine
);
1014 printf("EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp
, off
, len
, row
, col
, reverse
);
1018 hStr
= EDIT_GetStr(hwnd
, lp
, off
, len
, &diff
);
1019 str
= (char *)EDIT_HeapAddr(hwnd
, hStr
);
1020 hrgnClip
= CreateRectRgnIndirect(rc
);
1021 SelectClipRgn(hdc
, hrgnClip
);
1024 oldfont
= (HFONT
)SelectObject(hdc
, (HANDLE
)es
->hFont
);
1026 SendMessage(GetParent(hwnd
), WM_CTLCOLOR
, (WORD
)hdc
,
1027 MAKELPARAM(hwnd
, CTLCOLOR_EDIT
));
1031 oldBkgdColor
= GetBkColor(hdc
);
1032 oldTextColor
= GetTextColor(hdc
);
1033 SetBkColor(hdc
, oldTextColor
);
1034 SetTextColor(hdc
, oldBkgdColor
);
1037 if (strlen(blanks
) < (ClientWidth(wndPtr
) / charWidths
[32]) + 2)
1039 es
->hBlankLine
= EDIT_HeapReAlloc(hwnd
, es
->hBlankLine
,
1040 (ClientWidth(wndPtr
) / charWidths
[32]) + 2);
1041 blanks
= EDIT_HeapAddr(hwnd
, es
->hBlankLine
);
1042 memset(blanks
, ' ', (ClientWidth(wndPtr
) / charWidths
[32]) + 2);
1045 if (!(cp
= strchr(str
, VK_TAB
)))
1046 TextOut(hdc
, col
- diff
, row
* es
->txtht
, str
, strlen(str
));
1049 TextOut(hdc
, col
- diff
, row
* es
->txtht
, str
, (int)(cp
- str
));
1050 scol
= EDIT_StrLength(hwnd
, str
, (int)(cp
- str
), 0);
1051 tabwidth
= EDIT_CharWidth(hwnd
, VK_TAB
, scol
);
1052 num_spaces
= tabwidth
/ charWidths
[32] + 1;
1053 TextOut(hdc
, scol
, row
* es
->txtht
, blanks
, num_spaces
);
1057 while (cp1
= strchr(cp
, VK_TAB
))
1059 TextOut(hdc
, scol
, row
* es
->txtht
, cp
, (int)(cp1
- cp
));
1060 scol
+= EDIT_StrLength(hwnd
, cp
, (int)(cp1
- cp
), scol
);
1061 tabwidth
= EDIT_CharWidth(hwnd
, VK_TAB
, scol
);
1062 num_spaces
= tabwidth
/ charWidths
[32] + 1;
1063 TextOut(hdc
, scol
, row
* es
->txtht
, blanks
, num_spaces
);
1068 TextOut(hdc
, scol
, row
* es
->txtht
, cp
, strlen(cp
));
1073 SetBkColor(hdc
, oldBkgdColor
);
1074 SetTextColor(hdc
, oldTextColor
);
1077 /* blank out remainder of line if appropriate */
1080 if ((rc
->right
- col
) > len
)
1082 num_spaces
= (rc
->right
- col
- len
) / charWidths
[32];
1083 TextOut(hdc
, col
+ len
, row
* es
->txtht
, blanks
, num_spaces
);
1088 SelectObject(hdc
, (HANDLE
)oldfont
);
1090 EDIT_HeapFree(hwnd
, hStr
);
1091 ReleaseDC(hwnd
, hdc
);
1095 /*********************************************************************
1098 * Return sub-string starting at pixel _off_ of length _len_ pixels.
1099 * If _off_ is part way through a character, the negative offset of
1100 * the beginning of the character is returned in _diff_, else _diff_
1104 HANDLE
EDIT_GetStr(HWND hwnd
, char *lp
, int off
, int len
, int *diff
)
1108 int ch
= 0, i
= 0, j
, s_i
;
1110 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1112 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1115 printf("EDIT_GetStr %s %d %d\n", lp
, off
, len
);
1121 i
+= EDIT_CharWidth(hwnd
, *(lp
+ ch
), i
);
1125 /* if stepped past _off_, go back a character */
1134 while (i
< len
+ off
)
1136 i
+= EDIT_CharWidth(hwnd
, *(lp
+ ch
), i
);
1140 hStr
= EDIT_HeapAlloc(hwnd
, ch
- ch1
+ 3);
1141 str
= (char *)EDIT_HeapAddr(hwnd
, hStr
);
1142 for (i
= ch1
, j
= 0; i
< ch
; i
++, j
++)
1146 printf("EDIT_GetStr: returning %s\n", str
);
1152 /*********************************************************************
1153 * WM_CHAR message function
1156 void EDIT_CharMsg(HWND hwnd
, WORD wParam
)
1158 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1160 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1163 printf("EDIT_CharMsg: wParam=%c\n", (char)wParam
);
1173 EDIT_KeyTyped(hwnd
, wParam
);
1179 EDIT_KeyTyped(hwnd
, wParam
);
1183 if (wParam
>= 20 && wParam
<= 126)
1184 EDIT_KeyTyped(hwnd
, wParam
);
1190 /*********************************************************************
1193 * Process keystrokes that produce displayable characters.
1196 void EDIT_KeyTyped(HWND hwnd
, short ch
)
1198 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1200 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1201 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1202 char *currchar
= CurrChar
;
1204 BOOL FullPaint
= FALSE
;
1207 printf("EDIT_KeyTyped: ch=%c\n", (char)ch
);
1210 /* delete selected text (if any) */
1212 EDIT_DeleteSel(hwnd
);
1214 /* test for typing at end of maximum buffer size */
1215 if (currchar
== text
+ es
->MaxTextLen
)
1217 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1221 if (*currchar
== '\0' && IsMultiLine())
1223 /* insert a newline at end of text */
1225 *(currchar
+ 1) = '\0';
1226 EDIT_BuildTextPointers(hwnd
);
1229 /* insert the typed character */
1230 if (text
[es
->textlen
- 1] != '\0')
1232 /* current text buffer is full */
1233 if (es
->textlen
== es
->MaxTextLen
)
1235 /* text buffer is at maximum size */
1236 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1240 /* increase the text buffer size */
1241 es
->textlen
+= GROWLENGTH
;
1242 /* but not above maximum size */
1243 if (es
->textlen
> es
->MaxTextLen
)
1244 es
->textlen
= es
->MaxTextLen
;
1245 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, es
->textlen
+ 2);
1247 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1248 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1249 text
[es
->textlen
- 1] = '\0';
1250 currchar
= CurrChar
;
1252 /* make space for new character and put char in buffer */
1253 memmove(currchar
+ 1, currchar
, strlen(currchar
) + 1);
1255 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, 1);
1256 es
->TextChanged
= TRUE
;
1257 NOTIFY_PARENT(hwnd
, EN_UPDATE
);
1259 /* re-adjust textwidth, if necessary, and redraw line */
1261 if (IsMultiLine() && es
->wlines
> 1)
1263 es
->textwidth
= max(es
->textwidth
,
1264 EDIT_StrLength(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
1265 (int)(EDIT_TextLine(hwnd
, es
->CurrLine
+ 1) -
1266 EDIT_TextLine(hwnd
, es
->CurrLine
)), 0));
1269 es
->textwidth
= max(es
->textwidth
,
1270 EDIT_StrLength(hwnd
, text
, strlen(text
), 0));
1271 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ es
->WndRow
);
1278 EDIT_BuildTextPointers(hwnd
);
1282 /* invalidate rest of window */
1283 GetClientRect(hwnd
, &rc
);
1285 rc
.top
= es
->WndRow
* es
->txtht
;
1286 InvalidateRect(hwnd
, &rc
, FALSE
);
1288 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1291 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1295 /* test end of window */
1296 if (es
->WndCol
>= ClientWidth(wndPtr
) -
1297 EDIT_CharWidth(hwnd
, ch
, es
->WndCol
+ es
->wleft
))
1299 /* TODO:- Word wrap to be handled here */
1301 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1302 EDIT_KeyHScroll(hwnd
, SB_LINEDOWN
);
1304 es
->WndCol
+= EDIT_CharWidth(hwnd
, ch
, es
->WndCol
+ es
->wleft
);
1306 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1308 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1312 /*********************************************************************
1315 * Return the width of the given character in pixels.
1316 * The current column offset in pixels _pcol_ is required to calculate
1317 * the width of a tab.
1320 int EDIT_CharWidth(HWND hwnd
, short ch
, int pcol
)
1322 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1324 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1325 short *charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
1328 return (charWidths
[ch
]);
1330 return (EDIT_GetNextTabStop(hwnd
, pcol
) - pcol
);
1334 /*********************************************************************
1335 * EDIT_GetNextTabStop
1337 * Return the next tab stop beyond _pcol_.
1340 int EDIT_GetNextTabStop(HWND hwnd
, int pcol
)
1343 int baseUnitWidth
= LOWORD(GetDialogBaseUnits());
1344 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1346 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1347 unsigned short *tabstops
= EDIT_HeapAddr(hwnd
, es
->hTabStops
);
1349 if (es
->NumTabStops
== 0)
1350 return ROUNDUP(pcol
, 8 * baseUnitWidth
);
1351 else if (es
->NumTabStops
== 1)
1352 return ROUNDUP(pcol
, *tabstops
* baseUnitWidth
/ 4);
1355 for (i
= 0; i
< es
->NumTabStops
; i
++)
1357 if (*(tabstops
+ i
) * baseUnitWidth
/ 4 >= pcol
)
1358 return (*(tabstops
+ i
) * baseUnitWidth
/ 4);
1365 /*********************************************************************
1368 * Cursor right key: move right one character position.
1371 void EDIT_Forward(HWND hwnd
)
1373 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1375 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1376 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1378 if (*CurrChar
== '\0')
1381 if (*CurrChar
== '\n')
1384 EDIT_Downward(hwnd
);
1388 es
->WndCol
+= EDIT_CharWidth(hwnd
, *CurrChar
, es
->WndCol
+ es
->wleft
);
1390 if (es
->WndCol
>= ClientWidth(wndPtr
))
1391 EDIT_KeyHScroll(hwnd
, SB_LINEDOWN
);
1397 /*********************************************************************
1400 * Cursor down key: move down one line.
1403 void EDIT_Downward(HWND hwnd
)
1405 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1407 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1410 printf("EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n", es
->WndRow
, es
->wtop
, es
->wlines
);
1413 if (IsMultiLine() && (es
->WndRow
+ es
->wtop
+ 1 < es
->wlines
))
1416 if (es
->WndRow
== ClientHeight(wndPtr
, es
) - 1)
1419 EDIT_KeyVScrollLine(hwnd
, SB_LINEDOWN
);
1423 EDIT_StickEnd(hwnd
);
1428 /*********************************************************************
1431 * Cursor up key: move up one line.
1434 void EDIT_Upward(HWND hwnd
)
1436 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1438 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1440 if (IsMultiLine() && es
->CurrLine
!= 0)
1443 if (es
->WndRow
== 0)
1446 EDIT_KeyVScrollLine(hwnd
, SB_LINEUP
);
1450 EDIT_StickEnd(hwnd
);
1455 /*********************************************************************
1458 * Cursor left key: move left one character position.
1461 void EDIT_Backward(HWND hwnd
)
1463 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1465 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1466 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1471 if (*CurrChar
== VK_TAB
)
1472 es
->WndCol
-= EDIT_CharWidth(hwnd
, *CurrChar
,
1473 EDIT_StrLength(hwnd
,
1474 EDIT_TextLine(hwnd
, es
->CurrLine
),
1477 es
->WndCol
-= EDIT_CharWidth(hwnd
, *CurrChar
, 0);
1479 EDIT_KeyHScroll(hwnd
, SB_LINEUP
);
1481 else if (IsMultiLine() && es
->CurrLine
!= 0)
1489 /*********************************************************************
1492 * End key: move to end of line.
1495 void EDIT_End(HWND hwnd
)
1498 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1500 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1501 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
1503 while (*CurrChar
&& *CurrChar
!= '\n')
1505 es
->WndCol
+= EDIT_CharWidth(hwnd
, *CurrChar
, es
->WndCol
+ es
->wleft
);
1509 if (es
->WndCol
>= ClientWidth(wndPtr
))
1511 es
->wleft
= es
->WndCol
- ClientWidth(wndPtr
) + HSCROLLDIM
;
1512 es
->WndCol
-= es
->wleft
;
1513 InvalidateRect(hwnd
, NULL
, FALSE
);
1519 /*********************************************************************
1522 * Home key: move to beginning of line.
1525 void EDIT_Home(HWND hwnd
)
1528 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1530 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1532 es
->CurrCol
= es
->WndCol
= 0;
1536 InvalidateRect(hwnd
, NULL
, FALSE
);
1542 /*********************************************************************
1545 * Stick the cursor to the end of the line.
1548 void EDIT_StickEnd(HWND hwnd
)
1550 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1552 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1553 int len
= EDIT_LineLength(hwnd
, es
->CurrLine
);
1554 char *cp
= EDIT_TextLine(hwnd
, es
->CurrLine
);
1557 es
->CurrCol
= min(len
, es
->CurrCol
);
1558 es
->WndCol
= min(EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
, es
->WndCol
);
1559 currpel
= EDIT_StrLength(hwnd
, cp
, es
->CurrCol
, 0);
1561 if (es
->wleft
> currpel
)
1563 es
->wleft
= max(0, currpel
- 20);
1564 es
->WndCol
= currpel
- es
->wleft
;
1567 else if (currpel
- es
->wleft
>= ClientWidth(wndPtr
))
1569 es
->wleft
= currpel
- (ClientWidth(wndPtr
) - 5);
1570 es
->WndCol
= currpel
- es
->wleft
;
1576 /*********************************************************************
1577 * WM_KEYDOWN message function
1580 void EDIT_KeyDownMsg(HWND hwnd
, WORD wParam
)
1582 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1584 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1587 printf("EDIT_KeyDownMsg: key=%x\n", wParam
);
1595 EDIT_ClearSel(hwnd
);
1599 EDIT_Backward(hwnd
);
1604 EDIT_ClearSel(hwnd
);
1606 EDIT_Downward(hwnd
);
1613 EDIT_ClearSel(hwnd
);
1619 EDIT_ClearSel(hwnd
);
1620 EDIT_Backward(hwnd
);
1625 EDIT_ClearSel(hwnd
);
1631 EDIT_ClearSel(hwnd
);
1639 EDIT_ClearSel(hwnd
);
1640 EDIT_KeyVScrollPage(hwnd
, SB_PAGEUP
);
1648 EDIT_ClearSel(hwnd
);
1649 EDIT_KeyVScrollPage(hwnd
, SB_PAGEDOWN
);
1655 EDIT_DeleteSel(hwnd
);
1658 if (es
->CurrCol
== 0 && es
->CurrLine
== 0)
1660 EDIT_Backward(hwnd
);
1667 EDIT_DeleteSel(hwnd
);
1673 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1678 /*********************************************************************
1681 * Scroll text horizontally using cursor keys.
1684 void EDIT_KeyHScroll(HWND hwnd
, WORD opt
)
1688 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1690 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1692 if (opt
== SB_LINEDOWN
)
1694 es
->wleft
+= HSCROLLDIM
;
1695 es
->WndCol
-= HSCROLLDIM
;
1701 if (es
->wleft
- HSCROLLDIM
< 0)
1703 es
->WndCol
+= es
->wleft
;
1708 es
->wleft
-= HSCROLLDIM
;
1709 es
->WndCol
+= HSCROLLDIM
;
1713 InvalidateRect(hwnd
, NULL
, FALSE
);
1718 hscrollpos
= EDIT_ComputeHScrollPos(hwnd
);
1719 SetScrollPos(hwnd
, SB_HORZ
, hscrollpos
, TRUE
);
1724 /*********************************************************************
1725 * EDIT_KeyVScrollLine
1727 * Scroll text vertically by one line using keyboard.
1730 void EDIT_KeyVScrollLine(HWND hwnd
, WORD opt
)
1734 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1736 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1741 if (opt
== SB_LINEDOWN
)
1743 /* move down one line */
1744 if (es
->wtop
+ ClientHeight(wndPtr
, es
) >= es
->wlines
)
1750 /* move up one line */
1756 if (IsWindowVisible(hwnd
))
1758 /* adjust client bottom to nearest whole line */
1759 GetClientRect(hwnd
, &rc
);
1760 rc
.bottom
= (rc
.bottom
/ es
->txtht
) * es
->txtht
;
1762 if (opt
== SB_LINEUP
)
1764 /* move up one line (scroll window down) */
1765 ScrollWindow(hwnd
, 0, es
->txtht
, &rc
, &rc
);
1766 /* write top line */
1767 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
);
1772 /* move down one line (scroll window up) */
1773 ScrollWindow(hwnd
, 0, -(es
->txtht
), &rc
, &rc
);
1774 /* write bottom line */
1775 y
= (((rc
.bottom
- rc
.top
) / es
->txtht
) - 1);
1776 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ y
);
1781 /* reset the vertical scroll bar */
1784 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1785 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1790 /*********************************************************************
1791 * EDIT_KeyVScrollPage
1793 * Scroll text vertically by one page using keyboard.
1796 void EDIT_KeyVScrollPage(HWND hwnd
, WORD opt
)
1800 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1802 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1806 if (opt
== SB_PAGEUP
)
1809 es
->wtop
-= ClientHeight(wndPtr
, es
);
1813 if (es
->wtop
+ ClientHeight(wndPtr
, es
) < es
->wlines
)
1815 es
->wtop
+= ClientHeight(wndPtr
, es
);
1816 if (es
->wtop
> es
->wlines
- ClientHeight(wndPtr
, es
))
1817 es
->wtop
= es
->wlines
- ClientHeight(wndPtr
, es
);
1823 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
1824 EDIT_StickEnd(hwnd
);
1825 InvalidateRect(hwnd
, NULL
, TRUE
);
1828 /* reset the vertical scroll bar */
1831 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1832 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1838 /*********************************************************************
1839 * EDIT_KeyVScrollDoc
1841 * Scroll text to top and bottom of document using keyboard.
1844 void EDIT_KeyVScrollDoc(HWND hwnd
, WORD opt
)
1848 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1850 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1856 es
->wtop
= es
->wleft
= 0;
1857 else if (es
->wtop
+ ClientHeight(wndPtr
, es
) < es
->wlines
)
1859 es
->wtop
= es
->wlines
- ClientHeight(wndPtr
, es
);
1863 es
->CurrLine
= es
->wlines
;
1864 es
->WndRow
= es
->wlines
- es
->wtop
;
1866 InvalidateRect(hwnd
, NULL
, TRUE
);
1869 /* reset the vertical scroll bar */
1872 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1873 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1878 /*********************************************************************
1879 * EDIT_ComputeVScrollPos
1881 * Compute the vertical scroll bar position from the window
1882 * position and text width.
1885 int EDIT_ComputeVScrollPos(HWND hwnd
)
1888 short minpos
, maxpos
;
1889 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1891 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1893 GetScrollRange(hwnd
, SB_VERT
, &minpos
, &maxpos
);
1895 if (es
->wlines
> ClientHeight(wndPtr
, es
))
1896 vscrollpos
= (double)(es
->wtop
) / (double)(es
->wlines
-
1897 ClientHeight(wndPtr
, es
)) * (maxpos
- minpos
);
1899 vscrollpos
= minpos
;
1905 /*********************************************************************
1906 * EDIT_ComputeHScrollPos
1908 * Compute the horizontal scroll bar position from the window
1909 * position and text width.
1912 int EDIT_ComputeHScrollPos(HWND hwnd
)
1915 short minpos
, maxpos
;
1916 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1918 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1920 GetScrollRange(hwnd
, SB_HORZ
, &minpos
, &maxpos
);
1922 if (es
->textwidth
> ClientWidth(wndPtr
))
1923 hscrollpos
= (double)(es
->wleft
) / (double)(es
->textwidth
-
1924 ClientWidth(wndPtr
)) * (maxpos
- minpos
);
1926 hscrollpos
= minpos
;
1932 /*********************************************************************
1935 * Delete character to right of cursor.
1938 void EDIT_DelKey(HWND hwnd
)
1941 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1943 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1944 char *currchar
= CurrChar
;
1945 BOOL repaint
= *currchar
== '\n';
1947 if (IsMultiLine() && *currchar
== '\n' && *(currchar
+ 1) == '\0')
1949 strcpy(currchar
, currchar
+ 1);
1950 NOTIFY_PARENT(hwnd
, EN_UPDATE
);
1954 EDIT_BuildTextPointers(hwnd
);
1955 GetClientRect(hwnd
, &rc
);
1956 rc
.top
= es
->WndRow
* es
->txtht
;
1957 InvalidateRect(hwnd
, &rc
, FALSE
);
1962 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, -1);
1963 EDIT_WriteTextLine(hwnd
, NULL
, es
->WndRow
+ es
->wtop
);
1966 es
->TextChanged
= TRUE
;
1967 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1970 /*********************************************************************
1971 * WM_VSCROLL message function
1974 void EDIT_VScrollMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
1976 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1978 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
1988 EDIT_VScrollLine(hwnd
, wParam
);
1993 EDIT_VScrollPage(hwnd
, wParam
);
1998 SetCaretPos(es
->WndCol
, es
->WndRow
);
2003 /*********************************************************************
2006 * Scroll text vertically by one line using scrollbars.
2009 void EDIT_VScrollLine(HWND hwnd
, WORD opt
)
2013 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2015 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2018 printf("EDIT_VScrollLine: direction=%d\n", opt
);
2021 if (opt
== SB_LINEDOWN
)
2023 /* move down one line */
2024 if (es
->wtop
+ ClientHeight(wndPtr
, es
) >= es
->wlines
)
2030 /* move up one line */
2036 if (IsWindowVisible(hwnd
))
2038 /* adjust client bottom to nearest whole line */
2039 GetClientRect(hwnd
, &rc
);
2040 rc
.bottom
= (rc
.bottom
/ es
->txtht
) * es
->txtht
;
2042 if (opt
== SB_LINEUP
)
2044 /* move up one line (scroll window down) */
2045 ScrollWindow(hwnd
, 0, es
->txtht
, &rc
, &rc
);
2046 /* write top line */
2047 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
);
2052 /* move down one line (scroll window up) */
2053 ScrollWindow(hwnd
, 0, -(es
->txtht
), &rc
, &rc
);
2054 /* write bottom line */
2055 y
= ((rc
.bottom
- rc
.top
/ es
->txtht
) - 1);
2056 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ y
);
2063 /*********************************************************************
2066 * Scroll text vertically by one page using keyboard.
2069 void EDIT_VScrollPage(HWND hwnd
, WORD opt
)
2073 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2075 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2077 if (opt
== SB_PAGEUP
)
2080 es
->wtop
-= ClientHeight(wndPtr
, es
);
2084 if (es
->wtop
+ ClientHeight(wndPtr
, es
) < es
->wlines
)
2086 es
->wtop
+= ClientHeight(wndPtr
, es
);
2087 if (es
->wtop
> es
->wlines
- ClientHeight(wndPtr
, es
))
2088 es
->wtop
= es
->wlines
- ClientHeight(wndPtr
, es
);
2094 InvalidateRect(hwnd
, NULL
, TRUE
);
2097 /* reset the vertical scroll bar */
2100 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
2101 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
2106 /*********************************************************************
2107 * WM_HSCROLL message function
2110 void EDIT_HScrollMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2112 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2114 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2122 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2129 /*********************************************************************
2130 * WM_SIZE message function
2133 void EDIT_SizeMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2136 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2138 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2140 if (wParam
!= SIZE_MAXIMIZED
&& wParam
!= SIZE_RESTORED
) return;
2142 InvalidateRect(hwnd
, NULL
, TRUE
);
2143 es
->PaintBkgd
= TRUE
;
2148 /*********************************************************************
2149 * WM_LBUTTONDOWN message function
2152 void EDIT_LButtonDownMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2157 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2159 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2162 EDIT_ClearSel(hwnd
);
2164 es
->WndRow
= HIWORD(lParam
) / es
->txtht
;
2165 if (es
->WndRow
> es
->wlines
- es
->wtop
- 1)
2168 es
->WndRow
= es
->wlines
- es
->wtop
- 1;
2173 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
2175 cp
= EDIT_TextLine(hwnd
, es
->CurrLine
);
2176 len
= EDIT_LineLength(hwnd
, es
->CurrLine
);
2177 es
->WndCol
= LOWORD(lParam
);
2178 if (es
->WndCol
> EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
|| end
)
2179 es
->WndCol
= EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
;
2180 es
->CurrCol
= EDIT_PixelToChar(hwnd
, es
->CurrLine
, &(es
->WndCol
));
2183 ButtonRow
= es
->CurrLine
;
2184 ButtonCol
= es
->CurrCol
;
2188 /*********************************************************************
2189 * WM_MOUSEMOVE message function
2192 void EDIT_MouseMoveMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2194 if (wParam
!= MK_LBUTTON
)
2199 EDIT_SetAnchor(hwnd
, ButtonRow
, ButtonCol
);
2205 EDIT_ExtendSel(hwnd
, LOWORD(lParam
), HIWORD(lParam
));
2209 /*********************************************************************
2212 * Convert a pixel offset in the given row to a character offset,
2213 * adjusting the pixel offset to the nearest whole character if
2217 int EDIT_PixelToChar(HWND hwnd
, int row
, int *pixel
)
2219 int ch
= 0, i
= 0, s_i
;
2221 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2223 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2226 printf("EDIT_PixelToChar: row=%d, pixel=%d\n", row
, *pixel
);
2229 text
= EDIT_TextLine(hwnd
, row
);
2233 i
+= EDIT_CharWidth(hwnd
, *(text
+ ch
), i
);
2237 /* if stepped past _pixel_, go back a character */
2248 /*********************************************************************
2249 * WM_SETTEXT message function
2252 LONG
EDIT_SetTextMsg(HWND hwnd
, LONG lParam
)
2257 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2259 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2261 if (strlen((char *)lParam
) <= es
->MaxTextLen
)
2263 len
= strlen((char *)lParam
);
2264 EDIT_ClearText(hwnd
);
2266 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, len
+ 3);
2267 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2268 strcpy(text
, (char *)lParam
);
2269 text
[len
+ 1] = '\0';
2270 text
[len
+ 2] = '\0';
2271 EDIT_BuildTextPointers(hwnd
);
2272 InvalidateRect(hwnd
, NULL
, TRUE
);
2273 es
->PaintBkgd
= TRUE
;
2274 es
->TextChanged
= TRUE
;
2282 /*********************************************************************
2285 * Clear text from text buffer.
2288 void EDIT_ClearText(HWND hwnd
)
2290 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2292 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2293 unsigned int blen
= EditBufLen(wndPtr
) + 2;
2296 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, blen
);
2297 text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2298 memset(text
, 0, blen
);
2301 es
->CurrLine
= es
->CurrCol
= 0;
2302 es
->WndRow
= es
->WndCol
= 0;
2303 es
->wleft
= es
->wtop
= 0;
2305 es
->TextChanged
= FALSE
;
2306 EDIT_ClearTextPointers(hwnd
);
2310 /*********************************************************************
2311 * EM_SETSEL message function
2314 void EDIT_SetSelMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2317 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2319 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2321 so
= LOWORD(lParam
);
2322 eo
= HIWORD(lParam
);
2324 if (so
== -1) /* if so == -1, clear selection */
2326 EDIT_ClearSel(hwnd
);
2330 if (so
== eo
) /* if so == eo, set caret only */
2332 EDIT_GetLineCol(hwnd
, so
, &(es
->CurrLine
), &(es
->CurrCol
));
2333 es
->WndRow
= es
->CurrLine
- es
->wtop
;
2337 if (es
->WndRow
< 0 || es
->WndRow
> ClientHeight(wndPtr
, es
))
2339 es
->wtop
= es
->CurrLine
;
2342 es
->WndCol
= EDIT_StrLength(hwnd
,
2343 EDIT_TextLine(hwnd
, es
->CurrLine
),
2344 es
->CurrCol
, 0) - es
->wleft
;
2345 if (es
->WndCol
> ClientWidth(wndPtr
))
2347 es
->wleft
= es
->WndCol
;
2350 else if (es
->WndCol
< 0)
2352 es
->wleft
+= es
->WndCol
;
2357 else /* otherwise set selection */
2362 EDIT_GetLineCol(hwnd
, so
, &(es
->SelBegLine
), &(es
->SelBegCol
));
2363 EDIT_GetLineCol(hwnd
, eo
, &(es
->SelEndLine
), &(es
->SelEndCol
));
2364 es
->CurrLine
= es
->SelEndLine
;
2365 es
->CurrCol
= es
->SelEndCol
;
2366 es
->WndRow
= es
->SelEndLine
- es
->wtop
;
2368 if (!wParam
) /* don't suppress scrolling of text */
2372 es
->wtop
= es
->SelEndLine
;
2375 else if (es
->WndRow
> ClientHeight(wndPtr
, es
))
2377 es
->wtop
+= es
->WndRow
- ClientHeight(wndPtr
, es
);
2378 es
->WndRow
= ClientHeight(wndPtr
, es
);
2380 es
->WndCol
= EDIT_StrLength(hwnd
,
2381 EDIT_TextLine(hwnd
, es
->SelEndLine
),
2382 es
->SelEndCol
, 0) - es
->wleft
;
2383 if (es
->WndCol
> ClientWidth(wndPtr
))
2385 es
->wleft
+= es
->WndCol
- ClientWidth(wndPtr
);
2386 es
->WndCol
= ClientWidth(wndPtr
);
2388 else if (es
->WndCol
< 0)
2390 es
->wleft
+= es
->WndCol
;
2395 InvalidateRect(hwnd
, NULL
, TRUE
);
2401 /*********************************************************************
2404 * Return line and column in text buffer from character offset.
2407 void EDIT_GetLineCol(HWND hwnd
, int off
, int *line
, int *col
)
2411 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2413 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2414 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2415 unsigned int *textPtrs
=
2416 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2418 /* check for (0,0) */
2426 if (off
> strlen(text
)) off
= strlen(text
);
2428 for (lineno
= 0; lineno
< es
->wlines
; lineno
++)
2430 cp
= text
+ *(textPtrs
+ lineno
);
2431 if (off
== (int)(cp
- text
))
2437 if (off
< (int)(cp
- text
))
2442 *col
= off
- (int)(cp1
- text
);
2444 if (*(text
+ *col
) == '\0')
2450 /*********************************************************************
2453 * Delete the current selected text (if any)
2456 void EDIT_DeleteSel(HWND hwnd
)
2460 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2462 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2463 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2467 bbl
= EDIT_TextLine(hwnd
, es
->SelBegLine
) + es
->SelBegCol
;
2468 bel
= EDIT_TextLine(hwnd
, es
->SelEndLine
) + es
->SelEndCol
;
2469 len
= (int)(bel
- bbl
);
2470 EDIT_SaveDeletedText(hwnd
, bbl
, len
, es
->SelBegLine
, es
->SelBegCol
);
2471 es
->TextChanged
= TRUE
;
2474 es
->CurrLine
= es
->SelBegLine
;
2475 es
->CurrCol
= es
->SelBegCol
;
2476 es
->WndRow
= es
->SelBegLine
- es
->wtop
;
2479 es
->wtop
= es
->SelBegLine
;
2482 es
->WndCol
= EDIT_StrLength(hwnd
, bbl
- es
->SelBegCol
,
2483 es
->SelBegCol
, 0) - es
->wleft
;
2485 EDIT_BuildTextPointers(hwnd
);
2486 es
->PaintBkgd
= TRUE
;
2487 EDIT_ClearSel(hwnd
);
2492 /*********************************************************************
2495 * Clear the current selection.
2498 void EDIT_ClearSel(HWND hwnd
)
2500 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2502 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2504 es
->SelBegLine
= es
->SelBegCol
= 0;
2505 es
->SelEndLine
= es
->SelEndCol
= 0;
2507 InvalidateRect(hwnd
, NULL
, TRUE
);
2512 /*********************************************************************
2513 * EDIT_TextLineNumber
2515 * Return the line number in the text buffer of the supplied
2516 * character pointer.
2519 int EDIT_TextLineNumber(HWND hwnd
, char *lp
)
2523 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2525 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2526 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2527 unsigned int *textPtrs
=
2528 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2530 for (lineno
= 0; lineno
< es
->wlines
; lineno
++)
2532 cp
= text
+ *(textPtrs
+ lineno
);
2542 /*********************************************************************
2545 * Set down anchor for text marking.
2548 void EDIT_SetAnchor(HWND hwnd
, int row
, int col
)
2551 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2553 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2557 EDIT_ClearSel(hwnd
);
2558 es
->SelBegLine
= es
->SelEndLine
= row
;
2559 es
->SelBegCol
= es
->SelEndCol
= col
;
2562 InvalidateRect(hwnd
, NULL
, FALSE
);
2568 /*********************************************************************
2571 * Extend selection to the given screen co-ordinates.
2574 void EDIT_ExtendSel(HWND hwnd
, int x
, int y
)
2576 int bbl
, bel
, bbc
, bec
;
2580 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2582 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2585 printf("EDIT_ExtendSel: x=%d, y=%d\n", x
, y
);
2588 bbl
= es
->SelEndLine
;
2589 bbc
= es
->SelEndCol
;
2590 cp
= EDIT_TextLine(hwnd
, es
->wtop
+ y
/ es
->txtht
);
2591 len
= EDIT_LineLength(hwnd
, es
->wtop
+ y
/ es
->txtht
);
2593 es
->WndRow
= y
/ es
->txtht
;
2594 if (es
->WndRow
> es
->wlines
- es
->wtop
- 1)
2597 es
->WndRow
= es
->wlines
- es
->wtop
- 1;
2602 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
2603 es
->SelEndLine
= es
->CurrLine
;
2606 if (es
->WndCol
> EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
|| end
)
2607 es
->WndCol
= EDIT_StrLength(hwnd
, cp
, len
, 0) - es
->wleft
;
2608 es
->CurrCol
= EDIT_PixelToChar(hwnd
, es
->CurrLine
, &(es
->WndCol
));
2609 es
->SelEndCol
= es
->CurrCol
- 1;
2611 bel
= es
->SelEndLine
;
2612 bec
= es
->SelEndCol
;
2614 /* return if no new characters to mark */
2615 if (bbl
== bel
&& bbc
== bec
)
2618 /* put lowest marker first */
2624 if (bbl
== bel
&& bbc
> bec
)
2627 for (y
= bbl
; y
<= bel
; y
++)
2629 if (y
== bbl
&& y
== bel
)
2630 EDIT_WriteSel(hwnd
, y
, bbc
, bec
);
2632 EDIT_WriteSel(hwnd
, y
, bbc
, -1);
2634 EDIT_WriteSel(hwnd
, y
, 0, bec
);
2636 EDIT_WriteSel(hwnd
, y
, 0, -1);
2641 /*********************************************************************
2644 * Display selection by reversing pixels in selected text.
2645 * If end == -1, selection applies to end of line.
2648 void EDIT_WriteSel(HWND hwnd
, int y
, int start
, int end
)
2654 HBRUSH hbrush
, holdbrush
;
2656 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2658 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2661 printf("EDIT_WriteSel: y=%d start=%d end=%d\n", y
, start
, end
);
2663 GetClientRect(hwnd
, &rc
);
2665 /* make sure y is within the window */
2666 if (y
< es
->wtop
|| y
> (es
->wtop
+ ClientHeight(wndPtr
, es
)))
2669 /* get pointer to text */
2670 cp
= EDIT_TextLine(hwnd
, y
);
2672 /* get length of line if end == -1 */
2674 end
= EDIT_LineLength(hwnd
, y
);
2676 scol
= EDIT_StrLength(hwnd
, cp
, start
, 0);
2677 if (scol
> rc
.right
) return;
2678 if (scol
< rc
.left
) scol
= rc
.left
;
2679 ecol
= EDIT_StrLength(hwnd
, cp
, end
, 0);
2680 if (ecol
< rc
.left
) return;
2681 if (ecol
> rc
.right
) ecol
= rc
.right
;
2684 hbrush
= GetStockObject(BLACK_BRUSH
);
2685 holdbrush
= (HBRUSH
)SelectObject(hdc
, (HANDLE
)hbrush
);
2686 olddm
= SetROP2(hdc
, R2_XORPEN
);
2687 Rectangle(hdc
, scol
, y
* es
->txtht
, ecol
, (y
+ 1) * es
->txtht
);
2688 SetROP2(hdc
, olddm
);
2689 SelectObject(hdc
, (HANDLE
)holdbrush
);
2690 ReleaseDC(hwnd
, hdc
);
2694 /*********************************************************************
2697 * Stop text marking (selection).
2700 void EDIT_StopMarking(HWND hwnd
)
2702 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2704 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2706 TextMarking
= FALSE
;
2707 if (es
->SelBegLine
> es
->SelEndLine
)
2709 swap(&(es
->SelBegLine
), &(es
->SelEndLine
));
2710 swap(&(es
->SelBegCol
), &(es
->SelEndCol
));
2712 if (es
->SelBegLine
== es
->SelEndLine
&& es
->SelBegCol
> es
->SelEndCol
)
2713 swap(&(es
->SelBegCol
), &(es
->SelEndCol
));
2717 /*********************************************************************
2718 * EM_GETLINE message function
2721 LONG
EDIT_GetLineMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2725 char *buffer
= (char *)lParam
;
2726 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2728 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2730 cp
= EDIT_TextLine(hwnd
, wParam
);
2731 cp1
= EDIT_TextLine(hwnd
, wParam
+ 1);
2732 len
= min((int)(cp1
- cp
), (WORD
)(*buffer
));
2733 strncpy(buffer
, cp
, len
);
2739 /*********************************************************************
2740 * EM_GETSEL message function
2743 LONG
EDIT_GetSelMsg(HWND hwnd
)
2746 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2748 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2749 unsigned int *textPtrs
=
2750 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2752 so
= *(textPtrs
+ es
->SelBegLine
) + es
->SelBegCol
;
2753 eo
= *(textPtrs
+ es
->SelEndLine
) + es
->SelEndCol
;
2755 return MAKELONG(so
, eo
);
2759 /*********************************************************************
2760 * EM_REPLACESEL message function
2763 void EDIT_ReplaceSel(HWND hwnd
, LONG lParam
)
2765 EDIT_DeleteSel(hwnd
);
2766 EDIT_InsertText(hwnd
, (char *)lParam
, strlen((char *)lParam
));
2767 InvalidateRect(hwnd
, NULL
, TRUE
);
2772 /*********************************************************************
2775 * Insert text at current line and column.
2778 void EDIT_InsertText(HWND hwnd
, char *str
, int len
)
2781 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2783 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2784 char *text
= EDIT_HeapAddr(hwnd
, es
->hText
);
2786 plen
= strlen(text
) + len
;
2787 if (plen
+ 1 > es
->textlen
)
2789 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, es
->textlen
+ len
);
2790 es
->textlen
= plen
+ 1;
2792 memmove(CurrChar
+ len
, CurrChar
, strlen(CurrChar
) + 1);
2793 memcpy(CurrChar
, str
, len
);
2795 EDIT_BuildTextPointers(hwnd
);
2796 es
->PaintBkgd
= TRUE
;
2797 es
->TextChanged
= TRUE
;
2799 EDIT_GetLineCol(hwnd
, (int)((CurrChar
+ len
) - text
), &(es
->CurrLine
),
2801 es
->WndRow
= es
->CurrLine
- es
->wtop
;
2802 es
->WndCol
= EDIT_StrLength(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
2803 es
->CurrCol
, 0) - es
->wleft
;
2807 /*********************************************************************
2808 * EM_LINEFROMCHAR message function
2811 LONG
EDIT_LineFromCharMsg(HWND hwnd
, WORD wParam
)
2814 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2816 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2818 if (wParam
== (WORD
)-1)
2819 return (LONG
)(es
->SelBegLine
);
2821 EDIT_GetLineCol(hwnd
, wParam
, &row
, &col
);
2827 /*********************************************************************
2828 * EM_LINEINDEX message function
2831 LONG
EDIT_LineIndexMsg(HWND hwnd
, WORD wParam
)
2833 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2835 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2836 unsigned int *textPtrs
=
2837 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2839 if (wParam
== (WORD
)-1)
2840 wParam
= es
->CurrLine
;
2842 return (LONG
)(*(textPtrs
+ wParam
));
2846 /*********************************************************************
2847 * EM_LINELENGTH message function
2850 LONG
EDIT_LineLengthMsg(HWND hwnd
, WORD wParam
)
2853 int sbl
, sbc
, sel
, sec
;
2854 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2856 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2857 unsigned int *textPtrs
=
2858 (unsigned int *)EDIT_HeapAddr(hwnd
, es
->hTextPtrs
);
2860 if (wParam
== (WORD
)-1)
2864 sbl
= es
->SelBegLine
;
2865 sbc
= es
->SelBegCol
;
2866 sel
= es
->SelEndLine
;
2867 sec
= es
->SelEndCol
;
2874 if (sbl
== sel
&& sbc
> sec
)
2879 len
= *(textPtrs
+ sbl
+ 1) - *(textPtrs
+ sbl
) - 1;
2880 return len
- sec
- sbc
;
2883 len
= *(textPtrs
+ sel
+ 1) - *(textPtrs
+ sel
) - sec
- 1;
2886 else /* no selection marked */
2888 len
= *(textPtrs
+ es
->CurrLine
+ 1) -
2889 *(textPtrs
+ es
->CurrLine
) - 1;
2893 else /* line number specified */
2895 EDIT_GetLineCol(hwnd
, wParam
, &row
, &col
);
2896 len
= *(textPtrs
+ row
+ 1) - *(textPtrs
+ row
);
2902 /*********************************************************************
2903 * WM_SETFONT message function
2906 void EDIT_SetFont(HWND hwnd
, WORD wParam
, LONG lParam
)
2911 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2913 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2914 short *charWidths
= (short *)EDIT_HeapAddr(hwnd
, es
->hCharWidths
);
2918 oldfont
= (HFONT
)SelectObject(hdc
, (HANDLE
)es
->hFont
);
2919 GetCharWidth(hdc
, 0, 255, charWidths
);
2920 GetTextMetrics(hdc
, &tm
);
2921 es
->txtht
= tm
.tmHeight
+ tm
.tmExternalLeading
;
2922 SelectObject(hdc
, (HANDLE
)oldfont
);
2923 ReleaseDC(hwnd
, hdc
);
2925 es
->WndRow
= (es
->CurrLine
- es
->wtop
) / es
->txtht
;
2926 es
->WndCol
= EDIT_StrLength(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
2927 es
->CurrCol
, 0) - es
->wleft
;
2929 InvalidateRect(hwnd
, NULL
, TRUE
);
2930 es
->PaintBkgd
= TRUE
;
2931 if (lParam
) UpdateWindow(hwnd
);
2935 /*********************************************************************
2936 * EDIT_SaveDeletedText
2938 * Save deleted text in deleted text buffer.
2941 void EDIT_SaveDeletedText(HWND hwnd
, char *deltext
, int len
,
2945 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2947 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2949 es
->hDeletedText
= GlobalReAlloc(es
->hDeletedText
, len
, GMEM_MOVEABLE
);
2950 if (!es
->hDeletedText
) return;
2951 text
= (char *)GlobalLock(es
->hDeletedText
);
2952 memcpy(text
, deltext
, len
);
2953 GlobalUnlock(es
->hDeletedText
);
2954 es
->DeletedLength
= len
;
2955 es
->DeletedCurrLine
= line
;
2956 es
->DeletedCurrCol
= col
;
2960 /*********************************************************************
2961 * EDIT_ClearDeletedText
2963 * Clear deleted text buffer.
2966 void EDIT_ClearDeletedText(HWND hwnd
)
2968 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2970 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2972 GlobalFree(es
->hDeletedText
);
2973 es
->hDeletedText
= 0;
2974 es
->DeletedLength
= 0;
2978 /*********************************************************************
2979 * EM_UNDO message function
2982 LONG
EDIT_UndoMsg(HWND hwnd
)
2985 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2987 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
2989 if (es
->hDeletedText
)
2991 text
= (char *)GlobalLock(es
->hDeletedText
);
2992 es
->CurrLine
= es
->DeletedCurrLine
;
2993 es
->CurrCol
= es
->DeletedCurrCol
;
2994 EDIT_InsertText(hwnd
, text
, es
->DeletedLength
);
2995 GlobalUnlock(es
->hDeletedText
);
2996 EDIT_ClearDeletedText(hwnd
);
2998 es
->SelBegLine
= es
->CurrLine
;
2999 es
->SelBegCol
= es
->CurrCol
;
3000 EDIT_GetLineCol(hwnd
, (int)((CurrChar
+ es
->DeletedLength
) - text
),
3001 &(es
->CurrLine
), &(es
->CurrCol
));
3002 es
->WndRow
= es
->CurrLine
- es
->wtop
;
3003 es
->WndCol
= EDIT_StrLength(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
3004 es
->CurrCol
, 0) - es
->wleft
;
3005 es
->SelEndLine
= es
->CurrLine
;
3006 es
->SelEndCol
= es
->CurrCol
;
3008 InvalidateRect(hwnd
, NULL
, TRUE
);
3017 /*********************************************************************
3020 * Allocate the specified number of bytes on the specified local heap.
3023 unsigned int EDIT_HeapAlloc(HWND hwnd
, int bytes
)
3025 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3027 return ((unsigned int)HEAP_Alloc((MDESC
**)
3028 *(LONG
*)(wndPtr
->wExtra
+ 2),
3029 GMEM_MOVEABLE
, bytes
) & 0xffff);
3033 /*********************************************************************
3036 * Return the address of the memory pointed to by the handle.
3039 void *EDIT_HeapAddr(HWND hwnd
, unsigned int handle
)
3041 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3043 return ((void *)((handle
) ? ((handle
) | ((unsigned int)
3044 (*(MDESC
**)*(LONG
*)(wndPtr
->wExtra
+ 2))
3045 & 0xffff0000)) : 0));
3049 /*********************************************************************
3052 * Reallocate the memory pointed to by the handle.
3055 unsigned int EDIT_HeapReAlloc(HWND hwnd
, unsigned int handle
, int bytes
)
3057 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3059 return ((unsigned int)HEAP_ReAlloc((MDESC
**)
3060 *(LONG
*)(wndPtr
->wExtra
+ 2),
3061 EDIT_HeapAddr(hwnd
, handle
),
3062 bytes
, GMEM_MOVEABLE
) & 0xffff);
3066 /*********************************************************************
3069 * Frees the memory pointed to by the handle.
3072 void EDIT_HeapFree(HWND hwnd
, unsigned int handle
)
3074 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3076 HEAP_Free((MDESC
**)*(LONG
*)(wndPtr
->wExtra
+ 2),
3077 EDIT_HeapAddr(hwnd
, handle
));
3081 /*********************************************************************
3084 * Return the size of the given object on the local heap.
3087 unsigned int EDIT_HeapSize(HWND hwnd
, unsigned int handle
)
3089 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3091 return HEAP_LocalSize((MDESC
**)*(LONG
*)(wndPtr
->wExtra
+ 2), handle
);
3095 /*********************************************************************
3096 * EM_SETHANDLE message function
3099 void EDIT_SetHandleMsg(HWND hwnd
, WORD wParam
)
3102 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3104 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
3109 es
->MaxTextLen
= EDIT_HeapSize(hwnd
, es
->hText
);
3111 es
->wtop
= es
->wleft
= 0;
3112 es
->CurrLine
= es
->CurrCol
= 0;
3113 es
->WndRow
= es
->WndCol
= 0;
3114 es
->TextChanged
= FALSE
;
3116 es
->SelBegLine
= es
->SelBegCol
= 0;
3117 es
->SelEndLine
= es
->SelEndCol
= 0;
3119 es
->PaintBkgd
= TRUE
;
3120 InvalidateRect(hwnd
, NULL
, TRUE
);
3126 /*********************************************************************
3127 * EM_SETTABSTOPS message function
3130 LONG
EDIT_SetTabStopsMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
3132 unsigned short *tabstops
;
3133 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3135 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
3137 es
->NumTabStops
= wParam
;
3139 es
->hTabStops
= EDIT_HeapReAlloc(hwnd
, es
->hTabStops
, 1);
3140 else if (wParam
== 1)
3142 es
->hTabStops
= EDIT_HeapReAlloc(hwnd
, es
->hTabStops
, 1);
3143 tabstops
= (unsigned short *)EDIT_HeapAddr(hwnd
, es
->hTabStops
);
3144 *tabstops
= (unsigned short)lParam
;
3148 es
->hTabStops
= EDIT_HeapReAlloc(hwnd
, es
->hTabStops
, wParam
);
3149 tabstops
= (unsigned short *)EDIT_HeapAddr(hwnd
, es
->hTabStops
);
3150 memcpy(tabstops
, (unsigned short *)lParam
, wParam
);
3156 /*********************************************************************
3157 * EDIT_CopyToClipboard
3159 * Copy the specified text to the clipboard.
3162 void EDIT_CopyToClipboard(HWND hwnd
)
3168 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
3170 (EDITSTATE
*)EDIT_HeapAddr(hwnd
, (HANDLE
)(*(wndPtr
->wExtra
)));
3172 bbl
= EDIT_TextLine(hwnd
, es
->SelBegLine
) + es
->SelBegCol
;
3173 bel
= EDIT_TextLine(hwnd
, es
->SelEndLine
) + es
->SelEndCol
;
3174 len
= (int)(bel
- bbl
);
3176 hMem
= GlobalAlloc(GHND
, (DWORD
)(len
+ 1));
3177 lpMem
= GlobalLock(hMem
);
3179 for (i
= 0; i
< len
; i
++)
3183 OpenClipboard(hwnd
);
3185 SetClipboardData(CF_TEXT
, hMem
);
3190 /*********************************************************************
3191 * WM_PASTE message function
3194 void EDIT_PasteMsg(HWND hwnd
)
3199 OpenClipboard(hwnd
);
3200 if (!(hClipMem
= GetClipboardData(CF_TEXT
)))
3202 /* no text in clipboard */
3206 lpClipMem
= GlobalLock(hClipMem
);
3207 EDIT_InsertText(hwnd
, lpClipMem
, strlen(lpClipMem
));
3208 GlobalUnlock(hClipMem
);
3210 InvalidateRect(hwnd
, NULL
, TRUE
);
3215 /*********************************************************************
3219 void swap(int *a
, int *b
)