home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / t / tel2305s.zip / ENGINE / KEYMAP.C < prev    next >
C/C++ Source or Header  |  1992-03-27  |  26KB  |  516 lines

  1. /*
  2. *    keymap.c
  3. *
  4. *   Keymapping functions for the real screen
  5. *
  6. *   Quincey Koziol
  7. *
  8. *    Date        Notes
  9. *    --------------------------------------------
  10. *    8/90        Started
  11. *    10/90        Added functionality to allow octal & hex mappings
  12. *                and mixed case keywords
  13. *   6/91        Added functionality to allow '\' in curly braces,
  14. *               set special codes for the cursor control codes
  15. *               for Kermit cursor control codes,
  16. */
  17.  
  18. /*
  19. * Includes
  20. */
  21.  
  22. #define KEYMASTER
  23.  
  24. #ifdef __TURBOC__
  25. #include "turboc.h"
  26. #endif
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <io.h>
  31. #include <ctype.h>
  32. #ifdef MSC
  33. #include <malloc.h>
  34. #endif
  35. #include "vskeys.h"
  36. #include "keymap.h"
  37. #include "externs.h"
  38.  
  39. #define MAX_LINE_LENGTH    160        /* the maximum length of a line in the keyboard mapping file */
  40.  
  41. /*
  42. *    Global Variables
  43. */
  44. extern char path_name[];        /* the path name of telbin.exe, used to find telnet.key file */
  45.  
  46. /* Local functions */
  47. static char *parse_str(char *file_str,uint *ret_code);
  48. static int parse_verb(char *verb_str,uint *ret_code);
  49. static int add_key(unsigned int search_key,char *key_map_str,int is_special,byte special_code);
  50. static int del_key(unsigned int search_key);
  51.  
  52. /* Local variables */
  53. static char white_sp[]="\x009\x00a\x00b\x00c\x00d\x020";    /* string which contains all the white space characters */
  54. static char end_token[]="\x000\x009\x00a\x00b\x00c\x00d\x020};";    /* string which contains all the white space characters, and the right curley brace & the semi-colon */
  55.  
  56. /**********************************************************************
  57. *  Function    :    del_key
  58. *  Purpose    :    delete a node from the list of mapped keys
  59. *  Parameters    :
  60. *            search_key - the keycode to add to the list
  61. *  Returns    :    -1 to indicate the key is not found, 0 otherwise
  62. *  Calls    :    none
  63. *  Called by    :    read_keyboard_file()
  64. **********************************************************************/
  65. static int del_key(unsigned int search_key)
  66. {
  67.     key_node *temp_key,        /* temporary pointer for the key node to delete from the list */
  68.         *temp_2key;            /* another temporary pointer to a key node */
  69.  
  70.     if(IS_KEY_MAPPED(search_key) && head_key!=NULL) {    /* check whether the key is actually mapped, and there are mapped keys in memory */
  71.         temp_2key=temp_key=head_key;
  72.         if((*temp_key).key_code==search_key) {    /* check whether the key to delete is the head of the list */
  73.             head_key=(*head_key).next_node;        /* more around the deleted key */
  74.           }    /* end if */
  75.         else {
  76.             temp_key=(*temp_key).next_node;        /* go to the next node */
  77.             while(temp_key!=NULL && (*temp_key).key_code!=search_key) {    /* search for the key to delete */
  78.                 temp_2key=temp_key;        /* advance the trailing pointer */
  79.                 temp_key=(*temp_key).next_node;    /* advance the leading pointer */
  80.               }    /* end while */
  81.             if(temp_key==NULL)    /* check for the key not being in the list */
  82.                 return(-1);
  83.             (*temp_2key).next_node=(*temp_key).next_node;    /* link around the key to delete */
  84.           }    /* end else */
  85.         if(!IS_KEY_SPECIAL(search_key)) {        /* check for just a regular mapped key string */
  86.             if((*temp_key).key_data.key_str!=NULL)
  87.                 free((*temp_key).key_data.key_str);
  88.             else
  89.                 return(-1);
  90.           }    /* end if */
  91.         RESET_KEY_MAPPED((int)search_key);    /* reset the mapped & special flags */
  92.         RESET_KEY_SPECIAL((int)search_key);
  93.         free(temp_key);         /* free the key node */
  94.       }    /* end if */
  95.     else
  96.         return(-1);
  97. }    /* end del_key() */
  98.  
  99. /**********************************************************************
  100. *  Function    :    add_key
  101. *  Purpose    :    add a node to the list of mapped keys
  102. *  Parameters    :
  103. *            search_key - the keycode to add to the list
  104. *            key_map_str - the string to map the key to
  105. *            is_special - flag to indicate kermit verbs re-mapping
  106. *            special_code - the kermit code to re-map to
  107. *  Returns    :    -1 for an out of memory error, 0 otherwise
  108. *  Calls    :    none
  109. *  Called by    :    read_keyboard_file()
  110. **********************************************************************/
  111. static int add_key(unsigned int search_key,char *key_map_str,int is_special,byte special_code)
  112. {
  113.     key_node *temp_key;        /* temporary pointer for the key node to add to the list */
  114.  
  115.     if(IS_KEY_MAPPED(search_key)) {    /* check for strictly re-mapping this key */
  116.         if((temp_key=find_key(search_key))!=NULL) {        /* get the key code to remap */
  117.             if(IS_KEY_SPECIAL(search_key)) {        /* check whether the key we are re-mapping is a verb */
  118.                 if(is_special)        /* check whether the new key is special also */
  119.                     (*temp_key).key_data.vt100_code=special_code;    /* just change the vt100 code generated */
  120.                 else {            /* allocate room for the string to map */
  121.                     RESET_KEY_SPECIAL((int)search_key);    /* reset the special flag */
  122.                     if(((*temp_key).key_data.key_str=strdup(key_map_str))==NULL)    /* duplicate the string to re-map to */
  123.                         return(-1);    /* indicate no more memory */
  124.                   }    /* end else */
  125.               }    /* end if */
  126.             else {        /* not a special key, we need to free the old string */
  127.                 if((*temp_key).key_data.key_str!=NULL)    /* free the old string */
  128.                     free((*temp_key).key_data.key_str);
  129.                 if(is_special) {        /* check whether the new key is special also */
  130.                     (*temp_key).key_data.vt100_code=special_code;    /* just change the vt100 code generated */
  131.                     SET_KEY_SPECIAL((int)search_key);        /* set the special flag */
  132.                   }    /* end if */
  133.                 else {            /* allocate room for the string to map */
  134.                     if(((*temp_key).key_data.key_str=strdup(key_map_str))==NULL)    /* duplicate the string to re-map to */
  135.                         return(-1);    /* indicate no more memory */
  136.                   }    /* end else */
  137.               }    /* end else */
  138.             return(0);            /* indicate no error */
  139.           }    /* end if */
  140.         else        /* uh-uh, memory is messed up */
  141.             return(-1);
  142.       }    /* end if */
  143.     if((temp_key=(key_node *)malloc((size_t)sizeof(key_node)))!=NULL) {  /* allocate room for the key node */
  144.         (*temp_key).key_code=search_key;    /* set the key code for this node */
  145.         SET_KEY_MAPPED((int)search_key);    /* indicate this key is mapped */
  146.         if(is_special) {    /* check for a kermit verb to re-map to */
  147.             SET_KEY_SPECIAL((int)search_key);
  148.             (*temp_key).key_data.vt100_code=special_code;
  149.           }    /* end if */
  150.         else {
  151.             if(((*temp_key).key_data.key_str=strdup(key_map_str))==NULL)    /* duplicate the string to re-map to */
  152.                 return(-1);    /* indicate no more memory */
  153.           }    /* end else */
  154.         (*temp_key).next_node=head_key;    /* attach to the linked list */
  155.         head_key=temp_key;
  156.         return(0);
  157.       }    /* end if */
  158.     else
  159.         return(-1);        /* indicate out of memory */
  160. }    /* end add_key() */
  161.  
  162. /**********************************************************************
  163. *  Function    :    parse_verb()
  164. *  Purpose    :    compare the verb_str against the various Kermit verbs
  165. *                which we support, and set the correct (internal)
  166. *                vt100 code for that key.  Otherwise, set an error code
  167. *                to return.
  168. *  Parameters    :
  169. *            verb_str - pointer to a string to compare against the kermit verbs we support
  170. *            ret_code - pointer to an unsigned int to return the (internal) vt100 code in
  171. *  Returns    :    0xFFFF for error, otherwise, the length of the kermit verb
  172. *                indentified.
  173. *  Calls    :    none
  174. *  Called by    :    parse_str()
  175. **********************************************************************/
  176. static int parse_verb(char *verb_str,uint *ret_code)
  177. {
  178.     int i;      /* local counting variable */
  179.  
  180.     for(i=0; i<NUM_KERMIT_VERBS; i++) {
  181.         if(!strnicmp(verb_str,verb_table[i],verb_length[i])) {      /* check for sending each kermit verb */
  182.             *ret_code=verb_num[i];      /* indicate verb found character */
  183.             return(verb_length[i]);          /* indicate the number of characters to skip */
  184.           } /* end if */
  185.       } /* end for */
  186.     *ret_code=0xFFFF;       /* indicate that we don't recognize this verb */
  187.     return(strcspn(verb_str,end_token));    /* return the number of characters to skip */
  188. }   /* end parse_verb() */
  189.  
  190. /**********************************************************************
  191. *  Function    :    parse_str()
  192. *  Purpose    :    parse the string to map a key to.
  193. *  Parameters    :
  194. *            file_str - pointer to a string from the file to parse
  195. *            ret_code - pointer to an unsigned int to return an (internal)vt100 code in
  196. *  Returns    :    0xFFFF for error, otherwise, the vt100 code for telbin
  197. *  Calls    :    parse_verb()
  198. *  Called by    :    read_keyboard_file()
  199. **********************************************************************/
  200. static char *parse_str(char *file_str,uint *ret_code)
  201. {
  202.     int buff_off=0,            /* current location in the buffer */
  203.         ascii_num,            /* ascii character encoded after a backslash */
  204.         kermit_length,        /* the length of a kermit verb returned from parsing it */
  205.         done=0;                /* flag for dropping out of the loop */
  206.     byte *ret_str,            /* the string variable to return the result in */
  207.         *temp_str,            /* pointer to the current place in the string */
  208.         buffer[MAX_LINE_LENGTH];        /* buffer to store the string we are unravelling */
  209.  
  210.     *ret_code=0xFFFF;        /* mark return code to indicate nothing special to return */
  211.     temp_str=file_str;        /* start at the beginning of the string to parse */
  212.     while((*temp_str)!='\0' && buff_off<MAX_LINE_LENGTH && !done) {        /* parse until the end of the string or until the buffer is full */
  213.         while((*temp_str) && (*temp_str)!=';' && (*temp_str)!='\\' && (*temp_str)!='{' && (*temp_str)>' ') {    /* copy regular characters until a special one is hit */
  214.             buffer[buff_off]=(*temp_str);        /* copy the character */
  215.             buff_off++;        /* increment the position in the buffer */
  216.             temp_str++;        /* increment the position in the parse string */
  217.           }    /* end while */
  218.         if(*temp_str) {        /* check on the various special cases for dropping out of the loop */
  219.             switch(*temp_str) {        /* switch for the special case */
  220.                 case '\\':    /* backslash for escape coding a character */
  221.                     temp_str++;        /* get the character after the backslash */
  222.                     if((*temp_str)=='{') {    /* check for curly brace around numbers */
  223.                         temp_str++;    /* increment to the next character */
  224.                         if((*temp_str)=='K' || (*temp_str)=='k') {        /* check for Kermit escape code here also */
  225.                             temp_str++;        /* increment past the kermit flag */
  226.                             kermit_length=parse_verb(temp_str,ret_code);        /* parse the kermit verb, and return the correct kermit code in the ret_code */
  227.                             if(*ret_code!=0xFFFF)        /* a kermit verb was specified that we recognize */
  228.                                 return(NULL);        /* return now, indicating a kermit verb we recognize in the ret_code variable */
  229.                             temp_str+=kermit_length;    /* increment past the kermit verb */
  230.                           }    /* end if */
  231.                         else if((*temp_str)=='o') {    /* check for octal number */
  232.                             ascii_num=octal_to_int(temp_str);    /* get the acii number after the escape code */
  233.                             buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  234.                             buff_off++;                /* increment our position */
  235.                             while((*temp_str)>='0' && (*temp_str)<='7')    /* increment our position past the digits */
  236.                                 temp_str++;
  237.                           }    /* end if */
  238.                         else if((*temp_str)=='x') {    /* check for hexadecimal number */
  239.                             ascii_num=hex_to_int(temp_str);    /* get the acii number after the escape code */
  240.                             buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  241.                             buff_off++;                /* increment our position */
  242.                             while(isxdigit((int)(*temp_str)))    /* increment our position past the digits */
  243.                                 temp_str++;
  244.                           }    /* end if */
  245.                         else {        /* must be an escape integer */
  246.                             if((*temp_str)=='d')    /* check for redundant decimal number specification */
  247.                                 temp_str++;
  248.                             ascii_num=atoi(temp_str);    /* get the ascii number after the escape code */
  249.                             buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  250.                             buff_off++;                /* increment our position */
  251.                             while(isdigit((int)(*temp_str)))    /* increment our position past the digits */
  252.                                 temp_str++;
  253.                           }    /* end else */
  254.                         if((*temp_str)=='}')    /* found the closing curly brace */
  255.                             temp_str++;        /* jump over the closing curly brace */
  256.                         else {        /* closing curly brace missing, indicate error */
  257.                             buff_off=0;
  258.                             done=1;
  259.                           }    /* end else */
  260.                       }    /* end if */
  261.                     else if((*temp_str)=='K' || (*temp_str)=='k') {        /* check for Kermit escape code */
  262.                         temp_str++;        /* increment past the kermit flag */
  263.                         kermit_length=parse_verb(temp_str,ret_code);        /* parse the kermit verb, and return the correct kermit code in the ret_code */
  264.                         if(*ret_code!=0xFFFF)        /* a kermit verb was specified that we recognize */
  265.                             return(NULL);        /* return now, indicating a kermit verb we recognize in the ret_code variable */
  266.                         temp_str+=kermit_length;    /* increment past the kermit verb */
  267.                       }    /* end if */
  268.                     else if((*temp_str)=='o') {    /* check for octal number */
  269.                         ascii_num=octal_to_int(temp_str);    /* get the acii number after the escape code */
  270.                         buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  271.                         buff_off++;                /* increment our position */
  272.                         while((*temp_str)>='0' && (*temp_str)<='7')    /* increment our position past the digits */
  273.                             temp_str++;
  274.                       }    /* end if */
  275.                     else if((*temp_str)=='x') {    /* check for hexadecimal number */
  276.                         ascii_num=hex_to_int(temp_str);    /* get the acii number after the escape code */
  277.                         buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  278.                         buff_off++;                /* increment our position */
  279.                         while(isxdigit((int)(*temp_str)))    /* increment our position past the digits */
  280.                             temp_str++;
  281.                       }    /* end if */
  282.                     else {        /* must be an escape integer */
  283.                         if((*temp_str)=='d')    /* check for redundant decimal number specification */
  284.                             temp_str++;
  285.                         ascii_num=atoi(temp_str);    /* get the ascii number after the escape flag */
  286.                         buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  287.                         buff_off++;                /* increment our position */
  288.                         while(isdigit((int)(*temp_str)))    /* increment our position past the digits */
  289.                             temp_str++;
  290.                       }    /* end else */
  291.                     break;
  292.  
  293.                 case '{':    /* curly brace opens a quoted string */
  294.                     temp_str++;     /* jump over the brace itself */
  295.                     while((*temp_str) && (*temp_str)!='}') {    /* copy regular characters until a special one is hit */
  296.                         if((*temp_str)=='\\') {     /* check for a backslash in the curly braces */
  297.                             temp_str++; /* increment to the next character */
  298.                             if((*temp_str)=='o') { /* check for octal number */
  299.                                 ascii_num=octal_to_int(temp_str);   /* get the acii number after the escape code */
  300.                                 buffer[buff_off]=(byte)ascii_num;   /* store the ascii code in the buffer */
  301.                                 buff_off++;             /* increment our position */
  302.                                 while((*temp_str)>='0' && (*temp_str)<='7') /* increment our position past the digits */
  303.                                     temp_str++;
  304.                               } /* end if */
  305.                             else if((*temp_str)=='x') { /* check for hexadecimal number */
  306.                                 ascii_num=hex_to_int(temp_str); /* get the acii number after the escape code */
  307.                                 buffer[buff_off]=(byte)ascii_num;   /* store the ascii code in the buffer */
  308.                                 buff_off++;             /* increment our position */
  309.                                 while(isxdigit((int)(*temp_str)))   /* increment our position past the digits */
  310.                                     temp_str++;
  311.                               } /* end if */
  312.                             else {      /* must be an escape integer */
  313.                                 if((*temp_str)=='d')    /* check for redundant decimal number specification */
  314.                                     temp_str++;
  315.                                 ascii_num=atoi(temp_str);   /* get the ascii number after the escape code */
  316.                                 buffer[buff_off]=(byte)ascii_num;   /* store the ascii code in the buffer */
  317.                                 buff_off++;             /* increment our position */
  318.                                 while(isdigit((int)(*temp_str)))    /* increment our position past the digits */
  319.                                     temp_str++;
  320.                               } /* end else */
  321.                           } /* end if */
  322.                         else {
  323.                             buffer[buff_off]=(*temp_str);       /* copy the character */
  324.                             buff_off++;     /* increment the position in the buffer */
  325.                             temp_str++;     /* increment the position in the parse string */
  326.                           } /* end else */
  327.                       }    /* end while */
  328.                     if((*temp_str)=='}')        /* found the closing brace */
  329.                         temp_str++;        /* jump over the closing brace */
  330.                     else {        /* line terminated without closing brace */
  331.                         buff_off=0;        /* indicate error condition */
  332.                         done=1;            /* drop out of the loop */
  333.                       }    /* end else */
  334.                     break;
  335.  
  336.                 default:    /* ctrl characters, space, and semi-colon terminate a string */
  337.                     buffer[buff_off]='\0';  /* terminate the string */
  338.                     done=1;
  339.                     break;
  340.  
  341.               }    /* end switch */
  342.           }    /* end if */
  343.         else
  344.             buffer[buff_off]='\0';    /* terminate the string */
  345.       }    /* end while */
  346.     if(buff_off>0) {
  347.         if((ret_str=malloc(buff_off+1))!=NULL)
  348.             strcpy(ret_str,buffer);        /* copy the parsed string */
  349.         return(ret_str);
  350.       }    /* end if */
  351.     return(NULL);
  352. }    /* end parse_str() */
  353.  
  354. /**********************************************************************
  355. *  Function    :    read_keyboard_file
  356. *  Purpose    :    read in a keyboard mapping file, parse the input and 
  357. *                map keys
  358. *  Parameters    :
  359. *            key_file - string containing the name of the keyboard mapping file
  360. *  Returns    :    0 for no error, -1 for any errors which occur
  361. *  Calls    :    parse_str(), & lots of library string functions
  362. *  Called by    :    initkbfile(), Sconfile()
  363. **********************************************************************/
  364. int read_keyboard_file(char *key_file)
  365. {
  366.     FILE *key_fp;            /* pointer to the keyboard file */
  367.     char key_line[MAX_LINE_LENGTH],        /* static array to store lines read from keyboard file */
  368.         *map_str,            /* the parsed string from the keyboard file */
  369.         *temp_str;            /* temporary pointer to a string */
  370.     uint line_no=0,            /* what line in the file we are on */
  371.         token_num,            /* the current token we are parsing */
  372.         where,                /* pointer to the beginning of text */
  373.         kermit_code,        /* the variable to return the possible 'kermit verb' code in */
  374.         re_map_key,            /* the key to re-map */
  375.         error=0;            /* error from the file reading */
  376.  
  377.     if((key_fp=fopen(key_file,"rt"))!=NULL) {
  378.         while((temp_str=fgets(key_line,MAX_LINE_LENGTH,key_fp))!=NULL && !error) {    /* get a line of input */
  379.             token_num=0;            /* initialize the token we are on */
  380.             if((temp_str=strtok(key_line,white_sp))!=NULL) {    /* get the first token from the string */
  381.                 if((*temp_str)!=';') {        /* check for a comment line */
  382.                     do {
  383.                         switch(token_num) {        /* switch on which token we are processing */
  384.                             case 0:        /* the 'SET' token (we already know it is not a comment) */
  385.                                 if(stricmp(temp_str,"SET")) {    /* make certain the first token is a SET token */
  386.                                     printf("invalid token #%d:'%s' on line %d\n",token_num,temp_str,line_no);
  387.                                     token_num=4;    /* bump the token count up to drop out of the loop */
  388.                                   }    /* end if */
  389.                                 break;
  390.  
  391.                             case 1:        /* the 'KEY' token */
  392.                                 if(stricmp(temp_str,"KEY")) {    /* make certain the first token is a KEY token */
  393.                                     printf("invalid token #%d:'%s' on line %d\n",token_num,temp_str,line_no);
  394.                                     token_num=4;    /* bump the token count up to drop out of the loop */
  395.                                   }    /* end if */
  396.                                 break;
  397.  
  398.                             case 2:        /* the key to be re-mapped */
  399.                                 if(!stricmp(temp_str,"CLEAR") || !stricmp(temp_str,"OFF") || !stricmp(temp_str,"ON") || (*temp_str)==';') {    /* ignore the rest of the line if the 'key' is one of the tokens we don't support */
  400.                                     token_num=4;    /* bump the token count up to drop out of the loop */
  401.                                   }    /* end if */
  402.                                 else {        /* the 'key' field is not a special command or a comment, must be a valid character */
  403.                                     if(*(temp_str)!='\\') {    /* the key to re-map is not an escape code */
  404.                                         re_map_key=*temp_str;    /* set the re-mapping key */
  405.                                       }    /* end if */
  406.                                     else {
  407.                                         if(*(temp_str+1)=='d')  /* walk a past the 'd' character */
  408.                                             temp_str++;
  409.                                         re_map_key=atoi(temp_str+1);    /* get the re-mapping key value from the string */
  410.                                         if(re_map_key==0) {        /* invalid key code */
  411.                                             printf("Error, invalid key code:%s, on line %d\n",temp_str,line_no);
  412.                                             token_num=4;    /* bump the token count up to drop out of the loop */
  413.                                           }    /* end if */
  414.                                       }    /* end else */
  415.                                   }    /* end else */
  416.                                 break;
  417.  
  418.                             case 3:        /* the string to re-map the key to */
  419.                                 if((*temp_str)==';') {    /* ignore the rest of the line if the 'key' is one of the tokens we don't support */
  420.                                     if(IS_KEY_MAPPED(re_map_key))    /* check for the key being already re-mapped */
  421.                                         error=del_key(re_map_key);
  422.                                     token_num=4;    /* bump the token count up to drop out of the loop */
  423.                                   }    /* end if */
  424.                                 else {
  425.                                     if((map_str=parse_str(temp_str,&kermit_code))!=NULL) {        /* parse the re-mapping string */
  426.                                         error=add_key(re_map_key,map_str,0,0);    /* add a regular key string to the key mapping list */
  427.                                         free((char *)map_str);
  428.                                       }    /* end if */
  429.                                     else {
  430.                                         if(kermit_code!=0xFFFF) {    /* check for special kermit verb returned */
  431.                                             error=add_key(re_map_key,NULL,1,(byte)kermit_code);    /* add a kermit code to the list */
  432.                                           }    /* end if */
  433.                                         else {
  434.                                             if(IS_KEY_MAPPED(re_map_key))    /* check for the key being already re-mapped */
  435.                                                 error=del_key(re_map_key);
  436.                                             printf("Error, re-mapping string:%s invalid on line %d\n",temp_str,line_no);
  437.                                             token_num=4;    /* bump the token count up to drop out of the loop */
  438.                                           }    /* end else */
  439.                                       }    /* end else */
  440.                                   }    /* end else */
  441.                                 break;
  442.                           }    /* end switch */
  443.                         token_num++;
  444.                         if(token_num<3)        /* if the next token is not the last one, then grab it */
  445.                             temp_str=strtok(NULL,white_sp);        /* get the next token */
  446.                         else if(token_num==3) {        /* for the last 'token' (after the remapping key to the end of the line), just get the next character in the line */
  447.                             temp_str+=(strlen(temp_str)+1);        /* jump over the previous token */
  448.                             where=strspn(temp_str,white_sp);    /* look for the first non-white space in the line */
  449.                             temp_str+=where;    /* jump to the first position with a character */
  450.                             if(!isgraph(*temp_str)) {        /* not more characters in the line */
  451.                                 if(IS_KEY_MAPPED(re_map_key))    /* check for the key being already re-mapped */
  452.                                     error=del_key(re_map_key);
  453.                                 token_num=4;    /* bump the token count to drop out of the loop */
  454.                               }    /* end if */
  455.                           }    /* end if */
  456.                       }    while(temp_str!=NULL && token_num<4);
  457.                   }    /* end if */
  458.                 else {
  459.                   }    /* end else */
  460.               }    /* end if */
  461.             line_no++;            /* increment current line */
  462.           }    /* end while */
  463.         fclose(key_fp);
  464.       }    /* end if */
  465.     else
  466.         error=(-1);        /* indicate an error */
  467.     return(error);
  468. }    /* end read_keyboard_file() */
  469.  
  470. /**********************************************************************
  471. *  Function    :    find_key
  472. *  Purpose    :    search through the list of mapped keys and return a pointer
  473. *                to the node whose key_code matches the parameter passed
  474. *  Parameters    :
  475. *            search_key - the keycode to search the list for
  476. *  Returns    :    NULL for a match not found, or a pointer to the key_node
  477. *                containing the matched keycode
  478. *  Calls    :    none
  479. *  Called by    :    vt100key()
  480. **********************************************************************/
  481. key_node *find_key(unsigned int search_key)
  482. {
  483.     key_node *temp_key;        /* temporary pointer to a key node used to search to the matching key code */
  484.  
  485.     temp_key=head_key;        /* start at the head of the linked list */
  486.     while(temp_key!=NULL) {    /* search the entire list */
  487.         if((*temp_key).key_code==search_key)    /* check for match */
  488.             return(temp_key);    /* return the pointer to the matched node */
  489.         temp_key=(*temp_key).next_node;
  490.       }    /* end while */
  491.     return(NULL);
  492. }    /* end find_key() */
  493.  
  494. /**********************************************************************
  495. *  Function    :    initkbfile()
  496. *  Purpose    :    initialize the default keyboard settings and read in
  497. *                the default keycodes from telnet.key
  498. *  Parameters    :    none
  499. *  Returns    :    0 for no error, <0 for various errors
  500. *  Calls    :    none
  501. *  Called by    :    main()
  502. **********************************************************************/
  503. int initkbfile(void )
  504. {
  505.     char kb_name[_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT];    /* temporary variable to hold the entire pathname of "telnet.key" */
  506.     int error;            /* the error code returned from reading in the keyboard mapping file */
  507.  
  508.     memset(key_map_flags,0,1024);        /* initialize all the keyboard mapped flags to zero (not mapped) */
  509.     memset(key_special_flags,0,1024);    /* initialize all the keyboard special flags to zero (not special) */
  510.     strcpy(kb_name,path_name);    /* get the directory where telbin.exe is */
  511.     strcat(kb_name,"telnet.key");    /* append the proper name */
  512.     error=read_keyboard_file(kb_name);
  513.     return(error);
  514. }    /* end initkbfile() */
  515.  
  516.