4 * Copyright David W. Metcalfe, 1994
7 * April 1995 bug fixes (William Magro)
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 */
33 int wlines
; /* number of lines of text */
34 int wtop
; /* top line that is displayed */
35 int wleft
; /* left pixel that is displayed */
36 unsigned int textlen
; /* text buffer length */
37 int textwidth
; /* width of longest line in pixels */
38 RECT fmtrc
; /* rectangle in which to format text */
39 int txtht
; /* height of text line in pixels */
40 HANDLE hText
; /* handle to text buffer */
41 short *CharWidths
; /* widths of chars in font */
42 unsigned int *textptrs
; /* list of line offsets */
43 char *BlankLine
; /* to fill blank lines quickly */
44 int CurrCol
; /* current column */
45 int CurrLine
; /* current line */
46 int WndCol
; /* current window column */
47 int WndRow
; /* current window row */
48 BOOL TextChanged
; /* TRUE if text has changed */
49 BOOL PaintBkgd
; /* paint control background */
50 unsigned int MaxTextLen
; /* maximum text buffer length */
51 int SelBegLine
; /* beginning line of selection */
52 int SelBegCol
; /* beginning column of selection */
53 int SelEndLine
; /* ending line of selection */
54 int SelEndCol
; /* ending column of selection */
55 HFONT hFont
; /* handle of current font (if not default) */
56 HANDLE hDeletedText
; /* handle to deleted txet buffer for undo */
57 int DeletedLength
; /* length of deleted text */
58 int DeletedCurrLine
; /* starting line from which text was deleted */
59 int DeletedCurrCol
; /* starting col from which text was deleted */
60 int NumTabStops
; /* number of tab stops in buffer hTabStops */
61 unsigned short *TabStops
;/* tab stops buffer */
62 BOOL HaveFocus
; /* TRUE if this edit has the focus */
63 int ClientWidth
; /* computed from the window's ClientRect */
64 int ClientHeight
; /* dito */
67 #define EditBufStartLen(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE \
69 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
70 #define SelMarked(es) ((es)->SelBegLine != 0 || (es)->SelBegCol != 0 || \
71 (es)->SelEndLine != 0 || (es)->SelEndCol != 0)
72 #define ROUNDUP(numer, denom) (((numer) % (denom)) \
73 ? ((((numer) + (denom)) / (denom)) * (denom)) \
76 /* "line" dimension for horizontal scroll */
77 #define HSCROLLDIM(es) ((es)->ClientWidth / 3)
79 /* macros to access window styles */
80 #define IsMultiLine(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE)
81 #define IsVScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_VSCROLL)
82 #define IsHScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_HSCROLL)
84 /* internal variables */
85 static BOOL TextMarking
; /* TRUE if text marking in progress */
86 static BOOL ButtonDown
; /* TRUE if left mouse button down */
87 static int ButtonRow
; /* row in text buffer when button pressed */
88 static int ButtonCol
; /* col in text buffer when button pressed */
90 #define SWAP_INT(x,y) do { int temp = (x); (x) = (y); (y) = temp; } while(0)
92 /*********************************************************************
95 * Allocate the specified number of bytes on the specified local heap.
97 static unsigned int EDIT_HeapAlloc(HWND hwnd
, int bytes
, WORD flags
)
101 ret
= LOCAL_Alloc( GetWindowWord(hwnd
,GWW_HINSTANCE
), flags
, bytes
);
103 printf("EDIT_HeapAlloc: Out of heap-memory\n");
107 /*********************************************************************
110 * Return the address of the memory pointed to by the handle.
112 static void *EDIT_HeapLock(HWND hwnd
, unsigned int handle
)
114 WORD hinstance
= GetWindowWord( hwnd
, GWW_HINSTANCE
);
117 if (handle
== 0) return 0;
118 offs
= LOCAL_Lock( hinstance
, handle
);
119 return PTR_SEG_OFF_TO_LIN( hinstance
, offs
);
122 /*********************************************************************
125 static void EDIT_HeapUnlock(HWND hwnd
, unsigned int handle
)
127 if (handle
== 0) return;
128 LOCAL_Unlock( GetWindowWord( hwnd
, GWW_HINSTANCE
), handle
);
131 /*********************************************************************
134 * Reallocate the memory pointed to by the handle.
136 static unsigned int EDIT_HeapReAlloc(HWND hwnd
, unsigned int handle
, int bytes
)
138 return LOCAL_ReAlloc( GetWindowWord(hwnd
,GWW_HINSTANCE
), handle
, bytes
,
143 /*********************************************************************
146 * Frees the memory pointed to by the handle.
148 static void EDIT_HeapFree(HWND hwnd
, unsigned int handle
)
150 LOCAL_Free( GetWindowWord(hwnd
,GWW_HINSTANCE
), handle
);
154 /*********************************************************************
157 * Return the size of the given object on the local heap.
159 static unsigned int EDIT_HeapSize(HWND hwnd
, unsigned int handle
)
161 return LOCAL_Size( GetWindowWord(hwnd
,GWW_HINSTANCE
), handle
);
164 /********************************************************************
167 * Sets the ClientWidth/ClientHeight fields of the EDITSTATE
168 * Called on WM_SIZE and WM_SetFont messages
170 static void EDIT_RecalcSize(HWND hwnd
, EDITSTATE
*es
)
173 GetClientRect(hwnd
,&rect
);
174 es
->ClientWidth
= rect
.right
> rect
.left
? rect
.right
- rect
.left
: 0;
175 es
->ClientHeight
= rect
.bottom
> rect
.top
? (rect
.bottom
- rect
.top
) / es
->txtht
: 0;
178 /*********************************************************************
181 static EDITSTATE
*EDIT_GetEditState(HWND hwnd
)
183 return (EDITSTATE
*)GetWindowLong(hwnd
,0);
186 /*********************************************************************
187 * EDIT_GetNextTabStop
189 * Return the next tab stop beyond _pcol_.
191 static int EDIT_GetNextTabStop(HWND hwnd
, int pcol
)
194 int baseUnitWidth
= LOWORD(GetDialogBaseUnits());
195 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
197 if (es
->NumTabStops
== 0)
198 return ROUNDUP(pcol
, 8 * baseUnitWidth
);
199 if (es
->NumTabStops
== 1)
200 return ROUNDUP(pcol
, es
->TabStops
[0] * baseUnitWidth
/ 4);
201 for (i
= 0; i
< es
->NumTabStops
; i
++)
203 if (es
->TabStops
[i
] * baseUnitWidth
/ 4 >= pcol
)
204 return es
->TabStops
[i
] * baseUnitWidth
/ 4;
209 /*********************************************************************
212 * Return the width of the given character in pixels.
213 * The current column offset in pixels _pcol_ is required to calculate
214 * the width of a tab.
216 static int EDIT_CharWidth(HWND hwnd
, short ch
, int pcol
)
218 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
220 if (ch
== VK_TAB
) return EDIT_GetNextTabStop(hwnd
, pcol
) - pcol
;
221 return es
->CharWidths
[ch
];
224 /*********************************************************************
225 * EDIT_ClearTextPointers
227 * Clear and initialize text line pointer array.
229 static void EDIT_ClearTextPointers(HWND hwnd
)
231 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
233 dprintf_edit( stddeb
, "EDIT_ClerTextPointers\n" );
234 es
->textptrs
= realloc(es
->textptrs
, sizeof(int));
238 /*********************************************************************
239 * EDIT_BuildTextPointers
241 * Build array of pointers to text lines.
243 static void EDIT_BuildTextPointers(HWND hwnd
)
246 unsigned int off
, len
, line
;
249 es
= EDIT_GetEditState(hwnd
);
250 text
= EDIT_HeapLock(hwnd
, es
->hText
);
253 if (IsMultiLine(hwnd
)) {
256 while ((cp
= strchr(cp
,'\n')) != NULL
) {
259 } else es
->wlines
= 1;
261 dprintf_edit( stddeb
, "EDIT_BuildTextPointers: realloc\n" );
262 es
->textptrs
= realloc(es
->textptrs
, (es
->wlines
+ 2) * sizeof(int));
265 dprintf_edit(stddeb
,"BuildTextPointers: %d lines, pointer %p\n",
266 es
->wlines
, es
->textptrs
);
268 /* advance through text buffer */
272 off
= cp
- text
; /* offset of beginning of line */
273 dprintf_edit(stddeb
,"BuildTextPointers: line %d offs %d\n", line
, off
);
274 es
->textptrs
[line
] = off
;
278 /* advance through current line */
279 while (*cp
&& *cp
!= '\n')
281 len
+= EDIT_CharWidth(hwnd
, (BYTE
)*cp
, len
);
282 /* width of line in pixels */
285 es
->textwidth
= max(es
->textwidth
, len
);
287 cp
++; /* skip '\n' */
290 es
->textptrs
[line
] = off
;
291 EDIT_HeapUnlock(hwnd
, es
->hText
);
294 /*********************************************************************
295 * EDIT_ModTextPointers
297 * Modify text pointers from a specified position.
299 static void EDIT_ModTextPointers(HWND hwnd
, int lineno
, int var
)
301 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
302 for(;lineno
< es
->wlines
; lineno
++) es
->textptrs
[lineno
] += var
;
305 /*********************************************************************
308 * Return a pointer to the text in the specified line.
310 static char *EDIT_TextLine(HWND hwnd
, int sel
)
312 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
313 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
315 if (sel
> es
->wlines
) return NULL
;
316 dprintf_edit(stddeb
,"EDIT_TextLine: text %p, line %d offs %d\n",
317 text
, sel
, es
->textptrs
[sel
]);
318 return text
+ es
->textptrs
[sel
];
321 /*********************************************************************
324 * Get a copy of the text in the specified line.
326 static char *EDIT_GetTextLine(HWND hwnd
, int selection
)
331 dprintf_edit(stddeb
,"GetTextLine %d\n", selection
);
332 cp1
= EDIT_TextLine(hwnd
, selection
);
334 /* Find end of line */
335 cp
= strchr( cp1
, '\r' );
336 if (cp
== NULL
) len
= strlen(cp1
);
339 /* store selected line and return handle */
340 cp
= malloc( len
+ 1 );
341 strncpy( cp
, cp1
, len
);
346 /*********************************************************************
349 * Return length of string _str_ of length _len_ characters in pixels.
350 * The current column offset in pixels _pcol_ is required to calculate
351 * the width of a tab.
353 static int EDIT_StrWidth(HWND hwnd
, unsigned char *str
, int len
, int pcol
)
357 for (i
= 0; i
< len
; i
++)
358 plen
+= EDIT_CharWidth(hwnd
, (BYTE
)(*(str
+ i
)), pcol
+ plen
);
360 dprintf_edit(stddeb
,"EDIT_StrWidth: returning %d, len=%d\n", plen
,len
);
364 /*********************************************************************
367 * Return length of line _num_ in characters.
369 static int EDIT_LineLength(HWND hwnd
, int num
)
371 char *cp
= EDIT_TextLine(hwnd
, num
);
375 cp1
= strchr(cp
, '\r');
376 return cp1
? (cp1
- cp
) : strlen(cp
);
379 /*********************************************************************
382 * Return sub-string starting at pixel _off_ of length _len_ pixels.
383 * If _off_ is part way through a character, the negative offset of
384 * the beginning of the character is returned in _diff_, else _diff_
387 static HANDLE
EDIT_GetStr(HWND hwnd
, char *lp
, int off
, int len
, int *diff
)
391 int ch
= 0, i
= 0, j
, s_i
=0;
394 dprintf_edit(stddeb
,"EDIT_GetStr lp='%s' off=%d len=%d\n", lp
, off
, len
);
396 if (off
< 0) off
= 0;
400 i
+= EDIT_CharWidth(hwnd
, (BYTE
)(*(lp
+ ch
)), i
);
403 /* if stepped past _off_, go back a character */
411 while (i
< len
+ off
)
413 if (*(lp
+ ch
) == '\r' || *(lp
+ ch
) == '\n')
415 i
+= EDIT_CharWidth(hwnd
, (BYTE
)(*(lp
+ ch
)), i
);
419 hStr
= EDIT_HeapAlloc(hwnd
, ch
- ch1
+ 3, LMEM_FIXED
);
420 str
= (char *)EDIT_HeapLock(hwnd
, hStr
);
421 for (i
= ch1
, j
= 0; i
< ch
; i
++, j
++)
424 dprintf_edit(stddeb
,"EDIT_GetStr: returning %s\n", str
);
428 /*********************************************************************
431 * Write text to a window
433 * off - offset in text line (in pixels)
434 * len - length from off (in pixels)
435 * row - line in window
436 * col - column in window
437 * rc - rectangle in which to display line
438 * blank - blank remainder of line?
439 * reverse - reverse color of line?
441 static void EDIT_WriteText(HWND hwnd
, char *lp
, int off
, int len
, int row
,
442 int col
, RECT
*rc
, BOOL blank
, BOOL reverse
)
446 char *str
, *cp
, *cp1
;
447 int diff
=0, num_spaces
, tabwidth
, scol
;
449 COLORREF oldTextColor
, oldBkgdColor
;
451 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
453 dprintf_edit(stddeb
,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp
, off
, len
, row
, col
, reverse
);
462 hStr
= EDIT_GetStr(hwnd
, lp
, off
, len
, &diff
);
463 str
= (char *)EDIT_HeapLock(hwnd
, hStr
);
464 hrgnClip
= CreateRectRgnIndirect(rc
);
465 SelectClipRgn(hdc
, hrgnClip
);
468 oldfont
= (HFONT
)SelectObject(hdc
, (HANDLE
)es
->hFont
);
470 oldfont
= 0; /* -Wall does not see the use of if */
472 SendMessage(GetParent(hwnd
), WM_CTLCOLOR
, (WORD
)hdc
,
473 MAKELPARAM(hwnd
, CTLCOLOR_EDIT
));
477 oldBkgdColor
= GetBkColor(hdc
);
478 oldTextColor
= GetTextColor(hdc
);
479 SetBkColor(hdc
, oldTextColor
);
480 SetTextColor(hdc
, oldBkgdColor
);
482 else /* -Wall does not see the use of if */
483 oldTextColor
= oldBkgdColor
= 0;
485 if (strlen(es
->BlankLine
) < (es
->ClientWidth
/ es
->CharWidths
[32]) + 2)
487 dprintf_edit( stddeb
, "EDIT_WriteText: realloc\n" );
488 es
->BlankLine
= realloc(es
->BlankLine
,
489 (es
->ClientWidth
/ es
->CharWidths
[32]) + 2);
490 memset(es
->BlankLine
, ' ', (es
->ClientWidth
/ es
->CharWidths
[32]) + 2);
491 es
->BlankLine
[(es
->ClientWidth
/ es
->CharWidths
[32]) + 1] = 0;
494 if (!(cp
= strchr(str
, VK_TAB
)))
495 TextOut(hdc
, col
- diff
, row
* es
->txtht
, str
, strlen(str
));
498 TextOut(hdc
, col
- diff
, row
* es
->txtht
, str
, (int)(cp
- str
));
499 scol
= EDIT_StrWidth(hwnd
, str
, (int)(cp
- str
), 0);
500 tabwidth
= EDIT_CharWidth(hwnd
, VK_TAB
, scol
);
501 num_spaces
= tabwidth
/ es
->CharWidths
[32] + 1;
502 TextOut(hdc
, scol
, row
* es
->txtht
, es
->BlankLine
, num_spaces
);
506 while ((cp1
= strchr(cp
, VK_TAB
)))
508 TextOut(hdc
, scol
, row
* es
->txtht
, cp
, (int)(cp1
- cp
));
509 scol
+= EDIT_StrWidth(hwnd
, cp
, (int)(cp1
- cp
), scol
);
510 tabwidth
= EDIT_CharWidth(hwnd
, VK_TAB
, scol
);
511 num_spaces
= tabwidth
/ es
->CharWidths
[32] + 1;
512 TextOut(hdc
, scol
, row
* es
->txtht
, es
->BlankLine
, num_spaces
);
517 TextOut(hdc
, scol
, row
* es
->txtht
, cp
, strlen(cp
));
522 SetBkColor(hdc
, oldBkgdColor
);
523 SetTextColor(hdc
, oldTextColor
);
526 /* blank out remainder of line if appropriate */
529 if ((rc
->right
- col
) > len
)
531 num_spaces
= (rc
->right
- col
- len
) / es
->CharWidths
[32];
532 TextOut(hdc
, col
+ len
, row
* es
->txtht
, es
->BlankLine
, num_spaces
);
537 SelectObject(hdc
, (HANDLE
)oldfont
);
539 EDIT_HeapFree(hwnd
, hStr
);
540 ReleaseDC(hwnd
, hdc
);
543 /*********************************************************************
546 * Write the line of text at offset _y_ in text buffer to a window.
548 static void EDIT_WriteTextLine(HWND hwnd
, RECT
*rect
, int y
)
554 int sbl
, sel
, sbc
, sec
;
556 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
558 /* initialize rectangle if NULL, else copy */
562 GetClientRect(hwnd
, &rc
);
564 dprintf_edit(stddeb
,"WriteTextLine %d\n", y
);
566 /* make sure y is inside the window */
567 if (y
< es
->wtop
|| y
> (es
->wtop
+ es
->ClientHeight
))
569 dprintf_edit(stddeb
,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y
);
573 /* make sure rectangle is within window */
574 if (rc
.left
>= es
->ClientWidth
- 1)
576 dprintf_edit(stddeb
,"EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
582 dprintf_edit(stddeb
,"EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
586 if (y
- es
->wtop
< (rc
.top
/ es
->txtht
) ||
587 y
- es
->wtop
> (rc
.bottom
/ es
->txtht
))
589 dprintf_edit(stddeb
,"EDIT_WriteTextLine: y (%d) is outside window\n", y
);
593 /* get the text and length of line */
594 lp
= EDIT_GetTextLine( hwnd
, y
);
595 if (lp
== NULL
) return;
597 lnlen
= EDIT_StrWidth( hwnd
, lp
, strlen(lp
), 0 );
600 /* build the line to display */
601 if (lnlen
< (es
->wleft
+ rc
.left
))
615 lnlen
= lnlen1
- off
;
617 len
= min(lnlen
, rc
.right
- rc
.left
);
621 sbl
= es
->SelBegLine
;
622 sel
= es
->SelEndLine
;
626 /* put lowest marker first */
632 if (sbl
== sel
&& sbc
> sec
)
635 if (y
< sbl
|| y
> sel
)
636 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
638 else if (y
> sbl
&& y
< sel
)
639 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
643 col
= EDIT_StrWidth(hwnd
, lp
, sbc
, 0);
644 if (col
> (es
->wleft
+ rc
.left
))
646 len
= min(col
- off
, rc
.right
- off
);
647 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
648 rc
.left
, &rc
, FALSE
, FALSE
);
653 col
= EDIT_StrWidth(hwnd
, lp
, sec
, 0);
654 if (col
< (es
->wleft
+ rc
.right
))
656 len
= min(col
- off
, rc
.right
- off
);
657 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
658 off
- es
->wleft
, &rc
, FALSE
, TRUE
);
660 len
= min(lnlen
- off
, rc
.right
- off
);
661 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
662 off
- es
->wleft
, &rc
, TRUE
, FALSE
);
666 len
= min(lnlen
- off
, rc
.right
- off
);
667 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
668 off
- es
->wleft
, &rc
, TRUE
, TRUE
);
673 len
= min(lnlen
- off
, rc
.right
- off
);
674 if (col
< (es
->wleft
+ rc
.right
))
675 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
676 off
- es
->wleft
, &rc
, TRUE
, TRUE
);
681 col
= EDIT_StrWidth(hwnd
, lp
, sec
, 0);
682 if (col
< (es
->wleft
+ rc
.right
))
684 len
= min(col
- off
, rc
.right
- off
);
685 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
686 off
- es
->wleft
, &rc
, FALSE
, TRUE
);
688 len
= min(lnlen
- off
, rc
.right
- off
);
689 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
690 off
- es
->wleft
, &rc
, TRUE
, FALSE
);
695 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
701 /*********************************************************************
702 * EDIT_ComputeVScrollPos
704 * Compute the vertical scroll bar position from the window
705 * position and text width.
707 static int EDIT_ComputeVScrollPos(HWND hwnd
)
710 short minpos
, maxpos
;
711 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
713 GetScrollRange(hwnd
, SB_VERT
, &minpos
, &maxpos
);
715 if (es
->wlines
> es
->ClientHeight
)
716 vscrollpos
= (double)(es
->wtop
) / (double)(es
->wlines
-
717 es
->ClientHeight
) * (maxpos
- minpos
);
724 /*********************************************************************
725 * EDIT_ComputeHScrollPos
727 * Compute the horizontal scroll bar position from the window
728 * position and text width.
730 static int EDIT_ComputeHScrollPos(HWND hwnd
)
733 short minpos
, maxpos
;
734 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
736 GetScrollRange(hwnd
, SB_HORZ
, &minpos
, &maxpos
);
738 if (es
->textwidth
> es
->ClientWidth
)
739 hscrollpos
= (double)(es
->wleft
) / (double)(es
->textwidth
-
740 es
->ClientWidth
) * (maxpos
- minpos
);
747 /*********************************************************************
750 * Scroll text horizontally using cursor keys.
752 static void EDIT_KeyHScroll(HWND hwnd
, WORD opt
)
755 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
757 if (opt
== SB_LINEDOWN
)
759 es
->wleft
+= HSCROLLDIM(es
);
760 es
->WndCol
-= HSCROLLDIM(es
);
766 if (es
->wleft
- HSCROLLDIM(es
) < 0)
768 es
->WndCol
+= es
->wleft
;
773 es
->wleft
-= HSCROLLDIM(es
);
774 es
->WndCol
+= HSCROLLDIM(es
);
778 InvalidateRect(hwnd
, NULL
, FALSE
);
781 if (IsHScrollBar(hwnd
))
783 hscrollpos
= EDIT_ComputeHScrollPos(hwnd
);
784 SetScrollPos(hwnd
, SB_HORZ
, hscrollpos
, TRUE
);
788 /*********************************************************************
789 * EDIT_KeyVScrollLine
791 * Scroll text vertically by one line using keyboard.
793 static void EDIT_KeyVScrollLine(HWND hwnd
, WORD opt
)
797 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
799 if (!IsMultiLine(hwnd
))
802 if (opt
== SB_LINEDOWN
)
804 /* move down one line */
805 if (es
->wtop
+ es
->ClientHeight
>= es
->wlines
)
811 /* move up one line */
817 if (IsWindowVisible(hwnd
))
819 /* adjust client bottom to nearest whole line */
820 GetClientRect(hwnd
, &rc
);
821 rc
.bottom
= (rc
.bottom
/ es
->txtht
) * es
->txtht
;
823 if (opt
== SB_LINEUP
)
825 /* move up one line (scroll window down) */
826 ScrollWindow(hwnd
, 0, es
->txtht
, &rc
, &rc
);
828 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
);
833 /* move down one line (scroll window up) */
834 ScrollWindow(hwnd
, 0, -(es
->txtht
), &rc
, &rc
);
835 /* write bottom line */
836 y
= (((rc
.bottom
- rc
.top
) / es
->txtht
) - 1);
837 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ y
);
842 /* reset the vertical scroll bar */
843 if (IsVScrollBar(hwnd
))
845 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
846 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
850 /*********************************************************************
853 * End key: move to end of line.
855 static void EDIT_End(HWND hwnd
)
857 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
859 while (*CurrChar
&& *CurrChar
!= '\r')
861 es
->WndCol
+= EDIT_CharWidth(hwnd
, (BYTE
)(*CurrChar
), es
->WndCol
+ es
->wleft
);
865 if (es
->WndCol
>= es
->ClientWidth
)
867 es
->wleft
= es
->WndCol
- es
->ClientWidth
+ HSCROLLDIM(es
);
868 es
->WndCol
-= es
->wleft
;
869 InvalidateRect(hwnd
, NULL
, FALSE
);
874 /*********************************************************************
877 * Home key: move to beginning of line.
879 static void EDIT_Home(HWND hwnd
)
881 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
883 es
->CurrCol
= es
->WndCol
= 0;
887 InvalidateRect(hwnd
, NULL
, FALSE
);
892 /*********************************************************************
895 * Stick the cursor to the end of the line.
897 static void EDIT_StickEnd(HWND hwnd
)
899 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
900 int len
= EDIT_LineLength(hwnd
, es
->CurrLine
);
901 char *cp
= EDIT_TextLine(hwnd
, es
->CurrLine
);
904 es
->CurrCol
= min(len
, es
->CurrCol
);
905 es
->WndCol
= min(EDIT_StrWidth(hwnd
, cp
, len
, 0) - es
->wleft
, es
->WndCol
);
906 currpel
= EDIT_StrWidth(hwnd
, cp
, es
->CurrCol
, 0);
908 if (es
->wleft
> currpel
)
910 es
->wleft
= max(0, currpel
- 20);
911 es
->WndCol
= currpel
- es
->wleft
;
914 else if (currpel
- es
->wleft
>= es
->ClientWidth
)
916 es
->wleft
= currpel
- (es
->ClientWidth
- 5);
917 es
->WndCol
= currpel
- es
->wleft
;
922 /*********************************************************************
925 * Cursor down key: move down one line.
927 static void EDIT_Downward(HWND hwnd
)
929 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
931 dprintf_edit(stddeb
,"EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n",
932 es
->WndRow
, es
->wtop
, es
->wlines
);
934 if (IsMultiLine(hwnd
) && (es
->WndRow
+ es
->wtop
+ 1 < es
->wlines
))
937 if (es
->WndRow
== es
->ClientHeight
- 1)
940 EDIT_KeyVScrollLine(hwnd
, SB_LINEDOWN
);
948 /*********************************************************************
951 * Cursor up key: move up one line.
953 static void EDIT_Upward(HWND hwnd
)
955 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
957 if (IsMultiLine(hwnd
) && es
->CurrLine
!= 0)
963 EDIT_KeyVScrollLine(hwnd
, SB_LINEUP
);
971 /*********************************************************************
974 * Cursor right key: move right one character position.
976 static void EDIT_Forward(HWND hwnd
)
978 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
980 if (*CurrChar
== '\0')
983 if (*CurrChar
== '\r')
985 if (es
->CurrLine
< (es
->wlines
- 1))
993 es
->WndCol
+= EDIT_CharWidth(hwnd
, (BYTE
)(*CurrChar
), es
->WndCol
+ es
->wleft
);
995 if (es
->WndCol
>= es
->ClientWidth
)
996 EDIT_KeyHScroll(hwnd
, SB_LINEDOWN
);
1000 /*********************************************************************
1003 * Cursor left key: move left one character position.
1005 static void EDIT_Backward(HWND hwnd
)
1007 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1012 if (*CurrChar
== VK_TAB
)
1013 es
->WndCol
-= EDIT_CharWidth(hwnd
, (BYTE
)(*CurrChar
),
1015 EDIT_TextLine(hwnd
, es
->CurrLine
),
1018 es
->WndCol
-= EDIT_CharWidth(hwnd
, (BYTE
)(*CurrChar
), 0);
1020 EDIT_KeyHScroll(hwnd
, SB_LINEUP
);
1022 else if (IsMultiLine(hwnd
) && es
->CurrLine
!= 0)
1029 /*********************************************************************
1030 * EDIT_KeyVScrollPage
1032 * Scroll text vertically by one page using keyboard.
1034 static void EDIT_KeyVScrollPage(HWND hwnd
, WORD opt
)
1037 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1039 if (IsMultiLine(hwnd
))
1041 if (opt
== SB_PAGEUP
)
1043 if (es
->wtop
> es
->ClientHeight
) es
->wtop
-= es
->ClientHeight
;
1047 if (es
->wtop
+ es
->ClientHeight
< es
->wlines
)
1049 es
->wtop
+= es
->ClientHeight
;
1050 if (es
->wtop
> es
->wlines
- es
->ClientHeight
)
1051 es
->wtop
= es
->wlines
- es
->ClientHeight
;
1057 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
1058 EDIT_StickEnd(hwnd
);
1059 InvalidateRect(hwnd
, NULL
, TRUE
);
1062 /* reset the vertical scroll bar */
1063 if (IsVScrollBar(hwnd
))
1065 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1066 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1071 /*********************************************************************
1072 * EDIT_KeyVScrollDoc
1074 * Scroll text to top and bottom of document using keyboard.
1076 static void EDIT_KeyVScrollDoc(HWND hwnd
, WORD opt
)
1079 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1081 if (!IsMultiLine(hwnd
))
1085 es
->wtop
= es
->wleft
= 0;
1086 else if (es
->wtop
+ es
->ClientHeight
< es
->wlines
)
1088 es
->wtop
= es
->wlines
- es
->ClientHeight
;
1092 es
->CurrLine
= es
->wlines
;
1093 es
->WndRow
= es
->wlines
- es
->wtop
;
1095 InvalidateRect(hwnd
, NULL
, TRUE
);
1098 /* reset the vertical scroll bar */
1099 if (IsVScrollBar(hwnd
))
1101 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1102 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1106 /*********************************************************************
1109 * Delete character to right of cursor.
1111 static void EDIT_DelKey(HWND hwnd
)
1114 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1115 char *currchar
= CurrChar
;
1116 BOOL repaint
= *currchar
== '\n';
1118 if (IsMultiLine(hwnd
) && *currchar
== '\n' && *(currchar
+ 1) == '\0')
1120 strcpy(currchar
, currchar
+ 1);
1121 NOTIFY_PARENT(hwnd
, EN_UPDATE
);
1125 EDIT_BuildTextPointers(hwnd
);
1126 GetClientRect(hwnd
, &rc
);
1127 rc
.top
= es
->WndRow
* es
->txtht
;
1128 InvalidateRect(hwnd
, &rc
, FALSE
);
1133 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, -1);
1134 EDIT_WriteTextLine(hwnd
, NULL
, es
->WndRow
+ es
->wtop
);
1137 es
->TextChanged
= TRUE
;
1138 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1141 /*********************************************************************
1144 * Scroll text vertically by one line using scrollbars.
1146 static void EDIT_VScrollLine(HWND hwnd
, WORD opt
)
1150 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1152 dprintf_edit(stddeb
,"EDIT_VScrollLine: direction=%d\n", opt
);
1154 if (opt
== SB_LINEDOWN
)
1156 /* move down one line */
1157 if (es
->wtop
+ es
->ClientHeight
>= es
->wlines
)
1163 /* move up one line */
1169 if (IsWindowVisible(hwnd
))
1171 /* adjust client bottom to nearest whole line */
1172 GetClientRect(hwnd
, &rc
);
1173 rc
.bottom
= (rc
.bottom
/ es
->txtht
) * es
->txtht
;
1175 if (opt
== SB_LINEUP
)
1177 /* move up one line (scroll window down) */
1178 ScrollWindow(hwnd
, 0, es
->txtht
, &rc
, &rc
);
1179 /* write top line */
1180 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
);
1185 /* move down one line (scroll window up) */
1186 ScrollWindow(hwnd
, 0, -(es
->txtht
), &rc
, &rc
);
1187 /* write bottom line */
1188 y
= ((rc
.bottom
- rc
.top
/ es
->txtht
) - 1);
1189 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ y
);
1196 /*********************************************************************
1199 * Scroll text vertically by one page using keyboard.
1201 static void EDIT_VScrollPage(HWND hwnd
, WORD opt
)
1204 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1206 if (opt
== SB_PAGEUP
)
1209 es
->wtop
-= es
->ClientHeight
;
1213 if (es
->wtop
+ es
->ClientHeight
< es
->wlines
)
1215 es
->wtop
+= es
->ClientHeight
;
1216 if (es
->wtop
> es
->wlines
- es
->ClientHeight
)
1217 es
->wtop
= es
->wlines
- es
->ClientHeight
;
1223 InvalidateRect(hwnd
, NULL
, TRUE
);
1226 /* reset the vertical scroll bar */
1227 if (IsVScrollBar(hwnd
))
1229 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1230 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1234 /*********************************************************************
1237 * Convert a pixel offset in the given row to a character offset,
1238 * adjusting the pixel offset to the nearest whole character if
1241 static int EDIT_PixelToChar(HWND hwnd
, int row
, int *pixel
)
1243 int ch
= 0, i
= 0, s_i
= 0;
1246 dprintf_edit(stddeb
,"EDIT_PixelToChar: row=%d, pixel=%d\n", row
, *pixel
);
1248 text
= EDIT_TextLine(hwnd
, row
);
1252 i
+= EDIT_CharWidth(hwnd
, (BYTE
)(*(text
+ ch
)), i
);
1256 /* if stepped past _pixel_, go back a character */
1266 /*********************************************************************
1269 * Clear text from text buffer.
1271 static void EDIT_ClearText(HWND hwnd
)
1273 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1274 unsigned int blen
= EditBufStartLen(hwnd
) + 2;
1277 dprintf_edit(stddeb
,"EDIT_ClearText %d\n",blen
);
1278 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, blen
);
1279 text
= EDIT_HeapLock(hwnd
, es
->hText
);
1280 memset(text
, 0, blen
);
1283 es
->CurrLine
= es
->CurrCol
= 0;
1284 es
->WndRow
= es
->WndCol
= 0;
1285 es
->wleft
= es
->wtop
= 0;
1287 es
->TextChanged
= FALSE
;
1288 EDIT_ClearTextPointers(hwnd
);
1291 /*********************************************************************
1294 * Return line and column in text buffer from character offset.
1296 static void EDIT_GetLineCol(HWND hwnd
, int off
, int *line
, int *col
)
1300 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1301 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
1303 /* check for (0,0) */
1304 if (!off
|| !es
->wlines
)
1311 if (off
< 0 || off
> strlen(text
)) off
= strlen(text
);
1313 for (lineno
= 0; lineno
< es
->wlines
; lineno
++)
1315 cp
= text
+ es
->textptrs
[lineno
];
1316 if (off
== (int)(cp
- text
))
1322 if (off
< (int)(cp
- text
))
1327 *col
= off
- (int)(cp1
- text
);
1329 if (*(text
+ *col
) == '\0')
1334 /*********************************************************************
1337 * Clear the current selection.
1339 static void EDIT_ClearSel(HWND hwnd
)
1341 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1343 es
->SelBegLine
= es
->SelBegCol
= 0;
1344 es
->SelEndLine
= es
->SelEndCol
= 0;
1346 InvalidateRect(hwnd
, NULL
, TRUE
);
1350 /*********************************************************************
1351 * EDIT_SaveDeletedText
1353 * Save deleted text in deleted text buffer.
1355 static void EDIT_SaveDeletedText(HWND hwnd
, char *deltext
, int len
,
1359 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1361 dprintf_edit( stddeb
, "EDIT_SaveDeletedText\n" );
1362 if (!es
->hDeletedText
)
1363 es
->hDeletedText
= GlobalAlloc( GMEM_MOVEABLE
, len
);
1365 es
->hDeletedText
= GlobalReAlloc(es
->hDeletedText
, len
, GMEM_MOVEABLE
);
1366 if (!es
->hDeletedText
) return;
1367 text
= (char *)GlobalLock(es
->hDeletedText
);
1368 memcpy(text
, deltext
, len
);
1369 GlobalUnlock(es
->hDeletedText
);
1370 es
->DeletedLength
= len
;
1371 es
->DeletedCurrLine
= line
;
1372 es
->DeletedCurrCol
= col
;
1375 /*********************************************************************
1378 * Delete the current selected text (if any)
1380 static void EDIT_DeleteSel(HWND hwnd
)
1384 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1388 bbl
= EDIT_TextLine(hwnd
, es
->SelBegLine
) + es
->SelBegCol
;
1389 bel
= EDIT_TextLine(hwnd
, es
->SelEndLine
) + es
->SelEndCol
;
1390 len
= (int)(bel
- bbl
);
1391 EDIT_SaveDeletedText(hwnd
, bbl
, len
, es
->SelBegLine
, es
->SelBegCol
);
1392 es
->TextChanged
= TRUE
;
1395 es
->CurrLine
= es
->SelBegLine
;
1396 es
->CurrCol
= es
->SelBegCol
;
1397 es
->WndRow
= es
->SelBegLine
- es
->wtop
;
1400 es
->wtop
= es
->SelBegLine
;
1403 es
->WndCol
= EDIT_StrWidth(hwnd
, bbl
- es
->SelBegCol
,
1404 es
->SelBegCol
, 0) - es
->wleft
;
1406 EDIT_BuildTextPointers(hwnd
);
1407 es
->PaintBkgd
= TRUE
;
1408 EDIT_ClearSel(hwnd
);
1412 /*********************************************************************
1413 * EDIT_TextLineNumber
1415 * Return the line number in the text buffer of the supplied
1416 * character pointer.
1418 static int EDIT_TextLineNumber(HWND hwnd
, char *lp
)
1422 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1423 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
1425 for (lineno
= 0; lineno
< es
->wlines
; lineno
++)
1427 cp
= text
+ es
->textptrs
[lineno
];
1436 /*********************************************************************
1439 * Set down anchor for text marking.
1441 static void EDIT_SetAnchor(HWND hwnd
, int row
, int col
)
1444 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1449 EDIT_ClearSel(hwnd
);
1451 es
->SelBegLine
= es
->SelEndLine
= row
;
1452 es
->SelBegCol
= es
->SelEndCol
= col
;
1455 InvalidateRect(hwnd
, NULL
, FALSE
);
1460 /*********************************************************************
1463 * Display selection by reversing pixels in selected text.
1464 * If end == -1, selection applies to end of line.
1466 static void EDIT_WriteSel(HWND hwnd
, int y
, int start
, int end
)
1472 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1474 dprintf_edit(stddeb
,"EDIT_WriteSel: y=%d start=%d end=%d\n", y
, start
,end
);
1475 GetClientRect(hwnd
, &rc
);
1477 /* make sure y is within the window */
1478 if (y
< es
->wtop
|| y
> (es
->wtop
+ es
->ClientHeight
))
1481 /* get pointer to text */
1482 cp
= EDIT_TextLine(hwnd
, y
);
1484 /* get length of line if end == -1 */
1486 end
= EDIT_LineLength(hwnd
, y
);
1488 scol
= EDIT_StrWidth(hwnd
, cp
, start
, 0) - es
->wleft
;
1489 if (scol
> rc
.right
) return;
1490 if (scol
< rc
.left
) scol
= rc
.left
;
1491 ecol
= EDIT_StrWidth(hwnd
, cp
, end
, 0) - es
->wleft
;
1492 if (ecol
< rc
.left
) return;
1493 if (ecol
> rc
.right
) ecol
= rc
.right
;
1496 rcInvert
.left
= scol
;
1497 rcInvert
.top
= (y
- es
->wtop
) * es
->txtht
;
1498 rcInvert
.right
= ecol
;
1499 rcInvert
.bottom
= (y
- es
->wtop
+ 1) * es
->txtht
;
1500 InvertRect(hdc
, (LPRECT
) &rcInvert
);
1501 ReleaseDC(hwnd
, hdc
);
1504 /*********************************************************************
1507 * Extend selection to the given screen co-ordinates.
1509 static void EDIT_ExtendSel(HWND hwnd
, INT x
, INT y
)
1511 int bbl
, bel
, bbc
, bec
;
1514 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1516 dprintf_edit(stddeb
,"EDIT_ExtendSel: x=%d, y=%d\n", x
, y
);
1518 bbl
= es
->SelEndLine
;
1519 bbc
= es
->SelEndCol
;
1521 if (IsMultiLine(hwnd
))
1523 if ((line
= es
->wtop
+ y
/ es
->txtht
) >= es
->wlines
)
1524 line
= es
->wlines
- 1;
1529 cp
= EDIT_TextLine(hwnd
, line
);
1530 len
= EDIT_LineLength(hwnd
, line
);
1532 es
->WndRow
= y
/ es
->txtht
;
1533 if (!IsMultiLine(hwnd
))
1535 else if (es
->WndRow
> es
->wlines
- es
->wtop
- 1)
1536 es
->WndRow
= es
->wlines
- es
->wtop
- 1;
1537 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
1538 es
->SelEndLine
= es
->CurrLine
;
1540 es
->WndCol
= es
->wleft
+ max(x
,0);
1541 if (es
->WndCol
> EDIT_StrWidth(hwnd
, cp
, len
, 0))
1542 es
->WndCol
= EDIT_StrWidth(hwnd
, cp
, len
, 0);
1543 es
->CurrCol
= EDIT_PixelToChar(hwnd
, es
->CurrLine
, &(es
->WndCol
));
1544 es
->WndCol
-= es
->wleft
;
1545 es
->SelEndCol
= es
->CurrCol
;
1547 bel
= es
->SelEndLine
;
1548 bec
= es
->SelEndCol
;
1550 /* return if no new characters to mark */
1551 if (bbl
== bel
&& bbc
== bec
)
1554 /* put lowest marker first */
1560 if (bbl
== bel
&& bbc
> bec
)
1563 for (y
= bbl
; y
<= bel
; y
++)
1565 if (y
== bbl
&& y
== bel
)
1566 EDIT_WriteSel(hwnd
, y
, bbc
, bec
);
1568 EDIT_WriteSel(hwnd
, y
, bbc
, -1);
1570 EDIT_WriteSel(hwnd
, y
, 0, bec
);
1572 EDIT_WriteSel(hwnd
, y
, 0, -1);
1576 /*********************************************************************
1579 * Stop text marking (selection).
1581 static void EDIT_StopMarking(HWND hwnd
)
1583 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1585 TextMarking
= FALSE
;
1586 if (es
->SelBegLine
> es
->SelEndLine
)
1588 SWAP_INT((es
->SelBegLine
), (es
->SelEndLine
));
1589 SWAP_INT((es
->SelBegCol
), (es
->SelEndCol
));
1591 if (es
->SelBegLine
== es
->SelEndLine
&& es
->SelBegCol
> es
->SelEndCol
)
1592 SWAP_INT((es
->SelBegCol
), (es
->SelEndCol
));
1595 /*********************************************************************
1598 * Insert text at current line and column.
1600 static void EDIT_InsertText(HWND hwnd
, char *str
, int len
)
1603 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1604 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
1606 plen
= strlen(text
) + len
;
1607 if (plen
+ 1 > es
->textlen
)
1609 dprintf_edit(stddeb
,"InsertText: Realloc\n");
1610 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, es
->textlen
+ len
);
1611 text
= EDIT_HeapLock(hwnd
, es
->hText
);
1612 es
->textlen
= plen
+ 1;
1614 memmove(CurrChar
+ len
, CurrChar
, strlen(CurrChar
) + 1);
1615 memcpy(CurrChar
, str
, len
);
1617 EDIT_BuildTextPointers(hwnd
);
1618 es
->PaintBkgd
= TRUE
;
1619 es
->TextChanged
= TRUE
;
1621 EDIT_GetLineCol(hwnd
, (int)((CurrChar
+ len
) - text
), &(es
->CurrLine
),
1623 es
->WndRow
= es
->CurrLine
- es
->wtop
;
1624 es
->WndCol
= EDIT_StrWidth(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
1625 es
->CurrCol
, 0) - es
->wleft
;
1628 /*********************************************************************
1629 * EDIT_ClearDeletedText
1631 * Clear deleted text buffer.
1633 static void EDIT_ClearDeletedText(HWND hwnd
)
1635 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1637 GlobalFree(es
->hDeletedText
);
1638 es
->hDeletedText
= 0;
1639 es
->DeletedLength
= 0;
1642 /*********************************************************************
1643 * EDIT_CopyToClipboard
1645 * Copy the specified text to the clipboard.
1647 static void EDIT_CopyToClipboard(HWND hwnd
)
1653 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1655 bbl
= EDIT_TextLine(hwnd
, es
->SelBegLine
) + es
->SelBegCol
;
1656 bel
= EDIT_TextLine(hwnd
, es
->SelEndLine
) + es
->SelEndCol
;
1657 len
= (int)(bel
- bbl
);
1659 hMem
= GlobalAlloc(GHND
, (DWORD
)(len
+ 1));
1660 lpMem
= GlobalLock(hMem
);
1662 for (i
= 0; i
< len
; i
++)
1666 OpenClipboard(hwnd
);
1668 SetClipboardData(CF_TEXT
, hMem
);
1672 /*********************************************************************
1675 * Process keystrokes that produce displayable characters.
1677 static void EDIT_KeyTyped(HWND hwnd
, short ch
)
1679 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1680 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
1683 BOOL FullPaint
= FALSE
;
1685 dprintf_edit(stddeb
,"EDIT_KeyTyped: ch=%c\n", (char)ch
);
1687 /* delete selected text (if any) */
1689 EDIT_DeleteSel(hwnd
);
1691 /* currchar must be assigned after deleting the selection */
1692 currchar
= CurrChar
;
1694 /* test for typing at end of maximum buffer size */
1695 if (currchar
== text
+ es
->MaxTextLen
)
1697 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1701 if (*currchar
== '\0' && IsMultiLine(hwnd
))
1703 /* insert a newline at end of text */
1705 *(currchar
+ 1) = '\n';
1706 *(currchar
+ 2) = '\0';
1707 EDIT_BuildTextPointers(hwnd
);
1710 /* insert the typed character */
1711 if (text
[es
->textlen
- 1] != '\0')
1713 /* current text buffer is full */
1714 if (es
->textlen
== es
->MaxTextLen
)
1716 /* text buffer is at maximum size */
1717 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1721 /* increase the text buffer size */
1722 es
->textlen
+= GROWLENGTH
;
1723 /* but not above maximum size */
1724 if (es
->textlen
> es
->MaxTextLen
)
1725 es
->textlen
= es
->MaxTextLen
;
1726 dprintf_edit( stddeb
, "EDIT_KeyTyped: realloc\n" );
1727 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, es
->textlen
+ 2);
1729 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1730 text
= EDIT_HeapLock(hwnd
, es
->hText
);
1731 text
[es
->textlen
- 1] = '\0';
1732 currchar
= CurrChar
;
1734 /* make space for new character and put char in buffer */
1737 memmove(currchar
+ 2, currchar
, strlen(currchar
) + 1);
1739 *(currchar
+ 1) = '\n';
1740 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, 2);
1744 memmove(currchar
+ 1, currchar
, strlen(currchar
) + 1);
1746 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, 1);
1748 es
->TextChanged
= TRUE
;
1749 NOTIFY_PARENT(hwnd
, EN_UPDATE
);
1751 /* re-adjust textwidth, if necessary, and redraw line */
1753 if (IsMultiLine(hwnd
) && es
->wlines
> 1)
1755 es
->textwidth
= max(es
->textwidth
,
1756 EDIT_StrWidth(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
1757 (int)(EDIT_TextLine(hwnd
, es
->CurrLine
+ 1) -
1758 EDIT_TextLine(hwnd
, es
->CurrLine
)), 0));
1760 es
->textwidth
= max(es
->textwidth
,
1761 EDIT_StrWidth(hwnd
, text
, strlen(text
), 0));
1769 EDIT_BuildTextPointers(hwnd
);
1773 /* invalidate rest of window */
1774 GetClientRect(hwnd
, &rc
);
1776 rc
.top
= es
->WndRow
* es
->txtht
;
1777 InvalidateRect(hwnd
, &rc
, FALSE
);
1779 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1782 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1786 /* test end of window */
1787 if (es
->WndCol
>= es
->ClientWidth
-
1788 EDIT_CharWidth(hwnd
, (BYTE
)ch
, es
->WndCol
+ es
->wleft
))
1790 /* TODO:- Word wrap to be handled here */
1792 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1793 EDIT_KeyHScroll(hwnd
, SB_LINEDOWN
);
1795 es
->WndCol
+= EDIT_CharWidth(hwnd
, (BYTE
)ch
, es
->WndCol
+ es
->wleft
);
1797 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ es
->WndRow
);
1798 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1800 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1801 dprintf_edit(stddeb
,"KeyTyped O.K.\n");
1804 /*********************************************************************
1805 * EM_UNDO message function
1807 static LONG
EDIT_UndoMsg(HWND hwnd
)
1810 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1812 if (es
->hDeletedText
)
1814 text
= (char *)GlobalLock(es
->hDeletedText
);
1815 es
->CurrLine
= es
->DeletedCurrLine
;
1816 es
->CurrCol
= es
->DeletedCurrCol
;
1817 EDIT_InsertText(hwnd
, text
, es
->DeletedLength
);
1818 GlobalUnlock(es
->hDeletedText
);
1819 EDIT_ClearDeletedText(hwnd
);
1821 es
->SelBegLine
= es
->CurrLine
;
1822 es
->SelBegCol
= es
->CurrCol
;
1823 EDIT_GetLineCol(hwnd
, (int)((CurrChar
+ es
->DeletedLength
) - text
),
1824 &(es
->CurrLine
), &(es
->CurrCol
));
1825 es
->WndRow
= es
->CurrLine
- es
->wtop
;
1826 es
->WndCol
= EDIT_StrWidth(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
1827 es
->CurrCol
, 0) - es
->wleft
;
1828 es
->SelEndLine
= es
->CurrLine
;
1829 es
->SelEndCol
= es
->CurrCol
;
1831 InvalidateRect(hwnd
, NULL
, TRUE
);
1839 /*********************************************************************
1840 * EM_SETHANDLE message function
1842 static void EDIT_SetHandleMsg(HWND hwnd
, WORD wParam
)
1844 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1846 if (IsMultiLine(hwnd
))
1849 es
->textlen
= EDIT_HeapSize(hwnd
, es
->hText
);
1851 es
->wtop
= es
->wleft
= 0;
1852 es
->CurrLine
= es
->CurrCol
= 0;
1853 es
->WndRow
= es
->WndCol
= 0;
1854 es
->TextChanged
= FALSE
;
1856 es
->SelBegLine
= es
->SelBegCol
= 0;
1857 es
->SelEndLine
= es
->SelEndCol
= 0;
1858 dprintf_edit(stddeb
, "EDIT_SetHandleMsg: handle %04x, textlen=%d\n",
1859 wParam
, es
->textlen
);
1861 EDIT_BuildTextPointers(hwnd
);
1862 es
->PaintBkgd
= TRUE
;
1863 InvalidateRect(hwnd
, NULL
, TRUE
);
1868 /*********************************************************************
1869 * EM_SETTABSTOPS message function
1871 static LONG
EDIT_SetTabStopsMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
1873 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1875 dprintf_edit( stddeb
, "EDIT_SetTabStops\n" );
1876 es
->NumTabStops
= wParam
;
1878 es
->TabStops
= realloc(es
->TabStops
, 2);
1879 else if (wParam
== 1)
1881 es
->TabStops
= realloc(es
->TabStops
, 2);
1882 es
->TabStops
[0] = LOWORD(lParam
);
1886 es
->TabStops
= realloc(es
->TabStops
, wParam
* sizeof(*es
->TabStops
));
1887 memcpy(es
->TabStops
, (unsigned short *)PTR_SEG_TO_LIN(lParam
), wParam
);
1892 /*********************************************************************
1893 * EM_GETLINE message function
1895 static LONG
EDIT_GetLineMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
1899 unsigned char *buffer
= (char *)lParam
;
1901 cp
= EDIT_TextLine(hwnd
, wParam
);
1902 cp1
= EDIT_TextLine(hwnd
, wParam
+ 1);
1903 len
= min((int)(cp1
- cp
), (WORD
)(*buffer
));
1904 dprintf_edit( stddeb
, "EDIT_GetLineMsg: %d %d, len %d\n", (int)(WORD
)(*buffer
), (int)(WORD
)(*(char *)buffer
), len
);
1905 strncpy(buffer
, cp
, len
);
1910 /*********************************************************************
1911 * EM_GETSEL message function
1913 static LONG
EDIT_GetSelMsg(HWND hwnd
)
1916 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1918 so
= es
->textptrs
[es
->SelBegLine
] + es
->SelBegCol
;
1919 eo
= es
->textptrs
[es
->SelEndLine
] + es
->SelEndCol
;
1921 return MAKELONG(so
, eo
);
1924 /*********************************************************************
1925 * EM_REPLACESEL message function
1927 static void EDIT_ReplaceSel(HWND hwnd
, LONG lParam
)
1929 EDIT_DeleteSel(hwnd
);
1930 EDIT_InsertText(hwnd
, (char *)PTR_SEG_TO_LIN(lParam
),
1931 strlen((char *)PTR_SEG_TO_LIN(lParam
)));
1932 InvalidateRect(hwnd
, NULL
, TRUE
);
1936 /*********************************************************************
1937 * EM_LINEFROMCHAR message function
1939 static LONG
EDIT_LineFromCharMsg(HWND hwnd
, WORD wParam
)
1942 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1944 if (wParam
== (WORD
)-1)
1945 return (LONG
)(es
->SelBegLine
);
1947 EDIT_GetLineCol(hwnd
, wParam
, &row
, &col
);
1953 /*********************************************************************
1954 * EM_LINEINDEX message function
1956 static LONG
EDIT_LineIndexMsg(HWND hwnd
, WORD wParam
)
1958 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1960 if (wParam
== (WORD
)-1) wParam
= es
->CurrLine
;
1961 return es
->textptrs
[wParam
];
1965 /*********************************************************************
1966 * EM_LINELENGTH message function
1968 static LONG
EDIT_LineLengthMsg(HWND hwnd
, WORD wParam
)
1971 int sbl
, sbc
, sel
, sec
;
1972 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1974 if (wParam
== (WORD
)-1)
1978 sbl
= es
->SelBegLine
;
1979 sbc
= es
->SelBegCol
;
1980 sel
= es
->SelEndLine
;
1981 sec
= es
->SelEndCol
;
1988 if (sbl
== sel
&& sbc
> sec
)
1993 len
= es
->textptrs
[sbl
+ 1] - es
->textptrs
[sbl
] - 1;
1994 return len
- sec
- sbc
;
1997 len
= es
->textptrs
[sel
+ 1] - es
->textptrs
[sel
] - sec
- 1;
2000 else /* no selection marked */
2002 len
= es
->textptrs
[es
->CurrLine
+ 1] - es
->textptrs
[es
->CurrLine
] - 1;
2006 else /* line number specified */
2008 EDIT_GetLineCol(hwnd
, wParam
, &row
, &col
);
2009 len
= es
->textptrs
[row
+ 1] - es
->textptrs
[row
];
2014 /*********************************************************************
2015 * EM_SETSEL message function
2017 static void EDIT_SetSelMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2020 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2022 so
= LOWORD(lParam
);
2023 eo
= HIWORD(lParam
);
2025 if (so
== -1) /* if so == -1, clear selection */
2027 EDIT_ClearSel(hwnd
);
2031 if (so
== eo
) /* if so == eo, set caret only */
2033 EDIT_GetLineCol(hwnd
, (int) so
, &(es
->CurrLine
), &(es
->CurrCol
));
2034 es
->WndRow
= es
->CurrLine
- es
->wtop
;
2038 if (es
->WndRow
< 0 || es
->WndRow
> es
->ClientHeight
)
2040 es
->wtop
= es
->CurrLine
;
2043 es
->WndCol
= EDIT_StrWidth(hwnd
,
2044 EDIT_TextLine(hwnd
, es
->CurrLine
),
2045 es
->CurrCol
, 0) - es
->wleft
;
2046 if (es
->WndCol
> es
->ClientWidth
)
2048 es
->wleft
= es
->WndCol
;
2051 else if (es
->WndCol
< 0)
2053 es
->wleft
+= es
->WndCol
;
2058 else /* otherwise set selection */
2060 if (eo
>= 0 && so
> eo
) /* eo == -1 flag to extend to end of text */
2068 EDIT_GetLineCol(hwnd
, (int) so
, &(es
->SelBegLine
), &(es
->SelBegCol
));
2069 EDIT_GetLineCol(hwnd
, (int) eo
, &(es
->SelEndLine
), &(es
->SelEndCol
));
2070 es
->CurrLine
= es
->SelEndLine
;
2071 es
->CurrCol
= es
->SelEndCol
;
2072 es
->WndRow
= es
->SelEndLine
- es
->wtop
;
2074 if (!wParam
) /* don't suppress scrolling of text */
2078 es
->wtop
= es
->SelEndLine
;
2081 else if (es
->WndRow
> es
->ClientHeight
)
2083 es
->wtop
+= es
->WndRow
- es
->ClientHeight
;
2084 es
->WndRow
= es
->ClientHeight
;
2086 es
->WndCol
= EDIT_StrWidth(hwnd
,
2087 EDIT_TextLine(hwnd
, es
->SelEndLine
),
2088 es
->SelEndCol
, 0) - es
->wleft
;
2089 if (es
->WndCol
> es
->ClientWidth
)
2091 es
->wleft
+= es
->WndCol
- es
->ClientWidth
;
2092 es
->WndCol
= es
->ClientWidth
;
2094 else if (es
->WndCol
< 0)
2096 es
->wleft
+= es
->WndCol
;
2101 InvalidateRect(hwnd
, NULL
, TRUE
);
2106 /*********************************************************************
2109 static void EDIT_WM_SetFont(HWND hwnd
, WORD wParam
, LONG lParam
)
2114 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2118 oldfont
= (HFONT
)SelectObject(hdc
, (HANDLE
)es
->hFont
);
2119 GetCharWidth(hdc
, 0, 255, es
->CharWidths
);
2120 GetTextMetrics(hdc
, &tm
);
2121 es
->txtht
= tm
.tmHeight
+ tm
.tmExternalLeading
;
2122 SelectObject(hdc
, (HANDLE
)oldfont
);
2123 ReleaseDC(hwnd
, hdc
);
2125 es
->WndRow
= (es
->CurrLine
- es
->wtop
) / es
->txtht
;
2126 es
->WndCol
= EDIT_StrWidth(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
2127 es
->CurrCol
, 0) - es
->wleft
;
2129 InvalidateRect(hwnd
, NULL
, TRUE
);
2130 es
->PaintBkgd
= TRUE
;
2131 if (lParam
) UpdateWindow(hwnd
);
2132 EDIT_RecalcSize(hwnd
,es
);
2135 /*********************************************************************
2138 static void EDIT_WM_Paste(HWND hwnd
)
2143 OpenClipboard(hwnd
);
2144 if (!(hClipMem
= GetClipboardData(CF_TEXT
)))
2146 /* no text in clipboard */
2150 lpClipMem
= GlobalLock(hClipMem
);
2151 EDIT_InsertText(hwnd
, lpClipMem
, strlen(lpClipMem
));
2152 GlobalUnlock(hClipMem
);
2154 InvalidateRect(hwnd
, NULL
, TRUE
);
2158 /*********************************************************************
2161 static void EDIT_WM_Paint(HWND hwnd
)
2167 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2169 hdc
= BeginPaint(hwnd
, &ps
);
2172 dprintf_edit(stddeb
,"WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc
.left
, rc
.top
,
2173 rc
.right
, rc
.bottom
);
2176 FillWindow(GetParent(hwnd
), hwnd
, hdc
, CTLCOLOR_EDIT
);
2178 for (y
= (rc
.top
/ es
->txtht
); y
<= (rc
.bottom
/ es
->txtht
); y
++)
2180 if (y
< (IsMultiLine(hwnd
) ? es
->wlines
: 1) - es
->wtop
)
2181 EDIT_WriteTextLine(hwnd
, &rc
, y
+ es
->wtop
);
2184 EndPaint(hwnd
, &ps
);
2187 /*********************************************************************
2190 static long EDIT_WM_NCCreate(HWND hwnd
, LONG lParam
)
2192 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
2193 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2197 /* store pointer to local or global heap in window structure so that */
2198 /* EDITSTATE structure itself can be stored on local heap */
2200 /* allocate space for state variable structure */
2201 es
= malloc( sizeof(EDITSTATE
) );
2202 SetWindowLong( hwnd
, 0, (LONG
)es
);
2203 es
->textptrs
= malloc(sizeof(int));
2204 es
->CharWidths
= malloc(256 * sizeof(short));
2205 es
->ClientWidth
= es
->ClientHeight
= 1;
2206 /* --- text buffer */
2207 es
->MaxTextLen
= MAXTEXTLEN
+ 1;
2208 if (!(createStruct
->lpszName
))
2210 dprintf_edit( stddeb
, "EDIT_WM_NCCREATE: lpszName == 0\n" );
2211 es
->textlen
= EditBufStartLen(hwnd
) + 1;
2212 es
->hText
= EDIT_HeapAlloc(hwnd
, es
->textlen
+ 2, LMEM_MOVEABLE
);
2213 text
= EDIT_HeapLock(hwnd
, es
->hText
);
2214 memset(text
, 0, es
->textlen
+ 2);
2217 EDIT_ClearTextPointers(hwnd
);
2218 if (IsMultiLine(hwnd
)) strcpy(text
, "\r\n");
2219 EDIT_BuildTextPointers(hwnd
);
2223 char *windowName
= (char *)PTR_SEG_TO_LIN( createStruct
->lpszName
);
2224 dprintf_edit( stddeb
, "EDIT_WM_NCCREATE: lpszName != 0\n" );
2225 if (strlen(windowName
) < EditBufStartLen(hwnd
))
2227 es
->textlen
= EditBufStartLen(hwnd
) + 3;
2228 es
->hText
= EDIT_HeapAlloc(hwnd
, es
->textlen
+ 2, LMEM_MOVEABLE
);
2229 text
= EDIT_HeapLock(hwnd
, es
->hText
);
2230 strcpy(text
, windowName
);
2231 if(IsMultiLine(hwnd
)) {
2232 strcat(text
, "\r\n");
2234 *(text
+ es
->textlen
) = '\0';
2238 es
->textlen
= strlen(windowName
) + 3;
2239 es
->hText
= EDIT_HeapAlloc(hwnd
, es
->textlen
+ 2, LMEM_MOVEABLE
);
2240 text
= EDIT_HeapLock(hwnd
, es
->hText
);
2241 strcpy(text
, windowName
);
2242 if(IsMultiLine(hwnd
)) strcat(text
, "\r\n");
2243 *(text
+ es
->textlen
) = '\0';
2245 *(text
+ es
->textlen
+ 1) = '\0';
2246 EDIT_BuildTextPointers(hwnd
);
2249 /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
2250 /* the corresponding WS_* style is set */
2251 if (createStruct
->style
& WS_VSCROLL
)
2252 wndPtr
->dwStyle
|= ES_AUTOVSCROLL
;
2253 if (createStruct
->style
& WS_HSCROLL
)
2254 wndPtr
->dwStyle
|= ES_AUTOHSCROLL
;
2256 /* remove the WS_CAPTION style if it has been set - this is really a */
2257 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
2258 if (wndPtr
->dwStyle
& WS_BORDER
&& wndPtr
->dwStyle
& WS_DLGFRAME
)
2259 wndPtr
->dwStyle
^= WS_DLGFRAME
;
2264 /*********************************************************************
2267 static long EDIT_WM_Create(HWND hwnd
, LONG lParam
)
2270 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2274 /* initialize state variable structure */
2277 /* --- char width array */
2278 /* only initialise chars <= 32 as X returns strange widths */
2279 /* for other chars */
2280 memset(es
->CharWidths
, 0, 256 * sizeof(short));
2281 GetCharWidth(hdc
, 32, 254, &es
->CharWidths
[32]);
2283 /* --- other structure variables */
2284 GetTextMetrics(hdc
, &tm
);
2285 es
->txtht
= tm
.tmHeight
+ tm
.tmExternalLeading
;
2286 EDIT_RecalcSize(hwnd
,es
);
2287 es
->wtop
= es
->wleft
= 0;
2288 es
->CurrCol
= es
->CurrLine
= 0;
2289 es
->WndCol
= es
->WndRow
= 0;
2290 es
->TextChanged
= FALSE
;
2291 es
->SelBegLine
= es
->SelBegCol
= 0;
2292 es
->SelEndLine
= es
->SelEndCol
= 0;
2294 es
->hDeletedText
= 0;
2295 es
->DeletedLength
= 0;
2296 es
->NumTabStops
= 0;
2297 es
->TabStops
= malloc( sizeof(short) );
2299 /* allocate space for a line full of blanks to speed up */
2301 es
->BlankLine
= malloc( (es
->ClientWidth
/ es
->CharWidths
[32]) + 2);
2302 memset(es
->BlankLine
, ' ', (es
->ClientWidth
/ es
->CharWidths
[32]) + 2);
2303 es
->BlankLine
[(es
->ClientWidth
/ es
->CharWidths
[32]) + 1] = 0;
2305 /* set up text cursor for edit class */
2306 CLASS_FindClassByName("EDIT", 0, &classPtr
);
2307 classPtr
->wc
.hCursor
= LoadCursor(0, IDC_IBEAM
);
2309 /* paint background on first WM_PAINT */
2310 es
->PaintBkgd
= TRUE
;
2312 ReleaseDC(hwnd
, hdc
);
2316 /*********************************************************************
2319 static void EDIT_WM_VScroll(HWND hwnd
, WORD wParam
, LONG lParam
)
2321 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2323 if (IsMultiLine(hwnd
))
2331 EDIT_VScrollLine(hwnd
, wParam
);
2336 EDIT_VScrollPage(hwnd
, wParam
);
2341 SetCaretPos(es
->WndCol
, es
->WndRow
);
2345 /*********************************************************************
2348 static void EDIT_WM_HScroll(HWND hwnd
, WORD wParam
, LONG lParam
)
2350 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2358 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2364 /*********************************************************************
2367 static void EDIT_WM_Size(HWND hwnd
, WORD wParam
, LONG lParam
)
2369 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2371 EDIT_RecalcSize(hwnd
,es
);
2372 if (wParam
!= SIZE_MAXIMIZED
&& wParam
!= SIZE_RESTORED
) return;
2373 InvalidateRect(hwnd
, NULL
, TRUE
);
2374 es
->PaintBkgd
= TRUE
;
2378 /*********************************************************************
2381 static void EDIT_WM_LButtonDown(HWND hwnd
, WORD wParam
, LONG lParam
)
2386 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2389 EDIT_ClearSel(hwnd
);
2391 es
->WndRow
= HIWORD(lParam
) / es
->txtht
;
2392 dprintf_edit( stddeb
, "EDIT_LButtonDown: %04x %08lx, WndRow %d\n", wParam
,
2393 lParam
, es
->WndRow
);
2394 if (!IsMultiLine(hwnd
)) es
->WndRow
= 0;
2395 else if (es
->WndRow
> es
->wlines
- es
->wtop
- 1)
2397 es
->WndRow
= es
->wlines
- es
->wtop
- 1;
2400 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
2402 cp
= EDIT_TextLine(hwnd
, es
->CurrLine
);
2403 len
= EDIT_LineLength(hwnd
, es
->CurrLine
);
2404 es
->WndCol
= LOWORD(lParam
) + es
->wleft
;
2405 if (end
|| es
->WndCol
> EDIT_StrWidth(hwnd
, cp
, len
, 0))
2406 es
->WndCol
= EDIT_StrWidth(hwnd
, cp
, len
, 0);
2407 dprintf_edit( stddeb
, "EDIT_LButtonDown: CurrLine %d wtop %d wndcol %d\n",
2408 es
->CurrLine
, es
->wtop
, es
->WndCol
);
2409 es
->CurrCol
= EDIT_PixelToChar(hwnd
, es
->CurrLine
, &(es
->WndCol
));
2410 es
->WndCol
-= es
->wleft
;
2413 ButtonRow
= es
->CurrLine
;
2414 ButtonCol
= es
->CurrCol
;
2417 /*********************************************************************
2420 static void EDIT_WM_MouseMove(HWND hwnd
, WORD wParam
, LONG lParam
)
2422 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2424 if (wParam
!= MK_LBUTTON
)
2430 EDIT_SetAnchor(hwnd
, ButtonRow
, ButtonCol
);
2437 EDIT_ExtendSel(hwnd
, LOWORD(lParam
), HIWORD(lParam
));
2438 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2443 /*********************************************************************
2446 static void EDIT_WM_Char(HWND hwnd
, WORD wParam
)
2448 dprintf_edit(stddeb
,"EDIT_WM_Char: wParam=%c\n", (char)wParam
);
2454 if (!IsMultiLine(hwnd
))
2457 EDIT_KeyTyped(hwnd
, wParam
);
2461 if (!IsMultiLine(hwnd
))
2463 EDIT_KeyTyped(hwnd
, wParam
);
2467 if (wParam
>= 20 && wParam
<= 254 && wParam
!= 127 )
2468 EDIT_KeyTyped(hwnd
, wParam
);
2473 /*********************************************************************
2476 static void EDIT_WM_KeyDown(HWND hwnd
, WORD wParam
)
2478 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2480 dprintf_edit(stddeb
,"EDIT_WM_KeyDown: key=%x\n", wParam
);
2487 EDIT_ClearSel(hwnd
);
2488 if (IsMultiLine(hwnd
))
2491 EDIT_Backward(hwnd
);
2496 EDIT_ClearSel(hwnd
);
2497 if (IsMultiLine(hwnd
))
2498 EDIT_Downward(hwnd
);
2505 EDIT_ClearSel(hwnd
);
2511 EDIT_ClearSel(hwnd
);
2512 EDIT_Backward(hwnd
);
2517 EDIT_ClearSel(hwnd
);
2523 EDIT_ClearSel(hwnd
);
2528 if (IsMultiLine(hwnd
))
2531 EDIT_ClearSel(hwnd
);
2532 EDIT_KeyVScrollPage(hwnd
, SB_PAGEUP
);
2537 if (IsMultiLine(hwnd
))
2540 EDIT_ClearSel(hwnd
);
2541 EDIT_KeyVScrollPage(hwnd
, SB_PAGEDOWN
);
2547 EDIT_DeleteSel(hwnd
);
2550 if (es
->CurrCol
== 0 && es
->CurrLine
== 0)
2552 EDIT_Backward(hwnd
);
2559 EDIT_DeleteSel(hwnd
);
2565 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2569 /*********************************************************************
2572 static LONG
EDIT_WM_SetText(HWND hwnd
, LONG lParam
)
2575 char *text
,*settext
;
2576 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2578 settext
= PTR_SEG_TO_LIN( lParam
);
2579 dprintf_edit( stddeb
,"WM_SetText, length %d\n",strlen(settext
) );
2580 if (strlen(settext
) <= es
->MaxTextLen
)
2582 len
= settext
!= NULL
? strlen(settext
) : 0;
2583 EDIT_ClearText(hwnd
);
2585 dprintf_edit( stddeb
, "EDIT_WM_SetText: realloc\n" );
2586 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, len
+ 3);
2587 text
= EDIT_HeapLock(hwnd
, es
->hText
);
2589 strcpy(text
, (char *)PTR_SEG_TO_LIN(lParam
));
2591 text
[len
+ 1] = '\0';
2592 text
[len
+ 2] = '\0';
2593 EDIT_BuildTextPointers(hwnd
);
2594 InvalidateRect(hwnd
, NULL
, TRUE
);
2595 es
->PaintBkgd
= TRUE
;
2596 es
->TextChanged
= TRUE
;
2603 /*********************************************************************
2606 LONG
EditWndProc(HWND hwnd
, WORD uMsg
, WORD wParam
, LONG lParam
)
2611 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2615 lResult
= es
->hDeletedText
;
2618 case EM_EMPTYUNDOBUFFER
:
2619 EDIT_ClearDeletedText(hwnd
);
2623 fprintf(stdnimp
,"edit: EM_FMTLINES message received\n");
2630 case EM_GETFIRSTVISIBLELINE
:
2635 lResult
= es
->hText
;
2639 if (IsMultiLine(hwnd
))
2640 lResult
= EDIT_GetLineMsg(hwnd
, wParam
, lParam
);
2645 case EM_GETLINECOUNT
:
2646 if (IsMultiLine(hwnd
))
2647 lResult
= es
->wlines
;
2653 lResult
= es
->TextChanged
;
2656 case EM_GETPASSWORDCHAR
:
2657 fprintf(stdnimp
,"edit: cannot process EM_GETPASSWORDCHAR message\n");
2661 GetWindowRect(hwnd
, (LPRECT
)PTR_SEG_TO_LIN(lParam
));
2665 lResult
= EDIT_GetSelMsg(hwnd
);
2668 case EM_GETWORDBREAKPROC
:
2669 fprintf(stdnimp
,"edit: cannot process EM_GETWORDBREAKPROC message\n");
2674 es
->MaxTextLen
= wParam
;
2675 else if (IsMultiLine(hwnd
))
2676 es
->MaxTextLen
= 65535;
2678 es
->MaxTextLen
= 32767;
2681 case EM_LINEFROMCHAR
:
2682 lResult
= EDIT_LineFromCharMsg(hwnd
, wParam
);
2686 if (IsMultiLine(hwnd
))
2687 lResult
= EDIT_LineIndexMsg(hwnd
, wParam
);
2693 lResult
= EDIT_LineLengthMsg(hwnd
, wParam
);
2697 fprintf(stdnimp
,"edit: cannot process EM_LINESCROLL message\n");
2702 EDIT_ReplaceSel(hwnd
, lParam
);
2703 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2709 EDIT_SetHandleMsg(hwnd
, wParam
);
2710 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2715 es
->TextChanged
= wParam
;
2718 case EM_SETPASSWORDCHAR
:
2719 fprintf(stdnimp
,"edit: cannot process EM_SETPASSWORDCHAR message\n");
2722 case EM_SETREADONLY
:
2723 fprintf(stdnimp
,"edit: cannot process EM_SETREADONLY message\n");
2728 fprintf(stdnimp
,"edit: cannot process EM_SETRECT(NP) message\n");
2733 EDIT_SetSelMsg(hwnd
, wParam
, lParam
);
2734 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2738 case EM_SETTABSTOPS
:
2739 lResult
= EDIT_SetTabStopsMsg(hwnd
, wParam
, lParam
);
2742 case EM_SETWORDBREAKPROC
:
2743 fprintf(stdnimp
,"edit: cannot process EM_SETWORDBREAKPROC message\n");
2748 lResult
= EDIT_UndoMsg(hwnd
);
2749 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2754 return DLGC_HASSETSEL
| DLGC_WANTCHARS
| DLGC_WANTARROWS
;
2757 EDIT_WM_Char(hwnd
, wParam
);
2761 EDIT_CopyToClipboard(hwnd
);
2762 EDIT_ClearSel(hwnd
);
2766 lResult
= EDIT_WM_Create(hwnd
, lParam
);
2770 EDIT_CopyToClipboard(hwnd
);
2771 EDIT_DeleteSel(hwnd
);
2776 free(es
->CharWidths
);
2778 free(es
->BlankLine
);
2779 EDIT_HeapFree(hwnd
, es
->hText
);
2780 free( EDIT_GetEditState(hwnd
) );
2784 InvalidateRect(hwnd
, NULL
, FALSE
);
2788 textPtr
= EDIT_HeapLock(hwnd
, es
->hText
);
2789 len
= strlen( textPtr
);
2790 if ((int)wParam
> len
)
2792 strcpy((char *)PTR_SEG_TO_LIN(lParam
), textPtr
);
2793 lResult
= (DWORD
)len
;
2797 EDIT_HeapUnlock(hwnd
, es
->hText
);
2800 case WM_GETTEXTLENGTH
:
2801 textPtr
= EDIT_HeapLock(hwnd
, es
->hText
);
2802 lResult
= (DWORD
)strlen(textPtr
);
2803 EDIT_HeapUnlock(hwnd
, es
->hText
);
2807 EDIT_WM_HScroll(hwnd
, wParam
, lParam
);
2811 EDIT_WM_KeyDown(hwnd
, wParam
);
2815 es
->HaveFocus
= FALSE
;
2817 if (SelMarked(es
)) EDIT_ClearSel(hwnd
);
2818 NOTIFY_PARENT(hwnd
, EN_KILLFOCUS
);
2821 case WM_LBUTTONDOWN
:
2825 EDIT_WM_LButtonDown(hwnd
, wParam
, lParam
);
2826 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2831 if (GetCapture() != hwnd
) break;
2835 EDIT_StopMarking(hwnd
);
2840 EDIT_WM_MouseMove(hwnd
, wParam
, lParam
);
2848 lResult
= EDIT_WM_NCCreate(hwnd
, lParam
);
2852 EDIT_WM_Paint(hwnd
);
2856 EDIT_WM_Paste(hwnd
);
2860 es
->HaveFocus
= TRUE
;
2861 CreateCaret(hwnd
, 0, 2, es
->txtht
);
2862 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2864 NOTIFY_PARENT(hwnd
, EN_SETFOCUS
);
2869 EDIT_WM_SetFont(hwnd
, wParam
, lParam
);
2870 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2875 dprintf_edit(stddeb
, "WM_SETREDRAW: hwnd=%d, wParam=%x\n",
2881 EDIT_WM_SetText(hwnd
, lParam
);
2885 EDIT_WM_Size(hwnd
, wParam
, lParam
);
2890 EDIT_WM_VScroll(hwnd
, wParam
, lParam
);
2894 lResult
= DefWindowProc(hwnd
, uMsg
, wParam
, lParam
);