grafthistory: support curl
[elinks/elinks-j605.git] / src / bfu / msgbox.c
blob9494bbfab84e004c62498aeb38c34d2d9454ddb3
1 /* Prefabricated message box implementation. */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdarg.h>
9 #include "elinks.h"
11 #include "bfu/dialog.h"
12 #include "bfu/button.h"
13 #include "bfu/msgbox.h"
14 #include "bfu/text.h"
15 #include "intl/gettext/libintl.h"
16 #include "terminal/terminal.h"
17 #include "util/color.h"
18 #include "util/memlist.h"
19 #include "util/memory.h"
20 #include "util/snprintf.h"
21 #include "util/string.h"
24 struct dialog_data *
25 msg_box(struct terminal *term, struct memory_list *ml, enum msgbox_flags flags,
26 unsigned char *title, enum format_align align,
27 unsigned char *text, void *udata, int buttons, ...)
29 struct dialog *dlg;
30 va_list ap;
32 /* Check if the info string is valid. */
33 if (!text || buttons < 0) return NULL;
35 /* Use the @flags to determine whether @text should be free()d. */
36 if (flags & MSGBOX_FREE_TEXT)
37 add_one_to_ml(&ml, text);
39 /* Use the @flags to determine whether strings should be l18n'd. */
40 if (!(flags & MSGBOX_NO_INTL)) {
41 title = _(title, term);
42 if (!(flags & MSGBOX_FREE_TEXT)
43 && !(flags & MSGBOX_NO_TEXT_INTL))
44 text = _(text, term);
45 /* Button labels will be gettextized as will they be extracted
46 * from @ap. */
49 dlg = calloc_dialog(buttons + 1, 0);
50 if (!dlg) {
51 freeml(ml);
52 return NULL;
55 add_one_to_ml(&ml, dlg);
57 dlg->title = title;
58 dlg->layouter = generic_dialog_layouter;
59 dlg->layout.padding_top = 1;
60 dlg->udata2 = udata;
62 if (flags & MSGBOX_SCROLLABLE)
63 dlg->widgets->info.text.is_scrollable = 1;
64 add_dlg_text(dlg, text, align, 0);
66 va_start(ap, buttons);
68 while (dlg->number_of_widgets < buttons + 1) {
69 unsigned char *label;
70 done_handler_T *done;
71 int bflags;
73 label = va_arg(ap, unsigned char *);
74 done = va_arg(ap, void *);
75 bflags = va_arg(ap, int);
77 if (!label) {
78 /* Skip this button. */
79 buttons--;
80 continue;
83 if (!(flags & MSGBOX_NO_INTL))
84 label = _(label, term);
86 add_dlg_ok_button(dlg, label, bflags, done, udata);
89 va_end(ap);
91 add_dlg_end(dlg, buttons + 1);
93 return do_dialog(term, dlg, ml);
96 static inline unsigned char *
97 msg_text_do(unsigned char *format, va_list ap)
99 unsigned char *info;
100 int infolen, len;
101 va_list ap2;
103 VA_COPY(ap2, ap);
105 infolen = vsnprintf(NULL, 0, format, ap2);
106 info = mem_alloc(infolen + 1);
107 if (!info) return NULL;
109 len = vsnprintf((char *) info, infolen + 1, format, ap);
110 if (len != infolen) {
111 mem_free(info);
112 return NULL;
115 /* Wear safety boots */
116 info[infolen] = '\0';
117 return info;
120 unsigned char *
121 msg_text(struct terminal *term, unsigned char *format, ...)
123 unsigned char *info;
124 va_list ap;
126 va_start(ap, format);
127 info = msg_text_do(_(format, term), ap);
128 va_end(ap);
130 return info;
133 static void
134 abort_refreshed_msg_box_handler(struct dialog_data *dlg_data)
136 void *data = dlg_data->dlg->widgets->text;
138 if (dlg_data->dlg->udata != data)
139 mem_free(data);
142 static enum dlg_refresh_code
143 refresh_msg_box(struct dialog_data *dlg_data, void *data)
145 unsigned char *(*get_info)(struct terminal *, void *) = data;
146 void *msg_data = dlg_data->dlg->udata2;
147 unsigned char *info = get_info(dlg_data->win->term, msg_data);
149 if (!info) return REFRESH_CANCEL;
151 abort_refreshed_msg_box_handler(dlg_data);
153 dlg_data->dlg->widgets->text = info;
154 return REFRESH_DIALOG;
157 void
158 refreshed_msg_box(struct terminal *term, enum msgbox_flags flags,
159 unsigned char *title, enum format_align align,
160 unsigned char *(get_info)(struct terminal *, void *),
161 void *data)
163 struct dialog_data *dlg_data;
164 unsigned char *info = get_info(term, data);
166 if (!info) return;
168 dlg_data = msg_box(term, NULL, flags | MSGBOX_FREE_TEXT,
169 title, align,
170 info,
171 data, 1,
172 N_("~OK"), NULL, B_ENTER | B_ESC);
174 if (!dlg_data) return;
176 /* Save the original text to check up on it when the dialog
177 * is freed. */
178 dlg_data->dlg->udata = info;
179 dlg_data->dlg->abort = abort_refreshed_msg_box_handler;
180 refresh_dialog(dlg_data, refresh_msg_box, get_info);
183 struct dialog_data *
184 info_box(struct terminal *term, enum msgbox_flags flags,
185 unsigned char *title, enum format_align align,
186 unsigned char *text)
188 return msg_box(term, NULL, flags, title, align, text,
189 NULL, 1, N_("~OK"), NULL, B_ENTER | B_ESC);