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 toggle_success_msgbox(void *dummy
)
37 /* TODO: option_changed() */
38 get_opt_bool("ui.success_msgbox") = !get_opt_bool("ui.success_msgbox");
39 get_opt_rec(config_options
, "ui.success_msgbox")->flags
|= OPT_TOUCHED
;
43 write_config_dialog(struct terminal
*term
, unsigned char *config_file
,
44 int secsave_error
, int stdio_error
)
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")) 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 N_("~OK"), NULL
, B_ENTER
| B_ESC
,
58 N_("~Do not show anymore"), toggle_success_msgbox
, 0);
62 switch (secsave_error
) {
63 case SS_ERR_OPEN_READ
:
64 strerr
= _("Cannot read the file", term
);
67 strerr
= _("Cannot get file status", term
);
70 strerr
= _("Cannot access the file", term
);
73 strerr
= _("Cannot create temp file", term
);
76 strerr
= _("Cannot rename the file", term
);
79 strerr
= _("File saving disabled by option", term
);
81 case SS_ERR_OUT_OF_MEM
:
82 strerr
= _("Out of memory", term
);
84 case SS_ERR_OPEN_WRITE
:
85 strerr
= _("Cannot write the file", term
);
87 case SS_ERR_NONE
: /* Impossible. */
90 strerr
= _("Secure file saving error", term
);
95 errmsg
= straconcat(strerr
, " (", strerror(stdio_error
), ")", NULL
);
97 info_box(term
, MSGBOX_FREE_TEXT
,
98 N_("Write config error"), ALIGN_CENTER
,
99 msg_text(term
, N_("Unable to write to config file %s.\n%s"),
100 config_file
, errmsg
? errmsg
: strerr
));
107 /****************************************************************************
108 Option manager stuff.
109 ****************************************************************************/
111 /* Implementation of the listbox operations */
114 lock_option(struct listbox_item
*item
)
116 object_lock((struct option
*) item
->udata
);
120 unlock_option(struct listbox_item
*item
)
122 object_unlock((struct option
*) item
->udata
);
126 is_option_used(struct listbox_item
*item
)
128 return is_object_used((struct option
*) item
->udata
);
131 static unsigned char *
132 get_range_string(struct option
*option
)
136 if (!init_string(&info
)) return NULL
;
138 if (option
->type
== OPT_BOOL
)
139 add_to_string(&info
, "[0|1]");
140 else if (option
->type
== OPT_INT
|| option
->type
== OPT_LONG
)
141 add_format_to_string(&info
, "[%li..%li]", option
->min
, option
->max
);
146 static unsigned char *
147 get_option_text(struct listbox_item
*item
, struct terminal
*term
)
149 struct option
*option
= item
->udata
;
150 unsigned char *desc
= option
->capt
? option
->capt
: option
->name
;
152 if (option
->flags
& OPT_TOUCHED
)
153 return straconcat(_(desc
, term
),
154 " (", _("modified", term
), ")", NULL
);
156 return stracpy(_(desc
, term
));
159 static unsigned char *
160 get_option_info(struct listbox_item
*item
, struct terminal
*term
)
162 struct option
*option
= item
->udata
;
163 unsigned char *desc
, *type
;
166 if (!init_string(&info
)) return NULL
;
168 add_format_to_string(&info
, "%s: %s", _("Name", term
), option
->name
);
170 type
= _(option_types
[option
->type
].name
, term
);
171 if (option
->type
== OPT_TREE
) {
172 type
= straconcat(type
, " ",
173 _("(expand by pressing space)", term
), NULL
);
176 add_format_to_string(&info
, "\n%s: %s", _("Type", term
), type
);
178 if (option
->type
== OPT_TREE
) {
182 if (option_types
[option
->type
].write
) {
183 unsigned char *range
;
186 if (!init_string(&value
)) {
191 option_types
[option
->type
].write(option
, &value
);
193 range
= get_range_string(option
);
196 add_to_string(&info
, " ");
197 add_to_string(&info
, range
);
201 add_format_to_string(&info
, "\n%s: %s", _("Value", term
), value
.source
);
204 if (option
->flags
& OPT_TOUCHED
)
205 add_to_string(&info
, _("\n\nThis value has been changed"
206 " since you last saved your"
207 " configuration.", term
));
211 desc
= _(option
->desc
? option
->desc
: (unsigned char *) "N/A", term
);
213 add_format_to_string(&info
, "\n\n%s:\n%s", _("Description", term
), desc
);
218 static struct listbox_item
*
219 get_option_root(struct listbox_item
*item
)
221 struct option
*option
= item
->udata
;
223 /* The config_options root has no listbox so return that
224 * we are at the bottom. */
225 if (option
->root
== config_options
) return NULL
;
227 return option
->root
? option
->root
->box_item
: NULL
;
230 static enum listbox_match
231 match_option(struct listbox_item
*item
, struct terminal
*term
,
234 struct option
*option
= item
->udata
;
236 if (option
->type
== OPT_TREE
)
237 return LISTBOX_MATCH_IMPOSSIBLE
;
239 if (strcasestr(option
->name
, text
)
240 || (option
->capt
&& strcasestr(_(option
->capt
, term
), text
)))
241 return LISTBOX_MATCH_OK
;
243 return LISTBOX_MATCH_NO
;
247 can_delete_option(struct listbox_item
*item
)
249 struct option
*option
= item
->udata
;
252 struct option
*parent_option
= option
->root
;
254 return parent_option
->flags
& OPT_AUTOCREATE
;
261 delete_option_item(struct listbox_item
*item
, int last
)
263 struct option
*option
= item
->udata
;
265 assert(!is_object_used(option
));
267 /* Only built-in options needs to be marked as deleted, so if the
268 * option is allocated call the cleaner. */
269 if (option
->flags
& OPT_ALLOC
)
270 delete_option(option
);
272 mark_option_as_deleted(option
);
275 static struct listbox_ops options_listbox_ops
= {
290 /* Button handlers */
292 static widget_handler_status_T
293 check_valid_option(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
295 struct terminal
*term
= dlg_data
->win
->term
;
296 struct option
*option
= dlg_data
->dlg
->udata
;
297 struct session
*ses
= dlg_data
->dlg
->udata2
;
298 unsigned char *value
= widget_data
->cdata
;
299 unsigned char *chinon
;
303 chinon
= option_types
[option
->type
].read(option
, &value
, &dummy_line
);
305 if (option_types
[option
->type
].set
&&
306 option_types
[option
->type
].set(option
, chinon
)) {
307 struct option
*current
= option
;
309 option_changed(ses
, current
, option
);
313 return EVENT_PROCESSED
;
320 N_("Error"), ALIGN_LEFT
,
321 N_("Bad option value."));
323 return EVENT_NOT_PROCESSED
;
327 build_edit_dialog(struct terminal
*term
, struct session
*ses
,
328 struct option
*option
)
330 #define EDIT_WIDGETS_COUNT 5
332 unsigned char *value
, *name
, *desc
, *range
;
333 struct string tvalue
;
335 if (!init_string(&tvalue
)) return;
338 option_types
[option
->type
].write(option
, &tvalue
);
341 /* Create the dialog */
342 dlg
= calloc_dialog(EDIT_WIDGETS_COUNT
, MAX_STR_LEN
);
344 done_string(&tvalue
);
348 dlg
->title
= _("Edit", term
);
349 dlg
->layouter
= generic_dialog_layouter
;
353 value
= get_dialog_offset(dlg
, EDIT_WIDGETS_COUNT
);
354 safe_strncpy(value
, tvalue
.source
, MAX_STR_LEN
);
355 done_string(&tvalue
);
357 name
= straconcat(_("Name", term
), ": ", option
->name
, "\n",
358 _("Type", term
), ": ",
359 _(option_types
[option
->type
].name
, term
), NULL
);
360 desc
= straconcat(_("Description", term
), ": \n",
361 _(option
->desc
? option
->desc
362 : (unsigned char *) "N/A", term
),
364 range
= get_range_string(option
);
369 tmp
= straconcat(name
, " ", range
, NULL
);
378 if (!name
|| !desc
) {
385 /* FIXME: Compute some meaningful maximal width. --pasky */
386 add_dlg_text(dlg
, name
, ALIGN_LEFT
, 0);
387 add_dlg_field_float(dlg
, _("Value", term
), 0, 0, check_valid_option
, MAX_STR_LEN
, value
, NULL
);
389 add_dlg_text(dlg
, desc
, ALIGN_LEFT
, 0);
391 add_dlg_button(dlg
, _("~OK", term
), B_ENTER
, ok_dialog
, NULL
);
392 add_dlg_button(dlg
, _("~Cancel", term
), B_ESC
, cancel_dialog
, NULL
);
394 add_dlg_end(dlg
, EDIT_WIDGETS_COUNT
);
396 do_dialog(term
, dlg
, getml(dlg
, name
, desc
, NULL
));
397 #undef EDIT_WIDGETS_COUNT
400 static widget_handler_status_T
401 push_edit_button(struct dialog_data
*dlg_data
,
402 struct widget_data
*some_useless_info_button
)
404 struct terminal
*term
= dlg_data
->win
->term
;
405 struct listbox_data
*box
= get_dlg_listbox_data(dlg_data
);
406 struct option
*option
;
408 /* Show history item info */
409 if (!box
->sel
|| !box
->sel
->udata
) return EVENT_PROCESSED
;
410 option
= box
->sel
->udata
;
412 if (!option_types
[option
->type
].write
||
413 !option_types
[option
->type
].read
||
414 !option_types
[option
->type
].set
) {
416 N_("Edit"), ALIGN_LEFT
,
417 N_("This option cannot be edited. This means that "
418 "this is some special option like a folder - try "
419 "to press a space in order to see its contents."));
420 return EVENT_PROCESSED
;
423 build_edit_dialog(term
, dlg_data
->dlg
->udata
, option
);
425 return EVENT_PROCESSED
;
429 struct add_option_to_tree_ctx
{
430 struct option
*option
;
431 struct widget_data
*widget_data
;
435 add_option_to_tree(void *data
, unsigned char *name
)
437 struct add_option_to_tree_ctx
*ctx
= data
;
438 struct option
*old
= get_opt_rec_real(ctx
->option
, name
);
441 if (old
&& (old
->flags
& OPT_DELETED
)) delete_option(old
);
442 /* get_opt_rec() will create the option. */
443 new = get_opt_rec(ctx
->option
, name
);
444 if (new) listbox_sel(ctx
->widget_data
, new->box_item
);
445 /* TODO: If the return value is NULL, we should pop up a msgbox. */
448 static widget_handler_status_T
449 check_option_name(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
453 for (p
= widget_data
->cdata
; *p
; p
++)
454 /* Not '*' since it is used internally. */
456 /* FIXME: Encode '.' into '*'? */
457 info_box(dlg_data
->win
->term
, 0,
458 N_("Bad string"), ALIGN_CENTER
,
459 N_("Option names may only contain alpha-numeric characters\n"
460 "in addition to '_' and '-'."));
461 return EVENT_NOT_PROCESSED
;
464 return EVENT_PROCESSED
;
466 static widget_handler_status_T
467 push_add_button(struct dialog_data
*dlg_data
,
468 struct widget_data
*some_useless_info_button
)
470 struct terminal
*term
= dlg_data
->win
->term
;
471 struct listbox_data
*box
= get_dlg_listbox_data(dlg_data
);
472 struct listbox_item
*item
= box
->sel
;
473 struct option
*option
;
474 struct add_option_to_tree_ctx
*ctx
;
476 if (!item
|| !item
->udata
) {
479 info_box(term
, 0, N_("Add option"), ALIGN_CENTER
,
480 N_("Cannot add an option here."));
481 return EVENT_PROCESSED
;
485 if (item
->type
== BI_FOLDER
&& !item
->expanded
) {
486 item
= box
->ops
->get_root(item
);
487 if (!item
|| !item
->udata
)
491 option
= item
->udata
;
493 if (!(option
->flags
& OPT_AUTOCREATE
)) {
494 if (option
->root
) option
= option
->root
;
495 if (!option
|| !(option
->flags
& OPT_AUTOCREATE
))
499 ctx
= mem_alloc(sizeof(*ctx
));
500 if (!ctx
) return EVENT_PROCESSED
;
501 ctx
->option
= option
;
502 ctx
->widget_data
= dlg_data
->widgets_data
;
504 input_dialog(term
, getml(ctx
, NULL
), N_("Add option"), N_("Name"),
506 MAX_STR_LEN
, "", 0, 0, check_option_name
,
507 add_option_to_tree
, NULL
);
509 return EVENT_PROCESSED
;
513 static widget_handler_status_T
514 push_save_button(struct dialog_data
*dlg_data
,
515 struct widget_data
*some_useless_info_button
)
517 write_config(dlg_data
->win
->term
);
519 update_hierbox_browser(&option_browser
);
521 return EVENT_PROCESSED
;
525 static struct hierbox_browser_button option_buttons
[] = {
526 { N_("~Info"), push_hierbox_info_button
, 1 },
527 { N_("~Edit"), push_edit_button
, 0 },
528 { N_("~Add"), push_add_button
, 0 },
529 { N_("~Delete"), push_hierbox_delete_button
, 0 },
530 { N_("~Search"), push_hierbox_search_button
, 1 },
531 { N_("Sa~ve"), push_save_button
, 0 },
534 struct_hierbox_browser(
536 N_("Option manager"),
541 /* Builds the "Options manager" dialog */
543 options_manager(struct session
*ses
)
545 hierbox_browser(&option_browser
, ses
);
549 /****************************************************************************
550 Keybinding manager stuff.
551 ****************************************************************************/
554 static int keybinding_text_toggle
= 1;
556 static int keybinding_text_toggle
;
559 /* XXX: ACTION_BOX_SIZE is just a quick hack, we ought to allocate
560 * the sub-arrays separately. --pasky */
561 #define ACTION_BOX_SIZE 128
562 static struct listbox_item
*action_box_items
[KEYMAP_MAX
][ACTION_BOX_SIZE
];
564 struct listbox_item
*
565 get_keybinding_action_box_item(enum keymap_id keymap_id
, action_id_T action_id
)
567 assert(action_id
< ACTION_BOX_SIZE
);
568 if_assert_failed
return NULL
;
570 return action_box_items
[keymap_id
][action_id
];
573 struct listbox_item
*keymap_box_item
[KEYMAP_MAX
];
576 init_keybinding_listboxes(struct keymap keymap_table
[KEYMAP_MAX
], struct action_list actions
[])
578 struct listbox_item
*root
= &keybinding_browser
.root
;
580 enum keymap_id keymap_id
;
582 /* Do it backwards because add_listbox_item() add to front
584 for (keymap_id
= 0; keymap_id
< KEYMAP_MAX
; keymap_id
++) {
585 struct listbox_item
*keymap_box
;
587 keymap_box
= add_listbox_item(NULL
, root
, BI_FOLDER
, &keymap_table
[keymap_id
], -1);
588 if (!keymap_box
) continue;
590 for (act
= actions
[keymap_id
].actions
; act
->str
; act
++) {
591 struct listbox_item
*item
;
593 assert(act
->num
< ACTION_BOX_SIZE
);
594 if_assert_failed
continue;
596 if (act
->num
== ACT_MAIN_SCRIPTING_FUNCTION
597 || act
->num
== ACT_MAIN_NONE
)
604 item
= add_listbox_item(NULL
, keymap_box
, BI_FOLDER
, act
, -1);
609 action_box_items
[keymap_id
][act
->num
] = item
;
612 keymap_box_item
[keymap_id
] = keymap_box
;
617 done_keybinding_listboxes(void)
619 struct listbox_item
*action
;
621 foreach (action
, keybinding_browser
.root
.child
) {
622 struct listbox_item
*keymap
;
624 foreach (keymap
, action
->child
) {
625 free_list(keymap
->child
);
627 free_list(action
->child
);
629 free_list(keybinding_browser
.root
.child
);
633 /* Implementation of the listbox operations */
635 /* XXX: If anything but delete button will use these object_*() requiring
636 * functions we have to check if it is action or keymap box items. */
639 lock_keybinding(struct listbox_item
*item
)
641 if (item
->depth
== 2)
642 object_lock((struct keybinding
*) item
->udata
);
646 unlock_keybinding(struct listbox_item
*item
)
648 if (item
->depth
== 2)
649 object_unlock((struct keybinding
*) item
->udata
);
653 is_keybinding_used(struct listbox_item
*item
)
655 if (item
->depth
!= 2) return 0;
656 return is_object_used((struct keybinding
*) item
->udata
);
659 static unsigned char *
660 get_keybinding_text(struct listbox_item
*item
, struct terminal
*term
)
662 struct keybinding
*keybinding
= item
->udata
;
665 if (item
->depth
== 0) {
666 struct keymap
*keymap
= item
->udata
;
668 return stracpy(keybinding_text_toggle
? keymap
->str
669 : _(keymap
->desc
, term
));
670 } else if (item
->depth
< 2) {
671 struct action
*action
= item
->udata
;
673 return stracpy(keybinding_text_toggle
? action
->str
674 : _(action
->desc
, term
));
677 if (!init_string(&info
)) return NULL
;
678 add_keystroke_to_string(&info
, &keybinding
->kbd
, 0);
682 static unsigned char *
683 get_keybinding_info(struct listbox_item
*item
, struct terminal
*term
)
685 struct keybinding
*keybinding
= item
->udata
;
686 unsigned char *action
, *keymap
;
689 if (item
->depth
< 2) return NULL
;
690 if (item
->type
== BI_FOLDER
) return NULL
;
692 if (!init_string(&info
))
695 action
= get_action_name(keybinding
->keymap_id
, keybinding
->action_id
);
696 keymap
= get_keymap_name(keybinding
->keymap_id
);
698 add_format_to_string(&info
, "%s: ", _("Keystroke", term
));
699 add_keystroke_to_string(&info
, &keybinding
->kbd
, 0);
700 add_format_to_string(&info
, "\n%s: %s", _("Action", term
), action
);
701 add_format_to_string(&info
, "\n%s: %s", _("Keymap", term
), keymap
);
706 static struct listbox_item
*
707 get_keybinding_root(struct listbox_item
*item
)
709 /* .. at the bottom */
710 if (item
->depth
== 0) return NULL
;
712 if (item
->depth
== 1) {
713 struct action
*action
= item
->udata
;
715 return keymap_box_item
[action
->keymap_id
];
717 struct keybinding
*kb
= item
->udata
;
719 return get_keybinding_action_box_item(kb
->keymap_id
, kb
->action_id
);
723 static enum listbox_match
724 match_keybinding(struct listbox_item
*item
, struct terminal
*term
,
727 struct action
*action
= item
->udata
;
730 if (item
->depth
!= 1)
731 return LISTBOX_MATCH_IMPOSSIBLE
;
733 desc
= keybinding_text_toggle
734 ? action
->str
: _(action
->desc
, term
);
736 if ((desc
&& strcasestr(desc
, text
)))
737 return LISTBOX_MATCH_OK
;
739 return LISTBOX_MATCH_NO
;
743 can_delete_keybinding(struct listbox_item
*item
)
745 return item
->depth
== 2;
750 delete_keybinding_item(struct listbox_item
*item
, int last
)
752 struct keybinding
*keybinding
= item
->udata
;
754 assert(item
->depth
== 2 && !is_object_used(keybinding
));
756 free_keybinding(keybinding
);
759 static struct listbox_ops keybinding_listbox_ops
= {
768 can_delete_keybinding
,
769 delete_keybinding_item
,
775 struct kbdbind_add_hop
{
776 struct terminal
*term
;
777 action_id_T action_id
;
778 enum keymap_id keymap_id
;
779 struct term_event_keyboard kbd
;
780 struct widget_data
*widget_data
;
783 struct kbdbind_add_hop
*
784 new_hop_from(struct kbdbind_add_hop
*hop
)
786 struct kbdbind_add_hop
*new_hop
= mem_alloc(sizeof(*new_hop
));
789 copy_struct(new_hop
, hop
);
795 really_really_add_keybinding(void *data
)
797 struct kbdbind_add_hop
*hop
= data
;
798 struct keybinding
*keybinding
;
802 keybinding
= add_keybinding(hop
->keymap_id
, hop
->action_id
, &hop
->kbd
,
805 if (keybinding
&& keybinding
->box_item
)
806 listbox_sel(hop
->widget_data
, keybinding
->box_item
);
810 really_add_keybinding(void *data
, unsigned char *keystroke
)
812 struct kbdbind_add_hop
*hop
= data
;
813 action_id_T action_id
;
815 if (keybinding_exists(hop
->keymap_id
, &hop
->kbd
, &action_id
)
816 && action_id
!= ACT_MAIN_NONE
) {
817 struct kbdbind_add_hop
*new_hop
;
819 /* Same keystroke for same action, just return. */
820 if (action_id
== hop
->action_id
) return;
822 new_hop
= new_hop_from(hop
);
823 if (!new_hop
) return; /* out of mem */
825 msg_box(new_hop
->term
, getml(new_hop
, NULL
), MSGBOX_FREE_TEXT
,
826 N_("Keystroke already used"), ALIGN_CENTER
,
827 msg_text(new_hop
->term
, N_("The keystroke \"%s\" "
828 "is currently used for \"%s\".\n"
829 "Are you sure you want to replace it?"),
830 keystroke
, get_action_name(hop
->keymap_id
, action_id
)),
832 N_("~Yes"), really_really_add_keybinding
, B_ENTER
,
833 N_("~No"), NULL
, B_ESC
);
838 really_really_add_keybinding((void *) hop
);
841 widget_handler_status_T
842 check_keystroke(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
844 struct kbdbind_add_hop
*hop
= dlg_data
->dlg
->udata2
;
845 unsigned char *keystroke
= widget_data
->cdata
;
847 if (parse_keystroke(keystroke
, &hop
->kbd
) >= 0)
848 return EVENT_PROCESSED
;
850 info_box(hop
->term
, 0, N_("Add keybinding"), ALIGN_CENTER
,
851 N_("Invalid keystroke."));
853 return EVENT_NOT_PROCESSED
;
856 static widget_handler_status_T
857 push_kbdbind_add_button(struct dialog_data
*dlg_data
,
858 struct widget_data
*some_useless_info_button
)
860 struct terminal
*term
= dlg_data
->win
->term
;
861 struct listbox_data
*box
= get_dlg_listbox_data(dlg_data
);
862 struct listbox_item
*item
= box
->sel
;
863 struct kbdbind_add_hop
*hop
;
866 if (!item
|| !item
->depth
) {
867 info_box(term
, 0, N_("Add keybinding"), ALIGN_CENTER
,
868 N_("Need to select a keymap."));
869 return EVENT_PROCESSED
;
872 hop
= mem_calloc(1, sizeof(*hop
));
873 if (!hop
) return EVENT_PROCESSED
;
875 hop
->widget_data
= dlg_data
->widgets_data
;
877 if (item
->depth
== 2) {
878 struct keybinding
*keybinding
= item
->udata
;
880 hop
->action_id
= keybinding
->action_id
;
881 hop
->keymap_id
= keybinding
->keymap_id
;
883 struct action
*action
= item
->udata
;
885 hop
->action_id
= action
->num
;
886 hop
->keymap_id
= action
->keymap_id
;
889 text
= msg_text(term
,
893 "Keystroke should be written in the format: "
895 "Prefix: Shift, Ctrl, Alt\n"
896 "Key: a,b,c,...,1,2,3,...,Space,Up,PageDown,"
897 "Tab,Enter,Insert,F5,..."
900 get_action_name(hop
->keymap_id
, hop
->action_id
),
901 get_keymap_name(hop
->keymap_id
));
903 input_dialog(term
, getml(hop
, text
, NULL
),
904 N_("Add keybinding"), text
,
906 MAX_STR_LEN
, "", 0, 0, check_keystroke
,
907 really_add_keybinding
, NULL
);
909 return EVENT_PROCESSED
;
913 static widget_handler_status_T
914 push_kbdbind_toggle_display_button(struct dialog_data
*dlg_data
,
915 struct widget_data
*some_useless_info_button
)
918 keybinding_text_toggle
= !keybinding_text_toggle
;
919 clear_dialog(dlg_data
, some_useless_info_button
);
921 return EVENT_PROCESSED
;
925 /* FIXME: Races here, we need to lock the entry..? --pasky */
927 static widget_handler_status_T
928 push_kbdbind_save_button(struct dialog_data
*dlg_data
,
929 struct widget_data
*some_useless_info_button
)
931 write_config(dlg_data
->win
->term
);
932 return EVENT_PROCESSED
;
936 static INIT_LIST_HEAD(keybinding_dialog_list
);
938 static struct hierbox_browser_button keybinding_buttons
[] = {
939 { N_("~Add"), push_kbdbind_add_button
, 0 },
940 { N_("~Delete"), push_hierbox_delete_button
, 0 },
941 { N_("~Toggle display"), push_kbdbind_toggle_display_button
, 1 },
942 { N_("~Search"), push_hierbox_search_button
, 1 },
943 { N_("Sa~ve"), push_kbdbind_save_button
, 0 },
946 struct_hierbox_browser(
948 N_("Keybinding manager"),
950 &keybinding_listbox_ops
953 /* Builds the "Keybinding manager" dialog */
955 keybinding_manager(struct session
*ses
)
957 hierbox_browser(&keybinding_browser
, ses
);