4 * Copyright David W. Metcalfe, 1994
7 * April 1995 bug fixes (William Magro)
18 #include "stackframe.h" /* for MAKE_SEGPTR */
26 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
27 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
28 MAKEWPARAM(GetDlgCtrlID(hWndCntrl),wNotifyCode), \
31 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
32 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
33 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
36 #define MAXTEXTLEN 30000 /* maximum text buffer length */
37 #define EDITLEN 1024 /* starting length for multi-line control */
38 #define ENTRYLEN 256 /* starting length for single line control */
39 #define GROWLENGTH 64 /* buffers grow by this much */
43 int wlines
; /* number of lines of text */
44 int wtop
; /* top line that is displayed */
45 int wleft
; /* left pixel that is displayed */
46 unsigned int textlen
; /* text buffer length */
47 int textwidth
; /* width of longest line in pixels */
48 RECT fmtrc
; /* rectangle in which to format text */
49 int txtht
; /* height of text line in pixels */
50 HANDLE hText
; /* handle to text buffer */
51 INT
*CharWidths
; /* widths of chars in font */
52 unsigned int *textptrs
; /* list of line offsets */
53 char *BlankLine
; /* to fill blank lines quickly */
54 int CurrCol
; /* current column */
55 int CurrLine
; /* current line */
56 int WndCol
; /* current window column */
57 int WndRow
; /* current window row */
58 BOOL TextChanged
; /* TRUE if text has changed */
59 BOOL PaintBkgd
; /* paint control background */
60 unsigned int MaxTextLen
; /* maximum text buffer length */
61 int SelBegLine
; /* beginning line of selection */
62 int SelBegCol
; /* beginning column of selection */
63 int SelEndLine
; /* ending line of selection */
64 int SelEndCol
; /* ending column of selection */
65 HFONT hFont
; /* handle of current font (if not default) */
66 HANDLE hDeletedText
; /* handle to deleted text buffer for undo */
67 int DeletedLength
; /* length of deleted text */
68 int DeletedCurrLine
; /* starting line from which text was deleted */
69 int DeletedCurrCol
; /* starting col from which text was deleted */
70 int NumTabStops
; /* number of tab stops in buffer hTabStops */
71 unsigned short *TabStops
;/* tab stops buffer */
72 BOOL HaveFocus
; /* TRUE if this edit has the focus */
73 int ClientWidth
; /* computed from the window's ClientRect */
74 int ClientHeight
; /* dito */
77 #define EditBufStartLen(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE \
79 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
80 #define SelMarked(es) ((es)->SelBegLine != 0 || (es)->SelBegCol != 0 || \
81 (es)->SelEndLine != 0 || (es)->SelEndCol != 0)
82 #define ROUNDUP(numer, denom) (((numer) % (denom)) \
83 ? ((((numer) + (denom)) / (denom)) * (denom)) \
86 /* "line" dimension for horizontal scroll */
87 #define HSCROLLDIM(es) ((es)->ClientWidth / 3)
89 /* macros to access window styles */
90 #define IsMultiLine(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE)
91 #define IsVScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_VSCROLL)
92 #define IsHScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_HSCROLL)
94 /* internal variables */
95 static BOOL TextMarking
; /* TRUE if text marking in progress */
96 static BOOL ButtonDown
; /* TRUE if left mouse button down */
97 static int ButtonRow
; /* row in text buffer when button pressed */
98 static int ButtonCol
; /* col in text buffer when button pressed */
100 #define SWAP_INT(x,y) do { int temp = (x); (x) = (y); (y) = temp; } while(0)
102 /*********************************************************************
105 * Allocate the specified number of bytes on the specified local heap.
107 static HLOCAL
EDIT_HeapAlloc(HWND hwnd
, int bytes
, WORD flags
)
111 ret
= LOCAL_Alloc( WIN_GetWindowInstance(hwnd
), flags
, bytes
);
113 printf("EDIT_HeapAlloc: Out of heap-memory\n");
117 /*********************************************************************
120 * Return the address of the memory pointed to by the handle.
122 static void *EDIT_HeapLock(HWND hwnd
, HANDLE handle
)
124 HINSTANCE hinstance
= WIN_GetWindowInstance( hwnd
);
126 return LOCAL_Lock( hinstance
, handle
);
130 if (handle
== 0) return 0;
131 offs
= LOCAL_Lock( hinstance
, handle
);
132 return PTR_SEG_OFF_TO_LIN( hinstance
, offs
);
136 /*********************************************************************
139 static void EDIT_HeapUnlock(HWND hwnd
, HANDLE handle
)
141 if (handle
== 0) return;
142 LOCAL_Unlock( WIN_GetWindowInstance( hwnd
), handle
);
145 /*********************************************************************
148 * Reallocate the memory pointed to by the handle.
150 static HLOCAL
EDIT_HeapReAlloc(HWND hwnd
, HANDLE handle
, int bytes
)
152 return LOCAL_ReAlloc( WIN_GetWindowInstance(hwnd
), handle
, bytes
,
157 /*********************************************************************
160 * Frees the memory pointed to by the handle.
162 static void EDIT_HeapFree(HWND hwnd
, HANDLE handle
)
164 LOCAL_Free( WIN_GetWindowInstance(hwnd
), handle
);
168 /*********************************************************************
171 * Return the size of the given object on the local heap.
173 static unsigned int EDIT_HeapSize(HWND hwnd
, HANDLE handle
)
175 return LOCAL_Size( WIN_GetWindowInstance(hwnd
), handle
);
178 /********************************************************************
181 * Sets the ClientWidth/ClientHeight fields of the EDITSTATE
182 * Called on WM_SIZE and WM_SetFont messages
184 static void EDIT_RecalcSize(HWND hwnd
, EDITSTATE
*es
)
187 GetClientRect(hwnd
,&rect
);
188 es
->ClientWidth
= rect
.right
> rect
.left
? rect
.right
- rect
.left
: 0;
189 es
->ClientHeight
= rect
.bottom
> rect
.top
? (rect
.bottom
- rect
.top
) / es
->txtht
: 0;
192 /*********************************************************************
195 static EDITSTATE
*EDIT_GetEditState(HWND hwnd
)
197 return (EDITSTATE
*)GetWindowLong(hwnd
,0);
200 /*********************************************************************
201 * EDIT_GetNextTabStop
203 * Return the next tab stop beyond _pcol_.
205 static int EDIT_GetNextTabStop(HWND hwnd
, int pcol
)
208 int baseUnitWidth
= LOWORD(GetDialogBaseUnits());
209 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
211 if (es
->NumTabStops
== 0)
212 return ROUNDUP(pcol
, 8 * baseUnitWidth
);
213 if (es
->NumTabStops
== 1)
214 return ROUNDUP(pcol
, es
->TabStops
[0] * baseUnitWidth
/ 4);
215 for (i
= 0; i
< es
->NumTabStops
; i
++)
217 if (es
->TabStops
[i
] * baseUnitWidth
/ 4 >= pcol
)
218 return es
->TabStops
[i
] * baseUnitWidth
/ 4;
223 /*********************************************************************
226 * Return the width of the given character in pixels.
227 * The current column offset in pixels _pcol_ is required to calculate
228 * the width of a tab.
230 static int EDIT_CharWidth(HWND hwnd
, short ch
, int pcol
)
232 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
234 if (ch
== VK_TAB
) return EDIT_GetNextTabStop(hwnd
, pcol
) - pcol
;
235 return es
->CharWidths
[ch
];
238 /*********************************************************************
239 * EDIT_ClearTextPointers
241 * Clear and initialize text line pointer array.
243 static void EDIT_ClearTextPointers(HWND hwnd
)
245 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
247 dprintf_edit( stddeb
, "EDIT_ClearTextPointers\n" );
248 es
->textptrs
= xrealloc(es
->textptrs
, sizeof(int));
252 /*********************************************************************
253 * EDIT_BuildTextPointers
255 * Build array of pointers to text lines.
257 static void EDIT_BuildTextPointers(HWND hwnd
)
260 unsigned int off
, len
, line
;
263 es
= EDIT_GetEditState(hwnd
);
264 text
= EDIT_HeapLock(hwnd
, es
->hText
);
267 if (IsMultiLine(hwnd
)) {
270 while ((cp
= strchr(cp
,'\n')) != NULL
) {
273 } else es
->wlines
= 1;
275 dprintf_edit( stddeb
, "EDIT_BuildTextPointers: realloc\n" );
276 es
->textptrs
= xrealloc(es
->textptrs
, (es
->wlines
+ 2) * sizeof(int));
279 dprintf_edit(stddeb
,"BuildTextPointers: %d lines, pointer %p\n",
280 es
->wlines
, es
->textptrs
);
282 /* advance through text buffer */
286 off
= cp
- text
; /* offset of beginning of line */
287 dprintf_edit(stddeb
,"BuildTextPointers: line %d offs %d\n", line
, off
);
288 es
->textptrs
[line
] = off
;
292 /* advance through current line */
293 while (*cp
&& *cp
!= '\n')
295 len
+= EDIT_CharWidth(hwnd
, (BYTE
)*cp
, len
);
296 /* width of line in pixels */
299 es
->textwidth
= MAX(es
->textwidth
, len
);
301 cp
++; /* skip '\n' */
304 es
->textptrs
[line
] = off
;
305 EDIT_HeapUnlock(hwnd
, es
->hText
);
308 /*********************************************************************
309 * EDIT_ModTextPointers
311 * Modify text pointers from a specified position.
313 static void EDIT_ModTextPointers(HWND hwnd
, int lineno
, int var
)
315 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
316 for(;lineno
< es
->wlines
; lineno
++) es
->textptrs
[lineno
] += var
;
319 /*********************************************************************
322 * Return a pointer to the text in the specified line.
324 static char *EDIT_TextLine(HWND hwnd
, int sel
)
326 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
327 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
329 if (sel
> es
->wlines
) return NULL
;
330 dprintf_edit(stddeb
,"EDIT_TextLine: text %p, line %d offs %d\n",
331 text
, sel
, es
->textptrs
[sel
]);
332 return text
+ es
->textptrs
[sel
];
335 /*********************************************************************
338 * Get a copy of the text in the specified line.
340 static char *EDIT_GetTextLine(HWND hwnd
, int selection
)
345 dprintf_edit(stddeb
,"GetTextLine %d\n", selection
);
346 cp1
= EDIT_TextLine(hwnd
, selection
);
348 /* Find end of line */
349 cp
= strchr( cp1
, '\r' );
350 if (cp
== NULL
) len
= strlen(cp1
);
353 /* store selected line and return handle */
354 cp
= xmalloc( len
+ 1 );
355 strncpy( cp
, cp1
, len
);
360 /*********************************************************************
363 * Return length of string _str_ of length _len_ characters in pixels.
364 * The current column offset in pixels _pcol_ is required to calculate
365 * the width of a tab.
367 static int EDIT_StrWidth(HWND hwnd
, unsigned char *str
, int len
, int pcol
)
371 for (i
= 0; i
< len
; i
++)
372 plen
+= EDIT_CharWidth(hwnd
, (BYTE
)(*(str
+ i
)), pcol
+ plen
);
374 dprintf_edit(stddeb
,"EDIT_StrWidth: returning %d, len=%d\n", plen
,len
);
378 /*********************************************************************
381 * Return length of line _num_ in characters.
383 static int EDIT_LineLength(HWND hwnd
, int num
)
385 char *cp
= EDIT_TextLine(hwnd
, num
);
389 cp1
= strchr(cp
, '\r');
390 return cp1
? (cp1
- cp
) : strlen(cp
);
393 /*********************************************************************
396 * Return sub-string starting at pixel _off_ of length _len_ pixels.
397 * If _off_ is part way through a character, the negative offset of
398 * the beginning of the character is returned in _diff_, else _diff_
401 static HANDLE
EDIT_GetStr(HWND hwnd
, char *lp
, int off
, int len
, int *diff
)
405 int ch
= 0, i
= 0, j
, s_i
=0;
408 dprintf_edit(stddeb
,"EDIT_GetStr lp='%s' off=%d len=%d\n", lp
, off
, len
);
410 if (off
< 0) off
= 0;
414 i
+= EDIT_CharWidth(hwnd
, (BYTE
)(*(lp
+ ch
)), i
);
417 /* if stepped past _off_, go back a character */
425 while (i
< len
+ off
)
427 if (*(lp
+ ch
) == '\r' || *(lp
+ ch
) == '\n')
429 i
+= EDIT_CharWidth(hwnd
, (BYTE
)(*(lp
+ ch
)), i
);
433 hStr
= EDIT_HeapAlloc(hwnd
, ch
- ch1
+ 3, LMEM_FIXED
);
434 str
= (char *)EDIT_HeapLock(hwnd
, hStr
);
435 for (i
= ch1
, j
= 0; i
< ch
; i
++, j
++)
438 dprintf_edit(stddeb
,"EDIT_GetStr: returning %s\n", str
);
442 /*********************************************************************
445 * Write text to a window
447 * off - offset in text line (in pixels)
448 * len - length from off (in pixels)
449 * row - line in window
450 * col - column in window
451 * rc - rectangle in which to display line
452 * blank - blank remainder of line?
453 * reverse - reverse color of line?
455 static void EDIT_WriteText(HWND hwnd
, char *lp
, int off
, int len
, int row
,
456 int col
, RECT
*rc
, BOOL blank
, BOOL reverse
)
460 char *str
, *cp
, *cp1
;
461 int diff
=0, num_spaces
, tabwidth
, scol
;
463 COLORREF oldTextColor
, oldBkgdColor
;
465 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
467 dprintf_edit(stddeb
,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp
, off
, len
, row
, col
, reverse
);
476 hStr
= EDIT_GetStr(hwnd
, lp
, off
, len
, &diff
);
477 str
= (char *)EDIT_HeapLock(hwnd
, hStr
);
478 hrgnClip
= CreateRectRgnIndirect(rc
);
479 SelectClipRgn(hdc
, hrgnClip
);
482 oldfont
= (HFONT
)SelectObject(hdc
, (HANDLE
)es
->hFont
);
484 oldfont
= 0; /* -Wall does not see the use of if */
487 SendMessage(GetParent(hwnd
), WM_CTLCOLOREDIT
, (WPARAM
)hdc
, (LPARAM
)hwnd
);
489 SendMessage(GetParent(hwnd
), WM_CTLCOLOR
, (WPARAM
)hdc
,
490 MAKELPARAM(hwnd
, CTLCOLOR_EDIT
));
495 oldBkgdColor
= GetBkColor(hdc
);
496 oldTextColor
= GetTextColor(hdc
);
497 SetBkColor(hdc
, oldTextColor
);
498 SetTextColor(hdc
, oldBkgdColor
);
500 else /* -Wall does not see the use of if */
501 oldTextColor
= oldBkgdColor
= 0;
503 if (strlen(es
->BlankLine
) < (es
->ClientWidth
/ es
->CharWidths
[32]) + 2)
505 dprintf_edit( stddeb
, "EDIT_WriteText: realloc\n" );
506 es
->BlankLine
= xrealloc(es
->BlankLine
,
507 (es
->ClientWidth
/ es
->CharWidths
[32]) + 2);
508 memset(es
->BlankLine
, ' ', (es
->ClientWidth
/ es
->CharWidths
[32]) + 2);
509 es
->BlankLine
[(es
->ClientWidth
/ es
->CharWidths
[32]) + 1] = 0;
512 if ((GetWindowLong( hwnd
, GWL_STYLE
) & ES_PASSWORD
))
514 int len
= strlen(str
);
515 char *buff
= xmalloc( len
+1 );
516 memset( buff
, '*', len
);
518 TextOut( hdc
, col
- diff
, row
* es
->txtht
, buff
, len
);
520 else if (!(cp
= strchr(str
, VK_TAB
)))
521 TextOut(hdc
, col
- diff
, row
* es
->txtht
, str
, strlen(str
));
524 TextOut(hdc
, col
- diff
, row
* es
->txtht
, str
, (int)(cp
- str
));
525 scol
= EDIT_StrWidth(hwnd
, str
, (int)(cp
- str
), 0);
526 tabwidth
= EDIT_CharWidth(hwnd
, VK_TAB
, scol
);
527 num_spaces
= tabwidth
/ es
->CharWidths
[32] + 1;
528 TextOut(hdc
, scol
, row
* es
->txtht
, es
->BlankLine
, num_spaces
);
532 while ((cp1
= strchr(cp
, VK_TAB
)))
534 TextOut(hdc
, scol
, row
* es
->txtht
, cp
, (int)(cp1
- cp
));
535 scol
+= EDIT_StrWidth(hwnd
, cp
, (int)(cp1
- cp
), scol
);
536 tabwidth
= EDIT_CharWidth(hwnd
, VK_TAB
, scol
);
537 num_spaces
= tabwidth
/ es
->CharWidths
[32] + 1;
538 TextOut(hdc
, scol
, row
* es
->txtht
, es
->BlankLine
, num_spaces
);
543 TextOut(hdc
, scol
, row
* es
->txtht
, cp
, strlen(cp
));
548 SetBkColor(hdc
, oldBkgdColor
);
549 SetTextColor(hdc
, oldTextColor
);
552 /* blank out remainder of line if appropriate */
555 if ((rc
->right
- col
) > len
)
557 num_spaces
= (rc
->right
- col
- len
) / es
->CharWidths
[32];
558 TextOut(hdc
, col
+ len
, row
* es
->txtht
, es
->BlankLine
, num_spaces
);
563 SelectObject(hdc
, (HANDLE
)oldfont
);
565 EDIT_HeapFree(hwnd
, hStr
);
566 ReleaseDC(hwnd
, hdc
);
569 /*********************************************************************
572 * Write the line of text at offset _y_ in text buffer to a window.
574 static void EDIT_WriteTextLine(HWND hwnd
, RECT
*rect
, int y
)
580 int sbl
, sel
, sbc
, sec
;
582 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
584 /* initialize rectangle if NULL, else copy */
588 GetClientRect(hwnd
, &rc
);
590 dprintf_edit(stddeb
,"WriteTextLine %d\n", y
);
592 /* make sure y is inside the window */
593 if (y
< es
->wtop
|| y
> (es
->wtop
+ es
->ClientHeight
))
595 dprintf_edit(stddeb
,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y
);
599 /* make sure rectangle is within window */
600 if (rc
.left
>= es
->ClientWidth
- 1)
602 dprintf_edit(stddeb
,"EDIT_WriteTextLine: rc.left (%ld) is greater than right edge\n",
608 dprintf_edit(stddeb
,"EDIT_WriteTextLine: rc.right (%ld) is less than left edge\n",
612 if (y
- es
->wtop
< (rc
.top
/ es
->txtht
) ||
613 y
- es
->wtop
> (rc
.bottom
/ es
->txtht
))
615 dprintf_edit(stddeb
,"EDIT_WriteTextLine: y (%d) is outside window\n", y
);
619 /* get the text and length of line */
620 lp
= EDIT_GetTextLine( hwnd
, y
);
621 if (lp
== NULL
) return;
623 lnlen
= EDIT_StrWidth( hwnd
, lp
, strlen(lp
), 0 );
626 /* build the line to display */
627 if (lnlen
< (es
->wleft
+ rc
.left
))
641 lnlen
= lnlen1
- off
;
643 len
= MIN(lnlen
, rc
.right
- rc
.left
);
647 sbl
= es
->SelBegLine
;
648 sel
= es
->SelEndLine
;
652 /* put lowest marker first */
658 if (sbl
== sel
&& sbc
> sec
)
661 if (y
< sbl
|| y
> sel
)
662 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
664 else if (y
> sbl
&& y
< sel
)
665 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
669 col
= EDIT_StrWidth(hwnd
, lp
, sbc
, 0);
670 if (col
> (es
->wleft
+ rc
.left
))
672 len
= MIN(col
- off
, rc
.right
- off
);
673 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
674 rc
.left
, &rc
, FALSE
, FALSE
);
679 col
= EDIT_StrWidth(hwnd
, lp
, sec
, 0);
680 if (col
< (es
->wleft
+ rc
.right
))
682 len
= MIN(col
- off
, rc
.right
- off
);
683 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
684 off
- es
->wleft
, &rc
, FALSE
, TRUE
);
686 len
= MIN(lnlen
- off
, rc
.right
- off
);
687 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
688 off
- es
->wleft
, &rc
, TRUE
, FALSE
);
692 len
= MIN(lnlen
- off
, rc
.right
- off
);
693 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
694 off
- es
->wleft
, &rc
, TRUE
, TRUE
);
699 len
= MIN(lnlen
- off
, rc
.right
- off
);
700 if (col
< (es
->wleft
+ rc
.right
))
701 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
702 off
- es
->wleft
, &rc
, TRUE
, TRUE
);
707 col
= EDIT_StrWidth(hwnd
, lp
, sec
, 0);
708 if (col
< (es
->wleft
+ rc
.right
))
710 len
= MIN(col
- off
, rc
.right
- off
);
711 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
712 off
- es
->wleft
, &rc
, FALSE
, TRUE
);
714 len
= MIN(lnlen
- off
, rc
.right
- off
);
715 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
,
716 off
- es
->wleft
, &rc
, TRUE
, FALSE
);
721 EDIT_WriteText(hwnd
, lp
, off
, len
, y
- es
->wtop
, rc
.left
, &rc
,
727 /*********************************************************************
728 * EDIT_ComputeVScrollPos
730 * Compute the vertical scroll bar position from the window
731 * position and text width.
733 static int EDIT_ComputeVScrollPos(HWND hwnd
)
737 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
739 GetScrollRange(hwnd
, SB_VERT
, &minpos
, &maxpos
);
741 if (es
->wlines
> es
->ClientHeight
)
742 vscrollpos
= (double)(es
->wtop
) / (double)(es
->wlines
-
743 es
->ClientHeight
) * (maxpos
- minpos
);
750 /*********************************************************************
751 * EDIT_ComputeHScrollPos
753 * Compute the horizontal scroll bar position from the window
754 * position and text width.
756 static int EDIT_ComputeHScrollPos(HWND hwnd
)
760 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
762 GetScrollRange(hwnd
, SB_HORZ
, &minpos
, &maxpos
);
764 if (es
->textwidth
> es
->ClientWidth
)
765 hscrollpos
= (double)(es
->wleft
) / (double)(es
->textwidth
-
766 es
->ClientWidth
) * (maxpos
- minpos
);
773 /*********************************************************************
776 * Scroll text horizontally using cursor keys.
778 static void EDIT_KeyHScroll(HWND hwnd
, WORD opt
)
781 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
783 if (opt
== SB_LINEDOWN
)
785 es
->wleft
+= HSCROLLDIM(es
);
786 es
->WndCol
-= HSCROLLDIM(es
);
792 if (es
->wleft
- HSCROLLDIM(es
) < 0)
794 es
->WndCol
+= es
->wleft
;
799 es
->wleft
-= HSCROLLDIM(es
);
800 es
->WndCol
+= HSCROLLDIM(es
);
804 InvalidateRect(hwnd
, NULL
, FALSE
);
807 if (IsHScrollBar(hwnd
))
809 hscrollpos
= EDIT_ComputeHScrollPos(hwnd
);
810 SetScrollPos(hwnd
, SB_HORZ
, hscrollpos
, TRUE
);
814 /*********************************************************************
815 * EDIT_KeyVScrollLine
817 * Scroll text vertically by one line using keyboard.
819 static void EDIT_KeyVScrollLine(HWND hwnd
, WORD opt
)
823 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
825 if (!IsMultiLine(hwnd
))
828 if (opt
== SB_LINEDOWN
)
830 /* move down one line */
831 if (es
->wtop
+ es
->ClientHeight
>= es
->wlines
)
837 /* move up one line */
843 if (IsWindowVisible(hwnd
))
845 /* adjust client bottom to nearest whole line */
846 GetClientRect(hwnd
, &rc
);
847 rc
.bottom
= (rc
.bottom
/ es
->txtht
) * es
->txtht
;
849 if (opt
== SB_LINEUP
)
851 /* move up one line (scroll window down) */
852 ScrollWindow(hwnd
, 0, es
->txtht
, &rc
, &rc
);
854 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
);
859 /* move down one line (scroll window up) */
860 ScrollWindow(hwnd
, 0, -(es
->txtht
), &rc
, &rc
);
861 /* write bottom line */
862 y
= (((rc
.bottom
- rc
.top
) / es
->txtht
) - 1);
863 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ y
);
868 /* reset the vertical scroll bar */
869 if (IsVScrollBar(hwnd
))
871 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
872 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
876 /*********************************************************************
879 * End key: move to end of line.
881 static void EDIT_End(HWND hwnd
)
883 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
885 while (*CurrChar
&& *CurrChar
!= '\r')
887 es
->WndCol
+= EDIT_CharWidth(hwnd
, (BYTE
)(*CurrChar
), es
->WndCol
+ es
->wleft
);
891 if (es
->WndCol
>= es
->ClientWidth
)
893 es
->wleft
= es
->WndCol
- es
->ClientWidth
+ HSCROLLDIM(es
);
894 es
->WndCol
-= es
->wleft
;
895 InvalidateRect(hwnd
, NULL
, FALSE
);
900 /*********************************************************************
903 * Home key: move to beginning of line.
905 static void EDIT_Home(HWND hwnd
)
907 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
909 es
->CurrCol
= es
->WndCol
= 0;
913 InvalidateRect(hwnd
, NULL
, FALSE
);
918 /*********************************************************************
921 * Stick the cursor to the end of the line.
923 static void EDIT_StickEnd(HWND hwnd
)
925 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
926 int len
= EDIT_LineLength(hwnd
, es
->CurrLine
);
927 char *cp
= EDIT_TextLine(hwnd
, es
->CurrLine
);
930 es
->CurrCol
= MIN(len
, es
->CurrCol
);
931 es
->WndCol
= MIN(EDIT_StrWidth(hwnd
, cp
, len
, 0) - es
->wleft
, es
->WndCol
);
932 currpel
= EDIT_StrWidth(hwnd
, cp
, es
->CurrCol
, 0);
934 if (es
->wleft
> currpel
)
936 es
->wleft
= MAX(0, currpel
- 20);
937 es
->WndCol
= currpel
- es
->wleft
;
940 else if (currpel
- es
->wleft
>= es
->ClientWidth
)
942 es
->wleft
= currpel
- (es
->ClientWidth
- 5);
943 es
->WndCol
= currpel
- es
->wleft
;
948 /*********************************************************************
951 * Cursor down key: move down one line.
953 static void EDIT_Downward(HWND hwnd
)
955 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
957 dprintf_edit(stddeb
,"EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n",
958 es
->WndRow
, es
->wtop
, es
->wlines
);
960 if (IsMultiLine(hwnd
) && (es
->WndRow
+ es
->wtop
+ 1 < es
->wlines
))
963 if (es
->WndRow
== es
->ClientHeight
- 1)
966 EDIT_KeyVScrollLine(hwnd
, SB_LINEDOWN
);
974 /*********************************************************************
977 * Cursor up key: move up one line.
979 static void EDIT_Upward(HWND hwnd
)
981 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
983 if (IsMultiLine(hwnd
) && es
->CurrLine
!= 0)
989 EDIT_KeyVScrollLine(hwnd
, SB_LINEUP
);
997 /*********************************************************************
1000 * Cursor right key: move right one character position.
1002 static void EDIT_Forward(HWND hwnd
)
1004 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1006 if (*CurrChar
== '\0')
1009 if (*CurrChar
== '\r')
1011 if (es
->CurrLine
< (es
->wlines
- 1))
1014 EDIT_Downward(hwnd
);
1019 es
->WndCol
+= EDIT_CharWidth(hwnd
, (BYTE
)(*CurrChar
), es
->WndCol
+ es
->wleft
);
1021 if (es
->WndCol
>= es
->ClientWidth
)
1022 EDIT_KeyHScroll(hwnd
, SB_LINEDOWN
);
1026 /*********************************************************************
1029 * Cursor left key: move left one character position.
1031 static void EDIT_Backward(HWND hwnd
)
1033 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1038 if (*CurrChar
== VK_TAB
)
1039 es
->WndCol
-= EDIT_CharWidth(hwnd
, (BYTE
)(*CurrChar
),
1041 EDIT_TextLine(hwnd
, es
->CurrLine
),
1044 es
->WndCol
-= EDIT_CharWidth(hwnd
, (BYTE
)(*CurrChar
), 0);
1046 EDIT_KeyHScroll(hwnd
, SB_LINEUP
);
1048 else if (IsMultiLine(hwnd
) && es
->CurrLine
!= 0)
1055 /*********************************************************************
1056 * EDIT_KeyVScrollPage
1058 * Scroll text vertically by one page using keyboard.
1060 static void EDIT_KeyVScrollPage(HWND hwnd
, WORD opt
)
1063 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1065 if (IsMultiLine(hwnd
))
1067 if (opt
== SB_PAGEUP
)
1069 if (es
->wtop
> es
->ClientHeight
) es
->wtop
-= es
->ClientHeight
;
1073 if (es
->wtop
+ es
->ClientHeight
< es
->wlines
)
1075 es
->wtop
+= es
->ClientHeight
;
1076 if (es
->wtop
> es
->wlines
- es
->ClientHeight
)
1077 es
->wtop
= es
->wlines
- es
->ClientHeight
;
1083 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
1084 EDIT_StickEnd(hwnd
);
1085 InvalidateRect(hwnd
, NULL
, TRUE
);
1088 /* reset the vertical scroll bar */
1089 if (IsVScrollBar(hwnd
))
1091 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1092 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1097 #ifdef SUPERFLUOUS_FUNCTIONS
1098 /*********************************************************************
1099 * EDIT_KeyVScrollDoc
1101 * Scroll text to top and bottom of document using keyboard.
1103 static void EDIT_KeyVScrollDoc(HWND hwnd
, WORD opt
)
1106 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1108 if (!IsMultiLine(hwnd
))
1112 es
->wtop
= es
->wleft
= 0;
1113 else if (es
->wtop
+ es
->ClientHeight
< es
->wlines
)
1115 es
->wtop
= es
->wlines
- es
->ClientHeight
;
1119 es
->CurrLine
= es
->wlines
;
1120 es
->WndRow
= es
->wlines
- es
->wtop
;
1122 InvalidateRect(hwnd
, NULL
, TRUE
);
1125 /* reset the vertical scroll bar */
1126 if (IsVScrollBar(hwnd
))
1128 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1129 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1134 /*********************************************************************
1137 * Delete character to right of cursor.
1139 static void EDIT_DelKey(HWND hwnd
)
1142 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1143 char *currchar
= CurrChar
;
1144 BOOL repaint
= *currchar
== '\n';
1146 if (IsMultiLine(hwnd
) && *currchar
== '\n' && *(currchar
+ 1) == '\0')
1148 strcpy(currchar
, currchar
+ 1);
1149 NOTIFY_PARENT(hwnd
, EN_UPDATE
);
1153 EDIT_BuildTextPointers(hwnd
);
1154 GetClientRect(hwnd
, &rc
);
1155 rc
.top
= es
->WndRow
* es
->txtht
;
1156 InvalidateRect(hwnd
, &rc
, FALSE
);
1161 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, -1);
1162 EDIT_WriteTextLine(hwnd
, NULL
, es
->WndRow
+ es
->wtop
);
1165 es
->TextChanged
= TRUE
;
1166 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1169 /*********************************************************************
1172 * Scroll text vertically by one line using scrollbars.
1174 static void EDIT_VScrollLine(HWND hwnd
, WORD opt
)
1178 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1180 dprintf_edit(stddeb
,"EDIT_VScrollLine: direction=%d\n", opt
);
1182 if (opt
== SB_LINEDOWN
)
1184 /* move down one line */
1185 if (es
->wtop
+ es
->ClientHeight
>= es
->wlines
)
1191 /* move up one line */
1197 if (IsWindowVisible(hwnd
))
1199 /* adjust client bottom to nearest whole line */
1200 GetClientRect(hwnd
, &rc
);
1201 rc
.bottom
= (rc
.bottom
/ es
->txtht
) * es
->txtht
;
1203 if (opt
== SB_LINEUP
)
1205 /* move up one line (scroll window down) */
1206 ScrollWindow(hwnd
, 0, es
->txtht
, &rc
, &rc
);
1207 /* write top line */
1208 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
);
1213 /* move down one line (scroll window up) */
1214 ScrollWindow(hwnd
, 0, -(es
->txtht
), &rc
, &rc
);
1215 /* write bottom line */
1216 y
= ((rc
.bottom
- rc
.top
/ es
->txtht
) - 1);
1217 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ y
);
1224 /*********************************************************************
1227 * Scroll text vertically by one page using keyboard.
1229 static void EDIT_VScrollPage(HWND hwnd
, WORD opt
)
1232 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1234 if (opt
== SB_PAGEUP
)
1237 es
->wtop
-= es
->ClientHeight
;
1241 if (es
->wtop
+ es
->ClientHeight
< es
->wlines
)
1243 es
->wtop
+= es
->ClientHeight
;
1244 if (es
->wtop
> es
->wlines
- es
->ClientHeight
)
1245 es
->wtop
= es
->wlines
- es
->ClientHeight
;
1251 InvalidateRect(hwnd
, NULL
, TRUE
);
1254 /* reset the vertical scroll bar */
1255 if (IsVScrollBar(hwnd
))
1257 vscrollpos
= EDIT_ComputeVScrollPos(hwnd
);
1258 SetScrollPos(hwnd
, SB_VERT
, vscrollpos
, TRUE
);
1262 /*********************************************************************
1265 * Convert a pixel offset in the given row to a character offset,
1266 * adjusting the pixel offset to the nearest whole character if
1269 static int EDIT_PixelToChar(HWND hwnd
, int row
, int *pixel
)
1271 int ch
= 0, i
= 0, s_i
= 0;
1274 dprintf_edit(stddeb
,"EDIT_PixelToChar: row=%d, pixel=%d\n", row
, *pixel
);
1276 text
= EDIT_TextLine(hwnd
, row
);
1280 i
+= EDIT_CharWidth(hwnd
, (BYTE
)(*(text
+ ch
)), i
);
1284 /* if stepped past _pixel_, go back a character */
1294 /*********************************************************************
1297 * Clear text from text buffer.
1299 static void EDIT_ClearText(HWND hwnd
)
1301 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1302 unsigned int blen
= EditBufStartLen(hwnd
) + 2;
1305 dprintf_edit(stddeb
,"EDIT_ClearText %d\n",blen
);
1307 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, blen
);
1308 text
= EDIT_HeapLock(hwnd
, es
->hText
);
1309 memset(text
, 0, blen
);
1313 es
->CurrLine
= es
->CurrCol
= 0;
1314 es
->WndRow
= es
->WndCol
= 0;
1315 es
->wleft
= es
->wtop
= 0;
1317 es
->TextChanged
= FALSE
;
1319 EDIT_ClearTextPointers(hwnd
);
1323 /*********************************************************************
1326 * Return line and column in text buffer from character offset.
1328 static void EDIT_GetLineCol(HWND hwnd
, int off
, int *line
, int *col
)
1332 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1333 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
1335 /* check for (0,0) */
1336 if (!off
|| !es
->wlines
)
1343 if (off
< 0 || off
> strlen(text
)) off
= strlen(text
);
1345 for (lineno
= 0; lineno
< es
->wlines
; lineno
++)
1347 cp
= text
+ es
->textptrs
[lineno
];
1348 if (off
== (int)(cp
- text
))
1354 if (off
< (int)(cp
- text
))
1359 *col
= off
- (int)(cp1
- text
);
1361 if (*(text
+ *col
) == '\0')
1366 /*********************************************************************
1369 * Clear the current selection.
1371 static void EDIT_ClearSel(HWND hwnd
)
1373 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1375 es
->SelBegLine
= es
->SelBegCol
= 0;
1376 es
->SelEndLine
= es
->SelEndCol
= 0;
1378 InvalidateRect(hwnd
, NULL
, TRUE
);
1382 /*********************************************************************
1383 * EDIT_SaveDeletedText
1385 * Save deleted text in deleted text buffer.
1387 static void EDIT_SaveDeletedText(HWND hwnd
, char *deltext
, int len
,
1391 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1393 dprintf_edit( stddeb
, "EDIT_SaveDeletedText\n" );
1394 if (!es
->hDeletedText
)
1395 es
->hDeletedText
= GlobalAlloc( GMEM_MOVEABLE
, len
);
1397 es
->hDeletedText
= GlobalReAlloc(es
->hDeletedText
, len
, GMEM_MOVEABLE
);
1398 if (!es
->hDeletedText
) return;
1399 text
= (char *)GlobalLock(es
->hDeletedText
);
1400 memcpy(text
, deltext
, len
);
1401 GlobalUnlock(es
->hDeletedText
);
1402 es
->DeletedLength
= len
;
1403 es
->DeletedCurrLine
= line
;
1404 es
->DeletedCurrCol
= col
;
1407 /*********************************************************************
1410 * Delete the current selected text (if any)
1412 static void EDIT_DeleteSel(HWND hwnd
)
1416 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1420 bbl
= EDIT_TextLine(hwnd
, es
->SelBegLine
) + es
->SelBegCol
;
1421 bel
= EDIT_TextLine(hwnd
, es
->SelEndLine
) + es
->SelEndCol
;
1422 len
= (int)(bel
- bbl
);
1423 EDIT_SaveDeletedText(hwnd
, bbl
, len
, es
->SelBegLine
, es
->SelBegCol
);
1424 es
->TextChanged
= TRUE
;
1427 es
->CurrLine
= es
->SelBegLine
;
1428 es
->CurrCol
= es
->SelBegCol
;
1429 es
->WndRow
= es
->SelBegLine
- es
->wtop
;
1432 es
->wtop
= es
->SelBegLine
;
1435 es
->WndCol
= EDIT_StrWidth(hwnd
, bbl
- es
->SelBegCol
,
1436 es
->SelBegCol
, 0) - es
->wleft
;
1438 EDIT_BuildTextPointers(hwnd
);
1439 es
->PaintBkgd
= TRUE
;
1440 EDIT_ClearSel(hwnd
);
1444 #ifdef SUPERFLUOUS_FUNCTIONS
1445 /*********************************************************************
1446 * EDIT_TextLineNumber
1448 * Return the line number in the text buffer of the supplied
1449 * character pointer.
1451 static int EDIT_TextLineNumber(HWND hwnd
, char *lp
)
1455 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1456 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
1458 for (lineno
= 0; lineno
< es
->wlines
; lineno
++)
1460 cp
= text
+ es
->textptrs
[lineno
];
1470 /*********************************************************************
1473 * Set down anchor for text marking.
1475 static void EDIT_SetAnchor(HWND hwnd
, int row
, int col
)
1478 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1483 EDIT_ClearSel(hwnd
);
1485 es
->SelBegLine
= es
->SelEndLine
= row
;
1486 es
->SelBegCol
= es
->SelEndCol
= col
;
1489 InvalidateRect(hwnd
, NULL
, FALSE
);
1494 /*********************************************************************
1497 * Display selection by reversing pixels in selected text.
1498 * If end == -1, selection applies to end of line.
1500 static void EDIT_WriteSel(HWND hwnd
, int y
, int start
, int end
)
1506 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1508 dprintf_edit(stddeb
,"EDIT_WriteSel: y=%d start=%d end=%d\n", y
, start
,end
);
1509 GetClientRect(hwnd
, &rc
);
1511 /* make sure y is within the window */
1512 if (y
< es
->wtop
|| y
> (es
->wtop
+ es
->ClientHeight
))
1515 /* get pointer to text */
1516 cp
= EDIT_TextLine(hwnd
, y
);
1518 /* get length of line if end == -1 */
1520 end
= EDIT_LineLength(hwnd
, y
);
1522 scol
= EDIT_StrWidth(hwnd
, cp
, start
, 0) - es
->wleft
;
1523 if (scol
> rc
.right
) return;
1524 if (scol
< rc
.left
) scol
= rc
.left
;
1525 ecol
= EDIT_StrWidth(hwnd
, cp
, end
, 0) - es
->wleft
;
1526 if (ecol
< rc
.left
) return;
1527 if (ecol
> rc
.right
) ecol
= rc
.right
;
1530 rcInvert
.left
= scol
;
1531 rcInvert
.top
= (y
- es
->wtop
) * es
->txtht
;
1532 rcInvert
.right
= ecol
;
1533 rcInvert
.bottom
= (y
- es
->wtop
+ 1) * es
->txtht
;
1534 InvertRect(hdc
, (LPRECT
) &rcInvert
);
1535 ReleaseDC(hwnd
, hdc
);
1538 /*********************************************************************
1541 * Extend selection to the given screen co-ordinates.
1543 static void EDIT_ExtendSel(HWND hwnd
, INT x
, INT y
)
1545 int bbl
, bel
, bbc
, bec
;
1548 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1550 dprintf_edit(stddeb
,"EDIT_ExtendSel: x=%d, y=%d\n", x
, y
);
1552 bbl
= es
->SelEndLine
;
1553 bbc
= es
->SelEndCol
;
1555 if (IsMultiLine(hwnd
))
1557 if ((line
= es
->wtop
+ y
/ es
->txtht
) >= es
->wlines
)
1558 line
= es
->wlines
- 1;
1563 cp
= EDIT_TextLine(hwnd
, line
);
1564 len
= EDIT_LineLength(hwnd
, line
);
1566 es
->WndRow
= y
/ es
->txtht
;
1567 if (!IsMultiLine(hwnd
))
1569 else if (es
->WndRow
> es
->wlines
- es
->wtop
- 1)
1570 es
->WndRow
= es
->wlines
- es
->wtop
- 1;
1571 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
1572 es
->SelEndLine
= es
->CurrLine
;
1574 es
->WndCol
= es
->wleft
+ MAX(x
,0);
1575 if (es
->WndCol
> EDIT_StrWidth(hwnd
, cp
, len
, 0))
1576 es
->WndCol
= EDIT_StrWidth(hwnd
, cp
, len
, 0);
1577 es
->CurrCol
= EDIT_PixelToChar(hwnd
, es
->CurrLine
, &(es
->WndCol
));
1578 es
->WndCol
-= es
->wleft
;
1579 es
->SelEndCol
= es
->CurrCol
;
1581 bel
= es
->SelEndLine
;
1582 bec
= es
->SelEndCol
;
1584 /* return if no new characters to mark */
1585 if (bbl
== bel
&& bbc
== bec
)
1588 /* put lowest marker first */
1594 if (bbl
== bel
&& bbc
> bec
)
1597 for (y
= bbl
; y
<= bel
; y
++)
1599 if (y
== bbl
&& y
== bel
)
1600 EDIT_WriteSel(hwnd
, y
, bbc
, bec
);
1602 EDIT_WriteSel(hwnd
, y
, bbc
, -1);
1604 EDIT_WriteSel(hwnd
, y
, 0, bec
);
1606 EDIT_WriteSel(hwnd
, y
, 0, -1);
1610 /*********************************************************************
1613 * Stop text marking (selection).
1615 static void EDIT_StopMarking(HWND hwnd
)
1617 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1619 TextMarking
= FALSE
;
1620 if (es
->SelBegLine
> es
->SelEndLine
)
1622 SWAP_INT((es
->SelBegLine
), (es
->SelEndLine
));
1623 SWAP_INT((es
->SelBegCol
), (es
->SelEndCol
));
1625 if (es
->SelBegLine
== es
->SelEndLine
&& es
->SelBegCol
> es
->SelEndCol
)
1626 SWAP_INT((es
->SelBegCol
), (es
->SelEndCol
));
1629 /*********************************************************************
1632 * Insert text at current line and column.
1634 static void EDIT_InsertText(HWND hwnd
, char *str
, int len
)
1637 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1638 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
1640 plen
= strlen(text
) + len
;
1641 if (plen
+ 1 > es
->textlen
)
1643 dprintf_edit(stddeb
,"InsertText: Realloc\n");
1644 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, es
->textlen
+ len
);
1645 text
= EDIT_HeapLock(hwnd
, es
->hText
);
1646 es
->textlen
= plen
+ 1;
1648 memmove(CurrChar
+ len
, CurrChar
, strlen(CurrChar
) + 1);
1649 memcpy(CurrChar
, str
, len
);
1651 EDIT_BuildTextPointers(hwnd
);
1652 es
->PaintBkgd
= TRUE
;
1653 es
->TextChanged
= TRUE
;
1655 EDIT_GetLineCol(hwnd
, (int)((CurrChar
+ len
) - text
), &(es
->CurrLine
),
1657 es
->WndRow
= es
->CurrLine
- es
->wtop
;
1658 es
->WndCol
= EDIT_StrWidth(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
1659 es
->CurrCol
, 0) - es
->wleft
;
1662 /*********************************************************************
1663 * EDIT_ClearDeletedText
1665 * Clear deleted text buffer.
1667 static void EDIT_ClearDeletedText(HWND hwnd
)
1669 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1671 GlobalFree(es
->hDeletedText
);
1672 es
->hDeletedText
= 0;
1673 es
->DeletedLength
= 0;
1676 /*********************************************************************
1677 * EDIT_CopyToClipboard
1679 * Copy the specified text to the clipboard.
1681 static void EDIT_CopyToClipboard(HWND hwnd
)
1687 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1689 bbl
= EDIT_TextLine(hwnd
, es
->SelBegLine
) + es
->SelBegCol
;
1690 bel
= EDIT_TextLine(hwnd
, es
->SelEndLine
) + es
->SelEndCol
;
1691 len
= (int)(bel
- bbl
);
1693 hMem
= GlobalAlloc(GHND
, (DWORD
)(len
+ 1));
1694 lpMem
= GlobalLock(hMem
);
1696 for (i
= 0; i
< len
; i
++)
1700 OpenClipboard(hwnd
);
1702 SetClipboardData(CF_TEXT
, hMem
);
1706 /*********************************************************************
1709 * Process keystrokes that produce displayable characters.
1711 static void EDIT_KeyTyped(HWND hwnd
, short ch
)
1713 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1714 char *text
= EDIT_HeapLock(hwnd
, es
->hText
);
1717 BOOL FullPaint
= FALSE
;
1719 dprintf_edit(stddeb
,"EDIT_KeyTyped: ch=%c\n", (char)ch
);
1721 /* delete selected text (if any) */
1723 EDIT_DeleteSel(hwnd
);
1725 /* currchar must be assigned after deleting the selection */
1726 currchar
= CurrChar
;
1728 /* test for typing at end of maximum buffer size */
1729 if (currchar
== text
+ es
->MaxTextLen
)
1731 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1735 if (*currchar
== '\0' && IsMultiLine(hwnd
))
1737 /* insert a newline at end of text */
1739 *(currchar
+ 1) = '\n';
1740 *(currchar
+ 2) = '\0';
1741 EDIT_BuildTextPointers(hwnd
);
1744 /* insert the typed character */
1745 if (text
[es
->textlen
- 1] != '\0')
1747 /* current text buffer is full */
1748 if (es
->textlen
== es
->MaxTextLen
)
1750 /* text buffer is at maximum size */
1751 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1755 /* increase the text buffer size */
1756 es
->textlen
+= GROWLENGTH
;
1757 /* but not above maximum size */
1758 if (es
->textlen
> es
->MaxTextLen
)
1759 es
->textlen
= es
->MaxTextLen
;
1760 dprintf_edit( stddeb
, "EDIT_KeyTyped: realloc\n" );
1761 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, es
->textlen
+ 2);
1763 NOTIFY_PARENT(hwnd
, EN_ERRSPACE
);
1764 text
= EDIT_HeapLock(hwnd
, es
->hText
);
1765 text
[es
->textlen
- 1] = '\0';
1766 currchar
= CurrChar
;
1768 /* make space for new character and put char in buffer */
1771 memmove(currchar
+ 2, currchar
, strlen(currchar
) + 1);
1773 *(currchar
+ 1) = '\n';
1774 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, 2);
1778 memmove(currchar
+ 1, currchar
, strlen(currchar
) + 1);
1780 EDIT_ModTextPointers(hwnd
, es
->CurrLine
+ 1, 1);
1782 es
->TextChanged
= TRUE
;
1783 NOTIFY_PARENT(hwnd
, EN_UPDATE
);
1785 /* re-adjust textwidth, if necessary, and redraw line */
1787 if (IsMultiLine(hwnd
) && es
->wlines
> 1)
1789 es
->textwidth
= MAX(es
->textwidth
,
1790 EDIT_StrWidth(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
1791 (int)(EDIT_TextLine(hwnd
, es
->CurrLine
+ 1) -
1792 EDIT_TextLine(hwnd
, es
->CurrLine
)), 0));
1794 es
->textwidth
= MAX(es
->textwidth
,
1795 EDIT_StrWidth(hwnd
, text
, strlen(text
), 0));
1803 EDIT_BuildTextPointers(hwnd
);
1807 /* invalidate rest of window */
1808 GetClientRect(hwnd
, &rc
);
1810 rc
.top
= es
->WndRow
* es
->txtht
;
1811 InvalidateRect(hwnd
, &rc
, FALSE
);
1813 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1816 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1820 /* test end of window */
1821 if (es
->WndCol
>= es
->ClientWidth
-
1822 EDIT_CharWidth(hwnd
, (BYTE
)ch
, es
->WndCol
+ es
->wleft
))
1824 /* TODO:- Word wrap to be handled here */
1826 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1827 EDIT_KeyHScroll(hwnd
, SB_LINEDOWN
);
1829 es
->WndCol
+= EDIT_CharWidth(hwnd
, (BYTE
)ch
, es
->WndCol
+ es
->wleft
);
1831 EDIT_WriteTextLine(hwnd
, NULL
, es
->wtop
+ es
->WndRow
);
1832 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
1834 NOTIFY_PARENT(hwnd
, EN_CHANGE
);
1835 dprintf_edit(stddeb
,"KeyTyped O.K.\n");
1838 /*********************************************************************
1839 * EM_UNDO message function
1841 static LONG
EDIT_UndoMsg(HWND hwnd
)
1844 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1846 if (es
->hDeletedText
)
1848 text
= (char *)GlobalLock(es
->hDeletedText
);
1849 es
->CurrLine
= es
->DeletedCurrLine
;
1850 es
->CurrCol
= es
->DeletedCurrCol
;
1851 EDIT_InsertText(hwnd
, text
, es
->DeletedLength
);
1852 GlobalUnlock(es
->hDeletedText
);
1853 EDIT_ClearDeletedText(hwnd
);
1855 es
->SelBegLine
= es
->CurrLine
;
1856 es
->SelBegCol
= es
->CurrCol
;
1857 EDIT_GetLineCol(hwnd
, (int)((CurrChar
+ es
->DeletedLength
) - text
),
1858 &(es
->CurrLine
), &(es
->CurrCol
));
1859 es
->WndRow
= es
->CurrLine
- es
->wtop
;
1860 es
->WndCol
= EDIT_StrWidth(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
1861 es
->CurrCol
, 0) - es
->wleft
;
1862 es
->SelEndLine
= es
->CurrLine
;
1863 es
->SelEndCol
= es
->CurrCol
;
1865 InvalidateRect(hwnd
, NULL
, TRUE
);
1873 /*********************************************************************
1874 * EM_SETHANDLE message function
1876 static void EDIT_SetHandleMsg(HWND hwnd
, WPARAM wParam
)
1878 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1880 if (IsMultiLine(hwnd
))
1882 es
->hText
= (HANDLE
)wParam
;
1883 es
->textlen
= EDIT_HeapSize(hwnd
, es
->hText
);
1885 es
->wtop
= es
->wleft
= 0;
1886 es
->CurrLine
= es
->CurrCol
= 0;
1887 es
->WndRow
= es
->WndCol
= 0;
1888 es
->TextChanged
= FALSE
;
1890 es
->SelBegLine
= es
->SelBegCol
= 0;
1891 es
->SelEndLine
= es
->SelEndCol
= 0;
1892 dprintf_edit(stddeb
, "EDIT_SetHandleMsg: handle %04lx, textlen=%d\n",
1893 (DWORD
)wParam
, es
->textlen
);
1895 EDIT_BuildTextPointers(hwnd
);
1896 es
->PaintBkgd
= TRUE
;
1897 InvalidateRect(hwnd
, NULL
, TRUE
);
1902 /*********************************************************************
1903 * EM_SETTABSTOPS message function
1905 static LONG
EDIT_SetTabStopsMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
1907 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1909 dprintf_edit( stddeb
, "EDIT_SetTabStops\n" );
1910 es
->NumTabStops
= wParam
;
1912 es
->TabStops
= xrealloc(es
->TabStops
, 2);
1913 else if (wParam
== 1)
1915 es
->TabStops
= xrealloc(es
->TabStops
, 2);
1916 es
->TabStops
[0] = LOWORD(lParam
);
1920 es
->TabStops
= xrealloc(es
->TabStops
, wParam
* sizeof(*es
->TabStops
));
1921 memcpy(es
->TabStops
, (unsigned short *)PTR_SEG_TO_LIN(lParam
), wParam
);
1926 /*********************************************************************
1927 * EM_GETLINE message function
1929 static LONG
EDIT_GetLineMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
1933 unsigned char *buffer
= (char *)PTR_SEG_TO_LIN(lParam
);
1935 /* the line wanted */
1936 cp
= EDIT_TextLine (hwnd
, wParam
);
1937 len
= EDIT_LineLength(hwnd
, wParam
);
1939 /* if cp==NULL nothing will be copied - I hope */
1940 if ((char *) NULL
== cp
&& 0 != len
) {
1941 fprintf(stdnimp
,"edit: EDIT_GetLineMsg cp == NULL && len != 0");
1946 fprintf(stdnimp
,"edit: EDIT_GetLineMsg len < 0");
1948 /* suggested reason for the following line:
1949 never copy more than the buffer's size ?
1950 I thought that this would make sense only if
1951 the lstrcpyn fun was used instead of the gnu strncpy.
1953 len
= MIN(len
, (WORD
)(*buffer
));
1956 fprintf(stdnimp
,"edit: EDIT_GetLineMsg len < 0 after MIN");
1958 dprintf_edit( stddeb
, "EDIT_GetLineMsg: %d %d, len %d\n", (int)(WORD
)(*buffer
), (int)(WORD
)(*(char *)buffer
), len
);
1959 lstrcpyn(buffer
, cp
, len
);
1964 /*********************************************************************
1965 * EM_GETSEL message function
1967 static LONG
EDIT_GetSelMsg(HWND hwnd
)
1970 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1972 so
= es
->textptrs
[es
->SelBegLine
] + es
->SelBegCol
;
1973 eo
= es
->textptrs
[es
->SelEndLine
] + es
->SelEndCol
;
1975 return MAKELONG(so
, eo
);
1978 /*********************************************************************
1979 * EM_REPLACESEL message function
1981 static void EDIT_ReplaceSel(HWND hwnd
, LONG lParam
)
1983 EDIT_DeleteSel(hwnd
);
1984 EDIT_InsertText(hwnd
, (char *)PTR_SEG_TO_LIN(lParam
),
1985 strlen((char *)PTR_SEG_TO_LIN(lParam
)));
1986 InvalidateRect(hwnd
, NULL
, TRUE
);
1990 /*********************************************************************
1991 * EM_LINEFROMCHAR message function
1993 static LONG
EDIT_LineFromCharMsg(HWND hwnd
, WORD wParam
)
1996 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
1998 if (wParam
== (WORD
)-1)
1999 return (LONG
)(es
->SelBegLine
);
2001 EDIT_GetLineCol(hwnd
, wParam
, &row
, &col
);
2007 /*********************************************************************
2008 * EM_LINEINDEX message function
2010 static LONG
EDIT_LineIndexMsg(HWND hwnd
, WORD wParam
)
2012 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2014 if (wParam
== (WORD
)-1) wParam
= es
->CurrLine
;
2015 return es
->textptrs
[wParam
];
2019 /*********************************************************************
2020 * EM_LINELENGTH message function
2022 static LONG
EDIT_LineLengthMsg(HWND hwnd
, WORD wParam
)
2025 int sbl
, sbc
, sel
, sec
;
2026 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2028 if (wParam
== (WORD
)-1)
2032 sbl
= es
->SelBegLine
;
2033 sbc
= es
->SelBegCol
;
2034 sel
= es
->SelEndLine
;
2035 sec
= es
->SelEndCol
;
2042 if (sbl
== sel
&& sbc
> sec
)
2047 len
= es
->textptrs
[sbl
+ 1] - es
->textptrs
[sbl
] - 1;
2048 return len
- sec
- sbc
;
2051 len
= es
->textptrs
[sel
+ 1] - es
->textptrs
[sel
] - sec
- 1;
2054 else /* no selection marked */
2056 len
= es
->textptrs
[es
->CurrLine
+ 1] - es
->textptrs
[es
->CurrLine
] - 1;
2060 else /* line number specified */
2062 EDIT_GetLineCol(hwnd
, wParam
, &row
, &col
);
2063 len
= es
->textptrs
[row
+ 1] - es
->textptrs
[row
];
2068 /*********************************************************************
2069 * EM_SETSEL message function
2071 static void EDIT_SetSelMsg(HWND hwnd
, WORD wParam
, LONG lParam
)
2074 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2076 so
= LOWORD(lParam
);
2077 eo
= HIWORD(lParam
);
2079 if (so
== -1) /* if so == -1, clear selection */
2081 EDIT_ClearSel(hwnd
);
2085 if (so
== eo
) /* if so == eo, set caret only */
2087 EDIT_GetLineCol(hwnd
, (int) so
, &(es
->CurrLine
), &(es
->CurrCol
));
2088 es
->WndRow
= es
->CurrLine
- es
->wtop
;
2092 if (es
->WndRow
< 0 || es
->WndRow
> es
->ClientHeight
)
2094 es
->wtop
= es
->CurrLine
;
2097 es
->WndCol
= EDIT_StrWidth(hwnd
,
2098 EDIT_TextLine(hwnd
, es
->CurrLine
),
2099 es
->CurrCol
, 0) - es
->wleft
;
2100 if (es
->WndCol
> es
->ClientWidth
)
2102 es
->wleft
= es
->WndCol
;
2105 else if (es
->WndCol
< 0)
2107 es
->wleft
+= es
->WndCol
;
2112 else /* otherwise set selection */
2114 if (eo
>= 0 && so
> eo
) /* eo == -1 flag to extend to end of text */
2122 EDIT_GetLineCol(hwnd
, (int) so
, &(es
->SelBegLine
), &(es
->SelBegCol
));
2123 EDIT_GetLineCol(hwnd
, (int) eo
, &(es
->SelEndLine
), &(es
->SelEndCol
));
2124 es
->CurrLine
= es
->SelEndLine
;
2125 es
->CurrCol
= es
->SelEndCol
;
2126 es
->WndRow
= es
->SelEndLine
- es
->wtop
;
2128 if (!wParam
) /* don't suppress scrolling of text */
2132 es
->wtop
= es
->SelEndLine
;
2135 else if (es
->WndRow
> es
->ClientHeight
)
2137 es
->wtop
+= es
->WndRow
- es
->ClientHeight
;
2138 es
->WndRow
= es
->ClientHeight
;
2140 es
->WndCol
= EDIT_StrWidth(hwnd
,
2141 EDIT_TextLine(hwnd
, es
->SelEndLine
),
2142 es
->SelEndCol
, 0) - es
->wleft
;
2143 if (es
->WndCol
> es
->ClientWidth
)
2145 es
->wleft
+= es
->WndCol
- es
->ClientWidth
;
2146 es
->WndCol
= es
->ClientWidth
;
2148 else if (es
->WndCol
< 0)
2150 es
->wleft
+= es
->WndCol
;
2155 InvalidateRect(hwnd
, NULL
, TRUE
);
2160 /*********************************************************************
2163 static void EDIT_WM_SetFont(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2168 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2170 es
->hFont
= (HANDLE
)wParam
;
2172 oldfont
= (HFONT
)SelectObject(hdc
, (HANDLE
)es
->hFont
);
2173 GetCharWidth(hdc
, 0, 255, es
->CharWidths
);
2174 GetTextMetrics(hdc
, &tm
);
2175 es
->txtht
= tm
.tmHeight
+ tm
.tmExternalLeading
;
2176 SelectObject(hdc
, (HANDLE
)oldfont
);
2177 ReleaseDC(hwnd
, hdc
);
2179 es
->WndRow
= (es
->CurrLine
- es
->wtop
) / es
->txtht
;
2180 es
->WndCol
= EDIT_StrWidth(hwnd
, EDIT_TextLine(hwnd
, es
->CurrLine
),
2181 es
->CurrCol
, 0) - es
->wleft
;
2183 InvalidateRect(hwnd
, NULL
, TRUE
);
2184 es
->PaintBkgd
= TRUE
;
2185 if (lParam
) UpdateWindow(hwnd
);
2186 EDIT_RecalcSize(hwnd
,es
);
2189 /*********************************************************************
2192 static void EDIT_WM_Paste(HWND hwnd
)
2197 OpenClipboard(hwnd
);
2198 if (!(hClipMem
= GetClipboardData(CF_TEXT
)))
2200 /* no text in clipboard */
2204 lpClipMem
= GlobalLock(hClipMem
);
2205 EDIT_InsertText(hwnd
, lpClipMem
, strlen(lpClipMem
));
2206 GlobalUnlock(hClipMem
);
2208 InvalidateRect(hwnd
, NULL
, TRUE
);
2212 /*********************************************************************
2215 static void EDIT_WM_Paint(HWND hwnd
)
2221 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2223 hdc
= BeginPaint(hwnd
, &ps
);
2226 dprintf_edit(stddeb
,"WM_PAINT: rc=(%ld,%ld), (%ld,%ld)\n", (LONG
)rc
.left
,
2227 (LONG
)rc
.top
, (LONG
)rc
.right
, (LONG
)rc
.bottom
);
2230 FillWindow(GetParent(hwnd
), hwnd
, hdc
, (HBRUSH
)CTLCOLOR_EDIT
);
2232 for (y
= (rc
.top
/ es
->txtht
); y
<= (rc
.bottom
/ es
->txtht
); y
++)
2234 if (y
< (IsMultiLine(hwnd
) ? es
->wlines
: 1) - es
->wtop
)
2235 EDIT_WriteTextLine(hwnd
, &rc
, y
+ es
->wtop
);
2238 EndPaint(hwnd
, &ps
);
2241 static BOOL
LOCAL_HeapExists(HANDLE ds
)
2243 /* There is always a local heap in WineLib */
2245 INSTANCEDATA
*ptr
= (INSTANCEDATA
*)PTR_SEG_OFF_TO_LIN( ds
, 0 );
2246 if (!ptr
->heap
) return 0;
2251 /*********************************************************************
2254 static long EDIT_WM_NCCreate(HWND hwnd
, LONG lParam
)
2256 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
2257 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
2262 /* store pointer to local or global heap in window structure so that */
2263 /* EDITSTATE structure itself can be stored on local heap */
2264 /* allocate space for state variable structure */
2265 es
= xmalloc( sizeof(EDITSTATE
) );
2266 SetWindowLong( hwnd
, 0, (LONG
)es
);
2267 es
->textptrs
= xmalloc(sizeof(int));
2268 es
->CharWidths
= xmalloc(256 * sizeof(INT
));
2269 es
->ClientWidth
= es
->ClientHeight
= 1;
2270 /* --- text buffer */
2271 es
->MaxTextLen
= MAXTEXTLEN
+ 1;
2273 * Hack - If there is no local heap then hwnd should be a globalHeap block
2274 * and the local heap needs to be initilised to the same size(minus something)
2275 * as the global block
2277 ds
= WIN_GetWindowInstance(hwnd
);
2279 if (!LOCAL_HeapExists(ds
))
2282 globalSize
= GlobalSize(ds
);
2283 dprintf_edit(stddeb
, "No local heap allocated global size is %ld 0x%lx\n",globalSize
, globalSize
);
2285 * I assume the local heap should start at 0
2287 LocalInit(ds
, 0, globalSize
);
2289 * Apparantly we should do an UnlockSegment here but i think this
2290 * is because LocalInit is supposed to do a LockSegment. Since
2291 * Local Init doesn't do this then it doesn't seem like a good idea to do the
2292 * UnlockSegment here yet!
2293 * UnlockSegment(hwnd);
2299 if (!(createStruct
->lpszName
))
2301 dprintf_edit( stddeb
, "EDIT_WM_NCCREATE: lpszName == 0\n" );
2302 es
->textlen
= EditBufStartLen(hwnd
) + 1;
2303 es
->hText
= EDIT_HeapAlloc(hwnd
, es
->textlen
+ 2, LMEM_MOVEABLE
);
2304 text
= EDIT_HeapLock(hwnd
, es
->hText
);
2305 memset(text
, 0, es
->textlen
+ 2);
2308 EDIT_ClearTextPointers(hwnd
);
2309 if (IsMultiLine(hwnd
)) strcpy(text
, "\r\n");
2310 EDIT_BuildTextPointers(hwnd
);
2314 char *windowName
= (char *)PTR_SEG_TO_LIN( createStruct
->lpszName
);
2315 dprintf_edit( stddeb
, "EDIT_WM_NCCREATE: lpszName != 0\n" );
2317 if (strlen(windowName
) < EditBufStartLen(hwnd
))
2319 es
->textlen
= EditBufStartLen(hwnd
) + 3;
2320 es
->hText
= EDIT_HeapAlloc(hwnd
, es
->textlen
+ 2, LMEM_MOVEABLE
);
2323 text
= EDIT_HeapLock(hwnd
, es
->hText
);
2326 strcpy(text
, windowName
);
2327 if(IsMultiLine(hwnd
)) {
2328 strcat(text
, "\r\n");
2330 *(text
+ es
->textlen
) = '\0';
2336 es
->textlen
= strlen(windowName
) + 3;
2337 es
->hText
= EDIT_HeapAlloc(hwnd
, es
->textlen
+ 2, LMEM_MOVEABLE
);
2338 text
= EDIT_HeapLock(hwnd
, es
->hText
);
2339 strcpy(text
, windowName
);
2340 if(IsMultiLine(hwnd
)) strcat(text
, "\r\n");
2341 *(text
+ es
->textlen
) = '\0';
2345 *(text
+ es
->textlen
+ 1) = '\0';
2346 EDIT_BuildTextPointers(hwnd
);
2350 /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
2351 /* the corresponding WS_* style is set */
2352 if (createStruct
->style
& WS_VSCROLL
)
2353 wndPtr
->dwStyle
|= ES_AUTOVSCROLL
;
2354 if (createStruct
->style
& WS_HSCROLL
)
2355 wndPtr
->dwStyle
|= ES_AUTOHSCROLL
;
2357 /* remove the WS_CAPTION style if it has been set - this is really a */
2358 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
2359 if (wndPtr
->dwStyle
& WS_BORDER
&& wndPtr
->dwStyle
& WS_DLGFRAME
)
2360 wndPtr
->dwStyle
^= WS_DLGFRAME
;
2365 /*********************************************************************
2368 static long EDIT_WM_Create(HWND hwnd
, LONG lParam
)
2371 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2375 /* initialize state variable structure */
2378 /* --- char width array */
2379 /* only initialise chars <= 32 as X returns strange widths */
2380 /* for other chars */
2381 memset(es
->CharWidths
, 0, 256 * sizeof(INT
));
2382 GetCharWidth(hdc
, 32, 254, &es
->CharWidths
[32]);
2384 /* --- other structure variables */
2385 GetTextMetrics(hdc
, &tm
);
2386 es
->txtht
= tm
.tmHeight
+ tm
.tmExternalLeading
;
2387 EDIT_RecalcSize(hwnd
,es
);
2388 es
->wtop
= es
->wleft
= 0;
2389 es
->CurrCol
= es
->CurrLine
= 0;
2390 es
->WndCol
= es
->WndRow
= 0;
2391 es
->TextChanged
= FALSE
;
2392 es
->SelBegLine
= es
->SelBegCol
= 0;
2393 es
->SelEndLine
= es
->SelEndCol
= 0;
2395 es
->hDeletedText
= 0;
2396 es
->DeletedLength
= 0;
2397 es
->NumTabStops
= 0;
2398 es
->TabStops
= xmalloc( sizeof(short) );
2400 /* allocate space for a line full of blanks to speed up */
2402 es
->BlankLine
= xmalloc( (es
->ClientWidth
/ es
->CharWidths
[32]) + 2);
2403 memset(es
->BlankLine
, ' ', (es
->ClientWidth
/ es
->CharWidths
[32]) + 2);
2404 es
->BlankLine
[(es
->ClientWidth
/ es
->CharWidths
[32]) + 1] = 0;
2406 /* set up text cursor for edit class */
2408 char editname
[] = "EDIT";
2409 CLASS_FindClassByName( MAKE_SEGPTR(editname
), 0, &classPtr
);
2410 classPtr
->wc
.hCursor
= LoadCursor(0, IDC_IBEAM
);
2413 /* paint background on first WM_PAINT */
2414 es
->PaintBkgd
= TRUE
;
2416 ReleaseDC(hwnd
, hdc
);
2420 /*********************************************************************
2423 static void EDIT_WM_VScroll(HWND hwnd
, WORD wParam
, LONG lParam
)
2425 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2427 if (IsMultiLine(hwnd
))
2435 EDIT_VScrollLine(hwnd
, wParam
);
2440 EDIT_VScrollPage(hwnd
, wParam
);
2445 SetCaretPos(es
->WndCol
, es
->WndRow
);
2449 /*********************************************************************
2452 static void EDIT_WM_HScroll(HWND hwnd
, WORD wParam
, LONG lParam
)
2454 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2462 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2468 /*********************************************************************
2471 static void EDIT_WM_Size(HWND hwnd
, WORD wParam
, LONG lParam
)
2473 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2475 EDIT_RecalcSize(hwnd
,es
);
2476 if (wParam
!= SIZE_MAXIMIZED
&& wParam
!= SIZE_RESTORED
) return;
2477 InvalidateRect(hwnd
, NULL
, TRUE
);
2478 es
->PaintBkgd
= TRUE
;
2482 /*********************************************************************
2485 static void EDIT_WM_LButtonDown(HWND hwnd
, WORD wParam
, LONG lParam
)
2490 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2493 EDIT_ClearSel(hwnd
);
2495 es
->WndRow
= HIWORD(lParam
) / es
->txtht
;
2496 dprintf_edit( stddeb
, "EDIT_LButtonDown: %04x %08lx, WndRow %d\n", wParam
,
2497 lParam
, es
->WndRow
);
2498 if (!IsMultiLine(hwnd
)) es
->WndRow
= 0;
2499 else if (es
->WndRow
> es
->wlines
- es
->wtop
- 1)
2501 es
->WndRow
= es
->wlines
- es
->wtop
- 1;
2504 es
->CurrLine
= es
->wtop
+ es
->WndRow
;
2506 cp
= EDIT_TextLine(hwnd
, es
->CurrLine
);
2507 len
= EDIT_LineLength(hwnd
, es
->CurrLine
);
2508 es
->WndCol
= LOWORD(lParam
) + es
->wleft
;
2509 if (end
|| es
->WndCol
> EDIT_StrWidth(hwnd
, cp
, len
, 0))
2510 es
->WndCol
= EDIT_StrWidth(hwnd
, cp
, len
, 0);
2511 dprintf_edit( stddeb
, "EDIT_LButtonDown: CurrLine %d wtop %d wndcol %d\n",
2512 es
->CurrLine
, es
->wtop
, es
->WndCol
);
2513 es
->CurrCol
= EDIT_PixelToChar(hwnd
, es
->CurrLine
, &(es
->WndCol
));
2514 es
->WndCol
-= es
->wleft
;
2517 ButtonRow
= es
->CurrLine
;
2518 ButtonCol
= es
->CurrCol
;
2521 /*********************************************************************
2524 static void EDIT_WM_MouseMove(HWND hwnd
, WORD wParam
, LONG lParam
)
2526 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2528 if (wParam
!= MK_LBUTTON
)
2534 EDIT_SetAnchor(hwnd
, ButtonRow
, ButtonCol
);
2541 EDIT_ExtendSel(hwnd
, LOWORD(lParam
), HIWORD(lParam
));
2542 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2547 /*********************************************************************
2550 static void EDIT_WM_Char(HWND hwnd
, WORD wParam
)
2552 dprintf_edit(stddeb
,"EDIT_WM_Char: wParam=%c\n", (char)wParam
);
2558 if (!IsMultiLine(hwnd
))
2561 EDIT_KeyTyped(hwnd
, wParam
);
2565 if (!IsMultiLine(hwnd
))
2567 EDIT_KeyTyped(hwnd
, wParam
);
2571 if (wParam
>= 20 && wParam
<= 254 && wParam
!= 127 )
2572 EDIT_KeyTyped(hwnd
, wParam
);
2577 /*********************************************************************
2580 static void EDIT_WM_KeyDown(HWND hwnd
, WORD wParam
)
2582 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2584 dprintf_edit(stddeb
,"EDIT_WM_KeyDown: key=%x\n", wParam
);
2591 EDIT_ClearSel(hwnd
);
2592 if (IsMultiLine(hwnd
))
2595 EDIT_Backward(hwnd
);
2600 EDIT_ClearSel(hwnd
);
2601 if (IsMultiLine(hwnd
))
2602 EDIT_Downward(hwnd
);
2609 EDIT_ClearSel(hwnd
);
2615 EDIT_ClearSel(hwnd
);
2616 EDIT_Backward(hwnd
);
2621 EDIT_ClearSel(hwnd
);
2627 EDIT_ClearSel(hwnd
);
2632 if (IsMultiLine(hwnd
))
2635 EDIT_ClearSel(hwnd
);
2636 EDIT_KeyVScrollPage(hwnd
, SB_PAGEUP
);
2641 if (IsMultiLine(hwnd
))
2644 EDIT_ClearSel(hwnd
);
2645 EDIT_KeyVScrollPage(hwnd
, SB_PAGEDOWN
);
2651 EDIT_DeleteSel(hwnd
);
2654 if (es
->CurrCol
== 0 && es
->CurrLine
== 0)
2656 EDIT_Backward(hwnd
);
2663 EDIT_DeleteSel(hwnd
);
2669 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2673 /*********************************************************************
2676 static LONG
EDIT_WM_SetText(HWND hwnd
, LONG lParam
)
2679 char *text
,*settext
;
2680 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2682 settext
= PTR_SEG_TO_LIN( lParam
);
2683 dprintf_edit( stddeb
,"WM_SetText, length %d\n",strlen(settext
) );
2684 if (strlen(settext
) <= es
->MaxTextLen
)
2686 len
= settext
!= NULL
? strlen(settext
) : 0;
2687 EDIT_ClearText(hwnd
);
2689 dprintf_edit( stddeb
, "EDIT_WM_SetText: realloc\n" );
2690 es
->hText
= EDIT_HeapReAlloc(hwnd
, es
->hText
, len
+ 3);
2691 text
= EDIT_HeapLock(hwnd
, es
->hText
);
2693 strcpy(text
, (char *)PTR_SEG_TO_LIN(lParam
));
2695 text
[len
+ 1] = '\0';
2696 text
[len
+ 2] = '\0';
2697 EDIT_BuildTextPointers(hwnd
);
2698 InvalidateRect(hwnd
, NULL
, TRUE
);
2699 es
->PaintBkgd
= TRUE
;
2700 es
->TextChanged
= TRUE
;
2707 /*********************************************************************
2710 LRESULT
EditWndProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2715 EDITSTATE
*es
= EDIT_GetEditState(hwnd
);
2719 lResult
= (LONG
)es
->hDeletedText
;
2722 case EM_EMPTYUNDOBUFFER
:
2723 EDIT_ClearDeletedText(hwnd
);
2727 fprintf(stdnimp
,"edit: EM_FMTLINES message received\n");
2734 case EM_GETFIRSTVISIBLELINE
:
2739 lResult
= (LONG
)es
->hText
;
2743 if (IsMultiLine(hwnd
))
2744 lResult
= EDIT_GetLineMsg(hwnd
, wParam
, lParam
);
2749 case EM_GETLINECOUNT
:
2750 if (IsMultiLine(hwnd
))
2751 lResult
= es
->wlines
;
2757 lResult
= es
->TextChanged
;
2760 case EM_GETPASSWORDCHAR
:
2761 fprintf(stdnimp
,"edit: cannot process EM_GETPASSWORDCHAR message\n");
2765 GetWindowRect(hwnd
, (LPRECT
)PTR_SEG_TO_LIN(lParam
));
2769 lResult
= EDIT_GetSelMsg(hwnd
);
2772 case EM_GETWORDBREAKPROC
:
2773 fprintf(stdnimp
,"edit: cannot process EM_GETWORDBREAKPROC message\n");
2778 es
->MaxTextLen
= wParam
;
2779 else if (IsMultiLine(hwnd
))
2780 es
->MaxTextLen
= 65535;
2782 es
->MaxTextLen
= 32767;
2785 case EM_LINEFROMCHAR
:
2786 lResult
= EDIT_LineFromCharMsg(hwnd
, wParam
);
2790 if (IsMultiLine(hwnd
))
2791 lResult
= EDIT_LineIndexMsg(hwnd
, wParam
);
2797 lResult
= EDIT_LineLengthMsg(hwnd
, wParam
);
2801 fprintf(stdnimp
,"edit: cannot process EM_LINESCROLL message\n");
2806 EDIT_ReplaceSel(hwnd
, lParam
);
2807 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2813 EDIT_SetHandleMsg(hwnd
, wParam
);
2814 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2819 es
->TextChanged
= wParam
;
2822 case EM_SETPASSWORDCHAR
:
2823 fprintf(stdnimp
,"edit: cannot process EM_SETPASSWORDCHAR message\n");
2826 case EM_SETREADONLY
:
2827 fprintf(stdnimp
,"edit: cannot process EM_SETREADONLY message\n");
2832 fprintf(stdnimp
,"edit: cannot process EM_SETRECT(NP) message\n");
2837 EDIT_SetSelMsg(hwnd
, wParam
, lParam
);
2838 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2842 case EM_SETTABSTOPS
:
2843 lResult
= EDIT_SetTabStopsMsg(hwnd
, wParam
, lParam
);
2846 case EM_SETWORDBREAKPROC
:
2847 fprintf(stdnimp
,"edit: cannot process EM_SETWORDBREAKPROC message\n");
2852 lResult
= EDIT_UndoMsg(hwnd
);
2853 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2858 return DLGC_HASSETSEL
| DLGC_WANTCHARS
| DLGC_WANTARROWS
;
2861 EDIT_WM_Char(hwnd
, wParam
);
2865 EDIT_CopyToClipboard(hwnd
);
2866 EDIT_ClearSel(hwnd
);
2870 lResult
= EDIT_WM_Create(hwnd
, lParam
);
2874 EDIT_CopyToClipboard(hwnd
);
2875 EDIT_DeleteSel(hwnd
);
2880 free(es
->CharWidths
);
2882 free(es
->BlankLine
);
2883 EDIT_HeapFree(hwnd
, es
->hText
);
2884 free( EDIT_GetEditState(hwnd
) );
2888 InvalidateRect(hwnd
, NULL
, FALSE
);
2892 textPtr
= EDIT_HeapLock(hwnd
, es
->hText
);
2893 len
= strlen( textPtr
);
2894 if ((int)wParam
> len
)
2896 strcpy((char *)PTR_SEG_TO_LIN(lParam
), textPtr
);
2897 lResult
= (DWORD
)len
;
2901 EDIT_HeapUnlock(hwnd
, es
->hText
);
2904 case WM_GETTEXTLENGTH
:
2905 textPtr
= EDIT_HeapLock(hwnd
, es
->hText
);
2906 lResult
= (DWORD
)strlen(textPtr
);
2907 EDIT_HeapUnlock(hwnd
, es
->hText
);
2911 EDIT_WM_HScroll(hwnd
, wParam
, lParam
);
2915 EDIT_WM_KeyDown(hwnd
, wParam
);
2919 es
->HaveFocus
= FALSE
;
2921 if (SelMarked(es
)) EDIT_ClearSel(hwnd
);
2922 NOTIFY_PARENT(hwnd
, EN_KILLFOCUS
);
2925 case WM_LBUTTONDOWN
:
2929 EDIT_WM_LButtonDown(hwnd
, wParam
, lParam
);
2930 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2935 if (GetCapture() != hwnd
) break;
2939 EDIT_StopMarking(hwnd
);
2944 EDIT_WM_MouseMove(hwnd
, wParam
, lParam
);
2952 lResult
= EDIT_WM_NCCreate(hwnd
, lParam
);
2956 EDIT_WM_Paint(hwnd
);
2960 EDIT_WM_Paste(hwnd
);
2964 es
->HaveFocus
= TRUE
;
2965 CreateCaret(hwnd
, 0, 2, es
->txtht
);
2966 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2968 NOTIFY_PARENT(hwnd
, EN_SETFOCUS
);
2973 EDIT_WM_SetFont(hwnd
, wParam
, lParam
);
2974 SetCaretPos(es
->WndCol
, es
->WndRow
* es
->txtht
);
2979 dprintf_edit(stddeb
, "WM_SETREDRAW: hwnd=%d, wParam=%x\n",
2985 EDIT_WM_SetText(hwnd
, lParam
);
2989 EDIT_WM_Size(hwnd
, wParam
, lParam
);
2994 EDIT_WM_VScroll(hwnd
, wParam
, lParam
);
2998 lResult
= DefWindowProc(hwnd
, uMsg
, wParam
, lParam
);