File:  [Coherent Logic Development] / freem / src / service.c
Revision 1.7: download - view: text, annotated - select for diffs
Sun Mar 9 19:50:47 2025 UTC (7 months, 1 week ago) by snw
Branches: MAIN
CVS tags: v0-62-2, v0-62-1, v0-62-0, HEAD
Second phase of REUSE compliance and header reformat

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>