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

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: tcap.c,v 4.11 1993/11/22 19:33:47 mikes Exp $";
  3. #endif
  4. /*
  5.  * Program:    Display routines
  6.  *
  7.  *
  8.  * Michael Seibel
  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: mikes@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. /*    tcap:    Unix V5, V7 and BS4.2 Termcap video driver
  43.         for MicroEMACS
  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.  
  54. #if TERMCAP
  55. #include        "pico.h"
  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. extern int      tcapmove();
  70. extern int      tcapeeol();
  71. extern int      tcapeeop();
  72. extern int      tcapbeep();
  73. extern int    tcaprev();
  74. extern int      tcapopen();
  75. extern int      tcapclose();
  76. extern int      tput();
  77. extern char     *tgoto();
  78.  
  79. #ifdef HEBREW
  80. #include "hebrew.h"
  81. extern int stdputc();
  82. extern int ttcol,ttrow;
  83. char eobexist;
  84. #endif
  85.  
  86. #define TCAPSLEN 315
  87. char tcapbuf[TCAPSLEN];
  88. char *UP, PC, *CM, *CE, *CL, *SO, *SE, *CB;
  89. /* 
  90.  * PICO extentions 
  91.  */
  92. char    *DL,            /* delete line */
  93.     *AL,            /* insert line */
  94.     *CS,            /* define a scrolling region, vt100 */
  95.     *IC,            /* insert character, preferable to : */
  96.     *IM,            /* set insert mode and, */
  97.     *EI,            /* end insert mode */
  98.     *DC,            /* delete character */
  99.     *DM,            /* set delete mode and, */
  100.     *ED,            /* end delete mode */
  101.     *SF,            /* scroll text up */
  102.     *SR,            /* scroll text down */
  103.     *TI,            /* string to start termcap */
  104.         *TE;            /* string to end termcap */
  105.  
  106. char *KU, *KD, *KL, *KR;
  107. char *KPPU, *KPPD, *KPHOME, *KPEND;
  108.  
  109. struct KBSTREE *kpadseqs = NULL;
  110.  
  111. TERM term = {
  112.         NROW-1,
  113.         NCOL,
  114.     MARGIN,
  115.     SCRSIZ,
  116.         tcapopen,
  117.         tcapclose,
  118.         ttgetc,
  119.         ttputc,
  120.         ttflush,
  121.         tcapmove,
  122.         tcapeeol,
  123.         tcapeeop,
  124.         tcapbeep,
  125.         tcaprev
  126. };
  127.  
  128.  
  129. tcapopen()
  130. {
  131.     char   *t, *p, *tgetstr();
  132.     char    tcbuf[1024];
  133.     char   *tv_stype;
  134.     char    err_str[72];
  135.     char   *getenv();
  136.  
  137.     ttgetwinsz();
  138.  
  139.     /*
  140.      * determine the terminal's communication speed and decide
  141.      * if we need to do optimization ...
  142.      */
  143.     optimize = ttisslow();
  144.  
  145.     if ((tv_stype = getenv("TERM")) == NULL){
  146.     if(Pmaster){
  147.         return(FALSE);
  148.     }
  149.     else{
  150.         puts("Environment variable TERM not defined!");
  151.         exit(1);
  152.     }
  153.     }
  154.  
  155.     if((tgetent(tcbuf, tv_stype)) != 1){
  156.     if(Pmaster){
  157.         return(FALSE);
  158.     }
  159.     else{
  160.         sprintf(err_str, "Unknown terminal type %s!", tv_stype);
  161.         puts(err_str);
  162.         exit(1);
  163.     }
  164.     }
  165.  
  166.     p = tcapbuf;
  167.     t = tgetstr("pc", &p);
  168.     if(t)
  169.       PC = *t;
  170.  
  171. #ifdef HEBREW
  172.     CB = tgetstr("cb",&p);
  173.     eobexist= (CB != NULL);
  174. #endif
  175.  
  176.     CL = tgetstr("cl", &p);
  177.     CM = tgetstr("cm", &p);
  178.     CE = tgetstr("ce", &p);
  179.     UP = tgetstr("up", &p);
  180.     SE = tgetstr("se", &p);
  181.     SO = tgetstr("so", &p);
  182.     DL = tgetstr("dl", &p);
  183.     AL = tgetstr("al", &p);
  184.     CS = tgetstr("cs", &p);
  185.     IC = tgetstr("ic", &p);
  186.     IM = tgetstr("im", &p);
  187.     EI = tgetstr("ei", &p);
  188.     DC = tgetstr("dc", &p);
  189.     DM = tgetstr("dm", &p);
  190.     ED = tgetstr("ed", &p);
  191.     SF = tgetstr("sf", &p);
  192.     SR = tgetstr("sr", &p);
  193.     TI = tgetstr("ti", &p);
  194.     TE = tgetstr("te", &p);
  195.  
  196.     eolexist = (CE != NULL);    /* will we be able to use clear to EOL? */
  197.     revexist = (SO != NULL);
  198.     if(DC == NULL && (DM == NULL || ED == NULL))
  199.       delchar = FALSE;
  200.     if(IC == NULL && (IM == NULL || EI == NULL))
  201.       inschar = FALSE;
  202.     if((CS==NULL || SF==NULL || SR==NULL) && (DL==NULL || AL==NULL))
  203.       scrollexist = FALSE;
  204.  
  205.     if(CL == NULL || CM == NULL || UP == NULL){
  206.     if(Pmaster == NULL){
  207.         puts("Incomplete termcap entry\n");
  208.         exit(1);
  209.     }
  210.     }
  211.     else{
  212.     KPPU   = tgetstr("kP", &p);
  213.     KPPD   = tgetstr("kN", &p);
  214.     KPHOME = tgetstr("kh", &p);
  215.     KU     = tgetstr("ku", &p);
  216.     KD     = tgetstr("kd", &p);
  217.     KL     = tgetstr("kl", &p);
  218.     KR     = tgetstr("kr", &p);
  219.     if(KU != NULL && (KL != NULL && (KR != NULL && KD != NULL))){
  220.         kpinsert(KU,K_PAD_UP);
  221.         kpinsert(KD,K_PAD_DOWN);
  222.         kpinsert(KL,K_PAD_LEFT);
  223.         kpinsert(KR,K_PAD_RIGHT);
  224.  
  225.         if(KPPU != NULL)
  226.           kpinsert(KPPU,K_PAD_PREVPAGE);
  227.         if(KPPD != NULL)
  228.           kpinsert(KPPD,K_PAD_NEXTPAGE);
  229.         if(KPHOME != NULL)
  230.           kpinsert(KPHOME,K_PAD_HOME);
  231.     }
  232.     }
  233.  
  234.     /*
  235.      * add default keypad sequences to the trie...
  236.      */
  237.     if(gmode&MDFKEY){
  238.     /*
  239.      * Initialize UW-modified NCSA telnet to use it's functionkeys
  240.      */
  241.     if(Pmaster == NULL){
  242.         puts("\033[99h");
  243.     }
  244.  
  245.     /*
  246.      * this is sort of a hack, but it allows us to use
  247.      * the function keys on pc's running telnet
  248.      */
  249.  
  250.     /* 
  251.      * UW-NDC/UCS vt10[02] application mode.
  252.      */
  253.     kpinsert("OP",F1);
  254.     kpinsert("OQ",F2);
  255.     kpinsert("OR",F3);
  256.     kpinsert("OS",F4);
  257.     kpinsert("Op",F5);
  258.     kpinsert("Oq",F6);
  259.     kpinsert("Or",F7);
  260.     kpinsert("Os",F8);
  261.     kpinsert("Ot",F9);
  262.     kpinsert("Ou",F10);
  263.     kpinsert("Ov",F11);
  264.     kpinsert("Ow",F12);
  265.  
  266.     /*
  267.      * special keypad functions
  268.      */
  269.     kpinsert("[4J",K_PAD_PREVPAGE);
  270.     kpinsert("[3J",K_PAD_NEXTPAGE);
  271.     kpinsert("[2J",K_PAD_HOME);
  272.     kpinsert("[N",K_PAD_END);
  273.  
  274.     /* 
  275.      * ANSI mode.
  276.      */
  277.     kpinsert("[=a",F1);
  278.     kpinsert("[=b",F2);
  279.     kpinsert("[=c",F3);
  280.     kpinsert("[=d",F4);
  281.     kpinsert("[=e",F5);
  282.     kpinsert("[=f",F6);
  283.     kpinsert("[=g",F7);
  284.     kpinsert("[=h",F8);
  285.     kpinsert("[=i",F9);
  286.     kpinsert("[=j",F10);
  287.     kpinsert("[=k",F11);
  288.     kpinsert("[=l",F12);
  289.  
  290.     HelpKeyNames = funckeynames;
  291.  
  292.     }
  293.     else{
  294.     HelpKeyNames = NULL;
  295.     }
  296.  
  297.     kpinsert("OA",K_PAD_UP);    /* DEC vt100, ANSI and cursor key mode. */
  298.     kpinsert("OB",K_PAD_DOWN);
  299.     kpinsert("OD",K_PAD_LEFT);
  300.     kpinsert("OC",K_PAD_RIGHT);
  301.  
  302.     kpinsert("[A",K_PAD_UP);    /* DEC vt100, ANSI, cursor key mode reset. */
  303.     kpinsert("[B",K_PAD_DOWN);
  304.     kpinsert("[D",K_PAD_LEFT);
  305.     kpinsert("[C",K_PAD_RIGHT);
  306.  
  307.     kpinsert("A",K_PAD_UP);    /* DEC vt52 mode. */
  308.     kpinsert("B",K_PAD_DOWN);
  309.     kpinsert("D",K_PAD_LEFT);
  310.     kpinsert("C",K_PAD_RIGHT);
  311.  
  312.     kpinsert("[215z",K_PAD_UP); /* Sun Console sequences. */
  313.     kpinsert("[221z",K_PAD_DOWN);
  314.     kpinsert("[217z",K_PAD_LEFT);
  315.     kpinsert("[219z",K_PAD_RIGHT);
  316.  
  317.     if (p >= &tcapbuf[TCAPSLEN]){
  318.     if(Pmaster == NULL){
  319.         puts("Terminal description too big!\n");
  320.         exit(1);
  321.     }
  322.     }
  323.  
  324.     ttopen();
  325.  
  326.     if(TI && !Pmaster) {
  327.     putpad(TI);            /* any init termcap requires */
  328.     if (CS)
  329.       putpad(tgoto(CS, term.t_nrow, 0)) ;
  330.     }
  331. }
  332.  
  333.  
  334. tcapclose()
  335. {
  336.     if(!Pmaster){
  337.     if(gmode&MDFKEY)
  338.       puts("\033[99l");        /* reset UW-NCSA telnet keys */
  339.  
  340.     if(TE)                /* any cleanup termcap requires */
  341.       putpad(TE);
  342.     }
  343.  
  344.     ttclose();
  345. }
  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. 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.  
  389.         if(temp == NULL){   /* add new val */
  390.         temp = newnode();
  391.         temp->value = *buf;
  392.         temp->func = 0;
  393.         temp->left = NULL;
  394.         temp->down = NULL;
  395.         trail->left = temp;
  396.         }
  397.     }
  398.  
  399.     if (*(++buf) == '\0'){
  400.         break;
  401.     }
  402.     else{
  403.         trail = temp;
  404.         temp = temp->down;
  405.     }
  406.     }
  407.     
  408.     if(temp != NULL)
  409.       temp->func = kval;
  410. }
  411.  
  412.  
  413.  
  414. /*
  415.  * tcapinsert - insert a character at the current character position.
  416.  *              IC takes precedence.
  417.  */
  418. tcapinsert(ch)
  419. register char    ch;
  420. {
  421. #ifndef HEBREW
  422.     if(IC != NULL){
  423.     putpad(IC);
  424.     ttputc(ch);
  425.     }
  426.     else{
  427.     putpad(IM);
  428.     ttputc(ch);
  429.     putpad(EI);
  430.     }
  431. #else
  432.     if(compose_heb)
  433.       ttputc(ch);
  434.     else{
  435.     if(IC != NULL){
  436.     putpad(IC);
  437.     ttputc(ch);
  438.     }
  439.     else{
  440.     putpad(IM);
  441.     ttputc(ch);
  442.     putpad(EI);
  443.     }
  444.   }
  445. #endif
  446. }
  447.  
  448.  
  449. /*
  450.  * tcapdelete - delete a character at the current character position.
  451.  */
  452. tcapdelete()
  453. {
  454. #ifndef HEBREW
  455.     if(DM == NULL && ED == NULL)
  456.       putpad(DC);
  457.     else{
  458.     putpad(DM);
  459.     putpad(DC);
  460.     putpad(ED);
  461.     }
  462. #else
  463.     if(compose_heb){
  464.       stdputc(' ');
  465.     }
  466.     else{
  467.       if(DM == NULL && ED == NULL)
  468.     putpad(DC);
  469.       else{
  470.     putpad(DM);
  471.     putpad(DC);
  472.     putpad(ED);
  473.       }
  474.     }
  475.  
  476. #endif
  477. }
  478.  
  479.  
  480. /*
  481.  * o_scrolldown - open a line at the given row position.
  482.  *                use either region scrolling or deleteline/insertline
  483.  *                to open a new line.
  484.  */
  485. o_scrolldown(row, n)
  486. register int row;
  487. register int n;
  488. {
  489.     register int i;
  490.  
  491.     if(CS != NULL){
  492.     putpad(tgoto(CS, term.t_nrow - 3, row));
  493.     tcapmove(row, 0);
  494.     for(i = 0; i < n; i++)
  495.       putpad( (SR != NULL && *SR != '\0') ? SR : "\n" );
  496.     putpad(tgoto(CS, term.t_nrow, 0));
  497.     tcapmove(row, 0);
  498.     }
  499.     else{
  500.     /*
  501.      * this code causes a jiggly motion of the keymenu when scrolling
  502.      */
  503.     for(i = 0; i < n; i++){
  504.         tcapmove(term.t_nrow - 3, 0);
  505.         putpad(DL);
  506.         tcapmove(row, 0);
  507.         putpad(AL);
  508.     }
  509. #ifdef    NOWIGGLYLINES
  510.     /*
  511.      * this code causes a sweeping motion up and down the display
  512.      */
  513.     tcapmove(term.t_nrow - 2 - n, 0);
  514.     for(i = 0; i < n; i++)
  515.       putpad(DL);
  516.     tcapmove(row, 0);
  517.     for(i = 0; i < n; i++)
  518.       putpad(AL);
  519. #endif
  520.     }
  521. }
  522.  
  523.  
  524. /*
  525.  * o_scrollup - open a line at the given row position.
  526.  *              use either region scrolling or deleteline/insertline
  527.  *              to open a new line.
  528.  */
  529. o_scrollup(row, n)
  530. register int row;
  531. register int n;
  532. {
  533.     register int i;
  534.  
  535.     if(CS != NULL){
  536.     putpad(tgoto(CS, term.t_nrow - 3, row));
  537.     /* setting scrolling region moves cursor to home */
  538.     tcapmove(term.t_nrow-3, 0);
  539.     for(i = 0;i < n; i++)
  540.       putpad((SF == NULL || SF[0] == '\0') ? "\n" : SF);
  541.     putpad(tgoto(CS, term.t_nrow, 0));
  542.     tcapmove(2, 0);
  543.     }
  544.     else{
  545.     for(i = 0; i < n; i++){
  546.         tcapmove(row, 0);
  547.         putpad(DL);
  548.         tcapmove(term.t_nrow - 3, 0);
  549.         putpad(AL);
  550.     }
  551. #ifdef  NOWIGGLYLINES
  552.     /* see note above */
  553.     tcapmove(row, 0);
  554.     for(i = 0; i < n; i++)
  555.       putpad(DL);
  556.     tcapmove(term.t_nrow - 2 - n, 0);
  557.     for(i = 0;i < n; i++)
  558.       putpad(AL);
  559. #endif
  560.     }
  561. }
  562.  
  563.  
  564. /*
  565.  * o_insert - use termcap info to optimized character insert
  566.  *            returns: true if it optimized output, false otherwise
  567.  */
  568. o_insert(c)
  569. char c;
  570. {
  571.     if(inschar){
  572.     tcapinsert(c);
  573.     return(1);            /* no problems! */
  574.     }
  575.  
  576.     return(0);                /* can't do it. */
  577. }
  578.  
  579.  
  580. /*
  581.  * o_delete - use termcap info to optimized character insert
  582.  *            returns true if it optimized output, false otherwise
  583.  */
  584. o_delete()
  585. {
  586.     if(delchar){
  587.     tcapdelete();
  588.     return(1);            /* deleted, no problem! */
  589.     }
  590.  
  591.     return(0);                /* no dice. */
  592. }
  593.  
  594.  
  595. tcapmove(row, col)
  596. register int row, col;
  597. {
  598. #ifdef HEBREW
  599.   if(compose_heb && hebmode)
  600.     col = term.t_ncol - col - 1;
  601. #endif
  602.     putpad(tgoto(CM, col, row));
  603. }
  604.  
  605.  
  606. tcapeeol()
  607. {
  608. #ifndef HEBREW
  609.     putpad(CE);
  610. #else
  611.     if(compose_heb && hebmode){
  612.       if(eobexist)putpad(CB);
  613.       else tputs("\033[1K",1,stdputc);      
  614.     }
  615.     else
  616.       putpad(CE);
  617. #endif
  618. }
  619.  
  620.  
  621. tcapeeop()
  622. {
  623.     putpad(CL);
  624. #ifdef HEBREW
  625.     if(compose_heb && hebmode)
  626.     tcapmove(0,0);
  627. #endif
  628. }
  629.  
  630.  
  631. tcaprev(state)        /* change reverse video status */
  632. int state;            /* FALSE = normal video, TRUE = reverse 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.     } 
  643.     else{
  644.     if (SE != NULL)
  645.       putpad(SE);
  646.     }
  647. }
  648.  
  649.  
  650. tcapbeep()
  651. {
  652.     ttputc(BEL);
  653. }
  654.  
  655.  
  656. putpad(str)
  657. char    *str;
  658. {
  659. #ifndef HEBREW
  660.     tputs(str, 1, ttputc);
  661. #else
  662.     if(compose_heb && hebmode)
  663.       tputs(str, 1, stdputc);
  664.     else
  665.       tputs(str, 1, ttputc);
  666. #endif
  667. }
  668.  
  669.  
  670. putnpad(str, n)
  671. char    *str;
  672. {
  673. #ifndef HEBREW
  674.     tputs(str, n, ttputc);
  675. #else
  676.     if(compose_heb && hebmode)
  677.       tputs(str, n, stdputc);
  678.     else
  679.       tputs(str, n, ttputc);
  680. #endif
  681. }
  682.  
  683. #ifdef HEBREW
  684. hide_cur()
  685. {
  686. tputs("\033[?25l",1,stdputc);
  687. }
  688. show_cur()
  689. {
  690. tputs("\033[?25h",1,stdputc);
  691. }
  692. #endif
  693.  
  694. #else
  695.  
  696. hello()
  697. {
  698. }
  699.  
  700. #endif /* TERMCAP */