diff options
| author | Stefan Monnier | 2008-07-16 19:23:49 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2008-07-16 19:23:49 +0000 |
| commit | 0bcfd7d7798f089b5754ce188a33da2610620a3c (patch) | |
| tree | f3d09799f5b827e42c7f0da4b2f8a38aa2b45332 /src | |
| parent | 178377e10f4956eeb2edd5b05481f3771d32b7df (diff) | |
| download | emacs-0bcfd7d7798f089b5754ce188a33da2610620a3c.tar.gz emacs-0bcfd7d7798f089b5754ce188a33da2610620a3c.zip | |
* keymap.c: Remove all NS-specific code.
(where_is_preferred_modifier, Vwhere_is_preferred_modifier): New vars.
(preferred_sequence_p): Rename from ascii_sequence_p; pay attention to
where_is_preferred_modifier, return a different value depending on how
preferred is the binding.
(where_is_internal): Adjust accordingly.
(Fwhere_is_internal): Refresh where_is_preferred_modifier.
Adjust to new preferred_sequence_p.
(syms_of_keymap): Declare `where-is-preferred-modifier'.
* keyboard.c (parse_solitary_modifier): Not static any more.
* keyboard.h (parse_solitary_modifier): Declare.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 14 | ||||
| -rw-r--r-- | src/keyboard.c | 7 | ||||
| -rw-r--r-- | src/keyboard.h | 1 | ||||
| -rw-r--r-- | src/keymap.c | 152 |
4 files changed, 85 insertions, 89 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 0eb8fc0b253..8dffef41654 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,17 @@ | |||
| 1 | 2008-07-16 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * keymap.c: Remove all NS-specific code. | ||
| 4 | (where_is_preferred_modifier, Vwhere_is_preferred_modifier): New vars. | ||
| 5 | (preferred_sequence_p): Rename from ascii_sequence_p; pay attention to | ||
| 6 | where_is_preferred_modifier, return a different value depending on how | ||
| 7 | preferred is the binding. | ||
| 8 | (where_is_internal): Adjust accordingly. | ||
| 9 | (Fwhere_is_internal): Refresh where_is_preferred_modifier. | ||
| 10 | Adjust to new preferred_sequence_p. | ||
| 11 | (syms_of_keymap): Declare `where-is-preferred-modifier'. | ||
| 12 | * keyboard.c (parse_solitary_modifier): Not static any more. | ||
| 13 | * keyboard.h (parse_solitary_modifier): Declare. | ||
| 14 | |||
| 1 | 2008-07-16 Andreas Schwab <schwab@suse.de> | 15 | 2008-07-16 Andreas Schwab <schwab@suse.de> |
| 2 | 16 | ||
| 3 | * Makefile.in (SOME_MACHINE_LISP): Remove easy-mmode, fix spelling | 17 | * Makefile.in (SOME_MACHINE_LISP): Remove easy-mmode, fix spelling |
diff --git a/src/keyboard.c b/src/keyboard.c index 0ae24b70abb..219b42c2456 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -637,8 +637,6 @@ static Lisp_Object modify_event_symbol P_ ((int, unsigned, Lisp_Object, | |||
| 637 | Lisp_Object, char **, | 637 | Lisp_Object, char **, |
| 638 | Lisp_Object *, unsigned)); | 638 | Lisp_Object *, unsigned)); |
| 639 | static Lisp_Object make_lispy_switch_frame P_ ((Lisp_Object)); | 639 | static Lisp_Object make_lispy_switch_frame P_ ((Lisp_Object)); |
| 640 | static int parse_solitary_modifier P_ ((Lisp_Object)); | ||
| 641 | static int parse_solitary_modifier (); | ||
| 642 | static void save_getcjmp P_ ((jmp_buf)); | 640 | static void save_getcjmp P_ ((jmp_buf)); |
| 643 | static void save_getcjmp (); | 641 | static void save_getcjmp (); |
| 644 | static void restore_getcjmp P_ ((jmp_buf)); | 642 | static void restore_getcjmp P_ ((jmp_buf)); |
| @@ -6828,9 +6826,8 @@ has the same base event type and all the specified modifiers. */) | |||
| 6828 | /* Try to recognize SYMBOL as a modifier name. | 6826 | /* Try to recognize SYMBOL as a modifier name. |
| 6829 | Return the modifier flag bit, or 0 if not recognized. */ | 6827 | Return the modifier flag bit, or 0 if not recognized. */ |
| 6830 | 6828 | ||
| 6831 | static int | 6829 | int |
| 6832 | parse_solitary_modifier (symbol) | 6830 | parse_solitary_modifier (Lisp_Object symbol) |
| 6833 | Lisp_Object symbol; | ||
| 6834 | { | 6831 | { |
| 6835 | Lisp_Object name = SYMBOL_NAME (symbol); | 6832 | Lisp_Object name = SYMBOL_NAME (symbol); |
| 6836 | 6833 | ||
diff --git a/src/keyboard.h b/src/keyboard.h index e21766273a8..afdcd9d13de 100644 --- a/src/keyboard.h +++ b/src/keyboard.h | |||
| @@ -438,6 +438,7 @@ extern Lisp_Object parse_modifiers P_ ((Lisp_Object)); | |||
| 438 | extern Lisp_Object reorder_modifiers P_ ((Lisp_Object)); | 438 | extern Lisp_Object reorder_modifiers P_ ((Lisp_Object)); |
| 439 | extern Lisp_Object read_char P_ ((int, int, Lisp_Object *, Lisp_Object, | 439 | extern Lisp_Object read_char P_ ((int, int, Lisp_Object *, Lisp_Object, |
| 440 | int *, EMACS_TIME *)); | 440 | int *, EMACS_TIME *)); |
| 441 | extern int parse_solitary_modifier (Lisp_Object symbol); | ||
| 441 | 442 | ||
| 442 | 443 | ||
| 443 | /* Parent keymap of terminal-local function-key-map instances. */ | 444 | /* Parent keymap of terminal-local function-key-map instances. */ |
diff --git a/src/keymap.c b/src/keymap.c index 545ab3de81e..4b8c5cc0aa0 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -111,10 +111,6 @@ extern Lisp_Object meta_prefix_char; | |||
| 111 | 111 | ||
| 112 | extern Lisp_Object Voverriding_local_map; | 112 | extern Lisp_Object Voverriding_local_map; |
| 113 | 113 | ||
| 114 | #ifdef HAVE_NS | ||
| 115 | extern Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper; | ||
| 116 | #endif | ||
| 117 | |||
| 118 | /* Hash table used to cache a reverse-map to speed up calls to where-is. */ | 114 | /* Hash table used to cache a reverse-map to speed up calls to where-is. */ |
| 119 | static Lisp_Object where_is_cache; | 115 | static Lisp_Object where_is_cache; |
| 120 | /* Which keymaps are reverse-stored in the cache. */ | 116 | /* Which keymaps are reverse-stored in the cache. */ |
| @@ -2601,14 +2597,18 @@ See Info node `(elisp)Describing Characters' for examples. */) | |||
| 2601 | return build_string (str); | 2597 | return build_string (str); |
| 2602 | } | 2598 | } |
| 2603 | 2599 | ||
| 2604 | /* Return non-zero if SEQ contains only ASCII characters, perhaps with | 2600 | static int where_is_preferred_modifier; |
| 2605 | a meta bit. */ | 2601 | |
| 2602 | /* Return 0 if SEQ uses non-preferred modifiers or non-char events. | ||
| 2603 | Else, return 2 if SEQ uses the where_is_preferred_modifier, | ||
| 2604 | and 1 otherwise. */ | ||
| 2606 | static int | 2605 | static int |
| 2607 | ascii_sequence_p (seq) | 2606 | preferred_sequence_p (seq) |
| 2608 | Lisp_Object seq; | 2607 | Lisp_Object seq; |
| 2609 | { | 2608 | { |
| 2610 | int i; | 2609 | int i; |
| 2611 | int len = XINT (Flength (seq)); | 2610 | int len = XINT (Flength (seq)); |
| 2611 | int result = 1; | ||
| 2612 | 2612 | ||
| 2613 | for (i = 0; i < len; i++) | 2613 | for (i = 0; i < len; i++) |
| 2614 | { | 2614 | { |
| @@ -2617,49 +2617,21 @@ ascii_sequence_p (seq) | |||
| 2617 | XSETFASTINT (ii, i); | 2617 | XSETFASTINT (ii, i); |
| 2618 | elt = Faref (seq, ii); | 2618 | elt = Faref (seq, ii); |
| 2619 | 2619 | ||
| 2620 | if (!INTEGERP (elt) | 2620 | if (!INTEGERP (elt)) |
| 2621 | || (XUINT (elt) & ~CHAR_META) >= 0x80) | ||
| 2622 | return 0; | 2621 | return 0; |
| 2622 | else | ||
| 2623 | { | ||
| 2624 | int modifiers = XUINT (elt) & (CHAR_MODIFIER_MASK & ~CHAR_META); | ||
| 2625 | if (modifiers == where_is_preferred_modifier) | ||
| 2626 | result = 2; | ||
| 2627 | else if (modifiers) | ||
| 2628 | return 0; | ||
| 2629 | } | ||
| 2623 | } | 2630 | } |
| 2624 | 2631 | ||
| 2625 | return 1; | 2632 | return result; |
| 2626 | } | ||
| 2627 | |||
| 2628 | #ifdef HAVE_NS | ||
| 2629 | int lisp_to_mod(Lisp_Object lmod) | ||
| 2630 | /* ------------------------------------------------------------------------- | ||
| 2631 | Convert lisp symbol to emacs modifier code. | ||
| 2632 | ------------------------------------------------------------------------- */ | ||
| 2633 | { | ||
| 2634 | if (EQ(lmod, Qmeta)) | ||
| 2635 | return meta_modifier; | ||
| 2636 | else if (EQ(lmod, Qsuper)) | ||
| 2637 | return super_modifier; | ||
| 2638 | else if (EQ(lmod, Qcontrol)) | ||
| 2639 | return ctrl_modifier; | ||
| 2640 | else if (EQ(lmod, Qalt)) | ||
| 2641 | return alt_modifier; | ||
| 2642 | else if (EQ(lmod, Qhyper)) | ||
| 2643 | return hyper_modifier; | ||
| 2644 | return 0; | ||
| 2645 | } | 2633 | } |
| 2646 | 2634 | ||
| 2647 | /* Return non-zero if SEQ starts w/a char modified by given modifier only. */ | ||
| 2648 | static int | ||
| 2649 | modifier_sequence_p (Lisp_Object seq, Lisp_Object modifier) | ||
| 2650 | { | ||
| 2651 | Lisp_Object idx, elt; | ||
| 2652 | |||
| 2653 | if (XINT (Flength (seq)) == 0) | ||
| 2654 | return 0; | ||
| 2655 | XSETFASTINT(idx, 0); | ||
| 2656 | elt = Faref(seq, idx); | ||
| 2657 | |||
| 2658 | return (XUINT(elt) & (CHAR_MODIFIER_MASK ^ shift_modifier)) | ||
| 2659 | == lisp_to_mod(modifier); | ||
| 2660 | } | ||
| 2661 | #endif | ||
| 2662 | |||
| 2663 | 2635 | ||
| 2664 | /* where-is - finding a command in a set of keymaps. */ | 2636 | /* where-is - finding a command in a set of keymaps. */ |
| 2665 | 2637 | ||
| @@ -2751,7 +2723,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2751 | last_is_meta = (XINT (last) >= 0 | 2723 | last_is_meta = (XINT (last) >= 0 |
| 2752 | && EQ (Faref (this, last), meta_prefix_char)); | 2724 | && EQ (Faref (this, last), meta_prefix_char)); |
| 2753 | 2725 | ||
| 2754 | /* if (nomenus && !ascii_sequence_p (this)) */ | 2726 | /* if (nomenus && !preferred_sequence_p (this)) */ |
| 2755 | if (nomenus && XINT (last) >= 0 | 2727 | if (nomenus && XINT (last) >= 0 |
| 2756 | && SYMBOLP (tem = Faref (this, make_number (0))) | 2728 | && SYMBOLP (tem = Faref (this, make_number (0))) |
| 2757 | && !NILP (Fmemq (XCAR (parse_modifiers (tem)), Vmouse_events))) | 2729 | && !NILP (Fmemq (XCAR (parse_modifiers (tem)), Vmouse_events))) |
| @@ -2842,15 +2814,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2842 | we find. */ | 2814 | we find. */ |
| 2843 | if (EQ (firstonly, Qnon_ascii)) | 2815 | if (EQ (firstonly, Qnon_ascii)) |
| 2844 | RETURN_UNGCPRO (sequence); | 2816 | RETURN_UNGCPRO (sequence); |
| 2845 | #ifdef HAVE_NS | 2817 | else if (!NILP (firstonly) && 2 == preferred_sequence_p (sequence)) |
| 2846 | /* respond to modifier preference */ | ||
| 2847 | else if ((EQ (firstonly, Qalt) || EQ (firstonly, Qcontrol) | ||
| 2848 | || EQ (firstonly, Qhyper) || EQ (firstonly, Qmeta) | ||
| 2849 | || EQ (firstonly, Qsuper))) | ||
| 2850 | if (modifier_sequence_p(sequence, firstonly)) | ||
| 2851 | RETURN_UNGCPRO (sequence); | ||
| 2852 | #endif | ||
| 2853 | else if (!NILP (firstonly) && ascii_sequence_p (sequence)) | ||
| 2854 | RETURN_UNGCPRO (sequence); | 2818 | RETURN_UNGCPRO (sequence); |
| 2855 | 2819 | ||
| 2856 | if (CONSP (remapped)) | 2820 | if (CONSP (remapped)) |
| @@ -2869,12 +2833,25 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2869 | /* firstonly may have been t, but we may have gone all the way through | 2833 | /* firstonly may have been t, but we may have gone all the way through |
| 2870 | the keymaps without finding an all-ASCII key sequence. So just | 2834 | the keymaps without finding an all-ASCII key sequence. So just |
| 2871 | return the best we could find. */ | 2835 | return the best we could find. */ |
| 2872 | if (!NILP (firstonly)) | 2836 | if (NILP (firstonly)) |
| 2837 | return found; | ||
| 2838 | else if (where_is_preferred_modifier == 0) | ||
| 2873 | return Fcar (found); | 2839 | return Fcar (found); |
| 2874 | 2840 | else | |
| 2875 | return found; | 2841 | { /* Maybe we did not find a preferred_modifier binding, but we did find |
| 2842 | some ASCII binding. */ | ||
| 2843 | Lisp_Object bindings = found; | ||
| 2844 | while (CONSP (bindings)) | ||
| 2845 | if (preferred_sequence_p (XCAR (bindings))) | ||
| 2846 | return XCAR (bindings); | ||
| 2847 | else | ||
| 2848 | bindings = XCDR (bindings); | ||
| 2849 | return Fcar (found); | ||
| 2850 | } | ||
| 2876 | } | 2851 | } |
| 2877 | 2852 | ||
| 2853 | static Lisp_Object Vwhere_is_preferred_modifier; | ||
| 2854 | |||
| 2878 | DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 5, 0, | 2855 | DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 5, 0, |
| 2879 | doc: /* Return list of keys that invoke DEFINITION. | 2856 | doc: /* Return list of keys that invoke DEFINITION. |
| 2880 | If KEYMAP is a keymap, search only KEYMAP and the global keymap. | 2857 | If KEYMAP is a keymap, search only KEYMAP and the global keymap. |
| @@ -2883,13 +2860,10 @@ If KEYMAP is a list of keymaps, search only those keymaps. | |||
| 2883 | 2860 | ||
| 2884 | If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found, | 2861 | If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found, |
| 2885 | rather than a list of all possible key sequences. | 2862 | rather than a list of all possible key sequences. |
| 2886 | #ifdef HAVE_NS | ||
| 2887 | If FIRSTONLY is the symbol for a modifier key, return the first binding found, | ||
| 2888 | that is modified by that modifier only. | ||
| 2889 | #endif | ||
| 2890 | If FIRSTONLY is the symbol `non-ascii', return the first binding found, | 2863 | If FIRSTONLY is the symbol `non-ascii', return the first binding found, |
| 2891 | no matter what it is. | 2864 | no matter what it is. |
| 2892 | If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters | 2865 | If FIRSTONLY has another non-nil value, prefer bindings |
| 2866 | that use the modifier key specified in `where-is-preferred-modifier' | ||
| 2893 | \(or their meta variants) and entirely reject menu bindings. | 2867 | \(or their meta variants) and entirely reject menu bindings. |
| 2894 | 2868 | ||
| 2895 | If optional 4th arg NOINDIRECT is non-nil, don't follow indirections | 2869 | If optional 4th arg NOINDIRECT is non-nil, don't follow indirections |
| @@ -2908,6 +2882,10 @@ remapped command in the returned list. */) | |||
| 2908 | int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii); | 2882 | int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii); |
| 2909 | Lisp_Object result; | 2883 | Lisp_Object result; |
| 2910 | 2884 | ||
| 2885 | /* Refresh the C version of the modifier preference. */ | ||
| 2886 | where_is_preferred_modifier | ||
| 2887 | = parse_solitary_modifier (Vwhere_is_preferred_modifier); | ||
| 2888 | |||
| 2911 | /* Find the relevant keymaps. */ | 2889 | /* Find the relevant keymaps. */ |
| 2912 | if (CONSP (keymap) && KEYMAPP (XCAR (keymap))) | 2890 | if (CONSP (keymap) && KEYMAPP (XCAR (keymap))) |
| 2913 | keymaps = keymap; | 2891 | keymaps = keymap; |
| @@ -2921,7 +2899,7 @@ remapped command in the returned list. */) | |||
| 2921 | if (nomenus && NILP (noindirect) && NILP (keymap)) | 2899 | if (nomenus && NILP (noindirect) && NILP (keymap)) |
| 2922 | { | 2900 | { |
| 2923 | Lisp_Object *defns; | 2901 | Lisp_Object *defns; |
| 2924 | int i, j, n; | 2902 | int i, n; |
| 2925 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; | 2903 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; |
| 2926 | 2904 | ||
| 2927 | /* Check heuristic-consistency of the cache. */ | 2905 | /* Check heuristic-consistency of the cache. */ |
| @@ -2956,26 +2934,23 @@ remapped command in the returned list. */) | |||
| 2956 | the following can GC. */ | 2934 | the following can GC. */ |
| 2957 | GCPRO2 (definition, keymaps); | 2935 | GCPRO2 (definition, keymaps); |
| 2958 | result = Qnil; | 2936 | result = Qnil; |
| 2959 | j = -1; | 2937 | { |
| 2960 | for (i = n - 1; i >= 0; --i) | 2938 | int best_pref = -1; |
| 2961 | if (EQ (shadow_lookup (keymaps, defns[i], Qnil), definition)) | 2939 | int j = -1; |
| 2940 | for (i = n - 1; i >= 0; --i) | ||
| 2962 | { | 2941 | { |
| 2963 | #ifdef HAVE_NS | 2942 | int pref = preferred_sequence_p (defns[i]); |
| 2964 | if ((EQ (firstonly, Qalt) || EQ (firstonly, Qcontrol) | 2943 | if (pref > best_pref |
| 2965 | || EQ (firstonly, Qhyper) || EQ (firstonly, Qmeta) | 2944 | && EQ (shadow_lookup (keymaps, defns[i], Qnil), definition)) |
| 2966 | || EQ (firstonly, Qsuper)) | 2945 | { |
| 2967 | && modifier_sequence_p(defns[i], firstonly)) | 2946 | j = i; |
| 2968 | break; | 2947 | best_pref = pref; |
| 2969 | else if (EQ (firstonly, Qt) && ascii_sequence_p (defns[i])) | 2948 | if (best_pref == 2) |
| 2970 | #else | 2949 | break; |
| 2971 | if (ascii_sequence_p (defns[i])) | 2950 | } |
| 2972 | #endif | ||
| 2973 | break; | ||
| 2974 | else if (j < 0) | ||
| 2975 | j = i; | ||
| 2976 | } | 2951 | } |
| 2977 | 2952 | result = j >= 0 ? defns[j] : Qnil; | |
| 2978 | result = i >= 0 ? defns[i] : (j >= 0 ? defns[j] : Qnil); | 2953 | } |
| 2979 | UNGCPRO; | 2954 | UNGCPRO; |
| 2980 | } | 2955 | } |
| 2981 | else | 2956 | else |
| @@ -3155,7 +3130,7 @@ You type Translation\n\ | |||
| 3155 | char *title, *p; | 3130 | char *title, *p; |
| 3156 | 3131 | ||
| 3157 | if (!SYMBOLP (modes[i])) | 3132 | if (!SYMBOLP (modes[i])) |
| 3158 | abort(); | 3133 | abort (); |
| 3159 | 3134 | ||
| 3160 | p = title = (char *) alloca (42 + SCHARS (SYMBOL_NAME (modes[i]))); | 3135 | p = title = (char *) alloca (42 + SCHARS (SYMBOL_NAME (modes[i]))); |
| 3161 | *p++ = '\f'; | 3136 | *p++ = '\f'; |
| @@ -4027,6 +4002,15 @@ the same way. The "active" keymaps in each alist are used before | |||
| 4027 | `minor-mode-map-alist' and `minor-mode-overriding-map-alist'. */); | 4002 | `minor-mode-map-alist' and `minor-mode-overriding-map-alist'. */); |
| 4028 | Vemulation_mode_map_alists = Qnil; | 4003 | Vemulation_mode_map_alists = Qnil; |
| 4029 | 4004 | ||
| 4005 | DEFVAR_LISP ("where-is-preferred-modifier", &Vwhere_is_preferred_modifier, | ||
| 4006 | doc: /* Preferred modifier to use for `where-is'. | ||
| 4007 | When a single binding is requested, `where-is' will return one that | ||
| 4008 | uses this modifier if possible. If nil, or if no such binding exists, | ||
| 4009 | bindings using keys without modifiers (or only with meta) will be | ||
| 4010 | preferred. */); | ||
| 4011 | Vwhere_is_preferred_modifier = Qnil; | ||
| 4012 | where_is_preferred_modifier = 0; | ||
| 4013 | |||
| 4030 | staticpro (&Vmouse_events); | 4014 | staticpro (&Vmouse_events); |
| 4031 | Vmouse_events = Fcons (intern ("menu-bar"), | 4015 | Vmouse_events = Fcons (intern ("menu-bar"), |
| 4032 | Fcons (intern ("tool-bar"), | 4016 | Fcons (intern ("tool-bar"), |
| @@ -4103,7 +4087,7 @@ void | |||
| 4103 | keys_of_keymap () | 4087 | keys_of_keymap () |
| 4104 | { | 4088 | { |
| 4105 | initial_define_key (global_map, 033, "ESC-prefix"); | 4089 | initial_define_key (global_map, 033, "ESC-prefix"); |
| 4106 | initial_define_key (global_map, Ctl('X'), "Control-X-prefix"); | 4090 | initial_define_key (global_map, Ctl ('X'), "Control-X-prefix"); |
| 4107 | } | 4091 | } |
| 4108 | 4092 | ||
| 4109 | /* arch-tag: 6dd15c26-7cf1-41c4-b904-f42f7ddda463 | 4093 | /* arch-tag: 6dd15c26-7cf1-41c4-b904-f42f7ddda463 |