File:  [Coherent Logic Development] / freem / src / service.c
Revision 1.3: download - view: text, annotated - select for diffs
Tue Feb 25 18:55:13 2025 UTC (7 months ago) by snw
Branches: MAIN
CVS tags: HEAD
Attempt to fix termio issue on FreeBSD/NetBSD

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

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