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.
*/
/*
* 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 (!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 (shift && keyevent >= 0x100)
- keyevent |= MOD_SHFT;
- if (ctrl && keyevent >= 0x100)
- keyevent |= MOD_CTRL;
- midend_process_key(me, 0, 0, keyevent);
- update_undo_redo();
+ 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();
+ }
}
/*
}
};
- // 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();
};