home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / SWAPDCP.LZH / swapdcp.c next >
C/C++ Source or Header  |  1992-06-13  |  12KB  |  460 lines

  1. /* SWAPDCP -- list and/or swap keys in a KEYBOARD.DCP file
  2.  * (C) 1992 by Ned Konz -- FREELY DISTRIBUTABLE AND USABLE
  3.  * 6/13/92 version
  4.  */
  5.  
  6. char *logo_strings[] =
  7. {
  8.     "SWAPDCP -- list and/or swap keys in a KEYBOARD.DCP file (6/13/92)",
  9.     "(C) 1992 Ned Konz -- FREELY DISTRIBUTABLE AND USABLE",
  10.     "",
  11.     "MAKE A COPY OF YOUR KEYBOARD.DCP FILE TO RUN THIS PROGRAM ON!!!",
  12.     "THIS WILL EDIT THE GIVEN FILE IN PLACE!!!",
  13.     "",
  14.     "BIX: nkonz, CI$: 76046,223",
  15.     "",
  16.     0
  17. };
  18.  
  19. char *usage_strings[] =
  20. {
  21.     "Usage: SWAPDCP [-l n] [-s k1 k2 [...]] [-h] filename.DCP",
  22.     "   -l n         sets listing level to n ( 0-3 )",
  23.     "                0: no listing output",
  24.     "                1: basic info, status output (default)",
  25.     "                2: level 1 plus table headers",
  26.     "                3: level 2 plus key entries",
  27.     "   -s k1 k2     swaps keys with scan codes k1 and k2",
  28.     "                (multiple -s arguments are processed in order)",
  29.     "   -h           prints extended help to standard output and quits",
  30.     "                (run as \"SWAPDCP -h | more\" or \"SWAPDCP -h >file\")",
  31.     0
  32. };
  33.  
  34. char *doc_strings[] =
  35. {
  36.     "For instance, to swap the control and caps-lock keys on your keyboard,",
  37.     "you might use (assuming OS/2 is on your drive C:):",
  38.     "",
  39.     "    COPY C:\\OS2\\KEYBOARD.DCP C:\\OS2\\MYKBD.DCP",
  40.     "    SWAPDCP -s 29 58 C:\\OS2\\MYKBD.DCP",
  41.     "",
  42.     "This swaps the key definitions in-place.",
  43.     "",
  44.     "You could then change the line in your CONFIG.SYS which goes something like:",
  45.     "    DEVINFO=KBD,US,C:\\OS2\\KEYBOARD.DCP",
  46.     "to:",
  47.     "    DEVINFO=KBD,US,C:\\OS2\\MYKBD.DCP",
  48.     "",
  49.     "The next time you start up, your keys will be changed.",
  50.     0
  51. };
  52.  
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <string.h>
  56. #include <ctype.h>
  57. #include "swapdcp.h"
  58.  
  59. /* Globals */
  60. FILE *infile = NULL;    /* input/output file handle */
  61. char *filename = NULL;    /* input/output filename */
  62.  
  63. int listing = LIST_BASIC;        /* listing level, 0-LIST_KEYS */
  64. int swapping = 0;        /* number of key pairs to swap */
  65. int swapped_keys[2][MAX_SWAPPED];    /* swapped key pairs */
  66.  
  67. void swap_keys( void *table, int num )
  68. {
  69.     int i;
  70.     KeyDef *keytable = table;
  71.     for ( i = 0; i < swapping; i++ )
  72.     {
  73.         int k1 = swapped_keys[0][i] - 1;    /* correct for index */
  74.         int k2 = swapped_keys[1][i] - 1;
  75.         if ( keytable[ k1 ].XlateOp & AccentFlags )
  76.         {
  77.             printf( "ERROR: can't swap accented key %d\n", k1 );
  78.             return;
  79.         }
  80.         if ( keytable[ k2 ].XlateOp & AccentFlags )
  81.         {
  82.             printf( "ERROR: can't swap accented key %d\n", k2 );
  83.             return;
  84.         }
  85.         if ( k1 < num && k2 < num )
  86.         {
  87.             KeyDef tmp = keytable[ k1 ];
  88.             keytable[ k1 ] = keytable[ k2 ];
  89.             keytable[ k2 ] = tmp;
  90.         }
  91.     }
  92. }
  93.  
  94. void print_shift( unsigned sf, char *prefix )
  95. {
  96.     if ( !sf )
  97.         return;
  98.     if ( prefix )
  99.     {
  100.         printf( "%s", prefix );
  101.     }
  102.     if ( sf & SF_RIGHTSHIFT ) printf( "RIGHTSHIFT " );
  103.     if ( sf & SF_LEFTSHIFT ) printf( "LEFTSHIFT " );
  104.     if ( sf & SF_CONTROL ) printf( "CONTROL " );
  105.     if ( sf & SF_ALT ) printf( "ALT " );
  106.     if ( sf & SF_SCROLLLOCK_ON ) printf( "SCROLLLOCK_ON " );
  107.     if ( sf & SF_NUMLOCK_ON ) printf( "NUMLOCK_ON " );
  108.     if ( sf & SF_CAPSLOCK_ON ) printf( "CAPSLOCK_ON " );
  109.     if ( sf & SF_INSERT_ON ) printf( "INSERT_ON " );
  110.     if ( sf & SF_LEFTCONTROL ) printf( "LEFTCONTROL " );
  111.     if ( sf & SF_LEFTALT ) printf( "LEFTALT " );
  112.     if ( sf & SF_RIGHTCONTROL ) printf( "RIGHTCONTROL " );
  113.     if ( sf & SF_RIGHTALT ) printf( "RIGHTALT " );
  114.     if ( sf & SF_SCROLLLOCK ) printf( "SCROLLLOCK " );
  115.     if ( sf & SF_NUMLOCK ) printf( "NUMLOCK " );
  116.     if ( sf & SF_CAPSLOCK ) printf( "CAPSLOCK " );
  117.     if ( sf & SF_SYSREQ ) printf( "SYSREQ " );
  118. }
  119.  
  120. void pkey( KeyDef *key, char *name )
  121. {
  122.     BYTE *p = &key->Char1;
  123.     printf( "%s (", name);
  124.     while (p <= &key->Char5)
  125.     {
  126.         if ( isprint( *p ) )
  127.             printf("'%c'", (unsigned)*p);
  128.         else
  129.             printf("%#x", (unsigned)*p);
  130.  
  131.         if ( p == &key->Char5 )
  132.             printf(")");
  133.         else
  134.             printf(",");
  135.         p++;
  136.     }
  137. }
  138.  
  139. void print_keys( void *table, int num )
  140. {
  141.     KeyDef *key = table;
  142.     int i;
  143.  
  144.     for ( i=0; i<num; i++ )
  145.     {
  146.         unsigned keytype = ( unsigned )( key[i].XlateOp & KeyType );
  147.         unsigned keyflags = ( unsigned )( key[i].XlateOp & AccentFlags );
  148.  
  149.         if ( keytype )
  150.         {
  151.             printf( "%3d (%#02x): ", i+1, i+1 );
  152.             switch ( keytype )
  153.             {
  154.                 case 0x01:        /* AlphaKey */
  155.                     pkey( key+i, "AlphaKey" );
  156.                 break;
  157.                 case 0x02:        /* SpecKey */
  158.                     pkey( key+i, "SpecKey" );
  159.                 break;
  160.                 case 0x03:        /* SpecKeyC */
  161.                     pkey( key+i, "SpecKeyC" );
  162.                 break;
  163.                 case 0x04:        /* SpecKeyA */
  164.                     pkey( key+i, "SpecKeyA" );
  165.                 break;
  166.                 case 0x05:        /* SpecKeyCA */
  167.                     pkey( key+i, "SpecKeyCA" );
  168.                 break;
  169.                 case 0x06:        /* FuncKey */
  170.                     pkey( key+i, "FuncKey" );
  171.                 break;
  172.                 case 0x07:        /* PadKey */
  173.                     pkey( key+i, "PadKey" );
  174.                 break;
  175.                 case 0x08:        /* SpecCtlKey */
  176.                     pkey( key+i, "SpecCtlKey" );
  177.                 break;
  178.                 case 0x09:        /* PrtSc */
  179.                     pkey( key+i, "PrtSc" );
  180.                 break;
  181.                 case 0x0a:        /* SysReq */
  182.                     pkey( key+i, "SysReq" );
  183.                 break;
  184.                 case 0x0b:        /* AccentKey */
  185.                     pkey( key+i, "AccentKey" );
  186.                 break;
  187.                 case 0x0c:        /* ShiftKey */
  188.                     pkey( key+i, "ShiftKey" );
  189.                     print_shift( (unsigned)key[i].Char1, " " );
  190.                     print_shift( (unsigned)key[i].Char2 << 8, "/ " );
  191.                     print_shift( (unsigned)key[i].Char3 << 8,  "/ " );
  192.                 break;
  193.                 case 0x0d:        /* ToggleKey */
  194.                     pkey( key+i, "ToggleKey" );
  195.                 break;
  196.                 case 0x0e:        /* AltKey */
  197.                     pkey( key+i, "AltKey" );
  198.                 break;
  199.                 case 0x0f:        /* NumLock */
  200.                     pkey( key+i, "NumLock" );
  201.                 break;
  202.                 case 0x10:        /* CapsLock */
  203.                     pkey( key+i, "CapsLock" );
  204.                 break;
  205.                 case 0x11:        /* ScrollLock */
  206.                     pkey( key+i, "ScrollLock" );
  207.                 break;
  208.                 case 0x12:        /* XShiftKey */
  209.                     pkey( key+i, "XShiftKey" );
  210.                 break;
  211.                 case 0x13:        /* XToggleKey */
  212.                     pkey( key+i, "XToggleKey" );
  213.                 break;
  214.                 case 0x14:        /* SpecKeyCS */
  215.                     pkey( key+i, "SpecKeyCS" );
  216.                 break;
  217.                 case 0x15:        /* SpecKeyAS */
  218.                     pkey( key+i, "SpecKeyAS" );
  219.                 break;
  220.                 case 0x1a:        /* ExtExtKey */
  221.                     pkey( key+i, "ExtExtKey" );
  222.                 break;
  223.                 default:        /* reserved */
  224.                     printf( "type %#x", keytype );
  225.                     pkey( key+i, "" );
  226.                 break;
  227.             }    /* switch keytype */
  228.  
  229.             if ( keyflags )
  230.                 printf( " AccFlags:%#x\n", keyflags );
  231.             else
  232.                 printf( "\n" );
  233.         }    /* if keytype */
  234.     }    /* for i */
  235. }
  236.  
  237. #define PFLAG( flag ) printf( " " #flag ":%d", header->XTableFlags1.##flag )
  238.  
  239. void do_entry( IndexEntry *entry )
  240. {
  241.     long table_base;
  242.     XHeader *header = calloc( sizeof( XHeader ), 1 );
  243.     void *keys = NULL;
  244.  
  245.     fseek( infile, ( long )entry->HeaderLocation, SEEK_SET );
  246.     if ( fread( header, sizeof( XHeader ), 1, infile ) != 1 ) 
  247.     {
  248.         fprintf( stderr, "ERROR: can't read table header\n" );
  249.         return;
  250.     }
  251.     table_base = ftell( infile );
  252.  
  253.     if ( listing >= LIST_KEYS  || swapping )
  254.     {
  255.         keys = calloc( header->XtableLen, 1 );
  256.         if ( fread( keys, header->XtableLen, 1, infile ) != 1 )
  257.         {
  258.             fprintf( stderr, "ERROR: can't read key table\n" );
  259.             return;
  260.         }
  261.     }
  262.  
  263.     if ( listing >= LIST_HEADERS )
  264.     {
  265.         printf( "ID:%d", header->XTableID );
  266.         PFLAG( ShiftAlt );
  267.         PFLAG( AltGrafL );
  268.         PFLAG( AltGrafR );
  269.         PFLAG( ShiftLock );
  270.         PFLAG( DefaultTable );
  271.         printf( "\n" );
  272.         PFLAG( ShiftToggle );
  273.         PFLAG( AccentPass );
  274.         PFLAG( CapsShift );
  275.         PFLAG( MachDep );
  276.         printf( "\nKbdType:%d, KbdSubType:%d, XtableLen:%#x, EntryCount:%d,\n",
  277.             header->KbdType, header->KbdSubType, header->XtableLen,
  278.             header->EntryCount );
  279.         printf( "Country:\"%2.2s %4.4s\", TableTypeID:%d\n", header->Country,
  280.             header->SubCountryID, header->TableTypeID );
  281.         if ( listing >= LIST_KEYS )
  282.             print_keys( keys, header->EntryCount );
  283.     }
  284.  
  285.     if ( swapping )
  286.     {
  287.         swap_keys( keys, header->EntryCount );
  288.         fseek( infile, table_base, SEEK_SET );
  289.         if ( fwrite( keys, header->XtableLen, 1, infile ) != 1 )
  290.         {
  291.             fprintf( stderr, "ERROR: can't write key table\n" );
  292.         }
  293.     }
  294.  
  295.     if ( header ) free( header );
  296.     if ( keys )   free( keys );
  297. }
  298.  
  299. void print_index( ULONG index_location )
  300. {
  301.     WORD number_of_entries = 0;
  302.     WORD i;
  303.     IndexEntry *entry;
  304.     int nr;
  305.  
  306.     fseek( infile, ( long )index_location, SEEK_SET );
  307.     fread( &number_of_entries, sizeof( number_of_entries ), 1, infile );
  308.  
  309.     if ( listing >= LIST_BASIC )
  310.     {
  311.         printf( "%d keyboard tables in file\n", number_of_entries );
  312.     }
  313.     entry = calloc( number_of_entries, sizeof( IndexEntry ) );
  314.  
  315.     if ( ( nr = fread( entry, sizeof(IndexEntry), number_of_entries, infile ) )
  316.             != number_of_entries )
  317.     {
  318.         fprintf( stderr, "ERROR: only read %d of %d index entries\n",
  319.             nr, number_of_entries );
  320.         return;
  321.     }
  322.  
  323.     for ( i = 0; i < number_of_entries; i++ )
  324.     {
  325.         if ( entry[i].HeaderLocation )
  326.         {
  327.             if ( listing >= LIST_HEADERS )
  328.             {
  329.                 printf( "======== table %d =========\n", i );
  330.                 printf( "%2.2s %4.4s ID: %d table loc: %#lx ( %04x %04x %04x )\n",
  331.                     entry[i].Country,
  332.                     entry[i].SubCountryID,
  333.                     ( unsigned )entry[i].XTableID,
  334.                     ( unsigned long )entry[i].HeaderLocation,
  335.                     ( unsigned )entry[i].word1,
  336.                     ( unsigned )entry[i].word2,
  337.                     ( unsigned )entry[i].word3 );
  338.             }
  339.             do_entry( entry+i );
  340.         }
  341.     }
  342.     free( entry );
  343. }
  344.  
  345. /* prints usage message to given output */
  346. void usage( char **strings, FILE *out )
  347. {
  348.     char **s;
  349.     for ( s=strings; *s; s++ )
  350.     {
  351.         fprintf( out, "%s\n", *s );
  352.     }
  353. }
  354.  
  355. int main( int argc, char *argv[] )
  356. {
  357.     ULONG index_location = 0UL;
  358.  
  359.     for ( --argc, ++argv; argc > 0; argc--, argv++ )
  360.     {
  361.         if ( !stricmp( *argv, "-h" ) )
  362.         {
  363.             usage( logo_strings, stdout );
  364.             usage( usage_strings, stdout );
  365.             printf( "\n" );
  366.             usage( doc_strings, stdout );
  367.             return 0;
  368.         }
  369.         else if ( !stricmp( *argv, "-l" ) )
  370.         {
  371.             if ( argc >= 2 )
  372.             {
  373.                 listing = atoi( *++argv );
  374.                 --argc;
  375.             }
  376.             else
  377.             {
  378.                 fprintf( stderr, "ERROR: missing listing level\n" );
  379.                 usage( logo_strings, stderr );
  380.                 usage( usage_strings, stderr );
  381.                 return 1;
  382.             }
  383.         }
  384.         else if ( !stricmp( *argv, "-s" ) )
  385.         {
  386.             if ( argc >= 3 )
  387.             {
  388.                 if ( swapping < MAX_SWAPPED )
  389.                 {
  390.                     int key1 = atoi( *++argv );
  391.                     int key2 = atoi( *++argv );
  392.                     argc -= 2;
  393.                     swapped_keys[0][ swapping ] = key1;
  394.                     swapped_keys[1][ swapping ] = key2;
  395.                     swapping++;
  396.                 }
  397.                 else
  398.                 {
  399.                     fprintf( stderr, "ERROR: too many swap pairs ( maximum %d )\n",
  400.                         MAX_SWAPPED );
  401.                     usage( logo_strings, stderr );
  402.                     usage( usage_strings, stderr );
  403.                     return 1;
  404.                 }
  405.             }
  406.             else
  407.             {
  408.                 fprintf( stderr, "ERROR: need two key codes after -s\n" );
  409.                 usage( logo_strings, stderr );
  410.                 usage( usage_strings, stderr );
  411.                 return 1;
  412.             }
  413.         }
  414.         else if ( **argv == '-' )
  415.         {
  416.             fprintf( stderr, "ERROR: unrecognized option \"%s\"\n", *argv );
  417.             usage( logo_strings, stderr );
  418.             usage( usage_strings, stderr );
  419.             return 1;
  420.         }
  421.         else
  422.         {
  423.             filename = *argv;
  424.         }
  425.     }
  426.  
  427.     if ( filename == NULL )
  428.     {
  429.         fprintf( stderr, "ERROR: missing filename\n" );
  430.         usage( logo_strings, stderr );
  431.         usage( usage_strings, stderr );
  432.         return 1;
  433.     }
  434.  
  435.     if ( listing >= LIST_BASIC )
  436.     {
  437.         usage( logo_strings, stdout );
  438.     }
  439.  
  440.     if ( (infile = fopen( filename, "r+b" ) ) == NULL )
  441.     {
  442.         fprintf( stderr, "ERROR: can't open file \"%s\" for read/write\n",
  443.             filename );
  444.         return 2;
  445.     }
  446.  
  447.     /* read location of index */
  448.     fread( &index_location, sizeof( index_location ), 1, infile );
  449.  
  450.     if ( listing >= LIST_HEADERS )
  451.     {
  452.         printf( "table index at %#lx\n", ( long )index_location );
  453.     }
  454.     print_index( index_location );
  455.  
  456.     fclose( infile );
  457.     return 0;
  458. }
  459.  
  460.