0
0
mirror of https://github.com/rkd77/elinks.git synced 2025-06-30 22:19:29 -04:00
elinks/src/bfu/msgbox.c
Petr Baudis 0f6d4310ad Initial commit of the HEAD branch of the ELinks CVS repository, as of
Thu Sep 15 15:57:07 CEST 2005. The previous history can be added to this
by grafting.
2005-09-15 15:58:31 +02:00

192 lines
4.2 KiB
C

/* Prefabricated message box implementation. */
/* $Id: msgbox.c,v 1.102 2005/06/22 14:00:44 witekfl Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdarg.h>
#include "elinks.h"
#include "bfu/dialog.h"
#include "bfu/button.h"
#include "bfu/msgbox.h"
#include "bfu/text.h"
#include "intl/gettext/libintl.h"
#include "terminal/terminal.h"
#include "util/color.h"
#include "util/memlist.h"
#include "util/memory.h"
#include "util/snprintf.h"
#include "util/string.h"
struct dialog_data *
msg_box(struct terminal *term, struct memory_list *ml, enum msgbox_flags flags,
unsigned char *title, enum format_align align,
unsigned char *text, void *udata, int buttons, ...)
{
struct dialog *dlg;
va_list ap;
/* Check if the info string is valid. */
if (!text || buttons < 0) return NULL;
/* Use the @flags to determine whether @text should be free()d. */
if (flags & MSGBOX_FREE_TEXT)
add_one_to_ml(&ml, text);
/* Use the @flags to determine whether strings should be l18n'd. */
if (!(flags & MSGBOX_NO_INTL)) {
title = _(title, term);
if (!(flags & MSGBOX_FREE_TEXT)
&& !(flags & MSGBOX_NO_TEXT_INTL))
text = _(text, term);
/* Button labels will be gettextized as will they be extracted
* from @ap. */
}
dlg = calloc_dialog(buttons + 1, 0);
if (!dlg) {
freeml(ml);
return NULL;
}
add_one_to_ml(&ml, dlg);
dlg->title = title;
dlg->layouter = generic_dialog_layouter;
dlg->layout.padding_top = 1;
dlg->udata2 = udata;
if (flags & MSGBOX_SCROLLABLE)
dlg->widgets->info.text.is_scrollable = 1;
add_dlg_text(dlg, text, align, 0);
va_start(ap, buttons);
while (dlg->number_of_widgets < buttons + 1) {
unsigned char *label;
done_handler_T *done;
int bflags;
label = va_arg(ap, unsigned char *);
done = va_arg(ap, void *);
bflags = va_arg(ap, int);
if (!label) {
/* Skip this button. */
buttons--;
continue;
}
if (!(flags & MSGBOX_NO_INTL))
label = _(label, term);
add_dlg_ok_button(dlg, label, bflags, done, udata);
}
va_end(ap);
add_dlg_end(dlg, buttons + 1);
return do_dialog(term, dlg, ml);
}
static inline unsigned char *
msg_text_do(unsigned char *format, va_list ap)
{
unsigned char *info;
int infolen, len;
va_list ap2;
VA_COPY(ap2, ap);
infolen = vsnprintf(NULL, 0, format, ap2);
info = mem_alloc(infolen + 1);
if (!info) return NULL;
len = vsnprintf((char *) info, infolen + 1, format, ap);
if (len != infolen) {
mem_free(info);
return NULL;
}
/* Wear safety boots */
info[infolen] = '\0';
return info;
}
unsigned char *
msg_text(struct terminal *term, unsigned char *format, ...)
{
unsigned char *info;
va_list ap;
va_start(ap, format);
info = msg_text_do(_(format, term), ap);
va_end(ap);
return info;
}
static void
abort_refreshed_msg_box_handler(struct dialog_data *dlg_data)
{
void *data = dlg_data->dlg->widgets->text;
if (dlg_data->dlg->udata != data)
mem_free(data);
}
static enum dlg_refresh_code
refresh_msg_box(struct dialog_data *dlg_data, void *data)
{
unsigned char *(*get_info)(struct terminal *, void *) = data;
void *msg_data = dlg_data->dlg->udata2;
unsigned char *info = get_info(dlg_data->win->term, msg_data);
if (!info) return REFRESH_CANCEL;
abort_refreshed_msg_box_handler(dlg_data);
dlg_data->dlg->widgets->text = info;
return REFRESH_DIALOG;
}
void
refreshed_msg_box(struct terminal *term, enum msgbox_flags flags,
unsigned char *title, enum format_align align,
unsigned char *(get_info)(struct terminal *, void *),
void *data)
{
struct dialog_data *dlg_data;
unsigned char *info = get_info(term, data);
if (!info) return;
dlg_data = msg_box(term, NULL, flags | MSGBOX_FREE_TEXT,
title, align,
info,
data, 1,
N_("~OK"), NULL, B_ENTER | B_ESC);
if (!dlg_data) return;
/* Save the original text to check up on it when the dialog
* is freed. */
dlg_data->dlg->udata = info;
dlg_data->dlg->abort = abort_refreshed_msg_box_handler;
refresh_dialog(dlg_data, refresh_msg_box, get_info);
}
struct dialog_data *
info_box(struct terminal *term, enum msgbox_flags flags,
unsigned char *title, enum format_align align,
unsigned char *text)
{
return msg_box(term, NULL, flags, title, align, text,
NULL, 1, N_("~OK"), NULL, B_ENTER | B_ESC);
}