- Use the Wine spooler service as the service entry template as I was
[reactos.git] / rosapps / dflat32 / editbox.c
1 /* ------------- editbox.c ------------ */
2 #include "dflat.h"
3
4 #define EditBufLen(wnd) (DfIsMultiLine(wnd) ? DF_EDITLEN : DF_ENTRYLEN)
5 #define SetLinePointer(wnd, ln) (wnd->CurrLine = ln)
6 #define isWhite(c) ((c)==' '||(c)=='\n')
7 /* ---------- local prototypes ----------- */
8 static void SaveDeletedText(DFWINDOW, char *, int);
9 static void Forward(DFWINDOW);
10 static void Backward(DFWINDOW);
11 static void End(DFWINDOW);
12 static void Home(DFWINDOW);
13 static void Downward(DFWINDOW);
14 static void Upward(DFWINDOW);
15 static void StickEnd(DFWINDOW);
16 static void NextWord(DFWINDOW);
17 static void PrevWord(DFWINDOW);
18 static void ModTextPointers(DFWINDOW, int, int);
19 static void SetAnchor(DFWINDOW, int, int);
20 /* -------- local variables -------- */
21 static BOOL KeyBoardMarking, ButtonDown;
22 static BOOL TextMarking;
23 static int ButtonX, ButtonY;
24 static int PrevY = -1;
25
26 /* ----------- DFM_CREATE_WINDOW Message ---------- */
27 static int CreateWindowMsg(DFWINDOW wnd)
28 {
29 int rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_CREATE_WINDOW, 0, 0);
30 wnd->MaxTextLength = DF_MAXTEXTLEN+1;
31 wnd->textlen = EditBufLen(wnd);
32 wnd->InsertMode = TRUE;
33 DfSendMessage(wnd, DFM_CLEARTEXT, 0, 0);
34 return rtn;
35 }
36 /* ----------- DFM_SETTEXT Message ---------- */
37 static int SetTextMsg(DFWINDOW wnd, DF_PARAM p1)
38 {
39 int rtn = FALSE;
40 if (strlen((char *)p1) <= wnd->MaxTextLength)
41 rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_SETTEXT, p1, 0);
42 return rtn;
43 }
44 /* ----------- DFM_CLEARTEXT Message ------------ */
45 static int ClearTextMsg(DFWINDOW wnd)
46 {
47 int rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_CLEARTEXT, 0, 0);
48 unsigned blen = EditBufLen(wnd)+2;
49 wnd->text = DfRealloc(wnd->text, blen);
50 memset(wnd->text, 0, blen);
51 wnd->wlines = 0;
52 wnd->CurrLine = 0;
53 wnd->CurrCol = 0;
54 wnd->WndRow = 0;
55 wnd->wleft = 0;
56 wnd->wtop = 0;
57 wnd->textwidth = 0;
58 wnd->TextChanged = FALSE;
59 return rtn;
60 }
61 /* ----------- DFM_ADDTEXT Message ---------- */
62 static int AddTextMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
63 {
64 int rtn = FALSE;
65 if (strlen((char *)p1)+wnd->textlen <= wnd->MaxTextLength) {
66 rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_ADDTEXT, p1, p2);
67 if (rtn != FALSE) {
68 if (!DfIsMultiLine(wnd)) {
69 wnd->CurrLine = 0;
70 wnd->CurrCol = strlen((char *)p1);
71 if (wnd->CurrCol >= DfClientWidth(wnd)) {
72 wnd->wleft = wnd->CurrCol-DfClientWidth(wnd);
73 wnd->CurrCol -= wnd->wleft;
74 }
75 wnd->BlkEndCol = wnd->CurrCol;
76 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR,
77 DfWndCol, wnd->WndRow);
78 }
79 }
80 }
81 return rtn;
82 }
83 /* ----------- DFM_GETTEXT Message ---------- */
84 static int GetTextMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
85 {
86 char *cp1 = (char *)p1;
87 char *cp2 = wnd->text;
88 if (cp2 != NULL) {
89 while (p2-- && *cp2 && *cp2 != '\n')
90 *cp1++ = *cp2++;
91 *cp1 = '\0';
92 return TRUE;
93 }
94 return FALSE;
95 }
96 /* ----------- DFM_SETTEXTLENGTH Message ---------- */
97 static int SetTextLengthMsg(DFWINDOW wnd, unsigned int len)
98 {
99 if (++len < DF_MAXTEXTLEN) {
100 wnd->MaxTextLength = len;
101 if (len < wnd->textlen) {
102 wnd->text=DfRealloc(wnd->text, len+2);
103 wnd->textlen = len;
104 *((wnd->text)+len) = '\0';
105 *((wnd->text)+len+1) = '\0';
106 DfBuildTextPointers(wnd);
107 }
108 return TRUE;
109 }
110 return FALSE;
111 }
112 /* ----------- DFM_KEYBOARD_CURSOR Message ---------- */
113 static void KeyboardCursorMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
114 {
115 wnd->CurrCol = (int)p1 + wnd->wleft;
116 wnd->WndRow = (int)p2;
117 wnd->CurrLine = (int)p2 + wnd->wtop;
118 if (wnd == DfInFocus) {
119 if (DfCharInView(wnd, (int)p1, (int)p2))
120 DfSendMessage(NULL, DFM_SHOW_CURSOR,
121 (wnd->InsertMode && !TextMarking), 0);
122 else
123 DfSendMessage(NULL, DFM_HIDE_CURSOR, 0, 0);
124 }
125 }
126 /* ----------- SIZE Message ---------- */
127 int SizeMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
128 {
129 int rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_DFM_SIZE, p1, p2);
130 if (DfWndCol > DfClientWidth(wnd)-1)
131 wnd->CurrCol = DfClientWidth(wnd)-1 + wnd->wleft;
132 if (wnd->WndRow > DfClientHeight(wnd)-1) {
133 wnd->WndRow = DfClientHeight(wnd)-1;
134 SetLinePointer(wnd, wnd->WndRow+wnd->wtop);
135 }
136 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
137 return rtn;
138 }
139 /* ----------- DFM_SCROLL Message ---------- */
140 static int ScrollMsg(DFWINDOW wnd, DF_PARAM p1)
141 {
142 int rtn = FALSE;
143 if (DfIsMultiLine(wnd)) {
144 rtn = DfBaseWndProc(DF_EDITBOX,wnd,DFM_SCROLL,p1,0);
145 if (rtn != FALSE) {
146 if (p1) {
147 /* -------- scrolling up --------- */
148 if (wnd->WndRow == 0) {
149 wnd->CurrLine++;
150 StickEnd(wnd);
151 }
152 else
153 --wnd->WndRow;
154 }
155 else {
156 /* -------- scrolling down --------- */
157 if (wnd->WndRow == DfClientHeight(wnd)-1) {
158 if (wnd->CurrLine > 0)
159 --wnd->CurrLine;
160 StickEnd(wnd);
161 }
162 else
163 wnd->WndRow++;
164 }
165 DfSendMessage(wnd,DFM_KEYBOARD_CURSOR,DfWndCol,wnd->WndRow);
166 }
167 }
168 return rtn;
169 }
170 /* ----------- DFM_HORIZSCROLL Message ---------- */
171 static int HorizScrollMsg(DFWINDOW wnd, DF_PARAM p1)
172 {
173 int rtn = FALSE;
174 char *currchar = DfCurrChar;
175 if (!(p1 &&
176 wnd->CurrCol == wnd->wleft && *currchar == '\n')) {
177 rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_HORIZSCROLL, p1, 0);
178 if (rtn != FALSE) {
179 if (wnd->CurrCol < wnd->wleft)
180 wnd->CurrCol++;
181 else if (DfWndCol == DfClientWidth(wnd))
182 --wnd->CurrCol;
183 DfSendMessage(wnd,DFM_KEYBOARD_CURSOR,DfWndCol,wnd->WndRow);
184 }
185 }
186 return rtn;
187 }
188 /* ----------- DFM_SCROLLPAGE Message ---------- */
189 static int ScrollPageMsg(DFWINDOW wnd, DF_PARAM p1)
190 {
191 int rtn = FALSE;
192 if (DfIsMultiLine(wnd)) {
193 rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_SCROLLPAGE, p1, 0);
194 SetLinePointer(wnd, wnd->wtop+wnd->WndRow);
195 StickEnd(wnd);
196 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR,DfWndCol, wnd->WndRow);
197 }
198 return rtn;
199 }
200 /* ----------- HORIZSCROLLPAGE Message ---------- */
201 static int HorizPageMsg(DFWINDOW wnd, DF_PARAM p1)
202 {
203 int rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_HORIZPAGE, p1, 0);
204 if ((int) p1 == FALSE) {
205 if (wnd->CurrCol > wnd->wleft+DfClientWidth(wnd)-1)
206 wnd->CurrCol = wnd->wleft+DfClientWidth(wnd)-1;
207 }
208 else if (wnd->CurrCol < wnd->wleft)
209 wnd->CurrCol = wnd->wleft;
210 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
211 return rtn;
212 }
213 /* ----- Extend the marked block to the new x,y position ---- */
214 static void ExtendBlock(DFWINDOW wnd, int x, int y)
215 {
216 int bbl, bel;
217 int ptop = min(wnd->BlkBegLine, wnd->BlkEndLine);
218 int pbot = max(wnd->BlkBegLine, wnd->BlkEndLine);
219 char *lp = DfTextLine(wnd, wnd->wtop+y);
220 int len = (int) (strchr(lp, '\n') - lp);
221 x = max(0, min(x, len));
222 y = max(0, y);
223 wnd->BlkEndCol = min(len, x+wnd->wleft);
224 wnd->BlkEndLine = y+wnd->wtop;
225 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, wnd->BlkEndCol, wnd->BlkEndLine);
226 bbl = min(wnd->BlkBegLine, wnd->BlkEndLine);
227 bel = max(wnd->BlkBegLine, wnd->BlkEndLine);
228 while (ptop < bbl) {
229 DfWriteTextLine(wnd, NULL, ptop, FALSE);
230 ptop++;
231 }
232 for (y = bbl; y <= bel; y++)
233 DfWriteTextLine(wnd, NULL, y, FALSE);
234 while (pbot > bel) {
235 DfWriteTextLine(wnd, NULL, pbot, FALSE);
236 --pbot;
237 }
238 }
239 /* ----------- DFM_LEFT_BUTTON Message ---------- */
240 static int LeftButtonMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
241 {
242 int MouseX = (int) p1 - DfGetClientLeft(wnd);
243 int MouseY = (int) p2 - DfGetClientTop(wnd);
244 DFRECT rc = DfClientRect(wnd);
245 char *lp;
246 int len;
247 if (KeyBoardMarking)
248 return TRUE;
249 if (DfWindowMoving || DfWindowSizing)
250 return FALSE;
251 if (DfIsMultiLine(wnd)) {
252 if (TextMarking) {
253 if (!DfInsideRect(p1, p2, rc)) {
254 int x = MouseX, y = MouseY;
255 int dir;
256 DFMESSAGE msg = 0;
257 if ((int)p2 == DfGetTop(wnd))
258 y++, dir = FALSE, msg = DFM_SCROLL;
259 else if ((int)p2 == DfGetBottom(wnd))
260 --y, dir = TRUE, msg = DFM_SCROLL;
261 else if ((int)p1 == DfGetLeft(wnd))
262 --x, dir = FALSE, msg = DFM_HORIZSCROLL;
263 else if ((int)p1 == DfGetRight(wnd))
264 x++, dir = TRUE, msg = DFM_HORIZSCROLL;
265 if (msg != 0) {
266 if (DfSendMessage(wnd, msg, dir, 0))
267 ExtendBlock(wnd, x, y);
268 DfSendMessage(wnd, DFM_PAINT, 0, 0);
269 }
270 }
271 return TRUE;
272 }
273 if (!DfInsideRect(p1, p2, rc))
274 return FALSE;
275 if (DfTextBlockMarked(wnd)) {
276 DfClearTextBlock(wnd);
277 DfSendMessage(wnd, DFM_PAINT, 0, 0);
278 }
279 if (wnd->wlines) {
280 if (MouseY > wnd->wlines-1)
281 return TRUE;
282 lp = DfTextLine(wnd, MouseY+wnd->wtop);
283 len = (int) (strchr(lp, '\n') - lp);
284 MouseX = min(MouseX, len);
285 if (MouseX < wnd->wleft) {
286 MouseX = 0;
287 DfSendMessage(wnd, DFM_KEYBOARD, DF_HOME, 0);
288 }
289 ButtonDown = TRUE;
290 ButtonX = MouseX;
291 ButtonY = MouseY;
292 }
293 else
294 MouseX = MouseY = 0;
295 wnd->WndRow = MouseY;
296 SetLinePointer(wnd, MouseY+wnd->wtop);
297 }
298 if (DfIsMultiLine(wnd) ||
299 (!DfTextBlockMarked(wnd)
300 && (int)(MouseX+wnd->wleft) < (int)strlen(wnd->text)))
301 wnd->CurrCol = MouseX+wnd->wleft;
302 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
303 return TRUE;
304 }
305 /* ----------- MOUSE_MOVED Message ---------- */
306 static int MouseMovedMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
307 {
308 int MouseX = (int) p1 - DfGetClientLeft(wnd);
309 int MouseY = (int) p2 - DfGetClientTop(wnd);
310 DFRECT rc = DfClientRect(wnd);
311 if (!DfInsideRect(p1, p2, rc))
312 return FALSE;
313 if (MouseY > wnd->wlines-1)
314 return FALSE;
315 if (ButtonDown) {
316 SetAnchor(wnd, ButtonX+wnd->wleft, ButtonY+wnd->wtop);
317 TextMarking = TRUE;
318 rc = DfWindowRect(wnd);
319 DfSendMessage(NULL,DFM_MOUSE_TRAVEL,(DF_PARAM) &rc, 0);
320 ButtonDown = FALSE;
321 }
322 if (TextMarking && !(DfWindowMoving || DfWindowSizing)) {
323 ExtendBlock(wnd, MouseX, MouseY);
324 return TRUE;
325 }
326 return FALSE;
327 }
328 static void StopMarking(DFWINDOW wnd)
329 {
330 TextMarking = FALSE;
331 if (wnd->BlkBegLine > wnd->BlkEndLine) {
332 swap(wnd->BlkBegLine, wnd->BlkEndLine);
333 swap(wnd->BlkBegCol, wnd->BlkEndCol);
334 }
335 if (wnd->BlkBegLine == wnd->BlkEndLine &&
336 wnd->BlkBegCol > wnd->BlkEndCol)
337 swap(wnd->BlkBegCol, wnd->BlkEndCol);
338 }
339 /* ----------- BUTTON_RELEASED Message ---------- */
340 static int ButtonReleasedMsg(DFWINDOW wnd)
341 {
342 if (DfIsMultiLine(wnd)) {
343 ButtonDown = FALSE;
344 if (TextMarking && !(DfWindowMoving || DfWindowSizing)) {
345 /* release the mouse ouside the edit box */
346 DfSendMessage(NULL, DFM_MOUSE_TRAVEL, 0, 0);
347 StopMarking(wnd);
348 return TRUE;
349 }
350 else
351 PrevY = -1;
352 }
353 return FALSE;
354 }
355 /* ---- Process text block keys for multiline text box ---- */
356 static void DoMultiLines(DFWINDOW wnd, int c, DF_PARAM p2)
357 {
358 if (DfIsMultiLine(wnd) && !KeyBoardMarking) {
359 if ((int)p2 & (DF_LEFTSHIFT | DF_RIGHTSHIFT)) {
360 switch (c) {
361 case DF_HOME:
362 case DF_CTRL_HOME:
363 case DF_CTRL_BS:
364 case DF_PGUP:
365 case DF_CTRL_PGUP:
366 case DF_UP:
367 case DF_BS:
368 case DF_END:
369 case DF_CTRL_END:
370 case DF_PGDN:
371 case DF_CTRL_PGDN:
372 case DF_DN:
373 case DF_FWD:
374 case DF_CTRL_FWD:
375 KeyBoardMarking = TextMarking = TRUE;
376 SetAnchor(wnd, wnd->CurrCol, wnd->CurrLine);
377 break;
378 default:
379 break;
380 }
381 }
382 }
383 }
384 /* ---------- page/scroll keys ----------- */
385 static int DoScrolling(DFWINDOW wnd, int c, DF_PARAM p2)
386 {
387 switch (c) {
388 case DF_PGUP:
389 case DF_PGDN:
390 if (DfIsMultiLine(wnd))
391 DfBaseWndProc(DF_EDITBOX, wnd, DFM_KEYBOARD, c, p2);
392 break;
393 case DF_CTRL_PGUP:
394 case DF_CTRL_PGDN:
395 DfBaseWndProc(DF_EDITBOX, wnd, DFM_KEYBOARD, c, p2);
396 break;
397 case DF_HOME:
398 Home(wnd);
399 break;
400 case DF_END:
401 End(wnd);
402 break;
403 case DF_CTRL_FWD:
404 NextWord(wnd);
405 break;
406 case DF_CTRL_BS:
407 PrevWord(wnd);
408 break;
409 case DF_CTRL_HOME:
410 if (DfIsMultiLine(wnd)) {
411 DfSendMessage(wnd, DFM_SCROLLDOC, TRUE, 0);
412 wnd->CurrLine = 0;
413 wnd->WndRow = 0;
414 }
415 Home(wnd);
416 break;
417 case DF_CTRL_END:
418 if (DfIsMultiLine(wnd) &&
419 wnd->WndRow+wnd->wtop+1 < wnd->wlines
420 && wnd->wlines > 0) {
421 DfSendMessage(wnd, DFM_SCROLLDOC, FALSE, 0);
422 SetLinePointer(wnd, wnd->wlines-1);
423 wnd->WndRow =
424 min(DfClientHeight(wnd)-1, wnd->wlines-1);
425 Home(wnd);
426 }
427 End(wnd);
428 break;
429 case DF_UP:
430 if (DfIsMultiLine(wnd))
431 Upward(wnd);
432 break;
433 case DF_DN:
434 if (DfIsMultiLine(wnd))
435 Downward(wnd);
436 break;
437 case DF_FWD:
438 Forward(wnd);
439 break;
440 case DF_BS:
441 Backward(wnd);
442 break;
443 default:
444 return FALSE;
445 }
446 if (!KeyBoardMarking && DfTextBlockMarked(wnd)) {
447 DfClearTextBlock(wnd);
448 DfSendMessage(wnd, DFM_PAINT, 0, 0);
449 }
450 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
451 return TRUE;
452 }
453 /* -------------- Del key ---------------- */
454 static void DelKey(DFWINDOW wnd)
455 {
456 char *currchar = DfCurrChar;
457 int repaint = *currchar == '\n';
458 if (DfTextBlockMarked(wnd)) {
459 DfSendMessage(wnd, DFM_COMMAND, DF_ID_DELETETEXT, 0);
460 DfSendMessage(wnd, DFM_PAINT, 0, 0);
461 return;
462 }
463 if (DfIsMultiLine(wnd) && *currchar == '\n' && *(currchar+1) == '\0')
464 return;
465 strcpy(currchar, currchar+1);
466 if (repaint) {
467 DfBuildTextPointers(wnd);
468 DfSendMessage(wnd, DFM_PAINT, 0, 0);
469 }
470 else {
471 ModTextPointers(wnd, wnd->CurrLine+1, -1);
472 DfWriteTextLine(wnd, NULL, wnd->WndRow+wnd->wtop, FALSE);
473 }
474 wnd->TextChanged = TRUE;
475 }
476 /* ------------ Tab key ------------ */
477 static void TabKey(DFWINDOW wnd, DF_PARAM p2)
478 {
479 if (DfIsMultiLine(wnd)) {
480 int insmd = wnd->InsertMode;
481 do {
482 char *cc = DfCurrChar+1;
483 if (!insmd && *cc == '\0')
484 break;
485 if (wnd->textlen == wnd->MaxTextLength)
486 break;
487 DfSendMessage(wnd,DFM_KEYBOARD,insmd ? ' ' : DF_FWD,0);
488 } while (wnd->CurrCol % DfCfg.Tabs);
489 }
490 else
491 DfPostMessage(DfGetParent(wnd), DFM_KEYBOARD, '\t', p2);
492 }
493 /* ------------ Shift+Tab key ------------ */
494 static void ShiftTabKey(DFWINDOW wnd, DF_PARAM p2)
495 {
496 if (DfIsMultiLine(wnd)) {
497 do {
498 if (DfCurrChar == DfGetText(wnd))
499 break;
500 DfSendMessage(wnd,DFM_KEYBOARD,DF_BS,0);
501 } while (wnd->CurrCol % DfCfg.Tabs);
502 }
503 else
504 DfPostMessage(DfGetParent(wnd), DFM_KEYBOARD, DF_SHIFT_HT, p2);
505 }
506 /* --------- All displayable typed keys ------------- */
507 static void KeyTyped(DFWINDOW wnd, int c)
508 {
509 char *currchar = DfCurrChar;
510 if ((c != '\n' && c < ' ') || (c & 0x1000))
511 /* ---- not recognized by editor --- */
512 return;
513 if (!DfIsMultiLine(wnd) && DfTextBlockMarked(wnd)) {
514 DfSendMessage(wnd, DFM_CLEARTEXT, 0, 0);
515 currchar = DfCurrChar;
516 }
517 /* ---- test typing at end of text ---- */
518 if (currchar == (char*)(wnd->text+wnd->MaxTextLength)) {
519 /* ---- typing at the end of maximum buffer ---- */
520 DfBeep();
521 return;
522 }
523 if (*currchar == '\0') {
524 /* --- insert a newline at end of text --- */
525 *currchar = '\n';
526 *(currchar+1) = '\0';
527 DfBuildTextPointers(wnd);
528 }
529 /* --- displayable char or newline --- */
530 if (c == '\n' || wnd->InsertMode || *currchar == '\n') {
531 /* ------ inserting the keyed character ------ */
532 if (wnd->text[wnd->textlen-1] != '\0') {
533 /* --- the current text buffer is full --- */
534 if (wnd->textlen == wnd->MaxTextLength) {
535 /* --- text buffer is at maximum size --- */
536 DfBeep();
537 return;
538 }
539 /* ---- increase the text buffer size ---- */
540 wnd->textlen += DF_GROWLENGTH;
541 /* --- but not above maximum size --- */
542 if (wnd->textlen > wnd->MaxTextLength)
543 wnd->textlen = wnd->MaxTextLength;
544 wnd->text = DfRealloc(wnd->text, wnd->textlen+2);
545 wnd->text[wnd->textlen-1] = '\0';
546 currchar = DfCurrChar;
547 }
548 memmove(currchar+1, currchar, strlen(currchar)+1);
549 ModTextPointers(wnd, wnd->CurrLine+1, 1);
550 if (DfIsMultiLine(wnd) && wnd->wlines > 1)
551 wnd->textwidth = max(wnd->textwidth,
552 (int) (DfTextLine(wnd, wnd->CurrLine+1)-
553 DfTextLine(wnd, wnd->CurrLine)));
554 else
555 wnd->textwidth = max((int)wnd->textwidth,
556 (int)strlen(wnd->text));
557 DfWriteTextLine(wnd, NULL,
558 wnd->wtop+wnd->WndRow, FALSE);
559 }
560 /* ----- put the char in the buffer ----- */
561 *currchar = c;
562 wnd->TextChanged = TRUE;
563 if (c == '\n') {
564 wnd->wleft = 0;
565 DfBuildTextPointers(wnd);
566 End(wnd);
567 Forward(wnd);
568 DfSendMessage(wnd, DFM_PAINT, 0, 0);
569 return;
570 }
571 /* ---------- test end of window --------- */
572 if (DfWndCol == DfClientWidth(wnd)-1) {
573 if (!DfIsMultiLine(wnd)) {
574 if (!(currchar == (char*)(wnd->text+wnd->MaxTextLength-2)))
575 DfSendMessage(wnd, DFM_HORIZSCROLL, TRUE, 0);
576 }
577 else {
578 char *cp = currchar;
579 while (*cp != ' ' && cp != (char*)DfTextLine(wnd, wnd->CurrLine))
580 --cp;
581 if (cp == (char*)DfTextLine(wnd, wnd->CurrLine) ||
582 !wnd->WordWrapMode)
583 DfSendMessage(wnd, DFM_HORIZSCROLL, TRUE, 0);
584 else {
585 int dif = 0;
586 if (c != ' ') {
587 dif = (int) (currchar - cp);
588 wnd->CurrCol -= dif;
589 DfSendMessage(wnd, DFM_KEYBOARD, DF_DEL, 0);
590 --dif;
591 }
592 DfSendMessage(wnd, DFM_KEYBOARD, '\n', 0);
593 currchar = DfCurrChar;
594 wnd->CurrCol = dif;
595 if (c == ' ')
596 return;
597 }
598 }
599 }
600 /* ------ display the character ------ */
601 DfSetStandardColor(wnd);
602 DfPutWindowChar(wnd, c, DfWndCol, wnd->WndRow);
603 /* ----- advance the pointers ------ */
604 wnd->CurrCol++;
605 }
606 /* ------------ screen changing key strokes ------------- */
607 static void DoKeyStroke(DFWINDOW wnd, int c, DF_PARAM p2)
608 {
609 switch (c) {
610 case DF_RUBOUT:
611 if (wnd->CurrCol == 0 && wnd->CurrLine == 0)
612 break;
613 Backward(wnd);
614 case DF_DEL:
615 DelKey(wnd);
616 break;
617 case DF_SHIFT_HT:
618 ShiftTabKey(wnd, p2);
619 break;
620 case '\t':
621 TabKey(wnd, p2);
622 break;
623 case '\r':
624 if (!DfIsMultiLine(wnd)) {
625 DfPostMessage(DfGetParent(wnd), DFM_KEYBOARD, c, p2);
626 break;
627 }
628 c = '\n';
629 default:
630 if (DfTextBlockMarked(wnd)) {
631 DfSendMessage(wnd, DFM_COMMAND, DF_ID_DELETETEXT, 0);
632 DfSendMessage(wnd, DFM_PAINT, 0, 0);
633 }
634 KeyTyped(wnd, c);
635 break;
636 }
637 }
638 /* ----------- DFM_KEYBOARD Message ---------- */
639 static int KeyboardMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
640 {
641 int c = (int) p1;
642
643 if (DfWindowMoving || DfWindowSizing || ((int)p2 & DF_ALTKEY))
644 return FALSE;
645
646 switch (c)
647 {
648 /* these keys get processed by lower classes */
649 case DF_ESC:
650 case DF_F1:
651 case DF_F2:
652 case DF_F3:
653 case DF_F4:
654 case DF_F5:
655 case DF_F6:
656 case DF_F7:
657 case DF_F8:
658 case DF_F9:
659 case DF_F10:
660 case DF_INS:
661 case DF_SHIFT_INS:
662 case DF_SHIFT_DEL:
663 return FALSE;
664
665 /* these keys get processed here */
666 case DF_CTRL_FWD:
667 case DF_CTRL_BS:
668 case DF_CTRL_HOME:
669 case DF_CTRL_END:
670 case DF_CTRL_PGUP:
671 case DF_CTRL_PGDN:
672 break;
673
674 default:
675 /* other ctrl keys get processed by lower classes */
676 if ((int)p2 & DF_CTRLKEY)
677 return FALSE;
678 /* all other keys get processed here */
679 break;
680 }
681
682 DoMultiLines(wnd, c, p2);
683 if (DoScrolling(wnd, c, p2))
684 {
685 if (KeyBoardMarking)
686 ExtendBlock(wnd, DfWndCol, wnd->WndRow);
687 }
688 else if (!DfTestAttribute(wnd, DF_READONLY))
689 {
690 DoKeyStroke(wnd, c, p2);
691 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
692 }
693 else
694 DfBeep();
695
696 return TRUE;
697 }
698
699 /* ----------- DFM_SHIFT_CHANGED Message ---------- */
700 static void ShiftChangedMsg(DFWINDOW wnd, DF_PARAM p1)
701 {
702 if (!((int)p1 & (DF_LEFTSHIFT | DF_RIGHTSHIFT)) &&
703 KeyBoardMarking) {
704 StopMarking(wnd);
705 KeyBoardMarking = FALSE;
706 }
707 }
708 /* ----------- DF_ID_DELETETEXT Command ---------- */
709 static void DeleteTextCmd(DFWINDOW wnd)
710 {
711 if (DfTextBlockMarked(wnd)) {
712 char *bbl=DfTextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
713 char *bel=DfTextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
714 int len = (int) (bel - bbl);
715 SaveDeletedText(wnd, bbl, len);
716 wnd->TextChanged = TRUE;
717 strcpy(bbl, bel);
718 wnd->CurrLine = DfTextLineNumber(wnd, bbl-wnd->BlkBegCol);
719 wnd->CurrCol = wnd->BlkBegCol;
720 wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
721 if (wnd->WndRow < 0) {
722 wnd->wtop = wnd->BlkBegLine;
723 wnd->WndRow = 0;
724 }
725 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
726 DfClearTextBlock(wnd);
727 DfBuildTextPointers(wnd);
728 }
729 }
730 /* ----------- DF_ID_CLEAR Command ---------- */
731 static void ClearCmd(DFWINDOW wnd)
732 {
733 if (DfTextBlockMarked(wnd)) {
734 char *bbl=DfTextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
735 char *bel=DfTextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
736 int len = (int) (bel - bbl);
737 SaveDeletedText(wnd, bbl, len);
738 wnd->CurrLine = DfTextLineNumber(wnd, bbl);
739 wnd->CurrCol = wnd->BlkBegCol;
740 wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
741 if (wnd->WndRow < 0) {
742 wnd->WndRow = 0;
743 wnd->wtop = wnd->BlkBegLine;
744 }
745 /* ------ change all text lines in block to \n ----- */
746 while (bbl < bel) {
747 char *cp = strchr(bbl, '\n');
748 if (cp > bel)
749 cp = bel;
750 strcpy(bbl, cp);
751 bel -= (int) (cp - bbl);
752 bbl++;
753 }
754 DfClearTextBlock(wnd);
755 DfBuildTextPointers(wnd);
756 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
757 wnd->TextChanged = TRUE;
758 }
759 }
760 /* ----------- DF_ID_UNDO Command ---------- */
761 static void UndoCmd(DFWINDOW wnd)
762 {
763 if (wnd->DeletedText != NULL) {
764 DfPasteText(wnd, wnd->DeletedText, wnd->DeletedLength);
765 free(wnd->DeletedText);
766 wnd->DeletedText = NULL;
767 wnd->DeletedLength = 0;
768 DfSendMessage(wnd, DFM_PAINT, 0, 0);
769 }
770 }
771 /* ----------- DF_ID_PARAGRAPH Command ---------- */
772 static void ParagraphCmd(DFWINDOW wnd)
773 {
774 int bc, fl;
775 char *bl, *bbl, *bel, *bb;
776
777 DfClearTextBlock(wnd);
778 /* ---- forming paragraph from DfCursor position --- */
779 fl = wnd->wtop + wnd->WndRow;
780 bbl = bel = bl = DfTextLine(wnd, wnd->CurrLine);
781 if ((bc = wnd->CurrCol) >= DfClientWidth(wnd))
782 bc = 0;
783 Home(wnd);
784 /* ---- locate the end of the paragraph ---- */
785 while (*bel) {
786 int blank = TRUE;
787 char *bll = bel;
788 /* --- blank line marks end of paragraph --- */
789 while (*bel && *bel != '\n') {
790 if (*bel != ' ')
791 blank = FALSE;
792 bel++;
793 }
794 if (blank) {
795 bel = bll;
796 break;
797 }
798 if (*bel)
799 bel++;
800 }
801 if (bel == bbl) {
802 DfSendMessage(wnd, DFM_KEYBOARD, DF_DN, 0);
803 return;
804 }
805 if (*bel == '\0')
806 --bel;
807 if (*bel == '\n')
808 --bel;
809 /* --- change all newlines in block to spaces --- */
810 while ((char*)DfCurrChar < bel) {
811 if (*DfCurrChar == '\n') {
812 *DfCurrChar = ' ';
813 wnd->CurrLine++;
814 wnd->CurrCol = 0;
815 }
816 else
817 wnd->CurrCol++;
818 }
819 /* ---- insert newlines at new margin boundaries ---- */
820 bb = bbl;
821 while ((char*)bbl < (char*)bel) {
822 bbl++;
823 if ((int)(bbl - bb) == DfClientWidth(wnd)-1) {
824 while (*bbl != ' ' && bbl > bb)
825 --bbl;
826 if (*bbl != ' ') {
827 bbl = strchr(bbl, ' ');
828 if (bbl == NULL || bbl >= bel)
829 break;
830 }
831 *bbl = '\n';
832 bb = bbl+1;
833 }
834 }
835 DfBuildTextPointers(wnd);
836 /* --- put DfCursor back at beginning --- */
837 wnd->CurrLine = DfTextLineNumber(wnd, bl);
838 wnd->CurrCol = bc;
839 if (fl < wnd->wtop)
840 wnd->wtop = fl;
841 wnd->WndRow = fl - wnd->wtop;
842 DfSendMessage(wnd, DFM_PAINT, 0, 0);
843 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
844 wnd->TextChanged = TRUE;
845 DfBuildTextPointers(wnd);
846 }
847 /* ----------- COMMAND Message ---------- */
848 static int CommandMsg(DFWINDOW wnd, DF_PARAM p1)
849 {
850 switch ((int)p1) {
851 case DF_ID_DELETETEXT:
852 DeleteTextCmd(wnd);
853 return TRUE;
854 case DF_ID_CLEAR:
855 ClearCmd(wnd);
856 return TRUE;
857 case DF_ID_UNDO:
858 UndoCmd(wnd);
859 return TRUE;
860 case DF_ID_PARAGRAPH:
861 ParagraphCmd(wnd);
862 return TRUE;
863 default:
864 break;
865 }
866 return FALSE;
867 }
868 /* ---------- DFM_CLOSE_WINDOW Message ----------- */
869 static int CloseWindowMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
870 {
871 int rtn;
872 DfSendMessage(NULL, DFM_HIDE_CURSOR, 0, 0);
873 if (wnd->DeletedText != NULL)
874 free(wnd->DeletedText);
875 if (wnd->text != NULL)
876 {
877 free(wnd->text);
878 wnd->text = NULL;
879 }
880 rtn = DfBaseWndProc(DF_EDITBOX, wnd, DFM_CLOSE_WINDOW, p1, p2);
881 return rtn;
882 }
883
884 /* ------- Window processing module for DF_EDITBOX class ------ */
885 int DfEditBoxProc(DFWINDOW wnd, DFMESSAGE msg, DF_PARAM p1, DF_PARAM p2)
886 {
887 int rtn;
888 switch (msg) {
889 case DFM_CREATE_WINDOW:
890 return CreateWindowMsg(wnd);
891 case DFM_ADDTEXT:
892 return AddTextMsg(wnd, p1, p2);
893 case DFM_SETTEXT:
894 return SetTextMsg(wnd, p1);
895 case DFM_CLEARTEXT:
896 return ClearTextMsg(wnd);
897 case DFM_GETTEXT:
898 return GetTextMsg(wnd, p1, p2);
899 case DFM_SETTEXTLENGTH:
900 return SetTextLengthMsg(wnd, (unsigned) p1);
901 case DFM_KEYBOARD_CURSOR:
902 KeyboardCursorMsg(wnd, p1, p2);
903 return TRUE;
904 case DFM_SETFOCUS:
905 if (!(int)p1)
906 DfSendMessage(NULL, DFM_HIDE_CURSOR, 0, 0);
907 case DFM_PAINT:
908 case DFM_MOVE:
909 rtn = DfBaseWndProc(DF_EDITBOX, wnd, msg, p1, p2);
910 DfSendMessage(wnd,DFM_KEYBOARD_CURSOR,DfWndCol,wnd->WndRow);
911 return rtn;
912 case DFM_DFM_SIZE:
913 return SizeMsg(wnd, p1, p2);
914 case DFM_SCROLL:
915 return ScrollMsg(wnd, p1);
916 case DFM_HORIZSCROLL:
917 return HorizScrollMsg(wnd, p1);
918 case DFM_SCROLLPAGE:
919 return ScrollPageMsg(wnd, p1);
920 case DFM_HORIZPAGE:
921 return HorizPageMsg(wnd, p1);
922 case DFM_LEFT_BUTTON:
923 if (LeftButtonMsg(wnd, p1, p2))
924 return TRUE;
925 break;
926 case MOUSE_MOVED:
927 if (MouseMovedMsg(wnd, p1, p2))
928 return TRUE;
929 break;
930 case DFM_BUTTON_RELEASED:
931 if (ButtonReleasedMsg(wnd))
932 return TRUE;
933 break;
934 case DFM_KEYBOARD:
935 if (KeyboardMsg(wnd, p1, p2))
936 return TRUE;
937 break;
938 case DFM_SHIFT_CHANGED:
939 ShiftChangedMsg(wnd, p1);
940 break;
941 case DFM_COMMAND:
942 if (CommandMsg(wnd, p1))
943 return TRUE;
944 break;
945 case DFM_CLOSE_WINDOW:
946 return CloseWindowMsg(wnd, p1, p2);
947 default:
948 break;
949 }
950 return DfBaseWndProc(DF_EDITBOX, wnd, msg, p1, p2);
951 }
952 /* ------ save deleted text for the Undo command ------ */
953 static void SaveDeletedText(DFWINDOW wnd, char *bbl, int len)
954 {
955 wnd->DeletedLength = len;
956 wnd->DeletedText=DfRealloc(wnd->DeletedText,len);
957 memmove(wnd->DeletedText, bbl, len);
958 }
959 /* ---- DfCursor right key: right one character position ---- */
960 static void Forward(DFWINDOW wnd)
961 {
962 char *cc = DfCurrChar+1;
963 if (*cc == '\0')
964 return;
965 if (*DfCurrChar == '\n') {
966 Home(wnd);
967 Downward(wnd);
968 }
969 else {
970 wnd->CurrCol++;
971 if (DfWndCol == DfClientWidth(wnd))
972 DfSendMessage(wnd, DFM_HORIZSCROLL, TRUE, 0);
973 }
974 }
975 /* ----- stick the moving DfCursor to the end of the line ---- */
976 static void StickEnd(DFWINDOW wnd)
977 {
978 char *cp = DfTextLine(wnd, wnd->CurrLine);
979 char *cp1 = strchr(cp, '\n');
980 int len = cp1 ? (int) (cp1 - cp) : 0;
981 wnd->CurrCol = min(len, wnd->CurrCol);
982 if (wnd->wleft > wnd->CurrCol) {
983 wnd->wleft = max(0, wnd->CurrCol - 4);
984 DfSendMessage(wnd, DFM_PAINT, 0, 0);
985 }
986 else if (wnd->CurrCol-wnd->wleft >= DfClientWidth(wnd)) {
987 wnd->wleft = wnd->CurrCol - (DfClientWidth(wnd)-1);
988 DfSendMessage(wnd, DFM_PAINT, 0, 0);
989 }
990 }
991 /* --------- DfCursor down key: down one line --------- */
992 static void Downward(DFWINDOW wnd)
993 {
994 if (DfIsMultiLine(wnd) &&
995 wnd->WndRow+wnd->wtop+1 < wnd->wlines) {
996 wnd->CurrLine++;
997 if (wnd->WndRow == DfClientHeight(wnd)-1)
998 DfBaseWndProc(DF_EDITBOX, wnd, DFM_SCROLL, TRUE, 0);
999 else
1000 wnd->WndRow++;
1001 StickEnd(wnd);
1002 }
1003 }
1004 /* -------- DfCursor up key: up one line ------------ */
1005 static void Upward(DFWINDOW wnd)
1006 {
1007 if (DfIsMultiLine(wnd) && wnd->CurrLine != 0) {
1008 --wnd->CurrLine;
1009 if (wnd->WndRow == 0)
1010 DfBaseWndProc(DF_EDITBOX, wnd, DFM_SCROLL, FALSE, 0);
1011 else
1012 --wnd->WndRow;
1013 StickEnd(wnd);
1014 }
1015 }
1016 /* ---- DfCursor left key: left one character position ---- */
1017 static void Backward(DFWINDOW wnd)
1018 {
1019 if (wnd->CurrCol) {
1020 --wnd->CurrCol;
1021 if (wnd->CurrCol < wnd->wleft)
1022 DfSendMessage(wnd, DFM_HORIZSCROLL, FALSE, 0);
1023 }
1024 else if (DfIsMultiLine(wnd) && wnd->CurrLine != 0) {
1025 Upward(wnd);
1026 End(wnd);
1027 }
1028 }
1029 /* -------- End key: to end of line ------- */
1030 static void End(DFWINDOW wnd)
1031 {
1032 while (*DfCurrChar && *DfCurrChar != '\n')
1033 ++wnd->CurrCol;
1034 if (DfWndCol >= DfClientWidth(wnd)) {
1035 wnd->wleft = wnd->CurrCol - (DfClientWidth(wnd)-1);
1036 DfSendMessage(wnd, DFM_PAINT, 0, 0);
1037 }
1038 }
1039 /* -------- Home key: to beginning of line ------- */
1040 static void Home(DFWINDOW wnd)
1041 {
1042 wnd->CurrCol = 0;
1043 if (wnd->wleft != 0) {
1044 wnd->wleft = 0;
1045 DfSendMessage(wnd, DFM_PAINT, 0, 0);
1046 }
1047 }
1048 /* -- Ctrl+DfCursor right key: to beginning of next word -- */
1049 static void NextWord(DFWINDOW wnd)
1050 {
1051 int savetop = wnd->wtop;
1052 int saveleft = wnd->wleft;
1053 DfClearVisible(wnd);
1054 while (!isWhite(*DfCurrChar)) {
1055 char *cc = DfCurrChar+1;
1056 if (*cc == '\0')
1057 break;
1058 Forward(wnd);
1059 }
1060 while (isWhite(*DfCurrChar)) {
1061 char *cc = DfCurrChar+1;
1062 if (*cc == '\0')
1063 break;
1064 Forward(wnd);
1065 }
1066 DfSetVisible(wnd);
1067 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
1068 if (wnd->wtop != savetop || wnd->wleft != saveleft)
1069 DfSendMessage(wnd, DFM_PAINT, 0, 0);
1070 }
1071 /* -- Ctrl+DfCursor left key: to beginning of previous word -- */
1072 static void PrevWord(DFWINDOW wnd)
1073 {
1074 int savetop = wnd->wtop;
1075 int saveleft = wnd->wleft;
1076 DfClearVisible(wnd);
1077 Backward(wnd);
1078 while (isWhite(*DfCurrChar)) {
1079 if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
1080 break;
1081 Backward(wnd);
1082 }
1083 while (wnd->CurrCol != 0 && !isWhite(*DfCurrChar))
1084 Backward(wnd);
1085 if (isWhite(*DfCurrChar))
1086 Forward(wnd);
1087 DfSetVisible(wnd);
1088 if (wnd->wleft != saveleft)
1089 if (wnd->CurrCol >= saveleft)
1090 if (wnd->CurrCol - saveleft < DfClientWidth(wnd))
1091 wnd->wleft = saveleft;
1092 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, DfWndCol, wnd->WndRow);
1093 if (wnd->wtop != savetop || wnd->wleft != saveleft)
1094 DfSendMessage(wnd, DFM_PAINT, 0, 0);
1095 }
1096 /* ----- modify text pointers from a specified position
1097 by a specified plus or minus amount ----- */
1098 static void ModTextPointers(DFWINDOW wnd, int lineno, int var)
1099 {
1100 while (lineno < wnd->wlines)
1101 *((wnd->TextPointers) + lineno++) += var;
1102 }
1103 /* ----- set anchor point for marking text block ----- */
1104 static void SetAnchor(DFWINDOW wnd, int mx, int my)
1105 {
1106 DfClearTextBlock(wnd);
1107 /* ------ set the anchor ------ */
1108 wnd->BlkBegLine = wnd->BlkEndLine = my;
1109 wnd->BlkBegCol = wnd->BlkEndCol = mx;
1110 DfSendMessage(wnd, DFM_PAINT, 0, 0);
1111 }
1112
1113 /* EOF */