[comp.sources.misc] v07i055: keydef - quickly, easily redefine VT[23]xx function keys

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (08/08/89)

Posting-number: Volume 7, Issue 55
Submitted-by: gordon@prls.UUCP (Gordon Vickers)
Archive-name: keydef


    During the last year, I've submitted this to comp.source.unix
  three times but it's never been posted - don't know why.  Maybe
  it belongs here.  It is running at several sites and I've not
  received any bug reports. 

#! /bin/sh
# PROGRAM NAME: keydef -quickly easily redefine VT[23]xx function keys.
# LANGUAGE: 'C'
# DEVELOPED ON: VAX11/750 running Ultrix (~4.3BSD).
# PORTABILITY: I'm no expert, but I have tried to be careful. Lint complains
#            of the ussual "return value always ignored" and for some
#            reason, complains that exit() and perror() are used inconsitantly.
#            SYS V users will need to edit one line in keydef.h to change
#            the #include <strings.h> to #include <string.h> .
# SPECIAL REQUIREMENTS: none
# SHAR FILE SIZE: -rw-------  1 gordon      23424 Jun  6 10:49 keydef.shar
# AUTHOR: Gordon Vickers {pyramid|mips|phillabs}!prls!gordon
#
# Please send me email if it works for your computer/OS/compiler else please
# send patches.
#
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	keydef.L
#	sample
#	Notes
#	keydef.c
#	keydef.h
#	Makefile
#	132col
#	80col
# This archive created: Tue Jun  6 10:48:01 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(1393 characters)'
if test -f 'README'
then
        echo shar: will not over-write existing file "'README'"
else
sed 's/^        X//' << \SHAR_EOF > 'README'
        XSCCS ID "@(#)README	1.4	4/11/89"
        X
        X   The keydef program allows you to easily reprogram your VT[23]xx
        X function keys.  It allows you to maintain simple description files
        X for quickly setting your function keys for particular applications.
        X
        X   In addition to the keydef program, some other VT[23]xx related
        X stuff (totally independent of keydef) is included.
        X
        Xvt220.tcap  - vt2xx termcap entries and VT320 termcap. The keydef program
        X              DOES NOT rely upon these.  They are included only because I
        X              send this entire package to those requesting VT[23]xx 
        X              termcap entries.
        X
        Xkeydef      - reprogram vt2xx function keys easily (does NOT depend on
        X               vt220.tcap). Simple code. Read documentation for features.
        X
        Xkeydef.L    - manual page. Read with: nroff -man
        X
        X132col, 80col - vt2xx specific shell scripts. These are not executed but
        X             'sourced'. example: % source /usr/local/132col will switch
        X              terminal to 132 columns. As it is, relies on vt220.tcap
        X              but could be easily changed. If you are lazy like I am,
        X              and think the command line requires to much typing, just
        X              program it into one of your function keys !
        X
        X---------------------------------------------------------------------
        XComments, suggestions, and patches may be emailed to:
        XGordon Vickers {pyramid|mips|phillabs}!prls!gordon
SHAR_EOF
if test 1393 -ne "`wc -c < 'README'`"
then
        echo shar: error transmitting "'README'" '(should have been 1393 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'keydef.L'" '(3543 characters)'
if test -f 'keydef.L'
then
        echo shar: will not over-write existing file "'keydef.L'"
