# HG changeset patch # User Richard M. Stallman # Date 793837905 0 # Node ID 06d6b2e179874c68b12dfc45e09a949a95cde8e8 # Parent 2f2e5033b3bb6f2123254e01bd8db33fa421b993 (convert_event_type_list): New function. (lucid_event_type_list_p): New function. (parse_modifiers_uncached): If MODIFIERS_END is -1, look for just a modifier. Guts rewritten. diff -r 2f2e5033b3bb -r 06d6b2e17987 src/keyboard.c --- a/src/keyboard.c Sun Feb 26 22:06:49 1995 +0000 +++ b/src/keyboard.c Sun Feb 26 22:31:45 1995 +0000 @@ -1429,7 +1429,8 @@ #endif } -/* Applying the control modifier to CHARACTER. */ +/* Apply the control modifier to CHARACTER. */ + int make_ctrl_char (c) int c; @@ -3161,7 +3162,11 @@ SYMBOL's name of the end of the modifiers; the string from this position is the unmodified symbol name. + If MODIFIER_END is -1, parse *only* a modifier; expect + the symbol name to be just one modifier, with no dash. + This doesn't use any caches. */ + static int parse_modifiers_uncached (symbol, modifier_end) Lisp_Object symbol; @@ -3170,87 +3175,117 @@ struct Lisp_String *name; int i; int modifiers; + int just_one = ((int *) (-1) == modifier_end); CHECK_SYMBOL (symbol, 1); modifiers = 0; name = XSYMBOL (symbol)->name; - for (i = 0; i+2 <= name->size; ) - switch (name->data[i]) - { -#define SINGLE_LETTER_MOD(bit) \ - if (name->data[i+1] != '-') \ - goto no_more_modifiers; \ - modifiers |= bit; \ - i += 2; - - case 'A': - SINGLE_LETTER_MOD (alt_modifier); - break; - - case 'C': - SINGLE_LETTER_MOD (ctrl_modifier); - break; - - case 'H': - SINGLE_LETTER_MOD (hyper_modifier); - break; - - case 'M': - SINGLE_LETTER_MOD (meta_modifier); - break; - - case 'S': - SINGLE_LETTER_MOD (shift_modifier); - break; - - case 's': - SINGLE_LETTER_MOD (super_modifier); - break; - - case 'd': - if (i + 5 > name->size) - goto no_more_modifiers; - if (! strncmp (name->data + i, "drag-", 5)) - { - modifiers |= drag_modifier; - i += 5; - } - else if (! strncmp (name->data + i, "down-", 5)) - { - modifiers |= down_modifier; - i += 5; - } - else if (i + 7 <= name->size - && ! strncmp (name->data + i, "double-", 7)) - { - modifiers |= double_modifier; - i += 7; - } - else - goto no_more_modifiers; - break; - - case 't': - if (i + 7 > name->size) - goto no_more_modifiers; - if (! strncmp (name->data + i, "triple-", 7)) - { - modifiers |= triple_modifier; - i += 7; - } - else - goto no_more_modifiers; - break; - - default: - goto no_more_modifiers; + { + int this_mod_end = 0; + int this_mod = 0; + + /* See if the name continues with a modifier word. + Check that the word appears, but don't check what follows it. + Set this_mod and this_mod_end to record what we find. */ + + switch (name->data[i]) + { +#define SINGLE_LETTER_MOD(BIT) \ + (this_mod_end = i + 1, this_mod = BIT) + +#define MULTI_LETTER_MOD(BIT, NAME, LEN) \ + if (i + LEN <= name->size \ + && ! strncmp (name->data + i, NAME, LEN)) \ + { \ + this_mod_end = i + LEN; \ + this_mod = BIT; \ + break; \ + } + + case 'A': + SINGLE_LETTER_MOD (alt_modifier); + break; + + case 'a': + MULTI_LETTER_MOD (alt_modifier, "alt", 3); + break; + + case 'C': + SINGLE_LETTER_MOD (ctrl_modifier); + break; + + case 'c': + MULTI_LETTER_MOD (ctrl_modifier, "ctrl", 4); + MULTI_LETTER_MOD (ctrl_modifier, "control", 7); + break; + + case 'H': + SINGLE_LETTER_MOD (hyper_modifier); + break; + + case 'h': + MULTI_LETTER_MOD (hyper_modifier, "hyper", 5); + break; + + case 'M': + SINGLE_LETTER_MOD (meta_modifier); + break; + + case 'm': + MULTI_LETTER_MOD (meta_modifier, "meta", 4); + break; + + case 'S': + SINGLE_LETTER_MOD (shift_modifier); + break; + + case 's': + MULTI_LETTER_MOD (shift_modifier, "shift", 5); + MULTI_LETTER_MOD (super_modifier, "super", 5); + SINGLE_LETTER_MOD (super_modifier); + break; + + case 'd': + MULTI_LETTER_MOD (drag_modifier, "drag", 4); + MULTI_LETTER_MOD (down_modifier, "down", 4); + MULTI_LETTER_MOD (double_modifier, "double", 6); + break; + + case 't': + MULTI_LETTER_MOD (triple_modifier, "triple", 6); + break; #undef SINGLE_LETTER_MOD - } - no_more_modifiers: +#undef MULTI_LETTER_MOD + } + + /* If we are looking for just a modifier, return now. + Return 0 if we didn't find one; return the + modifier bit if we did find one. */ + if (just_one) + { + if (this_mod_end == name->size) + return this_mod; + else + return 0; + } + + /* If we found no modifier, stop looking for them. */ + if (this_mod_end == 0) + break; + + /* Check there is a dash after the modifier, so that it + really is a modifier. */ + if (this_mod_end >= name->size || name->data[this_mod_end] != '-') + break; + + /* This modifier is real; look for another. */ + modifiers |= this_mod; + i = this_mod_end + 1; + } /* Should we include the `click' modifier? */ if (! (modifiers & (down_modifier | drag_modifier @@ -3266,7 +3301,6 @@ return modifiers; } - /* Return a symbol whose name is the modifier prefixes for MODIFIERS prepended to the string BASE[0..BASE_LEN-1]. This doesn't use any caches. */ @@ -3582,6 +3616,79 @@ /* Apply modifiers to that symbol. */ return apply_modifiers (modifiers, value); } + +/* Convert a list that represents an event type, + such as (ctrl meta backspace), into the usual representation of that + event type as a number or a symbol. */ + +Lisp_Object +convert_event_type_list (event) + Lisp_Object event; +{ + Lisp_Object base; + int modifiers = 0; + Lisp_Object rest; + + base = Qnil; + rest = event; + while (CONSP (rest)) + { + Lisp_Object elt; + int this = 0; + + elt = XCONS (rest)->car; + + if (SYMBOLP (elt)) + this = parse_modifiers_uncached (elt, -1); + + if (this != 0) + modifiers |= this; + else if (!NILP (base)) + error ("Two bases given in one event"); + else + base = elt; + + rest = XCONS (rest)->cdr; + } + + if (INTEGERP (base)) + { + if (modifiers & ctrl_modifier) + return make_number ((modifiers & ~ ctrl_modifier) + | make_ctrl_char (XINT (base))); + else + return make_number (modifiers | XINT (base)); + } + else if (SYMBOLP (base)) + return apply_modifiers (modifiers, base); + else + error ("Invalid base event"); +} + +/* Return 1 if EVENT is a list whose elements are all integers or symbols. + Such a list is not valid as an event, + but it can be a Lucid-style event type list. */ + +int +lucid_event_type_list_p (object) + Lisp_Object object; +{ + Lisp_Object tail; + + if (! CONSP (object)) + return 0; + + for (tail = object; CONSP (tail); tail = XCONS (tail)->cdr) + { + Lisp_Object elt; + elt = XCONS (tail)->car; + if (! (INTEGERP (elt) || SYMBOLP (elt))) + return 0; + } + + return NILP (tail); +} + /* Store into *addr a value nonzero if terminal input chars are available.