diff --git a/emcc.c b/emcc.c index e3bcbf5..d85a0e8 100644 --- a/emcc.c +++ b/emcc.c @@ -148,6 +148,17 @@ void debug_printf(char *fmt, ...) js_debug(buf); } +/* + * Helper function that makes it easy to test strings that might be + * NULL. + */ +int strnullcmp(const char *a, const char *b) +{ + if (a == NULL || b == NULL) + return a != NULL ? +1 : b != NULL ? -1 : 0; + return strcmp(a, b); +} + /* * HTMLish names for the colours allocated by the puzzle. */ @@ -245,67 +256,64 @@ void mousemove(int x, int y, int buttons) /* * Keyboard handler called from JS. */ -void key(int keycode, int charcode, int shift, int ctrl) +void key(int keycode, int charcode, const char *key, const char *chr, + int shift, int ctrl) { int keyevent = -1; - if (charcode != 0) { - keyevent = charcode & (ctrl ? 0x1F : 0xFF); - } else { - switch (keycode) { - case 8: - keyevent = '\177'; /* backspace */ - break; - case 13: - keyevent = 13; /* return */ - break; - case 37: - keyevent = CURSOR_LEFT; - break; - case 38: - keyevent = CURSOR_UP; - break; - case 39: - keyevent = CURSOR_RIGHT; - break; - case 40: - keyevent = CURSOR_DOWN; - break; - /* - * We interpret Home, End, PgUp and PgDn as numeric keypad - * controls regardless of whether they're the ones on the - * numeric keypad (since we can't tell). The effect of - * this should only be that the non-numeric-pad versions - * of those keys generate directions in 8-way movement - * puzzles like Cube and Inertia. - */ - case 35: /* End */ - keyevent = MOD_NUM_KEYPAD | '1'; - break; - case 34: /* PgDn */ - keyevent = MOD_NUM_KEYPAD | '3'; - break; - case 36: /* Home */ - keyevent = MOD_NUM_KEYPAD | '7'; - break; - case 33: /* PgUp */ - keyevent = MOD_NUM_KEYPAD | '9'; - break; - case 96: case 97: case 98: case 99: case 100: - case 101: case 102: case 103: case 104: case 105: - keyevent = MOD_NUM_KEYPAD | ('0' + keycode - 96); - break; - default: - /* not a key we care about */ - return; - } - } - if (shift && keyevent >= 0x100) - keyevent |= MOD_SHFT; - if (ctrl && keyevent >= 0x100) - keyevent |= MOD_CTRL; - midend_process_key(me, 0, 0, keyevent); - update_undo_redo(); + if (!strnullcmp(key, "Backspace") || !strnullcmp(key, "Del") || + keycode == 8 || keycode == 46) { + keyevent = 127; /* Backspace / Delete */ + } else if (!strnullcmp(key, "Enter") || keycode == 13) { + keyevent = 13; /* return */ + } else if (!strnullcmp(key, "Left") || keycode == 37) { + keyevent = CURSOR_LEFT; + } else if (!strnullcmp(key, "Up") || keycode == 38) { + keyevent = CURSOR_UP; + } else if (!strnullcmp(key, "Right") || keycode == 39) { + keyevent = CURSOR_RIGHT; + } else if (!strnullcmp(key, "Down") || keycode == 40) { + keyevent = CURSOR_DOWN; + } else if (!strnullcmp(key, "End") || keycode == 35) { + /* + * We interpret Home, End, PgUp and PgDn as numeric keypad + * controls regardless of whether they're the ones on the + * numeric keypad (since we can't tell). The effect of + * this should only be that the non-numeric-pad versions + * of those keys generate directions in 8-way movement + * puzzles like Cube and Inertia. + */ + keyevent = MOD_NUM_KEYPAD | '1'; + } else if (!strnullcmp(key, "PageDown") || keycode==34) { + keyevent = MOD_NUM_KEYPAD | '3'; + } else if (!strnullcmp(key, "Home") || keycode==36) { + keyevent = MOD_NUM_KEYPAD | '7'; + } else if (!strnullcmp(key, "PageUp") || keycode==33) { + keyevent = MOD_NUM_KEYPAD | '9'; + } else if (chr && chr[0] && !chr[1]) { + keyevent = chr[0] & 0xFF; + } else if (keycode >= 96 && keycode < 106) { + keyevent = MOD_NUM_KEYPAD | ('0' + keycode - 96); + } else if (keycode >= 65 && keycode <= 90) { + keyevent = keycode + (shift ? 0 : 32); + } else if (keycode >= 48 && keycode <= 57) { + keyevent = keycode; + } + + if (keyevent >= 0) { + if (shift && keyevent >= 0x100) + keyevent |= MOD_SHFT; + + if (ctrl) { + if (keyevent >= 0x100) + keyevent |= MOD_CTRL; + else + keyevent &= 0x1F; + } + + midend_process_key(me, 0, 0, keyevent); + update_undo_redo(); + } } /* diff --git a/emccpre.js b/emccpre.js index 66e6354..701c7f7 100644 --- a/emccpre.js +++ b/emccpre.js @@ -157,26 +157,21 @@ function initPuzzle() { } }; - // Set up keyboard handlers. We expect ordinary keys (with a - // charCode) to be handled by onkeypress, but function keys - // (arrows etc) to be handled by onkeydown. - // - // We also call event.preventDefault() in both handlers. This - // means that while the canvas itself has focus, _all_ keypresses - // go only to the puzzle - so users of this puzzle collection in - // other media can indulge their instinct to press ^R for redo, - // for example, without accidentally reloading the page. - key = Module.cwrap('key', 'void', - ['number', 'number', 'number', 'number']); + // Set up keyboard handlers. We do all the actual keyboard + // handling in onkeydown; but we also call event.preventDefault() + // in both the keydown and keypress handlers. This means that + // while the canvas itself has focus, _all_ keypresses go only to + // the puzzle - so users of this puzzle collection in other media + // can indulge their instinct to press ^R for redo, for example, + // without accidentally reloading the page. + key = Module.cwrap('key', 'void', ['number', 'number', 'string', + 'string', 'number', 'number']); onscreen_canvas.onkeydown = function(event) { - key(event.keyCode, event.charCode, + key(event.keyCode, event.charCode, event.key, event.char, event.shiftKey ? 1 : 0, event.ctrlKey ? 1 : 0); event.preventDefault(); }; onscreen_canvas.onkeypress = function(event) { - if (event.charCode != 0) - key(event.keyCode, event.charCode, - event.shiftKey ? 1 : 0, event.ctrlKey ? 1 : 0); event.preventDefault(); };