Release 950403
[wine/multimedia.git] / controls / edit.c
blob2109aa3a56481df0dfcd338c1d62a09b32350acf
1 /*
2 * Edit control
4 * Copyright David W. Metcalfe, 1994
6 * Release 3, July 1994
7 * April 1995 bug fixes (William Magro)
9 static char Copyright[] = "Copyright David W. Metcalfe, 1994";
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <windows.h>
16 #include "local.h"
17 #include "win.h"
18 #include "class.h"
19 #include "user.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 BOOL HaveFocus; /* TRUE if this edit has the focus */
70 } EDITSTATE;
73 #define ClientWidth(wndPtr) \
74 (wndPtr->rectClient.right > wndPtr->rectClient.left ? \
75 wndPtr->rectClient.right - wndPtr->rectClient.left : 0)
76 #define ClientHeight(wndPtr, es) \
77 (wndPtr->rectClient.bottom > wndPtr->rectClient.top ? \
78 (wndPtr->rectClient.bottom - wndPtr->rectClient.top) / es->txtht : 0)
79 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
80 ? EDITLEN : ENTRYLEN)
81 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
82 #define SelMarked(es) (es->SelBegLine != 0 || es->SelBegCol != 0 || \
83 es->SelEndLine != 0 || es->SelEndCol != 0)
84 #define ROUNDUP(numer, denom) (((numer) % (denom)) \
85 ? ((((numer) + (denom)) / (denom)) * (denom)) \
86 : (numer) + (denom))
88 /* macros to access window styles */
89 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
90 #define IsAutoHScroll() (wndPtr->dwStyle & ES_AUTOHSCROLL)
91 #define IsMultiLine() (wndPtr->dwStyle & ES_MULTILINE)
92 #define IsVScrollBar() (wndPtr->dwStyle & WS_VSCROLL)
93 #define IsHScrollBar() (wndPtr->dwStyle & WS_HSCROLL)
95 /* internal variables */
96 static BOOL TextMarking; /* TRUE if text marking in progress */
97 static BOOL ButtonDown; /* TRUE if left mouse button down */
98 static int ButtonRow; /* row in text buffer when button pressed */
99 static int ButtonCol; /* col in text buffer when button pressed */
102 LONG EditWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
103 long EDIT_NCCreateMsg(HWND hwnd, LONG lParam);
104 long EDIT_CreateMsg(HWND hwnd, LONG lParam);
105 void EDIT_ClearTextPointers(HWND hwnd);
106 void EDIT_BuildTextPointers(HWND hwnd);
107 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var);
108 void EDIT_PaintMsg(HWND hwnd);
109 HANDLE EDIT_GetTextLine(HWND hwnd, int selection);
110 char *EDIT_TextLine(HWND hwnd, int sel);
111 int EDIT_StrLength(HWND hwnd, unsigned char *str, int len, int pcol);
112 int EDIT_LineLength(HWND hwnd, int num);
113 void EDIT_WriteTextLine(HWND hwnd, RECT *rc, int y);
114 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
115 int col, RECT *rc, BOOL blank, BOOL reverse);
116 HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff);
117 void EDIT_CharMsg(HWND hwnd, WORD wParam);
118 void EDIT_KeyTyped(HWND hwnd, short ch);
119 int EDIT_CharWidth(HWND hwnd, short ch, int pcol);
120 int EDIT_GetNextTabStop(HWND hwnd, int pcol);
121 void EDIT_Forward(HWND hwnd);
122 void EDIT_Downward(HWND hwnd);
123 void EDIT_Upward(HWND hwnd);
124 void EDIT_Backward(HWND hwnd);
125 void EDIT_End(HWND hwnd);
126 void EDIT_Home(HWND hwnd);
127 void EDIT_StickEnd(HWND hwnd);
128 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam);
129 void EDIT_KeyHScroll(HWND hwnd, WORD opt);
130 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt);
131 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt);
132 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt);
133 int EDIT_ComputeVScrollPos(HWND hwnd);
134 int EDIT_ComputeHScrollPos(HWND hwnd);
135 void EDIT_DelKey(HWND hwnd);
136 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
137 void EDIT_VScrollLine(HWND hwnd, WORD opt);
138 void EDIT_VScrollPage(HWND hwnd, WORD opt);
139 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam);
140 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam);
141 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam);
142 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam);
143 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel);
144 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam);
145 void EDIT_ClearText(HWND hwnd);
146 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam);
147 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col);
148 void EDIT_DeleteSel(HWND hwnd);
149 void EDIT_ClearSel(HWND hwnd);
150 int EDIT_TextLineNumber(HWND hwnd, char *lp);
151 void EDIT_SetAnchor(HWND hwnd, int row, int col);
152 void EDIT_ExtendSel(HWND hwnd, INT x, INT y);
153 void EDIT_WriteSel(HWND hwnd, int y, int start, int end);
154 void EDIT_StopMarking(HWND hwnd);
155 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
156 LONG EDIT_GetSelMsg(HWND hwnd);
157 void EDIT_ReplaceSel(HWND hwnd, LONG lParam);
158 void EDIT_InsertText(HWND hwnd, char *str, int len);
159 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam);
160 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam);
161 LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam);
162 void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam);
163 void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len, int line,
164 int col);
165 void EDIT_ClearDeletedText(HWND hwnd);
166 LONG EDIT_UndoMsg(HWND hwnd);
167 unsigned int EDIT_HeapAlloc(HWND hwnd, int bytes);
168 void *EDIT_HeapAddr(HWND hwnd, unsigned int handle);
169 unsigned int EDIT_HeapReAlloc(HWND hwnd, unsigned int handle, int bytes);
170 void EDIT_HeapFree(HWND hwnd, unsigned int handle);
171 unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle);
172 void EDIT_SetHandleMsg(HWND hwnd, WORD wParam);
173 LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam);
174 void EDIT_CopyToClipboard(HWND hwnd);
175 void EDIT_PasteMsg(HWND hwnd);
176 void swap(int *a, int *b);
179 LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
181 LONG lResult = 0L;
182 char *textPtr;
183 int len;
184 WND *wndPtr = WIN_FindWndPtr(hwnd);
185 EDITSTATE *es =
186 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
188 switch (uMsg) {
189 case EM_CANUNDO:
190 lResult = es->hDeletedText;
191 break;
193 case EM_EMPTYUNDOBUFFER:
194 EDIT_ClearDeletedText(hwnd);
195 break;
197 case EM_FMTLINES:
198 fprintf(stdnimp,"edit: EM_FMTLINES message received\n");
199 if (!wParam)
200 lResult = 1L;
201 else
202 lResult = 0L;
203 break;
205 case EM_GETFIRSTVISIBLELINE:
206 lResult = es->wtop;
207 break;
209 case EM_GETHANDLE:
210 lResult = es->hText;
211 break;
213 case EM_GETLINE:
214 if (IsMultiLine())
215 lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
216 else
217 lResult = 0L;
218 break;
220 case EM_GETLINECOUNT:
221 if (IsMultiLine())
222 lResult = es->wlines;
223 else
224 lResult = 0L;
225 break;
227 case EM_GETMODIFY:
228 lResult = es->TextChanged;
229 break;
231 case EM_GETPASSWORDCHAR:
232 fprintf(stdnimp,"edit: cannot process EM_GETPASSWORDCHAR message\n");
233 break;
235 case EM_GETRECT:
236 GetWindowRect(hwnd, (LPRECT)PTR_SEG_TO_LIN(lParam));
237 break;
239 case EM_GETSEL:
240 lResult = EDIT_GetSelMsg(hwnd);
241 break;
243 case EM_GETWORDBREAKPROC:
244 fprintf(stdnimp,"edit: cannot process EM_GETWORDBREAKPROC message\n");
245 break;
247 case EM_LIMITTEXT:
248 if (wParam)
249 es->MaxTextLen = wParam;
250 else if (IsMultiLine())
251 es->MaxTextLen = 65535;
252 else
253 es->MaxTextLen = 32767;
254 break;
256 case EM_LINEFROMCHAR:
257 lResult = EDIT_LineFromCharMsg(hwnd, wParam);
258 break;
260 case EM_LINEINDEX:
261 if (IsMultiLine())
262 lResult = EDIT_LineIndexMsg(hwnd, wParam);
263 else
264 lResult = 0L;
265 break;
267 case EM_LINELENGTH:
268 lResult = EDIT_LineLengthMsg(hwnd, wParam);
269 break;
271 case EM_LINESCROLL:
272 fprintf(stdnimp,"edit: cannot process EM_LINESCROLL message\n");
273 break;
275 case EM_REPLACESEL:
276 HideCaret(hwnd);
277 EDIT_ReplaceSel(hwnd, lParam);
278 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
279 ShowCaret(hwnd);
280 break;
282 case EM_SETHANDLE:
283 HideCaret(hwnd);
284 EDIT_SetHandleMsg(hwnd, wParam);
285 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
286 ShowCaret(hwnd);
287 break;
289 case EM_SETMODIFY:
290 es->TextChanged = wParam;
291 break;
293 case EM_SETPASSWORDCHAR:
294 fprintf(stdnimp,"edit: cannot process EM_SETPASSWORDCHAR message\n");
295 break;
297 case EM_SETREADONLY:
298 fprintf(stdnimp,"edit: cannot process EM_SETREADONLY message\n");
299 break;
301 case EM_SETRECT:
302 case EM_SETRECTNP:
303 fprintf(stdnimp,"edit: cannot process EM_SETRECT(NP) message\n");
304 break;
306 case EM_SETSEL:
307 HideCaret(hwnd);
308 EDIT_SetSelMsg(hwnd, wParam, lParam);
309 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
310 ShowCaret(hwnd);
311 break;
313 case EM_SETTABSTOPS:
314 lResult = EDIT_SetTabStopsMsg(hwnd, wParam, lParam);
315 break;
317 case EM_SETWORDBREAKPROC:
318 fprintf(stdnimp,"edit: cannot process EM_SETWORDBREAKPROC message\n");
319 break;
321 case EM_UNDO:
322 HideCaret(hwnd);
323 lResult = EDIT_UndoMsg(hwnd);
324 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
325 ShowCaret(hwnd);
326 break;
328 case WM_GETDLGCODE:
329 return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
331 case WM_CHAR:
332 EDIT_CharMsg(hwnd, wParam);
333 break;
335 case WM_COPY:
336 EDIT_CopyToClipboard(hwnd);
337 EDIT_ClearSel(hwnd);
338 break;
340 case WM_CREATE:
341 lResult = EDIT_CreateMsg(hwnd, lParam);
342 break;
344 case WM_CUT:
345 EDIT_CopyToClipboard(hwnd);
346 EDIT_DeleteSel(hwnd);
347 break;
349 case WM_DESTROY:
350 EDIT_HeapFree(hwnd, es->hTextPtrs);
351 EDIT_HeapFree(hwnd, es->hCharWidths);
352 EDIT_HeapFree(hwnd, es->hText);
353 EDIT_HeapFree(hwnd, (HANDLE)(*(wndPtr->wExtra)));
354 break;
356 case WM_ENABLE:
357 InvalidateRect(hwnd, NULL, FALSE);
358 break;
360 case WM_GETTEXT:
361 textPtr = EDIT_HeapAddr(hwnd, es->hText);
362 if ((int)wParam > (len = strlen(textPtr)))
364 strcpy((char *)PTR_SEG_TO_LIN(lParam), textPtr);
365 lResult = (DWORD)len ;
367 else
368 lResult = 0L;
369 break;
371 case WM_GETTEXTLENGTH:
372 textPtr = EDIT_HeapAddr(hwnd, es->hText);
373 lResult = (DWORD)strlen(textPtr);
374 break;
376 case WM_HSCROLL:
377 EDIT_HScrollMsg(hwnd, wParam, lParam);
378 break;
380 case WM_KEYDOWN:
381 EDIT_KeyDownMsg(hwnd, wParam);
382 break;
384 case WM_KILLFOCUS:
385 es->HaveFocus = FALSE;
386 DestroyCaret();
387 if (SelMarked(es)) EDIT_ClearSel(hwnd);
388 NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
389 break;
391 case WM_LBUTTONDOWN:
392 HideCaret(hwnd);
393 SetFocus(hwnd);
394 SetCapture(hwnd);
395 EDIT_LButtonDownMsg(hwnd, wParam, lParam);
396 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
397 ShowCaret(hwnd);
398 break;
400 case WM_LBUTTONUP:
401 if (GetCapture() != hwnd) break;
402 ReleaseCapture();
403 ButtonDown = FALSE;
404 if (TextMarking)
405 EDIT_StopMarking(hwnd);
406 break;
408 case WM_MOUSEMOVE:
409 if (es->HaveFocus)
410 EDIT_MouseMoveMsg(hwnd, wParam, lParam);
411 break;
413 case WM_MOVE:
414 lResult = 0;
415 break;
417 case WM_NCCREATE:
418 lResult = EDIT_NCCreateMsg(hwnd, lParam);
419 break;
421 case WM_PAINT:
422 EDIT_PaintMsg(hwnd);
423 break;
425 case WM_PASTE:
426 EDIT_PasteMsg(hwnd);
427 break;
429 case WM_SETFOCUS:
430 es->HaveFocus = TRUE;
431 CreateCaret(hwnd, 0, 2, es->txtht);
432 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
433 ShowCaret(hwnd);
434 NOTIFY_PARENT(hwnd, EN_SETFOCUS);
435 break;
437 case WM_SETFONT:
438 HideCaret(hwnd);
439 EDIT_SetFont(hwnd, wParam, lParam);
440 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
441 ShowCaret(hwnd);
442 break;
443 #if 0
444 case WM_SETREDRAW:
445 dprintf_edit(stddeb, "WM_SETREDRAW: hwnd=%d, wParam=%x\n",
446 hwnd, wParam);
447 lResult = 0;
448 break;
449 #endif
450 case WM_SETTEXT:
451 EDIT_SetTextMsg(hwnd, lParam);
452 break;
454 case WM_SIZE:
455 EDIT_SizeMsg(hwnd, wParam, lParam);
456 lResult = 0;
457 break;
459 case WM_VSCROLL:
460 EDIT_VScrollMsg(hwnd, wParam, lParam);
461 break;
463 default:
464 lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
465 break;
468 return lResult;
472 /*********************************************************************
473 * WM_NCCREATE message function
476 long EDIT_NCCreateMsg(HWND hwnd, LONG lParam)
478 CREATESTRUCT *createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
479 WND *wndPtr = WIN_FindWndPtr(hwnd);
480 EDITSTATE *es;
481 unsigned int *textPtrs;
482 char *text;
484 /* store pointer to local or global heap in window structure so that */
485 /* EDITSTATE structure itself can be stored on local heap */
486 #if 0
487 if (HEAP_LocalFindHeap(createStruct->hInstance)!=NULL)
488 (MDESC **)*(LONG *)(wndPtr->wExtra + 2) =
489 &HEAP_LocalFindHeap(createStruct->hInstance)->free_list;
490 else
492 (MDESC **)*(LONG *)(wndPtr->wExtra + 2) =
493 GlobalLock(createStruct->hInstance);
494 /* GlobalUnlock(createStruct->hInstance); */
496 #endif
497 /* allocate space for state variable structure */
498 (HANDLE)(*(wndPtr->wExtra)) = EDIT_HeapAlloc(hwnd, sizeof(EDITSTATE));
499 es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
500 es->hTextPtrs = EDIT_HeapAlloc(hwnd, sizeof(int));
501 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
502 es->hCharWidths = EDIT_HeapAlloc(hwnd, 256 * sizeof(short));
504 /* --- text buffer */
505 es->MaxTextLen = MAXTEXTLEN + 1;
506 if (!(createStruct->lpszName))
508 es->textlen = EditBufLen(wndPtr) + 1;
509 es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
510 text = EDIT_HeapAddr(hwnd, es->hText);
511 memset(text, 0, es->textlen + 2);
512 es->wlines = 0;
513 es->textwidth = 0;
514 EDIT_ClearTextPointers(hwnd);
515 if(IsMultiLine()) strcpy(text, "\r\n");
516 EDIT_BuildTextPointers(hwnd);
518 else
520 char *windowName = (char *)PTR_SEG_TO_LIN( createStruct->lpszName );
521 if (strlen(windowName) < EditBufLen(wndPtr))
523 es->textlen = EditBufLen(wndPtr) + 1;
524 es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
525 text = EDIT_HeapAddr(hwnd, es->hText);
526 strcpy(text, windowName);
527 if(IsMultiLine()) strcat(text, "\r\n");
528 es->textlen += 2;
529 *(text + es->textlen) = '\0';
531 else
533 es->hText = EDIT_HeapAlloc(hwnd, strlen(windowName) + 4);
534 text = EDIT_HeapAddr(hwnd, es->hText);
535 strcpy(text, windowName);
536 if(IsMultiLine()) strcat(text, "\r\n");
537 es->textlen = strlen(windowName) + 3;
538 *(text + es->textlen) = '\0';
540 *(text + es->textlen + 1) = '\0';
541 EDIT_BuildTextPointers(hwnd);
544 /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
545 /* the corresponding WS_* style is set */
546 if (createStruct->style & WS_VSCROLL)
547 wndPtr->dwStyle |= ES_AUTOVSCROLL;
548 if (createStruct->style & WS_HSCROLL)
549 wndPtr->dwStyle |= ES_AUTOHSCROLL;
551 /* remove the WS_CAPTION style if it has been set - this is really a */
552 /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
553 if (wndPtr->dwStyle & WS_BORDER && wndPtr->dwStyle & WS_DLGFRAME)
554 wndPtr->dwStyle ^= WS_DLGFRAME;
556 return 1;
560 /*********************************************************************
561 * WM_CREATE message function
564 long EDIT_CreateMsg(HWND hwnd, LONG lParam)
566 HDC hdc;
567 WND *wndPtr = WIN_FindWndPtr(hwnd);
568 EDITSTATE *es =
569 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
570 CLASS *classPtr;
571 short *charWidths;
572 TEXTMETRIC tm;
573 char *text;
575 /* initialize state variable structure */
576 hdc = GetDC(hwnd);
578 /* --- char width array */
579 /* only initialise chars <= 32 as X returns strange widths */
580 /* for other chars */
581 charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
582 memset(charWidths, 0, 256 * sizeof(short));
583 GetCharWidth(hdc, 32, 254, &charWidths[32]);
585 /* --- other structure variables */
586 GetTextMetrics(hdc, &tm);
587 es->txtht = tm.tmHeight + tm.tmExternalLeading;
588 es->wtop = es->wleft = 0;
589 es->CurrCol = es->CurrLine = 0;
590 es->WndCol = es->WndRow = 0;
591 es->TextChanged = FALSE;
592 es->SelBegLine = es->SelBegCol = 0;
593 es->SelEndLine = es->SelEndCol = 0;
594 es->hFont = 0;
595 es->hDeletedText = 0;
596 es->DeletedLength = 0;
597 es->NumTabStops = 0;
598 es->hTabStops = EDIT_HeapAlloc(hwnd, sizeof(int));
600 /* allocate space for a line full of blanks to speed up */
601 /* line filling */
602 es->hBlankLine = EDIT_HeapAlloc(hwnd, (ClientWidth(wndPtr) /
603 charWidths[32]) + 2);
604 text = EDIT_HeapAddr(hwnd, es->hBlankLine);
605 memset(text, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
607 /* set up text cursor for edit class */
608 CLASS_FindClassByName("EDIT", 0, &classPtr);
609 classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);
611 /* paint background on first WM_PAINT */
612 es->PaintBkgd = TRUE;
614 ReleaseDC(hwnd, hdc);
615 return 0L;
619 /*********************************************************************
620 * EDIT_ClearTextPointers
622 * Clear and initialize text line pointer array.
625 void EDIT_ClearTextPointers(HWND hwnd)
627 unsigned int *textPtrs;
628 WND *wndPtr = WIN_FindWndPtr(hwnd);
629 EDITSTATE *es =
630 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
632 es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs, sizeof(int));
633 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
634 *textPtrs = 0;
638 /*********************************************************************
639 * EDIT_BuildTextPointers
641 * Build array of pointers to text lines.
644 #define INITLINES 100
646 void EDIT_BuildTextPointers(HWND hwnd)
648 WND *wndPtr = WIN_FindWndPtr(hwnd);
649 char *text, *cp;
650 int incrs = INITLINES;
651 unsigned int off, len;
652 EDITSTATE *es;
653 unsigned int *textPtrs;
654 short *charWidths;
656 es = (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
657 text = EDIT_HeapAddr(hwnd, es->hText);
658 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
659 charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
661 es->textwidth = es->wlines = 0;
662 cp = text;
664 /* advance through text buffer */
665 while (*cp)
667 /* increase size of text pointer array */
668 if (incrs == INITLINES)
670 incrs = 0;
671 es->hTextPtrs = EDIT_HeapReAlloc(hwnd, es->hTextPtrs,
672 (es->wlines + INITLINES) * sizeof(int));
673 textPtrs = (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
675 off = (unsigned int)(cp - text); /* offset of beginning of line */
676 *(textPtrs + es->wlines) = off;
677 es->wlines++;
678 incrs++;
679 len = 0;
681 /* advance through current line */
682 while (*cp && *cp != '\n')
684 len += EDIT_CharWidth(hwnd, (BYTE)*cp, len);
685 /* width of line in pixels */
686 cp++;
688 es->textwidth = max(es->textwidth, len);
689 if (*cp)
690 cp++; /* skip '\n' */
693 off = (unsigned int)(cp - text);
694 *(textPtrs + es->wlines) = off;
698 /*********************************************************************
699 * EDIT_ModTextPointers
701 * Modify text pointers from a specified position.
704 void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
706 WND *wndPtr = WIN_FindWndPtr(hwnd);
707 EDITSTATE *es =
708 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
709 unsigned int *textPtrs =
710 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
712 while (lineno < es->wlines)
713 *(textPtrs + lineno++) += var;
717 /*********************************************************************
718 * WM_PAINT message function
721 void EDIT_PaintMsg(HWND hwnd)
723 PAINTSTRUCT ps;
724 HDC hdc;
725 int y;
726 RECT rc;
727 WND *wndPtr = WIN_FindWndPtr(hwnd);
728 EDITSTATE *es =
729 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
731 hdc = BeginPaint(hwnd, &ps);
732 rc = ps.rcPaint;
734 dprintf_edit(stddeb,"WM_PAINT: rc=(%d,%d), (%d,%d)\n", rc.left, rc.top,
735 rc.right, rc.bottom);
737 if (es->PaintBkgd)
738 FillWindow(GetParent(hwnd), hwnd, hdc, CTLCOLOR_EDIT);
740 for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
742 if (y < (IsMultiLine() ? es->wlines : 1) - es->wtop)
743 EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
746 EndPaint(hwnd, &ps);
750 /*********************************************************************
751 * EDIT_GetTextLine
753 * Get a copy of the text in the specified line.
756 HANDLE EDIT_GetTextLine(HWND hwnd, int selection)
758 char *line;
759 HANDLE hLine;
760 int len = 0;
761 char *cp, *cp1;
763 dprintf_edit(stddeb,"GetTextLine %d\n", selection);
764 cp = cp1 = EDIT_TextLine(hwnd, selection);
765 /* advance through line */
766 while (*cp && *cp != '\r')
768 len++;
769 cp++;
772 /* store selected line and return handle */
773 hLine = EDIT_HeapAlloc(hwnd, len + 6);
774 line = (char *)EDIT_HeapAddr(hwnd, hLine);
775 memmove(line, cp1, len);
776 line[len] = '\0';
777 return hLine;
781 /*********************************************************************
782 * EDIT_TextLine
784 * Return a pointer to the text in the specified line.
787 char *EDIT_TextLine(HWND hwnd, int sel)
789 WND *wndPtr = WIN_FindWndPtr(hwnd);
790 EDITSTATE *es =
791 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
792 char *text = EDIT_HeapAddr(hwnd, es->hText);
793 unsigned int *textPtrs =
794 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
796 if(sel>es->wlines)return NULL;
797 return (text + *(textPtrs + sel));
801 /*********************************************************************
802 * EDIT_StrLength
804 * Return length of string _str_ of length _len_ characters in pixels.
805 * The current column offset in pixels _pcol_ is required to calculate
806 * the width of a tab.
809 int EDIT_StrLength(HWND hwnd, unsigned char *str, int len, int pcol)
811 int i, plen = 0;
813 for (i = 0; i < len; i++)
814 plen += EDIT_CharWidth(hwnd, (BYTE)(*(str + i)), pcol + plen);
816 dprintf_edit(stddeb,"EDIT_StrLength: returning %d\n", plen);
817 return plen;
821 /*********************************************************************
822 * EDIT_LineLength
824 * Return length of line _num_ in characters.
827 int EDIT_LineLength(HWND hwnd, int num)
829 char *cp = EDIT_TextLine(hwnd, num);
830 char *cp1;
832 if(!cp)return 0;
833 cp1 = strchr(cp, '\r');
834 return cp1 ? (int)(cp1 - cp) : strlen(cp);
838 /*********************************************************************
839 * EDIT_WriteTextLine
841 * Write the line of text at offset _y_ in text buffer to a window.
844 void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
846 int len = 0;
847 HANDLE hLine;
848 unsigned char *lp;
849 int lnlen, lnlen1;
850 int col, off = 0;
851 int sbl, sel, sbc, sec;
852 RECT rc;
853 WND *wndPtr = WIN_FindWndPtr(hwnd);
854 EDITSTATE *es =
855 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
857 /* initialize rectangle if NULL, else copy */
858 if (rect)
859 CopyRect(&rc, rect);
860 else
861 GetClientRect(hwnd, &rc);
863 dprintf_edit(stddeb,"WriteTextLine %d\n", y);
865 /* make sure y is inside the window */
866 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
868 dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
869 return;
872 /* make sure rectangle is within window */
873 if (rc.left >= ClientWidth(wndPtr) - 1)
875 dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
876 rc.left);
877 return;
879 if (rc.right <= 0)
881 dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
882 rc.right);
883 return;
885 if (y - es->wtop < (rc.top / es->txtht) ||
886 y - es->wtop > (rc.bottom / es->txtht))
888 dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is outside window\n", y);
889 return;
892 /* get the text and length of line */
893 if ((hLine = EDIT_GetTextLine(hwnd, y)) == 0)
894 return;
895 lp = (unsigned char *)EDIT_HeapAddr(hwnd, hLine);
896 lnlen = EDIT_StrLength(hwnd, lp, strlen(lp), 0);
897 lnlen1 = lnlen;
899 /* build the line to display */
900 if (lnlen < (es->wleft + rc.left))
902 lnlen = 0;
903 return;
905 else
907 off += es->wleft;
908 lnlen -= off;
911 if (lnlen > rc.left)
913 off += rc.left;
914 lnlen = lnlen1 - off;
916 len = min(lnlen, rc.right - rc.left);
918 if (SelMarked(es))
920 sbl = es->SelBegLine;
921 sel = es->SelEndLine;
922 sbc = es->SelBegCol;
923 sec = es->SelEndCol;
925 /* put lowest marker first */
926 if (sbl > sel)
928 swap(&sbl, &sel);
929 swap(&sbc, &sec);
931 if (sbl == sel && sbc > sec)
932 swap(&sbc, &sec);
934 if (y < sbl || y > sel)
935 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
936 TRUE, FALSE);
937 else if (y > sbl && y < sel)
938 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
939 TRUE, TRUE);
940 else if (y == sbl)
942 col = EDIT_StrLength(hwnd, lp, sbc, 0);
943 if (col > (es->wleft + rc.left))
945 len = min(col - off, rc.right - off);
946 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
947 rc.left, &rc, FALSE, FALSE);
948 off = col;
950 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);
963 else
965 len = min(lnlen - off, rc.right - off);
966 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
967 off - es->wleft, &rc, TRUE, TRUE);
970 else
972 len = min(lnlen - off, rc.right - off);
973 if (col < (es->wleft + rc.right))
974 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
975 off - es->wleft, &rc, TRUE, TRUE);
978 else if (y == sel)
980 col = EDIT_StrLength(hwnd, lp, sec, 0);
981 if (col < (es->wleft + rc.right))
983 len = min(col - off, rc.right - off);
984 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
985 off - es->wleft, &rc, FALSE, TRUE);
986 off = col;
987 len = min(lnlen - off, rc.right - off);
988 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
989 off - es->wleft, &rc, TRUE, FALSE);
993 else
994 EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
995 TRUE, FALSE);
997 EDIT_HeapFree(hwnd, hLine);
1001 /*********************************************************************
1002 * EDIT_WriteText
1004 * Write text to a window
1005 * lp - text line
1006 * off - offset in text line (in pixels)
1007 * len - length from off (in pixels)
1008 * row - line in window
1009 * col - column in window
1010 * rc - rectangle in which to display line
1011 * blank - blank remainder of line?
1012 * reverse - reverse color of line?
1015 void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
1016 int col, RECT *rc, BOOL blank, BOOL reverse)
1018 HDC hdc;
1019 HANDLE hStr;
1020 char *str, *cp, *cp1;
1021 int diff=0, num_spaces, tabwidth, scol;
1022 HRGN hrgnClip;
1023 COLORREF oldTextColor, oldBkgdColor;
1024 HFONT oldfont;
1025 WND *wndPtr = WIN_FindWndPtr(hwnd);
1026 EDITSTATE *es =
1027 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1028 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
1029 char *blanks = (char *)EDIT_HeapAddr(hwnd, es->hBlankLine);
1031 dprintf_edit(stddeb,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
1033 if( off < 0 ) {
1034 len += off;
1035 col -= off;
1036 off = 0;
1039 hdc = GetDC(hwnd);
1040 hStr = EDIT_GetStr(hwnd, lp, off, len, &diff);
1041 str = (char *)EDIT_HeapAddr(hwnd, hStr);
1042 hrgnClip = CreateRectRgnIndirect(rc);
1043 SelectClipRgn(hdc, hrgnClip);
1045 if (es->hFont)
1046 oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
1048 SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
1049 MAKELPARAM(hwnd, CTLCOLOR_EDIT));
1051 if (reverse)
1053 oldBkgdColor = GetBkColor(hdc);
1054 oldTextColor = GetTextColor(hdc);
1055 SetBkColor(hdc, oldTextColor);
1056 SetTextColor(hdc, oldBkgdColor);
1059 if (strlen(blanks) < (ClientWidth(wndPtr) / charWidths[32]) + 2)
1061 es->hBlankLine = EDIT_HeapReAlloc(hwnd, es->hBlankLine,
1062 (ClientWidth(wndPtr) / charWidths[32]) + 2);
1063 blanks = EDIT_HeapAddr(hwnd, es->hBlankLine);
1064 memset(blanks, ' ', (ClientWidth(wndPtr) / charWidths[32]) + 2);
1067 if (!(cp = strchr(str, VK_TAB)))
1068 TextOut(hdc, col - diff, row * es->txtht, str, strlen(str));
1069 else
1071 TextOut(hdc, col - diff, row * es->txtht, str, (int)(cp - str));
1072 scol = EDIT_StrLength(hwnd, str, (int)(cp - str), 0);
1073 tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
1074 num_spaces = tabwidth / charWidths[32] + 1;
1075 TextOut(hdc, scol, row * es->txtht, blanks, num_spaces);
1076 cp++;
1077 scol += tabwidth;
1079 while ((cp1 = strchr(cp, VK_TAB)))
1081 TextOut(hdc, scol, row * es->txtht, cp, (int)(cp1 - cp));
1082 scol += EDIT_StrLength(hwnd, cp, (int)(cp1 - cp), scol);
1083 tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
1084 num_spaces = tabwidth / charWidths[32] + 1;
1085 TextOut(hdc, scol, row * es->txtht, blanks, num_spaces);
1086 cp = ++cp1;
1087 scol += tabwidth;
1090 TextOut(hdc, scol, row * es->txtht, cp, strlen(cp));
1093 if (reverse)
1095 SetBkColor(hdc, oldBkgdColor);
1096 SetTextColor(hdc, oldTextColor);
1099 /* blank out remainder of line if appropriate */
1100 if (blank)
1102 if ((rc->right - col) > len)
1104 num_spaces = (rc->right - col - len) / charWidths[32];
1105 TextOut(hdc, col + len, row * es->txtht, blanks, num_spaces);
1109 if (es->hFont)
1110 SelectObject(hdc, (HANDLE)oldfont);
1112 EDIT_HeapFree(hwnd, hStr);
1113 ReleaseDC(hwnd, hdc);
1117 /*********************************************************************
1118 * EDIT_GetStr
1120 * Return sub-string starting at pixel _off_ of length _len_ pixels.
1121 * If _off_ is part way through a character, the negative offset of
1122 * the beginning of the character is returned in _diff_, else _diff_
1123 * will be zero.
1126 HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff)
1128 HANDLE hStr;
1129 char *str;
1130 int ch = 0, i = 0, j, s_i=0;
1131 int ch1;
1133 dprintf_edit(stddeb,"EDIT_GetStr lp='%s' off=%d len=%d\n", lp, off, len);
1135 if (off < 0) off = 0;
1136 while (i < off)
1138 s_i = i;
1139 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
1140 ch++;
1142 /* if stepped past _off_, go back a character */
1143 if (i - off)
1145 i = s_i;
1146 ch--;
1148 *diff = off - i;
1149 ch1 = ch;
1150 while (i < len + off)
1152 if (*(lp + ch) == '\r' || *(lp + ch) == '\n')
1153 break;
1154 i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
1155 ch++;
1158 hStr = EDIT_HeapAlloc(hwnd, ch - ch1 + 3);
1159 str = (char *)EDIT_HeapAddr(hwnd, hStr);
1160 for (i = ch1, j = 0; i < ch; i++, j++)
1161 str[j] = lp[i];
1162 str[j] = '\0';
1163 dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str);
1164 return hStr;
1168 /*********************************************************************
1169 * WM_CHAR message function
1172 void EDIT_CharMsg(HWND hwnd, WORD wParam)
1174 WND *wndPtr = WIN_FindWndPtr(hwnd);
1176 dprintf_edit(stddeb,"EDIT_CharMsg: wParam=%c\n", (char)wParam);
1178 switch (wParam)
1180 case '\r':
1181 case '\n':
1182 if (!IsMultiLine())
1183 break;
1184 wParam = '\n';
1185 EDIT_KeyTyped(hwnd, wParam);
1186 break;
1188 case VK_TAB:
1189 if (!IsMultiLine())
1190 break;
1191 EDIT_KeyTyped(hwnd, wParam);
1192 break;
1194 default:
1195 if (wParam >= 20 && wParam <= 254 && wParam != 127 )
1196 EDIT_KeyTyped(hwnd, wParam);
1197 break;
1202 /*********************************************************************
1203 * EDIT_KeyTyped
1205 * Process keystrokes that produce displayable characters.
1208 void EDIT_KeyTyped(HWND hwnd, short ch)
1210 WND *wndPtr = WIN_FindWndPtr(hwnd);
1211 EDITSTATE *es =
1212 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1213 char *text = EDIT_HeapAddr(hwnd, es->hText);
1214 char *currchar;
1215 RECT rc;
1216 BOOL FullPaint = FALSE;
1218 dprintf_edit(stddeb,"EDIT_KeyTyped: ch=%c\n", (char)ch);
1220 /* delete selected text (if any) */
1221 if (SelMarked(es))
1222 EDIT_DeleteSel(hwnd);
1224 /* currchar must be assigned after deleting the selection */
1225 currchar = CurrChar;
1227 /* test for typing at end of maximum buffer size */
1228 if (currchar == text + es->MaxTextLen)
1230 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1231 return;
1234 if (*currchar == '\0' && IsMultiLine())
1236 /* insert a newline at end of text */
1237 *currchar = '\r';
1238 *(currchar + 1) = '\n';
1239 *(currchar + 2) = '\0';
1240 EDIT_BuildTextPointers(hwnd);
1243 /* insert the typed character */
1244 if (text[es->textlen - 1] != '\0')
1246 /* current text buffer is full */
1247 if (es->textlen == es->MaxTextLen)
1249 /* text buffer is at maximum size */
1250 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1251 return;
1254 /* increase the text buffer size */
1255 es->textlen += GROWLENGTH;
1256 /* but not above maximum size */
1257 if (es->textlen > es->MaxTextLen)
1258 es->textlen = es->MaxTextLen;
1259 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + 2);
1260 if (!es->hText)
1261 NOTIFY_PARENT(hwnd, EN_ERRSPACE);
1262 text = EDIT_HeapAddr(hwnd, es->hText);
1263 text[es->textlen - 1] = '\0';
1264 currchar = CurrChar;
1266 /* make space for new character and put char in buffer */
1267 if (ch == '\n')
1269 memmove(currchar + 2, currchar, strlen(currchar) + 1);
1270 *currchar = '\r';
1271 *(currchar + 1) = '\n';
1272 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 2);
1274 else
1276 memmove(currchar + 1, currchar, strlen(currchar) + 1);
1277 *currchar = ch;
1278 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
1280 es->TextChanged = TRUE;
1281 NOTIFY_PARENT(hwnd, EN_UPDATE);
1283 /* re-adjust textwidth, if necessary, and redraw line */
1284 HideCaret(hwnd);
1285 if (IsMultiLine() && es->wlines > 1)
1287 es->textwidth = max(es->textwidth,
1288 EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
1289 (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) -
1290 EDIT_TextLine(hwnd, es->CurrLine)), 0));
1292 else
1293 es->textwidth = max(es->textwidth,
1294 EDIT_StrLength(hwnd, text, strlen(text), 0));
1296 if (ch == '\n')
1298 if (es->wleft > 0)
1299 FullPaint = TRUE;
1300 es->wleft = 0;
1301 EDIT_BuildTextPointers(hwnd);
1302 EDIT_End(hwnd);
1303 EDIT_Forward(hwnd);
1305 /* invalidate rest of window */
1306 GetClientRect(hwnd, &rc);
1307 if (!FullPaint)
1308 rc.top = es->WndRow * es->txtht;
1309 InvalidateRect(hwnd, &rc, FALSE);
1311 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1312 ShowCaret(hwnd);
1313 UpdateWindow(hwnd);
1314 NOTIFY_PARENT(hwnd, EN_CHANGE);
1315 return;
1318 /* test end of window */
1319 if (es->WndCol >= ClientWidth(wndPtr) -
1320 EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft))
1322 /* TODO:- Word wrap to be handled here */
1324 /* if (!(currchar == text + es->MaxTextLen - 2)) */
1325 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1327 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft);
1328 es->CurrCol++;
1329 EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
1330 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1331 ShowCaret(hwnd);
1332 NOTIFY_PARENT(hwnd, EN_CHANGE);
1336 /*********************************************************************
1337 * EDIT_CharWidth
1339 * Return the width of the given character in pixels.
1340 * The current column offset in pixels _pcol_ is required to calculate
1341 * the width of a tab.
1344 int EDIT_CharWidth(HWND hwnd, short ch, int pcol)
1346 WND *wndPtr = WIN_FindWndPtr(hwnd);
1347 EDITSTATE *es =
1348 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1349 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
1351 if (ch != VK_TAB)
1352 return (charWidths[ch]);
1353 else
1354 return (EDIT_GetNextTabStop(hwnd, pcol) - pcol);
1358 /*********************************************************************
1359 * EDIT_GetNextTabStop
1361 * Return the next tab stop beyond _pcol_.
1364 int EDIT_GetNextTabStop(HWND hwnd, int pcol)
1366 int i;
1367 int baseUnitWidth = LOWORD(GetDialogBaseUnits());
1368 WND *wndPtr = WIN_FindWndPtr(hwnd);
1369 EDITSTATE *es =
1370 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1371 unsigned short *tabstops = EDIT_HeapAddr(hwnd, es->hTabStops);
1373 if (es->NumTabStops == 0)
1374 return ROUNDUP(pcol, 8 * baseUnitWidth);
1375 else if (es->NumTabStops == 1)
1376 return ROUNDUP(pcol, *tabstops * baseUnitWidth / 4);
1377 else
1379 for (i = 0; i < es->NumTabStops; i++)
1381 if (*(tabstops + i) * baseUnitWidth / 4 >= pcol)
1382 return (*(tabstops + i) * baseUnitWidth / 4);
1384 return pcol;
1389 /*********************************************************************
1390 * EDIT_Forward
1392 * Cursor right key: move right one character position.
1395 void EDIT_Forward(HWND hwnd)
1397 WND *wndPtr = WIN_FindWndPtr(hwnd);
1398 EDITSTATE *es =
1399 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1401 if (*CurrChar == '\0')
1402 return;
1404 if (*CurrChar == '\r')
1406 if (es->CurrLine < (es->wlines - 1))
1408 EDIT_Home(hwnd);
1409 EDIT_Downward(hwnd);
1412 else
1414 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
1415 es->CurrCol++;
1416 if (es->WndCol >= ClientWidth(wndPtr))
1417 EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
1423 /*********************************************************************
1424 * EDIT_Downward
1426 * Cursor down key: move down one line.
1429 void EDIT_Downward(HWND hwnd)
1431 WND *wndPtr = WIN_FindWndPtr(hwnd);
1432 EDITSTATE *es =
1433 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1435 dprintf_edit(stddeb,"EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n",
1436 es->WndRow, es->wtop, es->wlines);
1438 if (IsMultiLine() && (es->WndRow + es->wtop + 1 < es->wlines))
1440 es->CurrLine++;
1441 if (es->WndRow == ClientHeight(wndPtr, es) - 1)
1443 es->WndRow++;
1444 EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
1446 else
1447 es->WndRow++;
1448 EDIT_StickEnd(hwnd);
1453 /*********************************************************************
1454 * EDIT_Upward
1456 * Cursor up key: move up one line.
1459 void EDIT_Upward(HWND hwnd)
1461 WND *wndPtr = WIN_FindWndPtr(hwnd);
1462 EDITSTATE *es =
1463 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1465 if (IsMultiLine() && es->CurrLine != 0)
1467 --es->CurrLine;
1468 if (es->WndRow == 0)
1470 --es->WndRow;
1471 EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
1473 else
1474 --es->WndRow;
1475 EDIT_StickEnd(hwnd);
1480 /*********************************************************************
1481 * EDIT_Backward
1483 * Cursor left key: move left one character position.
1486 void EDIT_Backward(HWND hwnd)
1488 WND *wndPtr = WIN_FindWndPtr(hwnd);
1489 EDITSTATE *es =
1490 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1492 if (es->CurrCol)
1494 --es->CurrCol;
1495 if (*CurrChar == VK_TAB)
1496 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar),
1497 EDIT_StrLength(hwnd,
1498 EDIT_TextLine(hwnd, es->CurrLine),
1499 es->CurrCol, 0));
1500 else
1501 es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), 0);
1502 if (es->WndCol < 0)
1503 EDIT_KeyHScroll(hwnd, SB_LINEUP);
1505 else if (IsMultiLine() && es->CurrLine != 0)
1507 EDIT_Upward(hwnd);
1508 EDIT_End(hwnd);
1513 /*********************************************************************
1514 * EDIT_End
1516 * End key: move to end of line.
1519 void EDIT_End(HWND hwnd)
1521 WND *wndPtr = WIN_FindWndPtr(hwnd);
1522 EDITSTATE *es =
1523 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1525 while (*CurrChar && *CurrChar != '\r')
1527 es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
1528 es->CurrCol++;
1531 if (es->WndCol >= ClientWidth(wndPtr))
1533 es->wleft = es->WndCol - ClientWidth(wndPtr) + HSCROLLDIM;
1534 es->WndCol -= es->wleft;
1535 InvalidateRect(hwnd, NULL, FALSE);
1536 UpdateWindow(hwnd);
1541 /*********************************************************************
1542 * EDIT_Home
1544 * Home key: move to beginning of line.
1547 void EDIT_Home(HWND hwnd)
1549 WND *wndPtr = WIN_FindWndPtr(hwnd);
1550 EDITSTATE *es =
1551 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1553 es->CurrCol = es->WndCol = 0;
1554 if (es->wleft != 0)
1556 es->wleft = 0;
1557 InvalidateRect(hwnd, NULL, FALSE);
1558 UpdateWindow(hwnd);
1563 /*********************************************************************
1564 * EDIT_StickEnd
1566 * Stick the cursor to the end of the line.
1569 void EDIT_StickEnd(HWND hwnd)
1571 WND *wndPtr = WIN_FindWndPtr(hwnd);
1572 EDITSTATE *es =
1573 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1574 int len = EDIT_LineLength(hwnd, es->CurrLine);
1575 char *cp = EDIT_TextLine(hwnd, es->CurrLine);
1576 int currpel;
1578 es->CurrCol = min(len, es->CurrCol);
1579 es->WndCol = min(EDIT_StrLength(hwnd, cp, len, 0) - es->wleft, es->WndCol);
1580 currpel = EDIT_StrLength(hwnd, cp, es->CurrCol, 0);
1582 if (es->wleft > currpel)
1584 es->wleft = max(0, currpel - 20);
1585 es->WndCol = currpel - es->wleft;
1586 UpdateWindow(hwnd);
1588 else if (currpel - es->wleft >= ClientWidth(wndPtr))
1590 es->wleft = currpel - (ClientWidth(wndPtr) - 5);
1591 es->WndCol = currpel - es->wleft;
1592 UpdateWindow(hwnd);
1597 /*********************************************************************
1598 * WM_KEYDOWN message function
1601 void EDIT_KeyDownMsg(HWND hwnd, WORD wParam)
1603 WND *wndPtr = WIN_FindWndPtr(hwnd);
1604 EDITSTATE *es =
1605 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1607 dprintf_edit(stddeb,"EDIT_KeyDownMsg: key=%x\n", wParam);
1609 HideCaret(hwnd);
1610 switch (wParam)
1612 case VK_UP:
1613 if (SelMarked(es))
1614 EDIT_ClearSel(hwnd);
1615 if (IsMultiLine())
1616 EDIT_Upward(hwnd);
1617 else
1618 EDIT_Backward(hwnd);
1619 break;
1621 case VK_DOWN:
1622 if (SelMarked(es))
1623 EDIT_ClearSel(hwnd);
1624 if (IsMultiLine())
1625 EDIT_Downward(hwnd);
1626 else
1627 EDIT_Forward(hwnd);
1628 break;
1630 case VK_RIGHT:
1631 if (SelMarked(es))
1632 EDIT_ClearSel(hwnd);
1633 EDIT_Forward(hwnd);
1634 break;
1636 case VK_LEFT:
1637 if (SelMarked(es))
1638 EDIT_ClearSel(hwnd);
1639 EDIT_Backward(hwnd);
1640 break;
1642 case VK_HOME:
1643 if (SelMarked(es))
1644 EDIT_ClearSel(hwnd);
1645 EDIT_Home(hwnd);
1646 break;
1648 case VK_END:
1649 if (SelMarked(es))
1650 EDIT_ClearSel(hwnd);
1651 EDIT_End(hwnd);
1652 break;
1654 case VK_PRIOR:
1655 if (IsMultiLine())
1657 if (SelMarked(es))
1658 EDIT_ClearSel(hwnd);
1659 EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
1661 break;
1663 case VK_NEXT:
1664 if (IsMultiLine())
1666 if (SelMarked(es))
1667 EDIT_ClearSel(hwnd);
1668 EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
1670 break;
1672 case VK_BACK:
1673 if (SelMarked(es))
1674 EDIT_DeleteSel(hwnd);
1675 else
1677 if (es->CurrCol == 0 && es->CurrLine == 0)
1678 break;
1679 EDIT_Backward(hwnd);
1680 EDIT_DelKey(hwnd);
1682 break;
1684 case VK_DELETE:
1685 if (SelMarked(es))
1686 EDIT_DeleteSel(hwnd);
1687 else
1688 EDIT_DelKey(hwnd);
1689 break;
1692 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
1693 ShowCaret(hwnd);
1697 /*********************************************************************
1698 * EDIT_KeyHScroll
1700 * Scroll text horizontally using cursor keys.
1703 void EDIT_KeyHScroll(HWND hwnd, WORD opt)
1705 int hscrollpos;
1706 WND *wndPtr = WIN_FindWndPtr(hwnd);
1707 EDITSTATE *es =
1708 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1710 if (opt == SB_LINEDOWN)
1712 es->wleft += HSCROLLDIM;
1713 es->WndCol -= HSCROLLDIM;
1715 else
1717 if (es->wleft == 0)
1718 return;
1719 if (es->wleft - HSCROLLDIM < 0)
1721 es->WndCol += es->wleft;
1722 es->wleft = 0;
1724 else
1726 es->wleft -= HSCROLLDIM;
1727 es->WndCol += HSCROLLDIM;
1731 InvalidateRect(hwnd, NULL, FALSE);
1732 UpdateWindow(hwnd);
1734 if (IsHScrollBar())
1736 hscrollpos = EDIT_ComputeHScrollPos(hwnd);
1737 SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE);
1742 /*********************************************************************
1743 * EDIT_KeyVScrollLine
1745 * Scroll text vertically by one line using keyboard.
1748 void EDIT_KeyVScrollLine(HWND hwnd, WORD opt)
1750 RECT rc;
1751 int y, vscrollpos;
1752 WND *wndPtr = WIN_FindWndPtr(hwnd);
1753 EDITSTATE *es =
1754 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1756 if (!IsMultiLine())
1757 return;
1759 if (opt == SB_LINEDOWN)
1761 /* move down one line */
1762 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
1763 return;
1764 es->wtop++;
1766 else
1768 /* move up one line */
1769 if (es->wtop == 0)
1770 return;
1771 --es->wtop;
1774 if (IsWindowVisible(hwnd))
1776 /* adjust client bottom to nearest whole line */
1777 GetClientRect(hwnd, &rc);
1778 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
1780 if (opt == SB_LINEUP)
1782 /* move up one line (scroll window down) */
1783 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
1784 /* write top line */
1785 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
1786 es->WndRow++;
1788 else
1790 /* move down one line (scroll window up) */
1791 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
1792 /* write bottom line */
1793 y = (((rc.bottom - rc.top) / es->txtht) - 1);
1794 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
1795 --es->WndRow;
1799 /* reset the vertical scroll bar */
1800 if (IsVScrollBar())
1802 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1803 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1808 /*********************************************************************
1809 * EDIT_KeyVScrollPage
1811 * Scroll text vertically by one page using keyboard.
1814 void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
1816 int vscrollpos;
1817 WND *wndPtr = WIN_FindWndPtr(hwnd);
1818 EDITSTATE *es =
1819 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1821 if (IsMultiLine())
1823 if (opt == SB_PAGEUP)
1825 if (es->wtop)
1826 es->wtop -= ClientHeight(wndPtr, es);
1828 else
1830 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1832 es->wtop += ClientHeight(wndPtr, es);
1833 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
1834 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1837 if (es->wtop < 0)
1838 es->wtop = 0;
1840 es->CurrLine = es->wtop + es->WndRow;
1841 EDIT_StickEnd(hwnd);
1842 InvalidateRect(hwnd, NULL, TRUE);
1843 UpdateWindow(hwnd);
1845 /* reset the vertical scroll bar */
1846 if (IsVScrollBar())
1848 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1849 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1855 /*********************************************************************
1856 * EDIT_KeyVScrollDoc
1858 * Scroll text to top and bottom of document using keyboard.
1861 void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt)
1863 int vscrollpos;
1864 WND *wndPtr = WIN_FindWndPtr(hwnd);
1865 EDITSTATE *es =
1866 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1868 if (!IsMultiLine())
1869 return;
1871 if (opt == SB_TOP)
1872 es->wtop = es->wleft = 0;
1873 else if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
1875 es->wtop = es->wlines - ClientHeight(wndPtr, es);
1876 es->wleft = 0;
1879 es->CurrLine = es->wlines;
1880 es->WndRow = es->wlines - es->wtop;
1881 EDIT_End(hwnd);
1882 InvalidateRect(hwnd, NULL, TRUE);
1883 UpdateWindow(hwnd);
1885 /* reset the vertical scroll bar */
1886 if (IsVScrollBar())
1888 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
1889 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
1894 /*********************************************************************
1895 * EDIT_ComputeVScrollPos
1897 * Compute the vertical scroll bar position from the window
1898 * position and text width.
1901 int EDIT_ComputeVScrollPos(HWND hwnd)
1903 int vscrollpos;
1904 short minpos, maxpos;
1905 WND *wndPtr = WIN_FindWndPtr(hwnd);
1906 EDITSTATE *es =
1907 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1909 GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos);
1911 if (es->wlines > ClientHeight(wndPtr, es))
1912 vscrollpos = (double)(es->wtop) / (double)(es->wlines -
1913 ClientHeight(wndPtr, es)) * (maxpos - minpos);
1914 else
1915 vscrollpos = minpos;
1917 return vscrollpos;
1921 /*********************************************************************
1922 * EDIT_ComputeHScrollPos
1924 * Compute the horizontal scroll bar position from the window
1925 * position and text width.
1928 int EDIT_ComputeHScrollPos(HWND hwnd)
1930 int hscrollpos;
1931 short minpos, maxpos;
1932 WND *wndPtr = WIN_FindWndPtr(hwnd);
1933 EDITSTATE *es =
1934 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1936 GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos);
1938 if (es->textwidth > ClientWidth(wndPtr))
1939 hscrollpos = (double)(es->wleft) / (double)(es->textwidth -
1940 ClientWidth(wndPtr)) * (maxpos - minpos);
1941 else
1942 hscrollpos = minpos;
1944 return hscrollpos;
1948 /*********************************************************************
1949 * EDIT_DelKey
1951 * Delete character to right of cursor.
1954 void EDIT_DelKey(HWND hwnd)
1956 RECT rc;
1957 WND *wndPtr = WIN_FindWndPtr(hwnd);
1958 EDITSTATE *es =
1959 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1960 char *currchar = CurrChar;
1961 BOOL repaint = *currchar == '\n';
1963 if (IsMultiLine() && *currchar == '\n' && *(currchar + 1) == '\0')
1964 return;
1965 strcpy(currchar, currchar + 1);
1966 NOTIFY_PARENT(hwnd, EN_UPDATE);
1968 if (repaint)
1970 EDIT_BuildTextPointers(hwnd);
1971 GetClientRect(hwnd, &rc);
1972 rc.top = es->WndRow * es->txtht;
1973 InvalidateRect(hwnd, &rc, FALSE);
1974 UpdateWindow(hwnd);
1976 else
1978 EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1);
1979 EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop);
1982 es->TextChanged = TRUE;
1983 NOTIFY_PARENT(hwnd, EN_CHANGE);
1986 /*********************************************************************
1987 * WM_VSCROLL message function
1990 void EDIT_VScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
1992 WND *wndPtr = WIN_FindWndPtr(hwnd);
1993 EDITSTATE *es =
1994 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
1996 if (IsMultiLine())
1998 HideCaret(hwnd);
2000 switch (wParam)
2002 case SB_LINEUP:
2003 case SB_LINEDOWN:
2004 EDIT_VScrollLine(hwnd, wParam);
2005 break;
2007 case SB_PAGEUP:
2008 case SB_PAGEDOWN:
2009 EDIT_VScrollPage(hwnd, wParam);
2010 break;
2014 SetCaretPos(es->WndCol, es->WndRow);
2015 ShowCaret(hwnd);
2019 /*********************************************************************
2020 * EDIT_VScrollLine
2022 * Scroll text vertically by one line using scrollbars.
2025 void EDIT_VScrollLine(HWND hwnd, WORD opt)
2027 RECT rc;
2028 int y;
2029 WND *wndPtr = WIN_FindWndPtr(hwnd);
2030 EDITSTATE *es =
2031 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2033 dprintf_edit(stddeb,"EDIT_VScrollLine: direction=%d\n", opt);
2035 if (opt == SB_LINEDOWN)
2037 /* move down one line */
2038 if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines)
2039 return;
2040 es->wtop++;
2042 else
2044 /* move up one line */
2045 if (es->wtop == 0)
2046 return;
2047 --es->wtop;
2050 if (IsWindowVisible(hwnd))
2052 /* adjust client bottom to nearest whole line */
2053 GetClientRect(hwnd, &rc);
2054 rc.bottom = (rc.bottom / es->txtht) * es->txtht;
2056 if (opt == SB_LINEUP)
2058 /* move up one line (scroll window down) */
2059 ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
2060 /* write top line */
2061 EDIT_WriteTextLine(hwnd, NULL, es->wtop);
2062 es->WndRow++;
2064 else
2066 /* move down one line (scroll window up) */
2067 ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
2068 /* write bottom line */
2069 y = ((rc.bottom - rc.top / es->txtht) - 1);
2070 EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
2071 --es->WndRow;
2077 /*********************************************************************
2078 * EDIT_VScrollPage
2080 * Scroll text vertically by one page using keyboard.
2083 void EDIT_VScrollPage(HWND hwnd, WORD opt)
2085 int vscrollpos;
2086 WND *wndPtr = WIN_FindWndPtr(hwnd);
2087 EDITSTATE *es =
2088 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2090 if (opt == SB_PAGEUP)
2092 if (es->wtop)
2093 es->wtop -= ClientHeight(wndPtr, es);
2095 else
2097 if (es->wtop + ClientHeight(wndPtr, es) < es->wlines)
2099 es->wtop += ClientHeight(wndPtr, es);
2100 if (es->wtop > es->wlines - ClientHeight(wndPtr, es))
2101 es->wtop = es->wlines - ClientHeight(wndPtr, es);
2104 if (es->wtop < 0)
2105 es->wtop = 0;
2107 InvalidateRect(hwnd, NULL, TRUE);
2108 UpdateWindow(hwnd);
2110 /* reset the vertical scroll bar */
2111 if (IsVScrollBar())
2113 vscrollpos = EDIT_ComputeVScrollPos(hwnd);
2114 SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
2119 /*********************************************************************
2120 * WM_HSCROLL message function
2123 void EDIT_HScrollMsg(HWND hwnd, WORD wParam, LONG lParam)
2125 WND *wndPtr = WIN_FindWndPtr(hwnd);
2126 EDITSTATE *es =
2127 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2129 switch (wParam)
2131 case SB_LINEUP:
2132 case SB_LINEDOWN:
2133 HideCaret(hwnd);
2135 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2136 ShowCaret(hwnd);
2137 break;
2142 /*********************************************************************
2143 * WM_SIZE message function
2146 void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam)
2148 WND *wndPtr = WIN_FindWndPtr(hwnd);
2149 EDITSTATE *es =
2150 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2152 if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return;
2154 InvalidateRect(hwnd, NULL, TRUE);
2155 es->PaintBkgd = TRUE;
2156 UpdateWindow(hwnd);
2160 /*********************************************************************
2161 * WM_LBUTTONDOWN message function
2164 void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam)
2166 char *cp;
2167 int len;
2168 BOOL end = FALSE;
2169 WND *wndPtr = WIN_FindWndPtr(hwnd);
2170 EDITSTATE *es =
2171 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2173 if (SelMarked(es))
2174 EDIT_ClearSel(hwnd);
2176 es->WndRow = HIWORD(lParam) / es->txtht;
2177 if (!IsMultiLine())
2178 es->WndRow = 0;
2179 else if (es->WndRow > es->wlines - es->wtop - 1)
2181 es->WndRow = es->wlines - es->wtop - 1;
2182 end = TRUE;
2184 es->CurrLine = es->wtop + es->WndRow;
2186 cp = EDIT_TextLine(hwnd, es->CurrLine);
2187 len = EDIT_LineLength(hwnd, es->CurrLine);
2188 es->WndCol = LOWORD(lParam) + es->wleft;
2189 if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) || end)
2190 es->WndCol = EDIT_StrLength(hwnd, cp, len, 0);
2191 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2192 es->WndCol -= es->wleft;
2194 ButtonDown = TRUE;
2195 ButtonRow = es->CurrLine;
2196 ButtonCol = es->CurrCol;
2200 /*********************************************************************
2201 * WM_MOUSEMOVE message function
2204 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
2206 WND *wndPtr = WIN_FindWndPtr(hwnd);
2207 EDITSTATE *es =
2208 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2210 if (wParam != MK_LBUTTON)
2211 return;
2213 HideCaret(hwnd);
2214 if (ButtonDown)
2216 EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
2217 TextMarking = TRUE;
2218 ButtonDown = FALSE;
2221 if (TextMarking)
2223 EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
2224 SetCaretPos(es->WndCol, es->WndRow * es->txtht);
2226 ShowCaret(hwnd);
2230 /*********************************************************************
2231 * EDIT_PixelToChar
2233 * Convert a pixel offset in the given row to a character offset,
2234 * adjusting the pixel offset to the nearest whole character if
2235 * necessary.
2238 int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
2240 int ch = 0, i = 0, s_i = 0;
2241 char *text;
2243 dprintf_edit(stddeb,"EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
2245 text = EDIT_TextLine(hwnd, row);
2246 while (i < *pixel)
2248 s_i = i;
2249 i += EDIT_CharWidth(hwnd, (BYTE)(*(text + ch)), i);
2250 ch++;
2253 /* if stepped past _pixel_, go back a character */
2254 if (i - *pixel)
2256 i = s_i;
2257 --ch;
2259 *pixel = i;
2260 return ch;
2264 /*********************************************************************
2265 * WM_SETTEXT message function
2268 LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam)
2270 int len;
2271 char *text;
2272 WND *wndPtr = WIN_FindWndPtr(hwnd);
2273 EDITSTATE *es =
2274 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2276 if (strlen((char *)PTR_SEG_TO_LIN(lParam)) <= es->MaxTextLen)
2278 len = ( lParam? strlen((char *)PTR_SEG_TO_LIN(lParam)) : 0 );
2279 EDIT_ClearText(hwnd);
2280 es->textlen = len;
2281 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, len + 3);
2282 text = EDIT_HeapAddr(hwnd, es->hText);
2283 if (lParam)
2284 strcpy(text, (char *)PTR_SEG_TO_LIN(lParam));
2285 text[len] = '\0';
2286 text[len + 1] = '\0';
2287 text[len + 2] = '\0';
2288 EDIT_BuildTextPointers(hwnd);
2289 InvalidateRect(hwnd, NULL, TRUE);
2290 es->PaintBkgd = TRUE;
2291 es->TextChanged = TRUE;
2292 return 0L;
2294 else
2295 return EN_ERRSPACE;
2299 /*********************************************************************
2300 * EDIT_ClearText
2302 * Clear text from text buffer.
2305 void EDIT_ClearText(HWND hwnd)
2307 WND *wndPtr = WIN_FindWndPtr(hwnd);
2308 EDITSTATE *es =
2309 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2310 unsigned int blen = EditBufLen(wndPtr) + 2;
2311 char *text;
2313 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, blen);
2314 text = EDIT_HeapAddr(hwnd, es->hText);
2315 memset(text, 0, blen);
2316 es->textlen = 0;
2317 es->wlines = 0;
2318 es->CurrLine = es->CurrCol = 0;
2319 es->WndRow = es->WndCol = 0;
2320 es->wleft = es->wtop = 0;
2321 es->textwidth = 0;
2322 es->TextChanged = FALSE;
2323 EDIT_ClearTextPointers(hwnd);
2327 /*********************************************************************
2328 * EM_SETSEL message function
2331 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
2333 INT so, eo;
2334 WND *wndPtr = WIN_FindWndPtr(hwnd);
2335 EDITSTATE *es =
2336 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2338 so = LOWORD(lParam);
2339 eo = HIWORD(lParam);
2341 if (so == -1) /* if so == -1, clear selection */
2343 EDIT_ClearSel(hwnd);
2344 return;
2347 if (so == eo) /* if so == eo, set caret only */
2349 EDIT_GetLineCol(hwnd, (int) so, &(es->CurrLine), &(es->CurrCol));
2350 es->WndRow = es->CurrLine - es->wtop;
2352 if (!wParam)
2354 if (es->WndRow < 0 || es->WndRow > ClientHeight(wndPtr, es))
2356 es->wtop = es->CurrLine;
2357 es->WndRow = 0;
2359 es->WndCol = EDIT_StrLength(hwnd,
2360 EDIT_TextLine(hwnd, es->CurrLine),
2361 es->CurrCol, 0) - es->wleft;
2362 if (es->WndCol > ClientWidth(wndPtr))
2364 es->wleft = es->WndCol;
2365 es->WndCol = 0;
2367 else if (es->WndCol < 0)
2369 es->wleft += es->WndCol;
2370 es->WndCol = 0;
2374 else /* otherwise set selection */
2376 if (eo >= 0 && so > eo) /* eo == -1 flag to extend to end of text */
2378 INT tmp;
2379 tmp = so;
2380 so = eo;
2381 eo = tmp;
2384 EDIT_GetLineCol(hwnd, (int) so, &(es->SelBegLine), &(es->SelBegCol));
2385 EDIT_GetLineCol(hwnd, (int) eo, &(es->SelEndLine), &(es->SelEndCol));
2386 es->CurrLine = es->SelEndLine;
2387 es->CurrCol = es->SelEndCol;
2388 es->WndRow = es->SelEndLine - es->wtop;
2390 if (!wParam) /* don't suppress scrolling of text */
2392 if (es->WndRow < 0)
2394 es->wtop = es->SelEndLine;
2395 es->WndRow = 0;
2397 else if (es->WndRow > ClientHeight(wndPtr, es))
2399 es->wtop += es->WndRow - ClientHeight(wndPtr, es);
2400 es->WndRow = ClientHeight(wndPtr, es);
2402 es->WndCol = EDIT_StrLength(hwnd,
2403 EDIT_TextLine(hwnd, es->SelEndLine),
2404 es->SelEndCol, 0) - es->wleft;
2405 if (es->WndCol > ClientWidth(wndPtr))
2407 es->wleft += es->WndCol - ClientWidth(wndPtr);
2408 es->WndCol = ClientWidth(wndPtr);
2410 else if (es->WndCol < 0)
2412 es->wleft += es->WndCol;
2413 es->WndCol = 0;
2417 InvalidateRect(hwnd, NULL, TRUE);
2418 UpdateWindow(hwnd);
2423 /*********************************************************************
2424 * EDIT_GetLineCol
2426 * Return line and column in text buffer from character offset.
2429 void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
2431 int lineno;
2432 char *cp, *cp1;
2433 WND *wndPtr = WIN_FindWndPtr(hwnd);
2434 EDITSTATE *es =
2435 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2436 char *text = EDIT_HeapAddr(hwnd, es->hText);
2437 unsigned int *textPtrs =
2438 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2440 /* check for (0,0) */
2441 if (!off || !es->wlines)
2443 *line = 0;
2444 *col = 0;
2445 return;
2448 if (off < 0 || off > strlen(text)) off = strlen(text);
2449 cp1 = text;
2450 for (lineno = 0; lineno < es->wlines; lineno++)
2452 cp = text + *(textPtrs + lineno);
2453 if (off == (int)(cp - text))
2455 *line = lineno;
2456 *col = 0;
2457 return;
2459 if (off < (int)(cp - text))
2460 break;
2461 cp1 = cp;
2463 *line = lineno - 1;
2464 *col = off - (int)(cp1 - text);
2465 #if 0
2466 if (*(text + *col) == '\0')
2467 (*col)--;
2468 #endif
2472 /*********************************************************************
2473 * EDIT_DeleteSel
2475 * Delete the current selected text (if any)
2478 void EDIT_DeleteSel(HWND hwnd)
2480 char *bbl, *bel;
2481 int len;
2482 WND *wndPtr = WIN_FindWndPtr(hwnd);
2483 EDITSTATE *es =
2484 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2486 if (SelMarked(es))
2488 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
2489 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
2490 len = (int)(bel - bbl);
2491 EDIT_SaveDeletedText(hwnd, bbl, len, es->SelBegLine, es->SelBegCol);
2492 es->TextChanged = TRUE;
2493 strcpy(bbl, bel);
2495 es->CurrLine = es->SelBegLine;
2496 es->CurrCol = es->SelBegCol;
2497 es->WndRow = es->SelBegLine - es->wtop;
2498 if (es->WndRow < 0)
2500 es->wtop = es->SelBegLine;
2501 es->WndRow = 0;
2503 es->WndCol = EDIT_StrLength(hwnd, bbl - es->SelBegCol,
2504 es->SelBegCol, 0) - es->wleft;
2506 EDIT_BuildTextPointers(hwnd);
2507 es->PaintBkgd = TRUE;
2508 EDIT_ClearSel(hwnd);
2513 /*********************************************************************
2514 * EDIT_ClearSel
2516 * Clear the current selection.
2519 void EDIT_ClearSel(HWND hwnd)
2521 WND *wndPtr = WIN_FindWndPtr(hwnd);
2522 EDITSTATE *es =
2523 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2525 es->SelBegLine = es->SelBegCol = 0;
2526 es->SelEndLine = es->SelEndCol = 0;
2528 InvalidateRect(hwnd, NULL, TRUE);
2529 UpdateWindow(hwnd);
2533 /*********************************************************************
2534 * EDIT_TextLineNumber
2536 * Return the line number in the text buffer of the supplied
2537 * character pointer.
2540 int EDIT_TextLineNumber(HWND hwnd, char *lp)
2542 int lineno;
2543 char *cp;
2544 WND *wndPtr = WIN_FindWndPtr(hwnd);
2545 EDITSTATE *es =
2546 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2547 char *text = EDIT_HeapAddr(hwnd, es->hText);
2548 unsigned int *textPtrs =
2549 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2551 for (lineno = 0; lineno < es->wlines; lineno++)
2553 cp = text + *(textPtrs + lineno);
2554 if (cp == lp)
2555 return lineno;
2556 if (cp > lp)
2557 break;
2559 return lineno - 1;
2563 /*********************************************************************
2564 * EDIT_SetAnchor
2566 * Set down anchor for text marking.
2569 void EDIT_SetAnchor(HWND hwnd, int row, int col)
2571 BOOL sel = FALSE;
2572 WND *wndPtr = WIN_FindWndPtr(hwnd);
2573 EDITSTATE *es =
2574 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2576 if (SelMarked(es))
2578 sel = TRUE;
2579 EDIT_ClearSel(hwnd);
2581 es->SelBegLine = es->SelEndLine = row;
2582 es->SelBegCol = es->SelEndCol = col;
2583 if (sel)
2585 InvalidateRect(hwnd, NULL, FALSE);
2586 UpdateWindow(hwnd);
2591 /*********************************************************************
2592 * EDIT_ExtendSel
2594 * Extend selection to the given screen co-ordinates.
2597 void EDIT_ExtendSel(HWND hwnd, INT x, INT y)
2599 int bbl, bel, bbc, bec;
2600 char *cp;
2601 int len, line;
2602 WND *wndPtr = WIN_FindWndPtr(hwnd);
2603 EDITSTATE *es =
2604 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2606 dprintf_edit(stddeb,"EDIT_ExtendSel: x=%d, y=%d\n", x, y);
2608 bbl = es->SelEndLine;
2609 bbc = es->SelEndCol;
2610 y = max(y,0);
2611 if (IsMultiLine())
2613 if ((line = es->wtop + y / es->txtht) >= es->wlines)
2614 line = es->wlines - 1;
2616 else
2617 line = 0;
2619 cp = EDIT_TextLine(hwnd, line);
2620 len = EDIT_LineLength(hwnd, line);
2622 es->WndRow = y / es->txtht;
2623 if (!IsMultiLine())
2624 es->WndRow = 0;
2625 else if (es->WndRow > es->wlines - es->wtop - 1)
2626 es->WndRow = es->wlines - es->wtop - 1;
2627 es->CurrLine = es->wtop + es->WndRow;
2628 es->SelEndLine = es->CurrLine;
2630 es->WndCol = es->wleft + max(x,0);
2631 if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0))
2632 es->WndCol = EDIT_StrLength(hwnd, cp, len, 0);
2633 es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
2634 es->WndCol -= es->wleft;
2635 es->SelEndCol = es->CurrCol;
2637 bel = es->SelEndLine;
2638 bec = es->SelEndCol;
2640 /* return if no new characters to mark */
2641 if (bbl == bel && bbc == bec)
2642 return;
2644 /* put lowest marker first */
2645 if (bbl > bel)
2647 swap(&bbl, &bel);
2648 swap(&bbc, &bec);
2650 if (bbl == bel && bbc > bec)
2651 swap(&bbc, &bec);
2653 for (y = bbl; y <= bel; y++)
2655 if (y == bbl && y == bel)
2656 EDIT_WriteSel(hwnd, y, bbc, bec);
2657 else if (y == bbl)
2658 EDIT_WriteSel(hwnd, y, bbc, -1);
2659 else if (y == bel)
2660 EDIT_WriteSel(hwnd, y, 0, bec);
2661 else
2662 EDIT_WriteSel(hwnd, y, 0, -1);
2667 /*********************************************************************
2668 * EDIT_WriteSel
2670 * Display selection by reversing pixels in selected text.
2671 * If end == -1, selection applies to end of line.
2674 void EDIT_WriteSel(HWND hwnd, int y, int start, int end)
2676 RECT rc, rcInvert;
2677 int scol, ecol;
2678 char *cp;
2679 HDC hdc;
2680 WND *wndPtr = WIN_FindWndPtr(hwnd);
2681 EDITSTATE *es =
2682 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2684 dprintf_edit(stddeb,"EDIT_WriteSel: y=%d start=%d end=%d\n", y, start,end);
2685 GetClientRect(hwnd, &rc);
2687 /* make sure y is within the window */
2688 if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
2689 return;
2691 /* get pointer to text */
2692 cp = EDIT_TextLine(hwnd, y);
2694 /* get length of line if end == -1 */
2695 if (end == -1)
2696 end = EDIT_LineLength(hwnd, y);
2698 /* For some reason Rectangle, when called with R2_XORPEN filling,
2699 * appears to leave a 2 pixel gap between characters and between
2700 * lines. I have kludged this by adding on two pixels to ecol and
2701 * to the line height in the call to Rectangle.
2703 scol = EDIT_StrLength(hwnd, cp, start, 0) - es->wleft;
2704 if (scol > rc.right) return;
2705 if (scol < rc.left) scol = rc.left;
2706 ecol = EDIT_StrLength(hwnd, cp, end, 0) - es->wleft;
2707 if (ecol < rc.left) return;
2708 if (ecol > rc.right) ecol = rc.right;
2710 hdc = GetDC(hwnd);
2711 rcInvert.left = scol;
2712 rcInvert.top = y * es->txtht;
2713 rcInvert.right = ecol;
2714 rcInvert.bottom = (y + 1) * es->txtht;
2715 InvertRect(hdc, (LPRECT) &rcInvert);
2716 ReleaseDC(hwnd, hdc);
2720 /*********************************************************************
2721 * EDIT_StopMarking
2723 * Stop text marking (selection).
2726 void EDIT_StopMarking(HWND hwnd)
2728 WND *wndPtr = WIN_FindWndPtr(hwnd);
2729 EDITSTATE *es =
2730 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2732 TextMarking = FALSE;
2733 if (es->SelBegLine > es->SelEndLine)
2735 swap(&(es->SelBegLine), &(es->SelEndLine));
2736 swap(&(es->SelBegCol), &(es->SelEndCol));
2738 if (es->SelBegLine == es->SelEndLine && es->SelBegCol > es->SelEndCol)
2739 swap(&(es->SelBegCol), &(es->SelEndCol));
2743 /*********************************************************************
2744 * EM_GETLINE message function
2747 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam)
2749 char *cp, *cp1;
2750 int len;
2751 char *buffer = (char *)lParam;
2753 cp = EDIT_TextLine(hwnd, wParam);
2754 cp1 = EDIT_TextLine(hwnd, wParam + 1);
2755 len = min((int)(cp1 - cp), (WORD)(*buffer));
2756 strncpy(buffer, cp, len);
2758 return (LONG)len;
2762 /*********************************************************************
2763 * EM_GETSEL message function
2766 LONG EDIT_GetSelMsg(HWND hwnd)
2768 int so, eo;
2769 WND *wndPtr = WIN_FindWndPtr(hwnd);
2770 EDITSTATE *es =
2771 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2772 unsigned int *textPtrs =
2773 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2775 so = *(textPtrs + es->SelBegLine) + es->SelBegCol;
2776 eo = *(textPtrs + es->SelEndLine) + es->SelEndCol;
2778 return MAKELONG(so, eo);
2782 /*********************************************************************
2783 * EM_REPLACESEL message function
2786 void EDIT_ReplaceSel(HWND hwnd, LONG lParam)
2788 EDIT_DeleteSel(hwnd);
2789 EDIT_InsertText(hwnd, (char *)PTR_SEG_TO_LIN(lParam),
2790 strlen((char *)PTR_SEG_TO_LIN(lParam)));
2791 InvalidateRect(hwnd, NULL, TRUE);
2792 UpdateWindow(hwnd);
2796 /*********************************************************************
2797 * EDIT_InsertText
2799 * Insert text at current line and column.
2802 void EDIT_InsertText(HWND hwnd, char *str, int len)
2804 int plen;
2805 WND *wndPtr = WIN_FindWndPtr(hwnd);
2806 EDITSTATE *es =
2807 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2808 char *text = EDIT_HeapAddr(hwnd, es->hText);
2810 plen = strlen(text) + len;
2811 if (plen + 1 > es->textlen)
2813 es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + len);
2814 es->textlen = plen + 1;
2816 memmove(CurrChar + len, CurrChar, strlen(CurrChar) + 1);
2817 memcpy(CurrChar, str, len);
2819 EDIT_BuildTextPointers(hwnd);
2820 es->PaintBkgd = TRUE;
2821 es->TextChanged = TRUE;
2823 EDIT_GetLineCol(hwnd, (int)((CurrChar + len) - text), &(es->CurrLine),
2824 &(es->CurrCol));
2825 es->WndRow = es->CurrLine - es->wtop;
2826 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2827 es->CurrCol, 0) - es->wleft;
2831 /*********************************************************************
2832 * EM_LINEFROMCHAR message function
2835 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam)
2837 int row, col;
2838 WND *wndPtr = WIN_FindWndPtr(hwnd);
2839 EDITSTATE *es =
2840 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2842 if (wParam == (WORD)-1)
2843 return (LONG)(es->SelBegLine);
2844 else
2845 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2847 return (LONG)row;
2851 /*********************************************************************
2852 * EM_LINEINDEX message function
2855 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam)
2857 WND *wndPtr = WIN_FindWndPtr(hwnd);
2858 EDITSTATE *es =
2859 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2860 unsigned int *textPtrs =
2861 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2863 if (wParam == (WORD)-1)
2864 wParam = es->CurrLine;
2866 return (LONG)(*(textPtrs + wParam));
2870 /*********************************************************************
2871 * EM_LINELENGTH message function
2874 LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam)
2876 int row, col, len;
2877 int sbl, sbc, sel, sec;
2878 WND *wndPtr = WIN_FindWndPtr(hwnd);
2879 EDITSTATE *es =
2880 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2881 unsigned int *textPtrs =
2882 (unsigned int *)EDIT_HeapAddr(hwnd, es->hTextPtrs);
2884 if (wParam == (WORD)-1)
2886 if (SelMarked(es))
2888 sbl = es->SelBegLine;
2889 sbc = es->SelBegCol;
2890 sel = es->SelEndLine;
2891 sec = es->SelEndCol;
2893 if (sbl > sel)
2895 swap(&sbl, &sel);
2896 swap(&sbc, &sec);
2898 if (sbl == sel && sbc > sec)
2899 swap(&sbc, &sec);
2901 if (sbc == sel)
2903 len = *(textPtrs + sbl + 1) - *(textPtrs + sbl) - 1;
2904 return len - sec - sbc;
2907 len = *(textPtrs + sel + 1) - *(textPtrs + sel) - sec - 1;
2908 return len + sbc;
2910 else /* no selection marked */
2912 len = *(textPtrs + es->CurrLine + 1) -
2913 *(textPtrs + es->CurrLine) - 1;
2914 return len;
2917 else /* line number specified */
2919 EDIT_GetLineCol(hwnd, wParam, &row, &col);
2920 len = *(textPtrs + row + 1) - *(textPtrs + row);
2921 return len;
2926 /*********************************************************************
2927 * WM_SETFONT message function
2930 void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam)
2932 HDC hdc;
2933 TEXTMETRIC tm;
2934 HFONT oldfont;
2935 WND *wndPtr = WIN_FindWndPtr(hwnd);
2936 EDITSTATE *es =
2937 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2938 short *charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
2940 es->hFont = wParam;
2941 hdc = GetDC(hwnd);
2942 oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
2943 GetCharWidth(hdc, 0, 255, charWidths);
2944 GetTextMetrics(hdc, &tm);
2945 es->txtht = tm.tmHeight + tm.tmExternalLeading;
2946 SelectObject(hdc, (HANDLE)oldfont);
2947 ReleaseDC(hwnd, hdc);
2949 es->WndRow = (es->CurrLine - es->wtop) / es->txtht;
2950 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
2951 es->CurrCol, 0) - es->wleft;
2953 InvalidateRect(hwnd, NULL, TRUE);
2954 es->PaintBkgd = TRUE;
2955 if (lParam) UpdateWindow(hwnd);
2959 /*********************************************************************
2960 * EDIT_SaveDeletedText
2962 * Save deleted text in deleted text buffer.
2965 void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len,
2966 int line, int col)
2968 char *text;
2969 WND *wndPtr = WIN_FindWndPtr(hwnd);
2970 EDITSTATE *es =
2971 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2973 if (!es->hDeletedText)
2974 es->hDeletedText = GlobalAlloc( GMEM_MOVEABLE, len );
2975 else
2976 es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE);
2977 if (!es->hDeletedText) return;
2978 text = (char *)GlobalLock(es->hDeletedText);
2979 memcpy(text, deltext, len);
2980 GlobalUnlock(es->hDeletedText);
2981 es->DeletedLength = len;
2982 es->DeletedCurrLine = line;
2983 es->DeletedCurrCol = col;
2987 /*********************************************************************
2988 * EDIT_ClearDeletedText
2990 * Clear deleted text buffer.
2993 void EDIT_ClearDeletedText(HWND hwnd)
2995 WND *wndPtr = WIN_FindWndPtr(hwnd);
2996 EDITSTATE *es =
2997 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
2999 GlobalFree(es->hDeletedText);
3000 es->hDeletedText = 0;
3001 es->DeletedLength = 0;
3005 /*********************************************************************
3006 * EM_UNDO message function
3009 LONG EDIT_UndoMsg(HWND hwnd)
3011 char *text;
3012 WND *wndPtr = WIN_FindWndPtr(hwnd);
3013 EDITSTATE *es =
3014 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3016 if (es->hDeletedText)
3018 text = (char *)GlobalLock(es->hDeletedText);
3019 es->CurrLine = es->DeletedCurrLine;
3020 es->CurrCol = es->DeletedCurrCol;
3021 EDIT_InsertText(hwnd, text, es->DeletedLength);
3022 GlobalUnlock(es->hDeletedText);
3023 EDIT_ClearDeletedText(hwnd);
3025 es->SelBegLine = es->CurrLine;
3026 es->SelBegCol = es->CurrCol;
3027 EDIT_GetLineCol(hwnd, (int)((CurrChar + es->DeletedLength) - text),
3028 &(es->CurrLine), &(es->CurrCol));
3029 es->WndRow = es->CurrLine - es->wtop;
3030 es->WndCol = EDIT_StrLength(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
3031 es->CurrCol, 0) - es->wleft;
3032 es->SelEndLine = es->CurrLine;
3033 es->SelEndCol = es->CurrCol;
3035 InvalidateRect(hwnd, NULL, TRUE);
3036 UpdateWindow(hwnd);
3037 return 1;
3039 else
3040 return 0;
3044 /*********************************************************************
3045 * EDIT_HeapAlloc
3047 * Allocate the specified number of bytes on the specified local heap.
3050 unsigned int EDIT_HeapAlloc(HWND hwnd, int bytes)
3052 WND *wndPtr = WIN_FindWndPtr(hwnd);
3053 unsigned int ret;
3055 ret = LOCAL_Alloc( wndPtr->hInstance, LMEM_FIXED, bytes );
3056 if (ret == 0)
3057 printf("EDIT_HeapAlloc: Out of heap-memory\n");
3058 return ret;
3062 /*********************************************************************
3063 * EDIT_HeapAddr
3065 * Return the address of the memory pointed to by the handle.
3068 void *EDIT_HeapAddr(HWND hwnd, unsigned int handle)
3070 WND *wndPtr = WIN_FindWndPtr(hwnd);
3071 return handle ? PTR_SEG_OFF_TO_LIN( wndPtr->hInstance, handle ) : 0;
3075 /*********************************************************************
3076 * EDIT_HeapReAlloc
3078 * Reallocate the memory pointed to by the handle.
3081 unsigned int EDIT_HeapReAlloc(HWND hwnd, unsigned int handle, int bytes)
3083 WND *wndPtr = WIN_FindWndPtr(hwnd);
3085 return LOCAL_ReAlloc( wndPtr->hInstance, handle, bytes, LMEM_FIXED );
3089 /*********************************************************************
3090 * EDIT_HeapFree
3092 * Frees the memory pointed to by the handle.
3095 void EDIT_HeapFree(HWND hwnd, unsigned int handle)
3097 WND *wndPtr = WIN_FindWndPtr(hwnd);
3099 LOCAL_Free( wndPtr->hInstance, handle );
3103 /*********************************************************************
3104 * EDIT_HeapSize
3106 * Return the size of the given object on the local heap.
3109 unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle)
3111 WND *wndPtr = WIN_FindWndPtr(hwnd);
3113 #if 0
3114 return HEAP_LocalSize((MDESC **)*(LONG *)(wndPtr->wExtra + 2), handle);
3115 #endif
3116 return LOCAL_Size( wndPtr->hInstance, handle );
3120 /*********************************************************************
3121 * EM_SETHANDLE message function
3124 void EDIT_SetHandleMsg(HWND hwnd, WORD wParam)
3126 WND *wndPtr = WIN_FindWndPtr(hwnd);
3127 EDITSTATE *es =
3128 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3130 if (IsMultiLine())
3132 es->hText = wParam;
3133 es->textlen = EDIT_HeapSize(hwnd, es->hText);
3134 es->wlines = 0;
3135 es->wtop = es->wleft = 0;
3136 es->CurrLine = es->CurrCol = 0;
3137 es->WndRow = es->WndCol = 0;
3138 es->TextChanged = FALSE;
3139 es->textwidth = 0;
3140 es->SelBegLine = es->SelBegCol = 0;
3141 es->SelEndLine = es->SelEndCol = 0;
3142 dprintf_edit(stddeb, "EDIT_SetHandleMsg: textlen=%d\n",
3143 es->textlen);
3145 EDIT_BuildTextPointers(hwnd);
3146 es->PaintBkgd = TRUE;
3147 InvalidateRect(hwnd, NULL, TRUE);
3148 UpdateWindow(hwnd);
3153 /*********************************************************************
3154 * EM_SETTABSTOPS message function
3157 LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam)
3159 unsigned short *tabstops;
3160 WND *wndPtr = WIN_FindWndPtr(hwnd);
3161 EDITSTATE *es =
3162 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3164 es->NumTabStops = wParam;
3165 if (wParam == 0)
3166 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, 1);
3167 else if (wParam == 1)
3169 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, 1);
3170 tabstops = (unsigned short *)EDIT_HeapAddr(hwnd, es->hTabStops);
3171 *tabstops = (unsigned short)lParam;
3173 else
3175 es->hTabStops = EDIT_HeapReAlloc(hwnd, es->hTabStops, wParam);
3176 tabstops = (unsigned short *)EDIT_HeapAddr(hwnd, es->hTabStops);
3177 memcpy(tabstops, (unsigned short *)lParam, wParam);
3179 return 0L;
3183 /*********************************************************************
3184 * EDIT_CopyToClipboard
3186 * Copy the specified text to the clipboard.
3189 void EDIT_CopyToClipboard(HWND hwnd)
3191 HANDLE hMem;
3192 char *lpMem;
3193 int i, len;
3194 char *bbl, *bel;
3195 WND *wndPtr = WIN_FindWndPtr(hwnd);
3196 EDITSTATE *es =
3197 (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
3199 bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
3200 bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
3201 len = (int)(bel - bbl);
3203 hMem = GlobalAlloc(GHND, (DWORD)(len + 1));
3204 lpMem = GlobalLock(hMem);
3206 for (i = 0; i < len; i++)
3207 *lpMem++ = *bbl++;
3209 GlobalUnlock(hMem);
3210 OpenClipboard(hwnd);
3211 EmptyClipboard();
3212 SetClipboardData(CF_TEXT, hMem);
3213 CloseClipboard();
3217 /*********************************************************************
3218 * WM_PASTE message function
3221 void EDIT_PasteMsg(HWND hwnd)
3223 HANDLE hClipMem;
3224 char *lpClipMem;
3226 OpenClipboard(hwnd);
3227 if (!(hClipMem = GetClipboardData(CF_TEXT)))
3229 /* no text in clipboard */
3230 CloseClipboard();
3231 return;
3233 lpClipMem = GlobalLock(hClipMem);
3234 EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem));
3235 GlobalUnlock(hClipMem);
3236 CloseClipboard();
3237 InvalidateRect(hwnd, NULL, TRUE);
3238 UpdateWindow(hwnd);
3242 /*********************************************************************
3243 * Utility functions
3246 void swap(int *a, int *b)
3248 int x;
3250 x = *a;
3251 *a = *b;
3252 *b = x;