mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
Permit button-only file selectors.
Instead of an edit box together with a Browse button that pops up a sub-dialog, this is _just_ the browse button, only now it has a user-defined title. I'm about to want to use this for loading CA public keys from files.
This commit is contained in:
parent
259e877b92
commit
694d5184b7
31
dialog.h
31
dialog.h
@ -369,6 +369,37 @@ struct dlgcontrol {
|
|||||||
* This value _is_ expected to require freeing.
|
* This value _is_ expected to require freeing.
|
||||||
*/
|
*/
|
||||||
char *title;
|
char *title;
|
||||||
|
/*
|
||||||
|
* Reduce the file selector to just a single browse
|
||||||
|
* button.
|
||||||
|
*
|
||||||
|
* Normally, a file selector is used to set a config
|
||||||
|
* option that consists of a file name, so that that file
|
||||||
|
* will be read or written at run time. In that situation,
|
||||||
|
* it makes sense to have an edit box showing the
|
||||||
|
* currently selected file name, and a button to change it
|
||||||
|
* interactively.
|
||||||
|
*
|
||||||
|
* But occasionally a file selector is used to load a file
|
||||||
|
* _during_ configuration. For example, host CA public
|
||||||
|
* keys are entered directly into the configuration as
|
||||||
|
* strings, not stored by reference to a filename; but if
|
||||||
|
* you have one in a file, you want to be able to load it
|
||||||
|
* during the lifetime of the CA config box rather than
|
||||||
|
* awkwardly copy-pasting it. So in that case you just
|
||||||
|
* want a 'pop up a file chooser' button, and when that
|
||||||
|
* delivers a file name, you'll deal with it there and
|
||||||
|
* then and write some other thing (like the file's
|
||||||
|
* contents) into a nearby edit box.
|
||||||
|
*
|
||||||
|
* If you set this flag, then you may not call
|
||||||
|
* dlg_filesel_set on the file selector at all, because it
|
||||||
|
* doesn't store a filename. And you can only call
|
||||||
|
* dlg_filesel_get on it in the handler for EVENT_ACTION,
|
||||||
|
* which is what will be sent to you when the user has
|
||||||
|
* used it to choose a filename.
|
||||||
|
*/
|
||||||
|
bool just_button;
|
||||||
} fileselect;
|
} fileselect;
|
||||||
struct { /* for CTRL_COLUMNS */
|
struct { /* for CTRL_COLUMNS */
|
||||||
/* In this variant, `label' MUST be NULL. */
|
/* In this variant, `label' MUST be NULL. */
|
||||||
|
125
unix/dialog.c
125
unix/dialog.c
@ -74,6 +74,7 @@ struct uctrl {
|
|||||||
guint entrysig;
|
guint entrysig;
|
||||||
guint textsig;
|
guint textsig;
|
||||||
int nclicks;
|
int nclicks;
|
||||||
|
const char *textvalue; /* temporary, for button-only file selectors */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dlgparam {
|
struct dlgparam {
|
||||||
@ -869,8 +870,10 @@ void dlg_label_change(dlgcontrol *ctrl, dlgparam *dp, char const *text)
|
|||||||
shortcut_highlight(uc->label, ctrl->editbox.shortcut);
|
shortcut_highlight(uc->label, ctrl->editbox.shortcut);
|
||||||
break;
|
break;
|
||||||
case CTRL_FILESELECT:
|
case CTRL_FILESELECT:
|
||||||
gtk_label_set_text(GTK_LABEL(uc->label), text);
|
if (uc->label) {
|
||||||
shortcut_highlight(uc->label, ctrl->fileselect.shortcut);
|
gtk_label_set_text(GTK_LABEL(uc->label), text);
|
||||||
|
shortcut_highlight(uc->label, ctrl->fileselect.shortcut);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CTRL_FONTSELECT:
|
case CTRL_FONTSELECT:
|
||||||
gtk_label_set_text(GTK_LABEL(uc->label), text);
|
gtk_label_set_text(GTK_LABEL(uc->label), text);
|
||||||
@ -901,8 +904,12 @@ Filename *dlg_filesel_get(dlgcontrol *ctrl, dlgparam *dp)
|
|||||||
{
|
{
|
||||||
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
|
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
|
||||||
assert(uc->ctrl->type == CTRL_FILESELECT);
|
assert(uc->ctrl->type == CTRL_FILESELECT);
|
||||||
assert(uc->entry != NULL);
|
if (!uc->entry) {
|
||||||
return filename_from_str(gtk_entry_get_text(GTK_ENTRY(uc->entry)));
|
assert(uc->textvalue);
|
||||||
|
return filename_from_str(uc->textvalue);
|
||||||
|
} else {
|
||||||
|
return filename_from_str(gtk_entry_get_text(GTK_ENTRY(uc->entry)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dlg_fontsel_set(dlgcontrol *ctrl, dlgparam *dp, FontSpec *fs)
|
void dlg_fontsel_set(dlgcontrol *ctrl, dlgparam *dp, FontSpec *fs)
|
||||||
@ -1562,15 +1569,27 @@ static void droplist_selchange(GtkComboBox *combo, gpointer data)
|
|||||||
|
|
||||||
#endif /* !GTK_CHECK_VERSION(2,4,0) */
|
#endif /* !GTK_CHECK_VERSION(2,4,0) */
|
||||||
|
|
||||||
|
static void filechoose_emit_value(struct dlgparam *dp, struct uctrl *uc,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
if (uc->entry) {
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(uc->entry), name);
|
||||||
|
} else {
|
||||||
|
uc->textvalue = name;
|
||||||
|
uc->ctrl->handler(uc->ctrl, dp, dp->data, EVENT_ACTION);
|
||||||
|
uc->textvalue = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_GTK_FILE_CHOOSER_DIALOG
|
#ifdef USE_GTK_FILE_CHOOSER_DIALOG
|
||||||
static void filechoose_response(GtkDialog *dialog, gint response,
|
static void filechoose_response(GtkDialog *dialog, gint response,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
/* struct dlgparam *dp = (struct dlgparam *)data; */
|
struct dlgparam *dp = (struct dlgparam *)data;
|
||||||
struct uctrl *uc = g_object_get_data(G_OBJECT(dialog), "user-data");
|
struct uctrl *uc = g_object_get_data(G_OBJECT(dialog), "user-data");
|
||||||
if (response == GTK_RESPONSE_ACCEPT) {
|
if (response == GTK_RESPONSE_ACCEPT) {
|
||||||
gchar *name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
gchar *name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||||
gtk_entry_set_text(GTK_ENTRY(uc->entry), name);
|
filechoose_emit_value(dp, uc, name);
|
||||||
g_free(name);
|
g_free(name);
|
||||||
}
|
}
|
||||||
gtk_widget_destroy(GTK_WIDGET(dialog));
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
||||||
@ -1578,12 +1597,12 @@ static void filechoose_response(GtkDialog *dialog, gint response,
|
|||||||
#else
|
#else
|
||||||
static void filesel_ok(GtkButton *button, gpointer data)
|
static void filesel_ok(GtkButton *button, gpointer data)
|
||||||
{
|
{
|
||||||
/* struct dlgparam *dp = (struct dlgparam *)data; */
|
struct dlgparam *dp = (struct dlgparam *)data;
|
||||||
gpointer filesel = g_object_get_data(G_OBJECT(button), "user-data");
|
gpointer filesel = g_object_get_data(G_OBJECT(button), "user-data");
|
||||||
struct uctrl *uc = g_object_get_data(G_OBJECT(filesel), "user-data");
|
struct uctrl *uc = g_object_get_data(G_OBJECT(filesel), "user-data");
|
||||||
const char *name = gtk_file_selection_get_filename
|
const char *name = gtk_file_selection_get_filename
|
||||||
(GTK_FILE_SELECTION(filesel));
|
(GTK_FILE_SELECTION(filesel));
|
||||||
gtk_entry_set_text(GTK_ENTRY(uc->entry), name);
|
filechoose_emit_value(dp, uc, name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2104,56 +2123,65 @@ GtkWidget *layout_ctrls(
|
|||||||
case CTRL_FILESELECT:
|
case CTRL_FILESELECT:
|
||||||
case CTRL_FONTSELECT: {
|
case CTRL_FONTSELECT: {
|
||||||
GtkWidget *ww;
|
GtkWidget *ww;
|
||||||
const char *browsebtn =
|
|
||||||
(ctrl->type == CTRL_FILESELECT ?
|
|
||||||
"Browse..." : "Change...");
|
|
||||||
|
|
||||||
gint percentages[] = { 75, 25 };
|
if (!ctrl->fileselect.just_button) {
|
||||||
w = columns_new(4);
|
const char *browsebtn =
|
||||||
columns_set_cols(COLUMNS(w), 2, percentages);
|
(ctrl->type == CTRL_FILESELECT ?
|
||||||
|
"Browse..." : "Change...");
|
||||||
|
|
||||||
if (ctrl->label) {
|
gint percentages[] = { 75, 25 };
|
||||||
ww = gtk_label_new(ctrl->label);
|
w = columns_new(4);
|
||||||
columns_add(COLUMNS(w), ww, 0, 2);
|
columns_set_cols(COLUMNS(w), 2, percentages);
|
||||||
columns_force_left_align(COLUMNS(w), ww);
|
|
||||||
gtk_widget_show(ww);
|
|
||||||
shortcut_add(scs, ww,
|
|
||||||
(ctrl->type == CTRL_FILESELECT ?
|
|
||||||
ctrl->fileselect.shortcut :
|
|
||||||
ctrl->fontselect.shortcut),
|
|
||||||
SHORTCUT_UCTRL, uc);
|
|
||||||
uc->label = ww;
|
|
||||||
}
|
|
||||||
|
|
||||||
uc->entry = ww = gtk_entry_new();
|
if (ctrl->label) {
|
||||||
|
ww = gtk_label_new(ctrl->label);
|
||||||
|
columns_add(COLUMNS(w), ww, 0, 2);
|
||||||
|
columns_force_left_align(COLUMNS(w), ww);
|
||||||
|
gtk_widget_show(ww);
|
||||||
|
shortcut_add(scs, ww,
|
||||||
|
(ctrl->type == CTRL_FILESELECT ?
|
||||||
|
ctrl->fileselect.shortcut :
|
||||||
|
ctrl->fontselect.shortcut),
|
||||||
|
SHORTCUT_UCTRL, uc);
|
||||||
|
uc->label = ww;
|
||||||
|
}
|
||||||
|
|
||||||
|
uc->entry = ww = gtk_entry_new();
|
||||||
#if !GTK_CHECK_VERSION(3,0,0)
|
#if !GTK_CHECK_VERSION(3,0,0)
|
||||||
{
|
{
|
||||||
GtkRequisition req;
|
GtkRequisition req;
|
||||||
gtk_widget_size_request(ww, &req);
|
gtk_widget_size_request(ww, &req);
|
||||||
gtk_widget_set_size_request(ww, 10, req.height);
|
gtk_widget_set_size_request(ww, 10, req.height);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
gtk_entry_set_width_chars(GTK_ENTRY(ww), 1);
|
gtk_entry_set_width_chars(GTK_ENTRY(ww), 1);
|
||||||
#endif
|
#endif
|
||||||
columns_add(COLUMNS(w), ww, 0, 1);
|
columns_add(COLUMNS(w), ww, 0, 1);
|
||||||
gtk_widget_show(ww);
|
gtk_widget_show(ww);
|
||||||
|
|
||||||
uc->button = ww = gtk_button_new_with_label(browsebtn);
|
uc->button = ww = gtk_button_new_with_label(browsebtn);
|
||||||
columns_add(COLUMNS(w), ww, 1, 1);
|
columns_add(COLUMNS(w), ww, 1, 1);
|
||||||
gtk_widget_show(ww);
|
gtk_widget_show(ww);
|
||||||
|
|
||||||
columns_force_same_height(COLUMNS(w), uc->entry, uc->button);
|
columns_force_same_height(COLUMNS(w), uc->entry, uc->button);
|
||||||
|
|
||||||
g_signal_connect(G_OBJECT(uc->entry), "key_press_event",
|
g_signal_connect(G_OBJECT(uc->entry), "key_press_event",
|
||||||
G_CALLBACK(editbox_key), dp);
|
G_CALLBACK(editbox_key), dp);
|
||||||
uc->entrysig =
|
uc->entrysig =
|
||||||
g_signal_connect(G_OBJECT(uc->entry), "changed",
|
g_signal_connect(G_OBJECT(uc->entry), "changed",
|
||||||
G_CALLBACK(editbox_changed), dp);
|
G_CALLBACK(editbox_changed), dp);
|
||||||
g_signal_connect(G_OBJECT(uc->entry), "focus_in_event",
|
g_signal_connect(G_OBJECT(uc->entry), "focus_in_event",
|
||||||
G_CALLBACK(widget_focus), dp);
|
G_CALLBACK(widget_focus), dp);
|
||||||
|
} else {
|
||||||
|
uc->button = w = gtk_button_new_with_label(ctrl->label);
|
||||||
|
shortcut_add(scs, gtk_bin_get_child(GTK_BIN(w)),
|
||||||
|
ctrl->fileselect.shortcut, SHORTCUT_UCTRL, uc);
|
||||||
|
gtk_widget_show(w);
|
||||||
|
|
||||||
|
}
|
||||||
g_signal_connect(G_OBJECT(uc->button), "focus_in_event",
|
g_signal_connect(G_OBJECT(uc->button), "focus_in_event",
|
||||||
G_CALLBACK(widget_focus), dp);
|
G_CALLBACK(widget_focus), dp);
|
||||||
g_signal_connect(G_OBJECT(ww), "clicked",
|
g_signal_connect(G_OBJECT(uc->button), "clicked",
|
||||||
G_CALLBACK(filefont_clicked), dp);
|
G_CALLBACK(filefont_clicked), dp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2669,7 +2697,8 @@ gint win_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
|||||||
/* File/font selectors have their buttons pressed (ooer),
|
/* File/font selectors have their buttons pressed (ooer),
|
||||||
* and focus transferred to the edit box. */
|
* and focus transferred to the edit box. */
|
||||||
g_signal_emit_by_name(G_OBJECT(sc->uc->button), "clicked");
|
g_signal_emit_by_name(G_OBJECT(sc->uc->button), "clicked");
|
||||||
gtk_widget_grab_focus(sc->uc->entry);
|
if (sc->uc->entry)
|
||||||
|
gtk_widget_grab_focus(sc->uc->entry);
|
||||||
break;
|
break;
|
||||||
case CTRL_RADIO:
|
case CTRL_RADIO:
|
||||||
/*
|
/*
|
||||||
|
@ -1663,12 +1663,15 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
|
|||||||
sfree(escaped);
|
sfree(escaped);
|
||||||
break;
|
break;
|
||||||
case CTRL_FILESELECT:
|
case CTRL_FILESELECT:
|
||||||
num_ids = 3;
|
escaped = shortcut_escape(ctrl->label, ctrl->fileselect.shortcut);
|
||||||
escaped = shortcut_escape(ctrl->label,
|
|
||||||
ctrl->fileselect.shortcut);
|
|
||||||
shortcuts[nshortcuts++] = ctrl->fileselect.shortcut;
|
shortcuts[nshortcuts++] = ctrl->fileselect.shortcut;
|
||||||
editbutton(&pos, escaped, base_id, base_id+1,
|
num_ids = 3;
|
||||||
"Browse...", base_id+2);
|
if (!ctrl->fileselect.just_button) {
|
||||||
|
editbutton(&pos, escaped, base_id, base_id+1,
|
||||||
|
"Browse...", base_id+2);
|
||||||
|
} else {
|
||||||
|
button(&pos, escaped, base_id+2, false);
|
||||||
|
}
|
||||||
sfree(escaped);
|
sfree(escaped);
|
||||||
break;
|
break;
|
||||||
case CTRL_FONTSELECT:
|
case CTRL_FONTSELECT:
|
||||||
@ -1980,15 +1983,27 @@ bool winctrl_handle_command(struct dlgparam *dp, UINT msg,
|
|||||||
of.lpstrCustomFilter = NULL;
|
of.lpstrCustomFilter = NULL;
|
||||||
of.nFilterIndex = 1;
|
of.nFilterIndex = 1;
|
||||||
of.lpstrFile = filename;
|
of.lpstrFile = filename;
|
||||||
GetDlgItemText(dp->hwnd, c->base_id+1, filename, lenof(filename));
|
if (!ctrl->fileselect.just_button) {
|
||||||
filename[lenof(filename)-1] = '\0';
|
GetDlgItemText(dp->hwnd, c->base_id+1,
|
||||||
|
filename, lenof(filename));
|
||||||
|
filename[lenof(filename)-1] = '\0';
|
||||||
|
} else {
|
||||||
|
*filename = '\0';
|
||||||
|
}
|
||||||
of.nMaxFile = lenof(filename);
|
of.nMaxFile = lenof(filename);
|
||||||
of.lpstrFileTitle = NULL;
|
of.lpstrFileTitle = NULL;
|
||||||
of.lpstrTitle = ctrl->fileselect.title;
|
of.lpstrTitle = ctrl->fileselect.title;
|
||||||
of.Flags = 0;
|
of.Flags = 0;
|
||||||
if (request_file(NULL, &of, false, ctrl->fileselect.for_writing)) {
|
if (request_file(NULL, &of, false, ctrl->fileselect.for_writing)) {
|
||||||
SetDlgItemText(dp->hwnd, c->base_id + 1, filename);
|
if (!ctrl->fileselect.just_button) {
|
||||||
ctrl->handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
|
SetDlgItemText(dp->hwnd, c->base_id + 1, filename);
|
||||||
|
ctrl->handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
|
||||||
|
} else {
|
||||||
|
assert(!c->data);
|
||||||
|
c->data = filename;
|
||||||
|
ctrl->handler(ctrl, dp, dp->data, EVENT_ACTION);
|
||||||
|
c->data = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2330,7 +2345,10 @@ void dlg_label_change(dlgcontrol *ctrl, dlgparam *dp, char const *text)
|
|||||||
break;
|
break;
|
||||||
case CTRL_FILESELECT:
|
case CTRL_FILESELECT:
|
||||||
escaped = shortcut_escape(text, ctrl->fileselect.shortcut);
|
escaped = shortcut_escape(text, ctrl->fileselect.shortcut);
|
||||||
id = c->base_id;
|
if (ctrl->fileselect.just_button)
|
||||||
|
id = c->base_id + 2; /* the button */
|
||||||
|
else
|
||||||
|
id = c->base_id; /* the label */
|
||||||
break;
|
break;
|
||||||
case CTRL_FONTSELECT:
|
case CTRL_FONTSELECT:
|
||||||
escaped = shortcut_escape(text, ctrl->fontselect.shortcut);
|
escaped = shortcut_escape(text, ctrl->fontselect.shortcut);
|
||||||
@ -2348,7 +2366,9 @@ void dlg_label_change(dlgcontrol *ctrl, dlgparam *dp, char const *text)
|
|||||||
void dlg_filesel_set(dlgcontrol *ctrl, dlgparam *dp, Filename *fn)
|
void dlg_filesel_set(dlgcontrol *ctrl, dlgparam *dp, Filename *fn)
|
||||||
{
|
{
|
||||||
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
|
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
|
||||||
assert(c && c->ctrl->type == CTRL_FILESELECT);
|
assert(c);
|
||||||
|
assert(c->ctrl->type == CTRL_FILESELECT);
|
||||||
|
assert(!c->ctrl->fileselect.just_button);
|
||||||
SetDlgItemText(dp->hwnd, c->base_id+1, fn->path);
|
SetDlgItemText(dp->hwnd, c->base_id+1, fn->path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2357,11 +2377,16 @@ Filename *dlg_filesel_get(dlgcontrol *ctrl, dlgparam *dp)
|
|||||||
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
|
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
|
||||||
char *tmp;
|
char *tmp;
|
||||||
Filename *ret;
|
Filename *ret;
|
||||||
assert(c && c->ctrl->type == CTRL_FILESELECT);
|
assert(c);
|
||||||
tmp = GetDlgItemText_alloc(dp->hwnd, c->base_id+1);
|
assert(c->ctrl->type == CTRL_FILESELECT);
|
||||||
ret = filename_from_str(tmp);
|
if (!c->ctrl->fileselect.just_button) {
|
||||||
sfree(tmp);
|
tmp = GetDlgItemText_alloc(dp->hwnd, c->base_id+1);
|
||||||
return ret;
|
ret = filename_from_str(tmp);
|
||||||
|
sfree(tmp);
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
return filename_from_str(c->data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dlg_fontsel_set(dlgcontrol *ctrl, dlgparam *dp, FontSpec *fs)
|
void dlg_fontsel_set(dlgcontrol *ctrl, dlgparam *dp, FontSpec *fs)
|
||||||
|
Loading…
Reference in New Issue
Block a user