home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / vmsvt.c < prev    next >
C/C++ Source or Header  |  1998-05-14  |  12KB  |  547 lines

  1. /*
  2.  *  Advanced VMS terminal driver
  3.  *
  4.  *  Knows about any terminal defined in SMGTERMS.TXT and TERMTABLE.TXT
  5.  *  located in SYS$SYSTEM.
  6.  *
  7.  *  Author:  Curtis Smith
  8.  *  Last Updated: 07/14/87
  9.  *
  10.  * $Header: /usr/build/vile/vile/RCS/vmsvt.c,v 1.34 1998/05/14 23:17:05 tom Exp $
  11.  *
  12.  */
  13.  
  14. #include    "estruct.h"        /* Emacs' structures        */
  15. #include    "edef.h"        /* Emacs' definitions        */
  16.  
  17. #if    DISP_VMSVT
  18.  
  19. #include    <descrip.h>        /* Descriptor definitions    */
  20. #include    <iodef.h>        /* to get IO$_SENSEMODE        */
  21. #include    <ttdef.h>        /* to get TT$_UNKNOWN        */
  22.  
  23. #include    <starlet.h>
  24. #include    <smgtrmptr.h>        /* to get SMG$K_??? definitions    */
  25. #include    <smg$routines.h>
  26.  
  27. /** Forward references **/
  28. static    void    vmsscrollregion (int top, int bot);
  29. static    void    vmsscroll_reg (int from, int to, int n);
  30. static    void    vmsscroll_delins (int from, int to, int n);
  31. static    void    vmsopen    (void);
  32. static    void    vmskopen (void);
  33. static    void    vmskclose (void);
  34. static    void    vmsmove (int row, int col);
  35. static    void    vmseeol    (void);
  36. static    void    vmseeop    (void);
  37. static    void    vmsbeep    (void);
  38. static    void    vmsrev    (UINT);
  39. static    int    vmscres    (const char *);
  40.  
  41. extern    int    eolexist, revexist;
  42. extern    char    sres[];
  43.  
  44. /** SMG stuff (just like termcap) */
  45. static    int    initialized;
  46. static    int    termtype;
  47. static    char *    begin_reverse;
  48. static    char *    end_reverse;
  49. static    char *    erase_to_end_line;
  50. static    char *    erase_whole_display;
  51.  
  52. static    char *    delete_line;
  53. static    char *    insert_line;
  54. static    char *    scroll_forw;
  55. static    char *    scroll_back;
  56. static    char *    scroll_regn;
  57.  
  58. /* Dispatch table. All hard fields just point into the terminal I/O code. */
  59. TERM    term    = {
  60.     24,                /* Max number of rows allowable */
  61.     /* Filled in */ 0,        /* Current number of rows used    */
  62.     132,                /* Max number of columns    */
  63.     /* Filled in */ 0,        /* Current number of columns    */
  64.     64,                /* Min margin for extended lines*/
  65.     8,                /* Size of scroll region    */
  66.     100,                /* # times thru update to pause */
  67.     vmsopen,            /* Open terminal at the start    */
  68.     ttclose,            /* Close terminal at end    */
  69.     vmskopen,            /* Open keyboard        */
  70.     vmskclose,            /* Close keyboard        */
  71.     ttgetc,                /* Get character from keyboard    */
  72.     ttputc,                /* Put character to display    */
  73.     tttypahead,            /* char ready for reading    */
  74.     ttflush,            /* Flush output buffers        */
  75.     vmsmove,            /* Move cursor, origin 0    */
  76.     vmseeol,            /* Erase to end of line        */
  77.     vmseeop,            /* Erase to end of page        */
  78.     vmsbeep,            /* Beep                */
  79.     vmsrev,                /* Set reverse video state    */
  80.     vmscres,            /* Change screen resolution    */
  81.     null_t_setfor,            /* N/A: Set foreground color    */
  82.     null_t_setback,            /* N/A: Set background color    */
  83.     null_t_setpal,            /* N/A: Set palette colors    */
  84.     null_t_scroll,            /* set at init-time        */
  85.     null_t_pflush,
  86.     null_t_icursor,
  87.     null_t_title,
  88.     null_t_watchfd,
  89.     null_t_unwatchfd,
  90. };
  91.  
  92. static    const    struct    {
  93.     char    *seq;
  94.     int    code;
  95. } keyseqs[] = {
  96.     { "\33[A",  KEY_Up },    { "\33A", KEY_Up },
  97.     { "\33[B",  KEY_Down },  { "\33B", KEY_Down },
  98.     { "\33[C",  KEY_Right }, { "\33C", KEY_Right },
  99.     { "\33[D",  KEY_Left },  { "\33D", KEY_Left },
  100.     { "\33OP",  KEY_KP_F1 }, { "\33P", KEY_KP_F1 },
  101.     { "\33OQ",  KEY_KP_F2 }, { "\33Q", KEY_KP_F2 },
  102.     { "\33OR",  KEY_KP_F3 }, { "\33R", KEY_KP_F3 },
  103.     { "\33OS",  KEY_KP_F4 }, { "\33S", KEY_KP_F4 },
  104. };
  105.  
  106. /***
  107.  *  ttputs  -  Send a string to ttputc
  108.  *
  109.  *  Nothing returned
  110.  ***/
  111. static void
  112. ttputs(char * string)            /* String to write        */
  113. {
  114.     if (string)
  115.         while (*string != EOS)
  116.             ttputc(*string++);
  117. }
  118.  
  119. /***
  120.  *  putpad_tgoto - 2-argument request
  121.  *
  122.  *  Nothing returned
  123.  ***/
  124. static void
  125. putpad_tgoto(request_code, parm1, parm2)
  126. {
  127.     char buffer[32];
  128.     int ret_length;
  129.     static int max_buffer_length = sizeof(buffer);
  130.     static int arg_list[3] = { 2 };
  131.     register char * cp;
  132.  
  133.     register int i;
  134.  
  135.     if (!initialized) {
  136.         printf("\n");
  137.         return;
  138.     }
  139.  
  140.     /* Set the arguments into the arg_list array
  141.      */
  142.     arg_list[1] = parm1;
  143.     arg_list[2] = parm2;
  144.  
  145.     if ((smg$get_term_data(        /* Get terminal data        */
  146.         &termtype,        /* Terminal table address    */
  147.         &request_code,        /* Request code            */
  148.         &max_buffer_length,    /* Maximum buffer length    */
  149.         &ret_length,        /* Return length        */
  150.         buffer,            /* Capability data buffer    */
  151.         arg_list)        /* Argument list array        */
  152.  
  153.     /* We'll know soon enough if this doesn't work        */
  154.             & 1) == 0) {
  155.                 ttputs("OOPS");
  156.                 return;
  157.             }
  158.  
  159.     /* Send out resulting sequence                */
  160.     i = ret_length;
  161.     cp = buffer;
  162.     while (i-- > 0)
  163.         ttputc(*cp++);
  164. }
  165.  
  166.  
  167. /***
  168.  *  vmsmove  -  Move the cursor (0 origin)
  169.  *
  170.  *  Nothing returned
  171.  ***/
  172. static void
  173. vmsmove (int row, int col)
  174. {
  175.     putpad_tgoto(SMG$K_SET_CURSOR_ABS, row+1, col+1);
  176. }
  177.  
  178. /***
  179.  *  vmsrev  -  Set the reverse video status
  180.  *
  181.  *  Nothing returned
  182.  ***/
  183. static void
  184. vmsrev(UINT status)
  185. {
  186.     if (status)
  187.         ttputs(begin_reverse);
  188.     else
  189.         ttputs(end_reverse);
  190. }
  191.  
  192. /***
  193.  *  vmscres  -  Change screen resolution (which it doesn't)
  194.  *
  195.  *  Nothing returned
  196.  ***/
  197. static int
  198. vmscres(const char *res)
  199. {
  200.     /* But it could.  For vt100/vt200s, one could switch from
  201.     80 and 132 columns modes */
  202.     return 0;
  203. }
  204.  
  205. /***
  206.  *  vmseeol  -  Erase to end of line
  207.  *
  208.  *  Nothing returned
  209.  ***/
  210. static void
  211. vmseeol(void)
  212. {
  213.     ttputs(erase_to_end_line);
  214. }
  215.  
  216.  
  217. /***
  218.  *  vmseeop  -  Erase to end of page (clear screen)
  219.  *
  220.  *  Nothing returned
  221.  ***/
  222. static void
  223. vmseeop(void)
  224. {
  225.     ttputs(erase_whole_display);
  226. }
  227.  
  228.  
  229. /***
  230.  *  vmsbeep  -  Ring the bell
  231.  *
  232.  *  Nothing returned
  233.  ***/
  234. static void
  235. vmsbeep(void)
  236. {
  237.     ttputc(BEL);
  238. }
  239.  
  240.  
  241. /***
  242.  *  vmsgetstr  -  Get an SMG string capability by name
  243.  *
  244.  *  Returns:    Escape sequence
  245.  *        NULL    No escape sequence available
  246.  ***/
  247. static char *
  248. vmsgetstr(int request_code)
  249. {
  250.     register char * result;
  251.     static char seq_storage[1024];
  252.     static char * buffer = seq_storage;
  253.     static int arg_list[] = { 1, 1 };
  254.     int max_buffer_length, ret_length;
  255.  
  256.     /*  Precompute buffer length */
  257.  
  258.     max_buffer_length = (seq_storage + sizeof(seq_storage)) - buffer;
  259.  
  260.     /* Get terminal commands sequence from master table */
  261.  
  262.     if ((smg$get_term_data(    /* Get terminal data        */
  263.         &termtype,    /* Terminal table address    */
  264.         &request_code,    /* Request code            */
  265.         &max_buffer_length,/* Maximum buffer length    */
  266.         &ret_length,    /* Return length        */
  267.         buffer,        /* Capability data buffer    */
  268.         arg_list)    /* Argument list array        */
  269.  
  270.     /* If this doesn't work, try again with no arguments */
  271.  
  272.         & 1) == 0 &&
  273.  
  274.         (smg$get_term_data(    /* Get terminal data        */
  275.             &termtype,    /* Terminal table address    */
  276.             &request_code,    /* Request code            */
  277.             &max_buffer_length,/* Maximum buffer length    */
  278.             &ret_length,    /* Return length        */
  279.             buffer)        /* Capability data buffer    */
  280.  
  281.     /* Return NULL pointer if capability is not available */
  282.  
  283.             & 1) == 0)
  284.                 return NULL;
  285.  
  286.     /* Check for empty result */
  287.     if (ret_length == 0)
  288.         return NULL;
  289.  
  290.     /* Save current position so we can return it to caller */
  291.  
  292.     result = buffer;
  293.  
  294.     /* NIL terminate the sequence for return */
  295.  
  296.     buffer[ret_length] = 0;
  297.  
  298.     /* Advance buffer */
  299.  
  300.     buffer += ret_length + 1;
  301.  
  302.     /* Return capability to user */
  303.     return result;
  304. }
  305.  
  306.  
  307. /** I/O information block definitions **/
  308. struct iosb {            /* I/O status block            */
  309.     short    i_cond;        /* Condition value            */
  310.     short    i_xfer;        /* Transfer count            */
  311.     long    i_info;        /* Device information            */
  312. };
  313. struct termchar {        /* Terminal characteristics        */
  314.     char    t_class;    /* Terminal class            */
  315.     char    t_type;        /* Terminal type            */
  316.     short    t_width;    /* Terminal width in characters        */
  317.     long    t_mandl;    /* Terminal's mode and length        */
  318.     long    t_extend;    /* Extended terminal characteristics    */
  319. };
  320. static struct termchar tc;    /* Terminal characteristics        */
  321.  
  322. /***
  323.  *  vmsgtty - Get terminal type from system control block
  324.  *
  325.  *  Nothing returned
  326.  ***/
  327. static void
  328. vmsgtty(void)
  329. {
  330.     short fd;
  331.     int status;
  332.     struct iosb iostatus;
  333.     $DESCRIPTOR(devnam, "SYS$COMMAND");
  334.  
  335.     /* Assign input to a channel */
  336.     status = sys$assign(&devnam, &fd, 0, 0);
  337.     if ((status & 1) == 0)
  338.         tidy_exit(status);
  339.  
  340.     /* Get terminal characteristics */
  341.     status = sys$qiow(        /* Queue and wait        */
  342.         0,            /* Wait on event flag zero    */
  343.         fd,            /* Channel to input terminal    */
  344.         IO$_SENSEMODE,        /* Get current characteristic    */
  345.         &iostatus,        /* Status after operation    */
  346.         0, 0,            /* No AST service        */
  347.         &tc,            /* Terminal characteristics buf */
  348.         sizeof(tc),        /* Size of the buffer        */
  349.         0, 0, 0, 0);        /* P3-P6 unused            */
  350.  
  351.     /* De-assign the input device */
  352.     if ((sys$dassgn(fd) & 1) == 0)
  353.         tidy_exit(status);
  354.  
  355.     /* Jump out if bad status */
  356.     if ((status & 1) == 0)
  357.         tidy_exit(status);
  358.     if ((iostatus.i_cond & 1) == 0)
  359.         tidy_exit(iostatus.i_cond);
  360. }
  361.  
  362.  
  363. /***
  364.  *  vmsopen  -  Get terminal type and open terminal
  365.  *
  366.  *  Nothing returned
  367.  ***/
  368. static void
  369. vmsopen(void)
  370. {
  371.     int    i;
  372.  
  373.     /* Get terminal type */
  374.     vmsgtty();
  375.     if (tc.t_type == TT$_UNKNOWN) {
  376.         printf("Terminal type is unknown!\n");
  377.         printf("Try set your terminal type with SET TERMINAL/INQUIRE\n");
  378.         printf("Or get help on SET TERMINAL/DEVICE_TYPE\n");
  379.         tidy_exit(3);
  380.     }
  381.  
  382.     /* Access the system terminal definition table for the        */
  383.     /* information of the terminal type returned by IO$_SENSEMODE    */
  384.     if ((smg$init_term_table_by_type(&tc.t_type, &termtype) & 1) == 0) {
  385.         return;
  386.     }
  387.  
  388.     /* Set sizes */
  389.     term.t_nrow = ((UINT) tc.t_mandl >> 24);
  390.     term.t_ncol = tc.t_width;
  391.  
  392.     if (term.t_mrow < term.t_nrow)
  393.         term.t_mrow = term.t_nrow;
  394.  
  395.     if (term.t_mcol < term.t_ncol)
  396.         term.t_mcol = term.t_ncol;
  397.  
  398.     /* Get some capabilities */
  399.     begin_reverse    = vmsgetstr(SMG$K_BEGIN_REVERSE);
  400.     end_reverse    = vmsgetstr(SMG$K_END_REVERSE);
  401.     revexist    = begin_reverse    != NULL
  402.         &&      end_reverse    != NULL;
  403.  
  404.     erase_to_end_line = vmsgetstr(SMG$K_ERASE_TO_END_LINE);
  405.     eolexist = erase_whole_display != NULL;
  406.  
  407.     erase_whole_display = vmsgetstr(SMG$K_ERASE_WHOLE_DISPLAY);
  408.  
  409.     insert_line    = vmsgetstr(SMG$K_INSERT_LINE);        /* al */
  410.     delete_line    = vmsgetstr(SMG$K_DELETE_LINE);        /* dl */
  411.     scroll_forw    = vmsgetstr(SMG$K_SCROLL_FORWARD);    /* SF */
  412.     scroll_back    = vmsgetstr(SMG$K_SCROLL_REVERSE);    /* SR */
  413.     scroll_regn    = vmsgetstr(SMG$K_SET_SCROLL_REGION);    /* CS */
  414.  
  415.     /*
  416.      * I tried 'vmsgetstr()' for a VT100 terminal and it had no codes
  417.      * for insert_line or for delete_line.  (Have to work up a test for
  418.      * that).
  419.      */
  420.  
  421.     if (scroll_regn && scroll_back) {
  422.         if (scroll_forw == NULL) /* assume '\n' scrolls forward */
  423.             scroll_forw = "\n";
  424.         term.t_scroll = vmsscroll_reg;
  425.     } else if (delete_line && insert_line) {
  426.         term.t_scroll = vmsscroll_delins;
  427.     } else {
  428.         term.t_scroll = null_t_scroll;
  429.     }
  430.  
  431.     /* Set resolution */
  432.     (void)strcpy(sres, "NORMAL");
  433.  
  434.     /* Open terminal I/O drivers */
  435.     ttopen();
  436.  
  437.     /* Set predefined keys */
  438.     for (i = TABLESIZE(keyseqs); i--; ) {
  439.         addtosysmap(keyseqs[i].seq, strlen(keyseqs[i].seq), keyseqs[i].code);
  440.     }
  441.     initialized = TRUE;
  442. }
  443.  
  444.  
  445. /***
  446.  *  vmskopen  -  Open keyboard (not used)
  447.  *
  448.  *  Nothing returned
  449.  ***/
  450. static void
  451. vmskopen(void)
  452. {
  453. }
  454.  
  455.  
  456. /***
  457.  *  vmskclose  -  Close keyboard (not used)
  458.  *
  459.  *  Nothing returned
  460.  ***/
  461. static void
  462. vmskclose(void)
  463. {
  464. }
  465.  
  466. /* copied/adapted from 'tcap.c' 19-apr-1993 dickey@software.org */
  467.  
  468. /* move howmany lines starting at from to to */
  469. static void
  470. vmsscroll_reg(int from, int to, int n)
  471. {
  472.     int i;
  473.     if (to == from) return;
  474.     if (to < from) {
  475.         vmsscrollregion(to, from + n - 1);
  476.         vmsmove(from + n - 1,0);
  477.         for (i = from - to; i > 0; i--)
  478.             ttputs(scroll_forw);
  479.     } else { /* from < to */
  480.         vmsscrollregion(from, to + n - 1);
  481.         vmsmove(from,0);
  482.         for (i = to - from; i > 0; i--)
  483.             ttputs(scroll_back);
  484.     }
  485.     vmsscrollregion(0, term.t_nrow-1);
  486. }
  487.  
  488. /*
  489. OPT_PRETTIER_SCROLL is prettier but slower -- it scrolls
  490.         a line at a time instead of all at once.
  491. */
  492.  
  493. /* move howmany lines starting at from to to */
  494. static void
  495. vmsscroll_delins(int from, int to, int n)
  496. {
  497.     int i;
  498.     if (to == from) return;
  499.     /* patch: should make this more like 'tcap.c', or merge logic somehow */
  500. #if OPT_PRETTIER_SCROLL
  501.     if (absol(from-to) > 1) {
  502.         vmsscroll_delins(from, (from<to) ? to-1:to+1, n);
  503.         if (from < to)
  504.             from = to-1;
  505.         else
  506.             from = to+1;
  507.     }
  508. #endif
  509.     if (to < from) {
  510.         vmsmove(to,0);
  511.         for (i = from - to; i > 0; i--)
  512.             ttputs(delete_line);
  513.         vmsmove(to+n,0);
  514.         for (i = from - to; i > 0; i--)
  515.             ttputs(insert_line);
  516.     } else {
  517.         vmsmove(from+n,0);
  518.         for (i = to - from; i > 0; i--)
  519.             ttputs(delete_line);
  520.         vmsmove(from,0);
  521.         for (i = to - from; i > 0; i--)
  522.             ttputs(insert_line);
  523.     }
  524. }
  525.  
  526. /* cs is set up just like cm, so we use tgoto... */
  527. static void
  528. vmsscrollregion(int top, int bot)
  529. {
  530.     putpad_tgoto(SMG$K_SET_SCROLL_REGION, top+1, bot+1);
  531. }
  532.  
  533.  
  534. #else
  535.  
  536. /***
  537.  *  hellovms  -  Avoid error because of empty module
  538.  *
  539.  *  Nothing returned
  540.  ***/
  541. void
  542. hellovms(void)
  543. {
  544. }
  545.  
  546. #endif
  547.