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