File:  [Coherent Logic Development] / freem / src / service.c
Revision 1.13: download - view: text, annotated - select for diffs
Wed Apr 9 19:52:02 2025 UTC (3 months, 3 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Eliminate as many warnings as possible while building with -Wall

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

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