1 /* Prefabricated message box implementation. */
11 #include "bfu/dialog.h"
12 #include "bfu/button.h"
13 #include "bfu/msgbox.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"
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
, ...)
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
))
45 /* Button labels will be gettextized as will they be extracted
49 dlg
= calloc_dialog(buttons
+ 1, 0);
55 add_one_to_ml(&ml
, dlg
);
58 dlg
->layouter
= generic_dialog_layouter
;
59 dlg
->layout
.padding_top
= 1;
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) {
73 label
= va_arg(ap
, unsigned char *);
74 done
= va_arg(ap
, done_handler_T
*);
75 bflags
= va_arg(ap
, int);
78 /* Skip this button. */
83 if (!(flags
& MSGBOX_NO_INTL
))
84 label
= _(label
, term
);
86 add_dlg_ok_button(dlg
, label
, bflags
, done
, udata
);
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
)
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
) {
115 /* Wear safety boots */
116 info
[infolen
] = '\0';
121 msg_text(struct terminal
*term
, unsigned char *format
, ...)
126 va_start(ap
, format
);
127 info
= msg_text_do(_(format
, term
), ap
);
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
)
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
;
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 *),
163 /* [gettext_accelerator_context(refreshed_msg_box)] */
164 struct dialog_data
*dlg_data
;
165 unsigned char *info
= get_info(term
, data
);
169 dlg_data
= msg_box(term
, NULL
, flags
| MSGBOX_FREE_TEXT
,
173 MSG_BOX_BUTTON(N_("~OK"), NULL
, B_ENTER
| B_ESC
));
175 if (!dlg_data
) return;
177 /* Save the original text to check up on it when the dialog
179 dlg_data
->dlg
->udata
= info
;
180 dlg_data
->dlg
->abort
= abort_refreshed_msg_box_handler
;
181 refresh_dialog(dlg_data
, refresh_msg_box
, get_info
);
185 info_box(struct terminal
*term
, enum msgbox_flags flags
,
186 unsigned char *title
, enum format_align align
,
189 /* [gettext_accelerator_context(info_box)] */
190 return msg_box(term
, NULL
, flags
,
194 MSG_BOX_BUTTON(N_("~OK"), NULL
, B_ENTER
| B_ESC
));