1 /*
2 * WINDOW.C
3 *
4 * Written by John Dennis and released to the public domain on 10-Jul-94.
5 *
6 * This module contains routines that maintain text windows on the
7 * screen. Output routines are integrated in relation to the window
8 * coordinates on the screen. All coordinates have a 0 based origin!
9 * Please note this!
10 *
11 * This is the second level of abstraction from the physical device; it
12 * should not be necessary to modify this module when porting to other
13 * operating systems/devices.
14 *
15 * History:
16 *
17 * 10-Nov-91 JD Started.
18 * 25-Jul-92 JD Whole package (of which this is a module) was finished
19 * to a useable degree.
20 * 13-Aug-92 JD Functions added during the Msged port to this system.
21 * Should increase the packages' useability.
22 */
23
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <time.h>
28 #include "specch.h"
29 #include "memextra.h"
30 #include "keys.h"
31 #include "winsys.h"
32 #include "mcompile.h"
33
34 #define XMOD(w) ((w->flags & INSBDR) ? 3 : ((w->flags & NBDR) ? 0 : 1))
35 #define YMOD(w) ((w->flags & INSBDR) ? 2 : ((w->flags & NBDR) ? 0 : 1))
36
37 /* double and single border chars */
38 /*
39 unsigned char Dbdr[6] = {SC1, SC2, SC3, SC4, SC5, SC6};
40 unsigned char Sbdr[6] = {SC7, SC8, SC9, SC10, SC11, SC12};
41 */
42
43 #define Dbdr(x) SC(((x)+1))
44 #define Sbdr(x) SC(((x)+7))
45 #define Bdr(y,x) (((y) != SBDR) ? Dbdr((x)) : Sbdr((x)))
46
47
48 int wnd_bs_127 = 0; /* Is ASCII 127 backspace on ANSI console ? */
49 int wnd_suppress_shadows = 0; /* do not suppress window shadows */
50 #ifdef UNIX
51 int wnd_force_monochrome = 1;
52 #else
53 int wnd_force_monochrome = 0; /* do not enforce monochrome output */
54 #endif
55
56 unsigned long wndid = 20; /* unique window ID */
57 WND *CW = NULL; /* current window */
58
59 static void WDrwBox(int x1, int y1, int x2, int y2, int Bdrt, int Battr, int ins);
60
61 static char line[255];
62
CheckMousePos(int x1,int y1,int x2,int y2)63 int CheckMousePos(int x1, int y1, int x2, int y2)
64 {
65 int x, y;
66 GetMouInfo(&x, &y);
67 if (x >= x1 && x <= x2)
68 {
69 if (y >= y1 && y <= y2)
70 {
71 return 1;
72 }
73 }
74 return 0;
75 }
76
77 /*
78 * WndOpen; Creates and opens a window returning the handle to
79 * the user, using 0 based coordinates on the screen.
80 */
81
WndOpen(int x1,int y1,int x2,int y2,int Bdr,int BAttr,int Attr)82 WND *WndOpen(int x1, int y1, int x2, int y2, int Bdr, int BAttr, int Attr)
83 {
84 WND *w;
85 unsigned long ch;
86 int i, k = 0;
87 static int first_win = 1;
88
89 w = xmalloc(sizeof *w);
90
91 if (w == NULL)
92 {
93 return NULL;
94 }
95
96 if (wnd_suppress_shadows)
97 {
98 Bdr = Bdr & (~SHADOW);
99 }
100
101 /* sanity checks*/
102 if (x1 < 0) x1 = 0;
103 if (y1 < 0) y1 = 0;
104 if (x2 < x1) x2 = x1;
105 if (y2 < y1) y2 = y1;
106
107 w->wid = ++wndid;
108 w->x1 = (unsigned char)x1;
109 w->x2 = (unsigned char)x2;
110 w->y1 = (unsigned char)y1;
111 w->y2 = (unsigned char)y2;
112 w->wattr = (unsigned char)Attr;
113 w->battr = (unsigned char)BAttr;
114 w->flags = (unsigned char)Bdr;
115 w->title = NULL;
116
117 if (Bdr & SHADOW)
118 {
119 x2 += 2;
120 y2++;
121 }
122
123 MouseOFF();
124
125 /* get a copy of the background */
126
127 if ((!(Bdr & NOSAVE)) || (Bdr & SHADOW))
128 {
129 w->buffer = xmalloc(sizeof(unsigned long *) * ((y2 - y1) + 2));
130
131 if (!w->buffer)
132 {
133 return NULL;
134 }
135
136 for (i = y1; i <= y2; i++)
137 {
138 w->buffer[k] = xmalloc(sizeof(unsigned long) * ((x2 - x1) + 2));
139 if (!w->buffer[k])
140 {
141 return NULL;
142 }
143 TTReadStr(w->buffer[k], x2 - x1 + 1, i, x1);
144 k++;
145 }
146 }
147 else
148 {
149 w->buffer = NULL;
150 }
151
152 TTBeginOutput();
153
154 /* put out shadow */
155
156 if (Bdr & SHADOW)
157 {
158 k = 1;
159 for (i = y1 + 1; i <= y2; i++)
160 {
161 ch = (unsigned long)w->buffer[k][x2 - x1];
162 ch &= 0xFF00FFFFUL;
163 ch |= ((unsigned long)(DGREY | _BLACK) << 16);
164 TTWriteStr(&ch, 1, i, x2);
165 ch = (unsigned long)w->buffer[k][x2 - x1 - 1];
166 ch &= 0xFF00FFFFUL;
167 ch |= ((unsigned long)(DGREY | _BLACK) << 16);
168 TTWriteStr(&ch, 1, i, x2 - 1);
169 k++;
170 }
171 k = y2 - y1;
172 for (i = 2; i <= (x2 - x1); i++)
173 {
174 ch = (unsigned long)w->buffer[k][i];
175 ch &= 0xFF00FFFFUL;
176 ch |= ((unsigned long)(DGREY | _BLACK) << 16);
177 TTWriteStr(&ch, 1, y2, i + x1);
178 }
179 }
180 TTScolor(Attr);
181 if (!first_win)
182 {
183 TTClear(w->x1, w->y1, w->x2, w->y2);
184 }
185 else
186 {
187 first_win = 0;
188 }
189
190 if (!(Bdr & NBDR))
191 {
192 if (Bdr & SBDR)
193 {
194 WDrwBox(w->x1, w->y1, w->x2, w->y2, SBDR, BAttr, Bdr & INSBDR ? 1 : 0);
195 }
196 else
197 {
198 WDrwBox(w->x1, w->y1, w->x2, w->y2, DBDR, BAttr, Bdr & INSBDR ? 1 : 0);
199 }
200 }
201
202 MouseON();
203
204 TTEndOutput();
205
206 CW = w;
207
208 return CW;
209 }
210
211 /*
212 * WndPopUp; Opens up a window of the passed size in the middle of the
213 * screen.
214 */
215
WndPopUp(int wid,int dep,int Bdr,int BAttr,int NAttr)216 WND *WndPopUp(int wid, int dep, int Bdr, int BAttr, int NAttr)
217 {
218 int x1, x2, y1, y2;
219 x1 = max((term.NCol / 2) - (wid / 2) - 1, 0);
220 y1 = max((term.NRow / 2) - (dep / 2) - 1, 0);
221 x2 = min(x1 + wid, term.NCol - 1);
222 y2 = min(y1 + dep, term.NRow - 1);
223 return WndOpen(x1, y1, x2, y2, Bdr, BAttr, NAttr);
224 }
225
226 /*
227 * WndClose; Closes the passed window and restores the screen
228 * behind it.
229 *
230 * Caveats: Since no track is kept of the windows on the screen, it
231 * is the caller's responsibility to ensure that windows are closed
232 * in the right order.
233 */
234
WndClose(WND * w)235 void WndClose(WND * w)
236 {
237 WND *wnd;
238 int i, k = 0;
239 int x2, y2;
240
241 /* restore screen buffer */
242
243 if (w == NULL)
244 {
245 wnd = CW;
246 }
247 else
248 {
249 wnd = w;
250 }
251
252 if (wnd == NULL)
253 {
254 return;
255 }
256
257 x2 = wnd->x2;
258 y2 = wnd->y2;
259
260 if (wnd->flags & SHADOW)
261 {
262 x2 += 2;
263 y2++;
264 }
265
266 TTBeginOutput();
267 MouseOFF();
268
269 if (!(wnd->flags & NOSAVE))
270 {
271 for (i = wnd->y1; i <= y2; i++)
272 {
273 TTWriteStr(wnd->buffer[k], x2 - wnd->x1 + 1, i, wnd->x1);
274 xfree(wnd->buffer[k++]);
275 }
276 xfree(wnd->buffer);
277 }
278 xfree(wnd);
279 MouseON();
280 TTEndOutput();
281 }
282
283 /*
284 * WndDrwBox; Draws a box at the specified position. Internal function.
285 */
286
WDrwBox(int x1,int y1,int x2,int y2,int Bdrt,int Battr,int ins)287 static void WDrwBox(int x1, int y1, int x2, int y2, int Bdrt, int Battr, int ins)
288 {
289 unsigned int i, width;
290 unsigned long cell, *pcell, *p;
291 int xmod = ins ? 2 : 0;
292 int ymod = ins ? 1 : 0;
293
294 TTBeginOutput();
295 MouseOFF();
296
297 /* write corner chars */
298
299 cell = MAKECELL(Bdr(Bdrt,2), Battr | F_ALTERNATE);
300 TTWriteStr(&cell, 1, y1 + ymod, x1 + xmod);
301
302 cell = MAKECELL(Bdr(Bdrt,3), Battr | F_ALTERNATE);
303 TTWriteStr(&cell, 1, y1 + ymod, x2 - xmod);
304
305 cell = MAKECELL(Bdr(Bdrt,4), Battr | F_ALTERNATE);
306 TTWriteStr(&cell, 1, y2 - ymod, x1 + xmod);
307
308 cell = MAKECELL(Bdr(Bdrt,5), Battr | F_ALTERNATE);
309 TTWriteStr(&cell, 1, y2 - ymod, x2 - xmod);
310
311
312 /* write top & bottom horiziontal border chars */
313
314 width = (x2 - xmod) - (x1 + 1 + xmod);
315 pcell = xmalloc(width * sizeof *pcell);
316 p = pcell;
317 for (i = 0; i < width; i++)
318 {
319 *p = MAKECELL(Bdr(Bdrt,1), Battr | F_ALTERNATE);
320 p++;
321 }
322 TTWriteStr(pcell, width, y1 + ymod, x1 + 1 + xmod);
323 TTWriteStr(pcell, width, y2 - ymod, x1 + 1 + xmod);
324 xfree(pcell);
325
326 /* write left & right vertical border chars */
327
328 cell = MAKECELL(Bdr(Bdrt,0), Battr | F_ALTERNATE);
329 for (i = y1 + 1 + ymod; i < y2 - ymod; i++)
330 {
331 TTWriteStr(&cell, 1, i, x1 + xmod);
332 TTWriteStr(&cell, 1, i, x2 - xmod);
333 }
334
335 TTEndOutput();
336 MouseON();
337 }
338
339 /*
340 * WndBox; Draws a box in the window.
341 */
342
WndBox(int x1,int y1,int x2,int y2,int Attr,int type)343 void WndBox(int x1, int y1, int x2, int y2, int Attr, int type)
344 {
345 int xmod, ymod;
346 int Bdrt = (type & DBDR) ? DBDR : SBDR;
347
348 if (CW == NULL)
349 {
350 return;
351 }
352
353 ymod = YMOD(CW);
354 xmod = XMOD(CW);
355
356 if (y1 < 0 || x1 < 0 || CW->x1 + x2 + xmod > CW->x2 || CW->y1 + y2 + ymod > CW->y2)
357 {
358 return;
359 }
360
361 WDrwBox(x1 + CW->x1 + xmod, y1 + CW->y1 + ymod, x2 + CW->x1 + xmod, y2 + CW->y1 + ymod, Bdrt, Attr, 0);
362 }
363
364 /*
365 * WndGetRel; Converts absolute coordinates to coordinates relative
366 * to the current window.
367 */
368
WndGetRel(int x,int y,int * wx,int * wy)369 void WndGetRel(int x, int y, int *wx, int *wy)
370 {
371 int xmod, ymod;
372
373 if (CW == NULL)
374 {
375 return;
376 }
377
378 ymod = YMOD(CW);
379 xmod = XMOD(CW);
380
381 *wx = x - (CW->x1 + xmod);
382 *wy = y - (CW->y1 + ymod);
383 }
384
WndWidth(void)385 int WndWidth(void)
386 {
387 if (CW == NULL)
388 {
389 return 0;
390 }
391 return CW->x2 - CW->x1 - (XMOD(CW) * 2);
392 }
393
394 /*
395 * WndTitle; Writes a title to centre of the *current* window,
396 * clearing whatever was there initially.
397 *
398 * Caveats: Doesn't check to see if there is a border, only for the
399 * type of border.
400 */
401
WndTitle(const char * title,int Attr)402 void WndTitle(const char *title, int Attr)
403 {
404 int cntr;
405 int pos, i, len;
406 unsigned long ch;
407 int ymod;
408 int Bdrt = SBDR;
409 int m = 0;
410
411 if (CW == NULL)
412 {
413 return;
414 }
415
416 if (title == NULL)
417 {
418 title = "<-- null pointer passed -->";
419 }
420 cntr = (CW->x2 - CW->x1 + 1) / 2;
421 len = strlen(title);
422
423 /* 'cause were writing on the border */
424 if (CW->flags & INSBDR)
425 {
426 ymod = 1;
427 }
428 else
429 {
430 ymod = 0;
431 }
432
433 if (CheckMousePos(CW->x1, CW->y1, CW->x2, CW->y2))
434 {
435 m = 1;
436 MouseOFF();
437 }
438
439 TTBeginOutput();
440
441 if (CW->title)
442 {
443 if (!(CW->flags & NBDR))
444 {
445 if (CW->flags & SBDR)
446 {
447 Bdrt = SBDR;
448 }
449 else
450 {
451 Bdrt = DBDR;
452 }
453 }
454
455 ch = MAKECELL(Bdr(Bdrt,1), CW->battr | F_ALTERNATE);
456 for (i = CW->x1 + 1; i < CW->x2; i++)
457 {
458 TTWriteStr(&ch, 1, CW->y1 + ymod, i);
459 }
460
461 xfree(CW->title);
462 }
463
464 pos = (cntr - (len / 2)) + CW->x1;
465 CW->title = xstrdup(title);
466
467 TTScolor(Attr);
468 TTStrWr((unsigned char *)title, CW->y1 + ymod, pos, -1);
469
470 if (m)
471 {
472 MouseON();
473 }
474
475 TTEndOutput();
476 }
477
478 /*
479 * WndWriteStr; Writes a string to the (current) window, using a
480 * zero-based origin.
481 *
482 * Caveats: If string would write past end of line, it won't write
483 * the string.
484 */
485
WndWriteStr(int x,int y,int Attr,char * Str)486 void WndWriteStr(int x, int y, int Attr, char *Str)
487 {
488 int row, col, len;
489 int m = 0;
490 char *PrintStr = Str;
491
492 if (Str == NULL)
493 {
494 return;
495 }
496
497 len = strlen(Str);
498
499
500 if (CW == NULL)
501 {
502 return;
503 }
504
505 /* row and col must be zero-based */
506 row = CW->y1 + y;
507 col = CW->x1 + x;
508
509 if (x < 0 || y < 0)
510 {
511 return;
512 }
513
514 if (!(CW->flags & NBDR))
515 {
516 /* check end-of-window overstep */
517 row += YMOD(CW);
518 col += XMOD(CW);
519 if (row >= CW->y2 || col > CW->x2 - XMOD(CW))
520 {
521 return;
522 }
523 }
524 else
525 {
526 if (row > CW->y2 || col > CW->x2)
527 {
528 return;
529 }
530 }
531
532 if (CheckMousePos(col, row, col + len - 1, row))
533 {
534 m = 1;
535 MouseOFF();
536 }
537
538 if ((col + len - 1) > CW->x2 - XMOD(CW))
539 {
540 len = ((CW->x2 - XMOD(CW)) - col + 1);
541 PrintStr = xmalloc(len + 1);
542 memcpy(PrintStr, Str, len);
543 PrintStr[len] = '\0';
544 }
545
546 TTBeginOutput();
547
548 TTScolor(Attr);
549 TTStrWr((unsigned char *)PrintStr, row, col, len);
550
551 if (PrintStr != Str)
552 {
553 xfree(PrintStr);
554 }
555
556 TTEndOutput();
557
558 if (m)
559 {
560 MouseON();
561 }
562 }
563
564 /*
565 * WndPutsCen; Puts a string in the center of the window at the passed
566 * line.
567 */
568
WndPutsCen(int y,int attr,char * str)569 void WndPutsCen(int y, int attr, char *str)
570 {
571 int cntr;
572 int col, len;
573 int mod;
574
575 if (CW == NULL)
576 {
577 return;
578 }
579
580 if (str == NULL)
581 {
582 return;
583 }
584
585 if (y < 0)
586 {
587 return;
588 }
589
590 cntr = (CW->x2 - CW->x1 + 1) / 2;
591 mod = XMOD(CW);
592 len = strlen(str);
593
594
595 if (len > WndWidth())
596 {
597 col = 0;
598 }
599 else
600 {
601 col = cntr - (len / 2) - mod;
602 }
603 WndWriteStr(col, y, attr, str);
604 }
605
606 /*
607 * WndPrintf; Operates the same as printf(), except it does it to the
608 * current window, using the passed parameters.
609 */
610
WndPrintf(int x,int y,int attr,char * str,...)611 int WndPrintf(int x, int y, int attr, char *str, ...)
612 {
613 int rc;
614 va_list params;
615 va_start(params, str);
616 rc = vsprintf(line, str, params);
617 WndWriteStr(x, y, attr, line);
618 return rc;
619 }
620
621 /*
622 * WndPutsn; Puts len of str onto the current window.
623 */
624
WndPutsn(int x,int y,int len,int attr,char * str)625 void WndPutsn(int x, int y, int len, int attr, char *str)
626 {
627 char *s = str, *c = line;
628 int i = 0;
629
630 if (x < 0 || y < 0 || len < 1)
631 {
632 return;
633 }
634 if (len > 254)
635 {
636 len = 254;
637 }
638 if (s != NULL)
639 {
640 i = strlen(s);
641 if (i > len)
642 {
643 i = len;
644 }
645 memcpy(c, s, i);
646 }
647 if (i < len)
648 {
649 memset(c + i, ' ', len - i);
650 }
651 c[len] = '\0';
652 WndWriteStr(x, y, attr, line);
653 }
654
655 /*
656 * WndScroll; Scrolls a window at the specified cooridiates using a
657 * zero-based origin.
658 *
659 */
660
WndScroll(int x1,int y1,int x2,int y2,int dir)661 void WndScroll(int x1, int y1, int x2, int y2, int dir)
662 {
663 int xmod, ymod;
664 int m = 0;
665
666 if (CW == NULL)
667 {
668 return;
669 }
670
671 if (x1 < 0) x1 = 0;
672 if (y1 < 0) y1 = 0;
673 if (x2 < x1 || y2 < y1) return;
674
675 xmod = XMOD(CW);
676 ymod = YMOD(CW);
677
678 if (CheckMousePos(CW->x1 + x1 + xmod, CW->y1 + y1 + ymod, CW->x2 + x2 + xmod, CW->y2 + y2 + ymod))
679 {
680 m = 1;
681 MouseOFF();
682 }
683 TTBeginOutput();
684 TTScolor(CW->wattr);
685 TTScroll(CW->x1 + x1 + xmod, CW->y1 + y1 + ymod, CW->x1 + x2 + xmod,
686 CW->y1 + y2 + ymod, 1, dir);
687 TTEndOutput();
688
689 if (m)
690 {
691 MouseON();
692 }
693 }
694
695 /*
696 * WndCurr; Makes the passed window the current window.
697 *
698 * Caveats: The windowing system doesn't keep track of the windows
699 * that exist - the caller must do that.
700 */
701
WndCurr(WND * hWnd)702 void WndCurr(WND * hWnd)
703 {
704 if (CW == hWnd || hWnd == NULL)
705 {
706 return;
707 }
708 CW = hWnd;
709 }
710
711 /*
712 * WndTop; Returns the current window recognized by the windowing system.
713 */
714
WndTop(void)715 WND *WndTop(void)
716 {
717 if (CW != NULL)
718 {
719 return CW;
720 }
721 else
722 {
723 return NULL;
724 }
725 }
726
727 /*
728 * WndPutc; Puts a char anywhere on the window, ignoring borders, etc.
729 * Puts it at the current cursor position (virtual or real).
730 *
731 * Caveats: The cursor may not even be on the window, but it doesn't
732 * care. :-)
733 */
734
WndPutc(int Ch,int attr)735 void WndPutc(int Ch, int attr)
736 {
737 if (CW == NULL)
738 {
739 return;
740 }
741 MouseOFF();
742 TTScolor(attr);
743 TTPutChr(Ch);
744 MouseON();
745 }
746
747 /*
748 * WndGotoXY; Goes to the passed coordinates, zero-based, starting
749 * from any borders on the window.
750 *
751 * Caveats: No checks for validity of arguments.
752 */
753
WndGotoXY(int x,int y)754 void WndGotoXY(int x, int y)
755 {
756 int xmod, ymod;
757
758 if (CW == NULL)
759 {
760 return;
761 }
762
763 xmod = XMOD(CW);
764 ymod = YMOD(CW);
765
766 TTgotoxy(CW->y1 + y + ymod, CW->x1 + x + xmod);
767 }
768
769 /*
770 * WndClear; Clears the passed coordinates with the passed attribute
771 * in the current window.
772 *
773 * Caveats: No checks for validity of arguments.
774 */
775
WndClear(int x1,int y1,int x2,int y2,int attr)776 void WndClear(int x1, int y1, int x2, int y2, int attr)
777 {
778 int xmod, ymod, m = 0;
779
780 if (CW == NULL)
781 {
782 return;
783 }
784
785 xmod = XMOD(CW);
786 ymod = YMOD(CW);
787
788 if (CheckMousePos(CW->x1 + x1 + xmod, CW->y1 + y1 + ymod, CW->x2 + x2 + xmod, CW->y2 + y2 + ymod))
789 {
790 m = 1;
791 MouseOFF();
792 }
793 TTScolor(attr);
794 TTClear(CW->x1 + x1 + xmod, CW->y1 + y1 + ymod, CW->x1 + x2 + xmod, CW->y1 + y2 + ymod);
795 if (m)
796 {
797 MouseON();
798 }
799 }
800
801 /*
802 * WndClearLine; Clears the passed line in the current window.
803 */
804
WndClearLine(int y,int Att)805 void WndClearLine(int y, int Att)
806 {
807 if (CW == NULL)
808 {
809 return;
810 }
811 WndClear(0, y, CW->x2 - CW->x1 - (XMOD(CW) * 2), y, Att);
812 }
813
814 /*
815 * WndFillField; Fills in an edit-field region with char.
816 */
817
WndFillField(int x,int y,int len,unsigned char ch,int Attr)818 void WndFillField(int x, int y, int len, unsigned char ch, int Attr)
819 {
820 if (len > sizeof(line) - 1)
821 {
822 len = sizeof(line) - 1;
823 }
824 memset(line, ch, len);
825 *(line + len - 1) = '\0';
826 WndWriteStr(x, y, Attr, line);
827 }
828
829 /*
830 * WndGetLine; Gets a string from the user on the current window at
831 * the passed coordinates. Passes mouse events not on itself back to
832 * the caller via the extra parameters.
833 */
834
WndGetLine(int x,int y,int len,char * buf,int Attr,int * pos,int nokeys,int fil,int disp,EVT * ev)835 int WndGetLine(int x, int y, int len, char *buf, int Attr, int *pos, int nokeys, int fil, int disp, EVT * ev)
836 {
837 EVT event;
838 int done = 0;
839 int row = y, col = x;
840 int xmod, ymod, i;
841 unsigned int ch = 0;
842 unsigned char fill;
843
844 fill= (fil) ? SC13 : (unsigned char) ' ';
845
846 if (CW == NULL)
847 {
848 return 0;
849 }
850
851 if (x < 0) x = 0;
852 if (y < 0) y = 0;
853
854 if (disp)
855 {
856 TTBeginOutput();
857 WndFillField(col, row, len + 1, fill, Attr | F_ALTERNATE);
858 WndPutsn(col, row, len, Attr, buf);
859 TTEndOutput();
860 }
861
862 xmod = XMOD(CW);
863 ymod = YMOD(CW);
864
865 i = *pos;
866
867 TTCurSet(1);
868
869 while (!done)
870 {
871 WndGotoXY(i + col, row);
872 ch = MnuGetMsg(&event, 0);
873 switch (event.msgtype)
874 {
875 case WND_WM_MOUSE:
876 case WND_WM_COMMAND:
877 {
878 int p1 = event.x, p2 = event.y;
879 if (p1 < CW->x1 + xmod + x || p1 > CW->x1 + xmod + x + len - 1 || p2 != CW->y1 + ymod + y)
880 {
881 done = TRUE;
882 break;
883 }
884 }
885 break;
886
887 case WND_WM_CHAR:
888 switch (ch)
889 {
890 case Key_Up:
891 case Key_Dwn:
892 done = TRUE;
893 break;
894
895 case Key_Lft:
896 if (i > 0)
897 {
898 i--;
899 }
900 break;
901
902 case Key_Rgt:
903 if (i < strlen(buf))
904 {
905 i++;
906 }
907 break;
908
909 case Key_A_X:
910 memset(buf, 0, len);
911 i = 0;
912 break;
913
914 case Key_BS:
915 if (i > 0)
916 {
917 TTBeginOutput();
918 if (i < strlen(buf))
919 {
920 memmove(buf + i - 1, buf + i, strlen(buf + i) + 1);
921 i--;
922 WndWriteStr(col + i, row, Attr, buf + i);
923 WndPrintf(col + strlen(buf), row, Attr | F_ALTERNATE,
924 "%c", fill);
925 }
926 else
927 {
928 i--;
929 *(buf + i) = '\0';
930 WndGotoXY(i + col, row);
931 WndPutc(fill, Attr | F_ALTERNATE);
932 }
933 TTEndOutput();
934 }
935 break;
936
937 case Key_Del:
938 if (i < strlen(buf))
939 {
940 TTBeginOutput();
941 memmove(buf + i, buf + i + 1, strlen(buf + i + 1) + 1);
942 WndWriteStr(col + i, row, Attr, buf + i);
943 WndPrintf(col + strlen(buf), row, Attr | F_ALTERNATE,
944 "%c", fill);
945 TTEndOutput();
946 }
947 break;
948
949 case Key_End:
950 i = strlen(buf);
951 break;
952
953 case Key_Home:
954 i = 0;
955 break;
956
957 case Key_Ent:
958 done = 1;
959 break;
960
961 case Key_Esc:
962 done = 2;
963 break;
964
965 default:
966 if (ch > 0 && ch < 256 && i < len && strlen(buf) < len)
967 {
968 TTBeginOutput();
969 if (nokeys)
970 {
971 strcpy(buf, "");
972 WndFillField(col, row, len + 1, fill,
973 Attr | F_ALTERNATE);
974 i = 0;
975 WndGotoXY(i + col, row);
976 }
977 if (i < strlen(buf))
978 {
979 memmove(buf + i + 1, buf + i, strlen(buf + i) + 1);
980 *(buf + i) = (char)ch;
981 WndWriteStr(col + i, row, Attr, buf + i);
982 i++;
983 }
984 else
985 {
986 *(buf + i) = (char)ch;
987 *(buf + i + 1) = '\0';
988 WndPutc((unsigned char)ch, Attr);
989 i++;
990 }
991 TTEndOutput();
992 }
993 else
994 {
995 done = 1;
996 }
997 break;
998 }
999 break;
1000 }
1001 nokeys = 0;
1002 }
1003 TTCurSet(0);
1004
1005 if (ev != NULL)
1006 {
1007 *ev = event;
1008 }
1009
1010 *pos = i;
1011 return (int)ch;
1012 }
1013