1 /* List menus functions */
14 #include "bfu/listmenu.h"
16 #include "session/session.h"
17 #include "util/conv.h"
18 #include "util/error.h"
19 #include "util/string.h"
20 #include "viewer/text/form.h" /* selected_item() and get_current_state() */
22 /* TODO: massive cleanup, merging, code redundancy tracking between this file
23 * and bfu/menu.c (and perhaps others.)
24 * We should unify and clarify menu-related code. */
27 menu_contains(struct menu_item
*m
, int f
)
29 if (m
->func
!= do_select_submenu
)
30 return (long) m
->data
== f
;
32 foreach_menu_item (m
, m
->data
) {
33 if (menu_contains(m
, f
))
41 do_select_submenu(struct terminal
*term
, void *menu_
, void *ses_
)
43 struct menu_item
*menu
= menu_
;
44 struct session
*ses
= ses_
;
46 int def
= int_max(0, get_current_state(ses
));
49 foreach_menu_item (m
, menu
) {
50 if (menu_contains(m
, def
)) {
56 do_menu_selected(term
, menu
, ses
, sel
, 0);
60 new_menu_item(struct list_menu
*menu
, unsigned char *name
, int data
, int fullname
)
61 /* name == NULL - up; data == -1 - down */
63 struct menu_item
*new_menu_item
= NULL
; /* no uninitialized warnings */
64 struct menu_item
**items
;
65 size_t stack_size
= menu
->stack_size
;
71 } else if (data
!= -1 && menu
->stack_size
== 0) {
84 int size
= (menu
->stack_size
+ 1) * sizeof(*menu
->stack
);
85 struct menu_item
**stack
= mem_realloc(menu
->stack
, size
);
89 new_menu_item
= new_menu(NO_INTL
);
92 if (!stack
|| !new_menu_item
) {
93 if (new_menu_item
) mem_free(new_menu_item
);
98 /* Since we increment @stack_size use cached value */
99 menu
->stack
[menu
->stack_size
++] = new_menu_item
;
101 if (menu
->stack_size
== 1) {
107 items
= &menu
->stack
[stack_size
- 1];
110 add_to_menu(items
, name
, NULL
, ACT_MAIN_NONE
,
112 new_menu_item
, SUBMENU
);
114 add_to_menu(items
, name
, NULL
, ACT_MAIN_NONE
,
116 (void *) (long) data
, (fullname
? MENU_FULLNAME
: 0));
119 if (stack_size
>= 2) {
120 struct menu_item
*below
= menu
->stack
[stack_size
- 2];
122 while (below
->text
) below
++;
123 below
[-1].data
= *items
;
128 init_menu(struct list_menu
*menu
)
130 menu
->stack_size
= 0;
132 new_menu_item(menu
, stracpy(""), -1, 0);
135 /* TODO: merge with free_menu_items() in bfu/menu.h --Zas */
137 free_menu(struct menu_item
*m
) /* Grrr. Recursion */
139 struct menu_item
*mm
;
141 if (!m
) return; /* XXX: Who knows... need to be verified */
143 foreach_menu_item (mm
, m
) {
144 mem_free_if(mm
->text
);
145 if (mm
->func
== do_select_submenu
) free_menu(mm
->data
);
152 detach_menu(struct list_menu
*menu
)
154 struct menu_item
*i
= NULL
;
157 if (menu
->stack_size
) i
= menu
->stack
[0];
158 mem_free(menu
->stack
);
165 destroy_menu(struct list_menu
*menu
)
167 if (menu
->stack
) free_menu(menu
->stack
[0]);
172 menu_labels(struct menu_item
*items
, unsigned char *base
, unsigned char **lbls
)
174 struct menu_item
*item
;
177 foreach_menu_item (item
, items
) {
178 bs
= (item
->flags
& MENU_FULLNAME
) ? (unsigned char *) ""
180 bs
= straconcat(bs
, item
->text
, (unsigned char *) NULL
);
183 if (item
->func
== do_select_submenu
) {
184 add_to_strn(&bs
, " ");
185 menu_labels(item
->data
, bs
, lbls
);
188 assert(item
->func
== selected_item
);
189 lbls
[(long) item
->data
] = bs
;
195 add_select_item(struct list_menu
*menu
, struct string
*string
,
196 struct string
*orig_string
, unsigned char **value
,
197 int order
, int dont_add
)
201 assert(menu
&& string
);
203 if (!string
->source
) return;
205 assert(value
&& pos
>= 0);
208 /* <select> values are not mangled by various encode_*()
209 * functions, therefore we need to store them in the
210 * original document encoding. */
211 value
[pos
] = memacpy(orig_string
->source
, orig_string
->length
);
216 new_menu_item(menu
, string
->source
, pos
, 1);
217 string
->source
= NULL
;
220 done_string(orig_string
);