1: /*
2: * $Id: service.c,v 1.14 2026/01/07 19:51:33 snw Exp $
3: * terminal and sequential I/O handling,
4: * file and global locking
5: *
6: *
7: * Author: Serena Willis <snw@coherent-logic.com>
8: * Copyright (C) 1998 MUG Deutschland
9: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
10: *
11: *
12: * This file is part of FreeM.
13: *
14: * FreeM is free software: you can redistribute it and/or modify
15: * it under the terms of the GNU Affero Public License as published by
16: * the Free Software Foundation, either version 3 of the License, or
17: * (at your option) any later version.
18: *
19: * FreeM is distributed in the hope that it will be useful,
20: * but WITHOUT ANY WARRANTY; without even the implied warranty of
21: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22: * GNU Affero Public License for more details.
23: *
24: * You should have received a copy of the GNU Affero Public License
25: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
26: *
27: * $Log: service.c,v $
28: * Revision 1.14 2026/01/07 19:51:33 snw
29: * Fix segfault in reverse $QUERY
30: *
31: * Revision 1.13 2025/04/09 19:52:02 snw
32: * Eliminate as many warnings as possible while building with -Wall
33: *
34: * Revision 1.12 2025/03/24 04:05:36 snw
35: * Replace crlf with frm_crlf to avoid symbol conflict with readline on OS/2
36: *
37: * Revision 1.11 2025/03/24 02:00:30 snw
38: * Work around some OS/2 incompatibilities in service.c
39: *
40: * Revision 1.10 2025/03/24 01:55:46 snw
41: * Work around some OS/2 incompatibilities in service.c
42: *
43: * Revision 1.9 2025/03/24 01:54:09 snw
44: * Work around some OS/2 incompatibilities in set_break and set_zbreak
45: *
46: * Revision 1.8 2025/03/24 01:52:30 snw
47: * Work around some OS/2 incompatibilities in set_break and set_zbreak
48: *
49: * Revision 1.7 2025/03/09 19:50:47 snw
50: * Second phase of REUSE compliance and header reformat
51: *
52: *
53: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
54: * SPDX-License-Identifier: AGPL-3.0-or-later
55: **/
56:
57: #include <errno.h>
58: #include <sys/types.h>
59:
60: #if !defined(__OpenBSD__) && !defined(__FreeBSD__)
61: # include <sys/timeb.h>
62: #endif
63:
64: #include <sys/ioctl.h>
65: #include <unistd.h>
66: #include <stdlib.h>
67:
68: #ifdef AMIGA68K
69: #include <sys/fcntl.h>
70: #endif
71:
72: #define MAXZAS NESTLEVLS
73: #include "mpsdef.h"
74: #include "shmmgr.h"
75:
76: #include <time.h>
77:
78: #ifdef USE_SYS_TIME_H
79: #include <sys/time.h>
80: #endif
81:
82: #include "events.h"
83:
84: long int tell ();
85: void ris (struct vtstyp *scr);
86:
87: #ifdef SCO
88: int scosgr (short att, short bwflag);
89: #endif
90:
91: /* system services */
92: #if !defined(__APPLE__) && !defined(__gnu_hurd__) && !defined(EMSCRIPTEN)
93: # if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__AMIGA)
94: # include <termios.h>
95: # if !defined(__AMIGA)
96: # define TCGETA TIOCGETA
97: # define TCSETA TIOCSETA
98: # endif
99: # define termio termios
100: # else
101: # if !defined(MSDOS) && !defined(__linux__)
102: # include <termio.h>
103: # else
104: # include <termios.h>
105: # define termio termios
106: # endif
107: # endif
108: #else
109: # include <termios.h>
110: #endif
111:
112:
113: #include <fcntl.h>
114:
115: /* search 'string' for occurence of 'pattrn'
116: * return: 0='not found' nbr='pattern begins at nbr' */
117: long int find (char *string, char *pattrn)
118: {
119: short i;
120: short j;
121: register int k;
122: register int l;
123:
124: i = 0;
125:
126: while (pattrn[i] != EOL) i++; /* $l of 2nd arg */
127:
128: if (i == 1) {
129:
130: l = pattrn[0];
131: k = 0;
132:
133: while (string[k] != EOL) {
134:
135: if (string[k++] == l) return k;
136:
137: }
138:
139: return 0L;
140:
141: }
142:
143: j = stlen (string);
144:
145: for (k = 0; k < j; k++) {
146:
147: l = 0;
148:
149:
150: l10:
151:
152: if (string[k + l] != pattrn[l]) continue;
153: if (++l < i) goto l10;
154:
155: return ++k;
156:
157: }
158:
159: return 0L;
160: } /* end of find() */
161:
162: /* called by exclusive KILL to search 'exceptions' for occurence of 'variable'
163: * return: 1='not found, can be killed' 0='cannot be killed' */
164: short int kill_ok (char *exceptions, char *variable)
165: {
166: short i;
167: short j;
168: register int k;
169: register int l;
170:
171: j = stlen (exceptions);
172: i = stlen (variable);
173:
174: for (k = 0; k < j; k++) {
175:
176: for (l = 0; l < i; l++) {
177:
178: if (exceptions[k + l] != variable[l]) {
179:
180: if (exceptions[k + l] == SP && variable[l] == DELIM) return FALSE;
181:
182: goto outerspace;
183:
184: }
185:
186: }
187:
188: return FALSE;
189:
190:
191: outerspace:; /* the semicolon apparently needs to be here in this case. */
192: /* break time. */
193:
194: }
195:
196: return TRUE;
197: } /* end of kill_ok */
198:
199: /* write this format */
200: void write_f (char *intext)
201: {
202: char outtext[256]; /* output string */
203: short l;
204: int i;
205: char final;
206: int csi;
207:
208: csi = FALSE;
209: l = stlen (intext);
210:
211: if (l < 2) return; /* not recognized */
212:
213: for (i = 0; i < l; i++) {
214:
215: if (intext[i] == DELIM) break;
216:
217: }
218:
219:
220: intext[i] = EOL;
221:
222: /* CUB - Cursor Backward */
223: if (!stcmp (intext, "CUB\201")) {
224:
225: csi = TRUE;
226: final = 'D';
227:
228: goto end;
229:
230: }
231:
232: /* CUD - Cursor Down */
233: if (!stcmp (intext, "CUD\201")) {
234:
235: csi = TRUE;
236: final = 'B';
237:
238: goto end;
239:
240: }
241:
242: /* CUF - Cursor Forward */
243: if (!stcmp (intext, "CUF\201")) {
244:
245: csi = TRUE;
246: final = 'C';
247:
248: goto end;
249:
250: }
251:
252: /* CUP - Cursor Position */
253: /* HVP - Horizontal and vertical Position */
254: if (!stcmp (intext, "CUP\201") || !stcmp (intext, "HVP\201")) {
255:
256: csi = TRUE;
257: final = 'H';
258:
259: goto end;
260:
261: }
262:
263: /* CUU - Cursor Up */
264: if (!stcmp (intext, "CUU\201")) {
265:
266: csi = TRUE;
267: final = 'A';
268:
269: goto end;
270:
271: }
272:
273: /* DCH - Delete Character */
274: if (!stcmp (intext, "DCH\201")) {
275:
276: csi = TRUE;
277: final = 'P';
278:
279: goto end;
280:
281: }
282:
283: /* ICH - Insert Character */
284: if (!stcmp (intext, "ICH\201")) {
285:
286: csi = TRUE;
287: final = '@';
288:
289: goto end;
290:
291: }
292:
293: /* DL - Delete Line */
294: if (!stcmp (intext, "DL\201")) {
295:
296: csi = TRUE;
297: final = 'M';
298:
299: goto end;
300:
301: }
302:
303: /* IL - Insert Line */
304: if (!stcmp (intext, "IL\201")) {
305:
306: csi = TRUE;
307: final = 'L';
308:
309: goto end;
310:
311: }
312:
313: /* SU - Scroll Up = pan down */
314: if (!stcmp (intext, "SU\201")) {
315:
316: csi = TRUE;
317: final = 'S';
318:
319: goto end;
320:
321: }
322:
323: /* SD - Scroll Down = pan up */
324: if (!stcmp (intext, "SD\201")) {
325:
326: csi = TRUE;
327: final = 'T';
328:
329: goto end;
330:
331: }
332:
333: /* DA - Device Attributes */
334: if (!stcmp (intext, "DA\201")) {
335:
336: csi = TRUE;
337: final = 'c';
338:
339: goto end;
340:
341: }
342:
343: /* DSR - Device Status Report */
344: if (!stcmp (intext, "DSR\201")) {
345:
346: csi = TRUE;
347: final = 'n';
348:
349: goto end;
350:
351: }
352:
353: /* ED - Erase Display */
354: if (!stcmp (intext, "ED\201")) {
355:
356: csi = TRUE;
357: final = 'J';
358:
359: goto end;
360:
361: }
362:
363: /* EL - Erase Line */
364: if (!stcmp (intext, "EL\201")) {
365:
366: csi = TRUE;
367: final = 'K';
368:
369: goto end;
370:
371: }
372:
373: /* ECH - Erase Character */
374: if (!stcmp (intext, "ECH\201")) {
375:
376: csi = TRUE;
377: final = 'X';
378:
379: goto end;
380:
381: }
382:
383: /* HTS - Horizontal Tabulation Set */
384: if (!stcmp (intext, "HTS\201")) {
385:
386: final = 'H';
387:
388: goto end;
389:
390: }
391:
392: /* IND - Index */
393: if (!stcmp (intext, "IND\201")) {
394:
395: final = 'D';
396:
397: goto end;
398:
399: }
400:
401: /* NEL - NExt Line */
402: if (!stcmp (intext, "NEL\201")) {
403:
404: final = 'E';
405:
406: goto end;
407:
408: }
409:
410: if (!stcmp (intext, "SSA\201")) {
411:
412: final = 'F';
413:
414: goto end;
415:
416: }
417:
418: if (!stcmp (intext, "ESA\201")) {
419:
420: final = 'G';
421:
422: goto end;
423:
424: }
425:
426: if (!stcmp (intext, "HTJ\201")) {
427:
428: final = 'I';
429:
430: goto end;
431:
432: }
433:
434: if (!stcmp (intext, "VTS\201")) {
435:
436: final = 'J';
437:
438: goto end;
439:
440: }
441:
442: if (!stcmp (intext, "PLD\201")) {
443:
444: final = 'K';
445:
446: goto end;
447:
448: }
449:
450: if (!stcmp (intext, "PLU\201")) {
451:
452: final = 'L';
453:
454: goto end;
455:
456: }
457:
458: /* RI - Reverse Index */
459: if (!stcmp (intext, "RI\201")) {
460:
461: final = 'M';
462:
463: goto end;
464:
465: }
466:
467: /* SS2 - Single Shift G2 */
468: if (!stcmp (intext, "SS2\201")) {
469:
470: final = 'N';
471:
472: goto end;
473:
474: }
475:
476: /* SS3 - Single Shift G3 */
477: if (!stcmp (intext, "SS3\201")) {
478:
479: final = 'O';
480:
481: goto end;
482:
483: }
484:
485: /* DCS - Device Control String introducer */
486: if (!stcmp (intext, "DCS\201")) {
487:
488: final = 'P';
489:
490: goto end;
491:
492: }
493:
494: if (!stcmp (intext, "PU1\201")) {
495:
496: final = 'Q';
497:
498: goto end;
499:
500: }
501:
502: if (!stcmp (intext, "PU2\201")) {
503:
504: final = 'R';
505:
506: goto end;
507:
508: }
509:
510: if (!stcmp (intext, "STS\201")) {
511:
512: final = 'S';
513:
514: goto end;
515:
516: }
517:
518: if (!stcmp (intext, "CCH\201")) {
519:
520: final = 'T';
521:
522: goto end;
523:
524: }
525:
526: if (!stcmp (intext, "MW\201")) {
527:
528: final = 'U';
529:
530: goto end;
531:
532: }
533:
534: if (!stcmp (intext, "SPA\201")) {
535:
536: final = 'V';
537:
538: goto end;
539:
540: }
541:
542: if (!stcmp (intext, "EPA\201")) {
543:
544: final = 'W';
545:
546: goto end;
547:
548: }
549:
550: /* CSI - Command String Introducer */
551: if (!stcmp (intext, "CSI\201")) {
552:
553: final = '[';
554:
555: goto end;
556:
557: }
558:
559: /* ST - device control String Terminator */
560: if (!stcmp (intext, "ST\201")) {
561:
562: final = '\\';
563:
564: goto end;
565:
566: }
567:
568: if (!stcmp (intext, "OSC\201")) {
569:
570: final = ']';
571:
572: goto end;
573:
574: }
575:
576: if (!stcmp (intext, "PM\201")) {
577:
578: final = '^';
579:
580: goto end;
581:
582: }
583:
584: if (!stcmp (intext, "APC\201")) {
585:
586: final = '_';
587:
588: goto end;
589:
590: }
591:
592: /* RIS - Reset to Initial State */
593: if (!stcmp (intext, "RIS\201")) {
594:
595: final = 'c';
596:
597: goto end;
598:
599: }
600:
601: /* RM - Reset Mode */
602: if (!stcmp (intext, "RM\201")) {
603:
604: csi = TRUE;
605: final = 'l';
606:
607: goto end;
608:
609: }
610:
611: /* SGR - Select Graphic Rendition */
612: if (!stcmp (intext, "SGR\201")) {
613:
614: csi = TRUE;
615: final = 'm';
616:
617: goto end;
618:
619: }
620:
621: /* SM - Set Mode */
622: if (!stcmp (intext, "SM\201")) {
623:
624: csi = TRUE;
625: final = 'h';
626:
627: goto end;
628:
629: }
630:
631: /* TBC - Tabulation Clear */
632: if (!stcmp (intext, "TBC\201")) {
633:
634: csi = TRUE;
635: final = 'g';
636:
637: goto end;
638:
639: }
640:
641: if (!stcmp (intext, "NUL\201")) {
642:
643: final = NUL;
644:
645: goto controls;
646:
647: }
648:
649: if (!stcmp (intext, "SOH\201")) {
650:
651: final = SOH;
652:
653: goto controls;
654:
655: }
656:
657: if (!stcmp (intext, "STX\201")) {
658:
659: final = STX;
660:
661: goto controls;
662:
663: }
664:
665: if (!stcmp (intext, "ETX\201")) {
666:
667: final = ETX;
668:
669: goto controls;
670:
671: }
672:
673: if (!stcmp (intext, "EOT\201")) {
674:
675: final = EOT;
676:
677: goto controls;
678:
679: }
680:
681: if (!stcmp (intext, "ENQ\201")) {
682:
683: final = ENQ;
684:
685: goto controls;
686:
687: }
688:
689: if (!stcmp (intext, "ACK\201")) {
690:
691: final = ACK;
692:
693: goto controls;
694:
695: }
696:
697: if (!stcmp (intext, "BEL\201")) {
698:
699: final = BEL;
700:
701: goto controls;
702:
703: }
704:
705: if (!stcmp (intext, "BS\201")) {
706:
707: final = BS;
708:
709: goto controls;
710:
711: }
712:
713: if (!stcmp (intext, "HT\201")) {
714:
715: final = TAB;
716:
717: goto controls;
718:
719: }
720:
721: if (!stcmp (intext, "LF\201")) {
722:
723: final = LF;
724:
725: goto controls;
726:
727: }
728:
729: if (!stcmp (intext, "VT\201")) {
730:
731: final = VT;
732:
733: goto controls;
734:
735: }
736:
737: if (!stcmp (intext, "FF\201")) {
738:
739: final = FF;
740:
741: goto controls;
742:
743: }
744:
745: if (!stcmp (intext, "CR\201")) {
746:
747: final = CR;
748:
749: goto controls;
750:
751: }
752:
753: if (!stcmp (intext, "SO\201")) {
754:
755: final = SO;
756:
757: goto controls;
758:
759: }
760:
761: if (!stcmp (intext, "SI\201")) {
762:
763: final = SI;
764:
765: goto controls;
766:
767: }
768:
769: if (!stcmp (intext, "DLE\201")) {
770:
771: final = DLE;
772:
773: goto controls;
774:
775: }
776:
777: if (!stcmp (intext, "DC1\201")) {
778:
779: final = DC1;
780:
781: goto controls;
782:
783: }
784:
785: if (!stcmp (intext, "DC2\201")) {
786:
787: final = DC2;
788:
789: goto controls;
790:
791: }
792:
793: if (!stcmp (intext, "DC3\201")) {
794:
795: final = DC3;
796:
797: goto controls;
798:
799: }
800:
801: if (!stcmp (intext, "DC4\201")) {
802:
803: final = DC4;
804:
805: goto controls;
806:
807: }
808:
809: if (!stcmp (intext, "NAK\201")) {
810:
811: final = NAK;
812:
813: goto controls;
814:
815: }
816:
817: if (!stcmp (intext, "SYN\201")) {
818:
819: final = SYN;
820:
821: goto controls;
822:
823: }
824:
825: if (!stcmp (intext, "ETB\201")) {
826:
827: final = ETB;
828:
829: goto controls;
830:
831: }
832:
833: if (!stcmp (intext, "CAN\201")) {
834:
835: final = CAN;
836:
837: goto controls;
838:
839: }
840:
841: if (!stcmp (intext, "EM\201")) {
842:
843: final = EM;
844:
845: goto controls;
846:
847: }
848:
849: if (!stcmp (intext, "SUB\201")) {
850:
851: final = SUB;
852:
853: goto controls;
854:
855: }
856:
857: if (!stcmp (intext, "ESC\201")) {
858:
859: final = ESC;
860:
861: goto controls;
862:
863: }
864:
865: if (!stcmp (intext, "FS\201")) {
866:
867: final = FS;
868:
869: goto controls;
870:
871: }
872:
873: if (!stcmp (intext, "GS\201")) {
874:
875: final = GS;
876:
877: goto controls;
878:
879: }
880:
881:
882: if (!stcmp (intext, "RS\201")) {
883:
884: final = RS;
885:
886: goto controls;
887:
888: }
889:
890: if (!stcmp (intext, "US\201")) {
891:
892: final = US;
893:
894: goto controls;
895:
896: }
897:
898: if (!stcmp (intext, "DEL\201")) {
899:
900: final = DEL;
901:
902: goto controls;
903:
904: }
905:
906: /* DECKPAM Keypad Application Mode */
907: if (!stcmp (intext, "DECKPAM\201")) {
908:
909: final = '=';
910:
911: goto end;
912:
913: }
914:
915: /* DECKPNM Keypad Numeric Mode */
916: if (!stcmp (intext, "DECKPNM\201")) {
917:
918: final = '>';
919:
920: goto end;
921:
922: }
923:
924: /* DECLL Load LEDs */
925: if (!stcmp (intext, "DECLL\201")) {
926:
927: csi = TRUE;
928: final = 'q';
929:
930: goto end;
931:
932: }
933:
934: /* DECRC Restore Cursor */
935: if (!stcmp (intext, "DECRC\201")) {
936:
937: final = '8';
938:
939: goto end;
940:
941: }
942:
943: /* DECSC Save Cursor */
944: if (!stcmp (intext, "DECSC\201")) {
945:
946: final = '7';
947:
948: goto end;
949:
950: }
951:
952: /* DECSTBM Set Top & Bottom Margins */
953: if (!stcmp (intext, "TBM\201") ||
954:
955: !stcmp (intext, "DECSTBM\201")) {
956:
957: csi = TRUE;
958: final = 'r';
959:
960: goto end;
961:
962: }
963:
964: /* ZAS Alternate Screen */
965: if (!stcmp (intext, "ZAS\201")) {
966:
967: csi = TRUE;
968: final = '~';
969:
970: goto end;
971:
972: }
973:
974: return; /* code not recognized */
975:
976: controls:
977: outtext[0] = final;
978: outtext[1] = EOL;
979:
980: write_m (outtext);
981:
982: return;
983:
984: end:
985:
986: outtext[0] = ESC;
987:
988: if (csi++) outtext[1] = '[';
989:
990: while (++i < l) {
991:
992: if ((outtext[csi] = intext[i]) == DELIM) outtext[csi] = ';';
993:
994: csi++;
995:
996: }
997:
998: outtext[csi++] = final;
999: outtext[csi] = EOL;
1000:
1001: write_m (outtext);
1002:
1003: return;
1004: } /* end of write_f() */
1005:
1006: /* Output on HOME device */
1007: void writeHOME (char *text)
1008: {
1009:
1010: #if !defined(__OS2__)
1011: struct winsize terminal_window;
1012: #endif
1013: static char initflag = TRUE; /* initialisation flag */
1014: static char esc = 0; /* esc processing flag */
1015: static char dcs = 0; /* device control processing flag */
1016:
1017: static short args[ARGS_IN_ESC];
1018: static short argcnt = 0;
1019: static short noargs = TRUE;
1020: static char tmp[512];
1021: static short foreground = TRUE; /* foreground flag */
1022: static struct vtstyp *vts;
1023:
1024: /* external struct vtstyp *screen; active screen */
1025: static struct vtstyp *altscr; /* background screen */
1026: static struct vtstyp *zases[MAXZAS];
1027: static int zaslevel = 0;
1028:
1029: /* SGR and CSI=cF have ***different*** color codes */
1030: #ifdef COLOR
1031: static char coltrans[8] =
1032: {0, 4, 2, 6, 1, 5, 3, 7};
1033:
1034: #endif /* COLOR */
1035:
1036:
1037: short tmpx;
1038: register int ch;
1039: register int j;
1040: register int i;
1041: short k;
1042:
1043: /* we assume the HOME device is an ASCII machine according
1044: * to ANSI X3.4, X3.64 etc with 24 lines and 80 columns
1045: * so we look not only at controls as the MUMPS X11.1-1984
1046: * demands, but as well at esc sequences and device control
1047: * strings.
1048: *
1049: * In addition we assume, that the terminal cannot handle
1050: * tab_clear (CSI 3g) nor tab_set (ESC H) so these functions
1051: * are emulated here. For most terminals that might
1052: * not be neccesary. With 'PROC_TAB' we may switch versions.
1053: *
1054: * We support the VT100 on PC-"Terminals"
1055: * where there is no TBM so we have to emulate
1056: * scoll up /down with LF,RI and autowrap. SGR is somewhat
1057: * crazy on the PC and there is a lot of code to fix that.
1058: * The PC completely ignores SGRs it does not fully recognize.
1059: * E.g. SGR(7,4) will not work while SGR(4,7) at least inverts
1060: * the display.
1061: * CSI 10 p (invert INVERS at active position)
1062: * is being emulated too.
1063: * We emulate the terminal software so we have always an image
1064: * of the screen in memory. That enables us to have features like
1065: * CSI 0 ~ (private sequence: change screen)
1066: * CSI 1 ~ (private sequence: output to foreground screen)
1067: * CSI 2 ~ (private sequence: output to background screen)
1068: * CSI 3 ~ (private sequence: save foreground to background)
1069: * CSI 4 ~ (private sequence: screen restore)
1070: * and the 'hardcopy function'
1071: */
1072: if (initflag) {
1073:
1074: #if !defined(__OS2__)
1075: /* TODO: why are we casting to void here? */
1076: (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, &terminal_window);
1077:
1078: n_lines = terminal_window.ws_row;
1079: n_columns = terminal_window.ws_col;
1080: #else
1081: n_lines = 25;
1082: n_columns = 80;
1083: #endif
1084:
1085: screen = (struct vtstyp *) calloc (1, sizeof (struct vtstyp));
1086:
1087: ris (screen);
1088: altscr = (struct vtstyp *) calloc (1, sizeof (struct vtstyp));
1089:
1090: ris (altscr);
1091: initflag = FALSE;
1092:
1093: }
1094:
1095: opnfile[HOME] = stdout;
1096: tmpx = 0;
1097: j = 0;
1098:
1099: while ((ch = text[j++]) != EOL) {
1100:
1101: if (ch == NUL) continue;
1102:
1103: if (tmpx > 480) {
1104:
1105: tmp[tmpx] = EOL;
1106: tmpx = 0;
1107:
1108: if (foreground) m_output (tmp);
1109:
1110: }
1111:
1112:
1113: if (RightMargin && xpos[HOME] > RightMargin && esc == 0) {
1114:
1115: --j;
1116:
1117: tmp[tmpx++] = CR;
1118: xpos[HOME] = 0;
1119: ch = LF;
1120:
1121: }
1122:
1123: /* what in the name of good and holy is this macro abuse nonsense? */
1124:
1125: #ifdef PROC_TAB
1126: if (ch != TAB) tmp[tmpx++] = ch;
1127: #else
1128: tmp[tmpx++] = ch;
1129: #endif /* PROC_TAB */
1130:
1131:
1132: if (UNSIGN (ch) >= SP && ch != DEL) { /* printable characters */
1133:
1134: if (esc == 0) { /* no esc/dcs in progress; wrap-around */
1135:
1136: (*screen).screenx[(unsigned int) (*screen).sclines[ypos[HOME]]][xpos[HOME]] = ch;
1137:
1138: if ((*screen).savarg == FALSE) {
1139:
1140:
1141: #ifdef COLOR
1142: (*screen).screenc[(unsigned int) (*screen).sclines[ypos[HOME]]][xpos[HOME]] = (*screen).col;
1143: #endif /* COLOR */
1144:
1145: (*screen).screena[(unsigned int) (*screen).sclines[ypos[HOME]]][xpos[HOME]] = (*screen).att;
1146:
1147: }
1148:
1149: if (dcs == 0 && ++xpos[HOME] >= n_columns) {
1150:
1151: xpos[HOME] = 0;
1152:
1153: if ((*screen).rollflag) goto pLF;
1154:
1155: ypos[HOME] = (*screen).sc_lo;
1156:
1157: }
1158:
1159: continue;
1160:
1161: }
1162:
1163: if (esc == 1) { /* esc_sequence in progress */
1164:
1165: if (ch == '[') { /* CSI command string starts */
1166: esc = 2;
1167: continue;
1168: }
1169: else if (ch == 'H') { /* HTS set tab at $X */
1170: (*screen).tabs[xpos[HOME]] = 1;
1171: }
1172: else if (ch == 'M') { /* RI cursor up *//* upper margin of scroll area: scroll down */
1173:
1174: if (ypos[HOME] == (*screen).sc_up) {
1175:
1176: k = (*screen).sclines[(*screen).sc_lo];
1177:
1178: for (i = (*screen).sc_lo; i > (*screen).sc_up; i--) (*screen).sclines[i] = (*screen).sclines[i - 1];
1179:
1180: (*screen).sclines[(*screen).sc_up] = k;
1181:
1182: for (i = 0; i < n_columns; i++) {
1183:
1184: (*screen).screenx[k][i] = SP;
1185: (*screen).screena[k][i] = (*screen).att;
1186:
1187:
1188: #ifdef COLOR
1189: (*screen).screenc[k][i] = (*screen).col;
1190: #endif /* COLOR */
1191:
1192: }
1193:
1194: if (foreground) {
1195:
1196: tmp[tmpx - 2] = EOL;
1197: m_output (tmp);
1198:
1199: tmpx = 0;
1200: part_ref (screen, (*screen).sc_up, (*screen).sc_lo);
1201:
1202: }
1203: }
1204:
1205: if (ypos[HOME] != 0 && ypos[HOME] != (*screen).sc_up) ypos[HOME]--;
1206:
1207: tmp[tmpx++] = ESC;
1208: tmp[tmpx++] = '[';
1209:
1210: if (ypos[HOME] > 8) tmp[tmpx++] = (1 + ypos[HOME]) / 10 + '0';
1211:
1212: tmp[tmpx++] = (1 + ypos[HOME]) % 10 + '0';
1213:
1214: if (xpos[HOME] > 0) {
1215:
1216: tmp[tmpx++] = ';';
1217:
1218: if (xpos[HOME] > 8) tmp[tmpx++] = (1 + xpos[HOME]) / 10 + '0';
1219:
1220: tmp[tmpx++] = (1 + xpos[HOME]) % 10 + '0';
1221:
1222: }
1223:
1224: tmp[tmpx++] = 'H';
1225:
1226: }
1227: else if (ch == 'E') { /* NEL new line */
1228:
1229: /* RI */
1230:
1231: xpos[HOME] = 0;
1232: esc = 0;
1233:
1234: goto pLF;
1235:
1236: }
1237: else if (ch == 'Q') { /* DCS Device control string */
1238: dcs = 1;
1239: }
1240: else if (ch == '\\') { /* ST String terminator (DCS) */
1241: dcs = 0;
1242: }
1243: else if (ch == '7') { /* DEC CS Cursor Save */
1244:
1245: (*screen).csx[(*screen).cs] = xpos[HOME];
1246: (*screen).csy[(*screen).cs] = ypos[HOME];
1247:
1248: if (++((*screen).cs) >= CSLEN) (*screen).cs = CSLEN - 1;
1249:
1250: }
1251: else if (ch == '8') { /* DEC CRST Cursor Restore */
1252:
1253: if (--((*screen).cs) <= 0) (*screen).cs = 0;
1254:
1255: xpos[HOME] = (*screen).csx[(*screen).cs];
1256: ypos[HOME] = (*screen).csy[(*screen).cs];
1257:
1258: /* make sure cursor is at desired position */
1259: tmp[tmpx++] = ESC;
1260: tmp[tmpx++] = '[';
1261:
1262: if (ypos[HOME] > 8) tmp[tmpx++] = (1 + ypos[HOME]) / 10 + '0';
1263:
1264: tmp[tmpx++] = (1 + ypos[HOME]) % 10 + '0';
1265:
1266: if (xpos[HOME] > 0) {
1267:
1268: tmp[tmpx++] = ';';
1269:
1270: if (xpos[HOME] > 8) tmp[tmpx++] = (1 + xpos[HOME]) / 10 + '0';
1271:
1272: tmp[tmpx++] = (1 + xpos[HOME]) % 10 + '0';
1273:
1274: }
1275:
1276: tmp[tmpx++] = 'H';
1277:
1278: }
1279: else if (ch == 'c') { /* RIS Reset to initial state */
1280:
1281: esc = 0;
1282: dcs = 0;
1283: foreground = TRUE;
1284: xpos[HOME] = 0;
1285: ypos[HOME] = 0;
1286:
1287: ris (screen);
1288:
1289: }
1290: else if (ch == '(' || ch == ')') {
1291: continue;
1292: }
1293:
1294: esc = 0;
1295:
1296: continue;
1297:
1298: } /* end if (esc==1) */
1299:
1300: /* command string (esc [) in progress */
1301: /* numeric arguments ? */
1302: if (ch >= '0' && ch <= '9') {
1303:
1304: noargs = FALSE;
1305: args[argcnt] = args[argcnt] * 10 + ch - '0';
1306:
1307: continue;
1308:
1309: }
1310:
1311: if (ch == ';') {
1312:
1313: args[++argcnt] = 0;
1314:
1315: continue;
1316:
1317: }
1318:
1319: if (ch == '=') {
1320: esc = 3;
1321: continue;
1322: } /* color sequence */
1323:
1324: if (esc == 3) {
1325:
1326: esc = 0;
1327:
1328:
1329: #ifdef COLOR
1330: if (ch == 'F') { /* foreground color */
1331:
1332: (*screen).col = (((*screen).col & ~017) | (args[0] & 017));
1333:
1334: tmp[tmpx++] = ESC; /* reverse background */
1335: tmp[tmpx++] = '[';
1336: tmp[tmpx++] = '=';
1337:
1338: if (args[0] > 9) tmp[tmpx++] = '0' + (args[0] / 10);
1339:
1340: tmp[tmpx++] = '0' + (args[0] % 10);
1341: tmp[tmpx++] = 'I';
1342:
1343: continue;
1344:
1345: }
1346:
1347: if (ch == 'G') { /* background color */
1348:
1349: (*screen).col = (((*screen).col & 017) | (args[0] * 16));
1350:
1351: tmp[tmpx++] = ESC; /* reverse forground */
1352: tmp[tmpx++] = '[';
1353: tmp[tmpx++] = '=';
1354:
1355: if (args[0] > 9) tmp[tmpx++] = '0' + (args[0] / 10);
1356:
1357: tmp[tmpx++] = '0' + (args[0] % 10);
1358: tmp[tmpx++] = 'H';
1359:
1360: continue;
1361:
1362: }
1363: #endif /* COLOR */
1364:
1365:
1366: continue;
1367:
1368: } /* if (esc == 3) */
1369:
1370: if (ch < '@') continue;
1371:
1372: /* check final characters */
1373: if (ch == 'A') { /* CUU cursor up */
1374:
1375: do {
1376:
1377: if (--ypos[HOME] < 0) ypos[HOME] = 0;
1378:
1379: }
1380: while (--args[0] > 0);
1381:
1382: }
1383: else if (ch == 'B') { /* CUD cursor down */
1384:
1385: do {
1386:
1387: if (++ypos[HOME] >= (n_lines - 1)) ypos[HOME] = (n_lines - 1);
1388:
1389: }
1390: while (--args[0] > 0);
1391:
1392: }
1393: else if (ch == 'C') { /* CUF cursor right */
1394:
1395: do {
1396:
1397: if (++xpos[HOME] >= n_columns) xpos[HOME] = (n_columns - 1);
1398:
1399: }
1400: while (--args[0] > 0);
1401:
1402: }
1403: else if (ch == 'D') { /* CUB cursor left */
1404:
1405: do {
1406:
1407: if (--xpos[HOME] < 0) xpos[HOME] = 0;
1408:
1409: }
1410: while (--args[0] > 0) ;
1411:
1412: }
1413: else if (ch == 'H') { /* CUP cursor position */
1414:
1415: i = --args[0];
1416:
1417: if (i < 0) i = 0;
1418: if (i <= n_lines) ypos[HOME] = i;
1419:
1420: i = --args[1];
1421:
1422: if (i < 0) i = 0;
1423: if (i < n_columns) xpos[HOME] = i;
1424:
1425: }
1426: else if (ch == 'K') { /* EL erase line */
1427:
1428: int k;
1429:
1430: i = 0;
1431: k = n_columns;
1432:
1433: if (args[0] == 0) i = xpos[HOME];
1434: if (args[0] == 1) k = xpos[HOME] + 1;
1435:
1436: while (i < k) {
1437:
1438: (*screen).screenx[(unsigned int) (*screen).sclines[ypos[HOME]]][i] = SP;
1439: (*screen).screena[(unsigned int) (*screen).sclines[ypos[HOME]]][i] = 0; /* not 'att' */
1440:
1441:
1442: #ifdef COLOR
1443: (*screen).screenc[(unsigned int) (*screen).sclines[ypos[HOME]]][i] = (*screen).col;
1444: #endif /* COLOR */
1445:
1446: i++;
1447:
1448: }
1449: }
1450: else /* TODO: this bogosity must go away. */
1451:
1452:
1453: ED:
1454: if (ch == 'J') { /* ED erase display */
1455:
1456: register int k;
1457:
1458: #ifdef COLOR
1459: unsigned char color;
1460: #endif /* COLOR (COLOR is forced on in mpsdef.h or mpsdef0.h) */
1461:
1462: i = 0;
1463: k = n_columns;
1464:
1465: if (args[0] == 0) i = xpos[HOME];
1466: if (args[0] == 1) k = xpos[HOME] + 1;
1467:
1468:
1469: #ifdef COLOR
1470: color = (*screen).col;
1471: #endif /* COLOR */
1472:
1473: while (i < k) { /* clear current line */
1474:
1475: /* TODO: revisit this commented-out section. Was part of the
1476: * original support for terminals larger than 80x25.
1477: * Possibly responsible for screen state corruption?
1478: *
1479: * Ref: issue #95
1480: * https://gitlab.coherent-logic.com/jpw/freem/-/issues/95
1481: */
1482: /*
1483: (*screen).screenx[(unsigned int) (*screen).sclines[ypos[HOME]]][i] = SP;
1484: (*screen).screena[(unsigned int) (*screen).sclines[ypos[HOME]]][i] = 0;*/
1485:
1486: (*screen).screenx[ypos[HOME]][i] = SP;
1487: (*screen).screena[ypos[HOME]][i] = 0; /* not 'att' */
1488:
1489: #ifdef COLOR
1490: (*screen).screenc[ypos[HOME]][i] = color;
1491: #endif /* COLOR */
1492:
1493: i++;
1494:
1495: }
1496:
1497: /* clear rest of screen */
1498: if (args[0] != 1) {
1499:
1500: for (k = ypos[HOME] + 1; k < n_lines; k++) {
1501:
1502: for (i = 0; i < n_columns; i++) {
1503:
1504: /* TODO: revisit; see above */
1505: /* (*screen).screenx[(unsigned int) (*screen).sclines[k]][i] = SP; */
1506: (*screen).screenx[k][i] = SP;
1507: (*screen).screena[k][i] = 0;
1508:
1509:
1510: #ifdef COLOR
1511: (*screen).screenc[k][i] = color;
1512: #endif /* COLOR */
1513:
1514: }
1515:
1516: }
1517:
1518: }
1519:
1520: /* clear beginning of screen */
1521: if (args[0] != 0) {
1522:
1523: for (k = 0; k < ypos[HOME]; k++) {
1524:
1525: for (i = 0; i < n_columns; i++) {
1526:
1527: (*screen).screenx[k][i] = SP;
1528: (*screen).screena[k][i] = 0;
1529:
1530:
1531: #ifdef COLOR
1532: (*screen).screenc[k][i] = color;
1533: #endif /* COLOR */
1534:
1535: }
1536:
1537: }
1538:
1539: }
1540:
1541:
1542: #ifdef SCO
1543: if (foreground) {
1544:
1545: if ((*screen).lin24) tmp[tmpx - 1] = CAN;
1546:
1547: tmp[tmpx] = EOL;
1548: m_output (tmp);
1549:
1550: tmpx = 0;
1551: part_ref (screen, 0, n_lines - 1);
1552:
1553: }
1554: #endif /* SCO */
1555:
1556: }
1557: /* end ED */
1558: else if (ch == 'p') { /* private */
1559:
1560: if (args[0] == 10) {
1561:
1562: /* invert 'inverse' at */
1563: /* current cursor pos. */
1564:
1565: (*screen).screena[(unsigned int) (*screen).sclines[ypos[HOME]]][xpos[HOME]] ^= 0100;
1566:
1567: #ifdef SCO
1568:
1569: /* now we're in the meat of the really bizarre SCO UNIX terminal I/O stuff.
1570: most of this will need to be reworked. */
1571:
1572: if (foreground) {
1573:
1574: k = (*screen).screena[(unsigned int) (*screen).sclines[ypos[HOME]]][xpos[HOME]];
1575:
1576: if (((*screen).att & 01) != (k & 01)) tmp[tmpx++] = (k & 01) ? SO : SI;
1577:
1578: k = scosgr (k, (*screen).bw);
1579:
1580: tmp[tmpx++] = ESC;
1581: tmp[tmpx++] = '[';
1582:
1583: if ((*screen).bw) tmp[tmpx++] = '7';
1584:
1585: tmp[tmpx++] = 'm';
1586: tmp[tmpx++] = ESC;
1587: tmp[tmpx++] = '[';
1588:
1589: if (k & 02) {
1590: tmp[tmpx++] = '1';
1591: tmp[tmpx++] = ';';
1592: } /* SCO !!! Yeah, SCO. What of it? Such a useful comment... */
1593:
1594: if (k & 04) {
1595: tmp[tmpx++] = '3';
1596: tmp[tmpx++] = ';';
1597: }
1598:
1599: if (k & 010) {
1600: tmp[tmpx++] = '4';
1601: tmp[tmpx++] = ';';
1602: }
1603:
1604: if (k & 020) {
1605: tmp[tmpx++] = '5';
1606: tmp[tmpx++] = ';';
1607: }
1608:
1609: if (k & 040) {
1610: tmp[tmpx++] = '6';
1611: tmp[tmpx++] = ';';
1612: }
1613:
1614: if (k & 0100) {
1615: tmp[tmpx++] = '7';
1616: tmp[tmpx++] = ';';
1617: }
1618:
1619: if (k & 0200) {
1620: tmp[tmpx++] = '8';
1621: tmp[tmpx++] = ';';
1622: }
1623:
1624: if (tmp[tmpx - 1] == ';') tmpx--;
1625:
1626: tmp[tmpx++] = 'm';
1627: tmp[tmpx++] = (*screen).screenx[(unsigned int) (*screen).sclines[ypos[HOME]]][xpos[HOME]];
1628: tmp[tmpx++] = ESC;
1629: tmp[tmpx++] = '[';
1630: k = ypos[HOME] + 1;
1631:
1632: if (k > 9) tmp[tmpx++] = k / 10 + '0';
1633:
1634: tmp[tmpx++] = k % 10 + '0';
1635:
1636: if (xpos[HOME]) {
1637:
1638: tmp[tmpx++] = ';';
1639: k = xpos[HOME] + 1;
1640:
1641: if (k > 9) tmp[tmpx++] = k / 10 + '0';
1642:
1643: tmp[tmpx++] = k % 10 + '0';
1644:
1645: }
1646:
1647: tmp[tmpx++] = 'H';
1648:
1649: if (k != screen->att) {
1650:
1651: k = scosgr ((*screen).att, (*screen).bw);
1652:
1653: tmp[tmpx++] = (k & 01) ? SO : SI;
1654: tmp[tmpx++] = ESC;
1655: tmp[tmpx++] = '[';
1656: tmp[tmpx++] = '0';
1657:
1658: if (k & 02) {
1659: tmp[tmpx++] = ';';
1660: tmp[tmpx++] = '1';
1661: } /* SCO !!! Again... what about it? */
1662:
1663: if (k & 04) {
1664: tmp[tmpx++] = ';';
1665: tmp[tmpx++] = '3';
1666: }
1667:
1668: if (k & 010) {
1669: tmp[tmpx++] = ';';
1670: tmp[tmpx++] = '4';
1671: }
1672:
1673: if (k & 020) {
1674: tmp[tmpx++] = ';';
1675: tmp[tmpx++] = '5';
1676: }
1677:
1678: if (k & 040) {
1679: tmp[tmpx++] = ';';
1680: tmp[tmpx++] = '6';
1681: }
1682:
1683: if (k & 0100) {
1684: tmp[tmpx++] = ';';
1685: tmp[tmpx++] = '7';
1686: }
1687:
1688: if (k & 0200) {
1689: tmp[tmpx++] = ';';
1690: tmp[tmpx++] = '8';
1691: }
1692:
1693: tmp[tmpx++] = 'm';
1694:
1695: }
1696:
1697: }
1698: #endif /* SCO */
1699:
1700: }
1701: }
1702: else if (ch == 'r') { /* TBM Top_Bottom Margin */
1703:
1704: register int k;
1705:
1706: if (noargs || ((*screen).sc_up = (--args[0])) <= 0) (*screen).sc_up = 0;
1707:
1708: /* TODO: Revisit. This still appears to be hardcoded to the old fixed terminal size.
1709: * Ref issue #95
1710: */
1711: if (!argcnt || (((*screen).sc_lo = (--args[1])) > 24) || ((*screen).sc_lo == 23 && (*screen).lin24 == TRUE)) {
1712: (*screen).sc_lo = (*screen).lin24 ? 23 : 24;
1713: }
1714:
1715: /* restore old cursor position */
1716: tmp[tmpx++] = ESC;
1717: tmp[tmpx++] = '[';
1718: k = ypos[HOME] + 1;
1719:
1720: if (k > 9) tmp[tmpx++] = k / 10 + '0';
1721:
1722: tmp[tmpx++] = k % 10 + '0';
1723:
1724: if (xpos[HOME]) {
1725:
1726: tmp[tmpx++] = ';';
1727: k = xpos[HOME] + 1;
1728:
1729: if (k > 9) tmp[tmpx++] = k / 10 + '0';
1730:
1731: tmp[tmpx++] = k % 10 + '0';
1732:
1733: }
1734:
1735: tmp[tmpx++] = 'H';
1736:
1737: }
1738: else if (ch == 's') { /* CS Cursor Save */
1739:
1740: (*screen).csx[(*screen).cs] = xpos[HOME];
1741: (*screen).csy[(*screen).cs] = ypos[HOME];
1742: (*screen).cssgr[(*screen).cs] = (*screen).att;
1743:
1744:
1745: #ifdef COLOR
1746: (*screen).cscol[(*screen).cs] = (*screen).col;
1747: #endif /* COLOR */
1748:
1749: if (++((*screen).cs) >= CSLEN) (*screen).cs = CSLEN - 1;
1750:
1751: }
1752: else if (ch == 'u') {
1753:
1754: /* CRST Cursor Unsave (if no args) */
1755: /* those bloody bastards made 'CSI u' and CSI 0 u' */
1756: /* different. flag 'noargs' distinguishes */
1757:
1758: /* bloody bastards, eh? this whole module is a bloody bastard,
1759: * so I seriously have no idea what the hell you're complaining
1760: * about, Mr. ha-Ashkenaz.
1761: */
1762:
1763: if (noargs) {
1764:
1765:
1766: #ifdef COLOR
1767: int color;
1768: #endif /* COLOR */
1769:
1770: if (--((*screen).cs) <= 0) (*screen).cs = 0;
1771:
1772: xpos[HOME] = (*screen).csx[(*screen).cs];
1773: ypos[HOME] = (*screen).csy[(*screen).cs];
1774:
1775: (*screen).att = (*screen).cssgr[(*screen).cs];
1776:
1777:
1778: #ifdef COLOR
1779: (*screen).col = (*screen).cscol[(*screen).cs];
1780: color = (*screen).col;
1781: #endif /* COLOR */
1782:
1783: /* make sure cursor is at desired position */
1784: tmp[tmpx++] = ESC;
1785: tmp[tmpx++] = '[';
1786:
1787: if (ypos[HOME] > 8) tmp[tmpx++] = (1 + ypos[HOME]) / 10 + '0';
1788:
1789: tmp[tmpx++] = (1 + ypos[HOME]) % 10 + '0';
1790:
1791: if (xpos[HOME] > 0) {
1792:
1793: tmp[tmpx++] = ';';
1794:
1795: if (xpos[HOME] > 8) tmp[tmpx++] = (1 + xpos[HOME]) / 10 + '0';
1796:
1797: tmp[tmpx++] = (1 + xpos[HOME]) % 10 + '0';
1798:
1799: }
1800:
1801: tmp[tmpx++] = 'H';
1802:
1803:
1804: #ifdef COLOR
1805:
1806: /* make sure cursor has right color */
1807: tmp[tmpx++] = ESC; /* background color */
1808: tmp[tmpx++] = '[';
1809: tmp[tmpx++] = '=';
1810:
1811: if (color / 16 > 9) tmp[tmpx++] = '0' + (color / 16 / 10);
1812:
1813: tmp[tmpx++] = '0' + (color / 16 % 10);
1814: tmp[tmpx++] = 'G';
1815: tmp[tmpx++] = ESC; /* reverse foreground col */
1816: tmp[tmpx++] = '[';
1817: tmp[tmpx++] = '=';
1818:
1819: if (color / 16 > 9) tmp[tmpx++] = '0' + (color / 16 / 10);
1820:
1821: tmp[tmpx++] = '0' + (color / 16 % 10);
1822: tmp[tmpx++] = 'H';
1823: tmp[tmpx++] = ESC; /* foreground color */
1824: tmp[tmpx++] = '[';
1825: tmp[tmpx++] = '=';
1826:
1827: if (color % 16 > 9) tmp[tmpx++] = '0' + (color % 16 / 10);
1828:
1829: tmp[tmpx++] = '0' + (color % 16 % 10);
1830: tmp[tmpx++] = 'F';
1831: tmp[tmpx++] = ESC; /* reverse background col */
1832: tmp[tmpx++] = '[';
1833: tmp[tmpx++] = '=';
1834:
1835: if (color % 16 > 9) tmp[tmpx++] = '0' + (color % 16 / 10);
1836:
1837: tmp[tmpx++] = '0' + (color % 16 % 10);
1838: tmp[tmpx++] = 'I';
1839: #endif /* COLOR */
1840:
1841: }
1842: else if (args[0] == 0) {
1843:
1844: (*screen).lin24 = FALSE;
1845:
1846: if ((*screen).sc_lo == 23) (*screen).sc_lo = 24;
1847:
1848: }
1849: else if (args[0] == 1) {
1850:
1851: (*screen).lin24 = TRUE;
1852:
1853: if ((*screen).sc_lo == 24) (*screen).sc_lo = 23;
1854:
1855: }
1856: else if (args[0] == 8) {
1857: (*screen).rollflag = FALSE;
1858: }
1859: else if (args[0] == 9) {
1860: (*screen).rollflag = TRUE;
1861: }
1862: #ifdef SCO
1863: else if (args[0] == 20) {
1864:
1865: (*screen).bw = FALSE;
1866:
1867: if (foreground) {
1868:
1869: tmp[tmpx] = EOL;
1870: m_output (tmp);
1871:
1872: tmpx = 0;
1873: part_ref (screen, 0, n_lines - 1);
1874:
1875: }
1876:
1877: }
1878: else if (args[0] == 21) {
1879:
1880: (*screen).bw = TRUE;
1881:
1882: if (foreground) {
1883:
1884: tmp[tmpx] = EOL;
1885: m_output (tmp);
1886:
1887: tmpx = 0;
1888: part_ref (screen, 0, n_lines - 1);
1889:
1890: }
1891:
1892: }
1893: #endif /* SCO */
1894:
1895: }
1896: else if (ch == 'X') { /* ECH Erase Character */
1897:
1898: if ((k = args[0]) < 1) k = 1;
1899: if ((k + xpos[HOME]) > n_columns) k = n_columns - xpos[HOME];
1900:
1901: i = xpos[HOME];
1902: k = i + k;
1903:
1904: while (i < k) {
1905:
1906: (*screen).screenx[(unsigned int) (*screen).sclines[ypos[HOME]]][i] = SP;
1907: (*screen).screena[(unsigned int) (*screen).sclines[ypos[HOME]]][i] = 0; /* not 'att' */
1908:
1909:
1910: #ifdef COLOR
1911: (*screen).screenc[(unsigned int) (*screen).sclines[ypos[HOME]]][i] = (*screen).col;
1912: #endif /* COLOR */
1913:
1914: i++;
1915:
1916: }
1917:
1918: } else if (ch == 'g') { /* TBC Tabulation clear */
1919:
1920: if (args[0] == 3) {
1921: /* clear all */
1922: for (i = 0; i < n_columns; (*screen).tabs[i++] = 0) ;
1923: }
1924: else if (args[0] == 0) {
1925: /* clear one */
1926: (*screen).tabs[xpos[HOME]] = 0;
1927: }
1928:
1929:
1930: #ifdef SCO
1931: while (tmpx >= 0) if (tmp[--tmpx] == ESC) break;
1932:
1933: tmp[tmpx] = NUL;
1934: ch = NUL;
1935: #endif /* SCO */
1936:
1937: }
1938: else if (ch == 'm') { /* SGR Select Graphic Rendition */
1939:
1940: (*screen).att &= 01; /* clear att */
1941:
1942:
1943: #ifdef SCO
1944: while (tmpx > 0 && tmp[--tmpx] != ESC);
1945:
1946: ch = CAN;
1947: #endif /* SCO */
1948:
1949: i = argcnt;
1950:
1951: while (i >= 0) {
1952:
1953: if (((*screen).savarg = (args[i] == 50))) continue;
1954:
1955:
1956: #ifdef SCO /* process save SGR(1) in position of SGR(2) */
1957: if (args[i] == 1) args[i] = 2;
1958: #endif /* SCO */
1959:
1960: #ifdef COLOR
1961: if (args[i] > 29 && args[i] < 38) { /* foregr.color */
1962: (*screen).col = ((*screen).col & ~017) | coltrans[args[i] - 30];
1963: }
1964:
1965: if (args[i] > 39 && args[i] < 48) { /* backgr.color */
1966: (*screen).col = (((*screen).col & 017) | (coltrans[args[i] - 40] * 16));
1967: }
1968:
1969: #endif /* COLOR */
1970:
1971: if (args[i] > 1 && args[i] < 9) (*screen).att |= (1 << (args[i] - 1));
1972: if (args[i] == 0) (*screen).att &= 01; /* clear att */
1973:
1974: i--;
1975:
1976: }
1977:
1978: #ifdef SCO
1979: tmp[tmpx++] = ESC;
1980: tmp[tmpx++] = '[';
1981: if ((*screen).bw) tmp[tmpx++] = '7';
1982:
1983: tmp[tmpx++] = 'm';
1984:
1985:
1986: #ifdef COLOR
1987: tmp[tmpx++] = ESC;
1988: tmp[tmpx++] = '[';
1989: tmp[tmpx++] = '=';
1990: if ((*screen).col / 16 > 9) tmp[tmpx++] = '0' + ((*screen).col / 16 / 10);
1991:
1992: tmp[tmpx++] = '0' + ((*screen).col / 16 % 10);
1993: tmp[tmpx++] = 'G';
1994: tmp[tmpx++] = ESC;
1995: tmp[tmpx++] = '[';
1996: tmp[tmpx++] = '=';
1997: if ((*screen).col / 16 > 9) tmp[tmpx++] = '0' + ((*screen).col / 16 / 10);
1998:
1999: tmp[tmpx++] = '0' + ((*screen).col / 16 % 10);
2000: tmp[tmpx++] = 'H';
2001: tmp[tmpx++] = ESC;
2002: tmp[tmpx++] = '[';
2003: tmp[tmpx++] = '=';
2004: if ((*screen).col % 16 > 9) tmp[tmpx++] = '0' + ((*screen).col % 16 / 10);
2005:
2006: tmp[tmpx++] = '0' + ((*screen).col % 16 % 10);
2007: tmp[tmpx++] = 'F';
2008: tmp[tmpx++] = ESC;
2009: tmp[tmpx++] = '[';
2010: tmp[tmpx++] = '=';
2011: if ((*screen).col % 16 > 9) tmp[tmpx++] = '0' + ((*screen).col % 16 / 10);
2012:
2013: tmp[tmpx++] = '0' + ((*screen).col % 16 % 10);
2014: tmp[tmpx++] = 'I';
2015: #endif /* COLOR */
2016:
2017: if ((*screen).att & ~01) {
2018:
2019: int j;
2020:
2021: j = scosgr ((*screen).att & ~01, (*screen).bw);
2022:
2023: tmp[tmpx++] = ESC;
2024: tmp[tmpx++] = '[';
2025:
2026: if (j & 02) {
2027: tmp[tmpx++] = '1';
2028: tmp[tmpx++] = ';';
2029: }
2030:
2031: if (j & 04) {
2032: tmp[tmpx++] = '3';
2033: tmp[tmpx++] = ';';
2034: }
2035:
2036: if (j & 010) {
2037: tmp[tmpx++] = '4';
2038: tmp[tmpx++] = ';';
2039: }
2040:
2041: if (j & 020) {
2042: tmp[tmpx++] = '5';
2043: tmp[tmpx++] = ';';
2044: }
2045:
2046: if (j & 040) {
2047: tmp[tmpx++] = '6';
2048: tmp[tmpx++] = ';';
2049: }
2050:
2051: if (j & 0100) {
2052: tmp[tmpx++] = '7';
2053: tmp[tmpx++] = ';';
2054: }
2055:
2056: if (j & 0200) {
2057: tmp[tmpx++] = '8';
2058: tmp[tmpx++] = ';';
2059: }
2060:
2061: if (tmp[tmpx - 1] == ';') tmpx--;
2062:
2063: tmp[tmpx++] = 'm';
2064:
2065: }
2066: #endif /* SCO */
2067:
2068: }
2069: else if (ch == 'P') { /* DCH Delete Character */
2070: int j;
2071:
2072: if ((j = args[0]) == 0) j = 1;
2073:
2074: k = (*screen).sclines[ypos[HOME]];
2075:
2076: for (i = xpos[HOME]; i < (n_columns - j); i++) {
2077:
2078: (*screen).screenx[k][i] = (*screen).screenx[k][i + j];
2079: (*screen).screena[k][i] = (*screen).screena[k][i + j];
2080:
2081:
2082: #ifdef COLOR
2083: (*screen).screenc[k][i] = (*screen).screenc[k][i + j];
2084: #endif /* COLOR */
2085:
2086: }
2087:
2088: for (; i < n_columns; i++) {
2089:
2090: (*screen).screenx[k][i] = SP;
2091: (*screen).screena[k][i] = (*screen).att;
2092:
2093:
2094: #ifdef COLOR
2095: (*screen).screenc[k][i] = (*screen).col;
2096: #endif /* COLOR */
2097:
2098: }
2099:
2100:
2101: } else if (ch == '@') { /* ICH Insert Character */
2102: int j;
2103:
2104: if ((j = args[0]) == 0) j = 1;
2105:
2106: k = (*screen).sclines[ypos[HOME]];
2107:
2108: for (i = (n_columns - 1); i >= (xpos[HOME] + j); i--) {
2109:
2110: (*screen).screenx[k][i] = (*screen).screenx[k][i - j];
2111: (*screen).screena[k][i] = (*screen).screena[k][i - j];
2112:
2113:
2114: #ifdef COLOR
2115: (*screen).screenc[k][i] = (*screen).screenc[k][i - j];
2116: #endif /* COLOR */
2117:
2118: }
2119:
2120: for (; i >= xpos[HOME]; i--) {
2121:
2122: (*screen).screenx[k][i] = SP;
2123: (*screen).screena[k][i] = (*screen).att;
2124:
2125:
2126: #ifdef COLOR
2127: (*screen).screenc[k][i] = (*screen).col;
2128: #endif /* COLOR */
2129:
2130: }
2131:
2132: } else if (ch == 'M') { /* DL Delete Line */
2133: int j = args[0];
2134:
2135: do {
2136:
2137: k = (*screen).sclines[ypos[HOME]];
2138:
2139: for (i = ypos[HOME]; i < (*screen).sc_lo; i++) (*screen).sclines[i] = (*screen).sclines[i + 1];
2140:
2141: (*screen).sclines[i] = k;
2142:
2143: for (i = 0; i < n_columns; i++) {
2144:
2145: (*screen).screenx[k][i] = SP;
2146: (*screen).screena[k][i] = (*screen).att;
2147:
2148:
2149: #ifdef COLOR
2150: (*screen).screenc[k][i] = (*screen).col;
2151: #endif /* COLOR */
2152:
2153: }
2154:
2155: } while (--j > 0);
2156:
2157: xpos[HOME] = 0;
2158:
2159:
2160: #ifdef SCO
2161: if (foreground) {
2162:
2163: tmp[tmpx - 1] = CAN; /* do not send DL */
2164: tmp[tmpx] = EOL;
2165: m_output (tmp);
2166:
2167: tmpx = 0;
2168: part_ref (screen, (*screen).sc_up, n_lines - 1);
2169:
2170: }
2171:
2172: #endif /* SCO */
2173:
2174: }
2175: else if (ch == 'L') { /* IL Insert Line */
2176: int j = args[0];
2177:
2178: do {
2179: k = (*screen).sclines[(*screen).sc_lo];
2180:
2181: for (i = (*screen).sc_lo; i > ypos[HOME]; i--) {
2182: (*screen).sclines[i] = (*screen).sclines[i - 1];
2183: }
2184:
2185: (*screen).sclines[ypos[HOME]] = k;
2186:
2187: for (i = 0; i < n_columns; i++) {
2188:
2189: (*screen).screenx[k][i] = SP;
2190: (*screen).screena[k][i] = (*screen).att;
2191:
2192:
2193: #ifdef COLOR
2194: (*screen).screenc[k][i] = (*screen).col;
2195: #endif /* COLOR */
2196:
2197: }
2198: } while (--j > 0);
2199:
2200: xpos[HOME] = 0;
2201:
2202:
2203: #ifdef SCO
2204: if (foreground) {
2205:
2206: tmp[tmpx - 1] = CAN; /* do not send IL */
2207: tmp[tmpx] = EOL;
2208: m_output (tmp);
2209:
2210: tmpx = 0;
2211: part_ref (screen, (*screen).sc_up, n_lines - 1);
2212:
2213: }
2214: #endif /* SCO */
2215:
2216: }
2217: else if (ch == 'S') { /* SU Scroll up */
2218: int j = args[0];
2219:
2220: do {
2221:
2222: k = (*screen).sclines[(*screen).sc_up];
2223:
2224: for (i = (*screen).sc_up; i < (*screen).sc_lo; i++) {
2225: (*screen).sclines[i] = (*screen).sclines[i + 1];
2226: }
2227:
2228: (*screen).sclines[i] = k;
2229:
2230: for (i = 0; i < n_columns; i++) {
2231:
2232: (*screen).screenx[k][i] = SP;
2233: (*screen).screena[k][i] = (*screen).att;
2234:
2235:
2236: #ifdef COLOR
2237: (*screen).screenc[k][i] = (*screen).col;
2238: #endif /* COLOR */
2239:
2240: }
2241:
2242: } while (--j > 0);
2243:
2244:
2245: #ifdef SCO
2246: if (foreground) {
2247:
2248: tmp[tmpx - 1] = 'A'; /* do not send SU */
2249: tmp[tmpx] = EOL;
2250: m_output (tmp);
2251:
2252: tmpx = 0;
2253: part_ref (screen, (*screen).sc_up, n_lines - 1);
2254:
2255: }
2256: #endif /* SCO */
2257:
2258: }
2259: else if (ch == 'T') { /* SD Scroll down */
2260:
2261: int j = args[0];
2262:
2263: do {
2264:
2265: k = (*screen).sclines[(*screen).sc_lo];
2266:
2267: for (i = (*screen).sc_lo; i > (*screen).sc_up; i--) {
2268: (*screen).sclines[i] = (*screen).sclines[i - 1];
2269: }
2270:
2271: (*screen).sclines[i] = k;
2272:
2273: for (i = 0; i < n_columns; i++) {
2274:
2275: (*screen).screenx[k][i] = SP;
2276: (*screen).screena[k][i] = (*screen).att;
2277:
2278:
2279: #ifdef COLOR
2280: (*screen).screenc[k][i] = (*screen).col;
2281: #endif /* COLOR */
2282:
2283: }
2284:
2285: } while (--j > 0);
2286:
2287:
2288: #ifdef SCO
2289:
2290: if (foreground) {
2291:
2292: tmp[tmpx - 1] = 'A'; /* do not send SD */
2293: tmp[tmpx] = EOL;
2294: m_output (tmp);
2295:
2296: tmpx = 0;
2297: part_ref (screen, (*screen).sc_up, n_lines - 1);
2298:
2299: }
2300:
2301: #endif /* SCO */
2302:
2303: } else if (ch == 'Z') { /* CBT Cursor backward tab */
2304:
2305: if ((i = xpos[HOME] - 1) < 1) i = 1;
2306:
2307: do {
2308:
2309: while ((*screen).tabs[--i] == 0) {
2310:
2311: if (i < 0) {
2312: i++;
2313: break;
2314: }
2315:
2316: }
2317:
2318: if (i == 0) break;
2319:
2320: } while (args[0]-- > 0);
2321:
2322: xpos[HOME] = i;
2323:
2324:
2325: #ifdef PROC_TAB
2326: tmp[tmpx++] = CR;
2327:
2328: if ((xpos[HOME] = i) != 0) {
2329:
2330: tmp[tmpx++] = ESC;
2331: tmp[tmpx++] = '[';
2332:
2333: if (i > 9) tmp[tmpx++] = i / 10 + '0';
2334:
2335: tmp[tmpx++] = i % 10 + '0';
2336: tmp[tmpx++] = 'C';
2337:
2338: }
2339:
2340: #endif /* PROC_TAB */
2341:
2342: }
2343:
2344: if (ch != '~') goto zasend;
2345:
2346: /* ZAS Alternate Screen stuff */
2347: /* the following is better programmed with */
2348: /* 'switch' but some compilers do not have */
2349: /* enough power to swallow the implied stack */
2350: /* depth */
2351: /* switch (args[0]) */
2352:
2353: i = args[0];
2354:
2355: if (i == 1) goto zas1;
2356: if (i == 2) goto zas2;
2357: if (i == 3) goto zas3;
2358: if (i == 4) goto zas4;
2359: if (i == 5) goto zas5;
2360: if (i != 0) goto zas6;
2361:
2362: /* zas0: exchange foreground/background */
2363: tmp[tmpx] = EOL;
2364: tmpx = 0;
2365:
2366: if (foreground) m_output (tmp);
2367:
2368: /* exchange parameters of screen */
2369: (*screen).Xpos = xpos[HOME];
2370: (*screen).Ypos = ypos[HOME];
2371:
2372: vts = screen;
2373: screen = altscr;
2374: altscr = vts;
2375:
2376: xpos[HOME] = (*screen).Xpos;
2377: ypos[HOME] = (*screen).Ypos;
2378:
2379:
2380: zas4: /* refresh foreground */
2381:
2382: tmpx = 0;
2383:
2384: if (foreground) part_ref (screen, 0, n_lines - 1);
2385:
2386: goto zasend;
2387:
2388:
2389: zas1: /* foreground screen */
2390:
2391: if (foreground) goto zasend;
2392:
2393: foreground = TRUE;
2394:
2395:
2396: pPRIVATE: /* exchange parameters of screen */
2397:
2398: (*screen).Xpos = xpos[HOME];
2399: (*screen).Ypos = ypos[HOME];
2400:
2401: vts = screen;
2402: screen = altscr;
2403: altscr = vts;
2404:
2405: xpos[HOME] = (*screen).Xpos;
2406: ypos[HOME] = (*screen).Ypos;
2407:
2408: tmpx = 0;
2409:
2410: goto zasend;
2411:
2412:
2413: zas2: /* background screen */
2414:
2415: if (foreground == FALSE) goto zasend;
2416:
2417: tmp[tmpx] = EOL;
2418: m_output (tmp);
2419:
2420: foreground = FALSE;
2421:
2422: goto pPRIVATE;
2423:
2424:
2425: zas3: /* save foreground to back */
2426:
2427: stcpy0 ((char *) altscr, (const char *) screen, sizeof (struct vtstyp));
2428:
2429: goto zasend;
2430:
2431:
2432: zas5: /* push screen */
2433:
2434: if (zaslevel >= MAXZAS) goto zasend;
2435:
2436: vts = (struct vtstyp *) calloc (1, sizeof (struct vtstyp));
2437: zases[zaslevel++] = vts;
2438:
2439: (*screen).Xpos = xpos[HOME];
2440: (*screen).Ypos = ypos[HOME];
2441:
2442: stcpy0 ((char *) vts, (const char *) screen, sizeof (struct vtstyp));
2443:
2444: goto zasend;
2445:
2446:
2447: zas6: /* pop screen */
2448:
2449: if (--zaslevel < 0) {
2450: zaslevel = 0;
2451: goto zasend;
2452: }
2453:
2454: vts = zases[zaslevel];
2455:
2456:
2457: #ifdef SCO
2458: i = (*screen).bw; /* do not pop bw state */
2459: #endif /* SCO */
2460:
2461: stcpy0 ((char *) screen, (const char *) vts, sizeof (struct vtstyp));
2462:
2463:
2464: #ifdef SCO
2465: (*screen).bw = i;
2466: #endif /* SCO */
2467:
2468: xpos[HOME] = (*screen).Xpos;
2469: ypos[HOME] = (*screen).Ypos;
2470:
2471: free (vts);
2472:
2473: goto zas4;
2474: /* end zas6 */
2475:
2476:
2477: zasend: /* stuf we do when we're finished doing other zassy things */
2478:
2479: argcnt = 0;
2480: noargs = TRUE;
2481: esc = 0;
2482:
2483: continue;
2484:
2485: } /* end 'printable' characters */
2486:
2487: if ((esc = (ch == ESC))) {
2488:
2489: for (ch = 0; ch < ARGS_IN_ESC; args[ch++] = 0);
2490:
2491: argcnt = 0;
2492: noargs = TRUE;
2493:
2494: continue;
2495:
2496: }
2497:
2498: if (ch == LF) {
2499:
2500:
2501: pLF:
2502:
2503: if ((ypos[HOME] <= (*screen).sc_up) || (ypos[HOME] > (*screen).sc_lo)) {
2504:
2505: if (++ypos[HOME] >= (n_lines - 1)) {
2506: ypos[HOME] = (n_lines - 1);
2507: }
2508:
2509: if (ch == LF) tmpx--;
2510:
2511: tmp[tmpx++] = ESC;
2512: tmp[tmpx++] = '[';
2513:
2514: if (ypos[HOME] > 8) tmp[tmpx++] = (1 + ypos[HOME]) / 10 + '0';
2515:
2516: tmp[tmpx++] = (1 + ypos[HOME]) % 10 + '0';
2517:
2518: if (xpos[HOME] > 0) {
2519:
2520: tmp[tmpx++] = ';';
2521:
2522: if (xpos[HOME] > 8) tmp[tmpx++] = (1 + xpos[HOME]) / 10 + '0';
2523:
2524: tmp[tmpx++] = (1 + xpos[HOME]) % 10 + '0';
2525:
2526: }
2527:
2528: tmp[tmpx++] = 'H';
2529:
2530: }
2531: else if (ypos[HOME] < (*screen).sc_lo) {
2532:
2533: /* within scroll area */
2534: if (++ypos[HOME] >= (n_lines - 1)) {
2535: ypos[HOME] = (n_lines - 1);
2536: }
2537:
2538: }
2539: else {
2540:
2541: /* lower margin of scroll area: scroll up */
2542: xpos[HOME] = 0;
2543:
2544:
2545: #ifdef SCO
2546: if ((ch != LF) && (!(*screen).lin24) && (ypos[HOME] == (*screen).sc_lo) && (ypos[HOME] == n_lines - 1)) {
2547: continue;
2548: }
2549: #endif /* SCO */
2550:
2551: /* TODO: find out what 'rollflag' is */
2552: /* if ((*screen).rollflag==FALSE) continue; */
2553: k = (*screen).sclines[(*screen).sc_up];
2554:
2555: for (i = (*screen).sc_up; i < (*screen).sc_lo; i++) {
2556: (*screen).sclines[i] = (*screen).sclines[i + 1];
2557: }
2558:
2559: (*screen).sclines[(*screen).sc_lo] = k;
2560:
2561: for (i = 0; i < n_columns; i++) {
2562:
2563: (*screen).screenx[k][i] = SP;
2564: (*screen).screena[k][i] = (*screen).att;
2565:
2566: #ifdef COLOR
2567: (*screen).screenc[k][i] = (*screen).col;
2568: #endif /* COLOR */
2569:
2570: }
2571:
2572:
2573: #ifdef SCO
2574: tmp[tmpx] = EOL;
2575: tmpx = 0;
2576:
2577: if (foreground) {
2578: m_output (tmp);
2579: part_ref (screen, (*screen).sc_up, (*screen).sc_lo);
2580: }
2581: #endif /* SCO */
2582:
2583: }
2584:
2585: continue;
2586:
2587: } /* if (ch == LF) */
2588:
2589: if (ch == CR) {
2590: xpos[HOME] = 0;
2591: continue;
2592: }
2593:
2594: if (ch == BS) {
2595:
2596: if (--xpos[HOME] < 0) xpos[HOME] = 0;
2597:
2598: continue;
2599:
2600: }
2601:
2602: /* FORM FEED: clear screen */
2603: if (ch == FF) {
2604:
2605: xpos[HOME] = 0;
2606: ypos[HOME] = 0;
2607:
2608: ch = 'J';
2609:
2610: tmp[tmpx - 1] = ESC;
2611: tmp[tmpx++] = '[';
2612: tmp[tmpx++] = 'H';
2613: tmp[tmpx++] = ESC;
2614: tmp[tmpx++] = '[';
2615: tmp[tmpx++] = ch;
2616:
2617: args[0] = 0;
2618: noargs = TRUE;
2619: argcnt = 0;
2620:
2621: goto ED;
2622:
2623: }
2624:
2625: if (ch == TAB) {
2626:
2627: k = xpos[HOME];
2628:
2629: if ((i = k + 1) >= n_columns) i = (n_columns - 1);
2630:
2631: while ((*screen).tabs[i] == 0) {
2632:
2633: if (i >= n_columns) {
2634: i = (n_columns - 1);
2635: break;
2636: }
2637:
2638: i++;
2639:
2640: }
2641:
2642:
2643: #ifdef PROC_TAB
2644: if (i != k) {
2645:
2646: tmp[tmpx++] = CR;
2647:
2648: if ((xpos[HOME] = i) != 0) {
2649:
2650: tmp[tmpx++] = ESC;
2651: tmp[tmpx++] = '[';
2652:
2653: if (i > 9) tmp[tmpx++] = i / 10 + '0';
2654:
2655: tmp[tmpx++] = i % 10 + '0';
2656: tmp[tmpx++] = 'C';
2657:
2658: }
2659:
2660: }
2661: #endif /* PROC_TAB */
2662:
2663: continue;
2664: }
2665:
2666: /* SI Shift In */
2667: if (ch == SI) (*screen).att &= ~01; /* clear SO-Bit */
2668:
2669: /* SO Shift Out */
2670: if (ch == SO) (*screen).att |= 01; /* set SO-Bit */
2671:
2672: if (ch == CAN) { /* CANcel ESC_esquence */
2673: esc = argcnt = noargs = 0;
2674: continue;
2675: }
2676:
2677: } /* end while */
2678:
2679: tmp[tmpx] = EOL;
2680:
2681: if (foreground) m_output (tmp);
2682:
2683: return;
2684:
2685: } /* end writeHOME() */
2686:
2687:
2688: #ifdef SCO
2689:
2690: /*att screen attributes byte */
2691: /*bwflag black_on_white flag */
2692: int scosgr (short att, short bwflag)
2693: {
2694:
2695: att = att & ~044; /* suppress SGR(3) and SGR(6) */
2696:
2697: if (att & 0200) return att & 0201; /* no display */
2698: if (bwflag) att ^= 0100; /* toggle inverse */
2699: if (att & 0100) return att & 0121; /* inverse, evtl. incl. blink */
2700: if (att & 032) return att & 033; /* other valid combinations */
2701:
2702: return att;
2703:
2704: } /* end scosgr() */
2705:
2706: #endif /* SCO */
2707:
2708: /* init Screen params */
2709: void ris (struct vtstyp *scr)
2710: {
2711: short i;
2712: short l;
2713:
2714: scr->att = 0;
2715:
2716: #ifdef COLOR
2717: scr->col = 7; /* default color is white on black */
2718: #endif /* COLOR */
2719:
2720: scr->Xpos = 0;
2721: scr->Ypos = 0;
2722:
2723: for (i = 0; i < CSLEN; i++) {
2724: scr->csx[i] = 0;
2725: scr->csy[i] = 0;
2726: }
2727:
2728: scr->cs = 0;
2729: scr->sc_up = 0;
2730: scr->sc_lo = n_lines;
2731:
2732: for (i = 0; i <= n_lines; i++) {
2733:
2734: scr->sclines[i] = i;
2735:
2736: for (l = 0; l < n_columns; l++) {
2737:
2738: scr->screenx[i][l] = SP;
2739: scr->screena[i][l] = 0;
2740:
2741:
2742: #ifdef COLOR
2743: scr->screenc[i][l] = 7; /* default color is white on black */
2744: #endif /* COLOR */
2745:
2746: }
2747:
2748: }
2749:
2750: /* TABS */
2751: for (i = 0; i <= n_columns; i++) scr->tabs[i] = 0;
2752: for (i = 7; i <= n_columns; i += 8) scr->tabs[i] = 1;
2753:
2754: scr->rollflag = TRUE; /* Roll or Page mode */
2755: scr->lin24 = FALSE; /* 24 lines or 25 lines mode (MUST BE FALSE!!!!) */
2756: scr->savarg = FALSE;
2757:
2758: for (i = 0; i < CSLEN; i++) scr->cssgr[i] = FALSE; /* save SGR flag */
2759:
2760: return;
2761:
2762: } /* end ris() */
2763:
2764: /* refresh (foreground) screen partially */
2765: void part_ref (struct vtstyp *scr, short from, short to)
2766: {
2767: short k;
2768: short l;
2769: short max;
2770: unsigned char exa;
2771: #if !defined(LINUX) && defined(COLOR)
2772: unsigned char exc;
2773: #endif
2774: short i;
2775: unsigned char *linea;
2776: unsigned char *linex;
2777: unsigned char *linec;
2778: unsigned char ch;
2779: char tmp[1300]; /* was unsigned char tmp... (snw 4-9-2025) */
2780:
2781: /* build up alternate screen */
2782: /* reset SGR,TBM;white on black,go HOME; 25 Lines */
2783: stcpy (tmp, "\017\033[m\033[37;40m\033[r\033[H\033[0u\201");
2784: m_output (tmp);
2785:
2786:
2787: #ifndef PROC_TAB
2788:
2789: k = 0;
2790: i = 0; /* set TABs */
2791:
2792: tmp[k++] = ESC;
2793: tmp[k++] = '[';
2794:
2795: if (from > 8) tmp[k++] = '0' + (from + 1) / 10;
2796:
2797: tmp[k++] = '0' + (from + 1) % 10;
2798: tmp[k++] = 'H';
2799:
2800: for (l = 0; l < n_columns; l++) {
2801:
2802: tmp[k++] = SP;
2803:
2804: if ((*scr).tabs[l]) {
2805:
2806: tmp[k++] = ESC;
2807: tmp[k++] = 'H';
2808:
2809: i = k;
2810:
2811: }
2812:
2813: }
2814:
2815: tmp[i++] = CR;
2816: tmp[i] = EOL;
2817: m_output (tmp);
2818:
2819: #endif /* PROC_TAB */
2820:
2821: k = 0;
2822:
2823: for (i = from; i <= to; i++) {
2824:
2825: tmp[k++] = ESC; /* CUP(i) */
2826: tmp[k++] = '[';
2827:
2828: if (i > 8) tmp[k++] = (i + 1) / 10 + '0';
2829: if (i > 0) tmp[k++] = (i + 1) % 10 + '0';
2830:
2831: tmp[k++] = 'H';
2832:
2833: linex = (*scr).screenx[(unsigned int) (*scr).sclines[i]];
2834: linea = (*scr).screena[(unsigned int) (*scr).sclines[i]];
2835:
2836: #ifdef COLOR
2837: linec = (*scr).screenc[(unsigned int) (*scr).sclines[i]];
2838: #endif /* COLOR */
2839:
2840: for (max = n_columns - 1; max > 0; max--) {
2841:
2842: if (linex[max] != SP) break;
2843: if (linea[max] != linea[max - 1]) break;
2844: if (linec[max] != linec[max - 1]) break;
2845:
2846: }
2847:
2848: exa = ~linea[0]; /* dummy value to trigger argument codes on 1st char */
2849:
2850: #if !defined(LINUX) && defined(COLOR)
2851: exc = ~linec[0]; /* dummy value to trigger argument codes on 1st char */
2852: #endif
2853:
2854: for (l = 0; l <= max; l++) {
2855:
2856: if (l == (n_columns - 1) && (i == (n_lines))) continue;
2857:
2858: #ifndef LINUX
2859: #ifdef COLOR
2860: if (exc != linec[l]) { /* set color */
2861:
2862: if ((exc / 16) != (linec[l] / 16)) { /* background color */
2863:
2864: tmp[k++] = ESC;
2865: tmp[k++] = '[';
2866: tmp[k++] = '=';
2867: tmp[k++] = '0';
2868:
2869: if (linec[l] / 16 > 9) tmp[k++] = '0' + linec[l] / 16 / 10;
2870:
2871: tmp[k++] = '0' + linec[l] / 16 % 10;
2872: tmp[k++] = 'G';
2873: tmp[k++] = ESC; /* background == reverse foreground */
2874: tmp[k++] = '[';
2875: tmp[k++] = '=';
2876: tmp[k++] = '0';
2877:
2878: if (linec[l] / 16 > 9) tmp[k++] = '0' + linec[l] / 16 / 10;
2879:
2880: tmp[k++] = '0' + linec[l] / 16 % 10;
2881: tmp[k++] = 'H';
2882:
2883: }
2884:
2885: if ((exc % 16) != (linec[l] % 16)) { /* foreground color */
2886:
2887: tmp[k++] = ESC;
2888: tmp[k++] = '[';
2889: tmp[k++] = '=';
2890: tmp[k++] = '0';
2891:
2892: if (linec[l] % 16 > 9) tmp[k++] = '0' + linec[l] % 16 / 10;
2893:
2894: tmp[k++] = '0' + linec[l] % 16 % 10;
2895: tmp[k++] = 'F';
2896: tmp[k++] = ESC; /* foreground == reverse background */
2897: tmp[k++] = '[';
2898: tmp[k++] = '=';
2899: tmp[k++] = '0';
2900:
2901: if (linec[l] % 16 > 9) tmp[k++] = '0' + linec[l] % 16 / 10;
2902:
2903: tmp[k++] = '0' + linec[l] % 16 % 10;
2904: tmp[k++] = 'I';
2905:
2906: }
2907:
2908: exc = linec[l];
2909:
2910: }
2911:
2912: #endif /* COLOR */
2913: #endif /* LINUX */
2914:
2915: if (exa != linea[l]) { /* set attribute */
2916:
2917: short p;
2918: short xatt;
2919:
2920: p = exa;
2921: exa = linea[l];
2922:
2923: if ((p & 01) != (exa & 01)) tmp[k++] = (exa & 01) ? SO : SI;
2924:
2925: if ((p & ~01) != (exa & ~01)) {
2926:
2927: xatt = exa;
2928:
2929:
2930: #ifdef SCO
2931: xatt = scosgr (xatt, (*scr).bw);
2932: #endif /* SCO */
2933:
2934: tmp[k++] = ESC;
2935: tmp[k++] = '[';
2936:
2937:
2938: #ifdef SCO
2939: if ((*scr).bw) tmp[k++] = '7';
2940: #endif /* SCO */
2941:
2942: tmp[k++] = 'm';
2943: tmp[k++] = ESC;
2944: tmp[k++] = '[';
2945:
2946: if (xatt & 02) {
2947:
2948:
2949: #ifdef SCO
2950: tmp[k++] = '1';
2951: #else
2952: tmp[k++] = '2';
2953: #endif /* SCO */
2954:
2955: tmp[k++] = ';';
2956: }
2957:
2958: if (xatt & 04) {
2959: tmp[k++] = '3';
2960: tmp[k++] = ';';
2961: }
2962:
2963: if (xatt & 010) {
2964: tmp[k++] = '4';
2965: tmp[k++] = ';';
2966: }
2967:
2968: if (xatt & 020) {
2969: tmp[k++] = '5';
2970: tmp[k++] = ';';
2971: }
2972:
2973: if (xatt & 040) {
2974: tmp[k++] = '6';
2975: tmp[k++] = ';';
2976: }
2977:
2978: if (xatt & 0100) {
2979: tmp[k++] = '7';
2980: tmp[k++] = ';';
2981: }
2982:
2983: if (xatt & 0200) {
2984: tmp[k++] = '8';
2985: tmp[k++] = ';';
2986: }
2987:
2988: if (tmp[k - 1] == ';') k--;
2989:
2990: tmp[k++] = 'm';
2991:
2992: }
2993:
2994: }
2995:
2996: tmp[k++] = linex[l];
2997:
2998: }
2999:
3000: if (max + 1 < n_columns) {
3001: tmp[k++] = ESC;
3002: tmp[k++] = '[';
3003: tmp[k++] = 'K';
3004: }
3005:
3006: tmp[k] = EOL;
3007: k = mcmnd;
3008: mcmnd = 'w';
3009: ch = (*codptr);
3010: *codptr = ',';
3011:
3012: m_output (tmp);
3013:
3014: *codptr = ch;
3015: mcmnd = k;
3016:
3017: k = 0;
3018:
3019: }
3020:
3021: /* 'saved' cursor position */
3022: /* actual cursor position & actual attribute */
3023: /* 'flush' output */
3024: k = 0;
3025:
3026:
3027: #ifndef SCO
3028:
3029: tmp[k++] = ESC; /* restore CursorSave Position */
3030: tmp[k++] = '[';
3031: i = (*scr).csy[(*scr).cs] + 1;
3032:
3033: if (i > 9) tmp[k++] = '0' + i / 10;
3034:
3035: tmp[k++] = '0' + i % 10;
3036: tmp[k++] = ';';
3037:
3038: i = (*scr).csx[(*scr).cs] + 1;
3039:
3040: if (i > 9) tmp[k++] = '0' + i / 10;
3041:
3042: tmp[k++] = '0' + i % 10;
3043: tmp[k++] = 'H';
3044: tmp[k++] = ESC; /* DEC Cursor SAVE */
3045: tmp[k++] = '7';
3046: tmp[k++] = ESC; /* ANSI (?) Cursor SAVE */
3047: tmp[k++] = '[';
3048: tmp[k++] = 's';
3049: tmp[k++] = ESC; /* restore 24/25 line mode */
3050: tmp[k++] = '[';
3051: tmp[k++] = '0' + (*scr).lin24;
3052: tmp[k++] = 'u';
3053: tmp[k++] = ESC; /* restore Scroll area */
3054: tmp[k++] = '[';
3055:
3056: if (((*scr).sc_up) > 8) tmp[k++] = '0' + ((*scr).sc_up + 1) / 10;
3057:
3058: tmp[k++] = '0' + ((*scr).sc_up + 1) % 10;
3059: tmp[k++] = ';';
3060:
3061: if (((*scr).sc_lo) > 8) tmp[k++] = '0' + ((*scr).sc_lo + 1) / 10;
3062:
3063: tmp[k++] = '0' + ((*scr).sc_lo + 1) % 10;
3064: tmp[k++] = 'r';
3065:
3066: #endif /* not SCO */
3067:
3068: #ifndef LINUX
3069: #ifdef COLOR
3070:
3071: tmp[k++] = ESC; /* restore foreground color */
3072: tmp[k++] = '[';
3073: tmp[k++] = '=';
3074:
3075: if (((*scr).col) % 16 > 9) tmp[k++] = '0' + ((*scr).col) % 16 / 10;
3076:
3077: tmp[k++] = '0' + ((*scr).col) % 16 % 10;
3078: tmp[k++] = 'F';
3079: tmp[k++] = ESC; /* restore reverse background color */
3080: tmp[k++] = '[';
3081: tmp[k++] = '=';
3082:
3083: if (((*scr).col) % 16 > 9) tmp[k++] = '0' + ((*scr).col) % 16 / 10;
3084:
3085: tmp[k++] = '0' + ((*scr).col) % 16 % 10;
3086: tmp[k++] = 'I';
3087: tmp[k++] = ESC; /* restore background color */
3088: tmp[k++] = '[';
3089: tmp[k++] = '=';
3090:
3091: if (((*scr).col) / 16 > 9) tmp[k++] = '0' + ((*scr).col) / 16 / 10;
3092:
3093: tmp[k++] = '0' + ((*scr).col) / 16 % 10;
3094: tmp[k++] = 'G';
3095: tmp[k++] = ESC; /* restore reverse foreground color */
3096: tmp[k++] = '[';
3097: tmp[k++] = '=';
3098:
3099: if (((*scr).col) / 16 > 9) tmp[k++] = '0' + ((*scr).col) / 16 / 10;
3100:
3101: tmp[k++] = '0' + ((*scr).col) / 16 % 10;
3102: tmp[k++] = 'H';
3103:
3104: #endif /* COLOR */
3105: #endif /* LINUX */
3106:
3107: tmp[k++] = ESC; /* restore CursorPosition */
3108: tmp[k++] = '[';
3109:
3110: if (ypos[HOME] > 8) tmp[k++] = '0' + (ypos[HOME] + 1) / 10;
3111:
3112: tmp[k++] = '0' + (ypos[HOME] + 1) % 10;
3113: tmp[k++] = ';';
3114:
3115: if (xpos[HOME] > 8) tmp[k++] = '0' + (xpos[HOME] + 1) / 10;
3116:
3117: tmp[k++] = '0' + (xpos[HOME] + 1) % 10;
3118: tmp[k++] = 'H';
3119:
3120: i = UNSIGN ((*scr).att);
3121:
3122: tmp[k++] = ((i & 01) ? SO : SI);
3123: tmp[k++] = ESC; /* restore graphic attributes */
3124: tmp[k++] = '[';
3125:
3126:
3127: #ifdef SCO
3128:
3129: if ((*scr).bw) tmp[k++] = '7';
3130:
3131: tmp[k++] = 'm';
3132: tmp[k++] = ESC;
3133: tmp[k++] = '[';
3134:
3135: i = scosgr (i, (*scr).bw);
3136:
3137: if (i & 02) {
3138: tmp[k++] = '1';
3139: tmp[k++] = ';';
3140: }
3141:
3142: #else
3143:
3144: if (i & 02) {
3145: tmp[k++] = '2';
3146: tmp[k++] = ';';
3147: }
3148:
3149: #endif /* SCO */
3150:
3151: if (i & 04) {
3152: tmp[k++] = '3';
3153: tmp[k++] = ';';
3154: }
3155:
3156: if (i & 010) {
3157: tmp[k++] = '4';
3158: tmp[k++] = ';';
3159: }
3160:
3161: if (i & 020) {
3162: tmp[k++] = '5';
3163: tmp[k++] = ';';
3164: }
3165:
3166: if (i & 040) {
3167: tmp[k++] = '6';
3168: tmp[k++] = ';';
3169: }
3170:
3171: if (i & 0100) {
3172: tmp[k++] = '7';
3173: tmp[k++] = ';';
3174: }
3175:
3176: if (i & 0200) {
3177: tmp[k++] = '8';
3178: tmp[k++] = ';';
3179: }
3180:
3181: if (tmp[k - 1] == ';') k--;
3182:
3183: tmp[k++] = 'm';
3184: tmp[k] = EOL;
3185:
3186: k = mcmnd;
3187: mcmnd = 0;
3188:
3189: m_output (tmp);
3190:
3191: mcmnd = k;
3192:
3193: return;
3194:
3195: } /* end part_ref() */
3196:
3197: /* delayed write for higher system throughput */
3198: void m_output (char *text)
3199: {
3200: static char buffer[2048];
3201: static int p = 0;
3202: char *G;
3203: int i;
3204: int ch;
3205:
3206: if (io == HOME) opnfile[io] = stdout;
3207:
3208: G = SIflag[io] ? G0O[io] : G1O[io];
3209:
3210: i = 0;
3211:
3212: while ((ch = text[i++]) != EOL) {
3213:
3214: ch = UNSIGN (ch);
3215:
3216: if (ESCflag[io] == FALSE && ch >= NUL && ch < 255) ch = G[ch];
3217:
3218: buffer[p++] = ch;
3219:
3220: if (ch == SI) {
3221: SIflag[io] = TRUE;
3222: G = G0O[io];
3223: }
3224:
3225: if (ch == SO) {
3226: SIflag[io] = FALSE;
3227: G = G1O[io];
3228: }
3229:
3230: if (ch == ESC) {
3231: ESCflag[io] = TRUE;
3232: continue;
3233: }
3234:
3235: if (ch == '[' && ESCflag[io]) {
3236: ESCflag[io] = 2;
3237: continue;
3238: }
3239:
3240: if (ch >= '@' && ch < DEL) ESCflag[io] = FALSE;
3241: if (ch != NUL) continue;
3242:
3243: fputs (buffer, opnfile[io]);
3244:
3245: p = 0; /* NUL needs special treatment */
3246:
3247: fputc (NUL, opnfile[io]); /* 'cause unix uses it as delim */
3248:
3249: }
3250:
3251: buffer[p] = NUL;
3252:
3253: if (mcmnd == 'w' && *codptr == ',' && (p < 1536)) return;
3254:
3255: if (fm_nodelay[io]) {
3256:
3257: if (setjmp (sjbuf)) {
3258: merr_raise (NOWRITE);
3259: goto done;
3260: }
3261:
3262: sig_attach (SIGALRM, &ontimo);
3263: alarm (3);
3264:
3265: }
3266:
3267: fputs (buffer, opnfile[io]);
3268:
3269: p = 0;
3270:
3271: if (mcmnd == '*') fputc (EOL, opnfile[io]); /* special treatment for EOL */
3272: if (demomode) fputc (d0char, opnfile[io]);
3273:
3274: fflush (opnfile[io]);
3275:
3276:
3277: done:
3278:
3279: alarm (0); /* reset alarm request */
3280:
3281: return;
3282:
3283: } /* end of m_output() */
3284:
3285:
3286: void write_m (char *text)
3287: {
3288: static char esc = 0; /* esc processing flag */
3289: static char tmp[512];
3290: register int i;
3291: register int j;
3292: register int ch;
3293:
3294: if (io == HOME) {
3295:
3296: opnfile[HOME] = stdout;
3297:
3298: if (frm_filter == FALSE) {
3299: writeHOME (text);
3300: return;
3301: }
3302:
3303: }
3304:
3305: /* 'normal' output for devices other than HOME */
3306: j = 0;
3307: i = 0;
3308:
3309: while ((ch = text[j++]) != EOL) {
3310:
3311: tmp[i++] = ch;
3312:
3313: if (ch >= SP) {
3314:
3315: if (esc == 0) {
3316: xpos[io]++;
3317: continue;
3318: }
3319:
3320: if (ch == '[') {
3321: esc = 2;
3322: continue;
3323: }
3324:
3325: if (ch >= '@' || esc == 1) esc = 0;
3326:
3327: continue;
3328:
3329: }
3330:
3331: esc = (ch == ESC);
3332:
3333: if (ch == LF) {
3334:
3335: ypos[io]++;
3336:
3337: if (frm_crlf[io]) xpos[io] = 0;
3338:
3339: continue;
3340:
3341: }
3342:
3343: if (ch == CR) {
3344: xpos[io] = 0;
3345: continue;
3346: }
3347:
3348: if (ch == BS) {
3349: if (--xpos[io] < 0) xpos[io] = 0;
3350: continue;
3351: }
3352:
3353: if (ch == FF) {
3354:
3355: xpos[io] = 0;
3356: ypos[io] = 0;
3357:
3358: continue;
3359:
3360: }
3361:
3362: if (ch == TAB) {
3363: xpos[io] += 8 - (xpos[io] % 8);
3364: }
3365:
3366: } /* end while */
3367:
3368: tmp[i] = EOL;
3369:
3370: m_output (tmp);
3371:
3372: xpos[io] &= 0377;
3373: ypos[io] &= 0377;
3374:
3375: return;
3376:
3377: } /* end of write_m() */
3378:
3379: /* tab to number 'col' column' */
3380: void write_t (short int col)
3381: {
3382: short int i;
3383: short int j;
3384: char tmp[256]; /* Not tied to STRLEN necessarily*/
3385:
3386: if (col <= xpos[io]) return;
3387: if (col > (sizeof(tmp)-1)) col = (sizeof(tmp)-1); /* guard against buffer overflow */
3388:
3389: j = xpos[io];
3390: i = 0;
3391:
3392: while (j++ < col) tmp[i++] = SP;
3393:
3394: tmp[i] = EOL;
3395:
3396: write_m (tmp);
3397:
3398: return;
3399:
3400: } /* end of write_t() */
3401:
3402: void ontimo (void)
3403: { /* handle timeout (for read) */
3404: longjmp (sjbuf, 1);
3405: } /* end of ontimo() */
3406:
3407: /* Try to read up to 'length' characters from current 'io'
3408: * If 'length' == zero a single character read is performed and
3409: * its $ASCII value is returned in 'stuff'.
3410: * A negative value of 'timeout' means there's no timeout.
3411: * a zero value looks whether a character has been typed in already
3412: * a positive value terminates the read after 'timeout' seconds
3413: * a timeout will set $TEST to TRUE if successfull, FALSE otherwise
3414: *
3415: * timeouts 1 .. 3 are done by polling,
3416: * higher timeouts request an alarm. that different treatment is
3417: * necessary, because timeouts may be up to 2 seconds early.
3418: * polling on higher timeouts would be require too much system resources
3419: * just for nothing.
3420: * maximum timeout is 32767 (2**15-1) seconds (about 9 hrs)
3421: * There are no provisions to handle overflow.
3422: */
3423: void read_m (char *stuff, long read_timeout, short read_timeoutms, short length)
3424: {
3425: static char previous[2][256] = {{EOL}, {EOL}}; /* all static: longjmp! */
3426: static short p_toggle = 0;
3427: static char term_key[256] = {EOL, EOL};
3428: static short int escptr;
3429: static short int single;
3430: static short int timoflag; /* timeout flag */
3431: static short int i;
3432: static int ch;
3433:
3434: #ifdef USE_GETTIMEOFDAY
3435: static struct timeval timebuffer;
3436: #else
3437: static struct timeb timebuffer;
3438: #endif
3439:
3440: escptr = 0;
3441: single = 0;
3442: timoflag = FALSE;
3443:
3444: /* Not necessarily tied to STRLEN */
3445:
3446: if (length > 255) length = 255;
3447:
3448: stuff[length] = EOL;
3449: stuff[0] = EOL;
3450:
3451: if (length < 1) single = length = 1;
3452:
3453: if (io == HOME) opnfile[HOME] = stdin;
3454:
3455: if (io == HOME && !frm_filter) {
3456:
3457: if (NOTYPEAHEAD) fflush (stdin); /* ignore previous input */
3458:
3459: if (read_timeout >= 0) {
3460:
3461: test = TRUE;
3462:
3463: if (read_timeout > 2 && read_timeout <= 32767) { /* cave small/large values */
3464:
3465: if (setjmp (sjbuf)) {
3466:
3467: test = FALSE;
3468: timoflag = TRUE;
3469:
3470: goto done;
3471:
3472: }
3473:
3474: sig_attach (SIGALRM, &ontimo);
3475: alarm ((unsigned) read_timeout);
3476:
3477: read_timeout = (-1L);
3478:
3479: }
3480: else {
3481:
3482: if (read_timeout >= 0) {
3483:
3484:
3485: #ifdef USE_GETTIMEOFDAY
3486:
3487: gettimeofday (&timebuffer, NULL); /* get current time */
3488:
3489: read_timeout += timebuffer.tv_sec; /* target time */
3490: read_timeoutms += timebuffer.tv_usec;
3491:
3492: #else
3493:
3494: ftime (&timebuffer); /* get current time */
3495:
3496: read_timeout += timebuffer.time; /* target time */
3497: read_timeoutms += timebuffer.millitm;
3498:
3499: #endif
3500:
3501: if (read_timeoutms > 999) {
3502: read_timeoutms -= 1000;
3503: read_timeout++;
3504: }
3505:
3506: }
3507:
3508: }
3509:
3510: }
3511:
3512: zb[0] = EOL;
3513: zb[1] = EOL;
3514: zcc = FALSE;
3515:
3516: for (i = 0; i < length; i++) {
3517:
3518: if (merr () == INRPT) {
3519:
3520: if (--i < 0) i = 0;
3521: stuff[i] = EOL;
3522:
3523: break;
3524: }
3525:
3526: if (evt_async_enabled && (merr () == ASYNC)) break;
3527:
3528: /* TODO: remove old FreeM "journaling" nonsense here */
3529: if (jour_flag < 0) {
3530:
3531: if ((ch = fgetc (jouraccess)) == EOF) {
3532:
3533: jour_flag = 0;
3534:
3535: fclose (jouraccess);
3536:
3537: jouraccess = NULL;
3538:
3539: }
3540: else {
3541:
3542: if (ch == SI) {
3543: test = FALSE;
3544: break;
3545: } /* timeout char */
3546:
3547: }
3548:
3549: }
3550:
3551:
3552: if (jour_flag >= 0) {
3553:
3554: if (ug_buf[HOME][0] != EOL) {
3555: ch = ug_buf[HOME][0];
3556: stcpy (ug_buf[HOME], &ug_buf[HOME][1]);
3557: }
3558: else {
3559: if (read_timeout >= 0)
3560: #ifdef SYSFIVE
3561: {
3562: if (rdchk0 (&ch) == 1) {
3563: }
3564: #else
3565: {
3566:
3567: if (rdchk (fileno (stdin)) > 0)
3568: ch = getc (stdin);
3569: #endif /* SYSFIVE */
3570: else {
3571:
3572: if (read_timeout < 0) {
3573:
3574: test = FALSE;
3575: timoflag = TRUE;
3576: stuff[i] = EOL;
3577:
3578: break;
3579:
3580: }
3581: #ifdef USE_GETTIMEOFDAY
3582: gettimeofday (&timebuffer, NULL); /* get current time */
3583: if ((read_timeout < timebuffer.tv_sec) ||
3584: ((read_timeout == timebuffer.tv_sec) &&
3585: (read_timeoutms <= timebuffer.tv_usec))) {
3586: #else
3587: ftime (&timebuffer); /* get current time */
3588: if ((read_timeout < timebuffer.time) ||
3589: ((read_timeout == timebuffer.time) &&
3590: (read_timeoutms <= timebuffer.millitm))) {
3591: #endif
3592:
3593: test = FALSE;
3594: timoflag = TRUE;
3595: stuff[i] = EOL;
3596: break;
3597: }
3598:
3599: i--;
3600: continue;
3601:
3602: }
3603: }
3604: else {
3605: ch = getc (stdin);
3606: }
3607: }
3608: }
3609:
3610: if (UNSIGN (ch) == 255) {
3611: i--;
3612: continue;
3613: } /* illegal char */
3614:
3615: if (CONVUPPER) { /* convert to uppercase ? */
3616: if (ch >= 'a' && ch <= 'z') ch -= 32;
3617: }
3618:
3619: /* on CTRL/O suspend execution until next CTRL/O */
3620: if (ch == SI && CTRLOPROC) {
3621:
3622: printf ("\033[8p\033[4u"); /* screen dark, timeout off */
3623:
3624: while ((ch = getc (stdin)) != SI); /* loop until CTRL/O */
3625:
3626: printf ("\033[9p\033[5u"); /* screen light, timeout on */
3627:
3628: i--;
3629: continue;
3630: }
3631:
3632: zb[0] = ch;
3633:
3634: if (single == 0) {
3635:
3636: if (ch == ESC) {
3637:
3638: i--;
3639:
3640: term_key[0] = ESC;
3641: escptr = 1;
3642:
3643: continue;
3644:
3645: }
3646:
3647: if (escptr) {
3648:
3649: short j;
3650:
3651: i--;
3652:
3653: term_key[escptr++] = ch;
3654: term_key[escptr] = EOL;
3655:
3656: if (ch == '[' && escptr == 2) continue; /* CSI */
3657:
3658: /* DECs PF1..PF4 and Keypad application */
3659: if (ch == 'O' && PF1flag && escptr == 2) continue;
3660: if (escptr > 2 && (ch < '@' || ch >= DEL)) continue;
3661:
3662: if (ESCSEQPROC) {
3663: stcpy (zb, term_key);
3664: break;
3665: }
3666:
3667: if (escptr == 2) {
3668:
3669: if (ch == '9') { /* to begin of string */
3670:
3671: while (i >= 0) {
3672:
3673: if (ECHOON) {
3674:
3675: if (xpos[HOME] > 0) {
3676: write_m ("\033[D\201");
3677: }
3678: else {
3679: write_m ("\033M\033[79C\201");
3680: }
3681:
3682: }
3683:
3684: i--;
3685:
3686: }
3687:
3688: escptr = 0;
3689:
3690: continue;
3691:
3692: }
3693: else if (ch == ':') { /* to end of string */
3694:
3695: while (stuff[i] != EOL && stuff[i + 1] != EOL) {
3696:
3697: if (ECHOON) {
3698:
3699: if (xpos[HOME] < (n_columns - 1)) {
3700: write_m ("\033[C\201");
3701: }
3702: else {
3703: write_m ("\012\015\201");
3704: }
3705:
3706: }
3707:
3708: i++;
3709:
3710: }
3711:
3712: escptr = 0;
3713:
3714: continue;
3715:
3716: }
3717:
3718: }
3719:
3720: if (escptr == 3) {
3721:
3722: if (ch == 'D') { /* CUB left arrow */
3723:
3724: if (i >= 0) {
3725:
3726: if (ECHOON) {
3727:
3728: if (xpos[HOME] > 0) {
3729: write_m (term_key);
3730: }
3731: else {
3732: write_m ("\033M\033[79C\201");
3733: }
3734:
3735: }
3736:
3737: i--;
3738:
3739: }
3740:
3741: escptr = 0;
3742:
3743: continue;
3744:
3745: }
3746:
3747: if (stuff[i + 1] == EOL) {
3748: escptr = 0;
3749: continue;
3750: }
3751:
3752: if (ch == 'C') { /* CUF right arrow */
3753:
3754: if (ECHOON) {
3755:
3756: if (xpos[HOME] < (n_columns - 1)) {
3757: write_m (term_key);
3758: }
3759: else {
3760: write_m ("\012\015\201");
3761: }
3762:
3763: }
3764:
3765: i++;
3766:
3767: escptr = 0;
3768:
3769: continue;
3770:
3771: }
3772:
3773: if (ch == 'P') { /* DCH Delete Character */
3774:
3775: ch = i + 1;
3776:
3777: if (stuff[ch] != EOL) {
3778: while ((stuff[ch] = stuff[ch + 1]) != EOL) ch++;
3779: }
3780:
3781: if (ECHOON) {
3782:
3783: ch = xpos[HOME] + 1;
3784: j = ypos[HOME] + 1;
3785:
3786: stcpy (term_key, &stuff[i + 1]);
3787: stcat (term_key, " \033[\201");
3788: intstr (&term_key[stlen (term_key)], j);
3789: stcat (term_key, ";\201");
3790: intstr (&term_key[stlen (term_key)], ch);
3791: stcat (term_key, "H\201");
3792:
3793: write_m (term_key);
3794:
3795: }
3796:
3797: escptr = 0;
3798:
3799: continue;
3800:
3801: }
3802:
3803: if (ch == '@') { /* ICH Insert Character */
3804:
3805: ch = i;
3806: while (stuff[ch++] != EOL);
3807:
3808: while (ch > i) {
3809: stuff[ch] = stuff[ch - 1];
3810: ch--;
3811: }
3812:
3813: stuff[i + 1] = SP;
3814:
3815: if (ECHOON) {
3816:
3817: ch = xpos[HOME] + 1;
3818: j = ypos[HOME] + 1;
3819:
3820: stcpy (term_key, &stuff[i + 1]);
3821: stcat (term_key, "\033[\201");
3822: intstr (&term_key[stlen (term_key)], j);
3823: stcat (term_key, ";\201");
3824: intstr (&term_key[stlen (term_key)], ch);
3825: stcat (term_key, "H\201");
3826:
3827: write_m (term_key);
3828:
3829: }
3830:
3831: escptr = 0;
3832:
3833: continue;
3834:
3835: }
3836: }
3837:
3838: /* VT100 Functionkey */
3839: if (ch == '~' && (escptr == 4 || escptr == 5)) {
3840:
3841: j = term_key[2] - '0';
3842:
3843: if (term_key[3] != ch) j = j * 10 + term_key[3] - '0';
3844: if (j < 1 || j > 44) j = 0;
3845:
3846: }
3847: else {
3848: /* SCO Functionkey */
3849: j = find ("@ABCDFGHIJKLMNOP0_dTVX ;\"#$%&\'<=*+,-./123UWY\201", &term_key[1]);
3850: }
3851:
3852: escptr = 0;
3853:
3854: /* key unknown or without a value */
3855: if (j == 0 || zfunkey[j - 1][0] == EOL) continue;
3856:
3857: /* put key in input buffer, ignore overflow */
3858: {
3859: char tmp[256];
3860:
3861: stcpy (tmp, ug_buf[HOME]);
3862: stcpy (ug_buf[HOME], zfunkey[--j]);
3863: stcat (ug_buf[HOME], tmp);
3864: }
3865:
3866: continue;
3867: }
3868:
3869: term_key[0] = ch;
3870: term_key[1] = EOL;
3871:
3872: if (find (LineTerm, term_key)) break;
3873:
3874: if (ch == BS || ch == DEL) {
3875:
3876: if (stuff[i] != EOL) { /* DEL within string */
3877:
3878: if (ch == BS && i > 0) {
3879:
3880: if (ECHOON) {
3881:
3882: if (xpos[HOME] > 0) {
3883: write_m ("\033[D\201");
3884: }
3885: else {
3886: write_m ("\033M\033[79C\201");
3887: }
3888:
3889: }
3890:
3891: i--;
3892:
3893: }
3894:
3895: ch = i;
3896: if (stuff[ch] != EOL) {
3897: while ((stuff[ch] = stuff[ch + 1]) != EOL) ch++;
3898: }
3899:
3900: if (ECHOON) {
3901:
3902: int j;
3903:
3904: ch = xpos[HOME] + 1;
3905: j = ypos[HOME] + 1;
3906:
3907: stcpy (term_key, &stuff[i]);
3908: stcat (term_key, " \033[\201");
3909: intstr (&term_key[stlen (term_key)], j);
3910: stcat (term_key, ";\201");
3911: intstr (&term_key[stlen (term_key)], ch);
3912: stcat (term_key, "H\201");
3913:
3914: write_m (term_key);
3915:
3916: }
3917:
3918: continue;
3919:
3920: }
3921:
3922: if (i > 0) {
3923:
3924: if (ECHOON) {
3925:
3926: if (DELMODE) {
3927:
3928: if (xpos[HOME] > 0) {
3929: write_m ("\010 \010\201");
3930: }
3931: else {
3932: write_m ("\033M\033[79C\033[P\201");
3933: }
3934:
3935: } else {
3936: write_m ("\\\201");
3937: }
3938:
3939: }
3940:
3941: i--;
3942:
3943: ch = i;
3944:
3945: while ((stuff[ch] = stuff[ch + 1]) != EOL) ch++;
3946:
3947: }
3948: else if (DELEMPTY) {
3949:
3950: /* empty string delete? */
3951: stuff[0] = EOL;
3952: i = 1;
3953: term_key[0] = ch;
3954:
3955: break;
3956:
3957: }
3958:
3959: i--;
3960:
3961: continue;
3962:
3963: }
3964:
3965: if (ch == NAK || ch == DC2) { /* CTRL/U deletes all input */
3966:
3967: while (stuff[i] != EOL) {
3968:
3969: if (ECHOON) {
3970:
3971: if (xpos[HOME] < (n_columns - 1)) {
3972: write_m ("\033[C\201");
3973: }
3974: else {
3975: write_m ("\012\015\201");
3976: }
3977:
3978: }
3979:
3980: i++;
3981:
3982: }
3983:
3984: while (i > 0) {
3985:
3986: if (ECHOON) {
3987:
3988: if (DELMODE) {
3989:
3990: if (xpos[HOME] > 0) {
3991: write_m ("\010 \010\201");
3992: }
3993: else {
3994: write_m ("\033M\033[79C\033[P\201");
3995: }
3996:
3997: }
3998: else {
3999: write_m ("\\\201");
4000: }
4001:
4002: }
4003:
4004: stuff[i--] = EOL;
4005:
4006: }
4007:
4008: stuff[i--] = EOL;
4009:
4010: if (ch == NAK) continue;
4011:
4012: /* (ch==DC2) *//* CTRL/R Retypes last input */
4013:
4014: i = stcpy (stuff, previous[p_toggle]);
4015:
4016: stuff[i--] = EOL;
4017:
4018: toggle (p_toggle);
4019:
4020: if (ECHOON) write_m (stuff);
4021:
4022: continue;
4023: }
4024:
4025: if (ch == STX && (zbreakon || hardcopy)) {
4026:
4027: if (zbreakon) zbflag = TRUE;
4028:
4029: if (i > 0) {
4030: if (ECHOON) write_m ("\010 \010\201");
4031: }
4032:
4033: i--;
4034:
4035: continue;
4036:
4037: }
4038:
4039: if (ch == BrkKey) { /* CTRL/C may interrupt */
4040:
4041: i--;
4042:
4043: if (breakon) {
4044:
4045: stuff[i] = EOL;
4046: merr_raise (INRPT);
4047:
4048: return;
4049:
4050: }
4051:
4052: continue;
4053: }
4054:
4055: /* ignore non programmed CTRL/ key ?? */
4056: if (ch < SP && (ch != TAB || nstx) && NOCTRLS) { /* TAB may be a programmed key */
4057: i--;
4058: continue;
4059: }
4060:
4061: } /* if (single == 0) */
4062:
4063: if (stuff[i] == EOL) stuff[i + 1] = EOL;
4064: if (ch < 255) ch = (SIflag[io] ? G0I[io] : G1I[io])[UNSIGN (ch)];
4065:
4066: stuff[i] = ch;
4067:
4068: if (ECHOON) {
4069:
4070: term_key[0] = ch;
4071: term_key[1] = EOL;
4072:
4073: write_m (term_key);
4074:
4075: }
4076:
4077: } /* ??????????? may need to run through preprocessor to see where the heck this goes */
4078: }
4079: else { /* $io != HOME */
4080: int fd;
4081: int fdstat;
4082:
4083: fd = 0;
4084:
4085:
4086: #if defined(SYSFIVE) && !defined(__AMIGA) && !defined(MSDOS)
4087:
4088: if (read_timeout >= 0) {
4089:
4090: fd = fileno (opnfile[io]);
4091: fdstat = fcntl (fd, F_GETFL);
4092:
4093: fcntl (fd, F_SETFL, fdstat | O_NDELAY);
4094:
4095: }
4096:
4097: #endif /* SYSFIVE */
4098:
4099: for (i = 0; i < length; i++) {
4100:
4101: if (merr () == INRPT) {
4102:
4103: if (--i < 0) i = 0;
4104:
4105: stuff[i] = EOL;
4106:
4107: break;
4108:
4109: }
4110:
4111: if (ug_buf[io][0] != EOL) {
4112: ch = ug_buf[io][0];
4113: stcpy (ug_buf[io], &ug_buf[io][1]);
4114: }
4115: else if (read_timeout >= 0)
4116: {
4117: test = TRUE;
4118:
4119: #ifdef SYSFIVE
4120: if (fread (&ch, 1, 1, opnfile[io]) < 1)
4121: #else
4122: if (rdchk (fileno (opnfile[io])) == 0 || ((ch = fgetc (opnfile[io])) == EOF))
4123: #endif /* SYSFIVE */
4124:
4125: {
4126: if (--read_timeout < 0) {
4127:
4128: test = FALSE;
4129: timoflag = TRUE;
4130: stuff[i] = EOL;
4131:
4132: break;
4133:
4134: }
4135:
4136: sleep (1);
4137:
4138: i--;
4139:
4140: continue;
4141:
4142: }
4143:
4144: ch = UNSIGN (ch);
4145: }
4146: else {
4147: ch = fgetc (opnfile[io]);
4148: }
4149:
4150: stuff[i] = ch;
4151:
4152: if (ch == EOF) {
4153: /* EOF halts filtered mps */
4154: if ((io == HOME) && frm_filter) merr_raise (INRPT);
4155:
4156: stuff[i] = EOL;
4157:
4158: break;
4159: }
4160:
4161: if (single) break;
4162:
4163: if (ch == LF && frm_crlf[io]) {
4164: i--;
4165: continue;
4166: }
4167:
4168: if ((ch == CR) || (ch == LF)) {
4169: int ch0;
4170:
4171: stuff[i] = EOL;
4172:
4173: /* if input terminates with CR/LF or LF/CR take both */
4174: /* as a single termination character. So it is possible */
4175: /* to get correct input from files written by mumps */
4176: /* itself with CR/LF line termination */
4177:
4178: #if defined(SYSFIVE) && !defined(__AMIGA) && !defined(MSDOS)
4179:
4180: if (fd == 0) {
4181:
4182: fd = fileno (opnfile[io]);
4183: fdstat = fcntl (fd, F_GETFL);
4184:
4185: fcntl (fd, F_SETFL, fdstat | O_NDELAY);
4186:
4187: }
4188:
4189: if (fread (&ch0, 1, 1, opnfile[io]) == 1) {
4190: ch0 = UNSIGN (ch0);
4191:
4192: #else
4193: #if !defined(__AMIGA) && !defined(MSDOS)
4194:
4195: if (rdchk (fileno (opnfile[io])) == 1) {
4196: ch0 = fgetc (opnfile[io]);
4197:
4198: #else
4199:
4200: #if defined(__AMIGA)
4201:
4202: if (rdchk0 (fileno (opnfile[io])) == 1) {
4203: ch0 = fgetc (opnfile[io]);
4204: #endif
4205:
4206: #endif /* __AMIGA */
4207:
4208: #if defined(MSDOS)
4209: if (1) {
4210: ch0 = fgetc (opnfile[io]);
4211: #endif
4212:
4213: #endif /* SYSFIVE */
4214:
4215: if ((ch == CR && ch0 != LF) || (ch == LF && ch0 != CR))
4216: ungetc (ch0, opnfile[io]);
4217: }
4218:
4219: break;
4220: }
4221:
4222: if (UNSIGN (stuff[i]) < 255)
4223: stuff[i] = (SIflag[io] ? G0I[io] : G1I[io])[UNSIGN (stuff[i])];
4224: }
4225:
4226: #if defined(SYSFIVE) && !defined(__AMIGA)
4227: if (fd) fcntl (fd, F_SETFL, fdstat);
4228: #endif /* SYSFIVE */
4229:
4230: } /* if ((ch == CR) || (ch == LF)) */
4231:
4232:
4233: done:
4234:
4235: alarm (0); /* reset alarm request */
4236:
4237: if (io == HOME && jour_flag > 0) {
4238:
4239: char tmp[256];
4240:
4241: tmp[stcpy (tmp, stuff)] = NUL;
4242: fputs (tmp, jouraccess);
4243:
4244: if (timoflag) {
4245:
4246: tmp[0] = SI;
4247: tmp[1] = NUL; /* CTRL/O as timeout char */
4248:
4249: fputs (tmp, jouraccess);
4250:
4251: }
4252: else if ((i < length) || (stuff[0] == NUL && zb[0] == ESC)) {
4253:
4254: /* save termination char if meaningful */
4255: tmp[stcpy (tmp, zb)] = NUL;
4256: fputs (tmp, jouraccess);
4257:
4258: }
4259:
4260: }
4261:
4262: if (single) { /* to ASCII */
4263:
4264: if (timoflag) {
4265: stuff[0] = '-';
4266: stuff[1] = '1';
4267: stuff[2] = EOL;
4268: }
4269: else {
4270: intstr (stuff, UNSIGN (stuff[0]));
4271: }
4272:
4273: }
4274: else if (io == HOME && stuff[0] != EOL) {
4275: stcpy (previous[toggle (p_toggle)], stuff);
4276: }
4277:
4278: return;
4279:
4280: } /* end of read_m() */
4281:
4282: #if defined(SYSFIVE)
4283: /* UNIX system V has no 'rdchk' function. We must do it ourselves */
4284:
4285: #if !defined(__AMIGA) && !defined(MSDOS)
4286:
4287: int rdchk0 (int *data)
4288: {
4289: static int x;
4290: static int firsttime = TRUE;
4291: int retcode;
4292: char ch;
4293:
4294: if (firsttime) {
4295: x = fcntl (0, F_GETFL);
4296: firsttime = FALSE;
4297: }
4298:
4299: fcntl (0, F_SETFL, x | O_NDELAY);
4300:
4301: retcode = read (0, &ch, 1);
4302:
4303: fcntl (0, F_SETFL, x);
4304:
4305: *data = (retcode > 0) ? ch : NUL;
4306:
4307: return retcode;
4308:
4309: } /* end rdchk0() */
4310:
4311: #else
4312:
4313: int rdchk0 (int *data)
4314: {
4315: /* TODO: flesh out on m68k-amigaos */
4316: return TRUE;
4317: }
4318:
4319: #endif
4320:
4321: /******************************************************************************/
4322: /* under XENIX the system has an intrinsic function 'locking'. */
4323: /* under UNIX System V it must be done with fcntl. */
4324: /* the difference is, that the XENIX locking blocks all other accesses */
4325: /* whereas UNIX System V gives only protection if all users of a file */
4326: /* use 'locking'. */
4327: /* since 'fcntl' is not properly documented, the outcome in any cases of */
4328: /* errors is uncertain. */
4329:
4330: #ifdef AMIGA68K
4331:
4332: int locking (int fd, int action, long count)
4333: {
4334: /* TODO: flesh out on m68k-amigaos */
4335: return 0;
4336: }
4337:
4338: #else
4339:
4340: /* fd = file descriptor of file to be locked */
4341: /* action = action to be performed */
4342: /* count area to be locked */
4343: int locking (int fd, int action, long count)
4344: {
4345:
4346: struct flock lock;
4347:
4348: /* skip locking if we own the TP semaphore */
4349: if (shm_config->hdr->tp_owner == pid) {
4350: return 0;
4351: }
4352:
4353: lock.l_whence = 1; /* lock from current position */
4354: lock.l_start = 0;
4355: lock.l_len = count;
4356: lock.l_pid = getpid ();
4357:
4358: if (lonelyflag) return 0; /* no LOCK if single user */
4359:
4360: switch (action) {
4361:
4362:
4363: case 0: /* LK_UNLK free previously locked area */
4364:
4365: lock.l_type = F_UNLCK;
4366: fcntl (fd, F_SETLK, &lock);
4367:
4368: break;
4369:
4370:
4371: case 1: /* LK_LOCK lock against others reading and writing my data */
4372:
4373: lock.l_type = F_WRLCK;
4374: fcntl (fd, F_SETLKW, &lock);
4375:
4376: break;
4377:
4378:
4379: case 2: /* LK_NBLCK lock against others reading and writing my data, don't block */
4380:
4381: lock.l_type = F_WRLCK;
4382: fcntl (fd, F_SETLK, &lock);
4383:
4384: break;
4385:
4386:
4387: case 3: /* LK_RLCK lock against others writing my data */
4388:
4389: lock.l_type = F_RDLCK;
4390: fcntl (fd, F_SETLKW, &lock);
4391:
4392: break;
4393:
4394:
4395: case 4: /* LK_NBRLCK lock against others writing my data, don't block */
4396:
4397: lock.l_type = F_RDLCK;
4398: fcntl (fd, F_SETLK, &lock);
4399:
4400: break;
4401:
4402: }
4403:
4404: return 0; /* action properly performed */
4405:
4406: } /* end locking() */
4407:
4408: #endif
4409:
4410: #ifdef OLDUNIX
4411:
4412: /* set io_parameters to mumps/unix conventions */
4413: /* action: 0 = UNIX; 1 = MUMPS */
4414: void set_io (short action)
4415: {
4416: if (lio_mode == action) return;
4417:
4418: static char del;
4419: static char fs;
4420: struct termio tpara;
4421:
4422: if (frm_filter) return; /* nothing special if used as filter */
4423:
4424: fflush (stdin);
4425: fflush (stdout);
4426: fflush (stderr);
4427:
4428: ioctl (0, TCGETA, &tpara); /* get paramters */
4429:
4430: if (action == UNIX) {
4431:
4432: lio_mode = UNIX;
4433:
4434: tpara.c_lflag |= (ECHO | ICANON); /* enable echo/no cbreak mode */
4435: tpara.c_iflag |= ICRNL; /* cr-lf mapping */
4436: tpara.c_oflag |= ONLCR; /* cr-lf mapping */
4437: tpara.c_cc[VINTR] = del; /* interrupt */
4438: tpara.c_cc[VQUIT] = fs; /* quit */
4439: tpara.c_cc[VMIN] = EOT;
4440: tpara.c_cc[VTIME] = -1;
4441:
4442: }
4443: else { /* action == MUMPS */
4444:
4445: lio_mode = MUMPS;
4446:
4447: tpara.c_lflag &= (~(ECHO | ICANON)); /* disable echo/cbreak mode */
4448: tpara.c_iflag &= ~ICRNL; /* cr-lf mapping */
4449: tpara.c_oflag &= ~ONLCR; /* cr-lf mapping */
4450: del = tpara.c_cc[VINTR]; /* save previous state of */
4451: fs = tpara.c_cc[VQUIT]; /* quit and interrupt */
4452: tpara.c_cc[VINTR] = BrkKey; /* interrupt = CTRL/C */
4453: tpara.c_cc[VQUIT] = (zbreakon || hardcopy) ? STX : -1; /* zbreak/hardcopy */
4454: tpara.c_cc[VMIN] = 1;
4455: tpara.c_cc[VTIME] = 1;
4456:
4457: }
4458:
4459: ioctl (0, TCSETA, &tpara);
4460:
4461: return;
4462:
4463: } /* end of set_io() */
4464:
4465:
4466: /* break_char: */
4467: /* -1 = break disabled */
4468: /* ETX = MUMPS break */
4469: /* DEL = UNIX quit */
4470: void set_break (short break_char)
4471: {
4472: #if !defined(__OS2__)
4473: struct termio arg;
4474:
4475: ioctl (0, TCGETA, &arg);
4476:
4477: arg.c_cc[VINTR] = break_char; /* interrupt = CTRL/C */
4478:
4479: ioctl (0, TCSETA, &arg);
4480: #endif
4481: return;
4482:
4483: } /* end of set_break() */
4484:
4485: /* quit_char: */
4486: /* -1 = quit disabled */
4487: /* STX = MUMPS CTRL/B */
4488: /* DEL = UNIX quit */
4489: void set_zbreak (short quit_char)
4490: {
4491: #if !defined(__OS2__)
4492: struct termio arg;
4493:
4494: ioctl (0, TCGETA, &arg);
4495:
4496: arg.c_cc[VQUIT] = quit_char;
4497:
4498: ioctl (0, TCSETA, &arg);
4499: #endif
4500: return;
4501:
4502: } /* end of set_zbreak() */
4503:
4504: #else
4505:
4506: void set_io (short action) /* set io_parameters to mumps/unix conventions */
4507: {
4508: static struct termios unixtermio;
4509: struct termios termios_p;
4510:
4511: if (lio_mode == action) return;
4512:
4513: if (frm_filter) return; /* nothing special if used as filter */
4514:
4515: if (action == UNIX) {
4516: lio_mode = UNIX;
4517:
4518: tcsetattr (0, TCSADRAIN, &unixtermio);
4519: }
4520: else { /* action == MUMPS */
4521: lio_mode = MUMPS;
4522:
4523: tcgetattr (0, &unixtermio); /* get unix paramters */
4524: tcgetattr (0, &termios_p); /* get paramters */
4525:
4526: termios_p.c_lflag &= (~(ECHO | ICANON)); /* disable echo/cbreak mode */
4527: termios_p.c_iflag &= ~ICRNL; /* cr-lf mapping */
4528: termios_p.c_oflag &= ~ONLCR; /* cr-lf mapping */
4529: termios_p.c_cc[VINTR] = BrkKey; /* interrupt = CTRL/C */
4530: termios_p.c_cc[VQUIT] = (zbreakon || hardcopy) ? STX : -1; /* zbreak/hardcopy */
4531: termios_p.c_cc[VMIN] = 1;
4532: termios_p.c_cc[VTIME] = 1;
4533:
4534: tcsetattr (0, TCSADRAIN, &termios_p); /* set paramters */
4535:
4536: }
4537:
4538: return;
4539:
4540: } /* end of set_io() */
4541:
4542: void set_break (short break_char)
4543: {
4544:
4545: #if !defined(__OS2__)
4546: struct termios termios_p;
4547:
4548: tcgetattr (0, &termios_p);
4549:
4550: termios_p.c_cc[VINTR] = break_char; /* interrupt = CTRL/C */
4551:
4552: tcsetattr (0, TCSADRAIN, &termios_p); /* set paramters */
4553: #endif
4554: return;
4555:
4556: } /* end of set_break() */
4557:
4558: void set_zbreak (short quit_char)
4559: {
4560: #if !defined(__OS2__)
4561: struct termios termios_p;
4562:
4563: tcgetattr (0, &termios_p);
4564:
4565: termios_p.c_cc[VQUIT] = quit_char;
4566:
4567: tcsetattr (0, TCSADRAIN, &termios_p); /* set paramters */
4568: #endif
4569: return;
4570:
4571: } /* end of set_zbreak() */
4572:
4573: #endif /* OLDUNIX */
4574:
4575: #else
4576:
4577: /* same for XENIX */
4578: void set_io (short action) /* set io_parameters to mumps/unix conventions */
4579: {
4580: static char del;
4581: static char fs;
4582: struct sgttyb tt;
4583: struct tchars tc;
4584:
4585: if (frm_filter) return; /* nothing special if used as filter */
4586:
4587: fflush (stdin);
4588: fflush (stdout);
4589: fflush (stderr);
4590:
4591: ioctl (0, TIOCGETP, &tt);
4592: ioctl (0, TIOCGETC, &tc);
4593:
4594: if (action == UNIX) {
4595:
4596: tt.sg_flags &= ~02; /* no cbreak mode */
4597: tt.sg_flags |= (010 | 020); /* echo ; CR to LF map */
4598: tc.t_quitc = fs; /* quit */
4599: tc.t_intrc = del; /* interrupt */
4600:
4601: /* we desperately tried to do it with DEL - but it didn't work */
4602:
4603: }
4604: else { /* action == MUMPS */
4605:
4606: tt.sg_flags |= 02; /* cbreak mode */
4607: tt.sg_flags &= (~010 & ~020); /* 10 no echo; 20 no CR map */
4608: del = tc.t_intrc; /* save previous state of */
4609: fs = tc.t_quitc; /* quit and interrupt */
4610: tc.t_intrc = BrkKey; /* interrupt = CTRL/C */
4611: tc.t_quitc = (zbreakon || hardcopy) ? STX : -1; /* zbreak/hardcopy */
4612:
4613: }
4614:
4615: ioctl (0, TIOCSETP, &tt);
4616: ioctl (0, TIOCSETC, &tc);
4617:
4618: } /* end of set_io() */
4619:
4620: void set_break (short break_char)
4621: {
4622: struct tchars tc;
4623:
4624: ioctl (0, TIOCGETC, &tc);
4625:
4626: tc.t_intrc = break_char;
4627:
4628: ioctl (0, TIOCSETC, &tc);
4629:
4630: return;
4631:
4632: } /* end of set_break */
4633:
4634: void set_zbreak (short quit_char)
4635: {
4636: struct tchars tc;
4637:
4638:
4639: ioctl (0, TIOCGETC, &tc);
4640:
4641: tc.t_quitc = quit_char;
4642:
4643: ioctl (0, TIOCSETC, &tc);
4644:
4645: return;
4646:
4647: } /* end of set_zbreak */
4648:
4649: #endif /* SYSFIVE */
4650:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>