home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / pine / pico / tinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-06  |  16.0 KB  |  694 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: tinfo.c,v 4.10 1993/11/23 05:07:27 mikes Exp $";
  3. #endif
  4. /*
  5.  * Program:    Display routines
  6.  *
  7.  *
  8.  * Donn Cave
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: donn@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  * Copyright 1991-1993  University of Washington
  19.  *
  20.  *  Permission to use, copy, modify, and distribute this software and its
  21.  * documentation for any purpose and without fee to the University of
  22.  * Washington is hereby granted, provided that the above copyright notice
  23.  * appears in all copies and that both the above copyright notice and this
  24.  * permission notice appear in supporting documentation, and that the name
  25.  * of the University of Washington not be used in advertising or publicity
  26.  * pertaining to distribution of the software without specific, written
  27.  * prior permission.  This software is made available "as is", and
  28.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  29.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  30.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  31.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  32.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  33.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  34.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  35.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  36.  *
  37.  * Pine and Pico are trademarks of the University of Washington.
  38.  * No commercial use of these trademarks may be made without prior
  39.  * written permission of the University of Washington.
  40.  *
  41.  */
  42. /*
  43.  *      tinfo - substitute for tcap, on systems that have terminfo.
  44.  */
  45.  
  46. #define    termdef    1            /* don't define "term" external */
  47.  
  48. #include    <stdio.h>
  49. #include        <signal.h>
  50. #include    "osdep.h"
  51. #include    "estruct.h"
  52. #include        "edef.h"
  53. #include        "pico.h"
  54.  
  55. extern char *tigetstr ();
  56.  
  57. #define NROW    24
  58. #define NCOL    80
  59. #define    MARGIN    8
  60. #define    SCRSIZ    64
  61. #define BEL     0x07
  62. #define ESC     0x1B
  63.  
  64. extern int      ttopen();
  65. extern int      ttgetc();
  66. extern int      ttputc();
  67. extern int      ttflush();
  68. extern int      ttclose();
  69.  
  70. static int      tinfomove();
  71. static int      tinfoeeol();
  72. static int      tinfoeeop();
  73. static int      tinfobeep();
  74. static int    tinforev();
  75. static int      tinfoopen();
  76. static int      tinfoclose();
  77.  
  78. #ifdef HEBREW
  79. #include "hebrew.h"
  80. extern int stdputc();
  81. extern int ttcol,ttrow;
  82. char eobexist;
  83. #endif
  84.  
  85. extern int      tput();
  86. extern char     *tgoto();
  87.  
  88. static int      kpinsert();
  89. static int      putpad();
  90.  
  91. static char *UP, PC, *CM, *CE, *CL, *SO, *SE ,*CB ;
  92.  
  93. /* 
  94.  * PICO extentions 
  95.  */
  96. static char *DL,            /* delete line */
  97.     *AL,            /* insert line */
  98.     *CS,            /* define a scrolling region, vt100 */
  99.     *IC,            /* insert character, preferable to : */
  100.     *IM,            /* set insert mode and, */
  101.     *EI,            /* end insert mode */
  102.     *DC,            /* delete character */
  103.     *DM,            /* set delete mode and, */
  104.     *ED,            /* end delete mode */
  105.     *SF,            /* scroll text up */
  106.     *SR,            /* scroll text down */
  107.     *TI,            /* string to start termcap */
  108.         *TE;            /* string to end termcap */
  109.  
  110. static char *KU, *KD, *KL, *KR;
  111. static char *KPPU, *KPPD, *KPHOME, *KPEND;
  112.  
  113. struct KBSTREE *kpadseqs = NULL;
  114.  
  115. TERM term = {
  116.         NROW-1,
  117.         NCOL,
  118.     MARGIN,
  119.     SCRSIZ,
  120.         tinfoopen,
  121.         tinfoclose,
  122.         ttgetc,
  123.         ttputc,
  124.         ttflush,
  125.         tinfomove,
  126.         tinfoeeol,
  127.         tinfoeeop,
  128.         tinfobeep,
  129.         tinforev
  130. };
  131.  
  132.  
  133. static tinfoopen()
  134. {
  135.     char  *t;
  136.     char  *getenv();
  137.  
  138.     ttgetwinsz();
  139.  
  140.     /*
  141.      * determine the terminal's communication speed and decide
  142.      * if we need to do optimization ...
  143.      */
  144.     optimize = ttisslow();
  145.  
  146.     if (Pmaster) {
  147.     /*
  148.      *        setupterm() automatically retrieves the value
  149.      *        of the TERM variable.
  150.      */
  151.     int err;
  152.     setupterm (0, 1, &err);
  153.     if (err != 1) return FALSE;
  154.     }
  155.     else {
  156.     /*
  157.      *        setupterm() issues a message and exits, if the
  158.      *        terminfo data base is gone or the term type is
  159.      *        unknown, if arg2 is 0.
  160.      */
  161.     setupterm (0, 1, 0);
  162.     }
  163.  
  164.     t = tigetstr("pad");
  165.     if(t)
  166.       PC = *t;
  167. #ifdef HEBREW
  168.     CB = tigetstr("el1");
  169.     eobexist= (CB != NULL);
  170. #endif
  171.  
  172.     CL = tigetstr("clear");
  173.     CM = tigetstr("cup");
  174.     CE = tigetstr("el");
  175.     UP = tigetstr("cuu1");
  176.     SE = tigetstr("rmso");
  177.     SO = tigetstr("smso");
  178.     DL = tigetstr("dl1");
  179.     AL = tigetstr("il1");
  180.     CS = tigetstr("csr");
  181.     IC = tigetstr("ich1");
  182.     IM = tigetstr("smir");
  183.     EI = tigetstr("rmir");
  184.     DC = tigetstr("dch1");
  185.     DM = tigetstr("smdc");
  186.     ED = tigetstr("rmdc");
  187.     SF = tigetstr("ind");
  188.     SR = tigetstr("ri");
  189.     TI = tigetstr("smcup");
  190.     TE = tigetstr("rmcup");
  191.  
  192.     eolexist = (CE != NULL);    /* will we be able to use clear to EOL? */
  193.     revexist = (SO != NULL);    /* will be able to use reverse video */
  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 terminfo entry\n");
  204.         exit(1);
  205.     }
  206.     }
  207.     else{
  208.     KPPU   = tigetstr("kpp");
  209.     KPPD   = tigetstr("knp");
  210.     KPHOME = tigetstr("khome");
  211.     KU = tigetstr("kcuu1");
  212.     KD = tigetstr("kcud1");
  213.     KL = tigetstr("kcub1");
  214.     KR = tigetstr("kcuf1");
  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 its functionkeys
  236.      */
  237.     if(Pmaster == NULL){
  238.         puts("\033[99h");
  239.     }
  240.  
  241.     /*
  242.      * this is sort of a hack [no kidding], but it allows us to use
  243.      * the function keys on pc's running telnet
  244.      */
  245.  
  246.     /* 
  247.      * UW-NDC/UCS vt10[01] 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.     /*
  294.      * DEC vt100, ANSI and cursor key mode.
  295.      */
  296.     kpinsert("OA",K_PAD_UP);
  297.     kpinsert("OB",K_PAD_DOWN);
  298.     kpinsert("OD",K_PAD_LEFT);
  299.     kpinsert("OC",K_PAD_RIGHT);
  300.  
  301.     /*
  302.      * DEC vt100, ANSI and cursor key mode reset.
  303.      */
  304.     kpinsert("[A",K_PAD_UP);
  305.     kpinsert("[B",K_PAD_DOWN);
  306.     kpinsert("[D",K_PAD_LEFT);
  307.     kpinsert("[C",K_PAD_RIGHT);
  308.  
  309.     /*
  310.      * DEC vt52 mode.
  311.      */
  312.     kpinsert("A",K_PAD_UP);
  313.     kpinsert("B",K_PAD_DOWN);
  314.     kpinsert("D",K_PAD_LEFT);
  315.     kpinsert("C",K_PAD_RIGHT);
  316.  
  317.     /*
  318.      * Sun Console sequences.
  319.      */
  320.     kpinsert("[215z",K_PAD_UP);
  321.     kpinsert("[221z",K_PAD_DOWN);
  322.     kpinsert("[217z",K_PAD_LEFT);
  323.     kpinsert("[219z",K_PAD_RIGHT);
  324.  
  325.     ttopen();
  326.  
  327.     if(TI && !Pmaster){
  328.     putpad(TI);            /* any init terminfo requires */
  329.     if(CS)
  330.       putpad(tgoto(CS, term.t_nrow, 0));
  331.     }
  332. }
  333.  
  334.  
  335. static tinfoclose()
  336. {
  337.     if(!Pmaster){
  338.     if(gmode&MDFKEY)
  339.       puts("\033[99l");        /* reset UW-NCSA telnet keys */
  340.  
  341.     if(TE)                /* any clean up terminfo requires */
  342.       putpad(TE);
  343.     }
  344.  
  345.     ttclose();
  346. }
  347.  
  348.  
  349. #define    newnode()    (struct KBSTREE *)malloc(sizeof(struct KBSTREE))
  350. /*
  351.  * kbinsert - insert a keystroke escape sequence into the global search
  352.  *          structure.
  353.  */
  354. static kpinsert(kstr, kval)
  355. char    *kstr;
  356. int    kval;
  357. {
  358.     register    char    *buf;
  359.     register    struct KBSTREE *temp;
  360.     register    struct KBSTREE *trail;
  361.  
  362.     if(kstr == NULL)
  363.       return;
  364.  
  365.     temp = trail = kpadseqs;
  366.     if(kstr[0] == '\033')
  367.       buf = kstr+1;            /* can the ^[ character */ 
  368.     else
  369.       buf = kstr;
  370.  
  371.     for(;;) {
  372.     if(temp == NULL){
  373.         temp = newnode();
  374.         temp->value = *buf;
  375.         temp->func = 0;
  376.         temp->left = NULL;
  377.         temp->down = NULL;
  378.         if(kpadseqs == NULL)
  379.           kpadseqs = temp;
  380.         else
  381.           trail->down = temp;
  382.     }
  383.     else{                /* first entry */
  384.         while((temp != NULL) && (temp->value != *buf)){
  385.         trail = temp;
  386.         temp = temp->left;
  387.         }
  388.         if(temp == NULL){   /* add new val */
  389.         temp = newnode();
  390.         temp->value = *buf;
  391.         temp->func = 0;
  392.         temp->left = NULL;
  393.         temp->down = NULL;
  394.         trail->left = temp;
  395.         }
  396.     }
  397.  
  398.     if (*(++buf) == '\0'){
  399.         break;
  400.     }
  401.     else{
  402.         trail = temp;
  403.         temp = temp->down;
  404.     }
  405.     }
  406.  
  407.     if(temp != NULL)
  408.       temp->func = kval;
  409. }
  410.  
  411.  
  412. /*
  413.  * tinfoinsert - insert a character at the current character position.
  414.  *               IC takes precedence.
  415.  */
  416. tinfoinsert(ch)
  417. register char    ch;
  418. {
  419. #ifndef HEBREW
  420.     if(IC != NULL){
  421.     putpad(IC);
  422.     ttputc(ch);
  423.     }
  424.     else{
  425.     putpad(IM);
  426.     ttputc(ch);
  427.     putpad(EI);
  428.     }
  429. #else
  430.     if(compose_heb)
  431.       ttputc(ch);
  432.     else{
  433.     if(IC != NULL){
  434.     putpad(IC);
  435.     ttputc(ch);
  436.     }
  437.     else{
  438.     putpad(IM);
  439.     ttputc(ch);
  440.     putpad(EI);
  441.     }
  442.   }
  443. #endif
  444. }
  445.  
  446.  
  447. /*
  448.  * tinfodelete - delete a character at the current character position.
  449.  */
  450. tinfodelete()
  451. {
  452. #ifndef HEBREW
  453.     if(DM == NULL && ED == NULL)
  454.       putpad(DC);
  455.     else{
  456.     putpad(DM);
  457.     putpad(DC);
  458.     putpad(ED);
  459.     }
  460. #else
  461.     if(compose_heb){
  462.       stdputc(' ');
  463.     }
  464.     else{
  465.       if(DM == NULL && ED == NULL)
  466.     putpad(DC);
  467.       else{
  468.     putpad(DM);
  469.     putpad(DC);
  470.     putpad(ED);
  471.       }
  472.     }
  473.  
  474. #endif
  475. }
  476.  
  477.  
  478. /*
  479.  * o_scrolldown() - open a line at the given row position.
  480.  *               use either region scrolling or deleteline/insertline
  481.  *               to open a new line.
  482.  */
  483. o_scrolldown(row, n)
  484. register int row;
  485. register int n;
  486. {
  487.     register int i;
  488.  
  489.     if(CS != NULL){
  490.     putpad(tgoto(CS, term.t_nrow - 3, row));
  491.     tinfomove(row, 0);
  492.     for(i = 0; i < n; i++)
  493.       putpad( (SR != NULL && *SR != '\0') ? SR : "\n" );
  494.     putpad(tgoto(CS, term.t_nrow, 0));
  495.     tinfomove(row, 0);
  496.     }
  497.     else{
  498.     /*
  499.      * this code causes a jiggly motion of the keymenu when scrolling
  500.      */
  501.     for(i = 0; i < n; i++){
  502.         tinfomove(term.t_nrow - 3, 0);
  503.         putpad(DL);
  504.         tinfomove(row, 0);
  505.         putpad(AL);
  506.     }
  507. #ifdef    NOWIGGLYLINES
  508.     /*
  509.      * this code causes a sweeping motion up and down the display
  510.      */
  511.     tinfomove(term.t_nrow - 2 - n, 0);
  512.     for(i = 0; i < n; i++)
  513.       putpad(DL);
  514.     tinfomove(row, 0);
  515.     for(i = 0; i < n; i++)
  516.       putpad(AL);
  517. #endif
  518.     }
  519. }
  520.  
  521.  
  522. /*
  523.  * o_scrollup() - open a line at the given row position.
  524.  *               use either region scrolling or deleteline/insertline
  525.  *               to open a new line.
  526.  */
  527. o_scrollup(row, n)
  528. register int row;
  529. register int n;
  530. {
  531.     register int i;
  532.  
  533.     if(CS != NULL){
  534.     putpad(tgoto(CS, term.t_nrow - 3, row));
  535.     /* setting scrolling region moves cursor to home */
  536.     tinfomove(term.t_nrow-3, 0);
  537.     for(i = 0;i < n; i++)
  538.       putpad((SF == NULL || SF[0] == '\0') ? "\n" : SF);
  539.     putpad(tgoto(CS, term.t_nrow, 0));
  540.     tinfomove(2, 0);
  541.     }
  542.     else{
  543.     for(i = 0; i < n; i++){
  544.         tinfomove(row, 0);
  545.         putpad(DL);
  546.         tinfomove(term.t_nrow - 3, 0);
  547.         putpad(AL);
  548.     }
  549. #ifdef  NOWIGGLYLINES
  550.     /* see note above */
  551.     tinfomove(row, 0);
  552.     for(i = 0; i < n; i++)
  553.       putpad(DL);
  554.     tinfomove(term.t_nrow - 2 - n, 0);
  555.     for(i = 0;i < n; i++)
  556.       putpad(AL);
  557. #endif
  558.     }
  559. }
  560.  
  561.  
  562.  
  563. /*
  564.  * o_insert - use terminfo to optimized character insert
  565.  *            returns: true if it optimized output, false otherwise
  566.  */
  567. o_insert(c)
  568. char c;
  569. {
  570.     if(inschar){
  571.     tinfoinsert(c);
  572.     return(1);            /* no problems! */
  573.     }
  574.  
  575.     return(0);                /* can't do it. */
  576. }
  577.  
  578.  
  579. /*
  580.  * o_delete - use terminfo to optimized character insert
  581.  *            returns true if it optimized output, false otherwise
  582.  */
  583. o_delete()
  584. {
  585.     if(delchar){
  586.     tinfodelete();
  587.     return(1);            /* deleted, no problem! */
  588.     }
  589.  
  590.     return(0);                /* no dice. */
  591. }
  592.  
  593.  
  594. static tinfomove(row, col)
  595. register int row, col;
  596. {
  597. #ifdef HEBREW
  598.   if(compose_heb && hebmode)
  599.     col = term.t_ncol - col - 1;
  600. #endif
  601.     putpad(tgoto(CM, col, row));
  602. }
  603.  
  604.  
  605. static tinfoeeol()
  606. {
  607. #ifndef HEBREW
  608.     putpad(CE);
  609. #else
  610.     if(compose_heb && hebmode){
  611.       if(eobexist)putpad(CB);
  612.       else tputs("\033[1K",1,stdputc);      
  613.     }
  614.     else
  615.       putpad(CE);
  616. #endif
  617.  
  618. }
  619.  
  620.  
  621. static tinfoeeop()
  622. {
  623.         putpad(CL);
  624. #ifdef HEBREW
  625.     if(compose_heb && hebmode)
  626.     tinfomove(0,0);
  627. #endif
  628. }
  629.  
  630.  
  631. static tinforev(state)        /* change reverse video status */
  632. int state;                    /* FALSE = normal video, TRUE = rev video */
  633. {
  634.     static int cstate = FALSE;
  635.  
  636.     if(state == cstate)        /* no op if already set! */
  637.       return(0);
  638.  
  639.     if(cstate = state){        /* remember last setting */
  640.     if (SO != NULL)
  641.       putpad(SO);
  642.     } else {
  643.     if (SE != NULL)
  644.       putpad(SE);
  645.     }
  646. }
  647.  
  648.  
  649. static tinfobeep()
  650. {
  651.     ttputc(BEL);
  652. }
  653.  
  654.  
  655. static putpad(str)
  656. char    *str;
  657. {
  658. #ifndef HEBREW
  659.     tputs(str, 1, ttputc);
  660. #else
  661.     if(compose_heb && hebmode)
  662.       tputs(str, 1, stdputc);
  663.     else
  664.       tputs(str, 1, ttputc);
  665. #endif    
  666. }
  667.  
  668.  
  669. static putnpad(str, n)
  670. char    *str;
  671. {
  672. #ifndef HEBREW
  673.     tputs(str, n, ttputc);
  674. #else
  675.     if(compose_heb && hebmode)
  676.       tputs(str, n, stdputc);
  677.     else
  678.       tputs(str, n, ttputc);
  679. #endif
  680. }
  681.  
  682. #ifdef HEBREW
  683. hide_cur()
  684. {
  685. tputs("\033[?25l",1,stdputc);
  686. }
  687. show_cur()
  688. {
  689. tputs("\033[?25h",1,stdputc);
  690. }
  691. #endif
  692.  
  693.