home *** CD-ROM | disk | FTP | other *** search
/ Der Mediaplex Sampler - Die 6 von Plex / 6_v_plex.zip / 6_v_plex / DISK5 / DOS_50 / PVIC.ZIP / TERMCAP.C < prev    next >
C/C++ Source or Header  |  1993-04-21  |  16KB  |  604 lines

  1. #include <stdio.h>
  2. #include "pvic.h"
  3. #include "locdefs.h"
  4.  
  5. #define TERMCAP_ENTRY_SIZE    1024
  6.  
  7. /* Items read from the termcap file. */
  8. int termcap_lines=DEFAULT_TERMCAP_LINES;
  9. int termcap_columns=DEFAULT_TERMCAP_COLUMNS;
  10. char *termcap_clr_eol=DEFAULT_TERMCAP_CLR_EOL;
  11. char *termcap_save_cursor=DEFAULT_TERMCAP_SAVE_CURSOR;
  12. char *termcap_clear_screen=DEFAULT_TERMCAP_CLEAR_SCREEN;
  13. char *termcap_restore_cursor=DEFAULT_TERMCAP_RESTORE_CURSOR;
  14. char *termcap_cursor_invisible=DEFAULT_TERMCAP_CURSOR_INVISIBLE;
  15. char *termcap_cursor_visible=DEFAULT_TERMCAP_CURSOR_VISIBLE;
  16. char *termcap_cursor_address=DEFAULT_TERMCAP_CURSOR_ADDRESS;
  17. char *termcap_init_terminal=DEFAULT_TERMCAP_INIT_TERMINAL;
  18. char *termcap_deinit_terminal=DEFAULT_TERMCAP_DEINIT_TERMINAL;
  19. char *termcap_bell=DEFAULT_TERMCAP_BELL;
  20. char *termcap_key_f1=DEFAULT_TERMCAP_KEY_F1;
  21. char *termcap_key_f2=DEFAULT_TERMCAP_KEY_F2;
  22. char *termcap_key_ic=DEFAULT_TERMCAP_KEY_IC;
  23. char *termcap_key_dc=DEFAULT_TERMCAP_KEY_DC;
  24. char *termcap_key_home=DEFAULT_TERMCAP_KEY_HOME;
  25. char *termcap_key_eol=DEFAULT_TERMCAP_KEY_EOL;
  26. char *termcap_key_ppage=DEFAULT_TERMCAP_KEY_PPAGE;
  27. char *termcap_key_npage=DEFAULT_TERMCAP_KEY_NPAGE;
  28. char *termcap_key_up=DEFAULT_TERMCAP_KEY_UP;
  29. char *termcap_key_down=DEFAULT_TERMCAP_KEY_DOWN;
  30. char *termcap_key_left=DEFAULT_TERMCAP_KEY_LEFT;
  31. char *termcap_key_right=DEFAULT_TERMCAP_KEY_RIGHT;
  32. char *termcap_key_backspace=DEFAULT_TERMCAP_KEY_BACKSPACE;
  33.  
  34.  
  35. /* Initialize all termcap variables. */
  36. void init_termcap()
  37. {
  38.     char *term;
  39.     char *termcap_entry;
  40.     int n;
  41.     char *s;
  42.  
  43.     /* Get the terminal type from the environment. */
  44.     term=getenv(LOCAL_TERM_ENVIRONMENT_VAR);
  45.  
  46.     /* If the terminal type is not set in the environment, we use
  47.     the build in defaults. */
  48.     if(term==NULL)return;
  49.  
  50.     /* Read the termcap entry for the given terminal type. */
  51.     if( (termcap_entry=read_termcap_entry(term))==NULL )
  52.     {
  53.         fprintf(stderr,"No termcap entry for %s\n",term);
  54.         exit(1);
  55.     }
  56.  
  57.     /* Get all obligationary entries. */
  58.  
  59.     if( (s=get_termcap_string(termcap_entry,"cm"))!=NULL ) 
  60.         termcap_cursor_address=s;
  61.     else
  62.     {
  63.         fprintf(stderr,
  64.             "Incomplete termcap entry for %s (cm missing)\n",
  65.             term);
  66.         exit(1);
  67.     }
  68.     
  69.     if( (s=get_termcap_string(termcap_entry,"ce"))!=NULL )
  70.         termcap_clr_eol=s;
  71.     else
  72.     {
  73.         fprintf(stderr,
  74.             "Incomplete termcap entry for %s (ce missing)\n",
  75.             term);
  76.         exit(1);
  77.     }
  78.  
  79.     if( (s=get_termcap_string(termcap_entry,"cl"))!=NULL ) 
  80.         termcap_clear_screen=s;
  81.     else
  82.     {
  83.         fprintf(stderr,
  84.             "Incomplete termcap entry for %s (cl missing)\n",
  85.             term);
  86.         exit(1);
  87.     }
  88.  
  89.     /* Get all optional entries. */
  90.  
  91.     if( (s=get_termcap_string(termcap_entry,"sc"))!=NULL )
  92.         termcap_save_cursor=s;
  93.     else termcap_save_cursor="";
  94.  
  95.     if( (s=get_termcap_string(termcap_entry,"rc"))!=NULL )
  96.         termcap_restore_cursor=s;
  97.     else termcap_restore_cursor="";
  98.  
  99.     if( (s=get_termcap_string(termcap_entry,"vi"))!=NULL )
  100.         termcap_cursor_invisible=s;
  101.     else termcap_cursor_invisible="";
  102.  
  103.     if( (s=get_termcap_string(termcap_entry,"vs"))!=NULL )
  104.         termcap_cursor_visible=s;
  105.     else termcap_cursor_visible="";
  106.  
  107.     if( (s=get_termcap_string(termcap_entry,"ti"))!=NULL )
  108.         termcap_init_terminal=s;
  109.     else termcap_init_terminal="";
  110.  
  111.     if( (s=get_termcap_string(termcap_entry,"te"))!=NULL )
  112.         termcap_deinit_terminal=s;
  113.     else termcap_deinit_terminal="";
  114.  
  115.     if( (s=get_termcap_string(termcap_entry,"bl"))!=NULL )
  116.         termcap_bell=s;
  117.     else termcap_bell="";
  118.  
  119.     if( (s=get_termcap_string(termcap_entry,"k0"))!=NULL )
  120.         termcap_key_f1=s;
  121.     else termcap_key_f1="";
  122.  
  123.     if( (s=get_termcap_string(termcap_entry,"k1"))!=NULL )
  124.         termcap_key_f2=s;
  125.     else termcap_key_f2="";
  126.  
  127.     if( (s=get_termcap_string(termcap_entry,"kI"))!=NULL )
  128.         termcap_key_ic=s;
  129.     else termcap_key_ic="";
  130.  
  131.     if( (s=get_termcap_string(termcap_entry,"kD"))!=NULL )
  132.         termcap_key_dc=s;
  133.     else termcap_key_dc="";
  134.  
  135.     if( (s=get_termcap_string(termcap_entry,"kh"))!=NULL )
  136.         termcap_key_home=s;
  137.     else termcap_key_home="";
  138.  
  139.     if( (s=get_termcap_string(termcap_entry,"kE"))!=NULL )
  140.         termcap_key_eol=s;
  141.     else termcap_key_eol="";
  142.  
  143.     if( (s=get_termcap_string(termcap_entry,"kP"))!=NULL )
  144.         termcap_key_ppage=s;
  145.     else termcap_key_ppage="";
  146.  
  147.     if( (s=get_termcap_string(termcap_entry,"kN"))!=NULL )
  148.         termcap_key_npage=s;
  149.     else termcap_key_npage="";
  150.  
  151.     if( (s=get_termcap_string(termcap_entry,"ku"))!=NULL )
  152.         termcap_key_up=s;
  153.     else termcap_key_up="";
  154.  
  155.     if( (s=get_termcap_string(termcap_entry,"kd"))!=NULL )
  156.         termcap_key_down=s;
  157.     else termcap_key_down="";
  158.  
  159.     if( (s=get_termcap_string(termcap_entry,"kl"))!=NULL )
  160.         termcap_key_left=s;
  161.     else termcap_key_left="";
  162.  
  163.     if( (s=get_termcap_string(termcap_entry,"kr"))!=NULL )
  164.         termcap_key_right=s;
  165.     else termcap_key_right="";
  166.  
  167.     if( (s=get_termcap_string(termcap_entry,"kb"))!=NULL )
  168.         termcap_key_backspace=s;
  169.     else termcap_key_backspace="";
  170.  
  171.     if( (n=get_termcap_number(termcap_entry,"li"))!=-1 )
  172.         PARAMETER_VALUE(PARAMETER_LINES)=termcap_lines=n;
  173.  
  174.     if( (n=get_termcap_number(termcap_entry,"co"))!=-1)
  175.         termcap_columns=n;
  176.  
  177.     /* Ready. */
  178.     return;
  179. }
  180.  
  181.  
  182.  
  183. /* Write an escape sequence to the terminal. The escape sequence is
  184. defined by the termcap string and two optional parameters. */
  185. void termcap_out(termcap_string,par1,par2)
  186. char termcap_string[];
  187. int par1,par2;
  188. {
  189.     int i;
  190.         int tmppar;
  191.  
  192.     /* Skip a leading number indicating a delay time. */
  193.     for(i=0;'0'<=termcap_string[i] && termcap_string[i]<='9';i++);
  194.  
  195.     /* Write the termcap entry. */
  196.     for(;termcap_string[i]!='\0';i++)
  197.     {
  198.         /* '\200' is translated into '\0'. */
  199.         if(termcap_string[i]=='\200')putc('\0',stdout);
  200.  
  201.         /* All other characters except '%' are written unchanged. */
  202.         else if(termcap_string[i]!='%')putc(termcap_string[i],stdout);
  203.  
  204.         /* The '%' character introduces an escape. */
  205.         else switch(termcap_string[++i])
  206.         {
  207.             /* "%%" evalueates to a single '%'. */
  208.             case '%':
  209.                 putc('%',stdout);
  210.             break;
  211.  
  212.             /* "%d" prints the next parameter as integer. */
  213.             case 'd':
  214.                         fprintf(stdout,"%d",par1);
  215.                         par1=par2;
  216.                         break;
  217.  
  218.             /* "%2" prints the next parameter as two digit integer. */
  219.             case '2':
  220.                         fprintf(stdout,"%02d",par1);
  221.                         par1=par2;
  222.                         break;
  223.  
  224.             /* "%3" prints the next parameter as three digit integer. */
  225.             case '3':
  226.                         fprintf(stdout,"%03d",par1);
  227.                         par1=par2;
  228.                         break;
  229.  
  230.  
  231.             /* "%." prints the next parameter as character. */
  232.             case '.':
  233.                         fprintf(stdout,"%c",par1);
  234.                         par1=par2;
  235.                         break;
  236.  
  237.             /* "%+x" prints 'x' incremented with the next parameter 
  238.             as character. */
  239.             case '+':
  240.                         i++;
  241.                         if(termcap_string[i]=='\0')break;
  242.                         fprintf(stdout,"%c",par1+termcap_string[i]);
  243.                         par1=par2;
  244.                 break;
  245.  
  246.             /* "%>xy" adds 'y' to the first parameter if it is greater
  247.             then 'y'. */
  248.             case '>':
  249.                         i++;
  250.                         if(termcap_string[i]=='\0')break;
  251.                         i++;
  252.                         if(termcap_string[i]=='\0')break;
  253.                         if(par1>termcap_string[i-1])par1+=termcap_string[i];
  254.                 break;
  255.  
  256.              /* "%r" reverses the order of the parameters. */
  257.             case 'r':
  258.             tmppar=par1;
  259.                         par1=par2;
  260.                         par2=tmppar;
  261.                         break;
  262.  
  263.             /* "%i" increments both parameters with 1. */
  264.             case 'i':
  265.                 par1++;
  266.             par2++;
  267.             break;
  268.  
  269.             /* "%n" exclusive-or-s both parameters with 0140. */
  270.             case 'n':
  271.                 par1^=0140;
  272.             par2^=0140;
  273.             break;
  274.  
  275.             /* "%B" first parameter is BCD. */
  276.             case 'B':
  277.                 par1=16*(par1/10)+par1%10;
  278.             break;
  279.  
  280.             /* "%D" first parameter is reverse coded. */
  281.             case 'D':
  282.                 par1=par1-2*(par1%16);
  283.             break;
  284.  
  285.         }
  286.     }
  287. }
  288.  
  289.  
  290. /* Read the termcap entry for terminal term into memory. */
  291. char *read_termcap_entry(term)
  292. char term[];
  293. {
  294.     static char entry[TERMCAP_ENTRY_SIZE];  
  295.     char entry_name[128];
  296.     int entry_size;
  297.     char *termcap_file;
  298.     FILE *termcap_fp;
  299.     char *current_term;
  300.     char *current_entry;
  301.     int i,j;
  302.     int c;
  303.  
  304.     /* Initially the entry we are looking for is specified by term. */
  305.     current_term=term;
  306.  
  307.     /* Initially we start reading the entry into entry. */
  308.     current_entry=entry;
  309.  
  310.     /* Initially the entry found doesn't contain anything. */
  311.     entry_size=0;
  312.  
  313. again:
  314.  
  315.     /* Get the name of the termcap file_name from the environment. */
  316.     termcap_file=getenv(LOCAL_TERMCAP_ENVIRONMENT_VAR);
  317.  
  318.     /* If the termcap file_name is not specified in the environment,
  319.     use the default. */
  320.     if(termcap_file==NULL)termcap_file=LOCAL_TERMCAP_FILE;
  321.  
  322.     /* Open termcap file. */
  323.     if( (termcap_fp=fopen(termcap_file,"r"))==NULL )
  324.     {
  325.         fprintf(stderr,"Cannot open termcap file %s\n",termcap_file);
  326.         exit(1);
  327.     }
  328.  
  329.     /* Read until end of termcap file. */
  330.     while(!feof(termcap_fp))
  331.     {
  332.         /* Read entry. */
  333.         entry_size=read_one_entry_from_termcap_file(
  334.             termcap_fp,current_entry,TERMCAP_ENTRY_SIZE-entry_size);
  335.  
  336.         /* The first parameter in the entry are one or more entry
  337.         names, separated by '|'. Test whether one of these entry 
  338.         names is the one we are looking for. */
  339.         i=0;
  340.         for(;;)
  341.         {
  342.             /* Isolate next entry name. */
  343.             for(j=0;current_entry[i]!='|' && 
  344.                 current_entry[i]!='\0';i++,j++)
  345.                 entry_name[j]=current_entry[i];
  346.             entry_name[j]='\0';
  347.  
  348.             /* If entry for our terminal found. */
  349.             if(strcmp(entry_name,current_term)==0)
  350.             {
  351.  
  352.                 /* Close termcap file. */
  353.                 fclose(termcap_fp);
  354.  
  355.  
  356.                 /* Overwrite all entry names with '@'. */
  357.                 for(i=0;current_entry[i]!='\0';i++)
  358.                     current_entry[i]='@';
  359.  
  360.                 /* If the entry found contains a variable
  361.                 "tc", we will add the entry for the terminal
  362.                 type specified by this variable to the entry
  363.                 found. We will do this only once. */
  364.                 if( current_entry==entry && (current_term=
  365.                     get_termcap_string(entry,"tc"))
  366.                     !=NULL )
  367.                 {
  368.                     current_entry=entry+entry_size;
  369.                     goto again;
  370.                 }
  371.  
  372.                 /* Ready. */
  373.                 return entry;
  374.             }
  375.  
  376.             /* If there are no more entry names, break. */
  377.             if(current_entry[i]=='\0')break;
  378.  
  379.             /* Otherwise test the next entry name. */
  380.             else i++;
  381.         }
  382.  
  383.     }
  384.     
  385.     /* Close the termcap file. */
  386.     fclose(termcap_fp);
  387.  
  388.     /* We haven't found an entry, so NULL is returned. */
  389.     return NULL;
  390. }
  391.  
  392.  
  393.  
  394. /* Get a character termcap variable from the previously read termcap entry. */
  395. char *get_termcap_string(entry,key)
  396. char *entry;
  397. char key[];
  398. {
  399.     int i;
  400.  
  401.     /* Only two character variables are recognized. */
  402.     if(key[0]=='\0' || key[1]=='\0')return NULL;
  403.  
  404.     /* Find variable. */
  405.     for(i=0;;)
  406.     {
  407.  
  408.         /* Variable not found. */
  409.         if(entry[i]=='\0')return NULL;
  410.  
  411.         /* Variable found, but invalidated by a following '@'. */
  412.         if(entry[i]==key[0] && entry[i+1]==key[1] && 
  413.             entry[i+2]=='@')return NULL;
  414.  
  415.         /* Found. */
  416.         if(entry[i]==key[0] && entry[i+1]==key[1] && 
  417.             entry[i+2]=='=')return &entry[i+3];
  418.  
  419.         /* Next variable. */
  420.         for(;entry[i]!='\0';i++);
  421.         i++;
  422.     }
  423. }
  424.  
  425.  
  426.  
  427.  
  428. /* Get a integer termcap variable from the previously read termcap entry. */
  429. int get_termcap_number(entry,key)
  430. char *entry;
  431. char key[];
  432. {
  433.     int i;
  434.     int n;
  435.  
  436.     /* Only two character variables are recognized. */
  437.     if(key[0]=='\0' || key[1]=='\0')return -1;
  438.  
  439.     /* Find variable. */
  440.     for(i=0;;)
  441.     {
  442.         /* Variable not found. */
  443.         if(entry[i]=='\0')return -1;
  444.  
  445.         /* Variable found, but invalidated by a following '@'. */
  446.         if(entry[i]==key[0] && entry[i+1]==key[1] && 
  447.             entry[i+2]=='@')return -1;
  448.  
  449.         /* Found. */
  450.         if(entry[i]==key[0] && entry[i+1]==key[1] && 
  451.             entry[i+2]=='#')
  452.         {
  453.             if(sscanf(&entry[i+3],"%d",&n)!=1)return -1;
  454.             else return n;
  455.         }
  456.  
  457.         /* Next variable. */
  458.         for(;entry[i]!='\0';i++);
  459.         i++;
  460.     }
  461. }
  462.  
  463.  
  464.  
  465. int read_one_entry_from_termcap_file(termcap_fp,buffer,buffer_size)
  466. FILE *termcap_fp;
  467. char buffer[];
  468. int buffer_size;
  469. {
  470.     int i,j;
  471.     int c;
  472.  
  473.     for(i=0;;)
  474.     {
  475.         /* Read one character. */
  476.         c=getc(termcap_fp);
  477.  
  478.         /* A '\0' is converted into a '\200', because a '\0' is
  479.         already used for end-of-string. */
  480.         if(c=='\0')buffer[i]='\200';
  481.  
  482.         /* The entry ends on end-of-file or unescaped end-of-line. */
  483.         else if(c==EOF || c=='\n')break;
  484.  
  485.         /* White space is skipped. */
  486.         else if(i==0 && (c==' ' || c=='\t'))continue;
  487.  
  488.         /* A colon delimmits the sections in the entry. Empty
  489.         sections are dsicarded. */
  490.         else if(c==':')
  491.         {
  492.             if(i==0)continue;
  493.             else if(buffer[i-1]=='\0')continue;
  494.             else buffer[i]='\0';
  495.         }
  496.  
  497.         /* The backslash is the escape character. */
  498.         else if(c=='\\')
  499.         {
  500.             /* Get the next character. Break end-of-file. */
  501.             c=getc(termcap_fp);
  502.             if(c==EOF)break;
  503.  
  504.             /* Discard an escaped new-line. */
  505.             else if(c=='\n')continue;
  506.  
  507.             /* Discard an escaped null character. */
  508.             else if(c=='\0')continue;
  509.  
  510.             /* "\n" is translated into a control-j (linefeed). */
  511.             else if(c=='n')buffer[i]=CTRL_J;
  512.             else if(c=='N')buffer[i]=CTRL_J;
  513.  
  514.             /* "\r" is translated into a control-m     
  515.             (cariage-return). */
  516.             else if(c=='r')buffer[i]=CTRL_M;
  517.             else if(c=='R')buffer[i]=CTRL_M;
  518.  
  519.             /* "\t" is translated into a control-i (tab). */
  520.             else if(c=='t')buffer[i]=CTRL_I;
  521.             else if(c=='T')buffer[i]=CTRL_I;
  522.  
  523.             /* "\b" is translated into a control-h (backspace). */
  524.             else if(c=='b')buffer[i]=CTRL_H;
  525.             else if(c=='B')buffer[i]=CTRL_H;
  526.  
  527.             /* "\f" is translated into a control-l (formfeed). */
  528.             else if(c=='f')buffer[i]=CTRL_L;
  529.             else if(c=='F')buffer[i]=CTRL_L;
  530.  
  531.             /* "\e" is translated into an escape. */
  532.             else if(c=='e')buffer[i]=ESC;
  533.             else if(c=='E')buffer[i]=ESC;
  534.  
  535.             /* An octal numer preceded by a backslash is 
  536.             translated into the character which has the octal
  537.             number as ascii value. */
  538.             else if('0'<=c && c<='7')
  539.             {
  540.                 buffer[i]=c-'0';
  541.                 c=getc(termcap_fp);
  542.                 if('0'<=c && c<='7')
  543.                 {
  544.                     buffer[i]*=8;
  545.                     buffer[i]+=c-'0';
  546.                     c=getc(termcap_fp);
  547.                     if('0'<=c && c<='7')
  548.                     {
  549.                         buffer[i]*=8;
  550.                         buffer[i]+=c-'0';
  551.                     }
  552.                     else ungetc(c,termcap_fp);
  553.                 }
  554.                 else ungetc(c,termcap_fp);
  555.                 if(buffer[i]=='\0')buffer[i]='\200';
  556.             }
  557.  
  558.             /* If any other character is preceded by a backslash,
  559.             the the character is taken litterally. */
  560.             else buffer[i]=c;
  561.         }
  562.  
  563.         /* "^x" represents control-x. */
  564.         else if(c=='^')
  565.         {
  566.             /* Get next character. Break on end-of-file. */
  567.             c=getc(termcap_fp);
  568.             if(c==EOF)break;
  569.  
  570.             /* Put appropriate control character in the buffer. */
  571.             else if(c=='?')buffer[i]='\177';
  572.             else buffer[i]=c&31;
  573.  
  574.             /* Translate a '\0' into a '\200'. */
  575.             if(buffer[i]=='\0')buffer[i]='\200';
  576.         }
  577.  
  578.         /* Any other character is put without translation into 
  579.         the buffer. */
  580.         else buffer[i]=c;
  581.  
  582.         /* Increment the buffer index only if there is enough space
  583.         left in the buffer. */
  584.         if(i<buffer_size-2)i++;
  585.     }
  586.  
  587.     /* Strip the last variable if there is not enough space in the
  588.     buffer for the entry. */
  589.     if(i==buffer_size-2)for(;i>0 && buffer[i]!='\0';i--);
  590.  
  591.     /* Strip al terminating '\0' characters. */
  592.     for(;i>0 && buffer[i]=='\0';i--);
  593.  
  594.     /* Add two terminating '\0' characters. */
  595.     i++;
  596.     buffer[i]='\0';
  597.     i++;
  598.     buffer[i]='\0';
  599.  
  600.     /* Return the number of characters read. */
  601.     return i;
  602. }
  603.  
  604.