Release 941017
[wine/gsoc-2012-control.git] / controls / edit.c
blob968cc3dc7aade64280cdcf1d730c9434c9bdcc54
1 /*
2 * Edit control
4 * Copyright David W. Metcalfe, 1994
6 * Release 3, July 1994
7 */
9 static char Copyright[] = "Copyright David W. Metcalfe, 1994";
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <windows.h>
15 #include <heap.h>
16 #include "win.h"
17 #include "class.h"
18 #include "user.h"
19 #include "scroll.h"
20 #include "stddebug.h"
21 /* #define DEBUG_EDIT /* */
22 /* #undef DEBUG_EDIT /* */
23 #include "debug.h"
26 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
27 SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
28 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
30 #define MAXTEXTLEN 30000 /* maximum text buffer length */
31 #define EDITLEN 1024 /* starting length for multi-line control */
32 #define ENTRYLEN 256 /* starting length for single line control */
33 #define GROWLENGTH 64 /* buffers grow by this much */
35 #define HSCROLLDIM (ClientWidth(wndPtr) / 3)
36 /* "line" dimension for horizontal scroll */
38 typedef struct
40 int wlines; /* number of lines of text */
41 int wtop; /* top line that is displayed */
42 int wleft; /* left pixel that is displayed */
43 unsigned int textlen; /* text buffer length */
44 int textwidth; /* width of longest line in pixels */
45 RECT fmtrc; /* rectangle in which to format text */
46 int txtht; /* height of text line in pixels */
47 HANDLE hText; /* handle to text buffer */
48 HANDLE hCharWidths; /* widths of chars in font */
49 HANDLE hTextPtrs; /* list of line offsets */
50 HANDLE hBlankLine; /* to fill blank lines quickly */
51 int CurrCol; /* current column */
52 int CurrLine; /* current line */
53 int WndCol; /* current window column */
54 int WndRow; /* current window row */
55 BOOL TextChanged; /* TRUE if text has changed */
56 BOOL PaintBkgd; /* paint control background */
57 unsigned int MaxTextLen; /* maximum text buffer length */
58 int SelBegLine; /* beginning line of selection */
59 int SelBegCol; /* beginning column of selection */
60 int SelEndLine; /* ending line of selection */
61 int SelEndCol; /* ending column of selection */
62 HFONT hFont; /* handle of current font (if not default) */
63 HANDLE hDeletedText; /* handle to deleted txet buffer for undo */
64 int DeletedLength; /* length of deleted text */
65 int DeletedCurrLine; /* starting line from which text was deleted */
66 int DeletedCurrCol; /* starting col from which text was deleted */
67 int NumTabStops; /* number of tab stops in buffer hTabStops */
68 HANDLE hTabStops; /* handle of tab stops buffer */
69 } EDITSTATE;
72 #define ClientWidth(wndPtr) (wndPtr->rectClient.right - \
73 wndPtr->rectClient.left)
74 #define ClientHeight(wndPtr, es) ((wndPtr->rectClient.bottom - \
75 wndPtr->rectClient.top) / es->txtht)
76 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
77 ? EDITLEN : ENTRYLEN)
78 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
79 #define SelMarked(es) (es->SelBegLine != 0 || es->SelBegCol != 0 || \
80 es->SelEndLine != 0 || es->SelEndCol != 0)
81 #define ROUNDUP(numer, denom) (((numer) % (denom)) \
82 ? ((((numer) + (denom)) / (denom)) * (denom)) \
83 : (numer) + (denom))
85 /* macros to access window styles */
86 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
87 #define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
88 #define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
89 #define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
90 #define IsHScrollBar() (wndPtr->dwStyle & WS_HSCROLL)
92 /* internal variables */
93 static BOOL TextMarking; /* TRUE if text marking in progress */
94 static BOOL ButtonDown; /* TRUE if left mouse button down */
95 static int ButtonRow; /* row in text buffer when button pressed */
96 static int ButtonCol; /* col in text buffer when button pressed */
97 static BOOL Print = FALSE;
100 LONG EditWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
101 long EDIT_NCCreateMsg(HWND hwnd, LONG lParam);
102 long EDIT_CreateMsg(HWND hwnd, LONG lParam);
103 void EDIT_ClearTextPointers(HWND hwnd);
104 void EDIT_BuildTextPointers(HWND hwnd);
105 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var);
106 void EDIT_PaintMsg(HWND hwnd);
107 HANDLE EDIT_GetTextLine(HWND hwnd, int selection);
108 char *EDIT_TextLine(HWND hwnd, int sel);
109 int EDIT_StrLength(HWND hwnd, char *str, int len, int pcol);
110 int EDIT_LineLength(HWND hwnd, int num);
111 void EDIT_WriteTextLine(HWND hwnd, RECT *rc, int y);
112 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
113 int col, RECT *rc, BOOL blank, BOOL reverse);
114 HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff);
115 void EDIT_CharMsg(HWND hwnd, WORD wParam);
116 void EDIT_KeyTyped(HWND hwnd, short ch);
117 int EDIT_CharWidth(HWND hwnd, short ch, int pcol);
118 int EDIT_GetNextTabStop(HWND hwnd, int pcol);
119 void EDIT_Forward(HWND hwnd);
120 void EDIT_Downward(HWND hwnd);
121 void EDIT_Upward(HWND hwnd);
122 void EDIT_Backward(HWND hwnd);
123 void EDIT_End(HWND hwnd);
124 void EDIT_Home(HWND hwnd);
125 void EDIT_StickEnd(HWND hwnd);
126 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam);
127 void EDIT_KeyHScroll(HWND hwnd, WORD opt);
128 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt);
129 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt);
130 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt);
131 int EDIT_ComputeVScrollPos(HWND hwnd);
132 int EDIT_ComputeHScrollPos(HWND hwnd);
133 void EDIT_DelKey(HWND hwnd);
134 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
135 void EDIT_VScrollLine(HWND hwnd, WORD opt);
136 void EDIT_VScrollPage(HWND hwnd, WORD opt);
137 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
138 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam);
139 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam);
140 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam);
141 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel);
142 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam);
143 void EDIT_ClearText(HWND hwnd);
144 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam);
145 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col);
146 void EDIT_DeleteSel(HWND hwnd);
147 void EDIT_ClearSel(HWND hwnd);
148 int EDIT_TextLineNumber(HWND hwnd, char *lp);
149 void EDIT_SetAnchor(HWND hwnd, int row, int col);
150 void EDIT_ExtendSel(HWND hwnd, int x, int y);
151 void EDIT_WriteSel(HWND hwnd, int y, int start, int end);
152 void EDIT_StopMarking(HWND hwnd);
153 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
154 LONG EDIT_GetSelMsg(HWND hwnd);
155 void EDIT_ReplaceSel(HWND hwnd, LONG lParam);
156 void EDIT_InsertText(HWND hwnd, char *str, int len);
157 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam);
158 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam);
159 LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam);
160 void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam);
161 void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len, int line,
162 int col);
163 void EDIT_ClearDeletedText(HWND hwnd);
164 LONG EDIT_UndoMsg(HWND hwnd);
165 unsigned int EDIT_HeapAlloc(HWND hwnd, int bytes);
166 void *EDIT_HeapAddr(HWND hwnd, unsigned int handle);
167 unsigned int EDIT_HeapReAlloc(HWND hwnd, unsigned int handle, int bytes);
168 void EDIT_HeapFree(HWND hwnd, unsigned int handle);
169 unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle);
170 void EDIT_SetHandleMsg(HWND hwnd, WORD wParam);
171 LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam);
172 void EDIT_CopyToClipboard(HWND hwnd);
173 void EDIT_PasteMsg(HWND hwnd);
174 void swap(int *a, int *b);
177 LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
179 LONG lResult = 0L;
180 HDC hdc;
181 char *textPtr;
182 int len;
183 WND *wndPtr = WIN_FindWndPtr(hwnd);
184 EDITSTATE *es =
185 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
187 switch (uMsg) {
188 case EM_CANUNDO:
189 lResult = es->hDeletedText;
190 break;
192 case EM_EMPTYUNDOBUFFER:
193 EDIT_ClearDeletedText(hwnd);
194 break;
196 case EM_FMTLINES:
197 fprintf(stdnimp,"edit: EM_FMTLINES message received\n");
198 if (!wParam)
199 lResult = 1L;
200 else
201 lResult = 0L;
202 break;
204 case EM_GETFIRSTVISIBLELINE:
205 lResult = es->wtop;
206 break;
208 case EM_GETHANDLE:
209 lResult = es->hText;
210 break;
212 case EM_GETLINE:
213 if (IsMultiLine())
214 lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
215 else
216 lResult = 0L;
217 break;
219 case EM_GETLINECOUNT:
220 if (IsMultiLine())
221 lResult = es->wlines;
222 else
223 lResult = 0L;
224 break;
226 case EM_GETMODIFY:
227 lResult = es->TextChanged;
228 break;
230 case EM_GETPASSWORDCHAR:
231 fprintf(stdnimp,"edit: cannot process EM_GETPASSWORDCHAR message\n");
232 break;
234 case EM_GETRECT:
235 GetWindowRect(hwnd, (LPRECT)lParam);
236 break;
238 case EM_GETSEL:
239 lResult = EDIT_GetSelMsg(hwnd);
240 break;
242 case EM_GETWORDBREAKPROC:
243 fprintf(stdnimp,"edit: cannot process EM_GETWORDBREAKPROC message\n");
244 break;
246 case EM_LIMITTEXT:
247 if (wParam)
248 es->MaxTextLen = wParam;
249 else if (IsMultiLine())
250 es->MaxTextLen = 65535;
251 else
252 es->MaxTextLen = 32767;
253 break;
255 case EM_LINEFROMCHAR:
256 lResult = EDIT_LineFromCharMsg(hwnd, wParam);
257 break;
259 case EM_LINEINDEX:
260 if (IsMultiLine())
261 lResult = EDIT_LineIndexMsg(hwnd, wParam);
262 else
263 lResult = 0L;
264 break;
266 case EM_LINELENGTH:
267 lResult = EDIT_LineLengthMsg(hwnd, wParam);
268 break;
270 case EM_LINESCROLL:
271 fprintf(stdnimp,"edit: cannot process EM_LINESCROLL message\n");
272 break;
274 case EM_REPLACESEL:
275 HideCaret(hwnd);
276 EDIT_ReplaceSel(hwnd, lParam);
277 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
278 ShowCaret(hwnd);
279 break;
281 case EM_SETHANDLE:
282 EDIT_SetHandleMsg(hwnd, wParam);
283 break;
285 case EM_SETMODIFY:
286 es->TextChanged = wParam;
287 break;
289 case EM_SETPASSWORDCHAR:
290 fprintf(stdnimp,"edit: cannot process EM_SETPASSWORDCHAR message\n");
291 break;
293 case EM_SETREADONLY:
294 fprintf(stdnimp,"edit: cannot process EM_SETREADONLY message\n");
295 break;
297 case EM_SETRECT:
298 case EM_SETRECTNP:
299 fprintf(stdnimp,"edit: cannot process EM_SETRECT(NP) message\n");
300 break;
302 case EM_SETSEL:
303 HideCaret(hwnd);
304 EDIT_SetSelMsg(hwnd, wParam, lParam);
305 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
306 ShowCaret(hwnd);
307 break;
309 case EM_SETTABSTOPS:
310 lResult = EDIT_SetTabStopsMsg(hwnd, wParam, lParam);
311 break;
313 case EM_SETWORDBREAKPROC:
314 fprintf(stdnimp,"edit: cannot process EM_SETWORDBREAKPROC message\n");
315 break;
317 case EM_UNDO:
318 HideCaret(hwnd);
319 lResult = EDIT_UndoMsg(hwnd);
320 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
321 ShowCaret(hwnd);
322 break;
324 case WM_GETDLGCODE:
325 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
327 case WM_CHAR:
328 EDIT_CharMsg(hwnd, wParam);
329 break;
331 case WM_COPY:
332 EDIT_CopyToClipboard(hwnd);
333 EDIT_ClearSel(hwnd);
334 break;
336 case WM_CREATE:
337 lResult = EDIT_CreateMsg(hwnd, lParam);
338 break;
340 case WM_CUT:
341 EDIT_CopyToClipboard(hwnd);
342 EDIT_DeleteSel(hwnd);
343 break;
345 case WM_DESTROY:
346 EDIT_HeapFree(hwnd, es->hTextPtrs);
347 EDIT_HeapFree(hwnd, es->hCharWidths);
348 EDIT_HeapFree(hwnd, es->hText);
349 EDIT_HeapFree(hwnd, (HANDLE)(*(wndPtr->wExtra)));
350 break;
352 case WM_ENABLE:
353 InvalidateRect(hwnd, NULL, FALSE);
354 break;
356 case WM_GETTEXT:
357 textPtr = EDIT_HeapAddr(hwnd, es->hText);
358 if ((int)wParam > (len = strlen(textPtr)))
360 strcpy((char *)lParam, textPtr);
361 lResult = (DWORD)len ;
363 else
364 lResult = 0L;
365 break;
367 case WM_GETTEXTLENGTH:
368 textPtr = EDIT_HeapAddr(hwnd, es->hText);
369 lResult = (DWORD)strlen(textPtr);
370 break;
372 case WM_HSCROLL:
373 EDIT_HScrollMsg(hwnd, wParam, lParam);
374 break;
376 case WM_KEYDOWN:
377 EDIT_KeyDownMsg(hwnd, wParam);
378 break;
380 case WM_KILLFOCUS:
381 DestroyCaret();
382 NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
383 break;
385 case WM_LBUTTONDOWN:
386 HideCaret(hwnd);
387 SetFocus(hwnd);
388 EDIT_LButtonDownMsg(hwnd, wParam, lParam);
389 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
390 ShowCaret(hwnd);
391 break;
393 case WM_LBUTTONUP:
394 ButtonDown = FALSE;
395 if (TextMarking)
396 EDIT_StopMarking(hwnd);
397 break;
399 case WM_MOUSEMOVE:
400 HideCaret(hwnd);
401 EDIT_MouseMoveMsg(hwnd, wParam, lParam);
402 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
403 ShowCaret(hwnd);
404 break;
406 case WM_MOVE:
407 lResult = 0;
408 break;
410 case WM_NCCREATE:
411 lResult = EDIT_NCCreateMsg(hwnd, lParam);
412 break;
414 case WM_PAINT:
415 EDIT_PaintMsg(hwnd);
416 break;
418 case WM_PASTE:
419 EDIT_PasteMsg(hwnd);
420 break;
422 case WM_SETFOCUS:
423 CreateCaret(hwnd, 0, 2, es->txtht);
424 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
425 ShowCaret(hwnd);
426 NOTIFY_PARENT(hwnd, EN_SETFOCUS);
427 break;
429 case WM_SETFONT:
430 HideCaret(hwnd);
431 EDIT_SetFont(hwnd, wParam, lParam);
432 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
433 ShowCaret(hwnd);
434 break;
436 case WM_SETTEXT:
437 EDIT_SetTextMsg(hwnd, lParam);
438 break;
440 case WM_SIZE:
441 EDIT_SizeMsg(hwnd, wParam, lParam);
442 lResult = 0;
443 break;
445 case WM_VSCROLL:
446 EDIT_VScrollMsg(hwnd, wParam, lParam);
447 break;
449 default:
450 lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
451 break;
454 return lResult;
458 /*********************************************************************
459 * WM_NCCREATE message function
462 long EDIT_NCCreateMsg(HWND hwnd, LONG lParam)
464 CREATESTRUCT *createStruct = (CREATESTRUCT *)lParam;
465 WND *wndPtr = WIN_FindWndPtr(hwnd);
466 EDITSTATE *es;
467 unsigned int *textPtrs;
468 char *text;
469 int len;
471 /* store pointer to local or global heap in window structure so that */
472 /* EDITSTATE structure itself can be stored on local heap */
473 if (HEAP_LocalFindHeap(createStruct->hInstance)!=NULL)
474 (MDESC **)*(LONG *)(wndPtr->wExtra + 2) =
475 &HEAP_LocalFindHeap(createStruct->hInstance)->free_list;
476 else
478 (MDESC **)*(LONG *)(wndPtr->wExtra + 2) =
479 GlobalLock(createStruct->hInstance);
480 /* GlobalUnlock(createStruct->hInstance); */
482 /* allocate space for state variable structure */
483 (HANDLE)(*(wndPtr->wExtra)) = EDIT_HeapAlloc(hwnd, sizeof(EDITSTATE));
484 es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
485 es->hTextPtrs = EDIT_HeapAlloc(hwnd, sizeof(int));
486 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
487 es->hCharWidths = EDIT_HeapAlloc(hwnd, 256 * sizeof(short));
489 /* --- text buffer */
490 es->MaxTextLen = MAXTEXTLEN + 1;
491 if (!(createStruct->lpszName))
493 es->textlen = EditBufLen(wndPtr) + 1;
494 es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
495 text = EDIT_HeapAddr(hwnd, es->hText);
496 memset(text, 0, es->textlen + 2);
497 EDIT_ClearTextPointers(hwnd);
499 else
501 if (strlen(createStruct->lpszName) < EditBufLen(wndPtr))
503 es->textlen = EditBufLen(wndPtr) + 1;
504 es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
505 text = EDIT_HeapAddr(hwnd, es->hText);
506 strcpy(text, createStruct->lpszName);
507 *(text + es->textlen) = '\0';
509 else
511 es->hText = EDIT_HeapAlloc(hwnd,
512 strlen(createStruct->lpszName) + 2);
513 text = EDIT_HeapAddr(hwnd, es->hText);
514 strcpy(text, createStruct->lpszName);
515 es->textlen = strlen(createStruct->lpszName) + 1;
517 *(text + es->textlen + 1) = '\0';
518 EDIT_BuildTextPointers(hwnd);
521 if ((createStruct->style & WS_VSCROLL) ||
522 (createStruct->style & WS_HSCROLL)) NC_CreateScrollBars(hwnd);
524 /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
525 /* the corresponding WM_* message is set */
526 if (createStruct->style & WS_VSCROLL)
527 wndPtr->dwStyle |= ES_AUTOVSCROLL;
528 if (createStruct->style & WS_HSCROLL)
529 wndPtr->dwStyle |= ES_AUTOHSCROLL;
531 /* remove the WS_CAPTION style if it has been set - this is really a */
532 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
533 if (wndPtr->dwStyle & WS_BORDER && wndPtr->dwStyle & WS_DLGFRAME)
534 wndPtr->dwStyle ^= WS_DLGFRAME;
536 return 1;
540 /*********************************************************************
541 * WM_CREATE message function
544 long EDIT_CreateMsg(HWND hwnd, LONG lParam)
546 HDC hdc;
547 WND *wndPtr = WIN_FindWndPtr(hwnd);
548 EDITSTATE *es =
549 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
550 CLASS *classPtr;
551 short *charWidths;
552 TEXTMETRIC tm;
553 char *text;
555 /* initialize state variable structure */
556 /* --- char width array */
557 hdc = GetDC(hwnd);
558 charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
559 memset(charWidths, 0, 256 * sizeof(short));
560 GetCharWidth(hdc, 0, 255, charWidths);
562 /* --- other structure variables */
563 GetTextMetrics(hdc, &tm);
564 es->txtht = tm.tmHeight + tm.tmExternalLeading;
565 es->wlines = 0;
566 es->wtop = es->wleft = 0;
567 es->CurrCol = es->CurrLine = 0;
568 es->WndCol = es->WndRow = 0;
569 es->TextChanged = FALSE;
570 es->textwidth = 0;
571 es->SelBegLine = es->SelBegCol = 0;
572 es->SelEndLine = es->SelEndCol = 0;
573 es->hFont = 0;
574 es->hDeletedText = 0;
575 es->DeletedLength = 0;
576 es->NumTabStops = 0;
577 es->hTabStops = EDIT_HeapAlloc(hwnd, sizeof(int));
579 /* allocate space for a line full of blanks to speed up */
580 /* line filling */
581 es->hBlankLine = EDIT_HeapAlloc(hwnd, (ClientWidth(wndPtr) /
582 charWidths[32]) + 2);
583 text = EDIT_HeapAddr(hwnd, es->hBlankLine);
584 memset(text, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
586 /* set up text cursor for edit class */
587 CLASS_FindClassByName("EDIT", &classPtr);
588 classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);
590 /* paint background on first WM_PAINT */
591 es->PaintBkgd = TRUE;
593 ReleaseDC(hwnd, hdc);
594 return 0L;
598 /*********************************************************************
599 * EDIT_ClearTextPointers
601 * Clear and initialize text line pointer array.
604 void EDIT_ClearTextPointers(HWND hwnd)
606 unsigned int *textPtrs;
607 WND *wndPtr = WIN_FindWndPtr(hwnd);
608 EDITSTATE *es =
609 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
611 es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs, sizeof(int));
612 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
613 *textPtrs = 0;
617 /*********************************************************************
618 * EDIT_BuildTextPointers
620 * Build array of pointers to text lines.
623 #define INITLINES 100
625 void EDIT_BuildTextPointers(HWND hwnd)
627 WND *wndPtr = WIN_FindWndPtr(hwnd);
628 char *text, *cp;
629 int incrs = INITLINES;
630 unsigned int off, len, temp;
631 EDITSTATE *es;
632 unsigned int *textPtrs;
633 short *charWidths;
635 es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
636 text = EDIT_HeapAddr(hwnd, es->hText);
637 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
638 charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
640 es->textwidth = es->wlines = 0;
641 cp = text;
643 /* advance through text buffer */
644 while (*cp)
646 /* increase size of text pointer array */
647 if (incrs == INITLINES)
649 incrs = 0;
650 es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs,
651 (es->wlines + INITLINES) * sizeof(int));
652 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
654 off = (unsigned int)(cp - text); /* offset of beginning of line */
655 *(textPtrs + es->wlines) = off;
656 es->wlines++;
657 incrs++;
658 len = 0;
660 /* advance through current line */
661 while (*cp && *cp != '\n')
663 len += EDIT_CharWidth(hwnd, (BYTE)*cp, len);
664 /* width of line in pixels */
665 cp++;
667 es->textwidth = max(es->textwidth, len);
668 if (*cp)
669 cp++; /* skip '\n' */
672 off = (unsigned int)(cp - text);
673 *(textPtrs + es->wlines) = off;
677 /*********************************************************************
678 * EDIT_ModTextPointers
680 * Modify text pointers from a specified position.
683 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
685 WND *wndPtr = WIN_FindWndPtr(hwnd);
686 EDITSTATE *es =
687 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
688 unsigned int *textPtrs =
689 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
691 while (lineno < es->wlines)
692 *(textPtrs + lineno++) += var;
696 /*********************************************************************
697 * WM_PAINT message function
700 void EDIT_PaintMsg(HWND hwnd)
702 PAINTSTRUCT ps;
703 HDC hdc;
704 int y;
705 RECT rc;
706 WND *wndPtr = WIN_FindWndPtr(hwnd);
707 EDITSTATE *es =
708 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
710 hdc = BeginPaint(hwnd, &ps);
711 rc = ps.rcPaint;
713 dprintf_edit(stddeb,"WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc.left, rc.top,
714 rc.right, rc.bottom);
716 if (es->PaintBkgd)
717 FillWindow(GetParent(hwnd), hwnd, hdc, CTLCOLOR_EDIT);
719 for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
721 if (y < es->wlines - es->wtop)
722 EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
725 EndPaint(hwnd, &ps);
729 /*********************************************************************
730 * EDIT_GetTextLine
732 * Get a copy of the text in the specified line.
735 HANDLE EDIT_GetTextLine(HWND hwnd, int selection)
737 char *line;
738 HANDLE hLine;
739 int len = 0;
740 char *cp, *cp1;
742 dprintf_edit(stddeb,"GetTextLine %d\n", selection);
743 cp = cp1 = EDIT_TextLine(hwnd, selection);
744 /* advance through line */
745 while (*cp && *cp != '\n')
747 len++;
748 cp++;
751 /* store selected line and return handle */
752 hLine = EDIT_HeapAlloc(hwnd, len + 6);
753 line = (char *)EDIT_HeapAddr(hwnd, hLine);
754 memmove(line, cp1, len);
755 line[len] = '\0';
756 return hLine;
760 /*********************************************************************
761 * EDIT_TextLine
763 * Return a pointer to the text in the specified line.
766 char *EDIT_TextLine(HWND hwnd, int sel)
768 WND *wndPtr = WIN_FindWndPtr(hwnd);
769 EDITSTATE *es =
770 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
771 char *text = EDIT_HeapAddr(hwnd, es->hText);
772 unsigned int *textPtrs =
773 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
775 return (text + *(textPtrs + sel));
779 /*********************************************************************
780 * EDIT_StrLength
782 * Return length of string _str_ of length _len_ characters in pixels.
783 * The current column offset in pixels _pcol_ is required to calculate
784 * the width of a tab.
787 int EDIT_StrLength(HWND hwnd, char *str, int len, int pcol)
789 int i, plen = 0;
790 WND *wndPtr = WIN_FindWndPtr(hwnd);
791 EDITSTATE *es =
792 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
794 for (i = 0; i < len; i++)
795 plen += EDIT_CharWidth(hwnd, (BYTE)(*(str + i)), pcol + plen);
797 dprintf_edit(stddeb,"EDIT_StrLength: returning %d\n", plen);
798 return plen;
802 /*********************************************************************
803 * EDIT_LineLength
805 * Return length of line _num_ in characters.
808 int EDIT_LineLength(HWND hwnd, int num)
810 WND *wndPtr = WIN_FindWndPtr(hwnd);
811 EDITSTATE *es =
812 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
813 char *cp = EDIT_TextLine(hwnd, num);
814 char *cp1;
816 cp1 = strchr(cp, '\n');
817 return cp1 ? (int)(cp1 - cp) : strlen(cp);
821 /*********************************************************************
822 * EDIT_WriteTextLine
824 * Write the line of text at offset _y_ in text buffer to a window.
827 void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
829 int len = 0;
830 unsigned char line[200];
831 HANDLE hLine;
832 unsigned char *lp;
833 int lnlen, lnlen1;
834 int col, off = 0;
835 int sbl, sel, sbc, sec;
836 RECT rc;
837 BOOL trunc = FALSE;
838 WND *wndPtr = WIN_FindWndPtr(hwnd);
839 EDITSTATE *es =
840 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
842 /* initialize rectangle if NULL, else copy */
843 if (rect)
844 CopyRect(&rc, rect);
845 else
846 GetClientRect(hwnd, &rc);
848 dprintf_edit(stddeb,"WriteTextLine %d\n", y);
850 /* make sure y is inside the window */
851 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
853 dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
854 return;
857 /* make sure rectangle is within window */
858 if (rc.left >= ClientWidth(wndPtr) - 1)
860 dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
861 rc.left);
862 return;
864 if (rc.right <= 0)
866 dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
867 rc.right);
868 return;
870 if (y - es->wtop < (rc.top / es->txtht) ||
871 y - es->wtop > (rc.bottom / es->txtht))
873 dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is outside window\n", y);
874 return;
877 /* get the text and length of line */
878 if ((hLine = EDIT_GetTextLine(hwnd, y)) == 0)
879 return;
880 lp = (unsigned char *)EDIT_HeapAddr(hwnd, hLine);
881 lnlen = EDIT_StrLength(hwnd, lp, strlen(lp), 0);
882 lnlen1 = lnlen;
884 /* build the line to display */
885 if (lnlen < es->wleft)
886 lnlen = 0;
887 else
888 off += es->wleft;
890 if (lnlen > rc.left)
892 off += rc.left;
893 lnlen = lnlen1 - off;
894 len = min(lnlen, rc.right - rc.left);
897 if (SelMarked(es))
899 sbl = es->SelBegLine;
900 sel = es->SelEndLine;
901 sbc = es->SelBegCol;
902 sec = es->SelEndCol;
904 /* put lowest marker first */
905 if (sbl > sel)
907 swap(&sbl, &sel);
908 swap(&sbc, &sec);
910 if (sbl == sel && sbc > sec)
911 swap(&sbc, &sec);
913 if (y < sbl || y > sel)
914 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
915 TRUE, FALSE);
916 else if (y > sbl && y < sel)
917 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
918 TRUE, TRUE);
919 else if (y == sbl)
921 col = EDIT_StrLength(hwnd, lp, sbc, 0);
922 if (col > (es->wleft + rc.left))
924 len = min(col - off, rc.right - off);
925 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
926 rc.left, &rc, FALSE, FALSE);
927 off = col;
929 if (y == sel)
931 col = EDIT_StrLength(hwnd, lp, sec, 0);
932 if (col < (es->wleft + rc.right))
934 len = min(col - off, rc.right - off);
935 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
936 off - es->wleft, &rc, FALSE, TRUE);
937 off = col;
938 len = min(lnlen - off, rc.right - off);
939 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
940 off - es->wleft, &rc, TRUE, FALSE);
942 else
944 len = min(lnlen - off, rc.right - off);
945 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
946 off - es->wleft, &rc, TRUE, TRUE);
949 else
951 len = min(lnlen - off, rc.right - off);
952 if (col < (es->wleft + rc.right))
953 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
954 off - es->wleft, &rc, TRUE, TRUE);
957 else if (y == sel)
959 col = EDIT_StrLength(hwnd, lp, sec, 0);
960 if (col < (es->wleft + rc.right))
962 len = min(col - off, rc.right - off);
963 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
964 off - es->wleft, &rc, FALSE, TRUE);
965 off = col;
966 len = min(lnlen - off, rc.right - off);
967 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
968 off - es->wleft, &rc, TRUE, FALSE);
972 else
973 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
974 TRUE, FALSE);
976 EDIT_HeapFree(hwnd, hLine);
980 /*********************************************************************
981 * EDIT_WriteText
983 * Write text to a window
984 * lp - text line
985 * off - offset in text line (in pixels)
986 * len - length from off (in pixels)
987 * row - line in window
988 * col - column in window
989 * rc - rectangle in which to display line
990 * blank - blank remainder of line?
991 * reverse - reverse color of line?
994 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
995 int col, RECT *rc, BOOL blank, BOOL reverse)
997 HDC hdc;
998 HANDLE hStr;
999 char *str, *cp, *cp1;
1000 int diff, num_spaces, tabwidth, scol;
1001 HRGN hrgnClip;
1002 COLORREF oldTextColor, oldBkgdColor;
1003 HFONT oldfont;
1004 WND *wndPtr = WIN_FindWndPtr(hwnd);
1005 EDITSTATE *es =
1006 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1007 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
1008 char *blanks = (char *)EDIT_HeapAddr(hwnd, es->hBlankLine);
1010 dprintf_edit(stddeb,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
1012 hdc = GetDC(hwnd);
1013 hStr = EDIT_GetStr(hwnd, lp, off, len, &diff);
1014 str = (char *)EDIT_HeapAddr(hwnd, hStr);
1015 hrgnClip = CreateRectRgnIndirect(rc);
1016 SelectClipRgn(hdc, hrgnClip);
1018 if (es->hFont)
1019 oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
1021 SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
1022 MAKELPARAM(hwnd, CTLCOLOR_EDIT));
1024 if (reverse)
1026 oldBkgdColor = GetBkColor(hdc);
1027 oldTextColor = GetTextColor(hdc);
1028 SetBkColor(hdc, oldTextColor);
1029 SetTextColor(hdc, oldBkgdColor);
1032 if (strlen(blanks) < (ClientWidth(wndPtr) / charWidths[32]) + 2)
1034 es->hBlankLine = EDIT_HeapReAlloc(hwnd, es->hBlankLine,
1035 (ClientWidth(wndPtr) / charWidths[32]) + 2);
1036 blanks = EDIT_HeapAddr(hwnd, es->hBlankLine);
1037 memset(blanks, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
1040 if (!(cp = strchr(str, VK_TAB)))
1041 TextOut(hdc, col - diff, row * es->txtht, str, strlen(str));
1042 else
1044 TextOut(hdc, col - diff, row * es->txtht, str, (int)(cp - str));
1045 scol = EDIT_StrLength(hwnd, str, (int)(cp - str), 0);
1046 tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
1047 num_spaces = tabwidth / charWidths[32] + 1;
1048 TextOut(hdc, scol, row * es->txtht, blanks, num_spaces);
1049 cp++;
1050 scol += tabwidth;
1052 while (cp1 = strchr(cp, VK_TAB))
1054 TextOut(hdc, scol, row * es->txtht, cp, (int)(cp1 - cp));
1055 scol += EDIT_StrLength(hwnd, cp, (int)(cp1 - cp), scol);
1056 tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
1057 num_spaces = tabwidth / charWidths[32] + 1;
1058 TextOut(hdc, scol, row * es->txtht, blanks, num_spaces);
1059 cp = ++cp1;
1060 scol += tabwidth;
1063 TextOut(hdc, scol, row * es->txtht, cp, strlen(cp));
1066 if (reverse)
1068 SetBkColor(hdc, oldBkgdColor);
1069 SetTextColor(hdc, oldTextColor);
1072 /* blank out remainder of line if appropriate */
1073 if (blank)
1075 if ((rc->right - col) > len)
1077 num_spaces = (rc->right - col - len) / charWidths[32];
1078 TextOut(hdc, col + len, row * es->txtht, blanks, num_spaces);
1082 if (es->hFont)
1083 SelectObject(hdc, (HANDLE)oldfont);
1085 EDIT_HeapFree(hwnd, hStr);
1086 ReleaseDC(hwnd, hdc);
1090 /*********************************************************************
1091 * EDIT_GetStr
1093 * Return sub-string starting at pixel _off_ of length _len_ pixels.
1094 * If _off_ is part way through a character, the negative offset of
1095 * the beginning of the character is returned in _diff_, else _diff_
1096 * will be zero.
1099 HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff)
1101 HANDLE hStr;
1102 char *str;
1103 int ch = 0, i = 0, j, s_i;
1104 int ch1;
1105 WND *wndPtr = WIN_FindWndPtr(hwnd);
1106 EDITSTATE *es =
1107 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1109 dprintf_edit(stddeb,"EDIT_GetStr %s %d %d\n", lp, off, len);
1111 while (i < off)
1113 s_i = i;
1114 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
1115 ch++;
1118 /* if stepped past _off_, go back a character */
1119 if (i - off)
1121 i = s_i;
1122 ch--;
1124 *diff = off - i;
1125 ch1 = ch;
1127 while (i < len + off)
1129 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
1130 ch++;
1133 hStr = EDIT_HeapAlloc(hwnd, ch - ch1 + 3);
1134 str = (char *)EDIT_HeapAddr(hwnd, hStr);
1135 for (i = ch1, j = 0; i < ch; i++, j++)
1136 str[j] = lp[i];
1137 str[++j] = '\0';
1138 dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str);
1139 return hStr;
1143 /*********************************************************************
1144 * WM_CHAR message function
1147 void EDIT_CharMsg(HWND hwnd, WORD wParam)
1149 WND *wndPtr = WIN_FindWndPtr(hwnd);
1150 EDITSTATE *es =
1151 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1153 dprintf_edit(stddeb,"EDIT_CharMsg: wParam=%c\n", (char)wParam);
1155 switch (wParam)
1157 case '\r':
1158 case '\n':
1159 if (!IsMultiLine())
1160 break;
1161 wParam = '\n';
1162 EDIT_KeyTyped(hwnd, wParam);
1163 break;
1165 case VK_TAB:
1166 if (!IsMultiLine())
1167 break;
1168 EDIT_KeyTyped(hwnd, wParam);
1169 break;
1171 default:
1172 if (wParam >= 20 && wParam <= 126)
1173 EDIT_KeyTyped(hwnd, wParam);
1174 break;
1179 /*********************************************************************
1180 * EDIT_KeyTyped
1182 * Process keystrokes that produce displayable characters.
1185 void EDIT_KeyTyped(HWND hwnd, short ch)
1187 WND *wndPtr = WIN_FindWndPtr(hwnd);
1188 EDITSTATE *es =
1189 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1190 char *text = EDIT_HeapAddr(hwnd, es->hText);
1191 char *currchar = CurrChar;
1192 RECT rc;
1193 BOOL FullPaint = FALSE;
1195 dprintf_edit(stddeb,"EDIT_KeyTyped: ch=%c\n", (char)ch);
1197 /* delete selected text (if any) */
1198 if (SelMarked(es))
1199 EDIT_DeleteSel(hwnd);
1201 /* test for typing at end of maximum buffer size */
1202 if (currchar == text + es->MaxTextLen)
1204 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1205 return;
1208 if (*currchar == '\0' && IsMultiLine())
1210 /* insert a newline at end of text */
1211 *currchar = '\n';
1212 *(currchar + 1) = '\0';
1213 EDIT_BuildTextPointers(hwnd);
1216 /* insert the typed character */
1217 if (text[es->textlen - 1] != '\0')
1219 /* current text buffer is full */
1220 if (es->textlen == es->MaxTextLen)
1222 /* text buffer is at maximum size */
1223 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1224 return;
1227 /* increase the text buffer size */
1228 es->textlen += GROWLENGTH;
1229 /* but not above maximum size */
1230 if (es->textlen > es->MaxTextLen)
1231 es->textlen = es->MaxTextLen;
1232 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + 2);
1233 if (!es->hText)
1234 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1235 text = EDIT_HeapAddr(hwnd, es->hText);
1236 text[es->textlen - 1] = '\0';
1237 currchar = CurrChar;
1239 /* make space for new character and put char in buffer */
1240 memmove(currchar + 1, currchar, strlen(currchar) + 1);
1241 *currchar = ch;
1242 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
1243 es->TextChanged = TRUE;
1244 NOTIFY_PARENT(hwnd, EN_UPDATE);
1246 /* re-adjust textwidth, if necessary, and redraw line */
1247 HideCaret(hwnd);
1248 if (IsMultiLine() && es->wlines > 1)
1250 es->textwidth = max(es->textwidth,
1251 EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
1252 (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) -
1253 EDIT_TextLine(hwnd, es->CurrLine)), 0));
1255 else
1256 es->textwidth = max(es->textwidth,
1257 EDIT_StrLength(hwnd, text, strlen(text), 0));
1258 EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
1260 if (ch == '\n')
1262 if (es->wleft > 0)
1263 FullPaint = TRUE;
1264 es->wleft = 0;
1265 EDIT_BuildTextPointers(hwnd);
1266 EDIT_End(hwnd);
1267 EDIT_Forward(hwnd);
1269 /* invalidate rest of window */
1270 GetClientRect(hwnd, &rc);
1271 if (!FullPaint)
1272 rc.top = es->WndRow * es->txtht;
1273 InvalidateRect(hwnd, &rc, FALSE);
1275 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1276 ShowCaret(hwnd);
1277 UpdateWindow(hwnd);
1278 NOTIFY_PARENT(hwnd, EN_CHANGE);
1279 return;
1282 /* test end of window */
1283 if (es->WndCol >= ClientWidth(wndPtr) -
1284 EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft))
1286 /* TODO:- Word wrap to be handled here */
1288 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1289 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1291 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft);
1292 es->CurrCol++;
1293 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1294 ShowCaret(hwnd);
1295 NOTIFY_PARENT(hwnd, EN_CHANGE);
1299 /*********************************************************************
1300 * EDIT_CharWidth
1302 * Return the width of the given character in pixels.
1303 * The current column offset in pixels _pcol_ is required to calculate
1304 * the width of a tab.
1307 int EDIT_CharWidth(HWND hwnd, short ch, int pcol)
1309 WND *wndPtr = WIN_FindWndPtr(hwnd);
1310 EDITSTATE *es =
1311 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1312 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
1314 if (ch != VK_TAB)
1315 return (charWidths[ch]);
1316 else
1317 return (EDIT_GetNextTabStop(hwnd, pcol) - pcol);
1321 /*********************************************************************
1322 * EDIT_GetNextTabStop
1324 * Return the next tab stop beyond _pcol_.
1327 int EDIT_GetNextTabStop(HWND hwnd, int pcol)
1329 int i, tmp;
1330 int baseUnitWidth = LOWORD(GetDialogBaseUnits());
1331 WND *wndPtr = WIN_FindWndPtr(hwnd);
1332 EDITSTATE *es =
1333 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1334 unsigned short *tabstops = EDIT_HeapAddr(hwnd, es->hTabStops);
1336 if (es->NumTabStops == 0)
1337 return ROUNDUP(pcol, 8 * baseUnitWidth);
1338 else if (es->NumTabStops == 1)
1339 return ROUNDUP(pcol, *tabstops * baseUnitWidth / 4);
1340 else
1342 for (i = 0; i < es->NumTabStops; i++)
1344 if (*(tabstops + i) * baseUnitWidth / 4 >= pcol)
1345 return (*(tabstops + i) * baseUnitWidth / 4);
1347 return pcol;
1352 /*********************************************************************
1353 * EDIT_Forward
1355 * Cursor right key: move right one character position.
1358 void EDIT_Forward(HWND hwnd)
1360 WND *wndPtr = WIN_FindWndPtr(hwnd);
1361 EDITSTATE *es =
1362 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1363 char *text = EDIT_HeapAddr(hwnd, es->hText);
1365 if (*CurrChar == '\0')
1366 return;
1368 if (*CurrChar == '\n')
1370 EDIT_Home(hwnd);
1371 EDIT_Downward(hwnd);
1373 else
1375 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
1376 es->CurrCol++;
1377 if (es->WndCol >= ClientWidth(wndPtr))
1378 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1384 /*********************************************************************
1385 * EDIT_Downward
1387 * Cursor down key: move down one line.
1390 void EDIT_Downward(HWND hwnd)
1392 WND *wndPtr = WIN_FindWndPtr(hwnd);
1393 EDITSTATE *es =
1394 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1396 dprintf_edit(stddeb,"EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n",
1397 es->WndRow, es->wtop, es->wlines);
1399 if (IsMultiLine() && (es->WndRow + es->wtop + 1 < es->wlines))
1401 es->CurrLine++;
1402 if (es->WndRow == ClientHeight(wndPtr, es) - 1)
1404 es->WndRow++;
1405 EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
1407 else
1408 es->WndRow++;
1409 EDIT_StickEnd(hwnd);
1414 /*********************************************************************
1415 * EDIT_Upward
1417 * Cursor up key: move up one line.
1420 void EDIT_Upward(HWND hwnd)
1422 WND *wndPtr = WIN_FindWndPtr(hwnd);
1423 EDITSTATE *es =
1424 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1426 if (IsMultiLine() && es->CurrLine != 0)
1428 --es->CurrLine;
1429 if (es->WndRow == 0)
1431 --es->WndRow;
1432 EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
1434 else
1435 --es->WndRow;
1436 EDIT_StickEnd(hwnd);
1441 /*********************************************************************
1442 * EDIT_Backward
1444 * Cursor left key: move left one character position.
1447 void EDIT_Backward(HWND hwnd)
1449 WND *wndPtr = WIN_FindWndPtr(hwnd);
1450 EDITSTATE *es =
1451 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1452 char *text = EDIT_HeapAddr(hwnd, es->hText);
1454 if (es->CurrCol)
1456 --es->CurrCol;
1457 if (*CurrChar == VK_TAB)
1458 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar),
1459 EDIT_StrLength(hwnd,
1460 EDIT_TextLine(hwnd, es->CurrLine),
1461 es->CurrCol, 0));
1462 else
1463 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), 0);
1464 if (es->WndCol < 0)
1465 EDIT_KeyHScroll(hwnd, SB_LINEUP);
1467 else if (IsMultiLine() && es->CurrLine != 0)
1469 EDIT_Upward(hwnd);
1470 EDIT_End(hwnd);
1475 /*********************************************************************
1476 * EDIT_End
1478 * End key: move to end of line.
1481 void EDIT_End(HWND hwnd)
1483 RECT rc;
1484 WND *wndPtr = WIN_FindWndPtr(hwnd);
1485 EDITSTATE *es =
1486 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1487 char *text = EDIT_HeapAddr(hwnd, es->hText);
1489 while (*CurrChar && *CurrChar != '\n')
1491 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
1492 es->CurrCol++;
1495 if (es->WndCol >= ClientWidth(wndPtr))
1497 es->wleft = es->WndCol - ClientWidth(wndPtr) + HSCROLLDIM;
1498 es->WndCol -= es->wleft;
1499 InvalidateRect(hwnd, NULL, FALSE);
1500 UpdateWindow(hwnd);
1505 /*********************************************************************
1506 * EDIT_Home
1508 * Home key: move to beginning of line.
1511 void EDIT_Home(HWND hwnd)
1513 RECT rc;
1514 WND *wndPtr = WIN_FindWndPtr(hwnd);
1515 EDITSTATE *es =
1516 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1518 es->CurrCol = es->WndCol = 0;
1519 if (es->wleft != 0)
1521 es->wleft = 0;
1522 InvalidateRect(hwnd, NULL, FALSE);
1523 UpdateWindow(hwnd);
1528 /*********************************************************************
1529 * EDIT_StickEnd
1531 * Stick the cursor to the end of the line.
1534 void EDIT_StickEnd(HWND hwnd)
1536 WND *wndPtr = WIN_FindWndPtr(hwnd);
1537 EDITSTATE *es =
1538 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1539 int len = EDIT_LineLength(hwnd, es->CurrLine);
1540 char *cp = EDIT_TextLine(hwnd, es->CurrLine);
1541 char currpel;
1543 es->CurrCol = min(len, es->CurrCol);
1544 es->WndCol = min(EDIT_StrLength(hwnd, cp, len, 0) - es->wleft, es->WndCol);
1545 currpel = EDIT_StrLength(hwnd, cp, es->CurrCol, 0);
1547 if (es->wleft > currpel)
1549 es->wleft = max(0, currpel - 20);
1550 es->WndCol = currpel - es->wleft;
1551 UpdateWindow(hwnd);
1553 else if (currpel - es->wleft >= ClientWidth(wndPtr))
1555 es->wleft = currpel - (ClientWidth(wndPtr) - 5);
1556 es->WndCol = currpel - es->wleft;
1557 UpdateWindow(hwnd);
1562 /*********************************************************************
1563 * WM_KEYDOWN message function
1566 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam)
1568 WND *wndPtr = WIN_FindWndPtr(hwnd);
1569 EDITSTATE *es =
1570 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1572 dprintf_edit(stddeb,"EDIT_KeyDownMsg: key=%x\n", wParam);
1574 HideCaret(hwnd);
1575 switch (wParam)
1577 case VK_UP:
1578 if (SelMarked(es))
1579 EDIT_ClearSel(hwnd);
1580 if (IsMultiLine())
1581 EDIT_Upward(hwnd);
1582 else
1583 EDIT_Backward(hwnd);
1584 break;
1586 case VK_DOWN:
1587 if (SelMarked(es))
1588 EDIT_ClearSel(hwnd);
1589 if (IsMultiLine())
1590 EDIT_Downward(hwnd);
1591 else
1592 EDIT_Forward(hwnd);
1593 break;
1595 case VK_RIGHT:
1596 if (SelMarked(es))
1597 EDIT_ClearSel(hwnd);
1598 EDIT_Forward(hwnd);
1599 break;
1601 case VK_LEFT:
1602 if (SelMarked(es))
1603 EDIT_ClearSel(hwnd);
1604 EDIT_Backward(hwnd);
1605 break;
1607 case VK_HOME:
1608 if (SelMarked(es))
1609 EDIT_ClearSel(hwnd);
1610 EDIT_Home(hwnd);
1611 break;
1613 case VK_END:
1614 if (SelMarked(es))
1615 EDIT_ClearSel(hwnd);
1616 EDIT_End(hwnd);
1617 break;
1619 case VK_PRIOR:
1620 if (IsMultiLine())
1622 if (SelMarked(es))
1623 EDIT_ClearSel(hwnd);
1624 EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
1626 break;
1628 case VK_NEXT:
1629 if (IsMultiLine())
1631 if (SelMarked(es))
1632 EDIT_ClearSel(hwnd);
1633 EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
1635 break;
1637 case VK_BACK:
1638 if (SelMarked(es))
1639 EDIT_DeleteSel(hwnd);
1640 else
1642 if (es->CurrCol == 0 && es->CurrLine == 0)
1643 break;
1644 EDIT_Backward(hwnd);
1645 EDIT_DelKey(hwnd);
1647 break;
1649 case VK_DELETE:
1650 if (SelMarked(es))
1651 EDIT_DeleteSel(hwnd);
1652 else
1653 EDIT_DelKey(hwnd);
1654 break;
1657 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1658 ShowCaret(hwnd);
1662 /*********************************************************************
1663 * EDIT_KeyHScroll
1665 * Scroll text horizontally using cursor keys.
1668 void EDIT_KeyHScroll(HWND hwnd, WORD opt)
1670 RECT rc;
1671 int hscrollpos;
1672 WND *wndPtr = WIN_FindWndPtr(hwnd);
1673 EDITSTATE *es =
1674 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1676 if (opt == SB_LINEDOWN)
1678 es->wleft += HSCROLLDIM;
1679 es->WndCol -= HSCROLLDIM;
1681 else
1683 if (es->wleft == 0)
1684 return;
1685 if (es->wleft - HSCROLLDIM < 0)
1687 es->WndCol += es->wleft;
1688 es->wleft = 0;
1690 else
1692 es->wleft -= HSCROLLDIM;
1693 es->WndCol += HSCROLLDIM;
1697 InvalidateRect(hwnd, NULL, FALSE);
1698 UpdateWindow(hwnd);
1700 if (IsHScrollBar())
1702 hscrollpos = EDIT_ComputeHScrollPos(hwnd);
1703 SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE);
1708 /*********************************************************************
1709 * EDIT_KeyVScrollLine
1711 * Scroll text vertically by one line using keyboard.
1714 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt)
1716 RECT rc;
1717 int y, vscrollpos;
1718 WND *wndPtr = WIN_FindWndPtr(hwnd);
1719 EDITSTATE *es =
1720 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1722 if (!IsMultiLine())
1723 return;
1725 if (opt == SB_LINEDOWN)
1727 /* move down one line */
1728 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1729 return;
1730 es->wtop++;
1732 else
1734 /* move up one line */
1735 if (es->wtop == 0)
1736 return;
1737 --es->wtop;
1740 if (IsWindowVisible(hwnd))
1742 /* adjust client bottom to nearest whole line */
1743 GetClientRect(hwnd, &rc);
1744 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1746 if (opt == SB_LINEUP)
1748 /* move up one line (scroll window down) */
1749 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1750 /* write top line */
1751 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1752 es->WndRow++;
1754 else
1756 /* move down one line (scroll window up) */
1757 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1758 /* write bottom line */
1759 y = (((rc.bottom - rc.top) / es->txtht) - 1);
1760 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1761 --es->WndRow;
1765 /* reset the vertical scroll bar */
1766 if (IsVScrollBar())
1768 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1769 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1774 /*********************************************************************
1775 * EDIT_KeyVScrollPage
1777 * Scroll text vertically by one page using keyboard.
1780 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
1782 RECT rc;
1783 int vscrollpos;
1784 WND *wndPtr = WIN_FindWndPtr(hwnd);
1785 EDITSTATE *es =
1786 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1788 if (IsMultiLine())
1790 if (opt == SB_PAGEUP)
1792 if (es->wtop)
1793 es->wtop -= ClientHeight(wndPtr, es);
1795 else
1797 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1799 es->wtop += ClientHeight(wndPtr, es);
1800 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1801 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1804 if (es->wtop < 0)
1805 es->wtop = 0;
1807 es->CurrLine = es->wtop + es->WndRow;
1808 EDIT_StickEnd(hwnd);
1809 InvalidateRect(hwnd, NULL, TRUE);
1810 UpdateWindow(hwnd);
1812 /* reset the vertical scroll bar */
1813 if (IsVScrollBar())
1815 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1816 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1822 /*********************************************************************
1823 * EDIT_KeyVScrollDoc
1825 * Scroll text to top and bottom of document using keyboard.
1828 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt)
1830 RECT rc;
1831 int vscrollpos;
1832 WND *wndPtr = WIN_FindWndPtr(hwnd);
1833 EDITSTATE *es =
1834 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1836 if (!IsMultiLine())
1837 return;
1839 if (opt == SB_TOP)
1840 es->wtop = es->wleft = 0;
1841 else if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1843 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1844 es->wleft = 0;
1847 es->CurrLine = es->wlines;
1848 es->WndRow = es->wlines - es->wtop;
1849 EDIT_End(hwnd);
1850 InvalidateRect(hwnd, NULL, TRUE);
1851 UpdateWindow(hwnd);
1853 /* reset the vertical scroll bar */
1854 if (IsVScrollBar())
1856 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1857 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1862 /*********************************************************************
1863 * EDIT_ComputeVScrollPos
1865 * Compute the vertical scroll bar position from the window
1866 * position and text width.
1869 int EDIT_ComputeVScrollPos(HWND hwnd)
1871 int vscrollpos;
1872 short minpos, maxpos;
1873 WND *wndPtr = WIN_FindWndPtr(hwnd);
1874 EDITSTATE *es =
1875 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1877 GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos);
1879 if (es->wlines > ClientHeight(wndPtr, es))
1880 vscrollpos = (double)(es->wtop) / (double)(es->wlines -
1881 ClientHeight(wndPtr, es)) * (maxpos - minpos);
1882 else
1883 vscrollpos = minpos;
1885 return vscrollpos;
1889 /*********************************************************************
1890 * EDIT_ComputeHScrollPos
1892 * Compute the horizontal scroll bar position from the window
1893 * position and text width.
1896 int EDIT_ComputeHScrollPos(HWND hwnd)
1898 int hscrollpos;
1899 short minpos, maxpos;
1900 WND *wndPtr = WIN_FindWndPtr(hwnd);
1901 EDITSTATE *es =
1902 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1904 GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos);
1906 if (es->textwidth > ClientWidth(wndPtr))
1907 hscrollpos = (double)(es->wleft) / (double)(es->textwidth -
1908 ClientWidth(wndPtr)) * (maxpos - minpos);
1909 else
1910 hscrollpos = minpos;
1912 return hscrollpos;
1916 /*********************************************************************
1917 * EDIT_DelKey
1919 * Delete character to right of cursor.
1922 void EDIT_DelKey(HWND hwnd)
1924 RECT rc;
1925 WND *wndPtr = WIN_FindWndPtr(hwnd);
1926 EDITSTATE *es =
1927 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1928 char *currchar = CurrChar;
1929 BOOL repaint = *currchar == '\n';
1931 if (IsMultiLine() && *currchar == '\n' && *(currchar + 1) == '\0')
1932 return;
1933 strcpy(currchar, currchar + 1);
1934 NOTIFY_PARENT(hwnd, EN_UPDATE);
1936 if (repaint)
1938 EDIT_BuildTextPointers(hwnd);
1939 GetClientRect(hwnd, &rc);
1940 rc.top = es->WndRow * es->txtht;
1941 InvalidateRect(hwnd, &rc, FALSE);
1942 UpdateWindow(hwnd);
1944 else
1946 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1);
1947 EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop);
1950 es->TextChanged = TRUE;
1951 NOTIFY_PARENT(hwnd, EN_CHANGE);
1954 /*********************************************************************
1955 * WM_VSCROLL message function
1958 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1960 WND *wndPtr = WIN_FindWndPtr(hwnd);
1961 EDITSTATE *es =
1962 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1964 if (IsMultiLine())
1966 HideCaret(hwnd);
1968 switch (wParam)
1970 case SB_LINEUP:
1971 case SB_LINEDOWN:
1972 EDIT_VScrollLine(hwnd, wParam);
1973 break;
1975 case SB_PAGEUP:
1976 case SB_PAGEDOWN:
1977 EDIT_VScrollPage(hwnd, wParam);
1978 break;
1982 SetCaretPos(es->WndCol, es->WndRow);
1983 ShowCaret(hwnd);
1987 /*********************************************************************
1988 * EDIT_VScrollLine
1990 * Scroll text vertically by one line using scrollbars.
1993 void EDIT_VScrollLine(HWND hwnd, WORD opt)
1995 RECT rc;
1996 int y;
1997 WND *wndPtr = WIN_FindWndPtr(hwnd);
1998 EDITSTATE *es =
1999 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2001 dprintf_edit(stddeb,"EDIT_VScrollLine: direction=%d\n", opt);
2003 if (opt == SB_LINEDOWN)
2005 /* move down one line */
2006 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
2007 return;
2008 es->wtop++;
2010 else
2012 /* move up one line */
2013 if (es->wtop == 0)
2014 return;
2015 --es->wtop;
2018 if (IsWindowVisible(hwnd))
2020 /* adjust client bottom to nearest whole line */
2021 GetClientRect(hwnd, &rc);
2022 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
2024 if (opt == SB_LINEUP)
2026 /* move up one line (scroll window down) */
2027 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
2028 /* write top line */
2029 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
2030 es->WndRow++;
2032 else
2034 /* move down one line (scroll window up) */
2035 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
2036 /* write bottom line */
2037 y = ((rc.bottom - rc.top / es->txtht) - 1);
2038 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
2039 --es->WndRow;
2045 /*********************************************************************
2046 * EDIT_VScrollPage
2048 * Scroll text vertically by one page using keyboard.
2051 void EDIT_VScrollPage(HWND hwnd, WORD opt)
2053 RECT rc;
2054 int vscrollpos;
2055 WND *wndPtr = WIN_FindWndPtr(hwnd);
2056 EDITSTATE *es =
2057 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2059 if (opt == SB_PAGEUP)
2061 if (es->wtop)
2062 es->wtop -= ClientHeight(wndPtr, es);
2064 else
2066 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
2068 es->wtop += ClientHeight(wndPtr, es);
2069 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
2070 es->wtop = es->wlines - ClientHeight(wndPtr, es);
2073 if (es->wtop < 0)
2074 es->wtop = 0;
2076 InvalidateRect(hwnd, NULL, TRUE);
2077 UpdateWindow(hwnd);
2079 /* reset the vertical scroll bar */
2080 if (IsVScrollBar())
2082 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
2083 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
2088 /*********************************************************************
2089 * WM_HSCROLL message function
2092 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
2094 WND *wndPtr = WIN_FindWndPtr(hwnd);
2095 EDITSTATE *es =
2096 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2098 switch (wParam)
2100 case SB_LINEUP:
2101 case SB_LINEDOWN:
2102 HideCaret(hwnd);
2104 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2105 ShowCaret(hwnd);
2106 break;
2111 /*********************************************************************
2112 * WM_SIZE message function
2115 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam)
2117 RECT rc;
2118 WND *wndPtr = WIN_FindWndPtr(hwnd);
2119 EDITSTATE *es =
2120 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2122 if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return;
2124 InvalidateRect(hwnd, NULL, TRUE);
2125 es->PaintBkgd = TRUE;
2126 UpdateWindow(hwnd);
2130 /*********************************************************************
2131 * WM_LBUTTONDOWN message function
2134 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam)
2136 char *cp;
2137 int len;
2138 BOOL end = FALSE;
2139 WND *wndPtr = WIN_FindWndPtr(hwnd);
2140 EDITSTATE *es =
2141 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2143 if (SelMarked(es))
2144 EDIT_ClearSel(hwnd);
2146 es->WndRow = HIWORD(lParam) / es->txtht;
2147 if (es->WndRow > es->wlines - es->wtop - 1)
2149 if (es->wlines)
2150 es->WndRow = es->wlines - es->wtop - 1;
2151 else
2152 es->WndRow = 0;
2153 end = TRUE;
2155 es->CurrLine = es->wtop + es->WndRow;
2157 cp = EDIT_TextLine(hwnd, es->CurrLine);
2158 len = EDIT_LineLength(hwnd, es->CurrLine);
2159 es->WndCol = LOWORD(lParam);
2160 if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
2161 es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
2162 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2164 ButtonDown = TRUE;
2165 ButtonRow = es->CurrLine;
2166 ButtonCol = es->CurrCol;
2170 /*********************************************************************
2171 * WM_MOUSEMOVE message function
2174 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
2176 if (wParam != MK_LBUTTON)
2177 return;
2179 if (ButtonDown)
2181 EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
2182 TextMarking = TRUE;
2183 ButtonDown = FALSE;
2186 if (TextMarking)
2187 EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
2191 /*********************************************************************
2192 * EDIT_PixelToChar
2194 * Convert a pixel offset in the given row to a character offset,
2195 * adjusting the pixel offset to the nearest whole character if
2196 * necessary.
2199 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
2201 int ch = 0, i = 0, s_i;
2202 char *text;
2203 WND *wndPtr = WIN_FindWndPtr(hwnd);
2204 EDITSTATE *es =
2205 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2207 dprintf_edit(stddeb,"EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
2209 text = EDIT_TextLine(hwnd, row);
2210 while (i < *pixel)
2212 s_i = i;
2213 i += EDIT_CharWidth(hwnd, (BYTE)(*(text + ch)), i);
2214 ch++;
2217 /* if stepped past _pixel_, go back a character */
2218 if (i - *pixel)
2220 i = s_i;
2221 --ch;
2223 *pixel = i;
2224 return ch;
2228 /*********************************************************************
2229 * WM_SETTEXT message function
2232 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam)
2234 int len;
2235 char *text;
2236 RECT rc;
2237 WND *wndPtr = WIN_FindWndPtr(hwnd);
2238 EDITSTATE *es =
2239 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2241 if (strlen((char *)lParam) <= es->MaxTextLen)
2243 len = strlen((char *)lParam);
2244 EDIT_ClearText(hwnd);
2245 es->textlen = len;
2246 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, len + 3);
2247 text = EDIT_HeapAddr(hwnd, es->hText);
2248 strcpy(text, (char *)lParam);
2249 text[len + 1] = '\0';
2250 text[len + 2] = '\0';
2251 EDIT_BuildTextPointers(hwnd);
2252 InvalidateRect(hwnd, NULL, TRUE);
2253 es->PaintBkgd = TRUE;
2254 es->TextChanged = TRUE;
2255 return 0L;
2257 else
2258 return EN_ERRSPACE;
2262 /*********************************************************************
2263 * EDIT_ClearText
2265 * Clear text from text buffer.
2268 void EDIT_ClearText(HWND hwnd)
2270 WND *wndPtr = WIN_FindWndPtr(hwnd);
2271 EDITSTATE *es =
2272 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2273 unsigned int blen = EditBufLen(wndPtr) + 2;
2274 char *text;
2276 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, blen);
2277 text = EDIT_HeapAddr(hwnd, es->hText);
2278 memset(text, 0, blen);
2279 es->textlen = 0;
2280 es->wlines = 0;
2281 es->CurrLine = es->CurrCol = 0;
2282 es->WndRow = es->WndCol = 0;
2283 es->wleft = es->wtop = 0;
2284 es->textwidth = 0;
2285 es->TextChanged = FALSE;
2286 EDIT_ClearTextPointers(hwnd);
2290 /*********************************************************************
2291 * EM_SETSEL message function
2294 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
2296 int so, eo;
2297 WND *wndPtr = WIN_FindWndPtr(hwnd);
2298 EDITSTATE *es =
2299 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2301 so = LOWORD(lParam);
2302 eo = HIWORD(lParam);
2304 if (so == -1) /* if so == -1, clear selection */
2306 EDIT_ClearSel(hwnd);
2307 return;
2310 if (so == eo) /* if so == eo, set caret only */
2312 EDIT_GetLineCol(hwnd, so, &(es->CurrLine), &(es->CurrCol));
2313 es->WndRow = es->CurrLine - es->wtop;
2315 if (!wParam)
2317 if (es->WndRow < 0 || es->WndRow > ClientHeight(wndPtr, es))
2319 es->wtop = es->CurrLine;
2320 es->WndRow = 0;
2322 es->WndCol = EDIT_StrLength(hwnd,
2323 EDIT_TextLine(hwnd, es->CurrLine),
2324 es->CurrCol, 0) - es->wleft;
2325 if (es->WndCol > ClientWidth(wndPtr))
2327 es->wleft = es->WndCol;
2328 es->WndCol = 0;
2330 else if (es->WndCol < 0)
2332 es->wleft += es->WndCol;
2333 es->WndCol = 0;
2337 else /* otherwise set selection */
2339 if (so > eo)
2340 swap(&so, &eo);
2342 EDIT_GetLineCol(hwnd, so, &(es->SelBegLine), &(es->SelBegCol));
2343 EDIT_GetLineCol(hwnd, eo, &(es->SelEndLine), &(es->SelEndCol));
2344 es->CurrLine = es->SelEndLine;
2345 es->CurrCol = es->SelEndCol;
2346 es->WndRow = es->SelEndLine - es->wtop;
2348 if (!wParam) /* don't suppress scrolling of text */
2350 if (es->WndRow < 0)
2352 es->wtop = es->SelEndLine;
2353 es->WndRow = 0;
2355 else if (es->WndRow > ClientHeight(wndPtr, es))
2357 es->wtop += es->WndRow - ClientHeight(wndPtr, es);
2358 es->WndRow = ClientHeight(wndPtr, es);
2360 es->WndCol = EDIT_StrLength(hwnd,
2361 EDIT_TextLine(hwnd, es->SelEndLine),
2362 es->SelEndCol, 0) - es->wleft;
2363 if (es->WndCol > ClientWidth(wndPtr))
2365 es->wleft += es->WndCol - ClientWidth(wndPtr);
2366 es->WndCol = ClientWidth(wndPtr);
2368 else if (es->WndCol < 0)
2370 es->wleft += es->WndCol;
2371 es->WndCol = 0;
2375 InvalidateRect(hwnd, NULL, TRUE);
2376 UpdateWindow(hwnd);
2381 /*********************************************************************
2382 * EDIT_GetLineCol
2384 * Return line and column in text buffer from character offset.
2387 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
2389 int lineno;
2390 char *cp, *cp1;
2391 WND *wndPtr = WIN_FindWndPtr(hwnd);
2392 EDITSTATE *es =
2393 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2394 char *text = EDIT_HeapAddr(hwnd, es->hText);
2395 unsigned int *textPtrs =
2396 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2398 /* check for (0,0) */
2399 if (!off)
2401 *line = 0;
2402 *col = 0;
2403 return;
2406 if (off > strlen(text)) off = strlen(text);
2407 cp1 = text;
2408 for (lineno = 0; lineno < es->wlines; lineno++)
2410 cp = text + *(textPtrs + lineno);
2411 if (off == (int)(cp - text))
2413 *line = lineno;
2414 *col = 0;
2415 return;
2417 if (off < (int)(cp - text))
2418 break;
2419 cp1 = cp;
2421 *line = lineno - 1;
2422 *col = off - (int)(cp1 - text);
2423 #if 0
2424 if (*(text + *col) == '\0')
2425 (*col)--;
2426 #endif
2430 /*********************************************************************
2431 * EDIT_DeleteSel
2433 * Delete the current selected text (if any)
2436 void EDIT_DeleteSel(HWND hwnd)
2438 char *bbl, *bel;
2439 int len;
2440 WND *wndPtr = WIN_FindWndPtr(hwnd);
2441 EDITSTATE *es =
2442 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2443 char *text = EDIT_HeapAddr(hwnd, es->hText);
2445 if (SelMarked(es))
2447 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
2448 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
2449 len = (int)(bel - bbl);
2450 EDIT_SaveDeletedText(hwnd, bbl, len, es->SelBegLine, es->SelBegCol);
2451 es->TextChanged = TRUE;
2452 strcpy(bbl, bel);
2454 es->CurrLine = es->SelBegLine;
2455 es->CurrCol = es->SelBegCol;
2456 es->WndRow = es->SelBegLine - es->wtop;
2457 if (es->WndRow < 0)
2459 es->wtop = es->SelBegLine;
2460 es->WndRow = 0;
2462 es->WndCol = EDIT_StrLength(hwnd, bbl - es->SelBegCol,
2463 es->SelBegCol, 0) - es->wleft;
2465 EDIT_BuildTextPointers(hwnd);
2466 es->PaintBkgd = TRUE;
2467 EDIT_ClearSel(hwnd);
2472 /*********************************************************************
2473 * EDIT_ClearSel
2475 * Clear the current selection.
2478 void EDIT_ClearSel(HWND hwnd)
2480 WND *wndPtr = WIN_FindWndPtr(hwnd);
2481 EDITSTATE *es =
2482 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2484 es->SelBegLine = es->SelBegCol = 0;
2485 es->SelEndLine = es->SelEndCol = 0;
2487 InvalidateRect(hwnd, NULL, TRUE);
2488 UpdateWindow(hwnd);
2492 /*********************************************************************
2493 * EDIT_TextLineNumber
2495 * Return the line number in the text buffer of the supplied
2496 * character pointer.
2499 int EDIT_TextLineNumber(HWND hwnd, char *lp)
2501 int lineno;
2502 char *cp;
2503 WND *wndPtr = WIN_FindWndPtr(hwnd);
2504 EDITSTATE *es =
2505 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2506 char *text = EDIT_HeapAddr(hwnd, es->hText);
2507 unsigned int *textPtrs =
2508 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2510 for (lineno = 0; lineno < es->wlines; lineno++)
2512 cp = text + *(textPtrs + lineno);
2513 if (cp == lp)
2514 return lineno;
2515 if (cp > lp)
2516 break;
2518 return lineno - 1;
2522 /*********************************************************************
2523 * EDIT_SetAnchor
2525 * Set down anchor for text marking.
2528 void EDIT_SetAnchor(HWND hwnd, int row, int col)
2530 BOOL sel = FALSE;
2531 WND *wndPtr = WIN_FindWndPtr(hwnd);
2532 EDITSTATE *es =
2533 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2535 if (SelMarked(es))
2536 sel = TRUE;
2537 EDIT_ClearSel(hwnd);
2538 es->SelBegLine = es->SelEndLine = row;
2539 es->SelBegCol = es->SelEndCol = col;
2540 if (sel)
2542 InvalidateRect(hwnd, NULL, FALSE);
2543 UpdateWindow(hwnd);
2548 /*********************************************************************
2549 * EDIT_ExtendSel
2551 * Extend selection to the given screen co-ordinates.
2554 void EDIT_ExtendSel(HWND hwnd, int x, int y)
2556 int bbl, bel, bbc, bec;
2557 char *cp;
2558 int len;
2559 BOOL end = FALSE;
2560 WND *wndPtr = WIN_FindWndPtr(hwnd);
2561 EDITSTATE *es =
2562 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2564 dprintf_edit(stddeb,"EDIT_ExtendSel: x=%d, y=%d\n", x, y);
2566 bbl = es->SelEndLine;
2567 bbc = es->SelEndCol;
2568 cp = EDIT_TextLine(hwnd, es->wtop + y / es->txtht);
2569 len = EDIT_LineLength(hwnd, es->wtop + y / es->txtht);
2571 es->WndRow = y / es->txtht;
2572 if (es->WndRow > es->wlines - es->wtop - 1)
2574 if (es->wlines)
2575 es->WndRow = es->wlines - es->wtop - 1;
2576 else
2577 es->WndRow = 0;
2578 end = TRUE;
2580 es->CurrLine = es->wtop + es->WndRow;
2581 es->SelEndLine = es->CurrLine;
2583 es->WndCol = x;
2584 if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
2585 es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
2586 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2587 es->SelEndCol = es->CurrCol - 1;
2589 bel = es->SelEndLine;
2590 bec = es->SelEndCol;
2592 /* return if no new characters to mark */
2593 if (bbl == bel && bbc == bec)
2594 return;
2596 /* put lowest marker first */
2597 if (bbl > bel)
2599 swap(&bbl, &bel);
2600 swap(&bbc, &bec);
2602 if (bbl == bel && bbc > bec)
2603 swap(&bbc, &bec);
2605 for (y = bbl; y <= bel; y++)
2607 if (y == bbl && y == bel)
2608 EDIT_WriteSel(hwnd, y, bbc, bec);
2609 else if (y == bbl)
2610 EDIT_WriteSel(hwnd, y, bbc, -1);
2611 else if (y == bel)
2612 EDIT_WriteSel(hwnd, y, 0, bec);
2613 else
2614 EDIT_WriteSel(hwnd, y, 0, -1);
2619 /*********************************************************************
2620 * EDIT_WriteSel
2622 * Display selection by reversing pixels in selected text.
2623 * If end == -1, selection applies to end of line.
2626 void EDIT_WriteSel(HWND hwnd, int y, int start, int end)
2628 RECT rc;
2629 int scol, ecol;
2630 char *cp;
2631 HDC hdc;
2632 HBRUSH hbrush, holdbrush;
2633 int olddm;
2634 WND *wndPtr = WIN_FindWndPtr(hwnd);
2635 EDITSTATE *es =
2636 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2638 dprintf_edit(stddeb,"EDIT_WriteSel: y=%d start=%d end=%d\n", y, start,end);
2639 GetClientRect(hwnd, &rc);
2641 /* make sure y is within the window */
2642 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
2643 return;
2645 /* get pointer to text */
2646 cp = EDIT_TextLine(hwnd, y);
2648 /* get length of line if end == -1 */
2649 if (end == -1)
2650 end = EDIT_LineLength(hwnd, y);
2652 scol = EDIT_StrLength(hwnd, cp, start, 0);
2653 if (scol > rc.right) return;
2654 if (scol < rc.left) scol = rc.left;
2655 ecol = EDIT_StrLength(hwnd, cp, end, 0);
2656 if (ecol < rc.left) return;
2657 if (ecol > rc.right) ecol = rc.right;
2659 hdc = GetDC(hwnd);
2660 hbrush = GetStockObject(BLACK_BRUSH);
2661 holdbrush = (HBRUSH)SelectObject(hdc, (HANDLE)hbrush);
2662 olddm = SetROP2(hdc, R2_XORPEN);
2663 Rectangle(hdc, scol, y * es->txtht, ecol, (y + 1) * es->txtht);
2664 SetROP2(hdc, olddm);
2665 SelectObject(hdc, (HANDLE)holdbrush);
2666 ReleaseDC(hwnd, hdc);
2670 /*********************************************************************
2671 * EDIT_StopMarking
2673 * Stop text marking (selection).
2676 void EDIT_StopMarking(HWND hwnd)
2678 WND *wndPtr = WIN_FindWndPtr(hwnd);
2679 EDITSTATE *es =
2680 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2682 TextMarking = FALSE;
2683 if (es->SelBegLine > es->SelEndLine)
2685 swap(&(es->SelBegLine), &(es->SelEndLine));
2686 swap(&(es->SelBegCol), &(es->SelEndCol));
2688 if (es->SelBegLine == es->SelEndLine && es->SelBegCol > es->SelEndCol)
2689 swap(&(es->SelBegCol), &(es->SelEndCol));
2693 /*********************************************************************
2694 * EM_GETLINE message function
2697 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam)
2699 char *cp, *cp1;
2700 int len;
2701 char *buffer = (char *)lParam;
2702 WND *wndPtr = WIN_FindWndPtr(hwnd);
2703 EDITSTATE *es =
2704 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2706 cp = EDIT_TextLine(hwnd, wParam);
2707 cp1 = EDIT_TextLine(hwnd, wParam + 1);
2708 len = min((int)(cp1 - cp), (WORD)(*buffer));
2709 strncpy(buffer, cp, len);
2711 return (LONG)len;
2715 /*********************************************************************
2716 * EM_GETSEL message function
2719 LONG EDIT_GetSelMsg(HWND hwnd)
2721 int so, eo;
2722 WND *wndPtr = WIN_FindWndPtr(hwnd);
2723 EDITSTATE *es =
2724 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2725 unsigned int *textPtrs =
2726 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2728 so = *(textPtrs + es->SelBegLine) + es->SelBegCol;
2729 eo = *(textPtrs + es->SelEndLine) + es->SelEndCol;
2731 return MAKELONG(so, eo);
2735 /*********************************************************************
2736 * EM_REPLACESEL message function
2739 void EDIT_ReplaceSel(HWND hwnd, LONG lParam)
2741 EDIT_DeleteSel(hwnd);
2742 EDIT_InsertText(hwnd, (char *)lParam, strlen((char *)lParam));
2743 InvalidateRect(hwnd, NULL, TRUE);
2744 UpdateWindow(hwnd);
2748 /*********************************************************************
2749 * EDIT_InsertText
2751 * Insert text at current line and column.
2754 void EDIT_InsertText(HWND hwnd, char *str, int len)
2756 int plen;
2757 WND *wndPtr = WIN_FindWndPtr(hwnd);
2758 EDITSTATE *es =
2759 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2760 char *text = EDIT_HeapAddr(hwnd, es->hText);
2762 plen = strlen(text) + len;
2763 if (plen + 1 > es->textlen)
2765 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + len);
2766 es->textlen = plen + 1;
2768 memmove(CurrChar + len, CurrChar, strlen(CurrChar) + 1);
2769 memcpy(CurrChar, str, len);
2771 EDIT_BuildTextPointers(hwnd);
2772 es->PaintBkgd = TRUE;
2773 es->TextChanged = TRUE;
2775 EDIT_GetLineCol(hwnd, (int)((CurrChar + len) - text), &(es->CurrLine),
2776 &(es->CurrCol));
2777 es->WndRow = es->CurrLine - es->wtop;
2778 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2779 es->CurrCol, 0) - es->wleft;
2783 /*********************************************************************
2784 * EM_LINEFROMCHAR message function
2787 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam)
2789 int row, col;
2790 WND *wndPtr = WIN_FindWndPtr(hwnd);
2791 EDITSTATE *es =
2792 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2794 if (wParam == (WORD)-1)
2795 return (LONG)(es->SelBegLine);
2796 else
2797 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2799 return (LONG)row;
2803 /*********************************************************************
2804 * EM_LINEINDEX message function
2807 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam)
2809 WND *wndPtr = WIN_FindWndPtr(hwnd);
2810 EDITSTATE *es =
2811 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2812 unsigned int *textPtrs =
2813 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2815 if (wParam == (WORD)-1)
2816 wParam = es->CurrLine;
2818 return (LONG)(*(textPtrs + wParam));
2822 /*********************************************************************
2823 * EM_LINELENGTH message function
2826 LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam)
2828 int row, col, len;
2829 int sbl, sbc, sel, sec;
2830 WND *wndPtr = WIN_FindWndPtr(hwnd);
2831 EDITSTATE *es =
2832 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2833 unsigned int *textPtrs =
2834 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2836 if (wParam == (WORD)-1)
2838 if (SelMarked(es))
2840 sbl = es->SelBegLine;
2841 sbc = es->SelBegCol;
2842 sel = es->SelEndLine;
2843 sec = es->SelEndCol;
2845 if (sbl > sel)
2847 swap(&sbl, &sel);
2848 swap(&sbc, &sec);
2850 if (sbl == sel && sbc > sec)
2851 swap(&sbc, &sec);
2853 if (sbc == sel)
2855 len = *(textPtrs + sbl + 1) - *(textPtrs + sbl) - 1;
2856 return len - sec - sbc;
2859 len = *(textPtrs + sel + 1) - *(textPtrs + sel) - sec - 1;
2860 return len + sbc;
2862 else /* no selection marked */
2864 len = *(textPtrs + es->CurrLine + 1) -
2865 *(textPtrs + es->CurrLine) - 1;
2866 return len;
2869 else /* line number specified */
2871 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2872 len = *(textPtrs + row + 1) - *(textPtrs + row);
2873 return len;
2878 /*********************************************************************
2879 * WM_SETFONT message function
2882 void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam)
2884 HDC hdc;
2885 TEXTMETRIC tm;
2886 HFONT oldfont;
2887 WND *wndPtr = WIN_FindWndPtr(hwnd);
2888 EDITSTATE *es =
2889 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2890 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
2892 es->hFont = wParam;
2893 hdc = GetDC(hwnd);
2894 oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
2895 GetCharWidth(hdc, 0, 255, charWidths);
2896 GetTextMetrics(hdc, &tm);
2897 es->txtht = tm.tmHeight + tm.tmExternalLeading;
2898 SelectObject(hdc, (HANDLE)oldfont);
2899 ReleaseDC(hwnd, hdc);
2901 es->WndRow = (es->CurrLine - es->wtop) / es->txtht;
2902 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2903 es->CurrCol, 0) - es->wleft;
2905 InvalidateRect(hwnd, NULL, TRUE);
2906 es->PaintBkgd = TRUE;
2907 if (lParam) UpdateWindow(hwnd);
2911 /*********************************************************************
2912 * EDIT_SaveDeletedText
2914 * Save deleted text in deleted text buffer.
2917 void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len,
2918 int line, int col)
2920 char *text;
2921 WND *wndPtr = WIN_FindWndPtr(hwnd);
2922 EDITSTATE *es =
2923 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2925 es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE);
2926 if (!es->hDeletedText) return;
2927 text = (char *)GlobalLock(es->hDeletedText);
2928 memcpy(text, deltext, len);
2929 GlobalUnlock(es->hDeletedText);
2930 es->DeletedLength = len;
2931 es->DeletedCurrLine = line;
2932 es->DeletedCurrCol = col;
2936 /*********************************************************************
2937 * EDIT_ClearDeletedText
2939 * Clear deleted text buffer.
2942 void EDIT_ClearDeletedText(HWND hwnd)
2944 WND *wndPtr = WIN_FindWndPtr(hwnd);
2945 EDITSTATE *es =
2946 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2948 GlobalFree(es->hDeletedText);
2949 es->hDeletedText = 0;
2950 es->DeletedLength = 0;
2954 /*********************************************************************
2955 * EM_UNDO message function
2958 LONG EDIT_UndoMsg(HWND hwnd)
2960 char *text;
2961 WND *wndPtr = WIN_FindWndPtr(hwnd);
2962 EDITSTATE *es =
2963 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2965 if (es->hDeletedText)
2967 text = (char *)GlobalLock(es->hDeletedText);
2968 es->CurrLine = es->DeletedCurrLine;
2969 es->CurrCol = es->DeletedCurrCol;
2970 EDIT_InsertText(hwnd, text, es->DeletedLength);
2971 GlobalUnlock(es->hDeletedText);
2972 EDIT_ClearDeletedText(hwnd);
2974 es->SelBegLine = es->CurrLine;
2975 es->SelBegCol = es->CurrCol;
2976 EDIT_GetLineCol(hwnd, (int)((CurrChar + es->DeletedLength) - text),
2977 &(es->CurrLine), &(es->CurrCol));
2978 es->WndRow = es->CurrLine - es->wtop;
2979 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2980 es->CurrCol, 0) - es->wleft;
2981 es->SelEndLine = es->CurrLine;
2982 es->SelEndCol = es->CurrCol;
2984 InvalidateRect(hwnd, NULL, TRUE);
2985 UpdateWindow(hwnd);
2986 return 1;
2988 else
2989 return 0;
2993 /*********************************************************************
2994 * EDIT_HeapAlloc
2996 * Allocate the specified number of bytes on the specified local heap.
2999 unsigned int EDIT_HeapAlloc(HWND hwnd, int bytes)
3001 WND *wndPtr = WIN_FindWndPtr(hwnd);
3002 unsigned int ret;
3003 ret = ((unsigned int)HEAP_Alloc((MDESC **)
3004 *(LONG *)(wndPtr->wExtra + 2),
3005 GMEM_MOVEABLE, bytes) & 0xffff);
3006 if (ret == 0)
3007 printf("EDIT_HeapAlloc: Out of heap-memory\n");
3008 return ret;
3012 /*********************************************************************
3013 * EDIT_HeapAddr
3015 * Return the address of the memory pointed to by the handle.
3018 void *EDIT_HeapAddr(HWND hwnd, unsigned int handle)
3020 WND *wndPtr = WIN_FindWndPtr(hwnd);
3022 return ((void *)((handle) ? ((handle) | ((unsigned int)
3023 (*(MDESC **)*(LONG *)(wndPtr->wExtra + 2))
3024 & 0xffff0000)) : 0));
3028 /*********************************************************************
3029 * EDIT_HeapReAlloc
3031 * Reallocate the memory pointed to by the handle.
3034 unsigned int EDIT_HeapReAlloc(HWND hwnd, unsigned int handle, int bytes)
3036 WND *wndPtr = WIN_FindWndPtr(hwnd);
3038 return ((unsigned int)HEAP_ReAlloc((MDESC **)
3039 *(LONG *)(wndPtr->wExtra + 2),
3040 EDIT_HeapAddr(hwnd, handle),
3041 bytes, GMEM_MOVEABLE) & 0xffff);
3045 /*********************************************************************
3046 * EDIT_HeapFree
3048 * Frees the memory pointed to by the handle.
3051 void EDIT_HeapFree(HWND hwnd, unsigned int handle)
3053 WND *wndPtr = WIN_FindWndPtr(hwnd);
3055 HEAP_Free((MDESC **)*(LONG *)(wndPtr->wExtra + 2),
3056 EDIT_HeapAddr(hwnd, handle));
3060 /*********************************************************************
3061 * EDIT_HeapSize
3063 * Return the size of the given object on the local heap.
3066 unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle)
3068 WND *wndPtr = WIN_FindWndPtr(hwnd);
3070 return HEAP_LocalSize((MDESC **)*(LONG *)(wndPtr->wExtra + 2), handle);
3074 /*********************************************************************
3075 * EM_SETHANDLE message function
3078 void EDIT_SetHandleMsg(HWND hwnd, WORD wParam)
3080 MDESC *m;
3081 WND *wndPtr = WIN_FindWndPtr(hwnd);
3082 EDITSTATE *es =
3083 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3085 if (IsMultiLine())
3087 es->hText = wParam;
3088 es->MaxTextLen = EDIT_HeapSize(hwnd, es->hText);
3089 es->wlines = 0;
3090 es->wtop = es->wleft = 0;
3091 es->CurrLine = es->CurrCol = 0;
3092 es->WndRow = es->WndCol = 0;
3093 es->TextChanged = FALSE;
3094 es->textwidth = 0;
3095 es->SelBegLine = es->SelBegCol = 0;
3096 es->SelEndLine = es->SelEndCol = 0;
3098 es->PaintBkgd = TRUE;
3099 InvalidateRect(hwnd, NULL, TRUE);
3100 UpdateWindow(hwnd);
3105 /*********************************************************************
3106 * EM_SETTABSTOPS message function
3109 LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam)
3111 unsigned short *tabstops;
3112 WND *wndPtr = WIN_FindWndPtr(hwnd);
3113 EDITSTATE *es =
3114 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3116 es->NumTabStops = wParam;
3117 if (wParam == 0)
3118 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, 1);
3119 else if (wParam == 1)
3121 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, 1);
3122 tabstops = (unsigned short *)EDIT_HeapAddr(hwnd, es->hTabStops);
3123 *tabstops = (unsigned short)lParam;
3125 else
3127 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, wParam);
3128 tabstops = (unsigned short *)EDIT_HeapAddr(hwnd, es->hTabStops);
3129 memcpy(tabstops, (unsigned short *)lParam, wParam);
3131 return 0L;
3135 /*********************************************************************
3136 * EDIT_CopyToClipboard
3138 * Copy the specified text to the clipboard.
3141 void EDIT_CopyToClipboard(HWND hwnd)
3143 HANDLE hMem;
3144 char *lpMem;
3145 int i, len;
3146 char *bbl, *bel;
3147 WND *wndPtr = WIN_FindWndPtr(hwnd);
3148 EDITSTATE *es =
3149 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3151 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
3152 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
3153 len = (int)(bel - bbl);
3155 hMem = GlobalAlloc(GHND, (DWORD)(len + 1));
3156 lpMem = GlobalLock(hMem);
3158 for (i = 0; i < len; i++)
3159 *lpMem++ = *bbl++;
3161 GlobalUnlock(hMem);
3162 OpenClipboard(hwnd);
3163 EmptyClipboard();
3164 SetClipboardData(CF_TEXT, hMem);
3165 CloseClipboard();
3169 /*********************************************************************
3170 * WM_PASTE message function
3173 void EDIT_PasteMsg(HWND hwnd)
3175 HANDLE hClipMem;
3176 char *lpClipMem;
3178 OpenClipboard(hwnd);
3179 if (!(hClipMem = GetClipboardData(CF_TEXT)))
3181 /* no text in clipboard */
3182 CloseClipboard();
3183 return;
3185 lpClipMem = GlobalLock(hClipMem);
3186 EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem));
3187 GlobalUnlock(hClipMem);
3188 CloseClipboard();
3189 InvalidateRect(hwnd, NULL, TRUE);
3190 UpdateWindow(hwnd);
3194 /*********************************************************************
3195 * Utility functions
3198 void swap(int *a, int *b)
3200 int x;
3202 x = *a;
3203 *a = *b;
3204 *b = x;