Annotation of freem/src/service.c, revision 1.13

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

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