home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / NETWORK / TEL23SRC.ZIP / ENGINE / KEYMAP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-29  |  29.8 KB  |  604 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. #ifdef MEMORY_DEBUG
  36. #include "memdebug.h"
  37. #endif
  38. #include "vskeys.h"
  39. #include "externs.h"
  40. #include "keymap.h"
  41.  
  42. #define MAX_LINE_LENGTH    160        /* the maximum length of a line in the keyboard mapping file */
  43.  
  44. /*
  45. *    Global Variables
  46. */
  47. extern char path_name[];        /* the path name of telbin.exe, used to find telnet.key file */
  48.  
  49. /* Local functions */
  50. static char *parse_str(char *file_str,uint *ret_code);
  51. static int parse_verb(char *verb_str,uint *ret_code);
  52. static int add_key(unsigned int search_key,char *key_map_str,int is_special,byte special_code);
  53. static int del_key(unsigned int search_key);
  54.  
  55. /* Local variables */
  56. static char white_sp[]="\x009\x00a\x00b\x00c\x00d\x020";    /* string which contains all the white space characters */
  57. 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 */
  58.  
  59. /**********************************************************************
  60. *  Function    :    del_key
  61. *  Purpose    :    delete a node from the list of mapped keys
  62. *  Parameters    :
  63. *            search_key - the keycode to add to the list
  64. *  Returns    :    -1 to indicate the key is not found, 0 otherwise
  65. *  Calls    :    none
  66. *  Called by    :    read_keyboard_file()
  67. **********************************************************************/
  68. static int del_key(unsigned int search_key)
  69. {
  70.     key_node *temp_key,        /* temporary pointer for the key node to delete from the list */
  71.         *temp_2key;            /* another temporary pointer to a key node */
  72.  
  73.     if(IS_KEY_MAPPED(search_key) && head_key!=NULL) {    /* check whether the key is actually mapped, and there are mapped keys in memory */
  74.         temp_2key=temp_key=head_key;
  75.         if((*temp_key).key_code==search_key) {    /* check whether the key to delete is the head of the list */
  76.             head_key=(*head_key).next_node;        /* more around the deleted key */
  77.           }    /* end if */
  78.         else {
  79.             temp_key=(*temp_key).next_node;        /* go to the next node */
  80.             while(temp_key!=NULL && (*temp_key).key_code!=search_key) {    /* search for the key to delete */
  81.                 temp_2key=temp_key;        /* advance the trailing pointer */
  82.                 temp_key=(*temp_key).next_node;    /* advance the leading pointer */
  83.               }    /* end while */
  84.             if(temp_key==NULL)    /* check for the key not being in the list */
  85.                 return(-1);
  86.             (*temp_2key).next_node=(*temp_key).next_node;    /* link around the key to delete */
  87.           }    /* end else */
  88.         if(!IS_KEY_SPECIAL(search_key)) {        /* check for just a regular mapped key string */
  89.             if((*temp_key).key_data.key_str!=NULL)
  90.                 free((*temp_key).key_data.key_str);
  91.             else
  92.                 return(-1);
  93.           }    /* end if */
  94.         RESET_KEY_MAPPED((int)search_key);    /* reset the mapped & special flags */
  95.         RESET_KEY_SPECIAL((int)search_key);
  96.         free(temp_key);            /* free the key node */
  97.       }    /* end if */
  98.     else
  99.         return(-1);
  100. }    /* end del_key() */
  101.  
  102. /**********************************************************************
  103. *  Function    :    add_key
  104. *  Purpose    :    add a node to the list of mapped keys
  105. *  Parameters    :
  106. *            search_key - the keycode to add to the list
  107. *            key_map_str - the string to map the key to
  108. *            is_special - flag to indicate kermit verbs re-mapping
  109. *            special_code - the kermit code to re-map to
  110. *  Returns    :    -1 for an out of memory error, 0 otherwise
  111. *  Calls    :    none
  112. *  Called by    :    read_keyboard_file()
  113. **********************************************************************/
  114. static int add_key(unsigned int search_key,char *key_map_str,int is_special,byte special_code)
  115. {
  116.     key_node *temp_key;        /* temporary pointer for the key node to add to the list */
  117.  
  118.     if(IS_KEY_MAPPED(search_key)) {    /* check for strictly re-mapping this key */
  119.         if((temp_key=find_key(search_key))!=NULL) {        /* get the key code to remap */
  120.             if(IS_KEY_SPECIAL(search_key)) {        /* check whether the key we are re-mapping is a verb */
  121.                 if(is_special)        /* check whether the new key is special also */
  122.                     (*temp_key).key_data.vt100_code=special_code;    /* just change the vt100 code generated */
  123.                 else {            /* allocate room for the string to map */
  124.                     RESET_KEY_SPECIAL((int)search_key);    /* reset the special flag */
  125.                     if(((*temp_key).key_data.key_str=strdup(key_map_str))==NULL)    /* duplicate the string to re-map to */
  126.                         return(-1);    /* indicate no more memory */
  127.                   }    /* end else */
  128.               }    /* end if */
  129.             else {        /* not a special key, we need to free the old string */
  130.                 if((*temp_key).key_data.key_str!=NULL)    /* free the old string */
  131.                     free((*temp_key).key_data.key_str);
  132.                 if(is_special) {        /* check whether the new key is special also */
  133.                     (*temp_key).key_data.vt100_code=special_code;    /* just change the vt100 code generated */
  134.                     SET_KEY_SPECIAL((int)search_key);        /* set the special flag */
  135.                   }    /* end if */
  136.                 else {            /* allocate room for the string to map */
  137.                     if(((*temp_key).key_data.key_str=strdup(key_map_str))==NULL)    /* duplicate the string to re-map to */
  138.                         return(-1);    /* indicate no more memory */
  139.                   }    /* end else */
  140.               }    /* end else */
  141.             return(0);            /* indicate no error */
  142.           }    /* end if */
  143.         else        /* uh-uh, memory is messed up */
  144.             return(-1);
  145.       }    /* end if */
  146.     if((temp_key=(key_node *)malloc((size_t)sizeof(key_node)))!=NULL){    /* allocate room for the key node */
  147.         (*temp_key).key_code=search_key;    /* set the key code for this node */
  148.         SET_KEY_MAPPED((int)search_key);    /* indicate this key is mapped */
  149.         if(is_special) {    /* check for a kermit verb to re-map to */
  150.             SET_KEY_SPECIAL((int)search_key);
  151.             (*temp_key).key_data.vt100_code=special_code;
  152.           }    /* end if */
  153.         else {
  154.             if(((*temp_key).key_data.key_str=strdup(key_map_str))==NULL)    /* duplicate the string to re-map to */
  155.                 return(-1);    /* indicate no more memory */
  156.           }    /* end else */
  157.         (*temp_key).next_node=head_key;    /* attach to the linked list */
  158.         head_key=temp_key;
  159.         return(0);
  160.       }    /* end if */
  161.     else
  162.         return(-1);        /* indicate out of memory */
  163. }    /* end add_key() */
  164.  
  165. /**********************************************************************
  166. *  Function    :    parse_verb()
  167. *  Purpose    :    compare the verb_str against the various Kermit verbs
  168. *                which we support, and set the correct (internal)
  169. *                vt100 code for that key.  Otherwise, set an error code
  170. *                to return.
  171. *  Parameters    :
  172. *            verb_str - pointer to a string to compare against the kermit verbs we support
  173. *            ret_code - pointer to an unsigned int to return the (internal) vt100 code in
  174. *  Returns    :    0xFFFF for error, otherwise, the length of the kermit verb
  175. *                indentified.
  176. *  Calls    :    none
  177. *  Called by    :    parse_str()
  178. **********************************************************************/
  179. static int parse_verb(char *verb_str,uint *ret_code)
  180. {
  181.     if(!strnicmp(verb_str,"null",4)) {        /* check for sending NULL (0) character */
  182.         *ret_code=0;        /* indicate NULL character */
  183.         return(4);            /* indicate the number of characters to skip */
  184.       }    /* end if */
  185.     else if(!strnicmp(verb_str,"gold",4)) {    /* check for vt102 function key f1 */
  186.         *ret_code=VSF1;        /* indicate f1 character */
  187.         return(4);            /* indicate the number of characters to skip */
  188.       }    /* end if */
  189.     else if(!strnicmp(verb_str,"pf1",3)) {    /* check for vt102 function key f1 */
  190.         *ret_code=VSF1;        /* indicate f1 character */
  191.         return(3);            /* indicate the number of characters to skip */
  192.       }    /* end if */
  193.     else if(!strnicmp(verb_str,"pf2",3)) {    /* check for vt102 function key f2 */
  194.         *ret_code=VSF2;        /* indicate f2 character */
  195.         return(3);            /* indicate the number of characters to skip */
  196.       }    /* end if */
  197.     else if(!strnicmp(verb_str,"pf3",3)) {    /* check for vt102 function key f3 */
  198.         *ret_code=VSF3;        /* indicate f3 character */
  199.         return(3);            /* indicate the number of characters to skip */
  200.       }    /* end if */
  201.     else if(!strnicmp(verb_str,"pf4",3)) {    /* check for vt102 function key f4 */
  202.         *ret_code=VSF4;        /* indicate f4 character */
  203.         return(3);            /* indicate the number of characters to skip */
  204.       }    /* end if */
  205.     else if(!strnicmp(verb_str,"kp0",3)) {    /* check for vt102 keypad numeric keys */
  206.         *ret_code=VSK0;        /* indicate keypad character */
  207.         return(3);            /* indicate the number of characters to skip */
  208.       }    /* end if */
  209.     else if(!strnicmp(verb_str,"kp1",3)) {    /* check for vt102 keypad numeric keys */
  210.         *ret_code=VSK1;        /* indicate keypad character */
  211.         return(3);            /* indicate the number of characters to skip */
  212.       }    /* end if */
  213.     else if(!strnicmp(verb_str,"kp2",3)) {    /* check for vt102 keypad numeric keys */
  214.         *ret_code=VSK2;        /* indicate keypad character */
  215.         return(3);            /* indicate the number of characters to skip */
  216.       }    /* end if */
  217.     else if(!strnicmp(verb_str,"kp3",3)) {    /* check for vt102 keypad numeric keys */
  218.         *ret_code=VSK3;        /* indicate keypad character */
  219.         return(3);            /* indicate the number of characters to skip */
  220.       }    /* end if */
  221.     else if(!strnicmp(verb_str,"kp4",3)) {    /* check for vt102 keypad numeric keys */
  222.         *ret_code=VSK4;        /* indicate keypad character */
  223.         return(3);            /* indicate the number of characters to skip */
  224.       }    /* end if */
  225.     else if(!strnicmp(verb_str,"kp5",3)) {    /* check for vt102 keypad numeric keys */
  226.         *ret_code=VSK5;        /* indicate keypad character */
  227.         return(3);            /* indicate the number of characters to skip */
  228.       }    /* end if */
  229.     else if(!strnicmp(verb_str,"kp6",3)) {    /* check for vt102 keypad numeric keys */
  230.         *ret_code=VSK6;        /* indicate keypad character */
  231.         return(3);            /* indicate the number of characters to skip */
  232.       }    /* end if */
  233.     else if(!strnicmp(verb_str,"kp7",3)) {    /* check for vt102 keypad numeric keys */
  234.         *ret_code=VSK7;        /* indicate keypad character */
  235.         return(3);            /* indicate the number of characters to skip */
  236.       }    /* end if */
  237.     else if(!strnicmp(verb_str,"kp8",3)) {    /* check for vt102 keypad numeric keys */
  238.         *ret_code=VSK8;        /* indicate keypad character */
  239.         return(3);            /* indicate the number of characters to skip */
  240.       }    /* end if */
  241.     else if(!strnicmp(verb_str,"kp9",3)) {    /* check for vt102 keypad numeric keys */
  242.         *ret_code=VSK9;        /* indicate keypad character */
  243.         return(3);            /* indicate the number of characters to skip */
  244.       }    /* end if */
  245.     else if(!strnicmp(verb_str,"kpdot",5)) {    /* check for other vt102 keypad keys */
  246.         *ret_code=VSKP;        /* indicate keypad character */
  247.         return(5);            /* indicate the number of characters to skip */
  248.       }    /* end if */
  249.     else if(!strnicmp(verb_str,"kpminus",7)) {    /* check for other vt102 keypad keys */
  250.         *ret_code=VSKM;        /* indicate keypad character */
  251.         return(7);            /* indicate the number of characters to skip */
  252.       }    /* end if */
  253.     else if(!strnicmp(verb_str,"kpcoma",6)) {    /* check for other vt102 keypad keys */
  254.         *ret_code=VSKC;        /* indicate keypad character */
  255.         return(6);            /* indicate the number of characters to skip */
  256.       }    /* end if */
  257.     else if(!strnicmp(verb_str,"kpenter",7)) {    /* check for other vt102 keypad keys */
  258.         *ret_code=VSKE;        /* indicate keypad character */
  259.         return(7);            /* indicate the number of characters to skip */
  260.       }    /* end if */
  261.     else if(!strnicmp(verb_str,"uparr",5)) {    /* check for vt102 cursor (arrow) keys */
  262.         *ret_code=VSUP;        /* indicate cursor key */
  263.         return(5);            /* indicate the number of characters to skip */
  264.       }    /* end if */
  265.     else if(!strnicmp(verb_str,"dnarr",5)) {    /* check for vt102 cursor (arrow) keys */
  266.         *ret_code=VSDN;        /* indicate cursor key */
  267.         return(5);            /* indicate the number of characters to skip */
  268.       }    /* end if */
  269.     else if(!strnicmp(verb_str,"lfarr",5)) {    /* check for vt102 cursor (arrow) keys */
  270.         *ret_code=VSLT;        /* indicate cursor key */
  271.         return(5);            /* indicate the number of characters to skip */
  272.       }    /* end if */
  273.     else if(!strnicmp(verb_str,"rtarr",5)) {    /* check for vt102 cursor (arrow) keys */
  274.         *ret_code=VSRT;        /* indicate cursor key */
  275.         return(5);            /* indicate the number of characters to skip */
  276.       }    /* end if */
  277.     else {            /* indicate that we recognize this kermit verb */
  278.         *ret_code=0xFFFF;        /* indicate that we don't recognize this verb */
  279.         return(strcspn(verb_str,end_token));    /* return the number of characters to skip */
  280.       }    /* end else */
  281. }    /* end parse_verb() */
  282.  
  283. /**********************************************************************
  284. *  Function    :    parse_str()
  285. *  Purpose    :    parse the string to map a key to.
  286. *  Parameters    :
  287. *            file_str - pointer to a string from the file to parse
  288. *            ret_code - pointer to an unsigned int to return an (internal)vt100 code in
  289. *  Returns    :    0xFFFF for error, otherwise, the vt100 code for telbin
  290. *  Calls    :    parse_verb()
  291. *  Called by    :    read_keyboard_file()
  292. **********************************************************************/
  293. static char *parse_str(char *file_str,uint *ret_code)
  294. {
  295.     int buff_off=0,            /* current location in the buffer */
  296.         ascii_num,            /* ascii character encoded after a backslash */
  297.         kermit_length,        /* the length of a kermit verb returned from parsing it */
  298.         done=0;                /* flag for dropping out of the loop */
  299.     byte *ret_str,            /* the string variable to return the result in */
  300.         *temp_str,            /* pointer to the current place in the string */
  301.         buffer[MAX_LINE_LENGTH];        /* buffer to store the string we are unravelling */
  302.  
  303.     *ret_code=0xFFFF;        /* mark return code to indicate nothing special to return */
  304.     temp_str=file_str;        /* start at the beginning of the string to parse */
  305.     while((*temp_str)!='\0' && buff_off<MAX_LINE_LENGTH && !done) {        /* parse until the end of the string or until the buffer is full */
  306.         while((*temp_str) && (*temp_str)!=';' && (*temp_str)!='\\' && (*temp_str)!='{' && (*temp_str)>' ') {    /* copy regular characters until a special one is hit */
  307.             buffer[buff_off]=(*temp_str);        /* copy the character */
  308.             buff_off++;        /* increment the position in the buffer */
  309.             temp_str++;        /* increment the position in the parse string */
  310.           }    /* end while */
  311.         if(*temp_str) {        /* check on the various special cases for dropping out of the loop */
  312.             switch(*temp_str) {        /* switch for the special case */
  313.                 case '\\':    /* backslash for escape coding a character */
  314.                     temp_str++;        /* get the character after the backslash */
  315.                     if((*temp_str)=='{') {    /* check for curly brace around numbers */
  316.                         temp_str++;    /* increment to the next character */
  317.                         if((*temp_str)=='K' || (*temp_str)=='k') {        /* check for Kermit escape code here also */
  318.                             temp_str++;        /* increment past the kermit flag */
  319.                             kermit_length=parse_verb(temp_str,ret_code);        /* parse the kermit verb, and return the correct kermit code in the ret_code */
  320.                             if(*ret_code!=0xFFFF)        /* a kermit verb was specified that we recognize */
  321.                                 return(NULL);        /* return now, indicating a kermit verb we recognize in the ret_code variable */
  322.                             temp_str+=kermit_length;    /* increment past the kermit verb */
  323.                           }    /* end if */
  324.                         else if((*temp_str)=='o') {    /* check for octal number */
  325.                             ascii_num=octal_to_int(temp_str);    /* get the acii number after the escape code */
  326.                             buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  327.                             buff_off++;                /* increment our position */
  328.                             while((*temp_str)>='0' && (*temp_str)<='7')    /* increment our position past the digits */
  329.                                 temp_str++;
  330.                           }    /* end if */
  331.                         else if((*temp_str)=='x') {    /* check for hexadecimal number */
  332.                             ascii_num=hex_to_int(temp_str);    /* get the acii number after the escape code */
  333.                             buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  334.                             buff_off++;                /* increment our position */
  335.                             while(isxdigit((int)(*temp_str)))    /* increment our position past the digits */
  336.                                 temp_str++;
  337.                           }    /* end if */
  338.                         else {        /* must be an escape integer */
  339.                             if((*temp_str)=='d')    /* check for redundant decimal number specification */
  340.                                 temp_str++;
  341.                             ascii_num=atoi(temp_str);    /* get the ascii number after the escape code */
  342.                             buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  343.                             buff_off++;                /* increment our position */
  344.                             while(isdigit((int)(*temp_str)))    /* increment our position past the digits */
  345.                                 temp_str++;
  346.                           }    /* end else */
  347.                         if((*temp_str)=='}')    /* found the closing curly brace */
  348.                             temp_str++;        /* jump over the closing curly brace */
  349.                         else {        /* closing curly brace missing, indicate error */
  350.                             buff_off=0;
  351.                             done=1;
  352.                           }    /* end else */
  353.                       }    /* end if */
  354.                     else if((*temp_str)=='K' || (*temp_str)=='k') {        /* check for Kermit escape code */
  355.                         temp_str++;        /* increment past the kermit flag */
  356.                         kermit_length=parse_verb(temp_str,ret_code);        /* parse the kermit verb, and return the correct kermit code in the ret_code */
  357.                         if(*ret_code!=0xFFFF)        /* a kermit verb was specified that we recognize */
  358.                             return(NULL);        /* return now, indicating a kermit verb we recognize in the ret_code variable */
  359.                         temp_str+=kermit_length;    /* increment past the kermit verb */
  360.                       }    /* end if */
  361.                     else if((*temp_str)=='o') {    /* check for octal number */
  362.                         ascii_num=octal_to_int(temp_str);    /* get the acii number after the escape code */
  363.                         buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  364.                         buff_off++;                /* increment our position */
  365.                         while((*temp_str)>='0' && (*temp_str)<='7')    /* increment our position past the digits */
  366.                             temp_str++;
  367.                       }    /* end if */
  368.                     else if((*temp_str)=='x') {    /* check for hexadecimal number */
  369.                         ascii_num=hex_to_int(temp_str);    /* get the acii number after the escape code */
  370.                         buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  371.                         buff_off++;                /* increment our position */
  372.                         while(isxdigit((int)(*temp_str)))    /* increment our position past the digits */
  373.                             temp_str++;
  374.                       }    /* end if */
  375.                     else {        /* must be an escape integer */
  376.                         if((*temp_str)=='d')    /* check for redundant decimal number specification */
  377.                             temp_str++;
  378.                         ascii_num=atoi(temp_str);    /* get the ascii number after the escape flag */
  379.                         buffer[buff_off]=(byte)ascii_num;    /* store the ascii code in the buffer */
  380.                         buff_off++;                /* increment our position */
  381.                         while(isdigit((int)(*temp_str)))    /* increment our position past the digits */
  382.                             temp_str++;
  383.                       }    /* end else */
  384.                     break;
  385.  
  386.                 case '{':    /* curly brace opens a quoted string */
  387.                     temp_str++;        /* jump over the brace itself */
  388.                     while((*temp_str) && (*temp_str)!='}') {    /* copy regular characters until a special one is hit */
  389.                         if((*temp_str)=='\\') {     /* check for a backslash in the curly braces */
  390.                             temp_str++; /* increment to the next character */
  391.                             if((*temp_str)=='o') { /* check for octal number */
  392.                                 ascii_num=octal_to_int(temp_str);   /* get the acii number after the escape code */
  393.                                 buffer[buff_off]=(byte)ascii_num;   /* store the ascii code in the buffer */
  394.                                 buff_off++;             /* increment our position */
  395.                                 while((*temp_str)>='0' && (*temp_str)<='7') /* increment our position past the digits */
  396.                                     temp_str++;
  397.                               } /* end if */
  398.                             else if((*temp_str)=='x') { /* check for hexadecimal number */
  399.                                 ascii_num=hex_to_int(temp_str); /* get the acii number after the escape code */
  400.                                 buffer[buff_off]=(byte)ascii_num;   /* store the ascii code in the buffer */
  401.                                 buff_off++;             /* increment our position */
  402.                                 while(isxdigit((int)(*temp_str)))   /* increment our position past the digits */
  403.                                     temp_str++;
  404.                               } /* end if */
  405.                             else {      /* must be an escape integer */
  406.                                 if((*temp_str)=='d')    /* check for redundant decimal number specification */
  407.                                     temp_str++;
  408.                                 ascii_num=atoi(temp_str);   /* get the ascii number after the escape code */
  409.                                 buffer[buff_off]=(byte)ascii_num;   /* store the ascii code in the buffer */
  410.                                 buff_off++;             /* increment our position */
  411.                                 while(isdigit((int)(*temp_str)))    /* increment our position past the digits */
  412.                                     temp_str++;
  413.                               } /* end else */
  414.                           } /* end if */
  415.                         buffer[buff_off]=(*temp_str);        /* copy the character */
  416.                         buff_off++;        /* increment the position in the buffer */
  417.                         temp_str++;        /* increment the position in the parse string */
  418.                       }    /* end while */
  419.                     if((*temp_str)=='}')        /* found the closing brace */
  420.                         temp_str++;        /* jump over the closing brace */
  421.                     else {        /* line terminated without closing brace */
  422.                         buff_off=0;        /* indicate error condition */
  423.                         done=1;            /* drop out of the loop */
  424.                       }    /* end else */
  425.                     break;
  426.  
  427.                 default:    /* ctrl characters, space, and semi-colon terminate a string */
  428.                     buffer[buff_off]='\0';    /* terminate the string */
  429.                     done=1;
  430.                     break;
  431.  
  432.               }    /* end switch */
  433.           }    /* end if */
  434.         else
  435.             buffer[buff_off]='\0';    /* terminate the string */
  436.       }    /* end while */
  437.     if(buff_off>0) {
  438.         if((ret_str=malloc(buff_off+1))!=NULL)
  439.             strcpy(ret_str,buffer);        /* copy the parsed string */
  440.         return(ret_str);
  441.       }    /* end if */
  442.     return(NULL);
  443. }    /* end parse_str() */
  444.  
  445. /**********************************************************************
  446. *  Function    :    read_keyboard_file
  447. *  Purpose    :    read in a keyboard mapping file, parse the input and 
  448. *                map keys
  449. *  Parameters    :
  450. *            key_file - string containing the name of the keyboard mapping file
  451. *  Returns    :    0 for no error, -1 for any errors which occur
  452. *  Calls    :    parse_str(), & lots of library string functions
  453. *  Called by    :    initkbfile(), Sconfile()
  454. **********************************************************************/
  455. int read_keyboard_file(char *key_file)
  456. {
  457.     FILE *key_fp;            /* pointer to the keyboard file */
  458.     char key_line[MAX_LINE_LENGTH],        /* static array to store lines read from keyboard file */
  459.         *map_str,            /* the parsed string from the keyboard file */
  460.         *temp_str;            /* temporary pointer to a string */
  461.     uint line_no=0,            /* what line in the file we are on */
  462.         token_num,            /* the current token we are parsing */
  463.         where,                /* pointer to the beginning of text */
  464.         kermit_code,        /* the variable to return the possible 'kermit verb' code in */
  465.         re_map_key,            /* the key to re-map */
  466.         error=0;            /* error from the file reading */
  467.  
  468.     if((key_fp=fopen(key_file,"rt"))!=NULL) {
  469.         while((temp_str=fgets(key_line,MAX_LINE_LENGTH,key_fp))!=NULL && !error) {    /* get a line of input */
  470.             token_num=0;            /* initialize the token we are on */
  471.             if((temp_str=strtok(key_line,white_sp))!=NULL) {    /* get the first token from the string */
  472.                 if((*temp_str)!=';') {        /* check for a comment line */
  473.                     do {
  474.                         switch(token_num) {        /* switch on which token we are processing */
  475.                             case 0:        /* the 'SET' token (we already know it is not a comment) */
  476.                                 if(stricmp(temp_str,"SET")) {    /* make certain the first token is a SET token */
  477.                                     printf("invalid token #%d:'%s' on line %d\n",token_num,temp_str,line_no);
  478.                                     token_num=4;    /* bump the token count up to drop out of the loop */
  479.                                   }    /* end if */
  480.                                 break;
  481.  
  482.                             case 1:        /* the 'KEY' token */
  483.                                 if(stricmp(temp_str,"KEY")) {    /* make certain the first token is a KEY token */
  484.                                     printf("invalid token #%d:'%s' on line %d\n",token_num,temp_str,line_no);
  485.                                     token_num=4;    /* bump the token count up to drop out of the loop */
  486.                                   }    /* end if */
  487.                                 break;
  488.  
  489.                             case 2:        /* the key to be re-mapped */
  490.                                 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 */
  491.                                     token_num=4;    /* bump the token count up to drop out of the loop */
  492.                                   }    /* end if */
  493.                                 else {        /* the 'key' field is not a special command or a comment, must be a valid character */
  494.                                     if(*(temp_str)!='\\') {    /* the key to re-map is not an escape code */
  495.                                         re_map_key=*temp_str;    /* set the re-mapping key */
  496.                                       }    /* end if */
  497.                                     else {
  498.                                         re_map_key=atoi(temp_str+1);    /* get the re-mapping key value from the string */
  499.                                         if(re_map_key==0) {        /* invalid key code */
  500.                                             printf("Error, invalid key code:%s, on line %d\n",temp_str,line_no);
  501.                                             token_num=4;    /* bump the token count up to drop out of the loop */
  502.                                           }    /* end if */
  503.                                       }    /* end else */
  504.                                   }    /* end else */
  505.                                 break;
  506.  
  507.                             case 3:        /* the string to re-map the key to */
  508.                                 if((*temp_str)==';') {    /* ignore the rest of the line if the 'key' is one of the tokens we don't support */
  509.                                     if(IS_KEY_MAPPED(re_map_key))    /* check for the key being already re-mapped */
  510.                                         error=del_key(re_map_key);
  511.                                     token_num=4;    /* bump the token count up to drop out of the loop */
  512.                                   }    /* end if */
  513.                                 else {
  514.                                     if((map_str=parse_str(temp_str,&kermit_code))!=NULL) {        /* parse the re-mapping string */
  515.                                         error=add_key(re_map_key,map_str,0,0);    /* add a regular key string to the key mapping list */
  516.                                         free((char *)map_str);
  517.                                       }    /* end if */
  518.                                     else {
  519.                                         if(kermit_code!=0xFFFF) {    /* check for special kermit verb returned */
  520.                                             error=add_key(re_map_key,NULL,1,(byte)kermit_code);    /* add a kermit code to the list */
  521.                                           }    /* end if */
  522.                                         else {
  523.                                             if(IS_KEY_MAPPED(re_map_key))    /* check for the key being already re-mapped */
  524.                                                 error=del_key(re_map_key);
  525.                                             printf("Error, re-mapping string:%s invalid on line %d\n",temp_str,line_no);
  526.                                             token_num=4;    /* bump the token count up to drop out of the loop */
  527.                                           }    /* end else */
  528.                                       }    /* end else */
  529.                                   }    /* end else */
  530.                                 break;
  531.                           }    /* end switch */
  532.                         token_num++;
  533.                         if(token_num<3)        /* if the next token is not the last one, then grab it */
  534.                             temp_str=strtok(NULL,white_sp);        /* get the next token */
  535.                         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 */
  536.                             temp_str+=(strlen(temp_str)+1);        /* jump over the previous token */
  537.                             where=strspn(temp_str,white_sp);    /* look for the first non-white space in the line */
  538.                             temp_str+=where;    /* jump to the first position with a character */
  539.                             if(!isgraph(*temp_str)) {        /* not more characters in the line */
  540.                                 if(IS_KEY_MAPPED(re_map_key))    /* check for the key being already re-mapped */
  541.                                     error=del_key(re_map_key);
  542.                                 token_num=4;    /* bump the token count to drop out of the loop */
  543.                               }    /* end if */
  544.                           }    /* end if */
  545.                       }    while(temp_str!=NULL && token_num<4);
  546.                   }    /* end if */
  547.                 else {
  548.                   }    /* end else */
  549.               }    /* end if */
  550.             line_no++;            /* increment current line */
  551.           }    /* end while */
  552.         fclose(key_fp);
  553.       }    /* end if */
  554.     else
  555.         error=(-1);        /* indicate an error */
  556.     return(error);
  557. }    /* end read_keyboard_file() */
  558.  
  559. /**********************************************************************
  560. *  Function    :    find_key
  561. *  Purpose    :    search through the list of mapped keys and return a pointer
  562. *                to the node whose key_code matches the parameter passed
  563. *  Parameters    :
  564. *            search_key - the keycode to search the list for
  565. *  Returns    :    NULL for a match not found, or a pointer to the key_node
  566. *                containing the matched keycode
  567. *  Calls    :    none
  568. *  Called by    :    vt100key()
  569. **********************************************************************/
  570. key_node *find_key(unsigned int search_key)
  571. {
  572.     key_node *temp_key;        /* temporary pointer to a key node used to search to the matching key code */
  573.  
  574.     temp_key=head_key;        /* start at the head of the linked list */
  575.     while(temp_key!=NULL) {    /* search the entire list */
  576.         if((*temp_key).key_code==search_key)    /* check for match */
  577.             return(temp_key);    /* return the pointer to the matched node */
  578.         temp_key=(*temp_key).next_node;
  579.       }    /* end while */
  580.     return(NULL);
  581. }    /* end find_key() */
  582.  
  583. /**********************************************************************
  584. *  Function    :    initkbfile()
  585. *  Purpose    :    initialize the default keyboard settings and read in
  586. *                the default keycodes from telnet.key
  587. *  Parameters    :    none
  588. *  Returns    :    0 for no error, <0 for various errors
  589. *  Calls    :    none
  590. *  Called by    :    main()
  591. **********************************************************************/
  592. int initkbfile(void )
  593. {
  594.     char kb_name[_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT];    /* temporary variable to hold the entire pathname of "telnet.key" */
  595.     int error;            /* the error code returned from reading in the keyboard mapping file */
  596.  
  597.     memset(key_map_flags,0,1024);        /* initialize all the keyboard mapped flags to zero (not mapped) */
  598.     memset(key_special_flags,0,1024);    /* initialize all the keyboard special flags to zero (not special) */
  599.     strcpy(kb_name,path_name);    /* get the directory where telbin.exe is */
  600.     strcat(kb_name,"telnet.key");    /* append the proper name */
  601.     error=read_keyboard_file(kb_name);
  602.     return(error);
  603. }    /* end initkbfile() */
  604.