home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 198_02 / vmsvt.c < prev    next >
C/C++ Source or Header  |  1990-01-23  |  13KB  |  601 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.  
  11. #include    <stdio.h>        /* Standard I/O package        */
  12. #include    "estruct.h"        /* Emacs' structures        */
  13. #include    "edef.h"        /* Emacs' definitions        */
  14.  
  15. #if    VMSVT
  16.  
  17. #include     <descrip.h>        /* Descriptor definitions    */
  18.  
  19. /*  These would normally come from iodef.h and ttdef.h  */
  20. #define IO$_SENSEMODE    0x27        /* Sense mode of terminal    */
  21.  
  22. #include    <ttdef.h>
  23.  
  24. /* #define TT$_UNKNOWN    0x00 */        /* Unknown terminal        */
  25.  
  26. /** Forward references **/
  27. int vmsopen(), vmsclose(), vmskopen(), vmskclose(), ttgetc(), ttputc();
  28. int ttflush(), vmsmove(), vmseeol(), vmseeop(), vmsbeep(), vmsrev();
  29. int vmscres();
  30. extern int eolexist, revexist;
  31. extern char sres[];
  32.  
  33. #define    ESC    27
  34.  
  35. #if COLOR
  36. int vmsfcol(), vmsbcol();
  37.  
  38. int isansi = 0;        /* has support for ansi color */
  39. int cfcolor = -1;    /* current forground color */
  40. int cbcolor = -1;    /* current background color */
  41. int usedcolor = 0;    /* true if used a color */
  42. #endif
  43.  
  44. /** SMG stuff **/
  45. static char * begin_reverse, * end_reverse, * erase_to_end_line;
  46. static char * erase_whole_display;
  47. static int termtype;
  48. static int vmstermtype;
  49.  
  50. #define SMG$K_BEGIN_REVERSE        0x1bf
  51. #define SMG$K_END_REVERSE        0x1d6
  52. #define SMG$K_SET_CURSOR_ABS        0x23a
  53. #define SMG$K_ERASE_WHOLE_DISPLAY    0x1da
  54. #define SMG$K_ERASE_TO_END_LINE        0x1d9
  55.  
  56.  
  57. /* Dispatch table. All hard fields just point into the terminal I/O code. */
  58. TERM    term    = {
  59.     24 - 1,                /* Max number of rows allowable */
  60.     /* Filled in */ - 1,        /* Current number of rows used    */
  61.     132,                /* Max number of columns    */
  62.     /* Filled in */ 0,        /* Current number of columns    */
  63.     64,                /* Min margin for extended lines*/
  64.     8,                /* Size of scroll region    */
  65.     100,                /* # times thru update to pause */
  66.     vmsopen,            /* Open terminal at the start    */
  67.     vmsclose,            /* Close terminal at end    */
  68.     vmskopen,            /* Open keyboard        */
  69.     vmskclose,            /* Close keyboard        */
  70.     ttgetc,                /* Get character from keyboard    */
  71.     ttputc,                /* Put character to display    */
  72.     ttflush,            /* Flush output buffers        */
  73.     vmsmove,            /* Move cursor, origin 0    */
  74.     vmseeol,            /* Erase to end of line        */
  75.     vmseeop,            /* Erase to end of page        */
  76.     vmsbeep,            /* Beep                */
  77.     vmsrev,                /* Set reverse video state    */
  78.     vmscres                /* Change screen resolution    */
  79. #if    COLOR
  80.     , vmsfcol,            /* Set forground color        */
  81.     vmsbcol                /* Set background color        */
  82. #endif
  83. };
  84.  
  85. int oldwidth;
  86. int vmsinrev;
  87.  
  88. extern char obuf[NOBUF];    /* output buffer */
  89. extern int nobuf;        /* # of bytes in obuf */
  90.  
  91. #define fastputc(c)    {if (nobuf >= NOBUF) ttflush(); obuf[nobuf++] = c;}
  92.  
  93. /***
  94.  *  ttputs  -  Send a string to ttputc
  95.  *
  96.  *  Nothing returned
  97.  ***/
  98. ttputs(string)
  99. char * string;                /* String to write        */
  100. {
  101.     if (string)
  102.         while (*string != '\0')
  103.             fastputc(*string++);
  104. }
  105.  
  106. /***
  107.  * ttputi - Send an integer to ttputc
  108.  ***/
  109. ttputi(i)
  110. int i;
  111. {
  112.     char buf[20];
  113.     int len;
  114.  
  115.     if (i < 0) {ttputc('-'); i = -i;}
  116.     len = 0;
  117.     do {
  118.         buf[len++] = '0' + i % 10;
  119.         i /= 10;
  120.     } while (i > 0);
  121.  
  122.     while (len-- > 0)
  123.         fastputc(buf[len]);
  124. }
  125.  
  126. /***
  127.  *  vmsmove  -  Move the cursor (0 origin)
  128.  *
  129.  *  Nothing returned
  130.  ***/
  131. vmsmove(row, col)
  132. int row;                /* Row position            */
  133. int col;                /* Column position        */
  134. {
  135.     char buffer[32];
  136.     int ret_length;
  137.     static int request_code = SMG$K_SET_CURSOR_ABS;
  138.     static int max_buffer_length = sizeof(buffer);
  139.     static int arg_list[3] = { 2 };
  140.     register char * cp;
  141.  
  142.     register int i;
  143.  
  144.     if (row == phrow+1 && col == 0 && row != scrlbot) {
  145.         fastputc(13); fastputc(10);
  146.     }
  147.  
  148.     else if (vmstermtype == TT$_UNKNOWN) {
  149.         fastputc('\033');    fastputc('=');
  150.         fastputc(row+' ');    fastputc(col+' ');
  151.     }
  152.  
  153.     else {
  154.  
  155.         /* Set the arguments into the arg_list array
  156.          * SMG assumes the row/column positions are 1 based (boo!)
  157.          */
  158.         arg_list[1] = row + 1;
  159.         arg_list[2] = col + 1;
  160.  
  161.         if ((smg$get_term_data(        /* Get terminal data    */
  162.             &termtype,        /* Terminal table address */
  163.             &request_code,        /* Request code        */
  164.             &max_buffer_length,    /* Maximum buffer length */
  165.             &ret_length,        /* Return length    */
  166.             buffer,            /* Capability data buffer */
  167.             arg_list)        /* Argument list array    */
  168.  
  169.         /* We'll know soon enough if this doesn't work        */
  170.                 & 1) == 0) {
  171.                     ttputs("OOPS");
  172.                     return;
  173.                 }
  174.  
  175.         /* Send out resulting sequence                */
  176.         i = ret_length;
  177.         cp = buffer;
  178.         while (i-- > 0)
  179.             fastputc(*cp++);
  180.     }
  181.     phrow = row;
  182. }
  183.  
  184.  
  185. /***
  186.  *  vmsrev  -  Set the reverse video status
  187.  *
  188.  *  Nothing returned
  189.  ***/
  190. vmsrev(status)
  191. int status;                /* TRUE if setting reverse    */
  192. {
  193. #if    COLOR
  194.     if (usedcolor) return;
  195. #endif
  196.     if (vmsinrev == status) return;
  197.     vmsinrev = status;
  198.     if (status)
  199.         ttputs(begin_reverse);
  200.     else 
  201.         ttputs(end_reverse);
  202. }
  203.  
  204. /***
  205.  *  vmscres  -  Change screen resolution (which it doesn't)
  206.  *
  207.  *  Nothing returned
  208.  ***/
  209. vmscres()
  210. {
  211.     /* But it could.  For vt100/vt200s, one could switch from
  212.     80 and 132 columns modes */
  213. }
  214.  
  215.  
  216. #if    COLOR
  217. vmsparm(n)
  218. register int n;
  219. {
  220.     register q,r;
  221.  
  222.     q = n/10;
  223.     if (q != 0)    {
  224.         r = q/10;
  225.         if (r != 0)    {fastputc('0' + r%10);}
  226.         fastputc('0' + q%10);
  227.     }
  228.     fastputc('0' + n%10);
  229. }
  230.  
  231. /***
  232.  *  vmsfcol  -  Set the forground color
  233.  *
  234.  *  Nothing returned
  235.  ***/
  236. vmsfcol(color)
  237. int color;
  238. {
  239.     if (!usedcolor || color == cfcolor)    return;
  240.     fastputc(ESC);
  241.     fastputc('[');
  242.     vmsparm(color + 30);
  243.     fastputc('m');
  244.     cfcolor = color;
  245. }
  246.  
  247. /***
  248.  *  vmsbcol  -  Set the background color
  249.  *
  250.  *  Nothing returned
  251.  ***/
  252. vmsbcol(color)
  253. int color;
  254. {
  255.     if (!usedcolor || color == cbcolor)    return;
  256.     fastputc(ESC);
  257.     fastputc('[');
  258.     vmsparm(color + 40);
  259.     fastputc('m');
  260.     cbcolor = color;
  261. }
  262. #endif
  263.  
  264. /***
  265.  *  vmseeol  -  Erase to end of line
  266.  *
  267.  *  Nothing returned
  268.  ***/
  269. vmseeol()
  270. {
  271. #if    COLOR
  272.     vmsfcol(gfcolor);
  273.     vmsbcol(gbcolor);
  274. #endif
  275.     ttputs(erase_to_end_line);
  276. }
  277.  
  278.  
  279. /***
  280.  *  vmseeop  -  Erase to end of page (clear screen)
  281.  *
  282.  *  Nothing returned
  283.  ***/
  284. vmseeop()
  285. {
  286. #if    COLOR
  287.     vmsfcol(gfcolor);
  288.     vmsbcol(gbcolor);
  289. #endif
  290.     ttputs(erase_whole_display);
  291.     phrow = 1000;
  292. }
  293.  
  294.  
  295. /***
  296.  *  vmsbeep  -  Ring the bell
  297.  *
  298.  *  Nothing returned
  299.  ***/
  300. vmsbeep()
  301. {
  302.     fastputc('\007');
  303. }
  304.  
  305.  
  306. /***
  307.  *  vmsgetstr  -  Get an SMG string capability by name
  308.  *
  309.  *  Returns:    Escape sequence
  310.  *        NULL    No escape sequence available
  311.  ***/ 
  312. char * vmsgetstr(request_code)
  313. int request_code;            /* Request code            */
  314. {
  315.     register char * result;
  316.     static char seq_storage[1024];
  317.     static char * buffer = seq_storage;
  318.     static int arg_list[2] = { 1, 1 };
  319.     int max_buffer_length, ret_length;
  320.  
  321.     /*  Precompute buffer length */
  322.     
  323.     max_buffer_length = (seq_storage + sizeof(seq_storage)) - buffer;
  324.  
  325.     /* Get terminal commands sequence from master table */
  326.  
  327.     if ((smg$get_term_data(    /* Get terminal data        */
  328.         &termtype,    /* Terminal table address    */
  329.         &request_code,    /* Request code            */
  330.         &max_buffer_length,/* Maximum buffer length    */
  331.         &ret_length,    /* Return length        */
  332.         buffer,        /* Capability data buffer    */
  333.         arg_list)    /* Argument list array        */
  334.  
  335.     /* If this doesn't work, try again with no arguments */
  336.     
  337.         & 1) == 0 && 
  338.  
  339.         (smg$get_term_data(    /* Get terminal data        */
  340.             &termtype,    /* Terminal table address    */
  341.             &request_code,    /* Request code            */
  342.             &max_buffer_length,/* Maximum buffer length    */
  343.             &ret_length,    /* Return length        */
  344.             buffer)        /* Capability data buffer    */
  345.  
  346.     /* Return NULL pointer if capability is not available */
  347.     
  348.             & 1) == 0)
  349.                 return NULL;
  350.  
  351.     /* Check for empty result */
  352.     if (ret_length == 0)
  353.         return NULL;
  354.     
  355.     /* Save current position so we can return it to caller */
  356.  
  357.     result = buffer;
  358.  
  359.     /* NIL terminate the sequence for return */
  360.     
  361.     buffer[ret_length] = 0;
  362.  
  363.     /* Advance buffer */
  364.  
  365.     buffer += ret_length + 1;
  366.  
  367.     /* Return capability to user */
  368.     return result;
  369. }
  370.  
  371.  
  372. /** I/O information block definitions **/
  373. struct iosb {            /* I/O status block            */
  374.     short    i_cond;        /* Condition value            */
  375.     short    i_xfer;        /* Transfer count            */
  376.     long    i_info;        /* Device information            */
  377. };
  378. struct termchar {        /* Terminal characteristics        */
  379.     char    t_class;    /* Terminal class            */
  380.     char    t_type;        /* Terminal type            */
  381.     short    t_width;    /* Terminal width in characters        */
  382.     long    t_mandl;    /* Terminal's mode and length        */
  383.     long    t_extend;    /* Extended terminal characteristics    */
  384. };
  385. static struct termchar tc;    /* Terminal characteristics        */
  386.  
  387. /***
  388.  *  vmsgtty - Get terminal type from system control block
  389.  *
  390.  *  Nothing returned
  391.  ***/
  392. vmsgtty()
  393. {
  394.     short fd;
  395.     int status;
  396.     struct iosb iostatus;
  397.     $DESCRIPTOR(devnam, "SYS$INPUT");
  398.  
  399.     /* Assign input to a channel */
  400.     status = sys$assign(&devnam, &fd, 0, 0);
  401.     if ((status & 1) == 0)
  402.         exit (status);
  403.  
  404.     /* Get terminal characteristics */
  405.     status = sys$qiow(        /* Queue and wait        */
  406.         0,            /* Wait on event flag zero    */
  407.         fd,            /* Channel to input terminal    */
  408.         IO$_SENSEMODE,        /* Get current characteristic    */
  409.         &iostatus,        /* Status after operation    */
  410.         0, 0,            /* No AST service        */
  411.         &tc,            /* Terminal characteristics buf */
  412.         sizeof(tc),        /* Size of the buffer        */
  413.         0, 0, 0, 0);        /* P3-P6 unused            */
  414.  
  415.     /* De-assign the input device */
  416.     if ((sys$dassgn(fd) & 1) == 0)
  417.         exit(status);
  418.  
  419.     /* Jump out if bad status */
  420.     if ((status & 1) == 0)
  421.         exit(status);
  422.     if ((iostatus.i_cond & 1) == 0)
  423.         exit(iostatus.i_cond);
  424. }
  425.  
  426.  
  427. /***
  428.  *  vmsopen  -  Get terminal type and open terminal
  429.  *
  430.  *  Nothing returned
  431.  ***/
  432. vmsopen()
  433. {
  434.     phrow = scrltop = scrlbot = 1000;
  435.     vmsinrev = FAILED;
  436.  
  437.     /* Get terminal type */
  438.     vmsgtty();
  439.     vmstermtype = tc.t_type;
  440.  
  441.     if (vmstermtype == TT$_UNKNOWN) {
  442. #if    0
  443.         printf("Terminal type is unknown!\n");
  444.         printf("Try set your terminal type with SET TERMINAL/INQUIRE\n");
  445.         printf("Or get help on SET TERMINAL/DEVICE_TYPE\n");
  446.         exit(3);
  447. #endif
  448.         /* assume ADM3A */
  449.  
  450.         /* Set sizes */
  451.         term.t_nrow = 80;
  452.         term.t_ncol = 24;
  453.  
  454.         /* set some capabilities */
  455.         begin_reverse = "";
  456.         end_reverse = "";
  457.         revexist = FALSE;
  458.         erase_to_end_line = "";
  459.         eolexist = FALSE;
  460.         erase_whole_display = "\032";
  461.  
  462.         /* Set resolution */
  463.         strcpy(sres, "NORMAL");
  464.  
  465.         oldwidth = term.t_ncol;
  466.         isvt100 = FALSE;
  467.  
  468.         /* Open terminal I/O drivers */
  469.         ttopen();
  470.  
  471.         return;
  472.     }
  473.  
  474.     /* Access the system terminal definition table for the        */
  475.     /* information of the terminal type returned by IO$_SENSEMODE    */
  476.     if ((smg$init_term_table_by_type(&tc.t_type, &termtype) & 1) == 0)
  477.         return -1;
  478.         
  479.     /* Set sizes */
  480.     term.t_nrow = ((unsigned int) tc.t_mandl >> 24) - 1;
  481.     term.t_ncol = tc.t_width;
  482.  
  483.     /* Get some capabilities */
  484.     begin_reverse = vmsgetstr(SMG$K_BEGIN_REVERSE);
  485.     end_reverse = vmsgetstr(SMG$K_END_REVERSE);
  486.     revexist = begin_reverse != NULL && end_reverse != NULL;
  487.     erase_to_end_line = vmsgetstr(SMG$K_ERASE_TO_END_LINE);
  488.     eolexist = erase_whole_display != NULL;
  489.     erase_whole_display = vmsgetstr(SMG$K_ERASE_WHOLE_DISPLAY);
  490.  
  491.     /* Set resolution */
  492.     strcpy(sres, "NORMAL");
  493.  
  494.     oldwidth = term.t_ncol;
  495.     switch (vmstermtype) {
  496.         case TT$_VT100:
  497.         case TT$_VT101:
  498.         case TT$_VT102:
  499.         case TT$_VT105:
  500.         case TT$_VT125:
  501.         case TT$_VT131:
  502.         case TT$_VT132:
  503.         case TT$_VT200_SERIES:
  504.             isvt100 = TRUE;
  505.             break;
  506.         default:
  507.             isvt100 = FALSE;
  508.             break;
  509.     }
  510. #if    COLOR
  511.     isansi = isvt100;
  512.     cfcolor = -1;
  513.     cbcolor = -1;
  514. #endif
  515.     if (isvt100) {
  516.         ttputs("\033=");    /* enter keypad mode */
  517.         if (!eolexist) {
  518.             erase_to_end_line = "\033[K";
  519.             eolexist = TRUE;
  520.         }
  521.     }
  522.  
  523.     /* Open terminal I/O drivers */
  524.     ttopen();
  525. }
  526.  
  527. vmsclose()
  528. {
  529.     if (isvt100) {
  530.         ttputs("\033>");    /* leave keypad mode */
  531.         ttsetwid(oldwidth);
  532.     }
  533. #if    COLOR
  534.     if (usedcolor) {
  535.         vmsfcol(7);
  536.         vmsbcol(0);
  537.     }
  538. #endif
  539.     ttclose();
  540. }
  541.  
  542.  
  543. /***
  544.  *  vmskopen  -  Open keyboard (not used)
  545.  *
  546.  *  Nothing returned
  547.  ***/
  548. vmskopen()
  549. {
  550. }
  551.  
  552.  
  553. /***
  554.  *  vmskclose  -  Close keyboard (not used)
  555.  *
  556.  *  Nothing returned
  557.  ***/
  558. vmskclose()
  559. {
  560. }
  561.  
  562.  
  563. /***
  564.  *  fnclabel  -  Label function keys (not used)
  565.  *
  566.  *  Nothing returned
  567.  ***/
  568. #if    FLABEL
  569. fnclabel(f, n)        /* label a function key */
  570. int f,n;    /* default flag, numeric argument [unused] */
  571. {
  572.     /* on machines with no function keys...don't bother */
  573.     return(TRUE);
  574. }
  575. #endif
  576.  
  577.  
  578. /***
  579.  *  spal  -  Set palette type  (Are you kidding?)
  580.  *
  581.  *  Nothing returned
  582.  ***/
  583. spal(dummy)
  584. char *dummy;
  585. {
  586. }
  587.  
  588. #else
  589.  
  590. /***
  591.  *  hellovms  -  Avoid error because of empty module
  592.  *
  593.  *  Nothing returned
  594.  ***/
  595. hellovms()
  596. {
  597. }
  598.  
  599. #endif
  600.  
  601.