Release 941030
[wine/multimedia.git] / controls / edit.c
blob81e5b4f6209daa28afe2838193531634e9eb4667
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) \
73 (wndPtr->rectClient.right > wndPtr->rectClient.left ? \
74 wndPtr->rectClient.right - wndPtr->rectClient.left : 0)
75 #define ClientHeight(wndPtr, es) \
76 (wndPtr->rectClient.bottom > wndPtr->rectClient.top ? \
77 (wndPtr->rectClient.bottom - wndPtr->rectClient.top) / es->txtht : 0)
78 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
79 ? EDITLEN : ENTRYLEN)
80 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
81 #define SelMarked(es) (es->SelBegLine != 0 || es->SelBegCol != 0 || \
82 es->SelEndLine != 0 || es->SelEndCol != 0)
83 #define ROUNDUP(numer, denom) (((numer) % (denom)) \
84 ? ((((numer) + (denom)) / (denom)) * (denom)) \
85 : (numer) + (denom))
87 /* macros to access window styles */
88 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
89 #define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
90 #define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
91 #define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
92 #define IsHScrollBar() (wndPtr->dwStyle & WS_HSCROLL)
94 /* internal variables */
95 static BOOL TextMarking; /* TRUE if text marking in progress */
96 static BOOL ButtonDown; /* TRUE if left mouse button down */
97 static int ButtonRow; /* row in text buffer when button pressed */
98 static int ButtonCol; /* col in text buffer when button pressed */
101 LONG EditWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
102 long EDIT_NCCreateMsg(HWND hwnd, LONG lParam);
103 long EDIT_CreateMsg(HWND hwnd, LONG lParam);
104 void EDIT_ClearTextPointers(HWND hwnd);
105 void EDIT_BuildTextPointers(HWND hwnd);
106 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var);
107 void EDIT_PaintMsg(HWND hwnd);
108 HANDLE EDIT_GetTextLine(HWND hwnd, int selection);
109 char *EDIT_TextLine(HWND hwnd, int sel);
110 int EDIT_StrLength(HWND hwnd, unsigned char *str, int len, int pcol);
111 int EDIT_LineLength(HWND hwnd, int num);
112 void EDIT_WriteTextLine(HWND hwnd, RECT *rc, int y);
113 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
114 int col, RECT *rc, BOOL blank, BOOL reverse);
115 HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff);
116 void EDIT_CharMsg(HWND hwnd, WORD wParam);
117 void EDIT_KeyTyped(HWND hwnd, short ch);
118 int EDIT_CharWidth(HWND hwnd, short ch, int pcol);
119 int EDIT_GetNextTabStop(HWND hwnd, int pcol);
120 void EDIT_Forward(HWND hwnd);
121 void EDIT_Downward(HWND hwnd);
122 void EDIT_Upward(HWND hwnd);
123 void EDIT_Backward(HWND hwnd);
124 void EDIT_End(HWND hwnd);
125 void EDIT_Home(HWND hwnd);
126 void EDIT_StickEnd(HWND hwnd);
127 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam);
128 void EDIT_KeyHScroll(HWND hwnd, WORD opt);
129 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt);
130 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt);
131 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt);
132 int EDIT_ComputeVScrollPos(HWND hwnd);
133 int EDIT_ComputeHScrollPos(HWND hwnd);
134 void EDIT_DelKey(HWND hwnd);
135 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
136 void EDIT_VScrollLine(HWND hwnd, WORD opt);
137 void EDIT_VScrollPage(HWND hwnd, WORD opt);
138 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
139 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam);
140 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam);
141 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam);
142 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel);
143 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam);
144 void EDIT_ClearText(HWND hwnd);
145 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam);
146 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col);
147 void EDIT_DeleteSel(HWND hwnd);
148 void EDIT_ClearSel(HWND hwnd);
149 int EDIT_TextLineNumber(HWND hwnd, char *lp);
150 void EDIT_SetAnchor(HWND hwnd, int row, int col);
151 void EDIT_ExtendSel(HWND hwnd, int x, int y);
152 void EDIT_WriteSel(HWND hwnd, int y, int start, int end);
153 void EDIT_StopMarking(HWND hwnd);
154 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
155 LONG EDIT_GetSelMsg(HWND hwnd);
156 void EDIT_ReplaceSel(HWND hwnd, LONG lParam);
157 void EDIT_InsertText(HWND hwnd, char *str, int len);
158 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam);
159 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam);
160 LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam);
161 void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam);
162 void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len, int line,
163 int col);
164 void EDIT_ClearDeletedText(HWND hwnd);
165 LONG EDIT_UndoMsg(HWND hwnd);
166 unsigned int EDIT_HeapAlloc(HWND hwnd, int bytes);
167 void *EDIT_HeapAddr(HWND hwnd, unsigned int handle);
168 unsigned int EDIT_HeapReAlloc(HWND hwnd, unsigned int handle, int bytes);
169 void EDIT_HeapFree(HWND hwnd, unsigned int handle);
170 unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle);
171 void EDIT_SetHandleMsg(HWND hwnd, WORD wParam);
172 LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam);
173 void EDIT_CopyToClipboard(HWND hwnd);
174 void EDIT_PasteMsg(HWND hwnd);
175 void swap(int *a, int *b);
178 LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
180 LONG lResult = 0L;
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;
470 /* store pointer to local or global heap in window structure so that */
471 /* EDITSTATE structure itself can be stored on local heap */
472 if (HEAP_LocalFindHeap(createStruct->hInstance)!=NULL)
473 (MDESC **)*(LONG *)(wndPtr->wExtra + 2) =
474 &HEAP_LocalFindHeap(createStruct->hInstance)->free_list;
475 else
477 (MDESC **)*(LONG *)(wndPtr->wExtra + 2) =
478 GlobalLock(createStruct->hInstance);
479 /* GlobalUnlock(createStruct->hInstance); */
481 /* allocate space for state variable structure */
482 (HANDLE)(*(wndPtr->wExtra)) = EDIT_HeapAlloc(hwnd, sizeof(EDITSTATE));
483 es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
484 es->hTextPtrs = EDIT_HeapAlloc(hwnd, sizeof(int));
485 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
486 es->hCharWidths = EDIT_HeapAlloc(hwnd, 256 * sizeof(short));
488 /* --- text buffer */
489 es->MaxTextLen = MAXTEXTLEN + 1;
490 if (!(createStruct->lpszName))
492 es->textlen = EditBufLen(wndPtr) + 1;
493 es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
494 text = EDIT_HeapAddr(hwnd, es->hText);
495 memset(text, 0, es->textlen + 2);
496 EDIT_ClearTextPointers(hwnd);
498 else
500 if (strlen(createStruct->lpszName) < EditBufLen(wndPtr))
502 es->textlen = EditBufLen(wndPtr) + 1;
503 es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
504 text = EDIT_HeapAddr(hwnd, es->hText);
505 strcpy(text, createStruct->lpszName);
506 *(text + es->textlen) = '\0';
508 else
510 es->hText = EDIT_HeapAlloc(hwnd,
511 strlen(createStruct->lpszName) + 2);
512 text = EDIT_HeapAddr(hwnd, es->hText);
513 strcpy(text, createStruct->lpszName);
514 es->textlen = strlen(createStruct->lpszName) + 1;
516 *(text + es->textlen + 1) = '\0';
517 EDIT_BuildTextPointers(hwnd);
520 if ((createStruct->style & WS_VSCROLL) ||
521 (createStruct->style & WS_HSCROLL)) NC_CreateScrollBars(hwnd);
523 /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
524 /* the corresponding WM_* message is set */
525 if (createStruct->style & WS_VSCROLL)
526 wndPtr->dwStyle |= ES_AUTOVSCROLL;
527 if (createStruct->style & WS_HSCROLL)
528 wndPtr->dwStyle |= ES_AUTOHSCROLL;
530 /* remove the WS_CAPTION style if it has been set - this is really a */
531 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
532 if (wndPtr->dwStyle & WS_BORDER && wndPtr->dwStyle & WS_DLGFRAME)
533 wndPtr->dwStyle ^= WS_DLGFRAME;
535 return 1;
539 /*********************************************************************
540 * WM_CREATE message function
543 long EDIT_CreateMsg(HWND hwnd, LONG lParam)
545 HDC hdc;
546 WND *wndPtr = WIN_FindWndPtr(hwnd);
547 EDITSTATE *es =
548 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
549 CLASS *classPtr;
550 short *charWidths;
551 TEXTMETRIC tm;
552 char *text;
554 /* initialize state variable structure */
555 /* --- char width array */
556 hdc = GetDC(hwnd);
557 charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
558 memset(charWidths, 0, 256 * sizeof(short));
559 GetCharWidth(hdc, 0, 255, charWidths);
561 /* --- other structure variables */
562 GetTextMetrics(hdc, &tm);
563 es->txtht = tm.tmHeight + tm.tmExternalLeading;
564 es->wlines = 0;
565 es->wtop = es->wleft = 0;
566 es->CurrCol = es->CurrLine = 0;
567 es->WndCol = es->WndRow = 0;
568 es->TextChanged = FALSE;
569 es->textwidth = 0;
570 es->SelBegLine = es->SelBegCol = 0;
571 es->SelEndLine = es->SelEndCol = 0;
572 es->hFont = 0;
573 es->hDeletedText = 0;
574 es->DeletedLength = 0;
575 es->NumTabStops = 0;
576 es->hTabStops = EDIT_HeapAlloc(hwnd, sizeof(int));
578 /* allocate space for a line full of blanks to speed up */
579 /* line filling */
580 es->hBlankLine = EDIT_HeapAlloc(hwnd, (ClientWidth(wndPtr) /
581 charWidths[32]) + 2);
582 text = EDIT_HeapAddr(hwnd, es->hBlankLine);
583 memset(text, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
585 /* set up text cursor for edit class */
586 CLASS_FindClassByName("EDIT", &classPtr);
587 classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);
589 /* paint background on first WM_PAINT */
590 es->PaintBkgd = TRUE;
592 ReleaseDC(hwnd, hdc);
593 return 0L;
597 /*********************************************************************
598 * EDIT_ClearTextPointers
600 * Clear and initialize text line pointer array.
603 void EDIT_ClearTextPointers(HWND hwnd)
605 unsigned int *textPtrs;
606 WND *wndPtr = WIN_FindWndPtr(hwnd);
607 EDITSTATE *es =
608 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
610 es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs, sizeof(int));
611 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
612 *textPtrs = 0;
616 /*********************************************************************
617 * EDIT_BuildTextPointers
619 * Build array of pointers to text lines.
622 #define INITLINES 100
624 void EDIT_BuildTextPointers(HWND hwnd)
626 WND *wndPtr = WIN_FindWndPtr(hwnd);
627 char *text, *cp;
628 int incrs = INITLINES;
629 unsigned int off, len;
630 EDITSTATE *es;
631 unsigned int *textPtrs;
632 short *charWidths;
634 es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
635 text = EDIT_HeapAddr(hwnd, es->hText);
636 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
637 charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
639 es->textwidth = es->wlines = 0;
640 cp = text;
642 /* advance through text buffer */
643 while (*cp)
645 /* increase size of text pointer array */
646 if (incrs == INITLINES)
648 incrs = 0;
649 es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs,
650 (es->wlines + INITLINES) * sizeof(int));
651 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
653 off = (unsigned int)(cp - text); /* offset of beginning of line */
654 *(textPtrs + es->wlines) = off;
655 es->wlines++;
656 incrs++;
657 len = 0;
659 /* advance through current line */
660 while (*cp && *cp != '\n')
662 len += EDIT_CharWidth(hwnd, (BYTE)*cp, len);
663 /* width of line in pixels */
664 cp++;
666 es->textwidth = max(es->textwidth, len);
667 if (*cp)
668 cp++; /* skip '\n' */
671 off = (unsigned int)(cp - text);
672 *(textPtrs + es->wlines) = off;
676 /*********************************************************************
677 * EDIT_ModTextPointers
679 * Modify text pointers from a specified position.
682 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
684 WND *wndPtr = WIN_FindWndPtr(hwnd);
685 EDITSTATE *es =
686 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
687 unsigned int *textPtrs =
688 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
690 while (lineno < es->wlines)
691 *(textPtrs + lineno++) += var;
695 /*********************************************************************
696 * WM_PAINT message function
699 void EDIT_PaintMsg(HWND hwnd)
701 PAINTSTRUCT ps;
702 HDC hdc;
703 int y;
704 RECT rc;
705 WND *wndPtr = WIN_FindWndPtr(hwnd);
706 EDITSTATE *es =
707 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
709 hdc = BeginPaint(hwnd, &ps);
710 rc = ps.rcPaint;
712 dprintf_edit(stddeb,"WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc.left, rc.top,
713 rc.right, rc.bottom);
715 if (es->PaintBkgd)
716 FillWindow(GetParent(hwnd), hwnd, hdc, CTLCOLOR_EDIT);
718 for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
720 if (y < es->wlines - es->wtop)
721 EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
724 EndPaint(hwnd, &ps);
728 /*********************************************************************
729 * EDIT_GetTextLine
731 * Get a copy of the text in the specified line.
734 HANDLE EDIT_GetTextLine(HWND hwnd, int selection)
736 char *line;
737 HANDLE hLine;
738 int len = 0;
739 char *cp, *cp1;
741 dprintf_edit(stddeb,"GetTextLine %d\n", selection);
742 cp = cp1 = EDIT_TextLine(hwnd, selection);
743 /* advance through line */
744 while (*cp && *cp != '\n')
746 len++;
747 cp++;
750 /* store selected line and return handle */
751 hLine = EDIT_HeapAlloc(hwnd, len + 6);
752 line = (char *)EDIT_HeapAddr(hwnd, hLine);
753 memmove(line, cp1, len);
754 line[len] = '\0';
755 return hLine;
759 /*********************************************************************
760 * EDIT_TextLine
762 * Return a pointer to the text in the specified line.
765 char *EDIT_TextLine(HWND hwnd, int sel)
767 WND *wndPtr = WIN_FindWndPtr(hwnd);
768 EDITSTATE *es =
769 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
770 char *text = EDIT_HeapAddr(hwnd, es->hText);
771 unsigned int *textPtrs =
772 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
774 if(sel>es->wlines)return NULL;
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, unsigned char *str, int len, int pcol)
789 int i, plen = 0;
791 for (i = 0; i < len; i++)
792 plen += EDIT_CharWidth(hwnd, (BYTE)(*(str + i)), pcol + plen);
794 dprintf_edit(stddeb,"EDIT_StrLength: returning %d\n", plen);
795 return plen;
799 /*********************************************************************
800 * EDIT_LineLength
802 * Return length of line _num_ in characters.
805 int EDIT_LineLength(HWND hwnd, int num)
807 char *cp = EDIT_TextLine(hwnd, num);
808 char *cp1;
810 if(!cp)return 0;
811 cp1 = strchr(cp, '\n');
812 return cp1 ? (int)(cp1 - cp) : strlen(cp);
816 /*********************************************************************
817 * EDIT_WriteTextLine
819 * Write the line of text at offset _y_ in text buffer to a window.
822 void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
824 int len = 0;
825 HANDLE hLine;
826 unsigned char *lp;
827 int lnlen, lnlen1;
828 int col, off = 0;
829 int sbl, sel, sbc, sec;
830 RECT rc;
831 WND *wndPtr = WIN_FindWndPtr(hwnd);
832 EDITSTATE *es =
833 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
835 /* initialize rectangle if NULL, else copy */
836 if (rect)
837 CopyRect(&rc, rect);
838 else
839 GetClientRect(hwnd, &rc);
841 dprintf_edit(stddeb,"WriteTextLine %d\n", y);
843 /* make sure y is inside the window */
844 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
846 dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
847 return;
850 /* make sure rectangle is within window */
851 if (rc.left >= ClientWidth(wndPtr) - 1)
853 dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
854 rc.left);
855 return;
857 if (rc.right <= 0)
859 dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
860 rc.right);
861 return;
863 if (y - es->wtop < (rc.top / es->txtht) ||
864 y - es->wtop > (rc.bottom / es->txtht))
866 dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is outside window\n", y);
867 return;
870 /* get the text and length of line */
871 if ((hLine = EDIT_GetTextLine(hwnd, y)) == 0)
872 return;
873 lp = (unsigned char *)EDIT_HeapAddr(hwnd, hLine);
874 lnlen = EDIT_StrLength(hwnd, lp, strlen(lp), 0);
875 lnlen1 = lnlen;
877 /* build the line to display */
878 if (lnlen < es->wleft)
879 lnlen = 0;
880 else
881 off += es->wleft;
883 if (lnlen > rc.left)
885 off += rc.left;
886 lnlen = lnlen1 - off;
887 len = min(lnlen, rc.right - rc.left);
890 if (SelMarked(es))
892 sbl = es->SelBegLine;
893 sel = es->SelEndLine;
894 sbc = es->SelBegCol;
895 sec = es->SelEndCol;
897 /* put lowest marker first */
898 if (sbl > sel)
900 swap(&sbl, &sel);
901 swap(&sbc, &sec);
903 if (sbl == sel && sbc > sec)
904 swap(&sbc, &sec);
906 if (y < sbl || y > sel)
907 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
908 TRUE, FALSE);
909 else if (y > sbl && y < sel)
910 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
911 TRUE, TRUE);
912 else if (y == sbl)
914 col = EDIT_StrLength(hwnd, lp, sbc, 0);
915 if (col > (es->wleft + rc.left))
917 len = min(col - off, rc.right - off);
918 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
919 rc.left, &rc, FALSE, FALSE);
920 off = col;
922 if (y == sel)
924 col = EDIT_StrLength(hwnd, lp, sec, 0);
925 if (col < (es->wleft + rc.right))
927 len = min(col - off, rc.right - off);
928 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
929 off - es->wleft, &rc, FALSE, TRUE);
930 off = col;
931 len = min(lnlen - off, rc.right - off);
932 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
933 off - es->wleft, &rc, TRUE, FALSE);
935 else
937 len = min(lnlen - off, rc.right - off);
938 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
939 off - es->wleft, &rc, TRUE, TRUE);
942 else
944 len = min(lnlen - off, rc.right - off);
945 if (col < (es->wleft + rc.right))
946 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
947 off - es->wleft, &rc, TRUE, TRUE);
950 else if (y == sel)
952 col = EDIT_StrLength(hwnd, lp, sec, 0);
953 if (col < (es->wleft + rc.right))
955 len = min(col - off, rc.right - off);
956 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
957 off - es->wleft, &rc, FALSE, TRUE);
958 off = col;
959 len = min(lnlen - off, rc.right - off);
960 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
961 off - es->wleft, &rc, TRUE, FALSE);
965 else
966 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
967 TRUE, FALSE);
969 EDIT_HeapFree(hwnd, hLine);
973 /*********************************************************************
974 * EDIT_WriteText
976 * Write text to a window
977 * lp - text line
978 * off - offset in text line (in pixels)
979 * len - length from off (in pixels)
980 * row - line in window
981 * col - column in window
982 * rc - rectangle in which to display line
983 * blank - blank remainder of line?
984 * reverse - reverse color of line?
987 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
988 int col, RECT *rc, BOOL blank, BOOL reverse)
990 HDC hdc;
991 HANDLE hStr;
992 char *str, *cp, *cp1;
993 int diff, num_spaces, tabwidth, scol;
994 HRGN hrgnClip;
995 COLORREF oldTextColor, oldBkgdColor;
996 HFONT oldfont;
997 WND *wndPtr = WIN_FindWndPtr(hwnd);
998 EDITSTATE *es =
999 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1000 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
1001 char *blanks = (char *)EDIT_HeapAddr(hwnd, es->hBlankLine);
1003 dprintf_edit(stddeb,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
1005 hdc = GetDC(hwnd);
1006 hStr = EDIT_GetStr(hwnd, lp, off, len, &diff);
1007 str = (char *)EDIT_HeapAddr(hwnd, hStr);
1008 hrgnClip = CreateRectRgnIndirect(rc);
1009 SelectClipRgn(hdc, hrgnClip);
1011 if (es->hFont)
1012 oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
1014 SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
1015 MAKELPARAM(hwnd, CTLCOLOR_EDIT));
1017 if (reverse)
1019 oldBkgdColor = GetBkColor(hdc);
1020 oldTextColor = GetTextColor(hdc);
1021 SetBkColor(hdc, oldTextColor);
1022 SetTextColor(hdc, oldBkgdColor);
1025 if (strlen(blanks) < (ClientWidth(wndPtr) / charWidths[32]) + 2)
1027 es->hBlankLine = EDIT_HeapReAlloc(hwnd, es->hBlankLine,
1028 (ClientWidth(wndPtr) / charWidths[32]) + 2);
1029 blanks = EDIT_HeapAddr(hwnd, es->hBlankLine);
1030 memset(blanks, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
1033 if (!(cp = strchr(str, VK_TAB)))
1034 TextOut(hdc, col - diff, row * es->txtht, str, strlen(str));
1035 else
1037 TextOut(hdc, col - diff, row * es->txtht, str, (int)(cp - str));
1038 scol = EDIT_StrLength(hwnd, str, (int)(cp - str), 0);
1039 tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
1040 num_spaces = tabwidth / charWidths[32] + 1;
1041 TextOut(hdc, scol, row * es->txtht, blanks, num_spaces);
1042 cp++;
1043 scol += tabwidth;
1045 while ((cp1 = strchr(cp, VK_TAB)))
1047 TextOut(hdc, scol, row * es->txtht, cp, (int)(cp1 - cp));
1048 scol += EDIT_StrLength(hwnd, cp, (int)(cp1 - cp), scol);
1049 tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
1050 num_spaces = tabwidth / charWidths[32] + 1;
1051 TextOut(hdc, scol, row * es->txtht, blanks, num_spaces);
1052 cp = ++cp1;
1053 scol += tabwidth;
1056 TextOut(hdc, scol, row * es->txtht, cp, strlen(cp));
1059 if (reverse)
1061 SetBkColor(hdc, oldBkgdColor);
1062 SetTextColor(hdc, oldTextColor);
1065 /* blank out remainder of line if appropriate */
1066 if (blank)
1068 if ((rc->right - col) > len)
1070 num_spaces = (rc->right - col - len) / charWidths[32];
1071 TextOut(hdc, col + len, row * es->txtht, blanks, num_spaces);
1075 if (es->hFont)
1076 SelectObject(hdc, (HANDLE)oldfont);
1078 EDIT_HeapFree(hwnd, hStr);
1079 ReleaseDC(hwnd, hdc);
1083 /*********************************************************************
1084 * EDIT_GetStr
1086 * Return sub-string starting at pixel _off_ of length _len_ pixels.
1087 * If _off_ is part way through a character, the negative offset of
1088 * the beginning of the character is returned in _diff_, else _diff_
1089 * will be zero.
1092 HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff)
1094 HANDLE hStr;
1095 char *str;
1096 int ch = 0, i = 0, j, s_i;
1097 int ch1;
1099 dprintf_edit(stddeb,"EDIT_GetStr %s %d %d\n", lp, off, len);
1101 while (i < off)
1103 s_i = i;
1104 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
1105 ch++;
1108 /* if stepped past _off_, go back a character */
1109 if (i - off)
1111 i = s_i;
1112 ch--;
1114 *diff = off - i;
1115 ch1 = ch;
1117 while (i < len + off)
1119 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
1120 ch++;
1123 hStr = EDIT_HeapAlloc(hwnd, ch - ch1 + 3);
1124 str = (char *)EDIT_HeapAddr(hwnd, hStr);
1125 for (i = ch1, j = 0; i < ch; i++, j++)
1126 str[j] = lp[i];
1127 str[++j] = '\0';
1128 dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str);
1129 return hStr;
1133 /*********************************************************************
1134 * WM_CHAR message function
1137 void EDIT_CharMsg(HWND hwnd, WORD wParam)
1139 WND *wndPtr = WIN_FindWndPtr(hwnd);
1141 dprintf_edit(stddeb,"EDIT_CharMsg: wParam=%c\n", (char)wParam);
1143 switch (wParam)
1145 case '\r':
1146 case '\n':
1147 if (!IsMultiLine())
1148 break;
1149 wParam = '\n';
1150 EDIT_KeyTyped(hwnd, wParam);
1151 break;
1153 case VK_TAB:
1154 if (!IsMultiLine())
1155 break;
1156 EDIT_KeyTyped(hwnd, wParam);
1157 break;
1159 default:
1160 if (wParam >= 20 && wParam <= 126)
1161 EDIT_KeyTyped(hwnd, wParam);
1162 break;
1167 /*********************************************************************
1168 * EDIT_KeyTyped
1170 * Process keystrokes that produce displayable characters.
1173 void EDIT_KeyTyped(HWND hwnd, short ch)
1175 WND *wndPtr = WIN_FindWndPtr(hwnd);
1176 EDITSTATE *es =
1177 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1178 char *text = EDIT_HeapAddr(hwnd, es->hText);
1179 char *currchar = CurrChar;
1180 RECT rc;
1181 BOOL FullPaint = FALSE;
1183 dprintf_edit(stddeb,"EDIT_KeyTyped: ch=%c\n", (char)ch);
1185 /* delete selected text (if any) */
1186 if (SelMarked(es))
1187 EDIT_DeleteSel(hwnd);
1189 /* test for typing at end of maximum buffer size */
1190 if (currchar == text + es->MaxTextLen)
1192 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1193 return;
1196 if (*currchar == '\0' && IsMultiLine())
1198 /* insert a newline at end of text */
1199 *currchar = '\n';
1200 *(currchar + 1) = '\0';
1201 EDIT_BuildTextPointers(hwnd);
1204 /* insert the typed character */
1205 if (text[es->textlen - 1] != '\0')
1207 /* current text buffer is full */
1208 if (es->textlen == es->MaxTextLen)
1210 /* text buffer is at maximum size */
1211 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1212 return;
1215 /* increase the text buffer size */
1216 es->textlen += GROWLENGTH;
1217 /* but not above maximum size */
1218 if (es->textlen > es->MaxTextLen)
1219 es->textlen = es->MaxTextLen;
1220 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + 2);
1221 if (!es->hText)
1222 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1223 text = EDIT_HeapAddr(hwnd, es->hText);
1224 text[es->textlen - 1] = '\0';
1225 currchar = CurrChar;
1227 /* make space for new character and put char in buffer */
1228 memmove(currchar + 1, currchar, strlen(currchar) + 1);
1229 *currchar = ch;
1230 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
1231 es->TextChanged = TRUE;
1232 NOTIFY_PARENT(hwnd, EN_UPDATE);
1234 /* re-adjust textwidth, if necessary, and redraw line */
1235 HideCaret(hwnd);
1236 if (IsMultiLine() && es->wlines > 1)
1238 es->textwidth = max(es->textwidth,
1239 EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
1240 (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) -
1241 EDIT_TextLine(hwnd, es->CurrLine)), 0));
1243 else
1244 es->textwidth = max(es->textwidth,
1245 EDIT_StrLength(hwnd, text, strlen(text), 0));
1246 EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
1248 if (ch == '\n')
1250 if (es->wleft > 0)
1251 FullPaint = TRUE;
1252 es->wleft = 0;
1253 EDIT_BuildTextPointers(hwnd);
1254 EDIT_End(hwnd);
1255 EDIT_Forward(hwnd);
1257 /* invalidate rest of window */
1258 GetClientRect(hwnd, &rc);
1259 if (!FullPaint)
1260 rc.top = es->WndRow * es->txtht;
1261 InvalidateRect(hwnd, &rc, FALSE);
1263 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1264 ShowCaret(hwnd);
1265 UpdateWindow(hwnd);
1266 NOTIFY_PARENT(hwnd, EN_CHANGE);
1267 return;
1270 /* test end of window */
1271 if (es->WndCol >= ClientWidth(wndPtr) -
1272 EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft))
1274 /* TODO:- Word wrap to be handled here */
1276 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1277 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1279 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft);
1280 es->CurrCol++;
1281 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1282 ShowCaret(hwnd);
1283 NOTIFY_PARENT(hwnd, EN_CHANGE);
1287 /*********************************************************************
1288 * EDIT_CharWidth
1290 * Return the width of the given character in pixels.
1291 * The current column offset in pixels _pcol_ is required to calculate
1292 * the width of a tab.
1295 int EDIT_CharWidth(HWND hwnd, short ch, int pcol)
1297 WND *wndPtr = WIN_FindWndPtr(hwnd);
1298 EDITSTATE *es =
1299 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1300 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
1302 if (ch != VK_TAB)
1303 return (charWidths[ch]);
1304 else
1305 return (EDIT_GetNextTabStop(hwnd, pcol) - pcol);
1309 /*********************************************************************
1310 * EDIT_GetNextTabStop
1312 * Return the next tab stop beyond _pcol_.
1315 int EDIT_GetNextTabStop(HWND hwnd, int pcol)
1317 int i;
1318 int baseUnitWidth = LOWORD(GetDialogBaseUnits());
1319 WND *wndPtr = WIN_FindWndPtr(hwnd);
1320 EDITSTATE *es =
1321 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1322 unsigned short *tabstops = EDIT_HeapAddr(hwnd, es->hTabStops);
1324 if (es->NumTabStops == 0)
1325 return ROUNDUP(pcol, 8 * baseUnitWidth);
1326 else if (es->NumTabStops == 1)
1327 return ROUNDUP(pcol, *tabstops * baseUnitWidth / 4);
1328 else
1330 for (i = 0; i < es->NumTabStops; i++)
1332 if (*(tabstops + i) * baseUnitWidth / 4 >= pcol)
1333 return (*(tabstops + i) * baseUnitWidth / 4);
1335 return pcol;
1340 /*********************************************************************
1341 * EDIT_Forward
1343 * Cursor right key: move right one character position.
1346 void EDIT_Forward(HWND hwnd)
1348 WND *wndPtr = WIN_FindWndPtr(hwnd);
1349 EDITSTATE *es =
1350 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1352 if (*CurrChar == '\0')
1353 return;
1355 if (*CurrChar == '\n')
1357 EDIT_Home(hwnd);
1358 EDIT_Downward(hwnd);
1360 else
1362 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
1363 es->CurrCol++;
1364 if (es->WndCol >= ClientWidth(wndPtr))
1365 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1371 /*********************************************************************
1372 * EDIT_Downward
1374 * Cursor down key: move down one line.
1377 void EDIT_Downward(HWND hwnd)
1379 WND *wndPtr = WIN_FindWndPtr(hwnd);
1380 EDITSTATE *es =
1381 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1383 dprintf_edit(stddeb,"EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n",
1384 es->WndRow, es->wtop, es->wlines);
1386 if (IsMultiLine() && (es->WndRow + es->wtop + 1 < es->wlines))
1388 es->CurrLine++;
1389 if (es->WndRow == ClientHeight(wndPtr, es) - 1)
1391 es->WndRow++;
1392 EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
1394 else
1395 es->WndRow++;
1396 EDIT_StickEnd(hwnd);
1401 /*********************************************************************
1402 * EDIT_Upward
1404 * Cursor up key: move up one line.
1407 void EDIT_Upward(HWND hwnd)
1409 WND *wndPtr = WIN_FindWndPtr(hwnd);
1410 EDITSTATE *es =
1411 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1413 if (IsMultiLine() && es->CurrLine != 0)
1415 --es->CurrLine;
1416 if (es->WndRow == 0)
1418 --es->WndRow;
1419 EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
1421 else
1422 --es->WndRow;
1423 EDIT_StickEnd(hwnd);
1428 /*********************************************************************
1429 * EDIT_Backward
1431 * Cursor left key: move left one character position.
1434 void EDIT_Backward(HWND hwnd)
1436 WND *wndPtr = WIN_FindWndPtr(hwnd);
1437 EDITSTATE *es =
1438 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1440 if (es->CurrCol)
1442 --es->CurrCol;
1443 if (*CurrChar == VK_TAB)
1444 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar),
1445 EDIT_StrLength(hwnd,
1446 EDIT_TextLine(hwnd, es->CurrLine),
1447 es->CurrCol, 0));
1448 else
1449 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), 0);
1450 if (es->WndCol < 0)
1451 EDIT_KeyHScroll(hwnd, SB_LINEUP);
1453 else if (IsMultiLine() && es->CurrLine != 0)
1455 EDIT_Upward(hwnd);
1456 EDIT_End(hwnd);
1461 /*********************************************************************
1462 * EDIT_End
1464 * End key: move to end of line.
1467 void EDIT_End(HWND hwnd)
1469 WND *wndPtr = WIN_FindWndPtr(hwnd);
1470 EDITSTATE *es =
1471 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1473 while (*CurrChar && *CurrChar != '\n')
1475 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
1476 es->CurrCol++;
1479 if (es->WndCol >= ClientWidth(wndPtr))
1481 es->wleft = es->WndCol - ClientWidth(wndPtr) + HSCROLLDIM;
1482 es->WndCol -= es->wleft;
1483 InvalidateRect(hwnd, NULL, FALSE);
1484 UpdateWindow(hwnd);
1489 /*********************************************************************
1490 * EDIT_Home
1492 * Home key: move to beginning of line.
1495 void EDIT_Home(HWND hwnd)
1497 WND *wndPtr = WIN_FindWndPtr(hwnd);
1498 EDITSTATE *es =
1499 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1501 es->CurrCol = es->WndCol = 0;
1502 if (es->wleft != 0)
1504 es->wleft = 0;
1505 InvalidateRect(hwnd, NULL, FALSE);
1506 UpdateWindow(hwnd);
1511 /*********************************************************************
1512 * EDIT_StickEnd
1514 * Stick the cursor to the end of the line.
1517 void EDIT_StickEnd(HWND hwnd)
1519 WND *wndPtr = WIN_FindWndPtr(hwnd);
1520 EDITSTATE *es =
1521 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1522 int len = EDIT_LineLength(hwnd, es->CurrLine);
1523 char *cp = EDIT_TextLine(hwnd, es->CurrLine);
1524 char currpel;
1526 es->CurrCol = min(len, es->CurrCol);
1527 es->WndCol = min(EDIT_StrLength(hwnd, cp, len, 0) - es->wleft, es->WndCol);
1528 currpel = EDIT_StrLength(hwnd, cp, es->CurrCol, 0);
1530 if (es->wleft > currpel)
1532 es->wleft = max(0, currpel - 20);
1533 es->WndCol = currpel - es->wleft;
1534 UpdateWindow(hwnd);
1536 else if (currpel - es->wleft >= ClientWidth(wndPtr))
1538 es->wleft = currpel - (ClientWidth(wndPtr) - 5);
1539 es->WndCol = currpel - es->wleft;
1540 UpdateWindow(hwnd);
1545 /*********************************************************************
1546 * WM_KEYDOWN message function
1549 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam)
1551 WND *wndPtr = WIN_FindWndPtr(hwnd);
1552 EDITSTATE *es =
1553 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1555 dprintf_edit(stddeb,"EDIT_KeyDownMsg: key=%x\n", wParam);
1557 HideCaret(hwnd);
1558 switch (wParam)
1560 case VK_UP:
1561 if (SelMarked(es))
1562 EDIT_ClearSel(hwnd);
1563 if (IsMultiLine())
1564 EDIT_Upward(hwnd);
1565 else
1566 EDIT_Backward(hwnd);
1567 break;
1569 case VK_DOWN:
1570 if (SelMarked(es))
1571 EDIT_ClearSel(hwnd);
1572 if (IsMultiLine())
1573 EDIT_Downward(hwnd);
1574 else
1575 EDIT_Forward(hwnd);
1576 break;
1578 case VK_RIGHT:
1579 if (SelMarked(es))
1580 EDIT_ClearSel(hwnd);
1581 EDIT_Forward(hwnd);
1582 break;
1584 case VK_LEFT:
1585 if (SelMarked(es))
1586 EDIT_ClearSel(hwnd);
1587 EDIT_Backward(hwnd);
1588 break;
1590 case VK_HOME:
1591 if (SelMarked(es))
1592 EDIT_ClearSel(hwnd);
1593 EDIT_Home(hwnd);
1594 break;
1596 case VK_END:
1597 if (SelMarked(es))
1598 EDIT_ClearSel(hwnd);
1599 EDIT_End(hwnd);
1600 break;
1602 case VK_PRIOR:
1603 if (IsMultiLine())
1605 if (SelMarked(es))
1606 EDIT_ClearSel(hwnd);
1607 EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
1609 break;
1611 case VK_NEXT:
1612 if (IsMultiLine())
1614 if (SelMarked(es))
1615 EDIT_ClearSel(hwnd);
1616 EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
1618 break;
1620 case VK_BACK:
1621 if (SelMarked(es))
1622 EDIT_DeleteSel(hwnd);
1623 else
1625 if (es->CurrCol == 0 && es->CurrLine == 0)
1626 break;
1627 EDIT_Backward(hwnd);
1628 EDIT_DelKey(hwnd);
1630 break;
1632 case VK_DELETE:
1633 if (SelMarked(es))
1634 EDIT_DeleteSel(hwnd);
1635 else
1636 EDIT_DelKey(hwnd);
1637 break;
1640 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1641 ShowCaret(hwnd);
1645 /*********************************************************************
1646 * EDIT_KeyHScroll
1648 * Scroll text horizontally using cursor keys.
1651 void EDIT_KeyHScroll(HWND hwnd, WORD opt)
1653 int hscrollpos;
1654 WND *wndPtr = WIN_FindWndPtr(hwnd);
1655 EDITSTATE *es =
1656 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1658 if (opt == SB_LINEDOWN)
1660 es->wleft += HSCROLLDIM;
1661 es->WndCol -= HSCROLLDIM;
1663 else
1665 if (es->wleft == 0)
1666 return;
1667 if (es->wleft - HSCROLLDIM < 0)
1669 es->WndCol += es->wleft;
1670 es->wleft = 0;
1672 else
1674 es->wleft -= HSCROLLDIM;
1675 es->WndCol += HSCROLLDIM;
1679 InvalidateRect(hwnd, NULL, FALSE);
1680 UpdateWindow(hwnd);
1682 if (IsHScrollBar())
1684 hscrollpos = EDIT_ComputeHScrollPos(hwnd);
1685 SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE);
1690 /*********************************************************************
1691 * EDIT_KeyVScrollLine
1693 * Scroll text vertically by one line using keyboard.
1696 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt)
1698 RECT rc;
1699 int y, vscrollpos;
1700 WND *wndPtr = WIN_FindWndPtr(hwnd);
1701 EDITSTATE *es =
1702 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1704 if (!IsMultiLine())
1705 return;
1707 if (opt == SB_LINEDOWN)
1709 /* move down one line */
1710 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1711 return;
1712 es->wtop++;
1714 else
1716 /* move up one line */
1717 if (es->wtop == 0)
1718 return;
1719 --es->wtop;
1722 if (IsWindowVisible(hwnd))
1724 /* adjust client bottom to nearest whole line */
1725 GetClientRect(hwnd, &rc);
1726 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1728 if (opt == SB_LINEUP)
1730 /* move up one line (scroll window down) */
1731 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1732 /* write top line */
1733 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1734 es->WndRow++;
1736 else
1738 /* move down one line (scroll window up) */
1739 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1740 /* write bottom line */
1741 y = (((rc.bottom - rc.top) / es->txtht) - 1);
1742 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1743 --es->WndRow;
1747 /* reset the vertical scroll bar */
1748 if (IsVScrollBar())
1750 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1751 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1756 /*********************************************************************
1757 * EDIT_KeyVScrollPage
1759 * Scroll text vertically by one page using keyboard.
1762 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
1764 int vscrollpos;
1765 WND *wndPtr = WIN_FindWndPtr(hwnd);
1766 EDITSTATE *es =
1767 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1769 if (IsMultiLine())
1771 if (opt == SB_PAGEUP)
1773 if (es->wtop)
1774 es->wtop -= ClientHeight(wndPtr, es);
1776 else
1778 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1780 es->wtop += ClientHeight(wndPtr, es);
1781 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1782 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1785 if (es->wtop < 0)
1786 es->wtop = 0;
1788 es->CurrLine = es->wtop + es->WndRow;
1789 EDIT_StickEnd(hwnd);
1790 InvalidateRect(hwnd, NULL, TRUE);
1791 UpdateWindow(hwnd);
1793 /* reset the vertical scroll bar */
1794 if (IsVScrollBar())
1796 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1797 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1803 /*********************************************************************
1804 * EDIT_KeyVScrollDoc
1806 * Scroll text to top and bottom of document using keyboard.
1809 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt)
1811 int vscrollpos;
1812 WND *wndPtr = WIN_FindWndPtr(hwnd);
1813 EDITSTATE *es =
1814 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1816 if (!IsMultiLine())
1817 return;
1819 if (opt == SB_TOP)
1820 es->wtop = es->wleft = 0;
1821 else if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1823 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1824 es->wleft = 0;
1827 es->CurrLine = es->wlines;
1828 es->WndRow = es->wlines - es->wtop;
1829 EDIT_End(hwnd);
1830 InvalidateRect(hwnd, NULL, TRUE);
1831 UpdateWindow(hwnd);
1833 /* reset the vertical scroll bar */
1834 if (IsVScrollBar())
1836 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1837 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1842 /*********************************************************************
1843 * EDIT_ComputeVScrollPos
1845 * Compute the vertical scroll bar position from the window
1846 * position and text width.
1849 int EDIT_ComputeVScrollPos(HWND hwnd)
1851 int vscrollpos;
1852 short minpos, maxpos;
1853 WND *wndPtr = WIN_FindWndPtr(hwnd);
1854 EDITSTATE *es =
1855 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1857 GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos);
1859 if (es->wlines > ClientHeight(wndPtr, es))
1860 vscrollpos = (double)(es->wtop) / (double)(es->wlines -
1861 ClientHeight(wndPtr, es)) * (maxpos - minpos);
1862 else
1863 vscrollpos = minpos;
1865 return vscrollpos;
1869 /*********************************************************************
1870 * EDIT_ComputeHScrollPos
1872 * Compute the horizontal scroll bar position from the window
1873 * position and text width.
1876 int EDIT_ComputeHScrollPos(HWND hwnd)
1878 int hscrollpos;
1879 short minpos, maxpos;
1880 WND *wndPtr = WIN_FindWndPtr(hwnd);
1881 EDITSTATE *es =
1882 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1884 GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos);
1886 if (es->textwidth > ClientWidth(wndPtr))
1887 hscrollpos = (double)(es->wleft) / (double)(es->textwidth -
1888 ClientWidth(wndPtr)) * (maxpos - minpos);
1889 else
1890 hscrollpos = minpos;
1892 return hscrollpos;
1896 /*********************************************************************
1897 * EDIT_DelKey
1899 * Delete character to right of cursor.
1902 void EDIT_DelKey(HWND hwnd)
1904 RECT rc;
1905 WND *wndPtr = WIN_FindWndPtr(hwnd);
1906 EDITSTATE *es =
1907 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1908 char *currchar = CurrChar;
1909 BOOL repaint = *currchar == '\n';
1911 if (IsMultiLine() && *currchar == '\n' && *(currchar + 1) == '\0')
1912 return;
1913 strcpy(currchar, currchar + 1);
1914 NOTIFY_PARENT(hwnd, EN_UPDATE);
1916 if (repaint)
1918 EDIT_BuildTextPointers(hwnd);
1919 GetClientRect(hwnd, &rc);
1920 rc.top = es->WndRow * es->txtht;
1921 InvalidateRect(hwnd, &rc, FALSE);
1922 UpdateWindow(hwnd);
1924 else
1926 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1);
1927 EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop);
1930 es->TextChanged = TRUE;
1931 NOTIFY_PARENT(hwnd, EN_CHANGE);
1934 /*********************************************************************
1935 * WM_VSCROLL message function
1938 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1940 WND *wndPtr = WIN_FindWndPtr(hwnd);
1941 EDITSTATE *es =
1942 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1944 if (IsMultiLine())
1946 HideCaret(hwnd);
1948 switch (wParam)
1950 case SB_LINEUP:
1951 case SB_LINEDOWN:
1952 EDIT_VScrollLine(hwnd, wParam);
1953 break;
1955 case SB_PAGEUP:
1956 case SB_PAGEDOWN:
1957 EDIT_VScrollPage(hwnd, wParam);
1958 break;
1962 SetCaretPos(es->WndCol, es->WndRow);
1963 ShowCaret(hwnd);
1967 /*********************************************************************
1968 * EDIT_VScrollLine
1970 * Scroll text vertically by one line using scrollbars.
1973 void EDIT_VScrollLine(HWND hwnd, WORD opt)
1975 RECT rc;
1976 int y;
1977 WND *wndPtr = WIN_FindWndPtr(hwnd);
1978 EDITSTATE *es =
1979 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1981 dprintf_edit(stddeb,"EDIT_VScrollLine: direction=%d\n", opt);
1983 if (opt == SB_LINEDOWN)
1985 /* move down one line */
1986 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1987 return;
1988 es->wtop++;
1990 else
1992 /* move up one line */
1993 if (es->wtop == 0)
1994 return;
1995 --es->wtop;
1998 if (IsWindowVisible(hwnd))
2000 /* adjust client bottom to nearest whole line */
2001 GetClientRect(hwnd, &rc);
2002 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
2004 if (opt == SB_LINEUP)
2006 /* move up one line (scroll window down) */
2007 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
2008 /* write top line */
2009 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
2010 es->WndRow++;
2012 else
2014 /* move down one line (scroll window up) */
2015 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
2016 /* write bottom line */
2017 y = ((rc.bottom - rc.top / es->txtht) - 1);
2018 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
2019 --es->WndRow;
2025 /*********************************************************************
2026 * EDIT_VScrollPage
2028 * Scroll text vertically by one page using keyboard.
2031 void EDIT_VScrollPage(HWND hwnd, WORD opt)
2033 int vscrollpos;
2034 WND *wndPtr = WIN_FindWndPtr(hwnd);
2035 EDITSTATE *es =
2036 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2038 if (opt == SB_PAGEUP)
2040 if (es->wtop)
2041 es->wtop -= ClientHeight(wndPtr, es);
2043 else
2045 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
2047 es->wtop += ClientHeight(wndPtr, es);
2048 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
2049 es->wtop = es->wlines - ClientHeight(wndPtr, es);
2052 if (es->wtop < 0)
2053 es->wtop = 0;
2055 InvalidateRect(hwnd, NULL, TRUE);
2056 UpdateWindow(hwnd);
2058 /* reset the vertical scroll bar */
2059 if (IsVScrollBar())
2061 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
2062 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
2067 /*********************************************************************
2068 * WM_HSCROLL message function
2071 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
2073 WND *wndPtr = WIN_FindWndPtr(hwnd);
2074 EDITSTATE *es =
2075 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2077 switch (wParam)
2079 case SB_LINEUP:
2080 case SB_LINEDOWN:
2081 HideCaret(hwnd);
2083 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2084 ShowCaret(hwnd);
2085 break;
2090 /*********************************************************************
2091 * WM_SIZE message function
2094 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam)
2096 WND *wndPtr = WIN_FindWndPtr(hwnd);
2097 EDITSTATE *es =
2098 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2100 if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return;
2102 InvalidateRect(hwnd, NULL, TRUE);
2103 es->PaintBkgd = TRUE;
2104 UpdateWindow(hwnd);
2108 /*********************************************************************
2109 * WM_LBUTTONDOWN message function
2112 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam)
2114 char *cp;
2115 int len;
2116 BOOL end = FALSE;
2117 WND *wndPtr = WIN_FindWndPtr(hwnd);
2118 EDITSTATE *es =
2119 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2121 if (SelMarked(es))
2122 EDIT_ClearSel(hwnd);
2124 es->WndRow = HIWORD(lParam) / es->txtht;
2125 if (es->WndRow > es->wlines - es->wtop - 1)
2127 if (es->wlines)
2128 es->WndRow = es->wlines - es->wtop - 1;
2129 else
2130 es->WndRow = 0;
2131 end = TRUE;
2133 es->CurrLine = es->wtop + es->WndRow;
2135 cp = EDIT_TextLine(hwnd, es->CurrLine);
2136 len = EDIT_LineLength(hwnd, es->CurrLine);
2137 es->WndCol = LOWORD(lParam);
2138 if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
2139 es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
2140 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2142 ButtonDown = TRUE;
2143 ButtonRow = es->CurrLine;
2144 ButtonCol = es->CurrCol;
2148 /*********************************************************************
2149 * WM_MOUSEMOVE message function
2152 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
2154 if (wParam != MK_LBUTTON)
2155 return;
2157 if (ButtonDown)
2159 EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
2160 TextMarking = TRUE;
2161 ButtonDown = FALSE;
2164 if (TextMarking)
2165 EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
2169 /*********************************************************************
2170 * EDIT_PixelToChar
2172 * Convert a pixel offset in the given row to a character offset,
2173 * adjusting the pixel offset to the nearest whole character if
2174 * necessary.
2177 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
2179 int ch = 0, i = 0, s_i;
2180 char *text;
2182 dprintf_edit(stddeb,"EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
2184 text = EDIT_TextLine(hwnd, row);
2185 while (i < *pixel)
2187 s_i = i;
2188 i += EDIT_CharWidth(hwnd, (BYTE)(*(text + ch)), i);
2189 ch++;
2192 /* if stepped past _pixel_, go back a character */
2193 if (i - *pixel)
2195 i = s_i;
2196 --ch;
2198 *pixel = i;
2199 return ch;
2203 /*********************************************************************
2204 * WM_SETTEXT message function
2207 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam)
2209 int len;
2210 char *text;
2211 WND *wndPtr = WIN_FindWndPtr(hwnd);
2212 EDITSTATE *es =
2213 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2215 if (strlen((char *)lParam) <= es->MaxTextLen)
2217 len = strlen((char *)lParam);
2218 EDIT_ClearText(hwnd);
2219 es->textlen = len;
2220 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, len + 3);
2221 text = EDIT_HeapAddr(hwnd, es->hText);
2222 strcpy(text, (char *)lParam);
2223 text[len + 1] = '\0';
2224 text[len + 2] = '\0';
2225 EDIT_BuildTextPointers(hwnd);
2226 InvalidateRect(hwnd, NULL, TRUE);
2227 es->PaintBkgd = TRUE;
2228 es->TextChanged = TRUE;
2229 return 0L;
2231 else
2232 return EN_ERRSPACE;
2236 /*********************************************************************
2237 * EDIT_ClearText
2239 * Clear text from text buffer.
2242 void EDIT_ClearText(HWND hwnd)
2244 WND *wndPtr = WIN_FindWndPtr(hwnd);
2245 EDITSTATE *es =
2246 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2247 unsigned int blen = EditBufLen(wndPtr) + 2;
2248 char *text;
2250 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, blen);
2251 text = EDIT_HeapAddr(hwnd, es->hText);
2252 memset(text, 0, blen);
2253 es->textlen = 0;
2254 es->wlines = 0;
2255 es->CurrLine = es->CurrCol = 0;
2256 es->WndRow = es->WndCol = 0;
2257 es->wleft = es->wtop = 0;
2258 es->textwidth = 0;
2259 es->TextChanged = FALSE;
2260 EDIT_ClearTextPointers(hwnd);
2264 /*********************************************************************
2265 * EM_SETSEL message function
2268 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
2270 int so, eo;
2271 WND *wndPtr = WIN_FindWndPtr(hwnd);
2272 EDITSTATE *es =
2273 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2275 so = LOWORD(lParam);
2276 eo = HIWORD(lParam);
2278 if (so == -1) /* if so == -1, clear selection */
2280 EDIT_ClearSel(hwnd);
2281 return;
2284 if (so == eo) /* if so == eo, set caret only */
2286 EDIT_GetLineCol(hwnd, so, &(es->CurrLine), &(es->CurrCol));
2287 es->WndRow = es->CurrLine - es->wtop;
2289 if (!wParam)
2291 if (es->WndRow < 0 || es->WndRow > ClientHeight(wndPtr, es))
2293 es->wtop = es->CurrLine;
2294 es->WndRow = 0;
2296 es->WndCol = EDIT_StrLength(hwnd,
2297 EDIT_TextLine(hwnd, es->CurrLine),
2298 es->CurrCol, 0) - es->wleft;
2299 if (es->WndCol > ClientWidth(wndPtr))
2301 es->wleft = es->WndCol;
2302 es->WndCol = 0;
2304 else if (es->WndCol < 0)
2306 es->wleft += es->WndCol;
2307 es->WndCol = 0;
2311 else /* otherwise set selection */
2313 if (so > eo)
2314 swap(&so, &eo);
2316 EDIT_GetLineCol(hwnd, so, &(es->SelBegLine), &(es->SelBegCol));
2317 EDIT_GetLineCol(hwnd, eo, &(es->SelEndLine), &(es->SelEndCol));
2318 es->CurrLine = es->SelEndLine;
2319 es->CurrCol = es->SelEndCol;
2320 es->WndRow = es->SelEndLine - es->wtop;
2322 if (!wParam) /* don't suppress scrolling of text */
2324 if (es->WndRow < 0)
2326 es->wtop = es->SelEndLine;
2327 es->WndRow = 0;
2329 else if (es->WndRow > ClientHeight(wndPtr, es))
2331 es->wtop += es->WndRow - ClientHeight(wndPtr, es);
2332 es->WndRow = ClientHeight(wndPtr, es);
2334 es->WndCol = EDIT_StrLength(hwnd,
2335 EDIT_TextLine(hwnd, es->SelEndLine),
2336 es->SelEndCol, 0) - es->wleft;
2337 if (es->WndCol > ClientWidth(wndPtr))
2339 es->wleft += es->WndCol - ClientWidth(wndPtr);
2340 es->WndCol = ClientWidth(wndPtr);
2342 else if (es->WndCol < 0)
2344 es->wleft += es->WndCol;
2345 es->WndCol = 0;
2349 InvalidateRect(hwnd, NULL, TRUE);
2350 UpdateWindow(hwnd);
2355 /*********************************************************************
2356 * EDIT_GetLineCol
2358 * Return line and column in text buffer from character offset.
2361 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
2363 int lineno;
2364 char *cp, *cp1;
2365 WND *wndPtr = WIN_FindWndPtr(hwnd);
2366 EDITSTATE *es =
2367 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2368 char *text = EDIT_HeapAddr(hwnd, es->hText);
2369 unsigned int *textPtrs =
2370 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2372 /* check for (0,0) */
2373 if (!off)
2375 *line = 0;
2376 *col = 0;
2377 return;
2380 if (off > strlen(text)) off = strlen(text);
2381 cp1 = text;
2382 for (lineno = 0; lineno < es->wlines; lineno++)
2384 cp = text + *(textPtrs + lineno);
2385 if (off == (int)(cp - text))
2387 *line = lineno;
2388 *col = 0;
2389 return;
2391 if (off < (int)(cp - text))
2392 break;
2393 cp1 = cp;
2395 *line = lineno - 1;
2396 *col = off - (int)(cp1 - text);
2397 #if 0
2398 if (*(text + *col) == '\0')
2399 (*col)--;
2400 #endif
2404 /*********************************************************************
2405 * EDIT_DeleteSel
2407 * Delete the current selected text (if any)
2410 void EDIT_DeleteSel(HWND hwnd)
2412 char *bbl, *bel;
2413 int len;
2414 WND *wndPtr = WIN_FindWndPtr(hwnd);
2415 EDITSTATE *es =
2416 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2418 if (SelMarked(es))
2420 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
2421 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
2422 len = (int)(bel - bbl);
2423 EDIT_SaveDeletedText(hwnd, bbl, len, es->SelBegLine, es->SelBegCol);
2424 es->TextChanged = TRUE;
2425 strcpy(bbl, bel);
2427 es->CurrLine = es->SelBegLine;
2428 es->CurrCol = es->SelBegCol;
2429 es->WndRow = es->SelBegLine - es->wtop;
2430 if (es->WndRow < 0)
2432 es->wtop = es->SelBegLine;
2433 es->WndRow = 0;
2435 es->WndCol = EDIT_StrLength(hwnd, bbl - es->SelBegCol,
2436 es->SelBegCol, 0) - es->wleft;
2438 EDIT_BuildTextPointers(hwnd);
2439 es->PaintBkgd = TRUE;
2440 EDIT_ClearSel(hwnd);
2445 /*********************************************************************
2446 * EDIT_ClearSel
2448 * Clear the current selection.
2451 void EDIT_ClearSel(HWND hwnd)
2453 WND *wndPtr = WIN_FindWndPtr(hwnd);
2454 EDITSTATE *es =
2455 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2457 es->SelBegLine = es->SelBegCol = 0;
2458 es->SelEndLine = es->SelEndCol = 0;
2460 InvalidateRect(hwnd, NULL, TRUE);
2461 UpdateWindow(hwnd);
2465 /*********************************************************************
2466 * EDIT_TextLineNumber
2468 * Return the line number in the text buffer of the supplied
2469 * character pointer.
2472 int EDIT_TextLineNumber(HWND hwnd, char *lp)
2474 int lineno;
2475 char *cp;
2476 WND *wndPtr = WIN_FindWndPtr(hwnd);
2477 EDITSTATE *es =
2478 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2479 char *text = EDIT_HeapAddr(hwnd, es->hText);
2480 unsigned int *textPtrs =
2481 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2483 for (lineno = 0; lineno < es->wlines; lineno++)
2485 cp = text + *(textPtrs + lineno);
2486 if (cp == lp)
2487 return lineno;
2488 if (cp > lp)
2489 break;
2491 return lineno - 1;
2495 /*********************************************************************
2496 * EDIT_SetAnchor
2498 * Set down anchor for text marking.
2501 void EDIT_SetAnchor(HWND hwnd, int row, int col)
2503 BOOL sel = FALSE;
2504 WND *wndPtr = WIN_FindWndPtr(hwnd);
2505 EDITSTATE *es =
2506 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2508 if (SelMarked(es))
2509 sel = TRUE;
2510 EDIT_ClearSel(hwnd);
2511 es->SelBegLine = es->SelEndLine = row;
2512 es->SelBegCol = es->SelEndCol = col;
2513 if (sel)
2515 InvalidateRect(hwnd, NULL, FALSE);
2516 UpdateWindow(hwnd);
2521 /*********************************************************************
2522 * EDIT_ExtendSel
2524 * Extend selection to the given screen co-ordinates.
2527 void EDIT_ExtendSel(HWND hwnd, int x, int y)
2529 int bbl, bel, bbc, bec;
2530 char *cp;
2531 int len, line;
2532 BOOL end = FALSE;
2533 WND *wndPtr = WIN_FindWndPtr(hwnd);
2534 EDITSTATE *es =
2535 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2537 dprintf_edit(stddeb,"EDIT_ExtendSel: x=%d, y=%d\n", x, y);
2539 bbl = es->SelEndLine;
2540 bbc = es->SelEndCol;
2541 line = es->wtop + y / es->txtht;
2542 if (line > es->wlines)
2543 line = es->wlines;
2544 cp = EDIT_TextLine(hwnd, line);
2545 len = EDIT_LineLength(hwnd, line);
2547 es->WndRow = y / es->txtht;
2548 if (es->WndRow > es->wlines - es->wtop - 1)
2550 if (es->wlines)
2551 es->WndRow = es->wlines - es->wtop - 1;
2552 else
2553 es->WndRow = 0;
2554 end = TRUE;
2556 es->CurrLine = es->wtop + es->WndRow;
2557 es->SelEndLine = es->CurrLine;
2559 es->WndCol = x;
2560 if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
2561 es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
2562 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2563 es->SelEndCol = es->CurrCol - 1;
2565 bel = es->SelEndLine;
2566 bec = es->SelEndCol;
2568 /* return if no new characters to mark */
2569 if (bbl == bel && bbc == bec)
2570 return;
2572 /* put lowest marker first */
2573 if (bbl > bel)
2575 swap(&bbl, &bel);
2576 swap(&bbc, &bec);
2578 if (bbl == bel && bbc > bec)
2579 swap(&bbc, &bec);
2581 for (y = bbl; y <= bel; y++)
2583 if (y == bbl && y == bel)
2584 EDIT_WriteSel(hwnd, y, bbc, bec);
2585 else if (y == bbl)
2586 EDIT_WriteSel(hwnd, y, bbc, -1);
2587 else if (y == bel)
2588 EDIT_WriteSel(hwnd, y, 0, bec);
2589 else
2590 EDIT_WriteSel(hwnd, y, 0, -1);
2595 /*********************************************************************
2596 * EDIT_WriteSel
2598 * Display selection by reversing pixels in selected text.
2599 * If end == -1, selection applies to end of line.
2602 void EDIT_WriteSel(HWND hwnd, int y, int start, int end)
2604 RECT rc;
2605 int scol, ecol;
2606 char *cp;
2607 HDC hdc;
2608 HBRUSH hbrush, holdbrush;
2609 int olddm;
2610 WND *wndPtr = WIN_FindWndPtr(hwnd);
2611 EDITSTATE *es =
2612 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2614 dprintf_edit(stddeb,"EDIT_WriteSel: y=%d start=%d end=%d\n", y, start,end);
2615 GetClientRect(hwnd, &rc);
2617 /* make sure y is within the window */
2618 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
2619 return;
2621 /* get pointer to text */
2622 cp = EDIT_TextLine(hwnd, y);
2624 /* get length of line if end == -1 */
2625 if (end == -1)
2626 end = EDIT_LineLength(hwnd, y);
2628 scol = EDIT_StrLength(hwnd, cp, start, 0);
2629 if (scol > rc.right) return;
2630 if (scol < rc.left) scol = rc.left;
2631 ecol = EDIT_StrLength(hwnd, cp, end, 0);
2632 if (ecol < rc.left) return;
2633 if (ecol > rc.right) ecol = rc.right;
2635 hdc = GetDC(hwnd);
2636 hbrush = GetStockObject(BLACK_BRUSH);
2637 holdbrush = (HBRUSH)SelectObject(hdc, (HANDLE)hbrush);
2638 olddm = SetROP2(hdc, R2_XORPEN);
2639 Rectangle(hdc, scol, y * es->txtht, ecol, (y + 1) * es->txtht);
2640 SetROP2(hdc, olddm);
2641 SelectObject(hdc, (HANDLE)holdbrush);
2642 ReleaseDC(hwnd, hdc);
2646 /*********************************************************************
2647 * EDIT_StopMarking
2649 * Stop text marking (selection).
2652 void EDIT_StopMarking(HWND hwnd)
2654 WND *wndPtr = WIN_FindWndPtr(hwnd);
2655 EDITSTATE *es =
2656 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2658 TextMarking = FALSE;
2659 if (es->SelBegLine > es->SelEndLine)
2661 swap(&(es->SelBegLine), &(es->SelEndLine));
2662 swap(&(es->SelBegCol), &(es->SelEndCol));
2664 if (es->SelBegLine == es->SelEndLine && es->SelBegCol > es->SelEndCol)
2665 swap(&(es->SelBegCol), &(es->SelEndCol));
2669 /*********************************************************************
2670 * EM_GETLINE message function
2673 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam)
2675 char *cp, *cp1;
2676 int len;
2677 char *buffer = (char *)lParam;
2679 cp = EDIT_TextLine(hwnd, wParam);
2680 cp1 = EDIT_TextLine(hwnd, wParam + 1);
2681 len = min((int)(cp1 - cp), (WORD)(*buffer));
2682 strncpy(buffer, cp, len);
2684 return (LONG)len;
2688 /*********************************************************************
2689 * EM_GETSEL message function
2692 LONG EDIT_GetSelMsg(HWND hwnd)
2694 int so, eo;
2695 WND *wndPtr = WIN_FindWndPtr(hwnd);
2696 EDITSTATE *es =
2697 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2698 unsigned int *textPtrs =
2699 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2701 so = *(textPtrs + es->SelBegLine) + es->SelBegCol;
2702 eo = *(textPtrs + es->SelEndLine) + es->SelEndCol;
2704 return MAKELONG(so, eo);
2708 /*********************************************************************
2709 * EM_REPLACESEL message function
2712 void EDIT_ReplaceSel(HWND hwnd, LONG lParam)
2714 EDIT_DeleteSel(hwnd);
2715 EDIT_InsertText(hwnd, (char *)lParam, strlen((char *)lParam));
2716 InvalidateRect(hwnd, NULL, TRUE);
2717 UpdateWindow(hwnd);
2721 /*********************************************************************
2722 * EDIT_InsertText
2724 * Insert text at current line and column.
2727 void EDIT_InsertText(HWND hwnd, char *str, int len)
2729 int plen;
2730 WND *wndPtr = WIN_FindWndPtr(hwnd);
2731 EDITSTATE *es =
2732 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2733 char *text = EDIT_HeapAddr(hwnd, es->hText);
2735 plen = strlen(text) + len;
2736 if (plen + 1 > es->textlen)
2738 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + len);
2739 es->textlen = plen + 1;
2741 memmove(CurrChar + len, CurrChar, strlen(CurrChar) + 1);
2742 memcpy(CurrChar, str, len);
2744 EDIT_BuildTextPointers(hwnd);
2745 es->PaintBkgd = TRUE;
2746 es->TextChanged = TRUE;
2748 EDIT_GetLineCol(hwnd, (int)((CurrChar + len) - text), &(es->CurrLine),
2749 &(es->CurrCol));
2750 es->WndRow = es->CurrLine - es->wtop;
2751 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2752 es->CurrCol, 0) - es->wleft;
2756 /*********************************************************************
2757 * EM_LINEFROMCHAR message function
2760 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam)
2762 int row, col;
2763 WND *wndPtr = WIN_FindWndPtr(hwnd);
2764 EDITSTATE *es =
2765 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2767 if (wParam == (WORD)-1)
2768 return (LONG)(es->SelBegLine);
2769 else
2770 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2772 return (LONG)row;
2776 /*********************************************************************
2777 * EM_LINEINDEX message function
2780 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam)
2782 WND *wndPtr = WIN_FindWndPtr(hwnd);
2783 EDITSTATE *es =
2784 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2785 unsigned int *textPtrs =
2786 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2788 if (wParam == (WORD)-1)
2789 wParam = es->CurrLine;
2791 return (LONG)(*(textPtrs + wParam));
2795 /*********************************************************************
2796 * EM_LINELENGTH message function
2799 LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam)
2801 int row, col, len;
2802 int sbl, sbc, sel, sec;
2803 WND *wndPtr = WIN_FindWndPtr(hwnd);
2804 EDITSTATE *es =
2805 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2806 unsigned int *textPtrs =
2807 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2809 if (wParam == (WORD)-1)
2811 if (SelMarked(es))
2813 sbl = es->SelBegLine;
2814 sbc = es->SelBegCol;
2815 sel = es->SelEndLine;
2816 sec = es->SelEndCol;
2818 if (sbl > sel)
2820 swap(&sbl, &sel);
2821 swap(&sbc, &sec);
2823 if (sbl == sel && sbc > sec)
2824 swap(&sbc, &sec);
2826 if (sbc == sel)
2828 len = *(textPtrs + sbl + 1) - *(textPtrs + sbl) - 1;
2829 return len - sec - sbc;
2832 len = *(textPtrs + sel + 1) - *(textPtrs + sel) - sec - 1;
2833 return len + sbc;
2835 else /* no selection marked */
2837 len = *(textPtrs + es->CurrLine + 1) -
2838 *(textPtrs + es->CurrLine) - 1;
2839 return len;
2842 else /* line number specified */
2844 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2845 len = *(textPtrs + row + 1) - *(textPtrs + row);
2846 return len;
2851 /*********************************************************************
2852 * WM_SETFONT message function
2855 void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam)
2857 HDC hdc;
2858 TEXTMETRIC tm;
2859 HFONT oldfont;
2860 WND *wndPtr = WIN_FindWndPtr(hwnd);
2861 EDITSTATE *es =
2862 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2863 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
2865 es->hFont = wParam;
2866 hdc = GetDC(hwnd);
2867 oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
2868 GetCharWidth(hdc, 0, 255, charWidths);
2869 GetTextMetrics(hdc, &tm);
2870 es->txtht = tm.tmHeight + tm.tmExternalLeading;
2871 SelectObject(hdc, (HANDLE)oldfont);
2872 ReleaseDC(hwnd, hdc);
2874 es->WndRow = (es->CurrLine - es->wtop) / es->txtht;
2875 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2876 es->CurrCol, 0) - es->wleft;
2878 InvalidateRect(hwnd, NULL, TRUE);
2879 es->PaintBkgd = TRUE;
2880 if (lParam) UpdateWindow(hwnd);
2884 /*********************************************************************
2885 * EDIT_SaveDeletedText
2887 * Save deleted text in deleted text buffer.
2890 void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len,
2891 int line, int col)
2893 char *text;
2894 WND *wndPtr = WIN_FindWndPtr(hwnd);
2895 EDITSTATE *es =
2896 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2898 es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE);
2899 if (!es->hDeletedText) return;
2900 text = (char *)GlobalLock(es->hDeletedText);
2901 memcpy(text, deltext, len);
2902 GlobalUnlock(es->hDeletedText);
2903 es->DeletedLength = len;
2904 es->DeletedCurrLine = line;
2905 es->DeletedCurrCol = col;
2909 /*********************************************************************
2910 * EDIT_ClearDeletedText
2912 * Clear deleted text buffer.
2915 void EDIT_ClearDeletedText(HWND hwnd)
2917 WND *wndPtr = WIN_FindWndPtr(hwnd);
2918 EDITSTATE *es =
2919 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2921 GlobalFree(es->hDeletedText);
2922 es->hDeletedText = 0;
2923 es->DeletedLength = 0;
2927 /*********************************************************************
2928 * EM_UNDO message function
2931 LONG EDIT_UndoMsg(HWND hwnd)
2933 char *text;
2934 WND *wndPtr = WIN_FindWndPtr(hwnd);
2935 EDITSTATE *es =
2936 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2938 if (es->hDeletedText)
2940 text = (char *)GlobalLock(es->hDeletedText);
2941 es->CurrLine = es->DeletedCurrLine;
2942 es->CurrCol = es->DeletedCurrCol;
2943 EDIT_InsertText(hwnd, text, es->DeletedLength);
2944 GlobalUnlock(es->hDeletedText);
2945 EDIT_ClearDeletedText(hwnd);
2947 es->SelBegLine = es->CurrLine;
2948 es->SelBegCol = es->CurrCol;
2949 EDIT_GetLineCol(hwnd, (int)((CurrChar + es->DeletedLength) - text),
2950 &(es->CurrLine), &(es->CurrCol));
2951 es->WndRow = es->CurrLine - es->wtop;
2952 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2953 es->CurrCol, 0) - es->wleft;
2954 es->SelEndLine = es->CurrLine;
2955 es->SelEndCol = es->CurrCol;
2957 InvalidateRect(hwnd, NULL, TRUE);
2958 UpdateWindow(hwnd);
2959 return 1;
2961 else
2962 return 0;
2966 /*********************************************************************
2967 * EDIT_HeapAlloc
2969 * Allocate the specified number of bytes on the specified local heap.
2972 unsigned int EDIT_HeapAlloc(HWND hwnd, int bytes)
2974 WND *wndPtr = WIN_FindWndPtr(hwnd);
2975 unsigned int ret;
2976 ret = ((unsigned int)HEAP_Alloc((MDESC **)
2977 *(LONG *)(wndPtr->wExtra + 2),
2978 GMEM_MOVEABLE, bytes) & 0xffff);
2979 if (ret == 0)
2980 printf("EDIT_HeapAlloc: Out of heap-memory\n");
2981 return ret;
2985 /*********************************************************************
2986 * EDIT_HeapAddr
2988 * Return the address of the memory pointed to by the handle.
2991 void *EDIT_HeapAddr(HWND hwnd, unsigned int handle)
2993 WND *wndPtr = WIN_FindWndPtr(hwnd);
2995 return ((void *)((handle) ? ((handle) | ((unsigned int)
2996 (*(MDESC **)*(LONG *)(wndPtr->wExtra + 2))
2997 & 0xffff0000)) : 0));
3001 /*********************************************************************
3002 * EDIT_HeapReAlloc
3004 * Reallocate the memory pointed to by the handle.
3007 unsigned int EDIT_HeapReAlloc(HWND hwnd, unsigned int handle, int bytes)
3009 WND *wndPtr = WIN_FindWndPtr(hwnd);
3011 return ((unsigned int)HEAP_ReAlloc((MDESC **)
3012 *(LONG *)(wndPtr->wExtra + 2),
3013 EDIT_HeapAddr(hwnd, handle),
3014 bytes, GMEM_MOVEABLE) & 0xffff);
3018 /*********************************************************************
3019 * EDIT_HeapFree
3021 * Frees the memory pointed to by the handle.
3024 void EDIT_HeapFree(HWND hwnd, unsigned int handle)
3026 WND *wndPtr = WIN_FindWndPtr(hwnd);
3028 HEAP_Free((MDESC **)*(LONG *)(wndPtr->wExtra + 2),
3029 EDIT_HeapAddr(hwnd, handle));
3033 /*********************************************************************
3034 * EDIT_HeapSize
3036 * Return the size of the given object on the local heap.
3039 unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle)
3041 WND *wndPtr = WIN_FindWndPtr(hwnd);
3043 return HEAP_LocalSize((MDESC **)*(LONG *)(wndPtr->wExtra + 2), handle);
3047 /*********************************************************************
3048 * EM_SETHANDLE message function
3051 void EDIT_SetHandleMsg(HWND hwnd, WORD wParam)
3053 WND *wndPtr = WIN_FindWndPtr(hwnd);
3054 EDITSTATE *es =
3055 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3057 if (IsMultiLine())
3059 es->hText = wParam;
3060 es->MaxTextLen = EDIT_HeapSize(hwnd, es->hText);
3061 es->wlines = 0;
3062 es->wtop = es->wleft = 0;
3063 es->CurrLine = es->CurrCol = 0;
3064 es->WndRow = es->WndCol = 0;
3065 es->TextChanged = FALSE;
3066 es->textwidth = 0;
3067 es->SelBegLine = es->SelBegCol = 0;
3068 es->SelEndLine = es->SelEndCol = 0;
3070 es->PaintBkgd = TRUE;
3071 InvalidateRect(hwnd, NULL, TRUE);
3072 UpdateWindow(hwnd);
3077 /*********************************************************************
3078 * EM_SETTABSTOPS message function
3081 LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam)
3083 unsigned short *tabstops;
3084 WND *wndPtr = WIN_FindWndPtr(hwnd);
3085 EDITSTATE *es =
3086 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3088 es->NumTabStops = wParam;
3089 if (wParam == 0)
3090 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, 1);
3091 else if (wParam == 1)
3093 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, 1);
3094 tabstops = (unsigned short *)EDIT_HeapAddr(hwnd, es->hTabStops);
3095 *tabstops = (unsigned short)lParam;
3097 else
3099 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, wParam);
3100 tabstops = (unsigned short *)EDIT_HeapAddr(hwnd, es->hTabStops);
3101 memcpy(tabstops, (unsigned short *)lParam, wParam);
3103 return 0L;
3107 /*********************************************************************
3108 * EDIT_CopyToClipboard
3110 * Copy the specified text to the clipboard.
3113 void EDIT_CopyToClipboard(HWND hwnd)
3115 HANDLE hMem;
3116 char *lpMem;
3117 int i, len;
3118 char *bbl, *bel;
3119 WND *wndPtr = WIN_FindWndPtr(hwnd);
3120 EDITSTATE *es =
3121 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3123 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
3124 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
3125 len = (int)(bel - bbl);
3127 hMem = GlobalAlloc(GHND, (DWORD)(len + 1));
3128 lpMem = GlobalLock(hMem);
3130 for (i = 0; i < len; i++)
3131 *lpMem++ = *bbl++;
3133 GlobalUnlock(hMem);
3134 OpenClipboard(hwnd);
3135 EmptyClipboard();
3136 SetClipboardData(CF_TEXT, hMem);
3137 CloseClipboard();
3141 /*********************************************************************
3142 * WM_PASTE message function
3145 void EDIT_PasteMsg(HWND hwnd)
3147 HANDLE hClipMem;
3148 char *lpClipMem;
3150 OpenClipboard(hwnd);
3151 if (!(hClipMem = GetClipboardData(CF_TEXT)))
3153 /* no text in clipboard */
3154 CloseClipboard();
3155 return;
3157 lpClipMem = GlobalLock(hClipMem);
3158 EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem));
3159 GlobalUnlock(hClipMem);
3160 CloseClipboard();
3161 InvalidateRect(hwnd, NULL, TRUE);
3162 UpdateWindow(hwnd);
3166 /*********************************************************************
3167 * Utility functions
3170 void swap(int *a, int *b)
3172 int x;
3174 x = *a;
3175 *a = *b;
3176 *b = x;