Release 951226
[wine/multimedia.git] / controls / edit.c
blob98c28419f09edbe5bc37a2f9a04cbf57f783220f
1 /*
2 * Edit control
4 * Copyright David W. Metcalfe, 1994
6 * Release 3, July 1994
7 * April 1995 bug fixes (William Magro)
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <windows.h>
14 #include "instance.h"
15 #include "local.h"
16 #include "win.h"
17 #include "class.h"
18 #include "stackframe.h" /* for MAKE_SEGPTR */
19 #include "user.h"
20 #include "stddebug.h"
21 #include "debug.h"
22 #include "xmalloc.h"
25 #ifdef WINELIB32
26 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
27 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
28 MAKEWPARAM(GetDlgCtrlID(hWndCntrl),wNotifyCode), \
29 (LPARAM)hWndCntrl );
30 #else
31 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
32 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
33 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
34 #endif
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 */
41 typedef struct
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 */
75 } EDITSTATE;
77 #define EditBufStartLen(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE \
78 ? EDITLEN : ENTRYLEN)
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)) \
84 : (numer) + (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 /*********************************************************************
103 * EDIT_HeapAlloc
105 * Allocate the specified number of bytes on the specified local heap.
107 static HLOCAL EDIT_HeapAlloc(HWND hwnd, int bytes, WORD flags)
109 HLOCAL ret;
111 ret = LOCAL_Alloc( WIN_GetWindowInstance(hwnd), flags, bytes );
112 if (!ret)
113 printf("EDIT_HeapAlloc: Out of heap-memory\n");
114 return ret;
117 /*********************************************************************
118 * EDIT_HeapLock
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 );
125 #if defined(WINELIB)
126 return LOCAL_Lock( hinstance, handle );
127 #else
128 HANDLE offs;
130 if (handle == 0) return 0;
131 offs = LOCAL_Lock( hinstance, handle );
132 return PTR_SEG_OFF_TO_LIN( hinstance, offs );
133 #endif
136 /*********************************************************************
137 * EDIT_HeapUnlock
139 static void EDIT_HeapUnlock(HWND hwnd, HANDLE handle)
141 if (handle == 0) return;
142 LOCAL_Unlock( WIN_GetWindowInstance( hwnd ), handle );
145 /*********************************************************************
146 * EDIT_HeapReAlloc
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,
153 LMEM_FIXED );
157 /*********************************************************************
158 * EDIT_HeapFree
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 /*********************************************************************
169 * EDIT_HeapSize
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 /********************************************************************
179 * EDIT_RecalcSize
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)
186 RECT rect;
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 /*********************************************************************
193 * EDIT_GetEditState
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)
207 int i;
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;
220 return pcol;
223 /*********************************************************************
224 * EDIT_CharWidth
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));
249 es->textptrs[0] = 0;
252 /*********************************************************************
253 * EDIT_BuildTextPointers
255 * Build array of pointers to text lines.
257 static void EDIT_BuildTextPointers(HWND hwnd)
259 char *text, *cp;
260 unsigned int off, len, line;
261 EDITSTATE *es;
263 es = EDIT_GetEditState(hwnd);
264 text = EDIT_HeapLock(hwnd, es->hText);
266 es->textwidth = 0;
267 if (IsMultiLine(hwnd)) {
268 es->wlines = 0;
269 cp = text;
270 while ((cp = strchr(cp,'\n')) != NULL) {
271 es->wlines++; cp++;
273 } else es->wlines = 1;
275 dprintf_edit( stddeb, "EDIT_BuildTextPointers: realloc\n" );
276 es->textptrs = xrealloc(es->textptrs, (es->wlines + 2) * sizeof(int));
278 cp = text;
279 dprintf_edit(stddeb,"BuildTextPointers: %d lines, pointer %p\n",
280 es->wlines, es->textptrs);
282 /* advance through text buffer */
283 line = 0;
284 while (*cp)
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;
289 line++;
290 len = 0;
292 /* advance through current line */
293 while (*cp && *cp != '\n')
295 len += EDIT_CharWidth(hwnd, (BYTE)*cp, len);
296 /* width of line in pixels */
297 cp++;
299 es->textwidth = MAX(es->textwidth, len);
300 if (*cp)
301 cp++; /* skip '\n' */
303 off = cp - text;
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 /*********************************************************************
320 * EDIT_TextLine
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 /*********************************************************************
336 * EDIT_GetTextLine
338 * Get a copy of the text in the specified line.
340 static char *EDIT_GetTextLine(HWND hwnd, int selection)
342 int len;
343 char *cp, *cp1;
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);
351 else len = cp - cp1;
353 /* store selected line and return handle */
354 cp = xmalloc( len + 1 );
355 strncpy( cp, cp1, len);
356 cp[len] = 0;
357 return cp;
360 /*********************************************************************
361 * EDIT_StrWidth
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)
369 int i, plen = 0;
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);
375 return plen;
378 /*********************************************************************
379 * EDIT_LineLength
381 * Return length of line _num_ in characters.
383 static int EDIT_LineLength(HWND hwnd, int num)
385 char *cp = EDIT_TextLine(hwnd, num);
386 char *cp1;
388 if(!cp)return 0;
389 cp1 = strchr(cp, '\r');
390 return cp1 ? (cp1 - cp) : strlen(cp);
393 /*********************************************************************
394 * EDIT_GetStr
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_
399 * will be zero.
401 static HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff)
403 HANDLE hStr;
404 char *str;
405 int ch = 0, i = 0, j, s_i=0;
406 int ch1;
408 dprintf_edit(stddeb,"EDIT_GetStr lp='%s' off=%d len=%d\n", lp, off, len);
410 if (off < 0) off = 0;
411 while (i < off)
413 s_i = i;
414 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
415 ch++;
417 /* if stepped past _off_, go back a character */
418 if (i > off)
420 i = s_i;
421 ch--;
423 *diff = off - i;
424 ch1 = ch;
425 while (i < len + off)
427 if (*(lp + ch) == '\r' || *(lp + ch) == '\n')
428 break;
429 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
430 ch++;
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++)
436 str[j] = lp[i];
437 str[j] = '\0';
438 dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str);
439 return hStr;
442 /*********************************************************************
443 * EDIT_WriteText
445 * Write text to a window
446 * lp - text line
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)
458 HDC hdc;
459 HANDLE hStr;
460 char *str, *cp, *cp1;
461 int diff=0, num_spaces, tabwidth, scol;
462 HRGN hrgnClip;
463 COLORREF oldTextColor, oldBkgdColor;
464 HFONT oldfont;
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);
469 if( off < 0 ) {
470 len += off;
471 col -= off;
472 off = 0;
475 hdc = GetDC(hwnd);
476 hStr = EDIT_GetStr(hwnd, lp, off, len, &diff);
477 str = (char *)EDIT_HeapLock(hwnd, hStr);
478 hrgnClip = CreateRectRgnIndirect(rc);
479 SelectClipRgn(hdc, hrgnClip);
481 if (es->hFont)
482 oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
483 else
484 oldfont = 0; /* -Wall does not see the use of if */
486 #ifdef WINELIB32
487 SendMessage(GetParent(hwnd), WM_CTLCOLOREDIT, (WPARAM)hdc, (LPARAM)hwnd);
488 #else
489 SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WPARAM)hdc,
490 MAKELPARAM(hwnd, CTLCOLOR_EDIT));
491 #endif
493 if (reverse)
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 );
517 buff[len] = '\0';
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));
522 else
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);
529 cp++;
530 scol += tabwidth;
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);
539 cp = ++cp1;
540 scol += tabwidth;
543 TextOut(hdc, scol, row * es->txtht, cp, strlen(cp));
546 if (reverse)
548 SetBkColor(hdc, oldBkgdColor);
549 SetTextColor(hdc, oldTextColor);
552 /* blank out remainder of line if appropriate */
553 if (blank)
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);
562 if (es->hFont)
563 SelectObject(hdc, (HANDLE)oldfont);
565 EDIT_HeapFree(hwnd, hStr);
566 ReleaseDC(hwnd, hdc);
569 /*********************************************************************
570 * EDIT_WriteTextLine
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)
576 int len = 0;
577 unsigned char *lp;
578 int lnlen, lnlen1;
579 int col, off = 0;
580 int sbl, sel, sbc, sec;
581 RECT rc;
582 EDITSTATE *es = EDIT_GetEditState(hwnd);
584 /* initialize rectangle if NULL, else copy */
585 if (rect)
586 CopyRect(&rc, rect);
587 else
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);
596 return;
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",
603 (LONG)rc.left);
604 return;
606 if (rc.right <= 0)
608 dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.right (%ld) is less than left edge\n",
609 (LONG)rc.right);
610 return;
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);
616 return;
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 );
624 lnlen1 = lnlen;
626 /* build the line to display */
627 if (lnlen < (es->wleft + rc.left))
629 lnlen = 0;
630 return;
632 else
634 off += es->wleft;
635 lnlen -= off;
638 if (lnlen > rc.left)
640 off += rc.left;
641 lnlen = lnlen1 - off;
643 len = MIN(lnlen, rc.right - rc.left);
645 if (SelMarked(es))
647 sbl = es->SelBegLine;
648 sel = es->SelEndLine;
649 sbc = es->SelBegCol;
650 sec = es->SelEndCol;
652 /* put lowest marker first */
653 if (sbl > sel)
655 SWAP_INT(sbl, sel);
656 SWAP_INT(sbc, sec);
658 if (sbl == sel && sbc > sec)
659 SWAP_INT(sbc, sec);
661 if (y < sbl || y > sel)
662 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
663 TRUE, FALSE);
664 else if (y > sbl && y < sel)
665 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
666 TRUE, TRUE);
667 else if (y == sbl)
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);
675 off = col;
677 if (y == sel)
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);
685 off = col;
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);
690 else
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);
697 else
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);
705 else if (y == sel)
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);
713 off = col;
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);
720 else
721 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
722 TRUE, FALSE);
724 free( lp );
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)
735 int vscrollpos;
736 INT minpos, maxpos;
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);
744 else
745 vscrollpos = minpos;
747 return vscrollpos;
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)
758 int hscrollpos;
759 INT minpos, maxpos;
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);
767 else
768 hscrollpos = minpos;
770 return hscrollpos;
773 /*********************************************************************
774 * EDIT_KeyHScroll
776 * Scroll text horizontally using cursor keys.
778 static void EDIT_KeyHScroll(HWND hwnd, WORD opt)
780 int hscrollpos;
781 EDITSTATE *es = EDIT_GetEditState(hwnd);
783 if (opt == SB_LINEDOWN)
785 es->wleft += HSCROLLDIM(es);
786 es->WndCol -= HSCROLLDIM(es);
788 else
790 if (es->wleft == 0)
791 return;
792 if (es->wleft - HSCROLLDIM(es) < 0)
794 es->WndCol += es->wleft;
795 es->wleft = 0;
797 else
799 es->wleft -= HSCROLLDIM(es);
800 es->WndCol += HSCROLLDIM(es);
804 InvalidateRect(hwnd, NULL, FALSE);
805 UpdateWindow(hwnd);
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)
821 RECT rc;
822 int y, vscrollpos;
823 EDITSTATE *es = EDIT_GetEditState(hwnd);
825 if (!IsMultiLine(hwnd))
826 return;
828 if (opt == SB_LINEDOWN)
830 /* move down one line */
831 if (es->wtop + es->ClientHeight >= es->wlines)
832 return;
833 es->wtop++;
835 else
837 /* move up one line */
838 if (es->wtop == 0)
839 return;
840 --es->wtop;
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);
853 /* write top line */
854 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
855 es->WndRow++;
857 else
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);
864 --es->WndRow;
868 /* reset the vertical scroll bar */
869 if (IsVScrollBar(hwnd))
871 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
872 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
876 /*********************************************************************
877 * EDIT_End
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);
888 es->CurrCol++;
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);
896 UpdateWindow(hwnd);
900 /*********************************************************************
901 * EDIT_Home
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;
910 if (es->wleft != 0)
912 es->wleft = 0;
913 InvalidateRect(hwnd, NULL, FALSE);
914 UpdateWindow(hwnd);
918 /*********************************************************************
919 * EDIT_StickEnd
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);
928 int currpel;
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;
938 UpdateWindow(hwnd);
940 else if (currpel - es->wleft >= es->ClientWidth)
942 es->wleft = currpel - (es->ClientWidth - 5);
943 es->WndCol = currpel - es->wleft;
944 UpdateWindow(hwnd);
948 /*********************************************************************
949 * EDIT_Downward
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))
962 es->CurrLine++;
963 if (es->WndRow == es->ClientHeight - 1)
965 es->WndRow++;
966 EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
968 else
969 es->WndRow++;
970 EDIT_StickEnd(hwnd);
974 /*********************************************************************
975 * EDIT_Upward
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)
985 --es->CurrLine;
986 if (es->WndRow == 0)
988 --es->WndRow;
989 EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
991 else
992 --es->WndRow;
993 EDIT_StickEnd(hwnd);
997 /*********************************************************************
998 * EDIT_Forward
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')
1007 return;
1009 if (*CurrChar == '\r')
1011 if (es->CurrLine < (es->wlines - 1))
1013 EDIT_Home(hwnd);
1014 EDIT_Downward(hwnd);
1017 else
1019 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
1020 es->CurrCol++;
1021 if (es->WndCol >= es->ClientWidth)
1022 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1026 /*********************************************************************
1027 * EDIT_Backward
1029 * Cursor left key: move left one character position.
1031 static void EDIT_Backward(HWND hwnd)
1033 EDITSTATE *es = EDIT_GetEditState(hwnd);
1035 if (es->CurrCol)
1037 --es->CurrCol;
1038 if (*CurrChar == VK_TAB)
1039 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar),
1040 EDIT_StrWidth(hwnd,
1041 EDIT_TextLine(hwnd, es->CurrLine),
1042 es->CurrCol, 0));
1043 else
1044 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), 0);
1045 if (es->WndCol < 0)
1046 EDIT_KeyHScroll(hwnd, SB_LINEUP);
1048 else if (IsMultiLine(hwnd) && es->CurrLine != 0)
1050 EDIT_Upward(hwnd);
1051 EDIT_End(hwnd);
1055 /*********************************************************************
1056 * EDIT_KeyVScrollPage
1058 * Scroll text vertically by one page using keyboard.
1060 static void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
1062 int vscrollpos;
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;
1071 else
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;
1080 if (es->wtop < 0)
1081 es->wtop = 0;
1083 es->CurrLine = es->wtop + es->WndRow;
1084 EDIT_StickEnd(hwnd);
1085 InvalidateRect(hwnd, NULL, TRUE);
1086 UpdateWindow(hwnd);
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)
1105 int vscrollpos;
1106 EDITSTATE *es = EDIT_GetEditState(hwnd);
1108 if (!IsMultiLine(hwnd))
1109 return;
1111 if (opt == SB_TOP)
1112 es->wtop = es->wleft = 0;
1113 else if (es->wtop + es->ClientHeight < es->wlines)
1115 es->wtop = es->wlines - es->ClientHeight;
1116 es->wleft = 0;
1119 es->CurrLine = es->wlines;
1120 es->WndRow = es->wlines - es->wtop;
1121 EDIT_End(hwnd);
1122 InvalidateRect(hwnd, NULL, TRUE);
1123 UpdateWindow(hwnd);
1125 /* reset the vertical scroll bar */
1126 if (IsVScrollBar(hwnd))
1128 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1129 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1132 #endif
1134 /*********************************************************************
1135 * EDIT_DelKey
1137 * Delete character to right of cursor.
1139 static void EDIT_DelKey(HWND hwnd)
1141 RECT rc;
1142 EDITSTATE *es = EDIT_GetEditState(hwnd);
1143 char *currchar = CurrChar;
1144 BOOL repaint = *currchar == '\n';
1146 if (IsMultiLine(hwnd) && *currchar == '\n' && *(currchar + 1) == '\0')
1147 return;
1148 strcpy(currchar, currchar + 1);
1149 NOTIFY_PARENT(hwnd, EN_UPDATE);
1151 if (repaint)
1153 EDIT_BuildTextPointers(hwnd);
1154 GetClientRect(hwnd, &rc);
1155 rc.top = es->WndRow * es->txtht;
1156 InvalidateRect(hwnd, &rc, FALSE);
1157 UpdateWindow(hwnd);
1159 else
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 /*********************************************************************
1170 * EDIT_VScrollLine
1172 * Scroll text vertically by one line using scrollbars.
1174 static void EDIT_VScrollLine(HWND hwnd, WORD opt)
1176 RECT rc;
1177 int y;
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)
1186 return;
1187 es->wtop++;
1189 else
1191 /* move up one line */
1192 if (es->wtop == 0)
1193 return;
1194 --es->wtop;
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);
1209 es->WndRow++;
1211 else
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);
1218 --es->WndRow;
1224 /*********************************************************************
1225 * EDIT_VScrollPage
1227 * Scroll text vertically by one page using keyboard.
1229 static void EDIT_VScrollPage(HWND hwnd, WORD opt)
1231 int vscrollpos;
1232 EDITSTATE *es = EDIT_GetEditState(hwnd);
1234 if (opt == SB_PAGEUP)
1236 if (es->wtop)
1237 es->wtop -= es->ClientHeight;
1239 else
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;
1248 if (es->wtop < 0)
1249 es->wtop = 0;
1251 InvalidateRect(hwnd, NULL, TRUE);
1252 UpdateWindow(hwnd);
1254 /* reset the vertical scroll bar */
1255 if (IsVScrollBar(hwnd))
1257 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1258 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1262 /*********************************************************************
1263 * EDIT_PixelToChar
1265 * Convert a pixel offset in the given row to a character offset,
1266 * adjusting the pixel offset to the nearest whole character if
1267 * necessary.
1269 static int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
1271 int ch = 0, i = 0, s_i = 0;
1272 char *text;
1274 dprintf_edit(stddeb,"EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
1276 text = EDIT_TextLine(hwnd, row);
1277 while (i < *pixel)
1279 s_i = i;
1280 i += EDIT_CharWidth(hwnd, (BYTE)(*(text + ch)), i);
1281 ch++;
1284 /* if stepped past _pixel_, go back a character */
1285 if (i - *pixel)
1287 i = s_i;
1288 --ch;
1290 *pixel = i;
1291 return ch;
1294 /*********************************************************************
1295 * EDIT_ClearText
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;
1303 char *text;
1305 dprintf_edit(stddeb,"EDIT_ClearText %d\n",blen);
1306 /*#ifndef WINELIB*/
1307 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, blen);
1308 text = EDIT_HeapLock(hwnd, es->hText);
1309 memset(text, 0, blen);
1310 /*#endif*/
1311 es->textlen = 0;
1312 es->wlines = 0;
1313 es->CurrLine = es->CurrCol = 0;
1314 es->WndRow = es->WndCol = 0;
1315 es->wleft = es->wtop = 0;
1316 es->textwidth = 0;
1317 es->TextChanged = FALSE;
1318 /*#ifndef WINELIB*/
1319 EDIT_ClearTextPointers(hwnd);
1320 /*#endif*/
1323 /*********************************************************************
1324 * EDIT_GetLineCol
1326 * Return line and column in text buffer from character offset.
1328 static void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
1330 int lineno;
1331 char *cp, *cp1;
1332 EDITSTATE *es = EDIT_GetEditState(hwnd);
1333 char *text = EDIT_HeapLock(hwnd, es->hText);
1335 /* check for (0,0) */
1336 if (!off || !es->wlines)
1338 *line = 0;
1339 *col = 0;
1340 return;
1343 if (off < 0 || off > strlen(text)) off = strlen(text);
1344 cp1 = text;
1345 for (lineno = 0; lineno < es->wlines; lineno++)
1347 cp = text + es->textptrs[lineno];
1348 if (off == (int)(cp - text))
1350 *line = lineno;
1351 *col = 0;
1352 return;
1354 if (off < (int)(cp - text))
1355 break;
1356 cp1 = cp;
1358 *line = lineno - 1;
1359 *col = off - (int)(cp1 - text);
1360 #if 0
1361 if (*(text + *col) == '\0')
1362 (*col)--;
1363 #endif
1366 /*********************************************************************
1367 * EDIT_ClearSel
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);
1379 UpdateWindow(hwnd);
1382 /*********************************************************************
1383 * EDIT_SaveDeletedText
1385 * Save deleted text in deleted text buffer.
1387 static void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len,
1388 int line, int col)
1390 char *text;
1391 EDITSTATE *es = EDIT_GetEditState(hwnd);
1393 dprintf_edit( stddeb, "EDIT_SaveDeletedText\n" );
1394 if (!es->hDeletedText)
1395 es->hDeletedText = GlobalAlloc( GMEM_MOVEABLE, len );
1396 else
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 /*********************************************************************
1408 * EDIT_DeleteSel
1410 * Delete the current selected text (if any)
1412 static void EDIT_DeleteSel(HWND hwnd)
1414 char *bbl, *bel;
1415 int len;
1416 EDITSTATE *es = EDIT_GetEditState(hwnd);
1418 if (SelMarked(es))
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;
1425 strcpy(bbl, bel);
1427 es->CurrLine = es->SelBegLine;
1428 es->CurrCol = es->SelBegCol;
1429 es->WndRow = es->SelBegLine - es->wtop;
1430 if (es->WndRow < 0)
1432 es->wtop = es->SelBegLine;
1433 es->WndRow = 0;
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)
1453 int lineno;
1454 char *cp;
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];
1461 if (cp == lp)
1462 return lineno;
1463 if (cp > lp)
1464 break;
1466 return lineno - 1;
1468 #endif
1470 /*********************************************************************
1471 * EDIT_SetAnchor
1473 * Set down anchor for text marking.
1475 static void EDIT_SetAnchor(HWND hwnd, int row, int col)
1477 BOOL sel = FALSE;
1478 EDITSTATE *es = EDIT_GetEditState(hwnd);
1480 if (SelMarked(es))
1482 sel = TRUE;
1483 EDIT_ClearSel(hwnd);
1485 es->SelBegLine = es->SelEndLine = row;
1486 es->SelBegCol = es->SelEndCol = col;
1487 if (sel)
1489 InvalidateRect(hwnd, NULL, FALSE);
1490 UpdateWindow(hwnd);
1494 /*********************************************************************
1495 * EDIT_WriteSel
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)
1502 RECT rc, rcInvert;
1503 int scol, ecol;
1504 char *cp;
1505 HDC hdc;
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))
1513 return;
1515 /* get pointer to text */
1516 cp = EDIT_TextLine(hwnd, y);
1518 /* get length of line if end == -1 */
1519 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;
1529 hdc = GetDC(hwnd);
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 /*********************************************************************
1539 * EDIT_ExtendSel
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;
1546 char *cp;
1547 int len, line;
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;
1554 y = MAX(y,0);
1555 if (IsMultiLine(hwnd))
1557 if ((line = es->wtop + y / es->txtht) >= es->wlines)
1558 line = es->wlines - 1;
1560 else
1561 line = 0;
1563 cp = EDIT_TextLine(hwnd, line);
1564 len = EDIT_LineLength(hwnd, line);
1566 es->WndRow = y / es->txtht;
1567 if (!IsMultiLine(hwnd))
1568 es->WndRow = 0;
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)
1586 return;
1588 /* put lowest marker first */
1589 if (bbl > bel)
1591 SWAP_INT(bbl, bel);
1592 SWAP_INT(bbc, bec);
1594 if (bbl == bel && bbc > bec)
1595 SWAP_INT(bbc, bec);
1597 for (y = bbl; y <= bel; y++)
1599 if (y == bbl && y == bel)
1600 EDIT_WriteSel(hwnd, y, bbc, bec);
1601 else if (y == bbl)
1602 EDIT_WriteSel(hwnd, y, bbc, -1);
1603 else if (y == bel)
1604 EDIT_WriteSel(hwnd, y, 0, bec);
1605 else
1606 EDIT_WriteSel(hwnd, y, 0, -1);
1610 /*********************************************************************
1611 * EDIT_StopMarking
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 /*********************************************************************
1630 * EDIT_InsertText
1632 * Insert text at current line and column.
1634 static void EDIT_InsertText(HWND hwnd, char *str, int len)
1636 int plen;
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),
1656 &(es->CurrCol));
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)
1683 HANDLE hMem;
1684 char *lpMem;
1685 int i, len;
1686 char *bbl, *bel;
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++)
1697 *lpMem++ = *bbl++;
1699 GlobalUnlock(hMem);
1700 OpenClipboard(hwnd);
1701 EmptyClipboard();
1702 SetClipboardData(CF_TEXT, hMem);
1703 CloseClipboard();
1706 /*********************************************************************
1707 * EDIT_KeyTyped
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);
1715 char *currchar;
1716 RECT rc;
1717 BOOL FullPaint = FALSE;
1719 dprintf_edit(stddeb,"EDIT_KeyTyped: ch=%c\n", (char)ch);
1721 /* delete selected text (if any) */
1722 if (SelMarked(es))
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);
1732 return;
1735 if (*currchar == '\0' && IsMultiLine(hwnd))
1737 /* insert a newline at end of text */
1738 *currchar = '\r';
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);
1752 return;
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);
1762 if (!es->hText)
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 */
1769 if (ch == '\n')
1771 memmove(currchar + 2, currchar, strlen(currchar) + 1);
1772 *currchar = '\r';
1773 *(currchar + 1) = '\n';
1774 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 2);
1776 else
1778 memmove(currchar + 1, currchar, strlen(currchar) + 1);
1779 *currchar = ch;
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 */
1786 HideCaret(hwnd);
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));
1793 } else {
1794 es->textwidth = MAX(es->textwidth,
1795 EDIT_StrWidth(hwnd, text, strlen(text), 0));
1798 if (ch == '\n')
1800 if (es->wleft > 0)
1801 FullPaint = TRUE;
1802 es->wleft = 0;
1803 EDIT_BuildTextPointers(hwnd);
1804 EDIT_End(hwnd);
1805 EDIT_Forward(hwnd);
1807 /* invalidate rest of window */
1808 GetClientRect(hwnd, &rc);
1809 if (!FullPaint)
1810 rc.top = es->WndRow * es->txtht;
1811 InvalidateRect(hwnd, &rc, FALSE);
1813 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1814 ShowCaret(hwnd);
1815 UpdateWindow(hwnd);
1816 NOTIFY_PARENT(hwnd, EN_CHANGE);
1817 return;
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);
1830 es->CurrCol++;
1831 EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
1832 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1833 ShowCaret(hwnd);
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)
1843 char *text;
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);
1866 UpdateWindow(hwnd);
1867 return 1;
1869 else
1870 return 0;
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);
1884 es->wlines = 0;
1885 es->wtop = es->wleft = 0;
1886 es->CurrLine = es->CurrCol = 0;
1887 es->WndRow = es->WndCol = 0;
1888 es->TextChanged = FALSE;
1889 es->textwidth = 0;
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);
1898 UpdateWindow(hwnd);
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;
1911 if (wParam == 0)
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);
1918 else
1920 es->TabStops = xrealloc(es->TabStops, wParam * sizeof(*es->TabStops));
1921 memcpy(es->TabStops, (unsigned short *)PTR_SEG_TO_LIN(lParam), wParam);
1923 return 0;
1926 /*********************************************************************
1927 * EM_GETLINE message function
1929 static LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam)
1931 char *cp;
1932 int len = 0;
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");
1942 return 0L;
1945 if (0>len)
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));
1955 if (0>len)
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);
1961 return (LONG)len;
1964 /*********************************************************************
1965 * EM_GETSEL message function
1967 static LONG EDIT_GetSelMsg(HWND hwnd)
1969 int so, eo;
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);
1987 UpdateWindow(hwnd);
1990 /*********************************************************************
1991 * EM_LINEFROMCHAR message function
1993 static LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam)
1995 int row, col;
1996 EDITSTATE *es = EDIT_GetEditState(hwnd);
1998 if (wParam == (WORD)-1)
1999 return (LONG)(es->SelBegLine);
2000 else
2001 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2003 return (LONG)row;
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)
2024 int row, col, len;
2025 int sbl, sbc, sel, sec;
2026 EDITSTATE *es = EDIT_GetEditState(hwnd);
2028 if (wParam == (WORD)-1)
2030 if (SelMarked(es))
2032 sbl = es->SelBegLine;
2033 sbc = es->SelBegCol;
2034 sel = es->SelEndLine;
2035 sec = es->SelEndCol;
2037 if (sbl > sel)
2039 SWAP_INT(sbl, sel);
2040 SWAP_INT(sbc, sec);
2042 if (sbl == sel && sbc > sec)
2043 SWAP_INT(sbc, sec);
2045 if (sbc == sel)
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;
2052 return len + sbc;
2054 else /* no selection marked */
2056 len = es->textptrs[es->CurrLine + 1] - es->textptrs[es->CurrLine] - 1;
2057 return len;
2060 else /* line number specified */
2062 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2063 len = es->textptrs[row + 1] - es->textptrs[row];
2064 return len;
2068 /*********************************************************************
2069 * EM_SETSEL message function
2071 static void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
2073 INT so, eo;
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);
2082 return;
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;
2090 if (!wParam)
2092 if (es->WndRow < 0 || es->WndRow > es->ClientHeight)
2094 es->wtop = es->CurrLine;
2095 es->WndRow = 0;
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;
2103 es->WndCol = 0;
2105 else if (es->WndCol < 0)
2107 es->wleft += es->WndCol;
2108 es->WndCol = 0;
2112 else /* otherwise set selection */
2114 if (eo >= 0 && so > eo) /* eo == -1 flag to extend to end of text */
2116 INT tmp;
2117 tmp = so;
2118 so = eo;
2119 eo = tmp;
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 */
2130 if (es->WndRow < 0)
2132 es->wtop = es->SelEndLine;
2133 es->WndRow = 0;
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;
2151 es->WndCol = 0;
2155 InvalidateRect(hwnd, NULL, TRUE);
2156 UpdateWindow(hwnd);
2160 /*********************************************************************
2161 * WM_SETFONT
2163 static void EDIT_WM_SetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
2165 HDC hdc;
2166 TEXTMETRIC tm;
2167 HFONT oldfont;
2168 EDITSTATE *es = EDIT_GetEditState(hwnd);
2170 es->hFont = (HANDLE)wParam;
2171 hdc = GetDC(hwnd);
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 /*********************************************************************
2190 * WM_PASTE
2192 static void EDIT_WM_Paste(HWND hwnd)
2194 HANDLE hClipMem;
2195 char *lpClipMem;
2197 OpenClipboard(hwnd);
2198 if (!(hClipMem = GetClipboardData(CF_TEXT)))
2200 /* no text in clipboard */
2201 CloseClipboard();
2202 return;
2204 lpClipMem = GlobalLock(hClipMem);
2205 EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem));
2206 GlobalUnlock(hClipMem);
2207 CloseClipboard();
2208 InvalidateRect(hwnd, NULL, TRUE);
2209 UpdateWindow(hwnd);
2212 /*********************************************************************
2213 * WM_PAINT
2215 static void EDIT_WM_Paint(HWND hwnd)
2217 PAINTSTRUCT ps;
2218 HDC hdc;
2219 int y;
2220 RECT rc;
2221 EDITSTATE *es = EDIT_GetEditState(hwnd);
2223 hdc = BeginPaint(hwnd, &ps);
2224 rc = ps.rcPaint;
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);
2229 if (es->PaintBkgd)
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 */
2244 #ifndef WINELIB
2245 INSTANCEDATA *ptr = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( ds, 0 );
2246 if (!ptr->heap) return 0;
2247 #endif
2248 return 1;
2251 /*********************************************************************
2252 * WM_NCCREATE
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);
2258 EDITSTATE *es;
2259 char *text = NULL;
2260 HANDLE ds;
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))
2281 DWORD globalSize;
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);
2306 es->wlines = 0;
2307 es->textwidth = 0;
2308 EDIT_ClearTextPointers(hwnd);
2309 if (IsMultiLine(hwnd)) strcpy(text, "\r\n");
2310 EDIT_BuildTextPointers(hwnd);
2312 else
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);
2321 if (es->hText)
2323 text = EDIT_HeapLock(hwnd, es->hText);
2324 if (text)
2326 strcpy(text, windowName);
2327 if(IsMultiLine(hwnd)) {
2328 strcat(text, "\r\n");
2330 *(text + es->textlen) = '\0';
2334 else
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';
2343 if (text)
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;
2362 return 1;
2365 /*********************************************************************
2366 * WM_CREATE
2368 static long EDIT_WM_Create(HWND hwnd, LONG lParam)
2370 HDC hdc;
2371 EDITSTATE *es = EDIT_GetEditState(hwnd);
2372 CLASS *classPtr;
2373 TEXTMETRIC tm;
2375 /* initialize state variable structure */
2376 hdc = GetDC(hwnd);
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;
2394 es->hFont = 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 */
2401 /* line filling */
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);
2417 return 0L;
2420 /*********************************************************************
2421 * WM_VSCROLL
2423 static void EDIT_WM_VScroll(HWND hwnd, WORD wParam, LONG lParam)
2425 EDITSTATE *es = EDIT_GetEditState(hwnd);
2427 if (IsMultiLine(hwnd))
2429 HideCaret(hwnd);
2431 switch (wParam)
2433 case SB_LINEUP:
2434 case SB_LINEDOWN:
2435 EDIT_VScrollLine(hwnd, wParam);
2436 break;
2438 case SB_PAGEUP:
2439 case SB_PAGEDOWN:
2440 EDIT_VScrollPage(hwnd, wParam);
2441 break;
2445 SetCaretPos(es->WndCol, es->WndRow);
2446 ShowCaret(hwnd);
2449 /*********************************************************************
2450 * WM_HSCROLL
2452 static void EDIT_WM_HScroll(HWND hwnd, WORD wParam, LONG lParam)
2454 EDITSTATE *es = EDIT_GetEditState(hwnd);
2456 switch (wParam)
2458 case SB_LINEUP:
2459 case SB_LINEDOWN:
2460 HideCaret(hwnd);
2462 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2463 ShowCaret(hwnd);
2464 break;
2468 /*********************************************************************
2469 * WM_SIZE
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;
2479 UpdateWindow(hwnd);
2482 /*********************************************************************
2483 * WM_LBUTTONDOWN
2485 static void EDIT_WM_LButtonDown(HWND hwnd, WORD wParam, LONG lParam)
2487 char *cp;
2488 int len;
2489 BOOL end = FALSE;
2490 EDITSTATE *es = EDIT_GetEditState(hwnd);
2492 if (SelMarked(es))
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;
2502 end = TRUE;
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;
2516 ButtonDown = TRUE;
2517 ButtonRow = es->CurrLine;
2518 ButtonCol = es->CurrCol;
2521 /*********************************************************************
2522 * WM_MOUSEMOVE
2524 static void EDIT_WM_MouseMove(HWND hwnd, WORD wParam, LONG lParam)
2526 EDITSTATE *es = EDIT_GetEditState(hwnd);
2528 if (wParam != MK_LBUTTON)
2529 return;
2531 HideCaret(hwnd);
2532 if (ButtonDown)
2534 EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
2535 TextMarking = TRUE;
2536 ButtonDown = FALSE;
2539 if (TextMarking)
2541 EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
2542 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2544 ShowCaret(hwnd);
2547 /*********************************************************************
2548 * WM_CHAR
2550 static void EDIT_WM_Char(HWND hwnd, WORD wParam)
2552 dprintf_edit(stddeb,"EDIT_WM_Char: wParam=%c\n", (char)wParam);
2554 switch (wParam)
2556 case '\r':
2557 case '\n':
2558 if (!IsMultiLine(hwnd))
2559 break;
2560 wParam = '\n';
2561 EDIT_KeyTyped(hwnd, wParam);
2562 break;
2564 case VK_TAB:
2565 if (!IsMultiLine(hwnd))
2566 break;
2567 EDIT_KeyTyped(hwnd, wParam);
2568 break;
2570 default:
2571 if (wParam >= 20 && wParam <= 254 && wParam != 127 )
2572 EDIT_KeyTyped(hwnd, wParam);
2573 break;
2577 /*********************************************************************
2578 * WM_KEYDOWN
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);
2586 HideCaret(hwnd);
2587 switch (wParam)
2589 case VK_UP:
2590 if (SelMarked(es))
2591 EDIT_ClearSel(hwnd);
2592 if (IsMultiLine(hwnd))
2593 EDIT_Upward(hwnd);
2594 else
2595 EDIT_Backward(hwnd);
2596 break;
2598 case VK_DOWN:
2599 if (SelMarked(es))
2600 EDIT_ClearSel(hwnd);
2601 if (IsMultiLine(hwnd))
2602 EDIT_Downward(hwnd);
2603 else
2604 EDIT_Forward(hwnd);
2605 break;
2607 case VK_RIGHT:
2608 if (SelMarked(es))
2609 EDIT_ClearSel(hwnd);
2610 EDIT_Forward(hwnd);
2611 break;
2613 case VK_LEFT:
2614 if (SelMarked(es))
2615 EDIT_ClearSel(hwnd);
2616 EDIT_Backward(hwnd);
2617 break;
2619 case VK_HOME:
2620 if (SelMarked(es))
2621 EDIT_ClearSel(hwnd);
2622 EDIT_Home(hwnd);
2623 break;
2625 case VK_END:
2626 if (SelMarked(es))
2627 EDIT_ClearSel(hwnd);
2628 EDIT_End(hwnd);
2629 break;
2631 case VK_PRIOR:
2632 if (IsMultiLine(hwnd))
2634 if (SelMarked(es))
2635 EDIT_ClearSel(hwnd);
2636 EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
2638 break;
2640 case VK_NEXT:
2641 if (IsMultiLine(hwnd))
2643 if (SelMarked(es))
2644 EDIT_ClearSel(hwnd);
2645 EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
2647 break;
2649 case VK_BACK:
2650 if (SelMarked(es))
2651 EDIT_DeleteSel(hwnd);
2652 else
2654 if (es->CurrCol == 0 && es->CurrLine == 0)
2655 break;
2656 EDIT_Backward(hwnd);
2657 EDIT_DelKey(hwnd);
2659 break;
2661 case VK_DELETE:
2662 if (SelMarked(es))
2663 EDIT_DeleteSel(hwnd);
2664 else
2665 EDIT_DelKey(hwnd);
2666 break;
2669 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2670 ShowCaret(hwnd);
2673 /*********************************************************************
2674 * WM_SETTEXT
2676 static LONG EDIT_WM_SetText(HWND hwnd, LONG lParam)
2678 int len;
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);
2688 es->textlen = len;
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);
2692 if (lParam)
2693 strcpy(text, (char *)PTR_SEG_TO_LIN(lParam));
2694 text[len] = '\0';
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;
2701 return 0;
2703 else
2704 return EN_ERRSPACE;
2707 /*********************************************************************
2708 * EditWndProc()
2710 LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2712 LONG lResult = 0;
2713 char *textPtr;
2714 int len;
2715 EDITSTATE *es = EDIT_GetEditState(hwnd);
2717 switch (uMsg) {
2718 case EM_CANUNDO:
2719 lResult = (LONG)es->hDeletedText;
2720 break;
2722 case EM_EMPTYUNDOBUFFER:
2723 EDIT_ClearDeletedText(hwnd);
2724 break;
2726 case EM_FMTLINES:
2727 fprintf(stdnimp,"edit: EM_FMTLINES message received\n");
2728 if (!wParam)
2729 lResult = 1L;
2730 else
2731 lResult = 0L;
2732 break;
2734 case EM_GETFIRSTVISIBLELINE:
2735 lResult = es->wtop;
2736 break;
2738 case EM_GETHANDLE:
2739 lResult = (LONG)es->hText;
2740 break;
2742 case EM_GETLINE:
2743 if (IsMultiLine(hwnd))
2744 lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
2745 else
2746 lResult = 0L;
2747 break;
2749 case EM_GETLINECOUNT:
2750 if (IsMultiLine(hwnd))
2751 lResult = es->wlines;
2752 else
2753 lResult = 0L;
2754 break;
2756 case EM_GETMODIFY:
2757 lResult = es->TextChanged;
2758 break;
2760 case EM_GETPASSWORDCHAR:
2761 fprintf(stdnimp,"edit: cannot process EM_GETPASSWORDCHAR message\n");
2762 break;
2764 case EM_GETRECT:
2765 GetWindowRect(hwnd, (LPRECT)PTR_SEG_TO_LIN(lParam));
2766 break;
2768 case EM_GETSEL:
2769 lResult = EDIT_GetSelMsg(hwnd);
2770 break;
2772 case EM_GETWORDBREAKPROC:
2773 fprintf(stdnimp,"edit: cannot process EM_GETWORDBREAKPROC message\n");
2774 break;
2776 case EM_LIMITTEXT:
2777 if (wParam)
2778 es->MaxTextLen = wParam;
2779 else if (IsMultiLine(hwnd))
2780 es->MaxTextLen = 65535;
2781 else
2782 es->MaxTextLen = 32767;
2783 break;
2785 case EM_LINEFROMCHAR:
2786 lResult = EDIT_LineFromCharMsg(hwnd, wParam);
2787 break;
2789 case EM_LINEINDEX:
2790 if (IsMultiLine(hwnd))
2791 lResult = EDIT_LineIndexMsg(hwnd, wParam);
2792 else
2793 lResult = 0L;
2794 break;
2796 case EM_LINELENGTH:
2797 lResult = EDIT_LineLengthMsg(hwnd, wParam);
2798 break;
2800 case EM_LINESCROLL:
2801 fprintf(stdnimp,"edit: cannot process EM_LINESCROLL message\n");
2802 break;
2804 case EM_REPLACESEL:
2805 HideCaret(hwnd);
2806 EDIT_ReplaceSel(hwnd, lParam);
2807 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2808 ShowCaret(hwnd);
2809 break;
2811 case EM_SETHANDLE:
2812 HideCaret(hwnd);
2813 EDIT_SetHandleMsg(hwnd, wParam);
2814 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2815 ShowCaret(hwnd);
2816 break;
2818 case EM_SETMODIFY:
2819 es->TextChanged = wParam;
2820 break;
2822 case EM_SETPASSWORDCHAR:
2823 fprintf(stdnimp,"edit: cannot process EM_SETPASSWORDCHAR message\n");
2824 break;
2826 case EM_SETREADONLY:
2827 fprintf(stdnimp,"edit: cannot process EM_SETREADONLY message\n");
2828 break;
2830 case EM_SETRECT:
2831 case EM_SETRECTNP:
2832 fprintf(stdnimp,"edit: cannot process EM_SETRECT(NP) message\n");
2833 break;
2835 case EM_SETSEL:
2836 HideCaret(hwnd);
2837 EDIT_SetSelMsg(hwnd, wParam, lParam);
2838 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2839 ShowCaret(hwnd);
2840 break;
2842 case EM_SETTABSTOPS:
2843 lResult = EDIT_SetTabStopsMsg(hwnd, wParam, lParam);
2844 break;
2846 case EM_SETWORDBREAKPROC:
2847 fprintf(stdnimp,"edit: cannot process EM_SETWORDBREAKPROC message\n");
2848 break;
2850 case EM_UNDO:
2851 HideCaret(hwnd);
2852 lResult = EDIT_UndoMsg(hwnd);
2853 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2854 ShowCaret(hwnd);
2855 break;
2857 case WM_GETDLGCODE:
2858 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
2860 case WM_CHAR:
2861 EDIT_WM_Char(hwnd, wParam);
2862 break;
2864 case WM_COPY:
2865 EDIT_CopyToClipboard(hwnd);
2866 EDIT_ClearSel(hwnd);
2867 break;
2869 case WM_CREATE:
2870 lResult = EDIT_WM_Create(hwnd, lParam);
2871 break;
2873 case WM_CUT:
2874 EDIT_CopyToClipboard(hwnd);
2875 EDIT_DeleteSel(hwnd);
2876 break;
2878 case WM_DESTROY:
2879 free(es->textptrs);
2880 free(es->CharWidths);
2881 free(es->TabStops);
2882 free(es->BlankLine);
2883 EDIT_HeapFree(hwnd, es->hText);
2884 free( EDIT_GetEditState(hwnd) );
2885 break;
2887 case WM_ENABLE:
2888 InvalidateRect(hwnd, NULL, FALSE);
2889 break;
2891 case WM_GETTEXT:
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 ;
2899 else
2900 lResult = 0L;
2901 EDIT_HeapUnlock(hwnd, es->hText);
2902 break;
2904 case WM_GETTEXTLENGTH:
2905 textPtr = EDIT_HeapLock(hwnd, es->hText);
2906 lResult = (DWORD)strlen(textPtr);
2907 EDIT_HeapUnlock(hwnd, es->hText);
2908 break;
2910 case WM_HSCROLL:
2911 EDIT_WM_HScroll(hwnd, wParam, lParam);
2912 break;
2914 case WM_KEYDOWN:
2915 EDIT_WM_KeyDown(hwnd, wParam);
2916 break;
2918 case WM_KILLFOCUS:
2919 es->HaveFocus = FALSE;
2920 DestroyCaret();
2921 if (SelMarked(es)) EDIT_ClearSel(hwnd);
2922 NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
2923 break;
2925 case WM_LBUTTONDOWN:
2926 HideCaret(hwnd);
2927 SetFocus(hwnd);
2928 SetCapture(hwnd);
2929 EDIT_WM_LButtonDown(hwnd, wParam, lParam);
2930 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2931 ShowCaret(hwnd);
2932 break;
2934 case WM_LBUTTONUP:
2935 if (GetCapture() != hwnd) break;
2936 ReleaseCapture();
2937 ButtonDown = FALSE;
2938 if (TextMarking)
2939 EDIT_StopMarking(hwnd);
2940 break;
2942 case WM_MOUSEMOVE:
2943 if (es->HaveFocus)
2944 EDIT_WM_MouseMove(hwnd, wParam, lParam);
2945 break;
2947 case WM_MOVE:
2948 lResult = 0;
2949 break;
2951 case WM_NCCREATE:
2952 lResult = EDIT_WM_NCCreate(hwnd, lParam);
2953 break;
2955 case WM_PAINT:
2956 EDIT_WM_Paint(hwnd);
2957 break;
2959 case WM_PASTE:
2960 EDIT_WM_Paste(hwnd);
2961 break;
2963 case WM_SETFOCUS:
2964 es->HaveFocus = TRUE;
2965 CreateCaret(hwnd, 0, 2, es->txtht);
2966 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2967 ShowCaret(hwnd);
2968 NOTIFY_PARENT(hwnd, EN_SETFOCUS);
2969 break;
2971 case WM_SETFONT:
2972 HideCaret(hwnd);
2973 EDIT_WM_SetFont(hwnd, wParam, lParam);
2974 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2975 ShowCaret(hwnd);
2976 break;
2977 #if 0
2978 case WM_SETREDRAW:
2979 dprintf_edit(stddeb, "WM_SETREDRAW: hwnd=%d, wParam=%x\n",
2980 hwnd, wParam);
2981 lResult = 0;
2982 break;
2983 #endif
2984 case WM_SETTEXT:
2985 EDIT_WM_SetText(hwnd, lParam);
2986 break;
2988 case WM_SIZE:
2989 EDIT_WM_Size(hwnd, wParam, lParam);
2990 lResult = 0;
2991 break;
2993 case WM_VSCROLL:
2994 EDIT_WM_VScroll(hwnd, wParam, lParam);
2995 break;
2997 default:
2998 lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
2999 break;
3002 return lResult;