else
sed 's/^        X//' << \SHAR_EOF > 'keydef.L'
        X.TH KEYDEF local
        X.ds SI S\s-2IX\s+2\s-2ELS\s+2
        X.SH NAME
        Xkeydef - quickly / easily redefine VT2xx and VT3xx function keys.
        X.SH SYNTEX
        Xkeydef [n filename]
        X.SH DESCRIPTION
        X.I Keydef 
        Xreads a file
        Xin the user's home directory that contains definitions for the function keys.
        XIf no file is specified then the file read is .keydef else the file read
        Xis the concatenation of .keydef and the filename specified.
        XIf unable to open a file,
        Xcertain site specific default setting will be made.
        X.PP
        XThe definition file(s) consist of one definition per line.
        XEach line must start with a one or two digit function key number
        Xfollowed by the ascii string to be programed.
        XIf the string to be programmed begins with a digit,
        Xthen the function key number may require a leading zero to make it two
        Xdigits long.
        X.PP
        XDefinition records may also contain the the two letter symbols \\r,\\t,\\n
        X\\\, and \\^ .
        XThese will be mapped to; RETURN (013H), TAB (009H), NEWLINE
        X(010H), back-slash, and circumflex (AKA "carrot") respectfully.
        X.PP
        XDifinitions may also contain the "tame" representation of control charectors.
        XA two letter sequence begining with a circumflex is assumed to indicate
        Xthat a control charector is to be programmed.
        XIn this case the value of 64 is subtracted from the next charector and
        Xif the result is positive then it is substituted into the output string
        Xin place of the two original charectors.
        XTo program a literal circumflex, preceed it with a backslash.
        X.PP
        XIf the first non-white charector of a record is not a digit then it is
        Xassumed to be a comment and is ignored.
        XThe only exception is if this charector is an exclamation mark.
        XAny line beginning with an exclimation mark is assumed to be a shell escape.
        XThe remainder of the line is passed to a shell.
        X.PP
        X.I keydef
        Xmay also be given a numeric option on the command line.
        XIf the numeric corresponds to a reprogrammable function key number
        Xthe user will be asked to supply a new definition for that key.
        XThe program will then set just that one key and derminate.
        X.SH CHANGES
        X.PP
        X.I keydef
        Xno longer writes to the 
        X.I keydefID
        Xfile of the user's home directory.
        X.PP 
        XDescription files from previous versions are compatible with this version
        Xbut the user is cautioned that this version now maps certain key
        Xcombinations (\\r, \\t, and control charectors) that were not supported
        Xbefore.
        X.PP
        XTo use the programmed function keys simply depress the SHIFT key with
        Xthe desired funtion key.
        X.SH RESTRICTIONS
        X.I Keydef
        Xonly programs function keys 06-14, HELP, DO, and 17-20.
        XThe author has made various attempts at programming other keys
        Xbut without success.
        X.PP
        XLabeling your keyboard becomes more difficult.
        X.PP
        XThere is a finite amount of memory in the terminal for storing the
        Xdefinitions .
        X.PP
        XThe user may experiance dissapointing results in programming keys that
        Xhave long definitions or with keys that follow these.
        XI don't know the source of this problem, prehaps XON/XOFF are interfering.
        XThe work-around is to find a strategic place(s) between definitions
        Xfor a shell escape to "sleep 1".
        X./" reproduce with: nroff -man
        X./" SCCSID @(#)keydef.L	1.4	4/11/89
        X.SH "EXAMPLE FILE"
        X.br
        X06cat ~/.keyids
        X.br
        X7source /usr/local/80col\n
        X.br
        X!echo shell escape worked.
        X.br
        X08 source /usr/local/132col\n
        X.br
        X09 keydef vi
        X.br
        X10 main(argc,argv)\n int    argc;\n char **argv;\n {\n
        X.br
        Xexample of a comment.
        X.br
        X11^[
        X.br
        X15 apropos
        X.SH "SEE ALSO"
        XVT220 or VT320 Programmer Pocket Guide.
        X.SH Author
        XGordon Vickers {pyramid|mips|phillabs}!prls!gordon
        X.br
        Xcomments, suggestions, and patches welcomed.
SHAR_EOF
if test 3543 -ne "`wc -c < 'keydef.L'`"
then
        echo shar: error transmitting "'keydef.L'" '(should have been 3543 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'sample'" '(877 characters)'
if test -f 'sample'
then
        echo shar: will not over-write existing file "'sample'"
else
sed 's/^        X//' << \SHAR_EOF > 'sample'
        XMost any line not starting with a digit is a comment, see manual for exceptions
        X06keydef .vi
        X07source /usr/local/80col\n
        X08source /usr/local/132col\n
        X
        XI use my function key 10 for temporary, repetitive things; complicated
        Xcommands, sequences, etc. Real nice if application allows shell escapes.
        XMost often used with complicated vi commands. 
        X09keydef 10\n
        X
        XFunction key 11 may default to 'esc' but you can override it here
        X11^[
        X12#include <
        X13#define\t
        X14\nmain(argc,argv)\n   int    argc;\n   char **argv;\n{\n
        X
        X15apropos 
        X16mount /dev/ra3a /src;su sccs;cd
        X
        XA word I often need but can never spell
        X17Albuquerque
        X
        XAn example of a shell escape, normally used to sleep for one second (see man)
        X!echo "shell escape"
        X
        XSome vi commands
        X18 ^[:/\n:s\n
        X19 ^[:w\n
        X20^[:!soundslike 
        X
        XNow the hard part is remembering which key is what, especially if you
        Xmaintain several .keydef* files.
SHAR_EOF
if test 877 -ne "`wc -c < 'sample'`"
then
        echo shar: error transmitting "'sample'" '(should have been 877 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Notes'" '(1991 characters)'
if test -f 'Notes'
then
        echo shar: will not over-write existing file "'Notes'"
else
sed 's/^        X//' << \SHAR_EOF > 'Notes'
        XSCCSID @(#)Notes	1.4	4/11/89
        X/******************** Function Key Programming Notes ********************
        X
        X The following notes were gleaned from a Fortran program after having
        X wasted many hours trying to understand the information in the VT220
        X Programmer Pocket Guide ( EK-VT220-HR-001 ) published by Digital
        X Equipment Corp. It would be impracticl to include that Fortran program
        X here so, I apologetically refer the reader to Pg 29 of the guide.
        X
        X  Sending a single string to the terminal may program one or more of the
        X user defined keys (UDK).  The string format in DEC-gibberish is;
        X    DCS Pc;Pl |   Ky1/st1;ky2/st2;...kyn/stn ST
        X    where;
        X          DCS (Device Control String) is ^[P  (ESC-P)
        X          Pc  -if no value or Pc=0, clears all UDKs prior to loading new defs.
        X               if Pc = 1, load new defs, clear any remaining old ones.
        X          Pl  -if no value or Pl = 1, lock keys from being redefined.
        X               if Pl = 1, do not lock keys.
        X          Ky1 -function key address. Formed by adding function key number
        X               to an appropriate offset. See table below.
        X          st1 -the ASCII representation of the HEX digits that represent
        X               the ASCII character to be programmed. Made sense to someone.
        X          ST  -string terminator. ^[\  (ESC-\)
        X
        X   Function key addresses
        X      key number	offset	address (Ky1)
        X         6		11	17
        X         7		11	18
        X         8		11	19
        X         9		11	20
        X        10		11	21
        X        11		12	23
        X        12		12	24
        X        13		12	25
        X        14		12	26
        X   HELP 15		13	28
        X    DO  16		13	29
        X        17		14	31
        X        18		14	32
        X        19		14	33
        X        20		14	34
        X
        X  An example string that will program the HELP (F15) key to spit out "apropos" ;
        X  ^[P1;1|28/6170726f706f730^[\
        X   | | | |  \-------------/ |
        X   | | | |         |        - ST  (ESC-\)
        X   | | | |         - encoded text
        X   | | | -- key address
        X   | | - Pl
        X   | - Pc
        X   - DCS (ESC-P)
        X
        X   One simply prints the string (which will not be displayed) to the screen.
        X*/
SHAR_EOF
if test 1991 -ne "`wc -c < 'Notes'`"
then
        echo shar: error transmitting "'Notes'" '(should have been 1991 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'keydef.c'" '(5812 characters)'
if test -f 'keydef.c'
then
        echo shar: will not over-write existing file "'keydef.c'"
else
sed 's/^        X//' << \SHAR_EOF > 'keydef.c'
        X/*
        X * keydef() - easily / quickly redefine vt200, vt300 function keys
        X*/
        Xstatic char Keydef[] = "@(#)keydef.c	1.5	4/11/89";  /* posted to USENET */
        X#include <stdio.h>
        X#include <pwd.h>
        X   struct passwd *pw;
        X#include "keydef.h"
        X
        X/* string to program key      string to print to user  */
        X/*                    v          v                     */
        Xchar *Default[] = { "23/1B", "F11 is ESC",
        X                    "28/6170726f706f730a","HELP key is apropos",
        X                     NULL, NULL }; /* must be last in array */
        X/* Use the Default array for specifing local defaults that should be set */
        X
        Xvoid Getuser();
        Xint debug = 0;
        Xchar *ProgKey();
        X
        Xmain(argc, argv)
        X  int    argc;
        X  char **argv;
        X{
        X  int keynum;
        X  char fname[BUFSIZ], lfname[BUFSIZ], record[BUFSIZ];
        X  char *prog;
        X  char *p, **defaults = Default;
        X
        X if( 2 == 1 ) {
        X   /* The contents of this if() statement may not be changed   */
        X   printf(" (C) Copyright 1989 by Gordon P. Vickers, Sunnyvale, Ca.\n");
        X   printf("   { mips | pyramid | phillabs }!prls!gordon \n");
        X   printf("Distribution requiring payment in excess of reproduction\n");
        X   printf("cost requires authors written consent.\n");
        X   printf("Free distribution is encouraged if this notice remains intact\n");
        X/*     This program is offerred AS-IS, without warrenty of any kind.
        X           U S E   A T   Y O U R   O W N   R I S K
        X       I have nothing to gain from sharing this so I should have nothing
        X       to risk. 
        X*/  
        X }
        X
        X  strcat(fname,PROGNAME);
        X  argv++;     /* get past program name */
        X  while( *argv != NULL) {
        X     if (!IsDigit(*argv)) {
        X       if(!strcmp(*argv,"-d"))
        X         debug = 1;
        X       else
        X         strcat(fname, *argv);
        X     }
        X     else {
        X          Getuser(*argv);
        X          exit(0);
        X     }
        X   argv++;
        X  }
        X
        X  /* find user's home directory so we can find the correct keydef file */
        X  if( (pw = getpwuid(getuid())) == NULL) {
        X      fprintf(stderr,"Can't figure out where your home directory is.\n");
        X      exit(0);
        X  }
        X  sprintf(lfname,"%s/.%s",pw->pw_dir,fname); /* complete filename */
        X
        X  printf("Setting defaults:\n");
        X  while(*defaults != NULL) {  /* Must use two prints so pointer inc's OK */
        X  if(debug)
        X    printf("^[%s%s^[%c",PREFIX, *defaults++,BSLASH);
        X  else
        X    printf("%c%s%s%c%c",ESC,PREFIX, *defaults++,ESC,BSLASH);
        X  printf("\t%s\n", *defaults++);
        X  }
        X
        X  if( (freopen(lfname,"r",stdin)) == NULL) {
        X     perror(lfname);
        X     exit(0);
        X  }
        X 
        X  printf("Settings from %s%s\n",RCFILE,*argv);
        X
        X/* OK TO HERE */
        X  while ( (fgets(record,BUFSIZ,stdin)) != NULL ) {
        X    p = record;
        X    *(p + strlen(record) -1) = NULL; /* delete the newline,added in printf */
        X    if(*p == 'F' || *p == 'f')
        X      p++;              /* for compatibility with previous keydef versions */
        X    if(*p == '!') {     /* test for shell escape */
        X      p++;
        X      system(p);        /* the expensive way but isn't used often */
        X      continue;
        X    }
        X    if(!(keynum = GetKey(p)) )
        X        continue;
        X    prog = ProgKey(p,keynum);
        X    if(prog != NULL)
        X      printf("%s%s\n",prog,p); /* moved newline to here, personal preferance */
        X  }
        X} /* end of main */
        X
        Xvoid Getuser(s)
        X  char *s;
        X{
        X   int key;
        X   char *ip, record[BUFSIZ], input[BUFSIZ];
        X
        X   strcpy(record,s);
        X   while(!(key = GetKey(record)) ) { 
        X     if(record[0] == 'e' || record[0] == 'q')
        X        exit(0);
        X     printf("\n    Sorry, that's not a valid function key number\n",key);
        X     printf("Valid responses are:\n");
        X     printf("    6     7     8     9     10\n");
        X     printf("   11 (esc)     12 (bs)     13 (lf)\n");
        X     printf("   14    15 (help)   16 (do)\n");
        X     printf("   17    18    19    20\n");
        X     printf("OR type any of: exit     e    quit     q\n");
        X     printf("\nEnter function key number : ");
        X     fgets(record,BUFSIZ,stdin);
        X   }
        X   printf("New definition : ");
        X   fgets(input,BUFSIZ,stdin);
        X   ip = input;
        X   while(*ip++ != NULL)
        X     if(*ip == '\n')    /* strip newline from user input string */
        X       *ip = NULL;
        X   strcat(record,input);
        X   printf("%s\n",ProgKey(record,key));
        X   exit(0);
        X}
        X
        X/* IsDigit(s) - get function key number from string */
        XIsDigit(s)
        X  char *s;
        X{
        X  int digit = 0;
        X  if(*s <= '9' && *s >= '0') 
        X    sscanf(s,"%2d%*s",&digit);
        X return(digit);
        X}
        X
        X/* GetKey() */
        XGetKey(s)
        X char *s;
        X{
        X  int key;
        X
        X  key = IsDigit(s);
        X  switch (key) {
        X         case 6: case 7: case 8: case 9: case 10:
        X                 key += 11; break;
        X         case 11: case 12: case 13: case 14:
        X                 key += 12; break;
        X         case 15: case 16:
        X                 key += 13; break;
        X         case 17: case 18: case 19: case 20:
        X                 key += 14; break;
        X         default:
        X                 key = 0;
        X  }
        X  return(key);
        X} 
        X
        X/*** ProgKey() ****/
        Xchar *
        XProgKey(s,k)
        X  char *s;
        X  int k;
        X{
        X  char t[BUFSIZ], buf[4];
        X
        X  if(debug)
        X    sprintf(t,"^[%s%d/",PREFIX,k); /* make preamble */
        X  else
        X    sprintf(t,"%c%s%d/",ESC,PREFIX,k); /* make preamble */
        X
        X  if(*s >= '0' && *s <= '9') /* move past the key number */
        X     s++;
        X  if(*s >= '0' && *s <= '9') /* ...which may be two digits */
        X     s++;
        X  while( *s != NULL) {
        X     if(*s == '^'){ /* map a control charector */
        X        s++;
        X        sprintf(buf,"%02x", (int)(( *s - '@') > 0 ? *s - '@' : *s));
        X     }
        X     else if(*s == BSLASH){
        X        switch( *(s + 1) ) {
        X           case 'n' : sprintf(buf,"%02x",(int)'\n'); s++; break;
        X           case 'r' : sprintf(buf,"%02x",(int)'\r'); s++; break;
        X           case 't' : sprintf(buf,"%02x",(int)'\t'); s++; break;
        X           case BSLASH:sprintf(buf,"%02x",(int)'\\'); s++; break;
        X           case '^' :  sprintf(buf,"%02x",(int)'^'); s++; break;
        X           default: sprintf(buf,"%02x",(int)*s);
        X        }
        X     }
        X     else {
        X        sprintf(buf,"%02x",(int)*s);
        X     }
        X     strcat(t,buf);
        X     s++;
        X  } 
        X  if(debug)
        X    sprintf(buf,"^[\\");
        X  else
        X    sprintf(buf,"%c%c",ESC,BSLASH);
        X
        X strcat(t,buf);
        X return(t);
        X}
SHAR_EOF
if test 5812 -ne "`wc -c < 'keydef.c'`"
then
        echo shar: error transmitting "'keydef.c'" '(should have been 5812 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'keydef.h'" '(671 characters)'
if test -f 'keydef.h'
then
        echo shar: will not over-write existing file "'keydef.h'"
else
sed 's/^        X//' << \SHAR_EOF > 'keydef.h'
        X/* SCCSID @(#)keydef.h	1.5	4/11/89 */
        X#include <strings.h>    /* CHANGE to strings.h for BSD, string.h for SYS V */
        X
        X#define ESC '\033'     /* escape code */
        X#define BSLASH '\134'  /* back slash  */
        X#define NL     '\n'    /* newline     */
        X#define RET    '\r'    /* return      */
        X#define TAB    '\t'    /* tab         */
        X#define PREFIX "P1;1|" /* DEC refers to this as "Pc;Pl |"
        X                          see pg 29, VT220 Programmer Pocket Guide */
        X#define PROGNAME "keydef" /* argv[0][0] may be a full path name    */
        X#define RCFILE ".keydef"  /* every program has one these days, maybe */
        X                          /* what we need is a "dot" directory for them all */
SHAR_EOF
if test 671 -ne "`wc -c < 'keydef.h'`"
then
        echo shar: error transmitting "'keydef.h'" '(should have been 671 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(329 characters)'
if test -f 'Makefile'
then
        echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^        X//' << \SHAR_EOF > 'Makefile'
        X# sccs id:	@(#)Makefile	1.2	4/11/89
        X# 
        XPROG    = keydef
        XCFLAGS  = -O -s
        XHEADERS = $(PROG).h
        XSCR     = $(PROG).c
        XFILES   = README $(PROG).L sample Notes $(PROG).c $(PROG).h \
        X          Makefile 132col 80col
        X
        Xall:	$(PROG)
        X
        X$(PROG):	$(HEADERS) $(SCR)
        X	cc $(CFLAGS) $(SCR) -o $(PROG)
        X
        Xshar:	$(FILES)
        X	shar -a $(FILES) > $(PROG).shar
SHAR_EOF
if test 329 -ne "`wc -c < 'Makefile'`"
then
        echo shar: error transmitting "'Makefile'" '(should have been 329 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'132col'" '(94 characters)'
if test -f '132col'
then
        echo shar: will not over-write existing file "'132col'"
else
sed 's/^        X//' << \SHAR_EOF > '132col'
        X# SCCS ID "@(#)132col	1.4	4/11/89"
        Xstty dec
        Xset noglob; eval `tset -s -Q vt220w`
        Xunset noglob
SHAR_EOF
if test 94 -ne "`wc -c < '132col'`"
then
        echo shar: error transmitting "'132col'" '(should have been 94 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'80col'" '(93 characters)'
if test -f '80col'
then
        echo shar: will not over-write existing file "'80col'"
else
sed 's/^        X//' << \SHAR_EOF > '80col'
        X# SCCS ID "@(#)80col	1.4	4/11/89"
        Xstty dec
        Xset noglob; eval `tset -s -Q vt220n`
        Xunset noglob
SHAR_EOF
if test 93 -ne "`wc -c < '80col'`"
then
        echo shar: error transmitting "'80col'" '(should have been 93 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0