4 #define _GNU_SOURCE /* XXX: we _WANT_ strcasestr() ! */
15 #include "bfu/dialog.h"
16 #include "config/conf.h"
17 #include "config/dialogs.h"
18 #include "config/kbdbind.h"
19 #include "config/options.h"
20 #include "config/opttypes.h"
21 #include "intl/gettext/libintl.h"
22 #include "main/event.h"
23 #include "main/object.h"
24 #include "session/session.h"
25 #include "terminal/kbd.h"
26 #include "terminal/terminal.h"
27 #include "util/color.h"
28 #include "util/error.h"
29 #include "util/lists.h"
30 #include "util/memory.h"
31 #include "util/secsave.h"
35 disable_success_msgbox(void *dummy
)
37 get_opt_bool("ui.success_msgbox", NULL
) = 0;
38 option_changed(NULL
, get_opt_rec(config_options
, "ui.success_msgbox"));
42 write_config_dialog(struct terminal
*term
, unsigned char *config_file
,
43 int secsave_error
, int stdio_error
)
45 /* [gettext_accelerator_context(write_config_dialog)] */
46 unsigned char *errmsg
= NULL
;
47 unsigned char *strerr
;
49 if (secsave_error
== SS_ERR_NONE
&& !stdio_error
) {
50 if (!get_opt_bool("ui.success_msgbox", NULL
)) return;
52 msg_box(term
, NULL
, MSGBOX_FREE_TEXT
,
53 N_("Write config success"), ALIGN_CENTER
,
54 msg_text(term
, N_("Options were saved successfully to config file %s."),
57 MSG_BOX_BUTTON(N_("~OK"), NULL
, B_ENTER
| B_ESC
),
58 MSG_BOX_BUTTON(N_("~Do not show anymore"), disable_success_msgbox
, 0));
62 strerr
= secsave_strerror(secsave_error
, term
);
65 errmsg
= straconcat(strerr
, " (", strerror(stdio_error
), ")",
66 (unsigned char *) NULL
);
68 info_box(term
, MSGBOX_FREE_TEXT
,
69 N_("Write config error"), ALIGN_CENTER
,
70 msg_text(term
, N_("Unable to write to config file %s.\n%s"),
71 config_file
, errmsg
? errmsg
: strerr
));
78 /****************************************************************************
80 ****************************************************************************/
82 /* Implementation of the listbox operations */
85 lock_option(struct listbox_item
*item
)
87 object_lock((struct option
*) item
->udata
);
91 unlock_option(struct listbox_item
*item
)
93 object_unlock((struct option
*) item
->udata
);
97 is_option_used(struct listbox_item
*item
)
99 return is_object_used((struct option
*) item
->udata
);
102 static unsigned char *
103 get_range_string(struct option
*option
)
107 if (!init_string(&info
)) return NULL
;
109 if (option
->type
== OPT_BOOL
)
110 add_to_string(&info
, "[0|1]");
111 else if (option
->type
== OPT_INT
|| option
->type
== OPT_LONG
)
112 add_format_to_string(&info
, "[%li..%li]", option
->min
, option
->max
);
117 static unsigned char *
118 get_option_text(struct listbox_item
*item
, struct terminal
*term
)
120 struct option
*option
= item
->udata
;
121 unsigned char *desc
= option
->capt
? option
->capt
: option
->name
;
123 if (option
->flags
& OPT_TOUCHED
)
124 return straconcat(_(desc
, term
),
125 " (", _("modified", term
), ")",
126 (unsigned char *) NULL
);
128 return stracpy(_(desc
, term
));
131 static unsigned char *
132 get_option_info(struct listbox_item
*item
, struct terminal
*term
)
134 struct option
*option
= item
->udata
;
135 unsigned char *desc
, *type
;
138 if (!init_string(&info
)) return NULL
;
140 add_format_to_string(&info
, "%s: %s", _("Name", term
), option
->name
);
142 type
= _(option_types
[option
->type
].name
, term
);
143 if (option
->type
== OPT_TREE
) {
144 type
= straconcat(type
, " ",
145 _("(expand by pressing space)", term
),
146 (unsigned char *) NULL
);
149 add_format_to_string(&info
, "\n%s: %s", _("Type", term
), type
);
151 if (option
->type
== OPT_TREE
) {
155 if (option_types
[option
->type
].write
) {
156 unsigned char *range
;
159 if (!init_string(&value
)) {
164 option_types
[option
->type
].write(option
, &value
);
166 range
= get_range_string(option
);
169 add_to_string(&info
, " ");
170 add_to_string(&info
, range
);
174 add_format_to_string(&info
, "\n%s: %s", _("Value", term
), value
.source
);
177 if (option
->flags
& OPT_TOUCHED
)
178 add_to_string(&info
, _("\n\nThis value has been changed"
179 " since you last saved your"
180 " configuration.", term
));
184 desc
= _(option
->desc
? option
->desc
: (unsigned char *) "N/A", term
);
186 add_format_to_string(&info
, "\n\n%s:\n%s", _("Description", term
), desc
);
191 static struct listbox_item
*
192 get_option_root(struct listbox_item
*item
)
194 struct option
*option
= item
->udata
;
196 /* The config_options root has no listbox so return that
197 * we are at the bottom. */
198 if (option
->root
== config_options
) return NULL
;
200 return option
->root
? option
->root
->box_item
: NULL
;
203 static enum listbox_match
204 match_option(struct listbox_item
*item
, struct terminal
*term
,
207 struct option
*option
= item
->udata
;
209 if (option
->type
== OPT_TREE
)
210 return LISTBOX_MATCH_IMPOSSIBLE
;
212 if (strcasestr(option
->name
, text
)
213 || (option
->capt
&& strcasestr(_(option
->capt
, term
), text
)))
214 return LISTBOX_MATCH_OK
;
216 return LISTBOX_MATCH_NO
;
220 can_delete_option(struct listbox_item
*item
)
222 struct option
*option
= item
->udata
;
225 struct option
*parent_option
= option
->root
;
227 return parent_option
->flags
& OPT_AUTOCREATE
;
234 delete_option_item(struct listbox_item
*item
, int last
)
236 struct option
*option
= item
->udata
;
238 assert(!is_object_used(option
));
240 /* Only built-in options needs to be marked as deleted, so if the
241 * option is allocated call the cleaner. */
242 if (option
->flags
& OPT_ALLOC
)
243 delete_option(option
);
245 mark_option_as_deleted(option
);
248 static const struct listbox_ops options_listbox_ops
= {
263 /* Button handlers */
265 static widget_handler_status_T
266 check_valid_option(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
268 struct terminal
*term
= dlg_data
->win
->term
;
269 struct option
*option
= dlg_data
->dlg
->udata
;
270 struct session
*ses
= dlg_data
->dlg
->udata2
;
271 unsigned char *value
= widget_data
->cdata
;
272 unsigned char *chinon
;
276 chinon
= option_types
[option
->type
].read(option
, &value
, &dummy_line
);
278 if (option_types
[option
->type
].set
&&
279 option_types
[option
->type
].set(option
, chinon
)) {
280 option_changed(ses
, option
);
284 return EVENT_PROCESSED
;
291 N_("Error"), ALIGN_LEFT
,
292 N_("Bad option value."));
294 return EVENT_NOT_PROCESSED
;
298 build_edit_dialog(struct terminal
*term
, struct session
*ses
,
299 struct option
*option
)
301 /* [gettext_accelerator_context(.build_edit_dialog)] */
302 #define EDIT_WIDGETS_COUNT 5
304 unsigned char *value
, *name
, *desc
, *range
;
305 struct string tvalue
;
307 if (!init_string(&tvalue
)) return;
310 option_types
[option
->type
].write(option
, &tvalue
);
313 /* Create the dialog */
314 dlg
= calloc_dialog(EDIT_WIDGETS_COUNT
, MAX_STR_LEN
);
316 done_string(&tvalue
);
320 dlg
->title
= _("Edit", term
);
321 dlg
->layouter
= generic_dialog_layouter
;
325 value
= get_dialog_offset(dlg
, EDIT_WIDGETS_COUNT
);
326 safe_strncpy(value
, tvalue
.source
, MAX_STR_LEN
);
327 done_string(&tvalue
);
329 name
= straconcat(_("Name", term
), ": ", option
->name
, "\n",
330 _("Type", term
), ": ",
331 _(option_types
[option
->type
].name
, term
),
332 (unsigned char *) NULL
);
333 desc
= straconcat(_("Description", term
), ": \n",
334 _(option
->desc
? option
->desc
335 : (unsigned char *) "N/A", term
),
336 (unsigned char *) NULL
);
337 range
= get_range_string(option
);
342 tmp
= straconcat(name
, " ", range
,
343 (unsigned char *) NULL
);
352 if (!name
|| !desc
) {
359 /* FIXME: Compute some meaningful maximal width. --pasky */
360 add_dlg_text(dlg
, name
, ALIGN_LEFT
, 0);
361 add_dlg_field_float(dlg
, _("Value", term
), 0, 0, check_valid_option
, MAX_STR_LEN
, value
, NULL
);
363 add_dlg_text(dlg
, desc
, ALIGN_LEFT
, 0);
365 add_dlg_button(dlg
, _("~OK", term
), B_ENTER
, ok_dialog
, NULL
);
366 add_dlg_button(dlg
, _("~Cancel", term
), B_ESC
, cancel_dialog
, NULL
);
368 add_dlg_end(dlg
, EDIT_WIDGETS_COUNT
);
370 do_dialog(term
, dlg
, getml(dlg
, (void *) name
, (void *) desc
, (void *) NULL
));
371 #undef EDIT_WIDGETS_COUNT
374 static widget_handler_status_T
375 push_edit_button(struct dialog_data
*dlg_data
,
376 struct widget_data
*some_useless_info_button
)
378 struct terminal
*term
= dlg_data
->win
->term
;
379 struct listbox_data
*box
= get_dlg_listbox_data(dlg_data
);
380 struct option
*option
;
382 /* Show history item info */
383 if (!box
->sel
|| !box
->sel
->udata
) return EVENT_PROCESSED
;
384 option
= box
->sel
->udata
;
386 if (!option_types
[option
->type
].write
||
387 !option_types
[option
->type
].read
||
388 !option_types
[option
->type
].set
) {
390 N_("Edit"), ALIGN_LEFT
,
391 N_("This option cannot be edited. This means that "
392 "this is some special option like a folder - try "
393 "to press a space in order to see its contents."));
394 return EVENT_PROCESSED
;
397 build_edit_dialog(term
, dlg_data
->dlg
->udata
, option
);
399 return EVENT_PROCESSED
;
403 struct add_option_to_tree_ctx
{
404 struct option
*option
;
405 struct widget_data
*widget_data
;
409 add_option_to_tree(void *data
, unsigned char *name
)
411 struct add_option_to_tree_ctx
*ctx
= data
;
412 struct option
*old
= get_opt_rec_real(ctx
->option
, name
);
415 if (old
&& (old
->flags
& OPT_DELETED
)) delete_option(old
);
416 /* get_opt_rec() will create the option. */
417 new = get_opt_rec(ctx
->option
, name
);
418 if (new) listbox_sel(ctx
->widget_data
, new->box_item
);
419 /* TODO: If the return value is NULL, we should pop up a msgbox. */
422 static widget_handler_status_T
423 check_option_name(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
427 for (p
= widget_data
->cdata
; *p
; p
++)
428 /* Not '*' since it is used internally. */
430 /* FIXME: Encode '.' into '*'? */
431 info_box(dlg_data
->win
->term
, 0,
432 N_("Bad string"), ALIGN_CENTER
,
433 N_("Option names may only contain alpha-numeric characters\n"
434 "in addition to '_' and '-'."));
435 return EVENT_NOT_PROCESSED
;
438 return EVENT_PROCESSED
;
441 static widget_handler_status_T
442 push_add_button(struct dialog_data
*dlg_data
,
443 struct widget_data
*some_useless_info_button
)
445 struct terminal
*term
= dlg_data
->win
->term
;
446 struct listbox_data
*box
= get_dlg_listbox_data(dlg_data
);
447 struct listbox_item
*item
= box
->sel
;
448 struct option
*option
;
449 struct add_option_to_tree_ctx
*ctx
;
451 if (!item
|| !item
->udata
) {
454 info_box(term
, 0, N_("Add option"), ALIGN_CENTER
,
455 N_("Cannot add an option here."));
456 return EVENT_PROCESSED
;
460 if (item
->type
== BI_FOLDER
&& !item
->expanded
) {
461 item
= box
->ops
->get_root(item
);
462 if (!item
|| !item
->udata
)
466 option
= item
->udata
;
468 if (!(option
->flags
& OPT_AUTOCREATE
)) {
469 if (option
->root
) option
= option
->root
;
470 if (!option
|| !(option
->flags
& OPT_AUTOCREATE
))
474 ctx
= mem_alloc(sizeof(*ctx
));
475 if (!ctx
) return EVENT_PROCESSED
;
476 ctx
->option
= option
;
477 ctx
->widget_data
= dlg_data
->widgets_data
;
479 input_dialog(term
, getml(ctx
, (void *) NULL
), N_("Add option"), N_("Name"),
481 MAX_STR_LEN
, "", 0, 0, check_option_name
,
482 add_option_to_tree
, NULL
);
484 return EVENT_PROCESSED
;
488 static widget_handler_status_T
489 push_save_button(struct dialog_data
*dlg_data
,
490 struct widget_data
*some_useless_info_button
)
492 write_config(dlg_data
->win
->term
);
494 update_hierbox_browser(&option_browser
);
496 return EVENT_PROCESSED
;
500 static const struct hierbox_browser_button option_buttons
[] = {
501 /* [gettext_accelerator_context(.option_buttons)] */
502 { N_("~Info"), push_hierbox_info_button
, 1 },
503 { N_("~Edit"), push_edit_button
, 0 },
504 { N_("~Add"), push_add_button
, 0 },
505 { N_("~Delete"), push_hierbox_delete_button
, 0 },
506 { N_("~Search"), push_hierbox_search_button
, 1 },
507 { N_("Sa~ve"), push_save_button
, 0 },
510 struct_hierbox_browser(
512 N_("Option manager"),
517 /* Builds the "Options manager" dialog */
519 options_manager(struct session
*ses
)
521 hierbox_browser(&option_browser
, ses
);
525 /****************************************************************************
526 Keybinding manager stuff.
527 ****************************************************************************/
530 static int keybinding_text_toggle
= 1;
532 static int keybinding_text_toggle
;
535 /* XXX: ACTION_BOX_SIZE is just a quick hack, we ought to allocate
536 * the sub-arrays separately. --pasky */
537 #define ACTION_BOX_SIZE 128
538 static struct listbox_item
*action_box_items
[KEYMAP_MAX
][ACTION_BOX_SIZE
];
540 struct listbox_item
*
541 get_keybinding_action_box_item(enum keymap_id keymap_id
, action_id_T action_id
)
543 assert(action_id
< ACTION_BOX_SIZE
);
544 if_assert_failed
return NULL
;
546 return action_box_items
[keymap_id
][action_id
];
549 struct listbox_item
*keymap_box_item
[KEYMAP_MAX
];
552 init_keybinding_listboxes(struct keymap keymap_table
[KEYMAP_MAX
],
553 const struct action_list actions
[])
555 struct listbox_item
*root
= &keybinding_browser
.root
;
556 const struct action
*act
;
557 enum keymap_id keymap_id
;
559 /* Do it backwards because add_listbox_item() add to front
561 for (keymap_id
= 0; keymap_id
< KEYMAP_MAX
; keymap_id
++) {
562 struct listbox_item
*keymap_box
;
564 keymap_box
= add_listbox_item(NULL
, root
, BI_FOLDER
, &keymap_table
[keymap_id
], -1);
565 if (!keymap_box
) continue;
567 for (act
= actions
[keymap_id
].actions
; act
->str
; act
++) {
568 struct listbox_item
*item
;
570 assert(act
->num
< ACTION_BOX_SIZE
);
571 if_assert_failed
continue;
573 if (act
->num
== ACT_MAIN_SCRIPTING_FUNCTION
574 || act
->num
== ACT_MAIN_NONE
)
581 item
= add_listbox_item(NULL
, keymap_box
, BI_FOLDER
,
587 action_box_items
[keymap_id
][act
->num
] = item
;
590 keymap_box_item
[keymap_id
] = keymap_box
;
595 done_keybinding_listboxes(void)
597 struct listbox_item
*action
;
599 foreach (action
, keybinding_browser
.root
.child
) {
600 struct listbox_item
*keymap
;
602 foreach (keymap
, action
->child
) {
603 free_list(keymap
->child
);
605 free_list(action
->child
);
607 free_list(keybinding_browser
.root
.child
);
611 /* Implementation of the listbox operations */
613 /* XXX: If anything but delete button will use these object_*() requiring
614 * functions we have to check if it is action or keymap box items. */
617 lock_keybinding(struct listbox_item
*item
)
619 if (item
->depth
== 2)
620 object_lock((struct keybinding
*) item
->udata
);
624 unlock_keybinding(struct listbox_item
*item
)
626 if (item
->depth
== 2)
627 object_unlock((struct keybinding
*) item
->udata
);
631 is_keybinding_used(struct listbox_item
*item
)
633 if (item
->depth
!= 2) return 0;
634 return is_object_used((struct keybinding
*) item
->udata
);
637 static unsigned char *
638 get_keybinding_text(struct listbox_item
*item
, struct terminal
*term
)
640 struct keybinding
*keybinding
= item
->udata
;
643 if (item
->depth
== 0) {
644 struct keymap
*keymap
= item
->udata
;
646 return stracpy(keybinding_text_toggle
? keymap
->str
647 : _(keymap
->desc
, term
));
648 } else if (item
->depth
< 2) {
649 const struct action
*action
= item
->udata
;
651 return stracpy(keybinding_text_toggle
? action
->str
652 : _(action
->desc
, term
));
655 if (!init_string(&info
)) return NULL
;
656 add_keystroke_to_string(&info
, &keybinding
->kbd
, 0);
660 static unsigned char *
661 get_keybinding_info(struct listbox_item
*item
, struct terminal
*term
)
663 struct keybinding
*keybinding
= item
->udata
;
664 unsigned char *action
, *keymap
;
667 if (item
->depth
< 2) return NULL
;
668 if (item
->type
== BI_FOLDER
) return NULL
;
670 if (!init_string(&info
))
673 action
= get_action_name(keybinding
->keymap_id
, keybinding
->action_id
);
674 keymap
= get_keymap_name(keybinding
->keymap_id
);
676 add_format_to_string(&info
, "%s: ", _("Keystroke", term
));
677 add_keystroke_to_string(&info
, &keybinding
->kbd
, 0);
678 add_format_to_string(&info
, "\n%s: %s", _("Action", term
), action
);
679 add_format_to_string(&info
, "\n%s: %s", _("Keymap", term
), keymap
);
684 static struct listbox_item
*
685 get_keybinding_root(struct listbox_item
*item
)
687 /* .. at the bottom */
688 if (item
->depth
== 0) return NULL
;
690 if (item
->depth
== 1) {
691 const struct action
*action
= item
->udata
;
693 return keymap_box_item
[action
->keymap_id
];
695 struct keybinding
*kb
= item
->udata
;
697 return get_keybinding_action_box_item(kb
->keymap_id
, kb
->action_id
);
701 static enum listbox_match
702 match_keybinding(struct listbox_item
*item
, struct terminal
*term
,
705 const struct action
*action
= item
->udata
;
708 if (item
->depth
!= 1)
709 return LISTBOX_MATCH_IMPOSSIBLE
;
711 desc
= keybinding_text_toggle
712 ? action
->str
: _(action
->desc
, term
);
714 if ((desc
&& strcasestr(desc
, text
)))
715 return LISTBOX_MATCH_OK
;
717 return LISTBOX_MATCH_NO
;
721 can_delete_keybinding(struct listbox_item
*item
)
723 return item
->depth
== 2;
728 delete_keybinding_item(struct listbox_item
*item
, int last
)
730 struct keybinding
*keybinding
= item
->udata
;
732 assert(item
->depth
== 2 && !is_object_used(keybinding
));
734 free_keybinding(keybinding
);
737 static const struct listbox_ops keybinding_listbox_ops
= {
746 can_delete_keybinding
,
747 delete_keybinding_item
,
753 struct kbdbind_add_hop
{
754 struct terminal
*term
;
755 action_id_T action_id
;
756 enum keymap_id keymap_id
;
757 struct term_event_keyboard kbd
;
758 struct widget_data
*widget_data
;
761 static struct kbdbind_add_hop
*
762 new_hop_from(struct kbdbind_add_hop
*hop
)
764 struct kbdbind_add_hop
*new_hop
= mem_alloc(sizeof(*new_hop
));
767 copy_struct(new_hop
, hop
);
773 really_really_add_keybinding(void *data
)
775 struct kbdbind_add_hop
*hop
= data
;
776 struct keybinding
*keybinding
;
780 keybinding
= add_keybinding(hop
->keymap_id
, hop
->action_id
, &hop
->kbd
,
783 if (keybinding
&& keybinding
->box_item
)
784 listbox_sel(hop
->widget_data
, keybinding
->box_item
);
788 really_add_keybinding(void *data
, unsigned char *keystroke
)
790 /* [gettext_accelerator_context(.really_add_keybinding.yn)] */
791 struct kbdbind_add_hop
*hop
= data
;
792 action_id_T action_id
;
794 /* check_keystroke() has parsed @keystroke to @hop->kbd. */
795 if (keybinding_exists(hop
->keymap_id
, &hop
->kbd
, &action_id
)
796 && action_id
!= ACT_MAIN_NONE
) {
797 struct kbdbind_add_hop
*new_hop
;
798 struct string canonical
;
800 /* Same keystroke for same action, just return. */
801 if (action_id
== hop
->action_id
) return;
803 /* @*hop is on the memory_list of the input_dialog,
804 * which will be closed when this function returns. */
805 new_hop
= new_hop_from(hop
);
806 if (!new_hop
) return; /* out of mem */
808 /* Try to convert the parsed keystroke back to a
809 * string, so that the "Keystroke already used" box
810 * displays the same canonical name as the keybinding
811 * manager does. If something goes wrong here, then
812 * canonical.length will probably be 0, in which case
813 * we'll use the original @keystroke string instead. */
814 if (init_string(&canonical
))
815 add_keystroke_to_string(&canonical
, &hop
->kbd
, 0);
817 msg_box(new_hop
->term
, getml(new_hop
, (void *) NULL
), MSGBOX_FREE_TEXT
,
818 N_("Keystroke already used"), ALIGN_CENTER
,
819 msg_text(new_hop
->term
, N_("The keystroke \"%s\" "
820 "is currently used for \"%s\".\n"
821 "Are you sure you want to replace it?"),
822 canonical
.length
? canonical
.source
: keystroke
,
823 get_action_name(hop
->keymap_id
, action_id
)),
825 MSG_BOX_BUTTON(N_("~Yes"), really_really_add_keybinding
, B_ENTER
),
826 MSG_BOX_BUTTON(N_("~No"), NULL
, B_ESC
));
828 done_string(&canonical
); /* safe even if init failed */
832 really_really_add_keybinding((void *) hop
);
835 static widget_handler_status_T
836 check_keystroke(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
838 struct kbdbind_add_hop
*hop
= dlg_data
->dlg
->udata2
;
839 unsigned char *keystroke
= widget_data
->cdata
;
841 if (parse_keystroke(keystroke
, &hop
->kbd
) >= 0)
842 return EVENT_PROCESSED
;
844 info_box(hop
->term
, 0, N_("Add keybinding"), ALIGN_CENTER
,
845 N_("Invalid keystroke."));
847 return EVENT_NOT_PROCESSED
;
850 static widget_handler_status_T
851 push_kbdbind_add_button(struct dialog_data
*dlg_data
,
852 struct widget_data
*some_useless_info_button
)
854 struct terminal
*term
= dlg_data
->win
->term
;
855 struct listbox_data
*box
= get_dlg_listbox_data(dlg_data
);
856 struct listbox_item
*item
= box
->sel
;
857 struct kbdbind_add_hop
*hop
;
860 if (!item
|| !item
->depth
) {
861 info_box(term
, 0, N_("Add keybinding"), ALIGN_CENTER
,
862 N_("Need to select an action."));
863 return EVENT_PROCESSED
;
866 hop
= mem_calloc(1, sizeof(*hop
));
867 if (!hop
) return EVENT_PROCESSED
;
869 hop
->widget_data
= dlg_data
->widgets_data
;
871 if (item
->depth
== 2) {
872 struct keybinding
*keybinding
= item
->udata
;
874 hop
->action_id
= keybinding
->action_id
;
875 hop
->keymap_id
= keybinding
->keymap_id
;
877 const struct action
*action
= item
->udata
;
879 hop
->action_id
= action
->num
;
880 hop
->keymap_id
= action
->keymap_id
;
883 text
= msg_text(term
,
887 "Keystroke should be written in the format: "
888 "[Shift-][Ctrl-][Alt-]Key\n"
889 "Key: a,b,c,...,1,2,3,...,Space,Up,PageDown,"
890 "Tab,Enter,Insert,F5,..."
893 get_action_name(hop
->keymap_id
, hop
->action_id
),
894 get_keymap_name(hop
->keymap_id
));
896 input_dialog(term
, getml(hop
, (void *) text
, (void *) NULL
),
897 N_("Add keybinding"), text
,
899 MAX_STR_LEN
, "", 0, 0, check_keystroke
,
900 really_add_keybinding
, NULL
);
902 return EVENT_PROCESSED
;
906 static widget_handler_status_T
907 push_kbdbind_toggle_display_button(struct dialog_data
*dlg_data
,
908 struct widget_data
*some_useless_info_button
)
911 keybinding_text_toggle
= !keybinding_text_toggle
;
912 redraw_dialog(dlg_data
, 0);
914 return EVENT_PROCESSED
;
918 /* FIXME: Races here, we need to lock the entry..? --pasky */
920 static widget_handler_status_T
921 push_kbdbind_save_button(struct dialog_data
*dlg_data
,
922 struct widget_data
*some_useless_info_button
)
924 write_config(dlg_data
->win
->term
);
925 return EVENT_PROCESSED
;
929 static const struct hierbox_browser_button keybinding_buttons
[] = {
930 /* [gettext_accelerator_context(.keybinding_buttons)] */
931 { N_("~Add"), push_kbdbind_add_button
, 0 },
932 { N_("~Delete"), push_hierbox_delete_button
, 0 },
933 { N_("~Toggle display"), push_kbdbind_toggle_display_button
, 1 },
934 { N_("~Search"), push_hierbox_search_button
, 1 },
935 { N_("Sa~ve"), push_kbdbind_save_button
, 0 },
938 struct_hierbox_browser(
940 N_("Keybinding manager"),
942 &keybinding_listbox_ops
945 /* Builds the "Keybinding manager" dialog */
947 keybinding_manager(struct session
*ses
)
949 hierbox_browser(&keybinding_browser
, ses
);