Release 940518
[wine/multimedia.git] / controls / edit.c
blob552824726e477a23b4656936b4c22b2fe345432e
1 /*
2 * Edit control
4 * Copyright David W. Metcalfe, 1994
6 * Release 1, April 1994
7 */
9 static char Copyright[] = "Copyright David W. Metcalfe, 1994";
11 #include <stdlib.h>
12 #include <string.h>
13 #include <windows.h>
14 #include "win.h"
15 #include "class.h"
16 #include "user.h"
19 #define DEBUG_EDIT
22 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
23 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
24 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
26 #define MAXTEXTLEN 32000 /* maximum text buffer length */
27 #define EDITLEN 1024 /* starting length for multi-line control */
28 #define ENTRYLEN 256 /* starting length for single line control */
29 #define GROWLENGTH 64 /* buffers grow by this much */
31 #define HSCROLLDIM (ClientWidth(wndPtr) / 3)
32 /* "line" dimension for horizontal scroll */
34 #define EDIT_HEAP_ALLOC(size) USER_HEAP_ALLOC(GMEM_MOVEABLE,size)
35 #define EDIT_HEAP_REALLOC(handle,size) USER_HEAP_REALLOC(handle,size,\
36 GMEM_MOVEABLE)
37 #define EDIT_HEAP_ADDR(handle) USER_HEAP_ADDR(handle)
38 #define EDIT_HEAP_FREE(handle) USER_HEAP_FREE(handle)
40 typedef struct
42 int wlines; /* number of lines of text */
43 int wtop; /* top line that is displayed */
44 int wleft; /* left pixel that is displayed */
45 unsigned int textlen; /* text buffer length */
46 int textwidth; /* width of longest line in pixels */
47 RECT fmtrc; /* rectangle in which to format text */
48 int txtht; /* height of text line in pixels */
49 HANDLE hText; /* handle to text buffer */
50 HANDLE hCharWidths; /* widths of chars in font */
51 HANDLE hTextPtrs; /* list of line offsets */
52 HANDLE hBlankLine; /* to fill blank lines quickly */
53 int CurrCol; /* current column */
54 int CurrLine; /* current line */
55 int WndCol; /* current window column */
56 int WndRow; /* current window row */
57 BOOL TextChanged; /* TRUE if text has changed */
58 BOOL PaintBkgd; /* paint control background */
59 unsigned int MaxTextLen; /* maximum text buffer length */
60 int SelBegLine; /* beginning line of selection */
61 int SelBegCol; /* beginning column of selection */
62 int SelEndLine; /* ending line of selection */
63 int SelEndCol; /* ending column of selection */
64 } EDITSTATE;
67 #define ClientWidth(wndPtr) (wndPtr->rectClient.right - \
68 wndPtr->rectClient.left)
69 #define ClientHeight(wndPtr, es) ((wndPtr->rectClient.bottom - \
70 wndPtr->rectClient.top) / es->txtht)
71 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
72 ? EDITLEN : ENTRYLEN)
73 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
74 #define SelMarked(es) (es->SelBegLine != -1 && es->SelBegCol != -1 && \
75 es->SelEndLine != -1 && es->SelEndCol != -1)
77 /* macros to access window styles */
78 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
79 #define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
80 #define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
81 #define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
82 #define IsHScrollBar() (wndPtr->dwStyle & WS_HSCROLL)
84 /* internal variables */
85 static BOOL TextMarking; /* TRUE if text marking in progress */
86 static BOOL ButtonDown; /* TRUE if left mouse button down */
87 static int ButtonRow; /* row in text buffer when button pressed */
88 static int ButtonCol; /* col in text buffer when button pressed */
89 static BOOL Print = FALSE;
92 LONG EditWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
93 long EDIT_CreateMsg(HWND hwnd, LONG lParam);
94 void EDIT_ClearTextPointers(HWND hwnd);
95 void EDIT_BuildTextPointers(HWND hwnd);
96 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var);
97 void EDIT_PaintMsg(HWND hwnd);
98 HANDLE EDIT_GetTextLine(HWND hwnd, int selection);
99 char *EDIT_TextLine(HWND hwnd, int sel);
100 int EDIT_LineLength(EDITSTATE *es, char *str, int len);
101 void EDIT_WriteTextLine(HWND hwnd, RECT *rc, int y);
102 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
103 int col, RECT *rc, BOOL blank, BOOL reverse);
104 HANDLE EDIT_GetStr(EDITSTATE *es, char *lp, int off, int len, int *diff);
105 void EDIT_CharMsg(HWND hwnd, WORD wParam);
106 void EDIT_KeyTyped(HWND hwnd, short ch);
107 int EDIT_CharWidth(EDITSTATE *es, short ch);
108 void EDIT_Forward(HWND hwnd);
109 void EDIT_Downward(HWND hwnd);
110 void EDIT_Upward(HWND hwnd);
111 void EDIT_Backward(HWND hwnd);
112 void EDIT_End(HWND hwnd);
113 void EDIT_Home(HWND hwnd);
114 void EDIT_StickEnd(HWND hwnd);
115 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam);
116 void EDIT_KeyHScroll(HWND hwnd, WORD opt);
117 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt);
118 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt);
119 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt);
120 int EDIT_ComputeVScrollPos(HWND hwnd);
121 int EDIT_ComputeHScrollPos(HWND hwnd);
122 void EDIT_DelKey(HWND hwnd);
123 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
124 void EDIT_VScrollLine(HWND hwnd, WORD opt);
125 void EDIT_VScrollPage(HWND hwnd, WORD opt);
126 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
127 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam);
128 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam);
129 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam);
130 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel);
131 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam);
132 void EDIT_ClearText(HWND hwnd);
133 void EDIT_SetSelMsg(HWND hwnd, LONG lParam);
134 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col);
135 void EDIT_DeleteSel(HWND hwnd);
136 void EDIT_ClearSel(HWND hwnd);
137 int EDIT_TextLineNumber(HWND hwnd, char *lp);
138 void EDIT_SetAnchor(HWND hwnd, int row, int col);
139 void EDIT_ExtendSel(HWND hwnd, int x, int y);
140 void EDIT_StopMarking(HWND hwnd);
141 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
142 LONG EDIT_GetSelMsg(HWND hwnd);
143 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam);
144 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam);
145 void swap(int *a, int *b);
148 LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
150 LONG lResult = 0L;
151 HDC hdc;
152 char *textPtr;
153 int len;
154 WND *wndPtr = WIN_FindWndPtr(hwnd);
155 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
157 switch (uMsg) {
158 case EM_CANUNDO:
159 /* cannot process undo message */
160 lResult = 0L;
161 break;
163 case EM_FMTLINES:
164 printf("edit: cannot process EM_FMTLINES message\n");
165 lResult = 0L;
166 break;
168 case EM_GETFIRSTVISIBLELINE:
169 lResult = es->wtop;
170 break;
172 case EM_GETHANDLE:
173 printf("edit: cannot process EM_GETHANDLE message\n");
174 break;
176 case EM_GETLINE:
177 if (IsMultiLine())
178 lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
179 else
180 lResult = 0L;
181 break;
183 case EM_GETLINECOUNT:
184 if (IsMultiLine())
185 lResult = es->wlines;
186 else
187 lResult = 0L;
188 break;
190 case EM_GETMODIFY:
191 lResult = es->TextChanged;
192 break;
194 case EM_GETPASSWORDCHAR:
195 printf("edit: cannot process EM_GETPASSWORDCHAR message\n");
196 break;
198 case EM_GETRECT:
199 GetWindowRect(hwnd, (LPRECT)lParam);
200 break;
202 case EM_GETSEL:
203 lResult = EDIT_GetSelMsg(hwnd);
204 break;
206 case EM_GETWORDBREAKPROC:
207 printf("edit: cannot process EM_GETWORDBREAKPROC message\n");
208 break;
210 case EM_LIMITTEXT:
211 es->MaxTextLen = wParam;
212 break;
214 case EM_LINEFROMCHAR:
215 lResult = EDIT_LineFromCharMsg(hwnd, wParam);
216 break;
218 case EM_LINEINDEX:
219 if (IsMultiLine())
220 lResult = EDIT_LineIndexMsg(hwnd, wParam);
221 else
222 lResult = 0L;
223 break;
225 case EM_LINELENGTH:
226 printf("edit: cannot process EM_LINELENGTH message\n");
227 break;
229 case EM_LINESCROLL:
230 printf("edit: cannot process EM_LINESCROLL message\n");
231 break;
233 case EM_REPLACESEL:
234 printf("edit: cannot process EM_REPLACESEL message\n");
235 break;
237 case EM_SETHANDLE:
238 printf("edit: cannot process EM_SETHANDLE message\n");
239 break;
241 case EM_SETMODIFY:
242 es->TextChanged = wParam;
243 break;
245 case EM_SETPASSWORDCHAR:
246 printf("edit: cannot process EM_SETPASSWORDCHAR message\n");
247 break;
249 case EM_SETREADONLY:
250 printf("edit: cannot process EM_SETREADONLY message\n");
251 break;
253 case EM_SETRECT:
254 case EM_SETRECTNP:
255 printf("edit: cannot process EM_SETRECT(NP) message\n");
256 break;
258 case EM_SETSEL:
259 HideCaret(hwnd);
260 EDIT_SetSelMsg(hwnd, lParam);
261 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
262 ShowCaret(hwnd);
263 break;
265 case EM_SETTABSTOPS:
266 printf("edit: cannot process EM_SETTABSTOPS message\n");
267 break;
269 case EM_SETWORDBREAKPROC:
270 printf("edit: cannot process EM_SETWORDBREAKPROC message\n");
271 break;
273 case WM_CHAR:
274 EDIT_CharMsg(hwnd, wParam);
275 break;
277 case WM_CREATE:
278 lResult = EDIT_CreateMsg(hwnd, lParam);
279 break;
281 case WM_DESTROY:
282 EDIT_HEAP_FREE(es->hTextPtrs);
283 EDIT_HEAP_FREE(es->hCharWidths);
284 EDIT_HEAP_FREE((HANDLE)(*(wndPtr->wExtra)));
285 break;
287 case WM_ENABLE:
288 InvalidateRect(hwnd, NULL, FALSE);
289 break;
291 case WM_GETTEXT:
292 textPtr = (LPSTR)EDIT_HEAP_ADDR(es->hText);
293 if ((int)wParam > (len = strlen(textPtr)))
295 strcpy((char *)lParam, textPtr);
296 lResult = (DWORD)len;
298 else
299 lResult = 0L;
300 break;
302 case WM_GETTEXTLENGTH:
303 textPtr = (LPSTR)EDIT_HEAP_ADDR(es->hText);
304 lResult = (DWORD)strlen(textPtr);
305 break;
307 case WM_HSCROLL:
308 EDIT_HScrollMsg(hwnd, wParam, lParam);
309 break;
311 case WM_KEYDOWN:
312 printf("EDIT WM_KEYDOWN w=%04X !\n", wParam);
313 EDIT_KeyDownMsg(hwnd, wParam);
314 break;
316 case WM_KILLFOCUS:
317 DestroyCaret();
318 NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
319 break;
321 case WM_LBUTTONDOWN:
322 HideCaret(hwnd);
323 SetFocus(hwnd);
324 EDIT_LButtonDownMsg(hwnd, wParam, lParam);
325 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
326 ShowCaret(hwnd);
327 break;
329 case WM_LBUTTONUP:
330 ButtonDown = FALSE;
331 if (TextMarking)
332 EDIT_StopMarking(hwnd);
333 break;
335 case WM_MOUSEMOVE:
336 HideCaret(hwnd);
337 EDIT_MouseMoveMsg(hwnd, wParam, lParam);
338 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
339 ShowCaret(hwnd);
340 break;
342 case WM_MOVE:
343 lResult = 0;
344 break;
346 case WM_PAINT:
347 EDIT_PaintMsg(hwnd);
348 break;
350 case WM_SETFOCUS:
351 es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
352 CreateCaret(hwnd, 0, 2, es->txtht);
353 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
354 ShowCaret(hwnd);
355 NOTIFY_PARENT(hwnd, EN_SETFOCUS);
356 break;
358 case WM_SETFONT:
359 break;
361 case WM_SETTEXT:
362 EDIT_SetTextMsg(hwnd, lParam);
363 break;
365 case WM_SIZE:
366 EDIT_SizeMsg(hwnd, wParam, lParam);
367 lResult = 0;
368 break;
370 case WM_VSCROLL:
371 EDIT_VScrollMsg(hwnd, wParam, lParam);
372 break;
374 default:
375 lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
376 break;
379 GlobalUnlock(hwnd);
380 return lResult;
384 /*********************************************************************
385 * WM_CREATE message function
388 long EDIT_CreateMsg(HWND hwnd, LONG lParam)
390 HDC hdc;
391 WND *wndPtr = WIN_FindWndPtr(hwnd);
392 EDITSTATE *es;
393 CLASS *classPtr;
394 short *charWidths;
395 TEXTMETRIC tm;
396 char *text;
397 unsigned int *textPtrs;
399 /* allocate space for state variable structure */
400 (HANDLE)(*(wndPtr->wExtra)) =
401 EDIT_HEAP_ALLOC(sizeof(EDITSTATE));
402 es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
403 es->hTextPtrs = EDIT_HEAP_ALLOC(sizeof(int));
404 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
405 es->hCharWidths = EDIT_HEAP_ALLOC(256 * sizeof(short));
407 /* initialize state variable structure */
408 /* --- char width array */
409 hdc = GetDC(hwnd);
410 charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
411 memset(charWidths, 0, 256 * sizeof(short));
412 GetCharWidth(hdc, 0, 255, charWidths);
414 /* --- text buffer */
415 es->MaxTextLen = MAXTEXTLEN + 1;
416 if (!(wndPtr->hText))
418 es->textlen = EditBufLen(wndPtr);
419 es->hText = EDIT_HEAP_ALLOC(EditBufLen(wndPtr) + 2);
420 text = (LPSTR)EDIT_HEAP_ADDR(es->hText);
421 memset(text, 0, es->textlen + 2);
422 EDIT_ClearTextPointers(hwnd);
424 else
426 es->hText = wndPtr->hText;
427 wndPtr->hText = 0;
428 es->textlen = GetWindowTextLength(hwnd) + 1;
429 EDIT_BuildTextPointers(hwnd);
432 /* --- other structure variables */
433 GetTextMetrics(hdc, &tm);
434 es->txtht = tm.tmHeight + tm.tmExternalLeading;
435 es->wlines = 0;
436 es->wtop = es->wleft = 0;
437 es->CurrCol = es->CurrLine = 0;
438 es->WndCol = es->WndRow = 0;
439 es->TextChanged = FALSE;
440 es->textwidth = 0;
441 es->SelBegLine = es->SelBegCol = -1;
442 es->SelEndLine = es->SelEndCol = -1;
444 /* allocate space for a line full of blanks to speed up */
445 /* line filling */
446 es->hBlankLine = EDIT_HEAP_ALLOC((ClientWidth(wndPtr) /
447 charWidths[32]) + 2);
448 text = EDIT_HEAP_ADDR(es->hBlankLine);
449 memset(text, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
451 /* set up text cursor for edit class */
452 CLASS_FindClassByName("EDIT", &classPtr);
453 classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);
455 /* paint background on first WM_PAINT */
456 es->PaintBkgd = TRUE;
458 ReleaseDC(hwnd, hdc);
459 return 0L;
463 /*********************************************************************
464 * EDIT_ClearTextPointers
466 * Clear and initialize text line pointer array.
469 void EDIT_ClearTextPointers(HWND hwnd)
471 unsigned int *textPtrs;
472 WND *wndPtr = WIN_FindWndPtr(hwnd);
473 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
475 es->hTextPtrs = EDIT_HEAP_REALLOC(es->hTextPtrs, sizeof(int));
476 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
477 *textPtrs = 0;
481 /*********************************************************************
482 * EDIT_BuildTextPointers
484 * Build array of pointers to text lines.
487 #define INITLINES 100
489 void EDIT_BuildTextPointers(HWND hwnd)
491 WND *wndPtr = WIN_FindWndPtr(hwnd);
492 char *text, *cp;
493 int incrs = INITLINES;
494 unsigned int off, len, temp;
495 EDITSTATE *es;
496 unsigned int *textPtrs;
497 short *charWidths;
499 es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
500 text = (char *)EDIT_HEAP_ADDR(es->hText);
501 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
502 charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
504 es->textwidth = es->wlines = 0;
505 cp = text;
507 /* advance through text buffer */
508 while (*cp)
510 /* increase size of text pointer array */
511 if (incrs == INITLINES)
513 incrs = 0;
514 es->hTextPtrs = EDIT_HEAP_REALLOC(es->hTextPtrs,
515 (es->wlines + INITLINES) * sizeof(int));
516 textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
518 off = (unsigned int)(cp - text); /* offset of beginning of line */
519 *(textPtrs + es->wlines) = off;
520 es->wlines++;
521 incrs++;
522 len = 0;
524 /* advance through current line */
525 while (*cp && *cp != '\n')
527 len += charWidths[*cp]; /* width of line in pixels */
528 cp++;
530 es->textwidth = max(es->textwidth, len);
531 if (*cp)
532 cp++; /* skip '\n' */
534 off = (unsigned int)(cp - text); /* offset of beginning of line */
535 *(textPtrs + es->wlines) = off;
539 /*********************************************************************
540 * EDIT_ModTextPointers
542 * Modify text pointers from a specified position.
545 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
547 WND *wndPtr = WIN_FindWndPtr(hwnd);
548 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
549 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
551 while (lineno < es->wlines)
552 *(textPtrs + lineno++) += var;
556 /*********************************************************************
557 * WM_PAINT message function
560 void EDIT_PaintMsg(HWND hwnd)
562 PAINTSTRUCT ps;
563 HDC hdc;
564 int y;
565 RECT rc;
566 WND *wndPtr = WIN_FindWndPtr(hwnd);
567 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
569 hdc = BeginPaint(hwnd, &ps);
570 rc = ps.rcPaint;
572 #ifdef DEBUG_EDIT
573 printf("WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc.left, rc.top,
574 rc.right, rc.bottom);
575 #endif
577 if (es->PaintBkgd)
578 FillWindow(GetParent(hwnd), hwnd, hdc, CTLCOLOR_EDIT);
580 for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
582 if (y < es->wlines - es->wtop)
583 EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
586 EndPaint(hwnd, &ps);
590 /*********************************************************************
591 * EDIT_GetTextLine
593 * Get a copy of the text in the specified line.
596 HANDLE EDIT_GetTextLine(HWND hwnd, int selection)
598 char *line;
599 HANDLE hLine;
600 int len = 0;
601 char *cp, *cp1;
603 #ifdef DEBUG_EDIT
604 printf("GetTextLine %d\n", selection);
605 #endif
606 cp = cp1 = EDIT_TextLine(hwnd, selection);
607 /* advance through line */
608 while (*cp && *cp != '\n')
610 len++;
611 cp++;
614 /* store selected line and return handle */
615 hLine = EDIT_HEAP_ALLOC(len + 6);
616 line = (char *)EDIT_HEAP_ADDR(hLine);
617 memmove(line, cp1, len);
618 line[len] = '\0';
619 return hLine;
623 /*********************************************************************
624 * EDIT_TextLine
626 * Return a pointer to the text in the specified line.
629 char *EDIT_TextLine(HWND hwnd, int sel)
631 WND *wndPtr = WIN_FindWndPtr(hwnd);
632 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
633 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
634 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
636 return (text + *(textPtrs + sel));
640 /*********************************************************************
641 * EDIT_LineLength
643 * Return length of line _str_ of length _len_ characters in pixels.
646 int EDIT_LineLength(EDITSTATE *es, char *str, int len)
648 int i, plen = 0;
649 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
651 for (i = 0; i < len; i++)
652 plen += charWidths[*(str + i)];
654 #ifdef DEBUG_EDIT
655 printf("EDIT_LineLength: returning %d\n", plen);
656 #endif
657 return plen;
661 /*********************************************************************
662 * EDIT_WriteTextLine
664 * Write the line of text at offset _y_ in text buffer to a window.
667 void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
669 int len = 0;
670 unsigned char line[200];
671 HANDLE hLine;
672 unsigned char *lp;
673 int lnlen, lnlen1;
674 int col, off = 0;
675 int sbl, sel, sbc, sec;
676 RECT rc;
677 div_t num;
678 BOOL trunc = FALSE;
679 WND *wndPtr = WIN_FindWndPtr(hwnd);
680 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
682 /* initialize rectangle if NULL, else copy */
683 if (rect)
684 CopyRect(&rc, rect);
685 else
686 GetClientRect(hwnd, &rc);
688 #ifdef DEBUG_EDIT
689 printf("WriteTextLine %d\n", y);
690 #endif
692 /* make sure y is inside the window */
693 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
695 #ifdef DEBUG_EDIT
696 printf("EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
697 #endif
698 return;
701 /* make sure rectangle is within window */
702 if (rc.left >= ClientWidth(wndPtr) - 1)
704 #ifdef DEBUG_EDIT
705 printf("EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
706 rc.left);
707 #endif
708 return;
710 if (rc.right <= 0)
712 #ifdef DEBUG_EDIT
713 printf("EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
714 rc.right);
715 #endif
716 return;
718 if (y - es->wtop < (rc.top / es->txtht) ||
719 y - es->wtop > (rc.bottom / es->txtht))
721 #ifdef DEBUG_EDIT
722 printf("EDIT_WriteTextLine: y (%d) is outside window\n", y);
723 #endif
724 return;
727 /* get the text and length of line */
728 if ((hLine = EDIT_GetTextLine(hwnd, y)) == 0)
729 return;
730 lp = (unsigned char *)EDIT_HEAP_ADDR(hLine);
731 lnlen = EDIT_LineLength(es, lp, strlen(lp));
732 lnlen1 = lnlen;
734 /* build the line to display */
735 if (lnlen < es->wleft)
736 lnlen = 0;
737 else
738 off += es->wleft;
740 if (lnlen > rc.left)
742 off += rc.left;
743 lnlen = lnlen1 - off;
744 len = min(lnlen, rc.right - rc.left);
747 if (SelMarked(es))
749 sbl = es->SelBegLine;
750 sel = es->SelEndLine;
751 sbc = es->SelBegCol;
752 sec = es->SelEndCol;
754 /* put lowest marker first */
755 if (sbl > sel)
757 swap(&sbl, &sel);
758 swap(&sbc, &sec);
760 if (sbl == sel && sbc > sec)
761 swap(&sbc, &sec);
763 if (y < sbl || y > sel)
764 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
765 TRUE, FALSE);
766 else if (y > sbl && y < sel)
767 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
768 TRUE, TRUE);
769 else if (y == sbl)
771 col = EDIT_LineLength(es, lp, sbc);
772 if (col > (es->wleft + rc.left))
774 len = min(col - off, rc.right - off);
775 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
776 rc.left, &rc, FALSE, FALSE);
777 off = col;
779 if (y == sel)
781 col = EDIT_LineLength(es, lp, sec);
782 if (col < (es->wleft + rc.right))
784 len = min(col - off, rc.right - off);
785 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
786 off - es->wleft, &rc, FALSE, TRUE);
787 off = col;
788 len = min(lnlen - off, rc.right - off);
789 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
790 off - es->wleft, &rc, TRUE, FALSE);
792 else
794 len = min(lnlen - off, rc.right - off);
795 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
796 off - es->wleft, &rc, TRUE, TRUE);
799 else
801 len = min(lnlen - off, rc.right - off);
802 if (col < (es->wleft + rc.right))
803 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
804 off - es->wleft, &rc, TRUE, TRUE);
807 else if (y == sel)
809 col = EDIT_LineLength(es, lp, sec);
810 if (col < (es->wleft + rc.right))
812 len = min(col - off, rc.right - off);
813 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
814 off - es->wleft, &rc, FALSE, TRUE);
815 off = col;
816 len = min(lnlen - off, rc.right - off);
817 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
818 off - es->wleft, &rc, TRUE, FALSE);
822 else
823 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
824 TRUE, FALSE);
826 EDIT_HEAP_FREE(hLine);
830 /*********************************************************************
831 * EDIT_WriteText
833 * Write text to a window
834 * lp - text line
835 * off - offset in text line (in pixels)
836 * len - length from off (in pixels)
837 * row - line in window
838 * col - column in window
839 * rc - rectangle in which to display line
840 * blank - blank remainder of line?
841 * reverse - reverse color of line?
844 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
845 int col, RECT *rc, BOOL blank, BOOL reverse)
847 HDC hdc;
848 HANDLE hStr;
849 char *str, *blanks;
850 int diff, num_spaces;
851 HRGN hrgnClip;
852 COLORREF oldTextColor, oldBkgdColor;
853 WND *wndPtr = WIN_FindWndPtr(hwnd);
854 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
855 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
857 #ifdef DEBUG_EDIT
858 printf("EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
859 #endif
861 hdc = GetDC(hwnd);
862 hStr = EDIT_GetStr(es, lp, off, len, &diff);
863 str = (char *)EDIT_HEAP_ADDR(hStr);
864 hrgnClip = CreateRectRgnIndirect(rc);
865 SelectClipRgn(hdc, hrgnClip);
867 SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
868 MAKELPARAM(hwnd, CTLCOLOR_EDIT));
870 if (reverse)
872 oldBkgdColor = GetBkColor(hdc);
873 oldTextColor = GetTextColor(hdc);
874 SetBkColor(hdc, oldTextColor);
875 SetTextColor(hdc, oldBkgdColor);
878 TextOut(hdc, col - diff, row * es->txtht, str, strlen(str));
880 if (reverse)
882 SetBkColor(hdc, oldBkgdColor);
883 SetTextColor(hdc, oldTextColor);
886 /* blank out remainder of line if appropriate */
887 if (blank)
889 if ((rc->right - col) > len)
891 blanks = EDIT_HEAP_ADDR(es->hBlankLine);
892 num_spaces = (rc->right - col - len) / charWidths[32];
893 TextOut(hdc, col + len, row * es->txtht, blanks, num_spaces);
897 EDIT_HEAP_FREE(hStr);
898 ReleaseDC(hwnd, hdc);
902 /*********************************************************************
903 * EDIT_GetStr
905 * Return sub-string starting at pixel _off_ of length _len_ pixels.
906 * If _off_ is part way through a character, the negative offset of
907 * the beginning of the character is returned in _diff_, else _diff_
908 * will be zero.
911 HANDLE EDIT_GetStr(EDITSTATE *es, char *lp, int off, int len, int *diff)
913 HANDLE hStr;
914 char *str;
915 int ch = 0, i = 0, j, tmp;
916 int ch1;
917 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
919 #ifdef DEBUG_EDIT
920 printf("EDIT_GetStr %s %d %d\n", lp, off, len);
921 #endif
923 while (i < off)
925 i += charWidths[*(lp + ch)];
926 ch++;
929 /* if stepped past _off_, go back a character */
930 if (i - off)
931 i -= charWidths[*(lp + --ch)];
932 *diff = off - i;
933 ch1 = ch;
935 while (i < len + off)
937 i += charWidths[*(lp + ch)];
938 ch++;
941 hStr = EDIT_HEAP_ALLOC(ch - ch1 + 3);
942 str = (char *)EDIT_HEAP_ADDR(hStr);
943 for (i = ch1, j = 0; i < ch; i++, j++)
944 str[j] = lp[i];
945 str[++j] = '\0';
946 #ifdef DEBUG_EDIT
947 printf("EDIT_GetStr: returning %s\n", str);
948 #endif
949 return hStr;
953 /*********************************************************************
954 * WM_CHAR message function
957 void EDIT_CharMsg(HWND hwnd, WORD wParam)
959 WND *wndPtr = WIN_FindWndPtr(hwnd);
960 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
962 #ifdef DEBUG_EDIT
963 printf("EDIT_CharMsg: wParam=%c\n", (char)wParam);
964 #endif
966 switch (wParam)
968 case '\r':
969 case '\n':
970 if (!IsMultiLine())
971 break;
972 wParam = '\n';
973 EDIT_KeyTyped(hwnd, wParam);
974 break;
976 default:
977 if (wParam >= 20 && wParam <= 126)
978 EDIT_KeyTyped(hwnd, wParam);
979 break;
984 /*********************************************************************
985 * EDIT_KeyTyped
987 * Process keystrokes that produce displayable characters.
990 void EDIT_KeyTyped(HWND hwnd, short ch)
992 WND *wndPtr = WIN_FindWndPtr(hwnd);
993 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
994 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
995 char *currchar = CurrChar;
996 RECT rc;
997 BOOL FullPaint = FALSE;
999 #ifdef DEBUG_EDIT
1000 printf("EDIT_KeyTyped: ch=%c\n", (char)ch);
1001 #endif
1003 /* delete selected text (if any) */
1004 if (SelMarked(es))
1005 EDIT_DeleteSel(hwnd);
1007 /* test for typing at end of maximum buffer size */
1008 if (currchar == text + es->MaxTextLen)
1010 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1011 return;
1014 if (*currchar == '\0')
1016 /* insert a newline at end of text */
1017 *currchar = '\n';
1018 *(currchar + 1) = '\0';
1019 EDIT_BuildTextPointers(hwnd);
1022 /* insert the typed character */
1023 if (text[es->textlen - 1] != '\0')
1025 /* current text buffer is full */
1026 if (es->textlen == es->MaxTextLen)
1028 /* text buffer is at maximum size */
1029 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1030 return;
1033 /* increase the text buffer size */
1034 es->textlen += GROWLENGTH;
1035 /* but not above maximum size */
1036 if (es->textlen > es->MaxTextLen)
1037 es->textlen = es->MaxTextLen;
1038 es->hText = EDIT_HEAP_REALLOC(es->hText, es->textlen + 2);
1039 if (!es->hText)
1040 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1041 text = (char *)EDIT_HEAP_ADDR(es->hText);
1042 text[es->textlen - 1] = '\0';
1043 currchar = CurrChar;
1045 /* make space for new character and put char in buffer */
1046 memmove(currchar + 1, currchar, strlen(currchar) + 1);
1047 *currchar = ch;
1048 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
1049 es->TextChanged = TRUE;
1050 NOTIFY_PARENT(hwnd, EN_UPDATE);
1052 /* re-adjust textwidth, if necessary, and redraw line */
1053 HideCaret(hwnd);
1054 if (IsMultiLine() && es->wlines > 1)
1056 es->textwidth = max(es->textwidth,
1057 EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine),
1058 (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) -
1059 EDIT_TextLine(hwnd, es->CurrLine))));
1061 else
1062 es->textwidth = max(es->textwidth,
1063 EDIT_LineLength(es, text, strlen(text)));
1064 EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
1066 if (ch == '\n')
1068 if (es->wleft > 0)
1069 FullPaint = TRUE;
1070 es->wleft = 0;
1071 EDIT_BuildTextPointers(hwnd);
1072 EDIT_End(hwnd);
1073 EDIT_Forward(hwnd);
1075 /* invalidate rest of window */
1076 GetClientRect(hwnd, &rc);
1077 if (!FullPaint)
1078 rc.top = es->WndRow * es->txtht;
1079 InvalidateRect(hwnd, &rc, FALSE);
1081 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1082 ShowCaret(hwnd);
1083 UpdateWindow(hwnd);
1084 NOTIFY_PARENT(hwnd, EN_CHANGE);
1085 return;
1088 /* test end of window */
1089 if (es->WndCol >= ClientWidth(wndPtr) - EDIT_CharWidth(es, ch))
1091 /* TODO:- Word wrap to be handled here */
1093 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1094 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1096 es->WndCol += EDIT_CharWidth(es, ch);
1097 es->CurrCol++;
1098 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1099 ShowCaret(hwnd);
1100 NOTIFY_PARENT(hwnd, EN_CHANGE);
1104 /*********************************************************************
1105 * EDIT_CharWidth
1107 * Return the width of the given character in pixels.
1110 int EDIT_CharWidth(EDITSTATE *es, short ch)
1112 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
1114 return (charWidths[ch]);
1118 /*********************************************************************
1119 * EDIT_Forward
1121 * Cursor right key: move right one character position.
1124 void EDIT_Forward(HWND hwnd)
1126 WND *wndPtr = WIN_FindWndPtr(hwnd);
1127 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1128 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
1129 char *cc = CurrChar + 1;
1131 if (*cc == '\0')
1132 return;
1134 if (*CurrChar == '\n')
1136 EDIT_Home(hwnd);
1137 EDIT_Downward(hwnd);
1139 else
1141 es->WndCol += EDIT_CharWidth(es, *CurrChar);
1142 es->CurrCol++;
1143 if (es->WndCol >= ClientWidth(wndPtr))
1144 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1150 /*********************************************************************
1151 * EDIT_Downward
1153 * Cursor down key: move down one line.
1156 void EDIT_Downward(HWND hwnd)
1158 WND *wndPtr = WIN_FindWndPtr(hwnd);
1159 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1161 #ifdef DEBUG_EDIT
1162 printf("EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n", es->WndRow, es->wtop, es->wlines);
1163 #endif
1165 if (IsMultiLine() && (es->WndRow + es->wtop + 1 < es->wlines))
1167 es->CurrLine++;
1168 if (es->WndRow == ClientHeight(wndPtr, es) - 1)
1170 es->WndRow++;
1171 EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
1173 else
1174 es->WndRow++;
1175 EDIT_StickEnd(hwnd);
1180 /*********************************************************************
1181 * EDIT_Upward
1183 * Cursor up key: move up one line.
1186 void EDIT_Upward(HWND hwnd)
1188 WND *wndPtr = WIN_FindWndPtr(hwnd);
1189 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1191 if (IsMultiLine() && es->CurrLine != 0)
1193 --es->CurrLine;
1194 if (es->WndRow == 0)
1196 --es->WndRow;
1197 EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
1199 else
1200 --es->WndRow;
1201 EDIT_StickEnd(hwnd);
1206 /*********************************************************************
1207 * EDIT_Backward
1209 * Cursor left key: move left one character position.
1212 void EDIT_Backward(HWND hwnd)
1214 WND *wndPtr = WIN_FindWndPtr(hwnd);
1215 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1216 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
1218 if (es->CurrCol)
1220 --es->CurrCol;
1221 es->WndCol -= EDIT_CharWidth(es, *CurrChar);
1222 if (es->WndCol < 0)
1223 EDIT_KeyHScroll(hwnd, SB_LINEUP);
1225 else if (IsMultiLine() && es->CurrLine != 0)
1227 EDIT_Upward(hwnd);
1228 EDIT_End(hwnd);
1233 /*********************************************************************
1234 * EDIT_End
1236 * End key: move to end of line.
1239 void EDIT_End(HWND hwnd)
1241 RECT rc;
1242 WND *wndPtr = WIN_FindWndPtr(hwnd);
1243 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1244 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
1246 while (*CurrChar && *CurrChar != '\n')
1248 es->WndCol += EDIT_CharWidth(es, *CurrChar);
1249 es->CurrCol++;
1252 if (es->WndCol >= ClientWidth(wndPtr))
1254 es->wleft = es->WndCol - ClientWidth(wndPtr) + HSCROLLDIM;
1255 es->WndCol -= es->wleft;
1256 InvalidateRect(hwnd, NULL, FALSE);
1257 UpdateWindow(hwnd);
1262 /*********************************************************************
1263 * EDIT_Home
1265 * Home key: move to beginning of line.
1268 void EDIT_Home(HWND hwnd)
1270 RECT rc;
1271 WND *wndPtr = WIN_FindWndPtr(hwnd);
1272 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1274 es->CurrCol = es->WndCol = 0;
1275 if (es->wleft != 0)
1277 es->wleft = 0;
1278 InvalidateRect(hwnd, NULL, FALSE);
1279 UpdateWindow(hwnd);
1284 /*********************************************************************
1285 * EDIT_StickEnd
1287 * Stick the cursor to the end of the line.
1290 void EDIT_StickEnd(HWND hwnd)
1292 WND *wndPtr = WIN_FindWndPtr(hwnd);
1293 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1294 char currpel;
1296 char *cp = EDIT_TextLine(hwnd, es->CurrLine);
1297 char *cp1 = strchr(cp, '\n');
1298 int len = cp1 ? (int)(cp1 - cp) : 0;
1300 es->CurrCol = min(len, es->CurrCol);
1301 es->WndCol = min(EDIT_LineLength(es, cp, len) - es->wleft, es->WndCol);
1302 currpel = EDIT_LineLength(es, cp, es->CurrCol);
1304 if (es->wleft > currpel)
1306 es->wleft = max(0, currpel - 20);
1307 es->WndCol = currpel - es->wleft;
1308 UpdateWindow(hwnd);
1310 else if (currpel - es->wleft >= ClientWidth(wndPtr))
1312 es->wleft = currpel - (ClientWidth(wndPtr) - 5);
1313 es->WndCol = currpel - es->wleft;
1314 UpdateWindow(hwnd);
1319 /*********************************************************************
1320 * WM_KEYDOWN message function
1323 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam)
1325 WND *wndPtr = WIN_FindWndPtr(hwnd);
1326 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1328 #ifdef DEBUG_EDIT
1329 printf("EDIT_KeyDownMsg: key=%x\n", wParam);
1330 #endif
1332 HideCaret(hwnd);
1333 switch (wParam)
1335 case VK_UP:
1336 if (SelMarked(es))
1337 EDIT_ClearSel(hwnd);
1338 if (IsMultiLine())
1339 EDIT_Upward(hwnd);
1340 else
1341 EDIT_Backward(hwnd);
1342 break;
1344 case VK_DOWN:
1345 if (SelMarked(es))
1346 EDIT_ClearSel(hwnd);
1347 if (IsMultiLine())
1348 EDIT_Downward(hwnd);
1349 else
1350 EDIT_Forward(hwnd);
1351 break;
1353 case VK_RIGHT:
1354 if (SelMarked(es))
1355 EDIT_ClearSel(hwnd);
1356 EDIT_Forward(hwnd);
1357 break;
1359 case VK_LEFT:
1360 if (SelMarked(es))
1361 EDIT_ClearSel(hwnd);
1362 EDIT_Backward(hwnd);
1363 break;
1365 case VK_HOME:
1366 if (SelMarked(es))
1367 EDIT_ClearSel(hwnd);
1368 EDIT_Home(hwnd);
1369 break;
1371 case VK_END:
1372 if (SelMarked(es))
1373 EDIT_ClearSel(hwnd);
1374 EDIT_End(hwnd);
1375 break;
1377 case VK_PRIOR:
1378 if (IsMultiLine())
1380 if (SelMarked(es))
1381 EDIT_ClearSel(hwnd);
1382 EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
1384 break;
1386 case VK_NEXT:
1387 if (IsMultiLine())
1389 if (SelMarked(es))
1390 EDIT_ClearSel(hwnd);
1391 EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
1393 break;
1395 case VK_BACK:
1396 if (SelMarked(es))
1397 EDIT_DeleteSel(hwnd);
1398 else
1400 if (es->CurrCol == 0 && es->CurrLine == 0)
1401 break;
1402 EDIT_Backward(hwnd);
1403 EDIT_DelKey(hwnd);
1405 break;
1407 case VK_DELETE:
1408 if (SelMarked(es))
1409 EDIT_DeleteSel(hwnd);
1410 else
1411 EDIT_DelKey(hwnd);
1412 break;
1415 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1416 ShowCaret(hwnd);
1420 /*********************************************************************
1421 * EDIT_KeyHScroll
1423 * Scroll text horizontally using cursor keys.
1426 void EDIT_KeyHScroll(HWND hwnd, WORD opt)
1428 RECT rc;
1429 int hscrollpos;
1430 WND *wndPtr = WIN_FindWndPtr(hwnd);
1431 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1433 if (opt == SB_LINEDOWN)
1435 es->wleft += HSCROLLDIM;
1436 es->WndCol -= HSCROLLDIM;
1438 else
1440 if (es->wleft == 0)
1441 return;
1442 if (es->wleft - HSCROLLDIM < 0)
1444 es->WndCol += es->wleft;
1445 es->wleft = 0;
1447 else
1449 es->wleft -= HSCROLLDIM;
1450 es->WndCol += HSCROLLDIM;
1454 InvalidateRect(hwnd, NULL, FALSE);
1455 UpdateWindow(hwnd);
1457 if (IsHScrollBar())
1459 hscrollpos = EDIT_ComputeHScrollPos(hwnd);
1460 SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE);
1465 /*********************************************************************
1466 * EDIT_KeyVScrollLine
1468 * Scroll text vertically by one line using keyboard.
1471 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt)
1473 RECT rc;
1474 int y, vscrollpos;
1475 WND *wndPtr = WIN_FindWndPtr(hwnd);
1476 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1478 if (!IsMultiLine())
1479 return;
1481 if (opt == SB_LINEDOWN)
1483 /* move down one line */
1484 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1485 return;
1486 es->wtop++;
1488 else
1490 /* move up one line */
1491 if (es->wtop == 0)
1492 return;
1493 --es->wtop;
1496 if (IsWindowVisible(hwnd))
1498 /* adjust client bottom to nearest whole line */
1499 GetClientRect(hwnd, &rc);
1500 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1502 if (opt == SB_LINEUP)
1504 /* move up one line (scroll window down) */
1505 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1506 /* write top line */
1507 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1508 es->WndRow++;
1510 else
1512 /* move down one line (scroll window up) */
1513 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1514 /* write bottom line */
1515 y = (((rc.bottom - rc.top) / es->txtht) - 1);
1516 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1517 --es->WndRow;
1521 /* reset the vertical scroll bar */
1522 if (IsVScrollBar())
1524 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1525 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1530 /*********************************************************************
1531 * EDIT_KeyVScrollPage
1533 * Scroll text vertically by one page using keyboard.
1536 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
1538 RECT rc;
1539 int vscrollpos;
1540 WND *wndPtr = WIN_FindWndPtr(hwnd);
1541 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1543 if (IsMultiLine())
1545 if (opt == SB_PAGEUP)
1547 if (es->wtop)
1548 es->wtop -= ClientHeight(wndPtr, es);
1550 else
1552 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1554 es->wtop += ClientHeight(wndPtr, es);
1555 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1556 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1559 if (es->wtop < 0)
1560 es->wtop = 0;
1562 es->CurrLine = es->wtop + es->WndRow;
1563 EDIT_StickEnd(hwnd);
1564 InvalidateRect(hwnd, NULL, TRUE);
1565 UpdateWindow(hwnd);
1567 /* reset the vertical scroll bar */
1568 if (IsVScrollBar())
1570 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1571 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1577 /*********************************************************************
1578 * EDIT_KeyVScrollDoc
1580 * Scroll text to top and bottom of document using keyboard.
1583 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt)
1585 RECT rc;
1586 int vscrollpos;
1587 WND *wndPtr = WIN_FindWndPtr(hwnd);
1588 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1590 if (!IsMultiLine())
1591 return;
1593 if (opt == SB_TOP)
1594 es->wtop = es->wleft = 0;
1595 else if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1597 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1598 es->wleft = 0;
1601 es->CurrLine = es->wlines;
1602 es->WndRow = es->wlines - es->wtop;
1603 EDIT_End(hwnd);
1604 InvalidateRect(hwnd, NULL, TRUE);
1605 UpdateWindow(hwnd);
1607 /* reset the vertical scroll bar */
1608 if (IsVScrollBar())
1610 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1611 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1616 /*********************************************************************
1617 * EDIT_ComputeVScrollPos
1619 * Compute the vertical scroll bar position from the window
1620 * position and text width.
1623 int EDIT_ComputeVScrollPos(HWND hwnd)
1625 int vscrollpos;
1626 short minpos, maxpos;
1627 WND *wndPtr = WIN_FindWndPtr(hwnd);
1628 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1630 GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos);
1632 if (es->wlines > ClientHeight(wndPtr, es))
1633 vscrollpos = (double)(es->wtop) / (double)(es->wlines -
1634 ClientHeight(wndPtr, es)) * (maxpos - minpos);
1635 else
1636 vscrollpos = minpos;
1638 return vscrollpos;
1642 /*********************************************************************
1643 * EDIT_ComputeHScrollPos
1645 * Compute the horizontal scroll bar position from the window
1646 * position and text width.
1649 int EDIT_ComputeHScrollPos(HWND hwnd)
1651 int hscrollpos;
1652 short minpos, maxpos;
1653 WND *wndPtr = WIN_FindWndPtr(hwnd);
1654 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1656 GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos);
1658 if (es->textwidth > ClientWidth(wndPtr))
1659 hscrollpos = (double)(es->wleft) / (double)(es->textwidth -
1660 ClientWidth(wndPtr)) * (maxpos - minpos);
1661 else
1662 hscrollpos = minpos;
1664 return hscrollpos;
1668 /*********************************************************************
1669 * EDIT_DelKey
1671 * Delete character to right of cursor.
1674 void EDIT_DelKey(HWND hwnd)
1676 RECT rc;
1677 WND *wndPtr = WIN_FindWndPtr(hwnd);
1678 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1679 char *currchar = CurrChar;
1680 BOOL repaint = *currchar == '\n';
1682 if (IsMultiLine() && *currchar == '\n' && *(currchar + 1) == '\0')
1683 return;
1684 strcpy(currchar, currchar + 1);
1685 NOTIFY_PARENT(hwnd, EN_UPDATE);
1687 if (repaint)
1689 EDIT_BuildTextPointers(hwnd);
1690 GetClientRect(hwnd, &rc);
1691 rc.top = es->WndRow * es->txtht;
1692 InvalidateRect(hwnd, &rc, FALSE);
1693 UpdateWindow(hwnd);
1695 else
1697 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1);
1698 EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop);
1701 es->TextChanged = TRUE;
1702 NOTIFY_PARENT(hwnd, EN_CHANGE);
1705 /*********************************************************************
1706 * WM_VSCROLL message function
1709 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1711 WND *wndPtr = WIN_FindWndPtr(hwnd);
1712 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1714 if (IsMultiLine())
1716 HideCaret(hwnd);
1718 switch (wParam)
1720 case SB_LINEUP:
1721 case SB_LINEDOWN:
1722 EDIT_VScrollLine(hwnd, wParam);
1723 break;
1725 case SB_PAGEUP:
1726 case SB_PAGEDOWN:
1727 EDIT_VScrollPage(hwnd, wParam);
1728 break;
1732 SetCaretPos(es->WndCol, es->WndRow);
1733 ShowCaret(hwnd);
1737 /*********************************************************************
1738 * EDIT_VScrollLine
1740 * Scroll text vertically by one line using scrollbars.
1743 void EDIT_VScrollLine(HWND hwnd, WORD opt)
1745 RECT rc;
1746 int y;
1747 WND *wndPtr = WIN_FindWndPtr(hwnd);
1748 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1750 #ifdef DEBUG_EDIT
1751 printf("EDIT_VScrollLine: direction=%d\n", opt);
1752 #endif
1754 if (opt == SB_LINEDOWN)
1756 /* move down one line */
1757 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1758 return;
1759 es->wtop++;
1760 printf("Scroll line down: wtop=%d\n", es->wtop);
1762 else
1764 /* move up one line */
1765 if (es->wtop == 0)
1766 return;
1767 --es->wtop;
1768 printf("Scroll line up: wtop=%d\n", es->wtop);
1771 if (IsWindowVisible(hwnd))
1773 /* adjust client bottom to nearest whole line */
1774 GetClientRect(hwnd, &rc);
1775 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1777 if (opt == SB_LINEUP)
1779 /* move up one line (scroll window down) */
1780 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1781 /* write top line */
1782 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1783 es->WndRow++;
1785 else
1787 /* move down one line (scroll window up) */
1788 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1789 /* write bottom line */
1790 y = ((rc.bottom - rc.top / es->txtht) - 1);
1791 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1792 --es->WndRow;
1798 /*********************************************************************
1799 * EDIT_VScrollPage
1801 * Scroll text vertically by one page using keyboard.
1804 void EDIT_VScrollPage(HWND hwnd, WORD opt)
1806 RECT rc;
1807 int vscrollpos;
1808 WND *wndPtr = WIN_FindWndPtr(hwnd);
1809 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1811 if (opt == SB_PAGEUP)
1813 if (es->wtop)
1814 es->wtop -= ClientHeight(wndPtr, es);
1816 else
1818 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1820 es->wtop += ClientHeight(wndPtr, es);
1821 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1822 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1825 if (es->wtop < 0)
1826 es->wtop = 0;
1828 InvalidateRect(hwnd, NULL, TRUE);
1829 UpdateWindow(hwnd);
1831 /* reset the vertical scroll bar */
1832 if (IsVScrollBar())
1834 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1835 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1840 /*********************************************************************
1841 * WM_HSCROLL message function
1844 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1846 WND *wndPtr = WIN_FindWndPtr(hwnd);
1847 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1849 switch (wParam)
1851 case SB_LINEUP:
1852 case SB_LINEDOWN:
1853 HideCaret(hwnd);
1855 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1856 ShowCaret(hwnd);
1857 break;
1862 /*********************************************************************
1863 * WM_SIZE message function
1866 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam)
1868 RECT rc;
1869 WND *wndPtr = WIN_FindWndPtr(hwnd);
1870 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1872 if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return;
1874 InvalidateRect(hwnd, NULL, TRUE);
1875 es->PaintBkgd = TRUE;
1876 UpdateWindow(hwnd);
1880 /*********************************************************************
1881 * WM_LBUTTONDOWN message function
1884 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam)
1886 char *cp, *cp1;
1887 int len;
1888 BOOL end = FALSE;
1889 WND *wndPtr = WIN_FindWndPtr(hwnd);
1890 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1892 if (SelMarked(es))
1893 EDIT_ClearSel(hwnd);
1895 es->WndRow = HIWORD(lParam) / es->txtht;
1896 if (es->WndRow > es->wlines - es->wtop - 1)
1898 if (es->wlines)
1899 es->WndRow = es->wlines - es->wtop - 1;
1900 else
1901 es->WndRow = 0;
1902 end = TRUE;
1904 es->CurrLine = es->wtop + es->WndRow;
1906 cp = EDIT_TextLine(hwnd, es->CurrLine);
1907 cp1 = strchr(cp, '\n');
1908 len = cp1 ? (int)(cp1 - cp) : 0;
1910 es->WndCol = LOWORD(lParam);
1911 if (es->WndCol > EDIT_LineLength(es, cp, len) - es->wleft || end)
1912 es->WndCol = EDIT_LineLength(es, cp, len) - es->wleft;
1913 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
1915 ButtonDown = TRUE;
1916 ButtonRow = es->CurrLine;
1917 ButtonCol = es->CurrCol;
1921 /*********************************************************************
1922 * WM_MOUSEMOVE message function
1925 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
1927 if (wParam != MK_LBUTTON)
1928 return;
1930 if (ButtonDown)
1932 EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
1933 TextMarking = TRUE;
1934 ButtonDown = FALSE;
1937 if (TextMarking)
1938 EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
1942 /*********************************************************************
1943 * EDIT_PixelToChar
1945 * Convert a pixel offset in the given row to a character offset,
1946 * adjusting the pixel offset to the nearest whole character if
1947 * necessary.
1950 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
1952 int ch = 0, i = 0;
1953 char *text;
1954 WND *wndPtr = WIN_FindWndPtr(hwnd);
1955 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1956 short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
1958 #ifdef DEBUG_EDIT
1959 printf("EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
1960 #endif
1962 text = EDIT_TextLine(hwnd, row);
1963 while (i < *pixel)
1965 i += charWidths[*(text + ch)];
1966 ch++;
1969 /* if stepped past _pixel_, go back a character */
1970 if (i - *pixel)
1971 i -= charWidths[*(text + ch)];
1972 *pixel = i;
1973 return ch;
1977 /*********************************************************************
1978 * WM_SETTEXT message function
1981 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam)
1983 int len;
1984 char *text;
1985 RECT rc;
1986 WND *wndPtr = WIN_FindWndPtr(hwnd);
1987 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
1989 if (strlen((char *)lParam) <= es->MaxTextLen)
1991 len = strlen((char *)lParam);
1992 EDIT_ClearText(hwnd);
1993 es->textlen = len;
1994 es->hText = EDIT_HEAP_REALLOC(es->hText, len + 3);
1995 text = EDIT_HEAP_ADDR(es->hText);
1996 strcpy(text, (char *)lParam);
1997 text[len] = '\n';
1998 text[len + 1] = '\0';
1999 text[len + 2] = '\0';
2000 EDIT_BuildTextPointers(hwnd);
2001 InvalidateRect(hwnd, NULL, TRUE);
2002 es->PaintBkgd = TRUE;
2003 es->TextChanged = TRUE;
2004 return 0L;
2006 else
2007 return EN_ERRSPACE;
2011 /*********************************************************************
2012 * EDIT_ClearText
2014 * Clear text from text buffer.
2017 void EDIT_ClearText(HWND hwnd)
2019 WND *wndPtr = WIN_FindWndPtr(hwnd);
2020 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2021 unsigned int blen = EditBufLen(wndPtr) + 2;
2022 char *text;
2024 es->hText = EDIT_HEAP_REALLOC(es->hText, blen);
2025 text = EDIT_HEAP_ADDR(es->hText);
2026 memset(text, 0, blen);
2027 es->textlen = 0;
2028 es->wlines = 0;
2029 es->CurrLine = es->CurrCol = 0;
2030 es->WndRow = es->WndCol = 0;
2031 es->wleft = es->wtop = 0;
2032 es->textwidth = 0;
2033 es->TextChanged = FALSE;
2034 EDIT_ClearTextPointers(hwnd);
2038 /*********************************************************************
2039 * EM_SETSEL message function
2042 void EDIT_SetSelMsg(HWND hwnd, LONG lParam)
2044 int so, eo;
2045 WND *wndPtr = WIN_FindWndPtr(hwnd);
2046 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2048 so = LOWORD(lParam);
2049 eo = HIWORD(lParam);
2050 if (so > eo)
2051 swap(&so, &eo);
2053 EDIT_GetLineCol(hwnd, so, &(es->SelBegLine), &(es->SelBegCol));
2054 EDIT_GetLineCol(hwnd, eo, &(es->SelEndLine), &(es->SelEndCol));
2056 es->CurrLine = es->SelEndLine;
2057 es->CurrCol = es->SelEndCol;
2058 es->WndRow = es->SelEndLine - es->wtop;
2059 if (es->WndRow < 0)
2061 es->wtop = es->SelEndLine;
2062 es->WndRow = 0;
2064 es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->SelEndLine),
2065 es->SelEndCol) - es->wleft;
2067 InvalidateRect(hwnd, NULL, TRUE);
2068 UpdateWindow(hwnd);
2072 /*********************************************************************
2073 * EDIT_GetLineCol
2075 * Return line and column in text buffer from character offset.
2078 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
2080 int lineno;
2081 char *cp, *cp1;
2082 WND *wndPtr = WIN_FindWndPtr(hwnd);
2083 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2084 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
2085 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2087 if (off > strlen(text)) off = strlen(text);
2088 for (lineno = 0; lineno < es->wlines; lineno++)
2090 cp = text + *(textPtrs + lineno);
2091 if (off == (int)(cp - text))
2093 *line = lineno;
2094 *col = 0;
2095 return;
2097 if (off < (int)(cp - text))
2098 break;
2099 cp1 = cp;
2101 *line = lineno - 1;
2102 *col = off - (int)(cp1 - text);
2103 if (*(text + *col) == '\0')
2104 (*col)--;
2108 /*********************************************************************
2109 * EDIT_DeleteSel
2111 * Delete the current selected text (if any)
2114 void EDIT_DeleteSel(HWND hwnd)
2116 char *bbl, *bel;
2117 int len;
2118 WND *wndPtr = WIN_FindWndPtr(hwnd);
2119 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2120 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
2122 if (SelMarked(es))
2124 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
2125 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
2126 len = (int)(bel - bbl);
2127 es->TextChanged = TRUE;
2128 strcpy(bbl, bel);
2130 es->CurrLine = es->SelBegLine;
2131 es->CurrCol = es->SelBegCol;
2132 es->WndRow = es->SelBegLine - es->wtop;
2133 if (es->WndRow < 0)
2135 es->wtop = es->SelBegLine;
2136 es->WndRow = 0;
2138 es->WndCol = EDIT_LineLength(es, bbl - es->SelBegCol,
2139 es->SelBegCol) - es->wleft;
2141 EDIT_BuildTextPointers(hwnd);
2142 es->PaintBkgd = TRUE;
2143 EDIT_ClearSel(hwnd);
2148 /*********************************************************************
2149 * EDIT_ClearSel
2151 * Clear the current selection.
2154 void EDIT_ClearSel(HWND hwnd)
2156 WND *wndPtr = WIN_FindWndPtr(hwnd);
2157 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2159 es->SelBegLine = es->SelBegCol = -1;
2160 es->SelEndLine = es->SelEndCol = -1;
2162 InvalidateRect(hwnd, NULL, TRUE);
2163 UpdateWindow(hwnd);
2167 /*********************************************************************
2168 * EDIT_TextLineNumber
2170 * Return the line number in the text buffer of the supplied
2171 * character pointer.
2174 int EDIT_TextLineNumber(HWND hwnd, char *lp)
2176 int lineno;
2177 char *cp;
2178 WND *wndPtr = WIN_FindWndPtr(hwnd);
2179 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2180 char *text = (char *)EDIT_HEAP_ADDR(es->hText);
2181 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2183 for (lineno = 0; lineno < es->wlines; lineno++)
2185 cp = text + *(textPtrs + lineno);
2186 if (cp == lp)
2187 return lineno;
2188 if (cp > lp)
2189 break;
2191 return lineno - 1;
2195 /*********************************************************************
2196 * EDIT_SetAnchor
2198 * Set down anchor for text marking.
2201 void EDIT_SetAnchor(HWND hwnd, int row, int col)
2203 WND *wndPtr = WIN_FindWndPtr(hwnd);
2204 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2206 EDIT_ClearSel(hwnd);
2207 es->SelBegLine = es->SelEndLine = row;
2208 es->SelBegCol = es->SelEndCol = col;
2209 InvalidateRect(hwnd, NULL, FALSE);
2210 UpdateWindow(hwnd);
2214 /*********************************************************************
2215 * EDIT_ExtendSel
2217 * Extend selection to the given screen co-ordinates.
2220 void EDIT_ExtendSel(HWND hwnd, int x, int y)
2222 int bbl, bel;
2223 int ptop, pbot;
2224 char *cp, *cp1;
2225 int len;
2226 BOOL end = FALSE;
2227 WND *wndPtr = WIN_FindWndPtr(hwnd);
2228 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2230 #ifdef DEBUG_EDIT
2231 printf("EDIT_ExtendSel: x=%d, y=%d\n", x, y);
2232 #endif
2234 ptop = min(es->SelBegLine, es->SelEndLine);
2235 pbot = max(es->SelBegLine, es->SelEndLine);
2236 cp = EDIT_TextLine(hwnd, es->wtop + y / es->txtht);
2237 cp1 = strchr(cp, '\n');
2238 len = cp1 ? (int)(cp1 - cp) : 0;
2240 es->WndRow = y / es->txtht;
2241 if (es->WndRow > es->wlines - es->wtop - 1)
2243 if (es->wlines)
2244 es->WndRow = es->wlines - es->wtop - 1;
2245 else
2246 es->WndRow = 0;
2247 end = TRUE;
2249 es->CurrLine = es->wtop + es->WndRow;
2250 es->SelEndLine = es->CurrLine;
2252 es->WndCol = x;
2253 if (es->WndCol > EDIT_LineLength(es, cp, len) - es->wleft || end)
2254 es->WndCol = EDIT_LineLength(es, cp, len) - es->wleft;
2255 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2256 es->SelEndCol = es->CurrCol;
2258 bbl = min(es->SelBegLine, es->SelEndLine);
2259 bel = max(es->SelBegLine, es->SelEndLine);
2260 while (ptop < bbl)
2262 EDIT_WriteTextLine(hwnd, NULL, ptop);
2263 ptop++;
2265 for (y = bbl; y <= bel; y++)
2266 EDIT_WriteTextLine(hwnd, NULL, y);
2267 while (pbot > bel)
2269 EDIT_WriteTextLine(hwnd, NULL, pbot);
2270 --pbot;
2275 /*********************************************************************
2276 * EDIT_StopMarking
2278 * Stop text marking (selection).
2281 void EDIT_StopMarking(HWND hwnd)
2283 WND *wndPtr = WIN_FindWndPtr(hwnd);
2284 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2286 TextMarking = FALSE;
2287 if (es->SelBegLine > es->SelEndLine)
2289 swap(&(es->SelBegLine), &(es->SelEndLine));
2290 swap(&(es->SelBegCol), &(es->SelEndCol));
2292 if (es->SelBegLine == es->SelEndLine && es->SelBegCol > es->SelEndCol)
2293 swap(&(es->SelBegCol), &(es->SelEndCol));
2297 /*********************************************************************
2298 * EM_GETLINE message function
2301 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam)
2303 char *cp, *cp1;
2304 int len;
2305 char *buffer = (char *)lParam;
2306 WND *wndPtr = WIN_FindWndPtr(hwnd);
2307 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2309 cp = EDIT_TextLine(hwnd, wParam);
2310 cp1 = EDIT_TextLine(hwnd, wParam + 1);
2311 len = min((int)(cp1 - cp), (WORD)(*buffer));
2312 strncpy(buffer, cp, len);
2314 return (LONG)len;
2318 /*********************************************************************
2319 * EM_GETSEL message function
2322 LONG EDIT_GetSelMsg(HWND hwnd)
2324 int so, eo;
2325 WND *wndPtr = WIN_FindWndPtr(hwnd);
2326 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2327 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2329 so = *(textPtrs + es->SelBegLine) + es->SelBegCol;
2330 eo = *(textPtrs + es->SelEndLine) + es->SelEndCol;
2332 return MAKELONG(so, eo);
2336 /*********************************************************************
2337 * EM_LINEFROMCHAR message function
2340 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam)
2342 int row, col;
2343 WND *wndPtr = WIN_FindWndPtr(hwnd);
2344 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2346 if (wParam == (WORD)-1)
2347 return (LONG)(es->SelBegLine);
2348 else
2349 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2351 return (LONG)row;
2355 /*********************************************************************
2356 * EM_LINEINDEX message function
2359 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam)
2361 WND *wndPtr = WIN_FindWndPtr(hwnd);
2362 EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
2363 unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
2365 if (wParam == (WORD)-1)
2366 wParam = es->CurrLine;
2368 return (LONG)(*(textPtrs + wParam));
2372 /*********************************************************************
2373 * Utility functions
2376 void swap(int *a, int *b)
2378 int x;
2380 x = *a;
2381 *a = *b;
2382 *b = x;