1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-03-22 14:39:24 -05:00

Make the GTK message-box function non-variadic.

Now, in place of a variadic argument list with four parameters per
button and a terminating NULL, it takes a pointer to a struct which in
turn contains an (array,length) pair of small per-button structures.

In the process I've renamed the function from messagebox() to
message_box(). Partly that was just because it gave me a convenient
way to search the source for calls I hadn't converted yet, but also
I've thought for a while that that missing underscore didn't really
match the rest of my naming.

NFCI. Partly this minor refactor has the virtue that we can reuse the
more common button layouts without having to type them in at multiple
places in the code (and, indeed, I've provided buttons_yn and
buttons_ok for easy reuse, and could easily provide other things like
yesnocancel any time I need them). But mostly it's because I'm about
to split up message_box into multiple functions, and this saves me the
hassle of deciding which ones to make variadic and which to pass an
actual va_list to - particularly since messagebox() used to go over
its variadic argument list twice, which always makes delegating it to
another function that much more annoying.
This commit is contained in:
Simon Tatham 2017-11-26 14:05:02 +00:00
parent 5726940153
commit 2d289a9970
3 changed files with 101 additions and 87 deletions

View File

@ -3334,8 +3334,24 @@ static void messagebox_handler(union control *ctrl, void *dlg,
if (event == EVENT_ACTION) if (event == EVENT_ACTION)
dlg_end(dlg, ctrl->generic.context.i); dlg_end(dlg, ctrl->generic.context.i);
} }
int messagebox(GtkWidget *parentwin, const char *title, const char *msg,
int minwid, int selectable, ...) const struct message_box_button button_array_yn[] = {
{"Yes", 'y', +1, 1},
{"No", 'n', -1, 0},
};
const struct message_box_buttons buttons_yn = {
button_array_yn, lenof(button_array_yn),
};
const struct message_box_button button_array_ok[] = {
{"OK", 'o', 1, 1},
};
const struct message_box_buttons buttons_ok = {
button_array_ok, lenof(button_array_ok),
};
int message_box(
GtkWidget *parentwin, const char *title, const char *msg, int minwid,
int selectable, const struct message_box_buttons *buttons)
{ {
GtkWidget *window, *w0, *w1; GtkWidget *window, *w0, *w1;
struct controlbox *ctrlbox; struct controlbox *ctrlbox;
@ -3343,8 +3359,7 @@ int messagebox(GtkWidget *parentwin, const char *title, const char *msg,
union control *c, *textctrl; union control *c, *textctrl;
struct dlgparam dp; struct dlgparam dp;
struct Shortcuts scs; struct Shortcuts scs;
int index, ncols, min_type; int i, index, ncols, min_type;
va_list ap;
dlg_init(&dp); dlg_init(&dp);
@ -3355,24 +3370,17 @@ int messagebox(GtkWidget *parentwin, const char *title, const char *msg,
ctrlbox = ctrl_new_box(); ctrlbox = ctrl_new_box();
/* /*
* Preliminary pass over the va_list, to count up the number of * Count up the number of buttons and find out what kinds there
* buttons and find out what kinds there are. * are.
*/ */
ncols = 0; ncols = 0;
va_start(ap, selectable);
min_type = +1; min_type = +1;
while (va_arg(ap, char *) != NULL) { for (i = 0; i < buttons->nbuttons; i++) {
int type; const struct message_box_button *button = &buttons->buttons[i];
(void) va_arg(ap, int); /* shortcut */
type = va_arg(ap, int); /* normal/default/cancel */
(void) va_arg(ap, int); /* end value */
ncols++; ncols++;
if (min_type > type) if (min_type > button->type)
min_type = type; min_type = button->type;
} }
va_end(ap);
s0 = ctrl_getset(ctrlbox, "", "", ""); s0 = ctrl_getset(ctrlbox, "", "", "");
c = ctrl_columns(s0, 2, 50, 50); c = ctrl_columns(s0, 2, 50, 50);
@ -3380,20 +3388,14 @@ int messagebox(GtkWidget *parentwin, const char *title, const char *msg,
c->columns.percentages = sresize(c->columns.percentages, ncols, int); c->columns.percentages = sresize(c->columns.percentages, ncols, int);
for (index = 0; index < ncols; index++) for (index = 0; index < ncols; index++)
c->columns.percentages[index] = (index+1)*100/ncols - index*100/ncols; c->columns.percentages[index] = (index+1)*100/ncols - index*100/ncols;
va_start(ap, selectable);
index = 0; index = 0;
while (1) { for (i = 0; i < buttons->nbuttons; i++) {
char *title = va_arg(ap, char *); const struct message_box_button *button = &buttons->buttons[i];
int shortcut, type, value; c = ctrl_pushbutton(s0, button->title, button->shortcut,
if (title == NULL) HELPCTX(no_help), messagebox_handler,
break; I(button->value));
shortcut = va_arg(ap, int);
type = va_arg(ap, int);
value = va_arg(ap, int);
c = ctrl_pushbutton(s0, title, shortcut, HELPCTX(no_help),
messagebox_handler, I(value));
c->generic.column = index++; c->generic.column = index++;
if (type > 0) if (button->type > 0)
c->button.isdefault = TRUE; c->button.isdefault = TRUE;
/* We always arrange that _some_ button is labelled as /* We always arrange that _some_ button is labelled as
@ -3405,10 +3407,9 @@ int messagebox(GtkWidget *parentwin, const char *title, const char *msg,
* no will be picked, and if there's only one option (a box * no will be picked, and if there's only one option (a box
* that really is just showing a _message_ and not even asking * that really is just showing a _message_ and not even asking
* a question) then that will be picked. */ * a question) then that will be picked. */
if (type == min_type) if (button->type == min_type)
c->button.iscancel = TRUE; c->button.iscancel = TRUE;
} }
va_end(ap);
s1 = ctrl_getset(ctrlbox, "x", "", ""); s1 = ctrl_getset(ctrlbox, "x", "", "");
textctrl = ctrl_text(s1, msg, HELPCTX(no_help)); textctrl = ctrl_text(s1, msg, HELPCTX(no_help));
@ -3477,13 +3478,10 @@ int messagebox(GtkWidget *parentwin, const char *title, const char *msg,
int reallyclose(void *frontend) int reallyclose(void *frontend)
{ {
char *title = dupcat(appname, " Exit Confirmation", NULL); char *title = dupcat(appname, " Exit Confirmation", NULL);
int ret = messagebox(GTK_WIDGET(get_window(frontend)), int ret = message_box(GTK_WIDGET(get_window(frontend)), title,
title, "Are you sure you want to close this session?", "Are you sure you want to close this session?",
string_width("Most of the width of the above text"), string_width("Most of the width of the above text"),
FALSE, FALSE, &buttons_yn);
"Yes", 'y', +1, 1,
"No", 'n', -1, 0,
NULL);
sfree(title); sfree(title);
return ret; return ret;
} }
@ -3518,6 +3516,15 @@ int verify_ssh_host_key(void *frontend, char *host, int port,
"If you want to abandon the connection completely, press " "If you want to abandon the connection completely, press "
"\"Cancel\" to cancel. Pressing \"Cancel\" is the ONLY guaranteed " "\"Cancel\" to cancel. Pressing \"Cancel\" is the ONLY guaranteed "
"safe choice."; "safe choice.";
static const struct message_box_button button_array_hostkey[] = {
{"Accept", 'a', 0, 2},
{"Connect Once", 'o', 0, 1},
{"Cancel", 'c', -1, 0},
};
static const struct message_box_buttons buttons_hostkey = {
button_array_hostkey, lenof(button_array_hostkey),
};
char *text; char *text;
int ret; int ret;
@ -3531,14 +3538,10 @@ int verify_ssh_host_key(void *frontend, char *host, int port,
text = dupprintf((ret == 2 ? wrongtxt : absenttxt), keytype, fingerprint); text = dupprintf((ret == 2 ? wrongtxt : absenttxt), keytype, fingerprint);
ret = messagebox(GTK_WIDGET(get_window(frontend)), ret = message_box(GTK_WIDGET(get_window(frontend)),
"PuTTY Security Alert", text, "PuTTY Security Alert", text,
string_width(fingerprint), string_width(fingerprint),
TRUE, TRUE, &buttons_hostkey);
"Accept", 'a', 0, 2,
"Connect Once", 'o', 0, 1,
"Cancel", 'c', -1, 0,
NULL);
sfree(text); sfree(text);
@ -3565,14 +3568,11 @@ int askalg(void *frontend, const char *algtype, const char *algname,
int ret; int ret;
text = dupprintf(msg, algtype, algname); text = dupprintf(msg, algtype, algname);
ret = messagebox(GTK_WIDGET(get_window(frontend)), ret = message_box(GTK_WIDGET(get_window(frontend)),
"PuTTY Security Alert", text, "PuTTY Security Alert", text,
string_width("Reasonably long line of text as a width" string_width("Reasonably long line of text as a width"
" template"), " template"),
FALSE, FALSE, &buttons_yn);
"Yes", 'y', 0, 1,
"No", 'n', 0, 0,
NULL);
sfree(text); sfree(text);
if (ret) { if (ret) {
@ -3596,14 +3596,11 @@ int askhk(void *frontend, const char *algname, const char *betteralgs,
int ret; int ret;
text = dupprintf(msg, algname, betteralgs); text = dupprintf(msg, algname, betteralgs);
ret = messagebox(GTK_WIDGET(get_window(frontend)), ret = message_box(GTK_WIDGET(get_window(frontend)),
"PuTTY Security Alert", text, "PuTTY Security Alert", text,
string_width("is ecdsa-nistp521, which is" string_width("is ecdsa-nistp521, which is"
" below the configured warning threshold."), " below the configured warning threshold."),
FALSE, FALSE, &buttons_yn);
"Yes", 'y', 0, 1,
"No", 'n', 0, 0,
NULL);
sfree(text); sfree(text);
if (ret) { if (ret) {
@ -3622,16 +3619,16 @@ void old_keyfile_warning(void)
void fatal_message_box(void *window, const char *msg) void fatal_message_box(void *window, const char *msg)
{ {
messagebox(window, "PuTTY Fatal Error", msg, message_box(window, "PuTTY Fatal Error", msg,
string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"),
FALSE, "OK", 'o', 1, 1, NULL); FALSE, &buttons_ok);
} }
void nonfatal_message_box(void *window, const char *msg) void nonfatal_message_box(void *window, const char *msg)
{ {
messagebox(window, "PuTTY Error", msg, message_box(window, "PuTTY Error", msg,
string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"),
FALSE, "OK", 'o', 1, 1, NULL); FALSE, &buttons_ok);
} }
void fatalbox(const char *p, ...) void fatalbox(const char *p, ...)
@ -3680,10 +3677,10 @@ static void licence_clicked(GtkButton *button, gpointer data)
title = dupcat(appname, " Licence", NULL); title = dupcat(appname, " Licence", NULL);
assert(aboutbox != NULL); assert(aboutbox != NULL);
messagebox(aboutbox, title, LICENCE_TEXT("\n\n"), message_box(aboutbox, title, LICENCE_TEXT("\n\n"),
string_width("LONGISH LINE OF TEXT SO THE LICENCE" string_width("LONGISH LINE OF TEXT SO THE LICENCE"
" BOX ISN'T EXCESSIVELY TALL AND THIN"), " BOX ISN'T EXCESSIVELY TALL AND THIN"),
TRUE, "OK", 'o', 1, 1, NULL); TRUE, &buttons_ok);
sfree(title); sfree(title);
} }
@ -3736,7 +3733,7 @@ void about_box(void *window)
our_dialog_add_to_content_area(GTK_WINDOW(aboutbox), w, FALSE, FALSE, 0); our_dialog_add_to_content_area(GTK_WINDOW(aboutbox), w, FALSE, FALSE, 0);
#if GTK_CHECK_VERSION(2,0,0) #if GTK_CHECK_VERSION(2,0,0)
/* /*
* Same precautions against initial select-all as in messagebox(). * Same precautions against initial select-all as in message_box().
*/ */
gtk_widget_grab_focus(w); gtk_widget_grab_focus(w);
gtk_label_select_region(GTK_LABEL(w), 0, 0); gtk_label_select_region(GTK_LABEL(w), 0, 0);
@ -4003,6 +4000,15 @@ int askappend(void *frontend, Filename *filename,
"You can overwrite it with a new session log, " "You can overwrite it with a new session log, "
"append your session log to the end of it, " "append your session log to the end of it, "
"or disable session logging for this session."; "or disable session logging for this session.";
static const struct message_box_button button_array_append[] = {
{"Overwrite", 'o', 1, 2},
{"Append", 'a', 0, 1},
{"Disable", 'd', -1, 0},
};
static const struct message_box_buttons buttons_append = {
button_array_append, lenof(button_array_append),
};
char *message; char *message;
char *mbtitle; char *mbtitle;
int mbret; int mbret;
@ -4010,14 +4016,10 @@ int askappend(void *frontend, Filename *filename,
message = dupprintf(msgtemplate, FILENAME_MAX, filename->path); message = dupprintf(msgtemplate, FILENAME_MAX, filename->path);
mbtitle = dupprintf("%s Log to File", appname); mbtitle = dupprintf("%s Log to File", appname);
mbret = messagebox(get_window(frontend), mbtitle, message, mbret = message_box(get_window(frontend), mbtitle, message,
string_width("LINE OF TEXT SUITABLE FOR THE" string_width("LINE OF TEXT SUITABLE FOR THE"
" ASKAPPEND WIDTH"), " ASKAPPEND WIDTH"),
FALSE, FALSE, &buttons_append);
"Overwrite", 'o', 1, 2,
"Append", 'a', 0, 1,
"Disable", 'd', -1, 0,
NULL);
sfree(message); sfree(message);
sfree(mbtitle); sfree(mbtitle);

View File

@ -4125,10 +4125,10 @@ static void after_change_settings_dialog(void *vctx, int retval)
char *msgboxtext = char *msgboxtext =
dupprintf("Could not change fonts in terminal window: %s\n", dupprintf("Could not change fonts in terminal window: %s\n",
errmsg); errmsg);
messagebox(inst->window, "Font setup error", msgboxtext, message_box(inst->window, "Font setup error", msgboxtext,
string_width("Could not change fonts in terminal window:"), string_width("Could not change fonts in terminal"
FALSE, "OK", 'o', +1, 1, " window:"),
NULL); FALSE, &buttons_ok);
sfree(msgboxtext); sfree(msgboxtext);
sfree(errmsg); sfree(errmsg);
} else { } else {

View File

@ -164,8 +164,20 @@ void showeventlog(void *estuff, void *parentwin);
void logevent_dlg(void *estuff, const char *string); void logevent_dlg(void *estuff, const char *string);
int reallyclose(void *frontend); int reallyclose(void *frontend);
#ifdef MAY_REFER_TO_GTK_IN_HEADERS #ifdef MAY_REFER_TO_GTK_IN_HEADERS
int messagebox(GtkWidget *parentwin, const char *title, struct message_box_button {
const char *msg, int minwid, int selectable, ...); const char *title;
char shortcut;
int type; /* more negative means more appropriate to be the Esc action */
int value; /* message box's return value if this is pressed */
};
struct message_box_buttons {
const struct message_box_button *buttons;
int nbuttons;
};
extern const struct message_box_buttons buttons_yn, buttons_ok;
int message_box(
GtkWidget *parentwin, const char *title, const char *msg, int minwid,
int selectable, const struct message_box_buttons *buttons);
#endif #endif
/* Things pterm.c needs from {ptermm,uxputty}.c */ /* Things pterm.c needs from {ptermm,uxputty}.c */