/* Comm keyboard routines */ #define KEYBOARD 1 #include "globals.h" extern int capture; #define ERR "\nKEY MACRO error." #define KEYERR -1 #define NOMEM -2 #define OFFSET FN1 /* convert to cardinal number */ static UBYTE *string; /* temp string pointer */ static UBYTE workbuff[ SECSIZ ]; /* keyboard macro work area */ #define ENTRIES 112 /* keys on keyboard */ UBYTE toasc(code,qual) USHORT qual,code; { static USHORT caps = FALSE; UBYTE c; static UBYTE nosh[ ENTRIES ] = { '`','1','2','3','4','5','6','7', '8','9','0','-','=',SLH,UND,'0', 'q','w','e','r','t','y','u','i', 'o','p','[',']',UND,'1','2','3', 'a','s','d','f','g','h','j','k', 'l',';',APS,UND,UND,'4','5','6', UND,'z','x','c','v','b','n','m', ',','.','/',UND,'.','7','8','9', ' ',BKS,TAB,ENT,RET,ESC,DEL,UND, UND,UND,'-',UND,CUP,CDN,CFW,CBK, FN1,FN2,FN3,FN4,FN5,FN6,FN7,FN8, FN9,F10,UND,UND,UND,UND,UND,HLP, LSH,RSH,CAP,CTL,LAL,RAL,LAM,RAM, LMB,RMB,MMB,UND,UND,UND,UND,UND }; static UBYTE shift[ ENTRIES ] = { '~','!','@','#','$','%','^','&', '*','(',')','_','+','|',UND,'0', 'Q','W','E','R','T','Y','U','I', 'O','P','{','}',UND,'1','2','3', 'A','S','D','F','G','H','J','K', 'L',':','"',UND,UND,'4','5','6', UND,'Z','X','C','V','B','N','M', '<','>','?',UND,'.','7','8','9', ' ',BKS,TAB,ENT,RET,ESC,DEL,UND, UND,UND,'-',UND,CUP,CDN,CFW,CBK, SF1,SF2,SF3,SF4,SF5,SF6,SF7,SF8, SF9,S10,UND,UND,UND,UND,UND,SHH, LSH,RSH,CAP,CTL,LAL,RAL,LAM,RAM, LMB,RMB,MMB,UND,UND,UND,UND,UND }; switch(code) { case 98: caps = TRUE; break; /* caps lock pressed */ case 226: caps = FALSE; break; /* caps lock released */ } if(code < ENTRIES) { c = nosh[ code ]; /* default lower case */ if(qual & 0x40) /* left amiga */ { switch(c) { case 'p': return TOGPRT; /* Toggle printer */ case 'c': return TOGCAP; /* Toggle capture buffer */ case 's': return TOGSCR; } } if(qual & 3) return (shift[ code ]); /* shift key down */ if( isalpha(c) ) /* control or CAPS? */ { if(qual & 8) return(UBYTE)(shift[ code ] - '@');/* control down ? */ /* make it a control */ if ( caps ) /* caps lock down */ return ( shift[ code ]); /* make it upper case */ } return (c); } return (UND); /* for release code */ } /* end of routine */ /* Expand keyboard macros. Control characters are sent by prefixing the ASCII equiv. with ^. Ex, control C is ^C, control X is ^X. Also translates C type slash characters like \t, \r and \n. In this implimentation, \n and \r generate the RETURN code (0xD). Also, \w produces a 500 millisecond delay and \l produces a line break. */ void expand_macro(key) char key; { key -= OFFSET; /* F1 becomes offset zero */ string = keymacro[ key ]; /* point to definition */ if(string == NULL) return; /* return if not defined */ sendout( string ); } /* do the actual expansion. Send the characters to the modem */ sendout(str) UBYTE *str; { static UBYTE macro[] = "00000000000000000000"; unsigned key; UBYTE c; while( c = *str++ ) /* do until end of string */ { if( c == '^') { /* control character ^? */ if((c = *str++) == '^') break; else c = toupper(c)- 0x40; /* convert only valid chars */ } else if( c == '\\') /* have an escape character? */ switch( c = tolower(*str++)) /* yes, get next character */ { case 'r': c = '\r'; break; /* C equivilents */ case 'n': c = '\r'; break; case 't': c = '\t'; break; case 'f': c = '\f'; break; case 'b': c = '\b'; break; /* now my own */ /* case 'p': c = *str++; if( c == '^') c = toupper(*str++) - 0x40; do { key = readchar(10,0); if( key == TIMEOUT ) break; } while ( (tolower(key) != tolower(c)) ); continue; */ case 'l': /* line break */ SendBreak(); continue; case 'w': /* delay 1/2 second */ Delay(25L);continue; case 'm': /* expand another macro */ key = atoi(str); while(isdigit(*str)) str++; if( (key > 0) && (key <= KEYMACS) ) { if(macro[ key -1 ] != '0') { emits_rx("\nKEY MACRO RECURSION not allowed -- or desired!\n"); continue; } macro[ key-1 ] = '1'; expand_macro( key - 1 + OFFSET ); macro[ key-1 ] = '0'; } continue; case '\\':break; default: /* was really a \ character alone */ str--; /* adjust string pointer */ c = '\\'; /* and send the \ */ } if(halfduplex) emit_rx( c ); if(split_screen) emit_tx( c ); /* echo it to the user */ if (capture && capton) /* capturing data to disk file? */ if (isprint(c)) buffer_it(c); sendchar( c ); } } /* open keyboard macro file. Return 0 if not found, else return # of macros in the library. allocate memory for the macros and copy them to memory. */ int Init_keymacros() { USHORT i; for(i = 0; i < KEYMACS; i++) /* init array of pointers */ keymacro[i] = NULL; Load_keymacros(commkeys); } Load_keymacros(name) UBYTE *name; { extern UBYTE *malloc(); int index, i; FILE *inp; UBYTE temp[42], *file, p[42]; if(*name == NULL) return; /* no name given */ strcpy(p,name); i = strlen(p); while(--i) /* remove trailing blanks from */ if(p[i] != ' ') break; /* filename */ if(i == 0) return; /* blank name given */ p[++i] = NULL; index = 0; strcpy(temp,install.DefDir); strcat(temp,p); file = name; /* try to open macro file */ if(( inp = fopen(p,"r")) == NULL) /* check default directory */ { file = temp; if((inp = fopen(temp,"r")) == NULL) /* then SYS: directory */ return NULL; } strcpy(commkeys,file); Free_keymacros(); /* free any memory allocated */ while (fgets(workbuff,SECSIZ,inp)) /* do until end of file */ { if(strlen(workbuff) < 3) continue; /* ignore short lines */ workbuff[ strlen(workbuff)-1 ] = NULL; /* kill trailing \n */ if((index = Add_keymacro()) == NOMEM) /* no memory left */ { emits_rx("\nOut of memory\n"); break; } } fclose(inp); return index; } /* Save key macros to named file */ Save_keymacros(name) UBYTE *name; { FILE *out; USHORT i; int error; if((out = fopen(name,"w")) == NULL) { sprintf(sbuff,"\nCan't open file %s\n",name); emits_rx(sbuff); return NULL; } for(i = 0; i < KEYMACS; i++) if( keymacro[ i ] ) fprintf(out,"%c%d%s\n", (i > 9) ? 'S' : 'F', (i > 9) ? i-9 : i+1, keymacro[ i ]); error = ferror(out); fclose( out ); if( error ) { emits_rx("Error during file write\n"); return NULL; } return OK; } /* Return memory allocated for all key macros */ Free_keymacros() { int i; for( i=0; i < KEYMACS; i++) free_macro(i); } /* Return memory allocated for single macro */ free_macro(num) int num; { if(keymacro[ num ]) { free(keymacro[ num ]); keymacro[ num ] = NULL; } } /* Bring up the ASCII input window for macro entry */ Edit_keymacro() { workbuff[0] = NULL; getstring(" USE","new key macro",workbuff,SECSIZ); } /* Parse macro string and add it to macro list */ Add_keymacro() { int index, shift; if(*workbuff == NULL) return NULL; string = &workbuff[2]; if( (toupper(*workbuff) != 'F' && toupper(*workbuff) != 'S') || !isdigit(workbuff[1])) { /* line doesn't start with Fn or Sn */ emits_rx(ERR); sprintf(sbuff,"\nExpected Fnn or Snn but read: %10s\n",workbuff); emits_rx(sbuff); return KEYERR; } shift = (toupper(*workbuff) == 'F') ? 0 : 10; index = workbuff[1] - '1'; /* index is 0 to 9 */ if(workbuff[1] == '1') if(workbuff[2] == '0') { /* F10 is ok */ string++; /* skip past extra 0 */ index = 9; /* make index 10 - 1 */ } index += shift; /* account for shift Fnn key */ free_macro(index); /* if already allocated, deallocate it */ if(*string == NULL) return NULL; keymacro[index] = malloc(strlen(string)); if(keymacro[index]) /* if allocation succeeded, copy string */ strcpy(keymacro[index],string); else /* else, can't do it */ { sprintf(sbuff,"\nCan't allocate memory for key macro F%d\n", index+1); emits_rx(sbuff); return NOMEM; } return index; }