minow@thundr.dec.com (Fortran for Precedent) (10/15/88)
(This didn't seem to get out the first time: apologies if you see it twice) I'm writing a VT200 terminal emulator that implements the Dec LK201 keyboard. This means that my "option" character set is completely different from Apple's (I use a private font), and I have to handle the Option overstrikes differently. Because of a bug in the operating system, this isn't possible to do cleanly (<Option>e passes through deadkey processing before my event handler sees it). I thought I could fix this by creating my own KCHR resource (following Tech Note 160). My private resource is identical to the system resource except that all <Option> handling points to the "standard" eyboard. The code seems to run correctly, except for three problems: -- KeyTrans doesn't put the SICN resource in the menu bar. -- GetScript(... smScriptIcon) returns zero, not my resource id (however GetScript(... smScriptKeys) returns the correct value. -- The keyboard action doesn't change. I can live with the first two, but the last problem is driving me batty. Any suggestions as to what I'm doing wrong would be greatly appreciated. Martin Minow minow%thundr.dec@decwrl.dec.com /* * This hack is called at program startup. It finds the current keyboard * mapping resource (KCHR) and creates a new KCHR that does not have any * deadkeys. This allows our LK201 compose routine to work without * interference from the system keyboard translator. I suppose creating a * proper KCHR resource (with our mapping) would be somewhat better, but it's * a pain. The associated SICN resource is in the resource file. */ void setup_KCHR_resource() { register int i; int KCHR_resource_id; Handle kchr, new, sicn; union { unsigned char *c; short int *i; } table; int n_tables; long size; OSErr status; KCHR_resource_id = GetScript(smScriptKeys, GetEnvirons(smKeyScript)); kchr = GetResource('KCHR', KCHR_resource_id); if (kchr == NIL) { error_message("No KCHR?", ResError()); return; } HLock(kchr); table.c = (unsigned char *) *kchr; n_tables = table.i[1 + (256 / sizeof (short))]; /* * n_tables has the number of keyboard mapping tables (8 for US). * Build a resource just big enough. */ size = sizeof (short) /* Version number */ + 256 /* Table indexes */ + sizeof (short) /* number of tables */ + (n_tables * 128) /* the actual tables */ + sizeof (short); /* Number of deadkeys */ new = NewHandle((long) size); /* Get the resource */ if (new == NIL) { error_message("No room for KCHR?", (int) size); HUnlock(kchr); return; } HLock(new); BlockMove(*kchr, *new, size); HUnlock(kchr); /* Done with kchr */ table.c = (unsigned char *) *new; /* table -> new KCHR */ table.i[1 + 128 + 1 + (n_tables * 64)] = 0; /* No deadkeys */ table.c += sizeof (short); /* -> table @ indexes */ /* * Walk through the table_index entries. When we find one * with optionKey set, change it to point to the table without * option key (but with the same arrangements of shift/caps/control). * Not that this will leave some dangling (unused) tables. Can't * win 'em all. */ #define OPT (optionKey >> 8) for (i = 0; i < 256; i++) { if ((i & OPT) != 0) table.c[i] = table.c[i & ~OPT]; } HUnlock(new); AddResource(new, 'KCHR', KCHR_resource_id, "\pLK201 KCHR"); if (ResError() != noErr) { error_message("Can't add KCHR resource", ResError()); return; } SetResAttrs(new, 0); /* Clear "changed" bit */ if (GetResource('SICN', KCHR_id) == NIL) { error_message("No SICN?", ResError()); return; } status = SetScript(smRoman, smScriptKeys, KCHR_id); if (status != noErr) status = SetScript(smRoman, smScriptIcon, KCHR_id); if (status != noErr) error_message("Can't SetScript", status); KeyScript(smRoman); Debugger(); status = GetScript(GetEnvirons(smKeyScript), smScriptKeys); /* This returns the expected value (KCHR_id) */ status = GetScript(GetEnvirons(smKeyScript), smScriptIcon); /* This returns zero and "my" keyboard isn't enabled and the */ /* icon doesn't show */ }