1 /* Hotkeys handling. */
11 #include "bfu/hotkey.h"
13 #include "config/kbdbind.h"
14 #include "intl/gettext/libintl.h"
15 #include "terminal/draw.h"
16 #include "terminal/terminal.h"
17 #include "terminal/window.h"
18 #include "util/conv.h"
19 #include "util/memory.h"
22 /* Return position (starting at 1) of the first tilde in text,
23 * or 0 if not found. */
25 find_hotkey_pos(unsigned char *text
)
28 unsigned char *p
= strchr(text
, '~');
30 if (p
) return (int) (p
- text
) + 1;
37 init_hotkeys(struct terminal
*term
, struct menu
*menu
)
42 /* hotkey debugging */
44 struct menu_item
*used_hotkeys
[255];
46 memset(used_hotkeys
, 0, sizeof(used_hotkeys
));
48 foreach_menu_item(mi
, menu
->items
) {
49 unsigned char *text
= mi
->text
;
51 if (!mi_has_left_text(mi
)) continue;
52 if (mi_text_translate(mi
)) text
= _(text
, term
);
55 if (mi
->hotkey_state
!= HKS_CACHED
&& !mi
->hotkey_pos
)
56 mi
->hotkey_pos
= find_hotkey_pos(text
);
58 /* Negative value for hotkey_pos means the key is already
59 * used by another entry. We mark it to be able to highlight
60 * this hotkey in menus. --Zas */
62 struct menu_item
**used
= &used_hotkeys
[toupper(text
[mi
->hotkey_pos
])];
65 mi
->hotkey_pos
= -mi
->hotkey_pos
;
66 if ((*used
)->hotkey_pos
> 0)
67 (*used
)->hotkey_pos
= -(*used
)->hotkey_pos
;
71 mi
->hotkey_state
= HKS_CACHED
;
77 foreach_menu_item(mi
, menu
->items
) {
80 mi
->hotkey_state
= HKS_IGNORE
;
81 } else if (mi
->hotkey_state
!= HKS_CACHED
83 unsigned char *text
= mi
->text
;
85 if (!mi_has_left_text(mi
)) continue;
86 if (mi_text_translate(mi
)) text
= _(text
, term
);
89 mi
->hotkey_pos
= find_hotkey_pos(text
);
92 mi
->hotkey_state
= HKS_CACHED
;
99 clear_hotkeys_cache(struct menu
*menu
)
101 struct menu_item
*item
;
103 foreach_menu_item(item
, menu
->items
) {
104 item
->hotkey_state
= menu
->hotkeys
? HKS_SHOW
: HKS_IGNORE
;
105 item
->hotkey_pos
= 0;
111 refresh_hotkeys(struct terminal
*term
, struct menu
*menu
)
114 if (current_language
!= menu
->lang
) {
115 clear_hotkeys_cache(menu
);
116 init_hotkeys(term
, menu
);
117 menu
->lang
= current_language
;
120 init_hotkeys(term
, menu
);
125 check_hotkeys_common(struct menu
*menu
, term_event_char_T hotkey
, struct terminal
*term
,
129 unicode_val_T key
= unicode_fold_label_case(hotkey
);
130 int codepage
= get_terminal_codepage(term
);
132 unsigned char key
= toupper(hotkey
);
134 int i
= menu
->selected
;
137 if (menu
->size
< 1) return 0;
140 if (i
< 0) i
+= menu
->size
;
144 struct menu_item
*item
;
147 unicode_val_T items_hotkey
;
151 if (++i
== menu
->size
) i
= 0;
153 item
= &menu
->items
[i
];
155 if (!mi_has_left_text(item
)) continue;
158 if (mi_text_translate(item
)) text
= _(text
, term
);
159 if (!text
|| !*text
) continue;
161 /* Change @text to point to the character that should
162 * be compared to @key. */
163 if (check_mode
== 0) {
164 /* Does the key (upcased) matches one of the
165 * hotkeys in menu ? */
166 int key_pos
= item
->hotkey_pos
;
169 if (key_pos
< 0) key_pos
= -key_pos
;
171 if (!key_pos
) continue;
174 /* Does the key (upcased) matches first letter
175 * of menu item left text ? */
178 /* Compare @key to the character to which @text points. */
180 items_hotkey
= cp_to_unicode(codepage
, &text
,
182 /* items_hotkey can be UCS_NO_CHAR only if the text of
183 * the menu item is not in the expected codepage. */
184 assert(items_hotkey
!= UCS_NO_CHAR
);
185 if_assert_failed
continue;
186 found
= (unicode_fold_label_case(items_hotkey
) == key
);
188 found
= (toupper(*text
) == key
);
196 } while (i
!= start
);
201 /* Returns true if a hotkey was found in the menu, and set menu->selected. */
203 check_hotkeys(struct menu
*menu
, term_event_char_T key
, struct terminal
*term
)
205 return check_hotkeys_common(menu
, key
, term
, 0);
208 /* Search if first letter of an entry in menu matches the key (caseless comp.).
209 * It searchs in all entries, from selected entry to bottom and then from top
211 * It returns 1 if found and set menu->selected. */
213 check_not_so_hot_keys(struct menu
*menu
, term_event_char_T key
, struct terminal
*term
)
215 return check_hotkeys_common(menu
, key
, term
, 1);