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 */
}