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