home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Washington_1988 / DevCon88.1 / AmigaTechniques / keymap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  14.1 KB  |  521 lines

  1. /*
  2.   Copyright (c) 1988 Commodore-Amiga, Inc.
  3.  
  4.   Executables based on this information may be used in software
  5.   for Commodore Amiga computers.  All other rights reserved.
  6.  
  7.   This information is provided "as is"; no warranties are made.
  8.   All use is at your own risk, and no liability or responsibility is assumed.
  9. */
  10.  
  11. #include    "exec/types.h"
  12. #include    "exec/memory.h"
  13. #include    "devices/keymap.h"
  14. #include    "devices/console.h"
  15. #include    "libraries/dosextens.h"
  16.  
  17. #ifdef    MANX
  18. #include    "functions.h"
  19. #endif
  20.  
  21. ULONG *AllocMem();
  22. struct Task *FindTask();
  23.  
  24. struct KeyMapResource *OpenResource();
  25. struct KeyMapNode *FindName();
  26.  
  27. struct KeyMap *
  28. FindKeyMap(name)
  29. char *name;
  30. {
  31.     struct KeyMapResource *kmr;
  32.     struct KeyMapNode *kmn;
  33.  
  34.     kmr = (struct KeyMapResource *) OpenResource("keymap.resource");
  35.     if (kmr == NULL) return(NULL);
  36.     kmn = (struct KeyMapNode *) FindName(&kmr->kr_List, name);
  37.     return(&kmn->kn_KeyMap);
  38. }
  39.  
  40. int QualifierOnesCount[] = {
  41.     /* number of bits set in a nibble */
  42.     0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
  43. };
  44. int QualifierExtraBytes[] = {
  45.     /* number of extra bytes associated with non-special qualifier patterns */
  46.     0, 0, 0, 0, 0, 0, 0, 0,    /* the last is the special VANILLA case */
  47.     0, 0, 0, 8, 0, 8, 8, 16
  48. };
  49.  
  50. int DeadFactor;        /* to determine size of lookup tables at end */
  51. int DoubleDeadFactor;    /* (only used for double dead keys) */
  52.  
  53.  
  54. MaxDeadIndex(type, entry)
  55. UBYTE type;
  56. UBYTE *entry;    /* if it needs to be looked at, it's a pointer */
  57. {
  58.     int count;
  59.     int i;
  60.  
  61.     if ((type & KCF_DEAD) && (!(type & KCF_NOP))) {
  62.     /* dead or deadable */
  63.     /* there are 2 bytes for each qualifier combination at *entry */
  64.     count = 1<<(QualifierOnesCount[type & 0xf]+1);
  65.     for (i = 0; i < count; i+=2) {
  66.         if (entry[i] & DPF_DEAD) {
  67.         /* see if this index is a maximum */
  68.         if (DeadFactor < (entry[i+1] & DP_2DINDEXMASK))
  69.             DeadFactor = entry[i+1] & DP_2DINDEXMASK;
  70.         if ((entry[i+1] >> DP_2DFACSHIFT) &&
  71.             /* this index participates in double dead keys */
  72.             (DoubleDeadFactor < (entry[i+1] & DP_2DINDEXMASK)))
  73.             /* this participant in double dead keys is a maximum */
  74.             DoubleDeadFactor = entry[i+1] & DP_2DINDEXMASK;
  75.         }
  76.     }
  77.     }
  78. }
  79.  
  80.  
  81. int
  82. SizeType(type, entry)
  83. UBYTE type;
  84. UBYTE *entry;    /* if it needs to be looked at, it's a pointer */
  85. {
  86.     int count, size, subtype;
  87.     int i, j;
  88.  
  89.     if (type & KCF_NOP) {
  90.     /* NOP */
  91.     return(0);
  92.     }
  93.  
  94.     if (type & KCF_DEAD) {
  95.     /* dead or deadable */
  96.     /* there are 2 bytes for each qualifier combination at *entry */
  97.     count = 1<<(QualifierOnesCount[type & 0xf]+1);
  98.     /* add the deadHead and data bytes for each of the deads */
  99.     size = count;
  100.     for (i = 0; i < count; i+=2) {
  101.         /* find any more interesting references */
  102.         subtype = entry[i];
  103.         if (subtype & DPF_DEAD) {
  104.         continue;
  105.         }
  106.         if (subtype & DPF_MOD) {
  107.         /* one byte for every dead combination */
  108.         size += DeadFactor;
  109.         continue;
  110.         }
  111.     }
  112.     return(size);
  113.     }
  114.  
  115.     if (type & KCF_STRING) {
  116.     /* string */
  117.     /* there are 2 bytes for each qualifier combination at *entry */
  118.     count = 1<<(QualifierOnesCount[type & 0xf]+1);
  119.     /* add the length and offset bytes for each of the strings */
  120.     size = count;
  121.     for (i = 0; i < count; i+=2) {
  122.         /* add this string's length */
  123.         size += entry[i];
  124.     }
  125.     return(size);
  126.     }
  127.  
  128.     /* number of extra bytes needed to index all the qualifiers set */
  129.     return(QualifierExtraBytes[type & 0xf]);
  130. }
  131.  
  132. /* SizeKeyMap does a KeyMap, not a KeyMapNode */
  133. int
  134. SizeKeyMap(km, newLo, newHi)
  135. struct KeyMap *km;
  136. UBYTE *newLo, *newHi;
  137. {
  138.     UBYTE type;
  139.     int size;
  140.     int i;
  141.  
  142.     /*
  143.      * fixed byte size associated with 
  144.      *   Keymap structure itself
  145.      *     (8 pointers)             32
  146.      *   Lo entries for 64 codes
  147.      *     km_LoKeyMapTypes         64
  148.      *     km_LoKeyMap            256
  149.      *     km_LoCapsable          8
  150.      *     km_LoRepeatable          8
  151.      *   Hi entries for 56 codes
  152.      *     km_HiKeyMapTypes         56
  153.      *     km_HiKeyMap            224
  154.      *     km_HiCapsable          7
  155.      *     km_HiRepeatable          7
  156.      *                    ---
  157.      * total                662
  158.      */
  159.     size = 662;
  160.  
  161.     /* first need to find the number of dead keys */
  162.     DeadFactor = DoubleDeadFactor = 0;
  163.     for (i = 0; i < 64; i++) {
  164.     MaxDeadIndex(km->km_LoKeyMapTypes[i], km->km_LoKeyMap[i]);
  165.     }
  166.     for (i = 0; i < 56; i++) {
  167.     MaxDeadIndex(km->km_HiKeyMapTypes[i], km->km_HiKeyMap[i]);
  168.     }
  169.     if (DeadFactor) DeadFactor++;
  170.     if (DoubleDeadFactor) DeadFactor *= DoubleDeadFactor;
  171.  
  172.     /* now accumulate all applicable keymap trails */
  173.     for (i = 0; i < 64; i++) {
  174.     if (!(newLo[i/8] & (1<<(i&7))))
  175.         size += SizeType(km->km_LoKeyMapTypes[i], km->km_LoKeyMap[i]);
  176.     }
  177.     for (i = 0; i < 56; i++) {
  178.     if (!(newHi[i/8] & (1<<(i&7))))
  179.         size += SizeType(km->km_HiKeyMapTypes[i], km->km_HiKeyMap[i]);
  180.     }
  181.  
  182.     return(size);
  183. }
  184.  
  185. UBYTE *NextNewMapEntry;
  186.  
  187. CopyEntry(type, oentry, nentry)
  188. UBYTE type;
  189. UBYTE *oentry;
  190. UBYTE **nentry;
  191. {
  192.     UBYTE *suboentry, *subnentry;
  193.     int count, length, subtype;
  194.     int i, j, k;
  195.  
  196.     if (type & KCF_NOP) {
  197.     /* NOP */
  198.     return;
  199.     }
  200.  
  201.     if (type & KCF_DEAD) {
  202.     /* dead or deadable */
  203.     /* there are 2 bytes for each qualifier combination at *entry */
  204.     count = 1<<(QualifierOnesCount[type & 0xf]+1);
  205.     *nentry = NextNewMapEntry;
  206.     NextNewMapEntry += count;
  207.     /* initialize the deadHead and data bytes for each of the deads */
  208.     for (i = 0; i < count; i+=2) {
  209.         subtype = oentry[i];
  210.         (*nentry)[i] = subtype;
  211.         (*nentry)[i+1] = oentry[i+1];    /* default */
  212.  
  213.         /* find any more interesting references */
  214.         if (subtype & DPF_MOD) {
  215.         (*nentry)[i+1] = NextNewMapEntry - *nentry;
  216.         /* one byte for every dead combination */
  217.         suboentry = &oentry[oentry[i+1]];
  218.         for (j = 0; j < DeadFactor; j++) {
  219.             *NextNewMapEntry++ = suboentry[j];
  220.         }
  221.         }
  222.     }
  223.     return;
  224.     }
  225.  
  226.     if (type & KCF_STRING) {
  227.     /* string */
  228.     /* there are 2 bytes for each qualifier combination at *entry */
  229.     count = 1<<(QualifierOnesCount[type & 0xf]+1);
  230.     *nentry = NextNewMapEntry;
  231.     NextNewMapEntry += count;
  232.     /* initialize the length and offset bytes for each of the strings */
  233.     for (i = 0; i < count; i+=2) {
  234.         /* clone this string's length */
  235.         length = oentry[i];
  236.         (*nentry)[i] = length;
  237.  
  238.         /* clone this string's data */
  239.         (*nentry)[i+1] = NextNewMapEntry - *nentry;
  240.         for (j = 0; j < length; j++) {
  241.         *NextNewMapEntry++ = oentry[oentry[i+1]+j];
  242.         }
  243.     }
  244.     return;
  245.     }
  246.  
  247.     /* check if all the qualified bytes fit in the entry longword */
  248.     count = QualifierExtraBytes[type & 0xf];
  249.     if (count > 0) {
  250.     /* clone a new array for all the qualified bytes */
  251.     *nentry = NextNewMapEntry;
  252.     for (i = 0; i < count; i++) {
  253.         *NextNewMapEntry++ = oentry[i];
  254.     }
  255.     }
  256. }
  257.  
  258.  
  259. struct KeyMap *
  260. NewKeyMap(okm, newLo, newHi)
  261. struct KeyMap *okm;
  262. UBYTE *newLo, *newHi;
  263. {
  264.     ULONG *memChunk;
  265.     struct KeyMap *nkm;
  266.     int size;
  267.     int i;
  268.  
  269.     size = SizeKeyMap(okm, newLo, newHi);
  270.  
  271.     /* NewKeyMap has a longword header describing the size */
  272.     memChunk = (ULONG *) AllocMem(size+4, MEMF_PUBLIC);
  273.     if (memChunk == NULL)
  274.     return(NULL);
  275.     *memChunk++ = size;
  276.     nkm = (struct KeyMap *) memChunk;
  277.  
  278.     /* parcel out space for fixed size tables in allocated memory */
  279.     nkm->km_LoKeyMapTypes = ((UBYTE *) nkm) + sizeof(struct KeyMap);
  280.     nkm->km_LoKeyMap = (ULONG *) &nkm->km_LoKeyMapTypes[64];
  281.     nkm->km_LoCapsable = (UBYTE *) &nkm->km_LoKeyMap[64];
  282.     nkm->km_LoRepeatable = &nkm->km_LoCapsable[8];
  283.     nkm->km_HiKeyMapTypes = &nkm->km_LoRepeatable[8];
  284.     nkm->km_HiKeyMap = (ULONG *) &nkm->km_HiKeyMapTypes[56];
  285.     nkm->km_HiCapsable = (UBYTE *) &nkm->km_HiKeyMap[56];
  286.     nkm->km_HiRepeatable = &nkm->km_HiCapsable[7];
  287.     NextNewMapEntry = &nkm->km_HiRepeatable[7];
  288.  
  289.     /* copy the fixed size keymap data to the new keymap copy */
  290.     for (i = 0; i < 64; i++) {
  291.     nkm->km_LoKeyMapTypes[i] = okm->km_LoKeyMapTypes[i];
  292.     nkm->km_LoKeyMap[i] = okm->km_LoKeyMap[i];
  293.     }
  294.     for (i = 0; i < 8; i++) {
  295.     nkm->km_LoCapsable[i] = okm->km_LoCapsable[i];
  296.     nkm->km_LoRepeatable[i] = okm->km_LoRepeatable[i];
  297.     }
  298.     for (i = 0; i < 56; i++) {
  299.     nkm->km_HiKeyMapTypes[i] = okm->km_HiKeyMapTypes[i];
  300.     nkm->km_HiKeyMap[i] = okm->km_HiKeyMap[i];
  301.     }
  302.     for (i = 0; i < 7; i++) {
  303.     nkm->km_HiCapsable[i] = okm->km_HiCapsable[i];
  304.     nkm->km_HiRepeatable[i] = okm->km_HiRepeatable[i];
  305.     }
  306.  
  307.     /* now follow all applicable keymap trails */
  308.     for (i = 0; i < 64; i++) {
  309.     if (!(newLo[i/8] & (1<<(i&7))))
  310.         CopyEntry(okm->km_LoKeyMapTypes[i], okm->km_LoKeyMap[i],
  311.             &nkm->km_LoKeyMap[i]);
  312.     }
  313.     for (i = 0; i < 56; i++) {
  314.     if (!(newHi[i/8] & (1<<(i&7))))
  315.         CopyEntry(okm->km_HiKeyMapTypes[i], okm->km_HiKeyMap[i],
  316.             &nkm->km_HiKeyMap[i]);
  317.     }
  318.     return(nkm);
  319. }
  320.  
  321. DisposeKeyMap(km)
  322. ULONG *km;
  323. {
  324.     km--;
  325.     FreeMem(km, (*km)+4);
  326. }
  327.  
  328. struct MsgPort IORP = {
  329.     {0, 0, NT_MSGPORT, 0, 0}, 0, SIGF_SINGLE, 0, { 0, 0, 0, 0, 0 }
  330. };
  331.  
  332. struct IOStdReq IOR = {
  333.     { {0, 0, NT_MESSAGE, 0, 0},    /* Message Succ, Pred, Type, Pri, Name */
  334.     &IORP, 0 },            /* Message ReplyPort, Length */
  335.     0, 0, CMD_READ, 0, 0,    /* IO Device, Unit, Command, Flags, Error */
  336.     0, 0, 0, 0            /* IO Actual, Length, Data, Offset */
  337. };
  338.  
  339. /*
  340.  *  indicate replacement of function keys (0x50-0x59) will occur
  341.  */
  342. UBYTE NoNew[] = {
  343.     0, 0, 0, 0, 0, 0, 0, 0
  344. };
  345. UBYTE NewHi[] = {
  346.     0, 0, 0xff, 0x03, 0, 0, 0, 0
  347. };
  348. UBYTE NewFncTypes[] = {
  349.     KC_NOQUAL, KCF_SHIFT, KCF_SHIFT+KCF_ALT, KC_VANILLA,
  350.     KCF_SHIFT+KCF_ALT+KCF_CONTROL+KCF_DOWNUP,
  351.     KCF_STRING, KCF_SHIFT+KCF_STRING,
  352.     KCF_SHIFT+KCF_ALT+KCF_CONTROL+KCF_DOWNUP+KCF_STRING,
  353.     KCF_SHIFT+KCF_ALT+KCF_DEAD, KCF_STRING
  354. };
  355. UBYTE NewFnc1_4[] = {
  356.     0, 0, 0, '1',
  357.     0, 0, 0xb2, '2',
  358.     'F', 'f', 0xb3, '3',
  359.     'm', '!', 'i', 'h' 
  360. };
  361. UWORD NewFncOff5_10[] = {
  362.     /* offsets into the NewFncData area */
  363.     0, 16, 20, 108, 204, 224
  364. };
  365. BYTE NewFncData[] = {
  366.     /* 0 :f5 */
  367.     'a','b','c','d','e','f','g','h','A','B','C','D','E','F','G','H',
  368.     /* 16:f6 */
  369.     2,2,'f','6',
  370.     /* 20:f7 */
  371.     2,4,2,6,'f','7','F','7',
  372.     /*108:f8 */
  373.     /* more than 128 bytes of data, so some data must be a negative */
  374.     /* offset from the length/offset pairs */
  375.     'D','o','w','n',
  376.     'S','h','i','f','t','D','o','w','n',
  377.     'A','l','t','D','o','w','n',
  378.     'S','h','i','f','t','A','l','t','D','o','w','n',
  379.     'C','t','r','l','D','o','w','n',
  380.     'C','t','r','l','S','h','i','f','t','D','o','w','n',
  381.     'C','t','r','l','A','l','t','D','o','w','n',
  382.     'C','t','r','l','S','h','i','f','t','A','l','t','D','o','w','n',
  383.     /* length/offset pairs for strings for f8 */
  384.     4,-80, 9,-76, 7,-67, 12,-60, 8,-48, 13,-40, 11,-27, 16,-16,
  385.     2,32, 7,34, 5,41, 10,46, 6,56, 11,62, 9,73, 14,82,
  386.     /* more data for strings for f8 */
  387.     'U','p',
  388.     'S','h','i','f','t','U','p',
  389.     'A','l','t','U','p',
  390.     'S','h','i','f','t','A','l','t','U','p',
  391.     'C','t','r','l','U','p',
  392.     'C','t','r','l','S','h','i','f','t','U','p',
  393.     'C','t','r','l','A','l','t','U','p',
  394.     'C','t','r','l','S','h','i','f','t','A','l','t','U','p',
  395.     /*204:f9 */
  396.     DPF_MOD,8, DPF_MOD,14, DPF_DEAD, 2, 0, '@',
  397.     'a',0xe1,0xe0,0xe2,0xe3,0xe4,
  398.     'A',0xc1,0xc0,0xc2,0xc3,0xc4,
  399.     /*224:f10*/
  400.     4, 2, 0x18, 0x0c, 0x08, 0x0d
  401. };
  402. UBYTE NewFncCapsable[] = {
  403.     0x04, 0x00
  404. };
  405. UBYTE NewFncRepeatable[] = {
  406.     0x00, 0x00
  407. };
  408.  
  409. main(argc, argv)
  410. int argc;
  411. char *argv[];
  412. {
  413.     struct KeyMap *ukm;        /* usa keymap */
  414.     struct KeyMap ckm;        /* console keymap */
  415.     struct KeyMap *nkm;        /* new keymap */
  416.     int uSize, cSize;
  417.     struct MsgPort *con;
  418.     struct StandardPacket *packet;
  419.     struct InfoData *id;
  420.     BYTE *f;
  421.     int i;
  422.  
  423.     ukm = FindKeyMap("usa");
  424.     if (ukm == NULL) {
  425.     printf("usa map not found\n");
  426.     exit(20);
  427.     }
  428.     uSize = SizeKeyMap(ukm, NoNew, NoNew);
  429.     printf("usa map size %ld (0x%lx)\n", uSize, uSize);
  430.  
  431.     NewList(&IORP.mp_MsgList);
  432.     IORP.mp_SigTask = (struct Task *) FindTask((char *) NULL);
  433.     con = (struct MsgPort *)
  434.         ((struct Process *) IORP.mp_SigTask) -> pr_ConsoleTask;
  435.     if (con != NULL) {
  436.         packet = (struct StandardPacket *)
  437.             AllocMem(sizeof(*packet), MEMF_CLEAR);
  438.         if (packet != NULL) {
  439.         id = (struct InfoData *) AllocMem(sizeof(*id), MEMF_CLEAR);
  440.         if (id != NULL) {
  441.             /* this is the console handlers packet port */
  442.             packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
  443.             packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  444.             packet->sp_Pkt.dp_Port = &IORP;
  445.             packet->sp_Pkt.dp_Type = ACTION_DISK_INFO;
  446.             packet->sp_Pkt.dp_Arg1 = ((ULONG) id) >> 2;
  447.             PutMsg(con, packet);
  448.             WaitPort(&IORP);
  449.             if (id->id_InUse) {
  450.             /* clone iorequest and get keymap */
  451.             IOR.io_Unit =
  452.                 ((struct IOStdReq *) id->id_InUse)->io_Unit;
  453.             IOR.io_Device =
  454.                 ((struct IOStdReq *) id->id_InUse)->io_Device;
  455.             IOR.io_Command = CD_ASKKEYMAP;
  456.             IOR.io_Data = (APTR) &ckm;
  457.             IOR.io_Length = sizeof(struct KeyMap);
  458.             DoIO(&IOR);
  459.  
  460.             cSize = SizeKeyMap(&ckm, NoNew, NoNew);
  461.             printf("current map size %ld (0x%lx)\n", cSize, cSize);
  462.  
  463.             /* default: go back to the usa keymap */
  464.             nkm = ukm;
  465.             /*
  466.              *  if cSize == uSize, assume this is a usa keymap
  467.              *  else assume this has already been modified
  468.              *  (crude, but this is demo code)
  469.              */
  470.             if (cSize == uSize) {
  471.                 f = (BYTE *)
  472.                     AllocMem(sizeof(NewFncData), MEMF_PUBLIC);
  473.                 if (f) {
  474.                 /* make a new keymap */
  475.                 nkm = NewKeyMap(ukm, NoNew, NewHi);
  476.  
  477.                 /* replace the function key descriptions */
  478.                 for (i = 0; i < 10; i++)
  479.                     nkm->km_HiKeyMapTypes[i+0x10] =
  480.                         NewFncTypes[i];
  481.                 for (i = 0; i < 4; i++)
  482.                     nkm->km_HiKeyMap[i+0x10] =
  483.                     ((ULONG *) NewFnc1_4)[i];
  484.                 for (i = 0; i < 6; i++)
  485.                     nkm->km_HiKeyMap[i+0x14] =
  486.                         (ULONG) (f + NewFncOff5_10[i]);
  487.                 for (i = 0; i < 2; i++) {
  488.                     nkm->km_HiCapsable[i+2] = ((~NewHi[i+2]) &
  489.                         nkm->km_HiCapsable[i+2]) |
  490.                         NewFncCapsable[i];
  491.                     nkm->km_HiRepeatable[i+2] = ((~NewHi[i+2]) &
  492.                         nkm->km_HiRepeatable[i+2]) |
  493.                         NewFncRepeatable[i];
  494.                 }
  495.                 for (i = 0; i < sizeof(NewFncData); i++)
  496.                     f[i] = NewFncData[i];
  497.                 }
  498.             }
  499.             if (nkm == ukm)
  500.                 printf("installing usa keymap\n");
  501.             else
  502.                 printf("installing custom KeyMap\n");
  503.             /* set the keymap */
  504.             IOR.io_Command = CD_SETKEYMAP;
  505.             IOR.io_Data = (APTR) nkm;
  506.             IOR.io_Length = sizeof(struct KeyMap);
  507.             DoIO(&IOR);
  508.  
  509.             if (cSize != uSize) {
  510.                 /* release the old keymap: oh, this IS demo code! */
  511.                 DisposeKeyMap(ckm.km_LoKeyMapTypes -
  512.                     sizeof(struct KeyMap));
  513.             }
  514.             }
  515.             FreeMem(id, sizeof(*id));
  516.         }
  517.         FreeMem(packet, sizeof(*packet));
  518.         }
  519.     }
  520. }
  521.