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