home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / pine3.07 / pico / tcap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-30  |  12.3 KB  |  622 lines

  1. /*
  2.  * Program:    Display routines
  3.  *
  4.  * Modifier:    Michael Seibel
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: mikes@cac.washington.edu
  11.  *
  12.  * Date:    19 Jan 1991
  13.  * Last Edited:    6 Jan 1992
  14.  *
  15.  * Copyright 1991 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35. /*    tcap:    Unix V5, V7 and BS4.2 Termcap video driver
  36.         for MicroEMACS
  37. */
  38.  
  39. #define    termdef    1            /* don't define "term" external */
  40.  
  41. #include <stdio.h>
  42. #include    "osdep.h"
  43. #include    "estruct.h"
  44. #include        "edef.h"
  45.  
  46. #ifdef    POSIX
  47. #include    <termios.h>
  48. #endif
  49.  
  50. #if TERMCAP
  51. #include <sys/ioctl.h>
  52. #include        "pico.h"
  53. #include        <signal.h>
  54. #include        <sgtty.h>
  55. #ifndef    att
  56. #include        <sys/ttydev.h>
  57. #endif
  58.  
  59. #define NROW    24
  60. #define NCOL    80
  61. #define    MARGIN    8
  62. #define    SCRSIZ    64
  63. #define BEL     0x07
  64. #define ESC     0x1B
  65.  
  66. extern int      ttopen();
  67. extern int      ttgetc();
  68. extern int      ttputc();
  69. extern int      ttflush();
  70. extern int      ttclose();
  71. extern int      tcapmove();
  72. extern int      tcapeeol();
  73. extern int      tcapeeop();
  74. extern int      tcapbeep();
  75. extern int    tcaprev();
  76. extern int      tcapopen();
  77. extern int      tput();
  78. extern char     *tgoto();
  79.  
  80. #define TCAPSLEN 315
  81. char tcapbuf[TCAPSLEN];
  82. char *UP, PC, *CM, *CE, *CL, *SO, *SE;
  83. /* 
  84.  * PICO extentions 
  85.  */
  86. char    *DL,            /* delete line */
  87.     *AL,            /* insert line */
  88.     *CS,            /* define a scrolling region, vt100 */
  89.     *IC,            /* insert character, preferable to : */
  90.     *IM,            /* set insert mode and, */
  91.     *EI,            /* end insert mode */
  92.     *DC,            /* delete character */
  93.     *DM,            /* set delete mode and, */
  94.     *ED,            /* end delete mode */
  95.     *SF,            /* scroll text up */
  96.     *SR;            /* scroll text down */
  97.  
  98. char *KU, *KD, *KL, *KR;
  99. char *KPPU, *KPPD, *KPHOME, *KPEND;
  100.  
  101. struct KBSTREE *kpadseqs = NULL;
  102.  
  103. TERM term = {
  104.         NROW-1,
  105.         NCOL,
  106.     MARGIN,
  107.     SCRSIZ,
  108.         tcapopen,
  109.         ttclose,
  110.         ttgetc,
  111.         ttputc,
  112.         ttflush,
  113.         tcapmove,
  114.         tcapeeol,
  115.         tcapeeop,
  116.         tcapbeep,
  117.         tcaprev
  118. };
  119.  
  120.  
  121. tcapopen()
  122. {
  123.     char   *t, *p, *tgetstr();
  124.     char    tcbuf[1024];
  125.     char   *tv_stype;
  126.     char   *initstrng = "";
  127.     char    err_str[72];
  128.     char   *getenv();
  129.     struct  sgttyb tty;
  130.  
  131. #ifdef TIOCGWINSZ
  132.     struct winsize win;
  133.     if (ioctl(0, TIOCGWINSZ, &win) == 0) {
  134.     term.t_ncol = (win.ws_col) ? win.ws_col : 80;
  135.     term.t_nrow = (win.ws_row) ? win.ws_row - 1 : 23;
  136.     }
  137. #endif
  138.  
  139.     /*
  140.      * determine the terminal's communication speed and decide
  141.      * if we need to do optimization ...
  142.      */
  143.     if(ioctl(1, TIOCGETP, &tty) == 0){
  144.     if(tty.sg_ospeed < B9600)
  145.       optimize = TRUE;
  146.     }
  147.  
  148.     if ((tv_stype = getenv("TERM")) == NULL){
  149.     if(Pmaster){
  150.         return(FALSE);
  151.     }
  152.     else{
  153.         puts("Environment variable TERM not defined!");
  154.         exit(1);
  155.     }
  156.     }
  157.  
  158.     if((tgetent(tcbuf, tv_stype)) != 1){
  159.     if(Pmaster){
  160.         return(FALSE);
  161.     }
  162.     else{
  163.         sprintf(err_str, "Unknown terminal type %s!", tv_stype);
  164.         puts(err_str);
  165.         exit(1);
  166.     }
  167.     }
  168.  
  169.     p = tcapbuf;
  170.     t = tgetstr("pc", &p);
  171.     if(t)
  172.       PC = *t;
  173.  
  174.     CL = tgetstr("cl", &p);
  175.     CM = tgetstr("cm", &p);
  176.     CE = tgetstr("ce", &p);
  177.     UP = tgetstr("up", &p);
  178.     SE = tgetstr("se", &p);
  179.     SO = tgetstr("so", &p);
  180.     if (SO != NULL)
  181.       revexist = TRUE;
  182.  
  183.     DL = tgetstr("dl", &p);
  184.     AL = tgetstr("al", &p);
  185.     CS = tgetstr("cs", &p);
  186.     IC = tgetstr("ic", &p);
  187.     IM = tgetstr("im", &p);
  188.     EI = tgetstr("ei", &p);
  189.     DC = tgetstr("dc", &p);
  190.     DM = tgetstr("dm", &p);
  191.     ED = tgetstr("ed", &p);
  192.     SF = tgetstr("sf", &p);
  193.     SR = tgetstr("sr", &p);
  194.     if(DC == NULL && (DM == NULL || ED == NULL))
  195.       delchar = FALSE;
  196.     if(IC == NULL && (IM == NULL || EI == NULL))
  197.       inschar = FALSE;
  198.     if((CS==NULL || SF==NULL || SR==NULL) && (DL==NULL || AL==NULL))
  199.       scrollexist = FALSE;
  200.  
  201.     if(CL == NULL || CM == NULL || UP == NULL){
  202.     if(Pmaster == NULL){
  203.         puts("Incomplete termcap entry\n");
  204.         exit(1);
  205.     }
  206.     }
  207.     else{
  208.     KPPU   = tgetstr("kP", &p);
  209.     KPPD   = tgetstr("kN", &p);
  210.     KPHOME = tgetstr("kh", &p);
  211.     KU     = tgetstr("ku", &p);
  212.     KD     = tgetstr("kd", &p);
  213.     KL     = tgetstr("kl", &p);
  214.     KR     = tgetstr("kr", &p);
  215.     if(KU != NULL && (KL != NULL && (KR != NULL && KD != NULL))){
  216.         kpinsert(KU,K_PAD_UP);
  217.         kpinsert(KD,K_PAD_DOWN);
  218.         kpinsert(KL,K_PAD_LEFT);
  219.         kpinsert(KR,K_PAD_RIGHT);
  220.  
  221.         if(KPPU != NULL)
  222.           kpinsert(KPPU,K_PAD_PREVPAGE);
  223.         if(KPPD != NULL)
  224.           kpinsert(KPPD,K_PAD_NEXTPAGE);
  225.         if(KPHOME != NULL)
  226.           kpinsert(KPHOME,K_PAD_HOME);
  227.     }
  228.     }
  229.  
  230.     /*
  231.      * add default keypad sequences to the trie...
  232.      */
  233.     if(gmode&MDFKEY){
  234.     /*
  235.      * Initialize UW-modified NCSA telnet to use it's functionkeys
  236.      */
  237.     if(Pmaster == NULL){
  238.         puts("\033[99h");
  239.     }
  240.  
  241.     /*
  242.      * this is sort of a hack, but it allows us to use
  243.      * the function keys on pc's running telnet
  244.      */
  245.  
  246.     /* 
  247.      * UW-NDC/UCS vt10[02] application mode.
  248.      */
  249.     kpinsert("OP",F1);
  250.     kpinsert("OQ",F2);
  251.     kpinsert("OR",F3);
  252.     kpinsert("OS",F4);
  253.     kpinsert("Op",F5);
  254.     kpinsert("Oq",F6);
  255.     kpinsert("Or",F7);
  256.     kpinsert("Os",F8);
  257.     kpinsert("Ot",F9);
  258.     kpinsert("Ou",F10);
  259.     kpinsert("Ov",F11);
  260.     kpinsert("Ow",F12);
  261.  
  262.     /*
  263.      * special keypad functions
  264.      */
  265.     kpinsert("[4J",K_PAD_PREVPAGE);
  266.     kpinsert("[3J",K_PAD_NEXTPAGE);
  267.     kpinsert("[2J",K_PAD_HOME);
  268.     kpinsert("[N",K_PAD_END);
  269.  
  270.     /* 
  271.      * ANSI mode.
  272.      */
  273.     kpinsert("[=a",F1);
  274.     kpinsert("[=b",F2);
  275.     kpinsert("[=c",F3);
  276.     kpinsert("[=d",F4);
  277.     kpinsert("[=e",F5);
  278.     kpinsert("[=f",F6);
  279.     kpinsert("[=g",F7);
  280.     kpinsert("[=h",F8);
  281.     kpinsert("[=i",F9);
  282.     kpinsert("[=j",F10);
  283.     kpinsert("[=k",F11);
  284.     kpinsert("[=l",F12);
  285.  
  286.     HelpKeyNames = funckeynames;
  287.  
  288.     }
  289.     else{
  290.     HelpKeyNames = NULL;
  291.     }
  292.  
  293.     kpinsert("OA",K_PAD_UP);    /* DEC vt100, ANSI and cursor key mode. */
  294.     kpinsert("OB",K_PAD_DOWN);
  295.     kpinsert("OD",K_PAD_LEFT);
  296.     kpinsert("OC",K_PAD_RIGHT);
  297.  
  298.     kpinsert("[A",K_PAD_UP);    /* DEC vt100, ANSI, cursor key mode reset. */
  299.     kpinsert("[B",K_PAD_DOWN);
  300.     kpinsert("[D",K_PAD_LEFT);
  301.     kpinsert("[C",K_PAD_RIGHT);
  302.  
  303.     kpinsert("A",K_PAD_UP);    /* DEC vt52 mode. */
  304.     kpinsert("B",K_PAD_DOWN);
  305.     kpinsert("D",K_PAD_LEFT);
  306.     kpinsert("C",K_PAD_RIGHT);
  307.  
  308.     kpinsert("[215z",K_PAD_UP); /* Sun Console sequences. */
  309.     kpinsert("[221z",K_PAD_DOWN);
  310.     kpinsert("[217z",K_PAD_LEFT);
  311.     kpinsert("[219z",K_PAD_RIGHT);
  312.  
  313.     if (CE == NULL)        /* will we be able to use clear to EOL? */
  314.       eolexist = FALSE;
  315.         
  316.     if (p >= &tcapbuf[TCAPSLEN]){
  317.     if(Pmaster == NULL){
  318.         puts("Terminal description too big!\n");
  319.         exit(1);
  320.     }
  321.     }
  322.  
  323.     if(*initstrng != '\0')
  324.       puts(initstrng);
  325.  
  326.     ttopen();
  327. }
  328.  
  329.  
  330.  
  331. #define    newnode()    (struct KBSTREE *)malloc(sizeof(struct KBSTREE))
  332. /*
  333.  * kbinsert - insert a keystroke escape sequence into the global search
  334.  *          structure.
  335.  */
  336. kpinsert(kstr, kval)
  337. char    *kstr;
  338. int    kval;
  339. {
  340.     register    char    *buf;
  341.     register    struct KBSTREE *temp;
  342.     register    struct KBSTREE *trail;
  343.  
  344.     if(kstr == NULL)
  345.       return;
  346.  
  347.     temp = trail = kpadseqs;
  348.     if(kstr[0] == '\033')
  349.       buf = kstr+1;            /* can the ^[ character */ 
  350.     else
  351.       buf = kstr;
  352.  
  353.     for(;;) {
  354.     if(temp == NULL){
  355.         temp = newnode();
  356.         temp->value = *buf;
  357.         temp->func = 0;
  358.         temp->left = NULL;
  359.         temp->down = NULL;
  360.         if(kpadseqs == NULL)
  361.           kpadseqs = temp;
  362.         else
  363.           trail->down = temp;
  364.     }
  365.     else{                /* first entry */
  366.         while((temp != NULL) && (temp->value != *buf)){
  367.         trail = temp;
  368.         temp = temp->left;
  369.         }
  370.  
  371.         if(temp == NULL){   /* add new val */
  372.         temp = newnode();
  373.         temp->value = *buf;
  374.         temp->func = 0;
  375.         temp->left = NULL;
  376.         temp->down = NULL;
  377.         trail->left = temp;
  378.         }
  379.     }
  380.  
  381.     if (*(++buf) == '\0'){
  382.         break;
  383.     }
  384.     else{
  385.         trail = temp;
  386.         temp = temp->down;
  387.     }
  388.     }
  389.     
  390.     if(temp != NULL)
  391.       temp->func = kval;
  392. }
  393.  
  394.  
  395.  
  396. /*
  397.  * tcapinsert - insert a character at the current character position.
  398.  *              IC takes precedence.
  399.  */
  400. tcapinsert(ch)
  401. register char    ch;
  402. {
  403.     if(IC != NULL){
  404.     putpad(IC);
  405.     ttputc(ch);
  406.     }
  407.     else{
  408.     putpad(IM);
  409.     ttputc(ch);
  410.     putpad(EI);
  411.     }
  412. }
  413.  
  414.  
  415. /*
  416.  * tcapdelete - delete a character at the current character position.
  417.  */
  418. tcapdelete()
  419. {
  420.     if(DM == NULL && ED == NULL)
  421.       putpad(DC);
  422.     else{
  423.     putpad(DM);
  424.     putpad(DC);
  425.     putpad(ED);
  426.     }
  427. }
  428.  
  429.  
  430. /*
  431.  * tcapscrolldn - open a line at the given row position.
  432.  *                use either region scrolling or deleteline/insertline
  433.  *                to open a new line.
  434.  */
  435. tcapscrolldn(row, n)
  436. register int row;
  437. register int n;
  438. {
  439.     register int i;
  440.  
  441.     if(CS != NULL){
  442.     putpad(tgoto(CS, term.t_nrow - 3, row));
  443.     tcapmove(row, 0);
  444.     for(i = 0; i < n; i++)
  445.       putpad( (SR != NULL && *SR != '\0') ? SR : "\n" );
  446.     putpad(tgoto(CS, term.t_nrow, 0));
  447.     tcapmove(row, 0);
  448.     }
  449.     else{
  450.     /*
  451.      * this code causes a jiggly motion of the keymenu when scrolling
  452.      */
  453.     for(i = 0; i < n; i++){
  454.         tcapmove(term.t_nrow - 3, 0);
  455.         putpad(DL);
  456.         tcapmove(row, 0);
  457.         putpad(AL);
  458.     }
  459. #ifdef    NOWIGGLYLINES
  460.     /*
  461.      * this code causes a sweeping motion up and down the display
  462.      */
  463.     tcapmove(term.t_nrow - 2 - n, 0);
  464.     for(i = 0; i < n; i++)
  465.       putpad(DL);
  466.     tcapmove(row, 0);
  467.     for(i = 0; i < n; i++)
  468.       putpad(AL);
  469. #endif
  470.     }
  471. }
  472.  
  473.  
  474. /*
  475.  * tcapscrollup - open a line at the given row position.
  476.  *                use either region scrolling or deleteline/insertline
  477.  *                to open a new line.
  478.  */
  479. tcapscrollup(row, n)
  480. register int row;
  481. register int n;
  482. {
  483.     register int i;
  484.  
  485.     if(CS != NULL){
  486.     putpad(tgoto(CS, term.t_nrow - 3, row));
  487.     /* setting scrolling region moves cursor to home */
  488.     tcapmove(term.t_nrow-3, 0);
  489.     for(i = 0;i < n; i++)
  490.       putpad((SF == NULL || SF[0] == '\0') ? "\n" : SF);
  491.     putpad(tgoto(CS, term.t_nrow, 0));
  492.     tcapmove(2, 0);
  493.     }
  494.     else{
  495.     for(i = 0; i < n; i++){
  496.         tcapmove(row, 0);
  497.         putpad(DL);
  498.         tcapmove(term.t_nrow - 3, 0);
  499.         putpad(AL);
  500.     }
  501. #ifdef  NOWIGGLYLINES
  502.     /* see note above */
  503.     tcapmove(row, 0);
  504.     for(i = 0; i < n; i++)
  505.       putpad(DL);
  506.     tcapmove(term.t_nrow - 2 - n, 0);
  507.     for(i = 0;i < n; i++)
  508.       putpad(AL);
  509. #endif
  510.     }
  511. }
  512.  
  513.  
  514. /*
  515.  * o_insert - use termcap info to optimized character insert
  516.  *            returns: true if it optimized output, false otherwise
  517.  */
  518. o_insert(c)
  519. char c;
  520. {
  521.     if(inschar){
  522.     tcapinsert(c);
  523.     return(1);            /* no problems! */
  524.     }
  525.  
  526.     return(0);                /* can't do it. */
  527. }
  528.  
  529.  
  530. /*
  531.  * o_delete - use termcap info to optimized character insert
  532.  *            returns true if it optimized output, false otherwise
  533.  */
  534. o_delete()
  535. {
  536.     if(delchar){
  537.     tcapdelete();
  538.     return(1);            /* deleted, no problem! */
  539.     }
  540.  
  541.     return(0);                /* no dice. */
  542. }
  543.  
  544.  
  545. /*
  546.  * scrollup - use terminal characteristics to optimize screen updates that
  547.  *            scroll up the display
  548.  */
  549. o_scrollup()
  550. {
  551. }
  552.  
  553.  
  554. /*
  555.  * scrolldown - use terminal characteristics to optimize screen updates that
  556.  *              scroll down the display
  557.  */
  558. o_scrolldown()
  559. {
  560. }
  561.  
  562.  
  563. tcapmove(row, col)
  564. register int row, col;
  565. {
  566.     putpad(tgoto(CM, col, row));
  567. }
  568.  
  569.  
  570. tcapeeol()
  571. {
  572.     putpad(CE);
  573. }
  574.  
  575.  
  576. tcapeeop()
  577. {
  578.     putpad(CL);
  579. }
  580.  
  581.  
  582. tcaprev(state)        /* change reverse video status */
  583. int state;            /* FALSE = normal video, TRUE = reverse video */
  584. {
  585.     if(state){
  586.     if (SO != NULL)
  587.       putpad(SO);
  588.     } 
  589.     else{
  590.     if (SE != NULL)
  591.       putpad(SE);
  592.     }
  593. }
  594.  
  595.  
  596. tcapbeep()
  597. {
  598.     ttputc(BEL);
  599. }
  600.  
  601.  
  602. putpad(str)
  603. char    *str;
  604. {
  605.     tputs(str, 1, ttputc);
  606. }
  607.  
  608.  
  609. putnpad(str, n)
  610. char    *str;
  611. {
  612.     tputs(str, n, ttputc);
  613. }
  614.  
  615. #else
  616.  
  617. hello()
  618. {
  619. }
  620.  
  621. #endif /* TERMCAP */
  622.