File:  [Coherent Logic Development] / freem / src / service.c
Revision 1.14: download - view: text, annotated - select for diffs
Wed Jan 7 19:51:33 2026 UTC (2 months, 3 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Fix segfault in reverse $QUERY

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

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