X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=unix%2Fgtkdlg.c;h=6c532024c488febf3b6784ad4d064f1a3d5cf00a;hb=89da2ddf564a93414ee9ab2df3f053608094e417;hp=aa974546c9b2467d26322a86eecadf2d00b43b24;hpb=79f7249185f0bb6eddc30a94b4b21072b3ac460e;p=PuTTY.git diff --git a/unix/gtkdlg.c b/unix/gtkdlg.c index aa974546..6c532024 100644 --- a/unix/gtkdlg.c +++ b/unix/gtkdlg.c @@ -37,18 +37,18 @@ struct Shortcuts { struct uctrl { union control *ctrl; GtkWidget *toplevel; - void *privdata; - int privdata_needs_free; GtkWidget **buttons; int nbuttons; /* for radio buttons */ GtkWidget *entry; /* for editbox, filesel, fontsel */ GtkWidget *button; /* for filesel, fontsel */ -#if !GTK_CHECK_VERSION(2,0,0) - GtkWidget *list; /* for combobox, listbox */ +#if !GTK_CHECK_VERSION(2,4,0) + GtkWidget *list; /* for listbox (in GTK1), combobox (<=GTK2.3) */ GtkWidget *menu; /* for optionmenu (==droplist) */ GtkWidget *optmenu; /* also for optionmenu */ #else GtkWidget *combo; /* for combo box (either editable or not) */ - GtkWidget *treeview; /* for list box (list, droplist, combo box) */ +#endif +#if GTK_CHECK_VERSION(2,0,0) + GtkWidget *treeview; /* for listbox (GTK2), droplist+combo (>=2.4) */ GtkListStore *listmodel; /* for all types of list box */ #endif GtkWidget *text; /* for text */ @@ -112,6 +112,8 @@ static gboolean listitem_button_press(GtkWidget *item, GdkEventButton *event, gpointer data); static gboolean listitem_button_release(GtkWidget *item, GdkEventButton *event, gpointer data); +#endif +#if !GTK_CHECK_VERSION(2,4,0) static void menuitem_activate(GtkMenuItem *item, gpointer data); #endif static void coloursel_ok(GtkButton *button, gpointer data); @@ -185,8 +187,6 @@ static void dlg_cleanup(struct dlgparam *dp) dp->byctrl = NULL; while ( (uc = index234(dp->bywidget, 0)) != NULL) { del234(dp->bywidget, uc); - if (uc->privdata_needs_free) - sfree(uc->privdata); sfree(uc->buttons); sfree(uc); } @@ -224,34 +224,6 @@ static struct uctrl *dlg_find_bywidget(struct dlgparam *dp, GtkWidget *w) return ret; } -void *dlg_get_privdata(union control *ctrl, void *dlg) -{ - struct dlgparam *dp = (struct dlgparam *)dlg; - struct uctrl *uc = dlg_find_byctrl(dp, ctrl); - return uc->privdata; -} - -void dlg_set_privdata(union control *ctrl, void *dlg, void *ptr) -{ - struct dlgparam *dp = (struct dlgparam *)dlg; - struct uctrl *uc = dlg_find_byctrl(dp, ctrl); - uc->privdata = ptr; - uc->privdata_needs_free = FALSE; -} - -void *dlg_alloc_privdata(union control *ctrl, void *dlg, size_t size) -{ - struct dlgparam *dp = (struct dlgparam *)dlg; - struct uctrl *uc = dlg_find_byctrl(dp, ctrl); - /* - * This is an internal allocation routine, so it's allowed to - * use smalloc directly. - */ - uc->privdata = smalloc(size); - uc->privdata_needs_free = FALSE; - return uc->privdata; -} - union control *dlg_last_focused(union control *ctrl, void *dlg) { struct dlgparam *dp = (struct dlgparam *)dlg; @@ -308,25 +280,14 @@ void dlg_editbox_set(union control *ctrl, void *dlg, char const *text) char *tmpstring; assert(uc->ctrl->generic.type == CTRL_EDITBOX); -#if !GTK_CHECK_VERSION(2,0,0) - /* - * In GTK 1, `entry' is valid for combo boxes and edit boxes - * alike. - */ - assert(uc->entry != NULL); - entry = uc->entry; -#else - /* - * In GTK 2, combo boxes use a completely different widget. - */ - if (!uc->ctrl->editbox.has_list) { - assert(uc->entry != NULL); - entry = uc->entry; - } else { - assert(uc->combo != NULL); +#if GTK_CHECK_VERSION(2,4,0) + if (uc->combo) entry = gtk_bin_get_child(GTK_BIN(uc->combo)); - } + else #endif + entry = uc->entry; + + assert(entry != NULL); /* * GTK 2 implements gtk_entry_set_text by means of two separate @@ -337,11 +298,10 @@ void dlg_editbox_set(union control *ctrl, void *dlg, char const *text) * The first call to "changed", if allowed to proceed normally, * will cause an EVENT_VALCHANGE event on the edit box, causing * a call to dlg_editbox_get() which will read the empty string - * out of the GtkEntry - and promptly write it straight into - * the Config structure, which is precisely where our `text' - * pointer is probably pointing, so the second editing - * operation will insert that instead of the string we - * originally asked for. + * out of the GtkEntry - and promptly write it straight into the + * Conf structure, which is precisely where our `text' pointer + * is probably pointing, so the second editing operation will + * insert that instead of the string we originally asked for. * * Hence, we must take our own copy of the text before we do * this. @@ -351,38 +311,31 @@ void dlg_editbox_set(union control *ctrl, void *dlg, char const *text) sfree(tmpstring); } -void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length) +char *dlg_editbox_get(union control *ctrl, void *dlg) { struct dlgparam *dp = (struct dlgparam *)dlg; struct uctrl *uc = dlg_find_byctrl(dp, ctrl); assert(uc->ctrl->generic.type == CTRL_EDITBOX); -#if GTK_CHECK_VERSION(2,0,0) - if (!uc->ctrl->editbox.has_list) { -#endif - assert(uc->entry != NULL); - strncpy(buffer, gtk_entry_get_text(GTK_ENTRY(uc->entry)), - length); - buffer[length-1] = '\0'; -#if GTK_CHECK_VERSION(2,0,0) - } else { - assert(uc->combo != NULL); +#if GTK_CHECK_VERSION(2,4,0) + if (uc->combo) { #if GTK_CHECK_VERSION(2,6,0) - strncpy(buffer, - gtk_combo_box_get_active_text(GTK_COMBO_BOX(uc->combo)), - length); + return dupstr(gtk_combo_box_get_active_text(GTK_COMBO_BOX(uc->combo))); #else - strncpy(buffer, - gtk_entry_get_text - (GTK_ENTRY(gtk_bin_get_child(GTK_BIN(uc->combo)))), - length); + return dupstr(gtk_entry_get_text + (GTK_ENTRY(gtk_bin_get_child(GTK_BIN(uc->combo))))); #endif - buffer[length-1] = '\0'; } #endif + + if (uc->entry) { + return dupstr(gtk_entry_get_text(GTK_ENTRY(uc->entry))); + } + + assert(!"We shouldn't get here"); } -#if !GTK_CHECK_VERSION(2,0,0) +#if !GTK_CHECK_VERSION(2,4,0) static void container_remove_and_destroy(GtkWidget *w, gpointer data) { GtkContainer *cont = GTK_CONTAINER(data); @@ -400,19 +353,25 @@ void dlg_listbox_clear(union control *ctrl, void *dlg) assert(uc->ctrl->generic.type == CTRL_EDITBOX || uc->ctrl->generic.type == CTRL_LISTBOX); -#if !GTK_CHECK_VERSION(2,0,0) - assert(uc->menu != NULL || uc->list != NULL); +#if !GTK_CHECK_VERSION(2,4,0) if (uc->menu) { gtk_container_foreach(GTK_CONTAINER(uc->menu), container_remove_and_destroy, GTK_CONTAINER(uc->menu)); - } else { + return; + } + if (uc->list) { gtk_list_clear_items(GTK_LIST(uc->list), 0, -1); + return; } -#else - assert(uc->listmodel != NULL); - gtk_list_store_clear(uc->listmodel); #endif +#if GTK_CHECK_VERSION(2,0,0) + if (uc->listmodel) { + gtk_list_store_clear(uc->listmodel); + return; + } +#endif + assert(!"We shouldn't get here"); } void dlg_listbox_del(union control *ctrl, void *dlg, int index) @@ -423,17 +382,20 @@ void dlg_listbox_del(union control *ctrl, void *dlg, int index) assert(uc->ctrl->generic.type == CTRL_EDITBOX || uc->ctrl->generic.type == CTRL_LISTBOX); -#if !GTK_CHECK_VERSION(2,0,0) - assert(uc->menu != NULL || uc->list != NULL); +#if !GTK_CHECK_VERSION(2,4,0) if (uc->menu) { gtk_container_remove (GTK_CONTAINER(uc->menu), g_list_nth_data(GTK_MENU_SHELL(uc->menu)->children, index)); - } else { + return; + } + if (uc->list) { gtk_list_clear_items(GTK_LIST(uc->list), index, index+1); + return; } -#else - { +#endif +#if GTK_CHECK_VERSION(2,0,0) + if (uc->listmodel) { GtkTreePath *path; GtkTreeIter iter; assert(uc->listmodel != NULL); @@ -441,8 +403,10 @@ void dlg_listbox_del(union control *ctrl, void *dlg, int index) gtk_tree_model_get_iter(GTK_TREE_MODEL(uc->listmodel), &iter, path); gtk_list_store_remove(uc->listmodel, &iter); gtk_tree_path_free(path); + return; } #endif + assert(!"We shouldn't get here"); } void dlg_listbox_add(union control *ctrl, void *dlg, char const *text) @@ -470,12 +434,9 @@ void dlg_listbox_addwithid(union control *ctrl, void *dlg, * This routine is long and complicated in both GTK 1 and 2, * and completely different. Sigh. */ -#if !GTK_CHECK_VERSION(2,0,0) - - assert(uc->menu != NULL || uc->list != NULL); - dp->flags |= FLAG_UPDATING_COMBO_LIST; +#if !GTK_CHECK_VERSION(2,4,0) if (uc->menu) { /* * List item in a drop-down (but non-combo) list. Tabs are @@ -491,7 +452,26 @@ void dlg_listbox_addwithid(union control *ctrl, void *dlg, GINT_TO_POINTER(id)); gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(menuitem_activate), dp); - } else if (!uc->entry) { + goto done; + } + if (uc->list && uc->entry) { + /* + * List item in a combo-box list, which means the sensible + * thing to do is make it a perfectly normal label. Hence + * tabs are disregarded. + */ + GtkWidget *listitem = gtk_list_item_new_with_label(text); + + gtk_container_add(GTK_CONTAINER(uc->list), listitem); + gtk_widget_show(listitem); + + gtk_object_set_data(GTK_OBJECT(listitem), "user-data", + GINT_TO_POINTER(id)); + goto done; + } +#endif +#if !GTK_CHECK_VERSION(2,0,0) + if (uc->list) { /* * List item in a non-combo-box list box. We make all of * these Columns containing GtkLabels. This allows us to do @@ -554,31 +534,13 @@ void dlg_listbox_addwithid(union control *ctrl, void *dlg, GTK_SIGNAL_FUNC(listitem_button_release), dp); gtk_object_set_data(GTK_OBJECT(listitem), "user-data", GINT_TO_POINTER(id)); - } else { - /* - * List item in a combo-box list, which means the sensible - * thing to do is make it a perfectly normal label. Hence - * tabs are disregarded. - */ - GtkWidget *listitem = gtk_list_item_new_with_label(text); - - gtk_container_add(GTK_CONTAINER(uc->list), listitem); - gtk_widget_show(listitem); - - gtk_object_set_data(GTK_OBJECT(listitem), "user-data", - GINT_TO_POINTER(id)); + goto done; } - - dp->flags &= ~FLAG_UPDATING_COMBO_LIST; - #else - - { + if (uc->listmodel) { GtkTreeIter iter; int i, cols; - assert(uc->listmodel); - dp->flags |= FLAG_UPDATING_LISTBOX;/* inhibit drag-list update */ gtk_list_store_append(uc->listmodel, &iter); dp->flags &= ~FLAG_UPDATING_LISTBOX; @@ -600,10 +562,12 @@ void dlg_listbox_addwithid(union control *ctrl, void *dlg, text += collen; if (*text) text++; } + goto done; } - #endif - + assert(!"We shouldn't get here"); + done: + dp->flags &= ~FLAG_UPDATING_COMBO_LIST; } int dlg_listbox_getid(union control *ctrl, void *dlg, int index) @@ -614,13 +578,11 @@ int dlg_listbox_getid(union control *ctrl, void *dlg, int index) assert(uc->ctrl->generic.type == CTRL_EDITBOX || uc->ctrl->generic.type == CTRL_LISTBOX); -#if !GTK_CHECK_VERSION(2,0,0) - { +#if !GTK_CHECK_VERSION(2,4,0) + if (uc->menu || uc->list) { GList *children; GtkObject *item; - assert(uc->menu != NULL || uc->list != NULL); - children = gtk_container_children(GTK_CONTAINER(uc->menu ? uc->menu : uc->list)); item = GTK_OBJECT(g_list_nth_data(children, index)); @@ -629,14 +591,13 @@ int dlg_listbox_getid(union control *ctrl, void *dlg, int index) return GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(item), "user-data")); } -#else - { +#endif +#if GTK_CHECK_VERSION(2,0,0) + if (uc->listmodel) { GtkTreePath *path; GtkTreeIter iter; int ret; - assert(uc->listmodel != NULL); - path = gtk_tree_path_new_from_indices(index, -1); gtk_tree_model_get_iter(GTK_TREE_MODEL(uc->listmodel), &iter, path); gtk_tree_model_get(GTK_TREE_MODEL(uc->listmodel), &iter, 0, &ret, -1); @@ -645,6 +606,8 @@ int dlg_listbox_getid(union control *ctrl, void *dlg, int index) return ret; } #endif + assert(!"We shouldn't get here"); + return -1; /* placate dataflow analysis */ } /* dlg_listbox_index returns <0 if no single element is selected. */ @@ -656,16 +619,13 @@ int dlg_listbox_index(union control *ctrl, void *dlg) assert(uc->ctrl->generic.type == CTRL_EDITBOX || uc->ctrl->generic.type == CTRL_LISTBOX); -#if !GTK_CHECK_VERSION(2,0,0) - - { +#if !GTK_CHECK_VERSION(2,4,0) + if (uc->menu || uc->list) { GList *children; GtkWidget *item, *activeitem; int i; int selected = -1; - assert(uc->menu != NULL || uc->list != NULL); - if (uc->menu) activeitem = gtk_menu_get_active(GTK_MENU(uc->menu)); else @@ -686,22 +646,20 @@ int dlg_listbox_index(union control *ctrl, void *dlg) g_list_free(children); return selected < 0 ? -1 : selected; } - #else - - /* - * We have to do this completely differently for a combo box - * (editable or otherwise) and a full-size list box. - */ if (uc->combo) { /* * This API function already does the right thing in the * case of no current selection. */ return gtk_combo_box_get_active(GTK_COMBO_BOX(uc->combo)); - } else { + } +#endif +#if GTK_CHECK_VERSION(2,0,0) + if (uc->treeview) { GtkTreeSelection *treesel; GtkTreePath *path; + GtkTreeModel *model; GList *sellist; gint *indices; int ret; @@ -712,7 +670,7 @@ int dlg_listbox_index(union control *ctrl, void *dlg) if (gtk_tree_selection_count_selected_rows(treesel) != 1) return -1; - sellist = gtk_tree_selection_get_selected_rows(treesel, NULL); + sellist = gtk_tree_selection_get_selected_rows(treesel, &model); assert(sellist && sellist->data); path = sellist->data; @@ -733,8 +691,9 @@ int dlg_listbox_index(union control *ctrl, void *dlg) return ret; } - #endif + assert(!"We shouldn't get here"); + return -1; /* placate dataflow analysis */ } int dlg_listbox_issel(union control *ctrl, void *dlg, int index) @@ -745,9 +704,8 @@ int dlg_listbox_issel(union control *ctrl, void *dlg, int index) assert(uc->ctrl->generic.type == CTRL_EDITBOX || uc->ctrl->generic.type == CTRL_LISTBOX); -#if !GTK_CHECK_VERSION(2,0,0) - - { +#if !GTK_CHECK_VERSION(2,4,0) + if (uc->menu || uc->list) { GList *children; GtkWidget *item, *activeitem; @@ -767,20 +725,17 @@ int dlg_listbox_issel(union control *ctrl, void *dlg, int index) return GTK_WIDGET_STATE(item) == GTK_STATE_SELECTED; } } - #else - - /* - * We have to do this completely differently for a combo box - * (editable or otherwise) and a full-size list box. - */ if (uc->combo) { /* * This API function already does the right thing in the * case of no current selection. */ return gtk_combo_box_get_active(GTK_COMBO_BOX(uc->combo)) == index; - } else { + } +#endif +#if GTK_CHECK_VERSION(2,0,0) + if (uc->treeview) { GtkTreeSelection *treesel; GtkTreePath *path; int ret; @@ -794,8 +749,9 @@ int dlg_listbox_issel(union control *ctrl, void *dlg, int index) return ret; } - #endif + assert(!"We shouldn't get here"); + return -1; /* placate dataflow analysis */ } void dlg_listbox_select(union control *ctrl, void *dlg, int index) @@ -806,13 +762,12 @@ void dlg_listbox_select(union control *ctrl, void *dlg, int index) assert(uc->ctrl->generic.type == CTRL_EDITBOX || uc->ctrl->generic.type == CTRL_LISTBOX); -#if !GTK_CHECK_VERSION(2,0,0) - - assert(uc->optmenu != NULL || uc->list != NULL); - +#if !GTK_CHECK_VERSION(2,4,0) if (uc->optmenu) { gtk_option_menu_set_history(GTK_OPTION_MENU(uc->optmenu), index); - } else { + return; + } + if (uc->list) { int nitems; GList *items; gdouble newtop, newbot; @@ -842,21 +797,19 @@ void dlg_listbox_select(union control *ctrl, void *dlg, int index) if (modified) gtk_adjustment_value_changed(uc->adj); } + return; } - #else - - /* - * We have to do this completely differently for a combo box - * (editable or otherwise) and a full-size list box. - */ if (uc->combo) { gtk_combo_box_set_active(GTK_COMBO_BOX(uc->combo), index); - } else { + return; + } +#endif +#if GTK_CHECK_VERSION(2,0,0) + if (uc->treeview) { GtkTreeSelection *treesel; GtkTreePath *path; - assert(uc->treeview != NULL); treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(uc->treeview)); path = gtk_tree_path_new_from_indices(index, -1); @@ -864,10 +817,10 @@ void dlg_listbox_select(union control *ctrl, void *dlg, int index) gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(uc->treeview), path, NULL, FALSE, 0.0, 0.0); gtk_tree_path_free(path); + return; } - #endif - + assert(!"We shouldn't get here"); } void dlg_text_set(union control *ctrl, void *dlg, char const *text) @@ -921,44 +874,48 @@ void dlg_label_change(union control *ctrl, void *dlg, char const *text) } } -void dlg_filesel_set(union control *ctrl, void *dlg, Filename fn) +void dlg_filesel_set(union control *ctrl, void *dlg, Filename *fn) { struct dlgparam *dp = (struct dlgparam *)dlg; struct uctrl *uc = dlg_find_byctrl(dp, ctrl); + /* We must copy fn->path before passing it to gtk_entry_set_text. + * See comment in dlg_editbox_set() for the reasons. */ + char *duppath = dupstr(fn->path); assert(uc->ctrl->generic.type == CTRL_FILESELECT); assert(uc->entry != NULL); - gtk_entry_set_text(GTK_ENTRY(uc->entry), fn.path); + gtk_entry_set_text(GTK_ENTRY(uc->entry), duppath); + sfree(duppath); } -void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn) +Filename *dlg_filesel_get(union control *ctrl, void *dlg) { struct dlgparam *dp = (struct dlgparam *)dlg; struct uctrl *uc = dlg_find_byctrl(dp, ctrl); assert(uc->ctrl->generic.type == CTRL_FILESELECT); assert(uc->entry != NULL); - strncpy(fn->path, gtk_entry_get_text(GTK_ENTRY(uc->entry)), - lenof(fn->path)); - fn->path[lenof(fn->path)-1] = '\0'; + return filename_from_str(gtk_entry_get_text(GTK_ENTRY(uc->entry))); } -void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fs) +void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec *fs) { struct dlgparam *dp = (struct dlgparam *)dlg; struct uctrl *uc = dlg_find_byctrl(dp, ctrl); + /* We must copy fs->name before passing it to gtk_entry_set_text. + * See comment in dlg_editbox_set() for the reasons. */ + char *dupname = dupstr(fs->name); assert(uc->ctrl->generic.type == CTRL_FONTSELECT); assert(uc->entry != NULL); - gtk_entry_set_text(GTK_ENTRY(uc->entry), fs.name); + gtk_entry_set_text(GTK_ENTRY(uc->entry), dupname); + sfree(dupname); } -void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fs) +FontSpec *dlg_fontsel_get(union control *ctrl, void *dlg) { struct dlgparam *dp = (struct dlgparam *)dlg; struct uctrl *uc = dlg_find_byctrl(dp, ctrl); assert(uc->ctrl->generic.type == CTRL_FONTSELECT); assert(uc->entry != NULL); - strncpy(fs->name, gtk_entry_get_text(GTK_ENTRY(uc->entry)), - lenof(fs->name)); - fs->name[lenof(fs->name)-1] = '\0'; + return fontspec_new(gtk_entry_get_text(GTK_ENTRY(uc->entry))); } /* @@ -1000,7 +957,7 @@ void dlg_set_focus(union control *ctrl, void *dlg) /* Anything containing an edit box gets that focused. */ gtk_widget_grab_focus(uc->entry); } -#if GTK_CHECK_VERSION(2,0,0) +#if GTK_CHECK_VERSION(2,4,0) else if (uc->combo) { /* Failing that, there'll be a combo box. */ gtk_widget_grab_focus(uc->combo); @@ -1022,29 +979,34 @@ void dlg_set_focus(union control *ctrl, void *dlg) } break; case CTRL_LISTBOX: -#if !GTK_CHECK_VERSION(2,0,0) - /* - * If the list is really an option menu, we focus it. - * Otherwise we tell it to focus one of its children, which - * appears to do the Right Thing. - */ +#if !GTK_CHECK_VERSION(2,4,0) if (uc->optmenu) { gtk_widget_grab_focus(uc->optmenu); - } else { - assert(uc->list != NULL); + break; + } +#else + if (uc->combo) { + gtk_widget_grab_focus(uc->combo); + break; + } +#endif +#if !GTK_CHECK_VERSION(2,0,0) + if (uc->list) { + /* + * For GTK-1 style list boxes, we tell it to focus one + * of its children, which appears to do the Right + * Thing. + */ gtk_container_focus(GTK_CONTAINER(uc->list), GTK_DIR_TAB_FORWARD); + break; } #else - /* - * There might be a combo box (drop-down list) here, or a - * proper list box. - */ if (uc->treeview) { gtk_widget_grab_focus(uc->treeview); - } else if (uc->combo) { - gtk_widget_grab_focus(uc->combo); + break; } #endif + assert(!"We shouldn't get here"); break; } } @@ -1093,7 +1055,7 @@ static void set_transient_window_pos(GtkWidget *parent, GtkWidget *child) gtk_widget_set_uposition(GTK_WIDGET(child), dx, dy); } -void dlg_error_msg(void *dlg, char *msg) +void dlg_error_msg(void *dlg, const char *msg) { struct dlgparam *dp = (struct dlgparam *)dlg; GtkWidget *window, *hbox, *text, *ok; @@ -1437,15 +1399,6 @@ static void list_selchange(GtkList *list, gpointer data) uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_SELCHANGE); } -static void menuitem_activate(GtkMenuItem *item, gpointer data) -{ - struct dlgparam *dp = (struct dlgparam *)data; - GtkWidget *menushell = GTK_WIDGET(item)->parent; - gpointer optmenu = gtk_object_get_data(GTK_OBJECT(menushell), "user-data"); - struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(optmenu)); - uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_SELCHANGE); -} - static void draglist_move(struct dlgparam *dp, struct uctrl *uc, int direction) { int index = dlg_listbox_index(uc->ctrl, dp); @@ -1500,14 +1453,6 @@ static void listbox_doubleclick(GtkTreeView *treeview, GtkTreePath *path, uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_ACTION); } -static void droplist_selchange(GtkComboBox *combo, gpointer data) -{ - struct dlgparam *dp = (struct dlgparam *)data; - struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(combo)); - if (uc) - uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_SELCHANGE); -} - static void listbox_selchange(GtkTreeSelection *treeselection, gpointer data) { @@ -1575,6 +1520,29 @@ static void listbox_reorder(GtkTreeModel *treemodel, GtkTreePath *path, #endif /* !GTK_CHECK_VERSION(2,0,0) */ +#if !GTK_CHECK_VERSION(2,4,0) + +static void menuitem_activate(GtkMenuItem *item, gpointer data) +{ + struct dlgparam *dp = (struct dlgparam *)data; + GtkWidget *menushell = GTK_WIDGET(item)->parent; + gpointer optmenu = gtk_object_get_data(GTK_OBJECT(menushell), "user-data"); + struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(optmenu)); + uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_SELCHANGE); +} + +#else + +static void droplist_selchange(GtkComboBox *combo, gpointer data) +{ + struct dlgparam *dp = (struct dlgparam *)data; + struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(combo)); + if (uc) + uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_SELCHANGE); +} + +#endif /* !GTK_CHECK_VERSION(2,4,0) */ + static void filesel_ok(GtkButton *button, gpointer data) { /* struct dlgparam *dp = (struct dlgparam *)data; */ @@ -1832,14 +1800,15 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, uc = snew(struct uctrl); uc->ctrl = ctrl; - uc->privdata = NULL; - uc->privdata_needs_free = FALSE; uc->buttons = NULL; uc->entry = NULL; -#if !GTK_CHECK_VERSION(2,0,0) +#if !GTK_CHECK_VERSION(2,4,0) uc->list = uc->menu = uc->optmenu = NULL; #else - uc->combo = uc->treeview = NULL; + uc->combo = NULL; +#endif +#if GTK_CHECK_VERSION(2,0,0) + uc->treeview = NULL; uc->listmodel = NULL; #endif uc->button = uc->text = NULL; @@ -1938,7 +1907,7 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, GtkWidget *signalobject; if (ctrl->editbox.has_list) { -#if !GTK_CHECK_VERSION(2,0,0) +#if !GTK_CHECK_VERSION(2,4,0) /* * GTK 1 combo box. */ @@ -2029,7 +1998,7 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, { GtkWidget *ww; GtkRequisition req; - char *browsebtn = + const char *browsebtn = (ctrl->generic.type == CTRL_FILESELECT ? "Browse..." : "Change..."); @@ -2075,12 +2044,45 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, break; case CTRL_LISTBOX: -#if !GTK_CHECK_VERSION(2,0,0) +#if GTK_CHECK_VERSION(2,0,0) /* - * GTK 1 list box setup. + * First construct the list data store, with the right + * number of columns. */ +# if !GTK_CHECK_VERSION(2,4,0) + /* (For GTK 2.0 to 2.3, we do this for full listboxes only, + * because combo boxes are still done the old GTK1 way.) */ + if (ctrl->listbox.height > 0) +# endif + { + GType *types; + int i; + int cols; + + cols = ctrl->listbox.ncols; + cols = cols ? cols : 1; + types = snewn(1 + cols, GType); + + types[0] = G_TYPE_INT; + for (i = 0; i < cols; i++) + types[i+1] = G_TYPE_STRING; + + uc->listmodel = gtk_list_store_newv(1 + cols, types); + + sfree(types); + } +#endif - if (ctrl->listbox.height == 0) { + /* + * See if it's a drop-down list (non-editable combo + * box). + */ + if (ctrl->listbox.height == 0) { +#if !GTK_CHECK_VERSION(2,4,0) + /* + * GTK1 and early-GTK2 option-menu style of + * drop-down list. + */ uc->optmenu = w = gtk_option_menu_new(); uc->menu = gtk_menu_new(); gtk_option_menu_set_menu(GTK_OPTION_MENU(w), uc->menu); @@ -2088,7 +2090,41 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, (gpointer)uc->optmenu); gtk_signal_connect(GTK_OBJECT(uc->optmenu), "focus_in_event", GTK_SIGNAL_FUNC(widget_focus), dp); +#else + /* + * Late-GTK2 style using a GtkComboBox. + */ + GtkCellRenderer *cr; + + /* + * Create a non-editable GtkComboBox (that is, not + * its subclass GtkComboBoxEntry). + */ + w = gtk_combo_box_new_with_model + (GTK_TREE_MODEL(uc->listmodel)); + uc->combo = w; + + /* + * Tell it how to render a list item (i.e. which + * column to look at in the list model). + */ + cr = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), cr, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(w), cr, + "text", 1, NULL); + + /* + * And tell it to notify us when the selection + * changes. + */ + g_signal_connect(G_OBJECT(w), "changed", + G_CALLBACK(droplist_selchange), dp); +#endif } else { +#if !GTK_CHECK_VERSION(2,0,0) + /* + * GTK1-style full list box. + */ uc->list = gtk_list_new(); if (ctrl->listbox.multisel == 2) { gtk_list_set_selection_mode(GTK_LIST(uc->list), @@ -2129,11 +2165,7 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, */ { int edge; -#if GTK_CHECK_VERSION(2,0,0) - edge = GTK_WIDGET(uc->list)->style->ythickness; -#else edge = GTK_WIDGET(uc->list)->style->klass->ythickness; -#endif gtk_widget_set_usize(w, 10, 2*edge + (ctrl->listbox.height * get_listitemheight(w))); @@ -2171,91 +2203,10 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, w = cols; } - - } - if (ctrl->generic.label) { - GtkWidget *label, *container; - - label = gtk_label_new(ctrl->generic.label); - - container = columns_new(4); - if (ctrl->listbox.percentwidth == 100) { - columns_add(COLUMNS(container), label, 0, 1); - columns_force_left_align(COLUMNS(container), label); - columns_add(COLUMNS(container), w, 0, 1); - } else { - gint percentages[2]; - percentages[1] = ctrl->listbox.percentwidth; - percentages[0] = 100 - ctrl->listbox.percentwidth; - columns_set_cols(COLUMNS(container), 2, percentages); - columns_add(COLUMNS(container), label, 0, 1); - columns_force_left_align(COLUMNS(container), label); - columns_add(COLUMNS(container), w, 1, 1); - } - gtk_widget_show(label); - gtk_widget_show(w); - shortcut_add(scs, label, ctrl->listbox.shortcut, - SHORTCUT_UCTRL, uc); - w = container; - uc->label = label; - } - -#else /* !GTK_CHECK_VERSION(2,0,0) */ - /* - * GTK 2 list box setup. - */ - /* - * First construct the list data store, with the right - * number of columns. - */ - { - GType *types; - int i; - int cols; - - cols = ctrl->listbox.ncols; - cols = cols ? cols : 1; - types = snewn(1 + cols, GType); - - types[0] = G_TYPE_INT; - for (i = 0; i < cols; i++) - types[i+1] = G_TYPE_STRING; - - uc->listmodel = gtk_list_store_newv(1 + cols, types); - - sfree(types); - } - - /* - * Drop-down lists are done completely differently. - */ - if (ctrl->listbox.height == 0) { - GtkCellRenderer *cr; - - /* - * Create a non-editable GtkComboBox (that is, not - * its subclass GtkComboBoxEntry). - */ - w = gtk_combo_box_new_with_model - (GTK_TREE_MODEL(uc->listmodel)); - uc->combo = w; - - /* - * Tell it how to render a list item (i.e. which - * column to look at in the list model). - */ - cr = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), cr, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(w), cr, - "text", 1, NULL); - +#else /* - * And tell it to notify us when the selection - * changes. + * GTK2 treeview-based full list box. */ - g_signal_connect(G_OBJECT(w), "changed", - G_CALLBACK(droplist_selchange), dp); - } else { GtkTreeSelection *sel; /* @@ -2291,15 +2242,22 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, cols = cols ? cols : 1; for (i = 0; i < cols; i++) { GtkTreeViewColumn *column; + GtkCellRenderer *cellrend; /* * It appears that GTK 2 doesn't leave us any * particularly sensible way to honour the * "percentages" specification in the ctrl * structure. */ + cellrend = gtk_cell_renderer_text_new(); + if (!ctrl->listbox.hscroll) { + gtk_object_set(GTK_OBJECT(cellrend), + "ellipsize", PANGO_ELLIPSIZE_END, + "ellipsize-set", TRUE, + NULL); + } column = gtk_tree_view_column_new_with_attributes - ("heading", gtk_cell_renderer_text_new(), - "text", i+1, (char *)NULL); + ("heading", cellrend, "text", i+1, (char *)NULL); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_append_column(GTK_TREE_VIEW(w), column); @@ -2323,7 +2281,8 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, w = scroll; } - } +#endif + } if (ctrl->generic.label) { GtkWidget *label, *container; @@ -2359,8 +2318,6 @@ GtkWidget *layout_ctrls(struct dlgparam *dp, struct Shortcuts *scs, uc->label = label; } -#endif /* !GTK_CHECK_VERSION(2,0,0) */ - break; case CTRL_TEXT: /* @@ -2585,14 +2542,7 @@ int win_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data) break; case CTRL_LISTBOX: -#if !GTK_CHECK_VERSION(2,0,0) - - /* - * If the list is really an option menu, we focus - * and click it. Otherwise we tell it to focus one - * of its children, which appears to do the Right - * Thing. - */ +#if !GTK_CHECK_VERSION(2,4,0) if (sc->uc->optmenu) { GdkEventButton bev; gint returnval; @@ -2605,24 +2555,33 @@ int win_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data) gtk_signal_emit_by_name(GTK_OBJECT(sc->uc->optmenu), "button_press_event", &bev, &returnval); - } else { - assert(sc->uc->list != NULL); - + break; + } +#else + if (sc->uc->combo) { + gtk_widget_grab_focus(sc->uc->combo); + gtk_combo_box_popup(GTK_COMBO_BOX(sc->uc->combo)); + break; + } +#endif +#if !GTK_CHECK_VERSION(2,0,0) + if (sc->uc->list) { + /* + * For GTK-1 style list boxes, we tell it to + * focus one of its children, which appears to + * do the Right Thing. + */ gtk_container_focus(GTK_CONTAINER(sc->uc->list), GTK_DIR_TAB_FORWARD); + break; } - #else - if (sc->uc->treeview) { gtk_widget_grab_focus(sc->uc->treeview); - } else if (sc->uc->combo) { - gtk_widget_grab_focus(sc->uc->combo); - gtk_combo_box_popup(GTK_COMBO_BOX(sc->uc->combo)); + break; } - #endif - + assert(!"We shouldn't get here"); break; } break; @@ -2834,12 +2793,12 @@ void set_dialog_action_area(GtkDialog *dlg, GtkWidget *w) #endif } -int do_config_box(const char *title, Config *cfg, int midsession, +int do_config_box(const char *title, Conf *conf, int midsession, int protcfginfo) { GtkWidget *window, *hbox, *vbox, *cols, *label, *tree, *treescroll, *panels, *panelvbox; - int index, level; + int index, level, protocol; struct controlbox *ctrlbox; char *path; #if GTK_CHECK_VERSION(2,0,0) @@ -2867,8 +2826,9 @@ int do_config_box(const char *title, Config *cfg, int midsession, window = gtk_dialog_new(); ctrlbox = ctrl_new_box(); - setup_config_box(ctrlbox, midsession, cfg->protocol, protcfginfo); - unix_setup_config_box(ctrlbox, midsession, cfg->protocol); + protocol = conf_get_int(conf, CONF_protocol); + setup_config_box(ctrlbox, midsession, protocol, protcfginfo); + unix_setup_config_box(ctrlbox, midsession, protocol); gtk_setup_config_box(ctrlbox, midsession, window); gtk_window_set_title(GTK_WINDOW(window), title); @@ -3103,7 +3063,7 @@ int do_config_box(const char *title, Config *cfg, int midsession, } #endif - dp.data = cfg; + dp.data = conf; dlg_refresh(NULL, &dp); dp.shortcuts = &selparams[0].shortcuts; @@ -3178,7 +3138,8 @@ static void messagebox_handler(union control *ctrl, void *dlg, if (event == EVENT_ACTION) dlg_end(dlg, ctrl->generic.context.i); } -int messagebox(GtkWidget *parentwin, char *title, char *msg, int minwid, ...) +int messagebox(GtkWidget *parentwin, const char *title, const char *msg, + int minwid, ...) { GtkWidget *window, *w0, *w1; struct controlbox *ctrlbox; @@ -3275,7 +3236,7 @@ int messagebox(GtkWidget *parentwin, char *title, char *msg, int minwid, ...) return dp.retval; } -static int string_width(char *text) +int string_width(const char *text) { GtkWidget *label = gtk_label_new(text); GtkRequisition req; @@ -3297,8 +3258,8 @@ int reallyclose(void *frontend) return ret; } -int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype, - char *keystr, char *fingerprint, +int verify_ssh_host_key(void *frontend, char *host, int port, + const char *keytype, char *keystr, char *fingerprint, void (*callback)(void *ctx, int result), void *ctx) { static const char absenttxt[] = @@ -3395,14 +3356,21 @@ void old_keyfile_warning(void) */ } -void fatal_message_box(void *window, char *msg) +void fatal_message_box(void *window, const char *msg) { messagebox(window, "PuTTY Fatal Error", msg, string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), "OK", 'o', 1, 1, NULL); } -void fatalbox(char *p, ...) +void nonfatal_message_box(void *window, const char *msg) +{ + messagebox(window, "PuTTY Error", msg, + string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), + "OK", 'o', 1, 1, NULL); +} + +void fatalbox(const char *p, ...) { va_list ap; char *msg; @@ -3414,6 +3382,17 @@ void fatalbox(char *p, ...) cleanup_exit(1); } +void nonfatal(const char *p, ...) +{ + va_list ap; + char *msg; + va_start(ap, p); + msg = dupvprintf(p, ap); + va_end(ap); + nonfatal_message_box(NULL, msg); + sfree(msg); +} + static GtkWidget *aboutbox = NULL; static void about_close_clicked(GtkButton *button, gpointer data) @@ -3426,13 +3405,13 @@ static void licence_clicked(GtkButton *button, gpointer data) { char *title; - char *licence = - "Copyright 1997-2008 Simon Tatham.\n\n" + const char *licence = + "Copyright 1997-2015 Simon Tatham.\n\n" "Portions copyright Robert de Bath, Joris van Rantwijk, Delian " "Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas " "Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, " - "Markus Kuhn, Colin Watson, and CORE SDI S.A.\n\n" + "Markus Kuhn, Colin Watson, Christopher Staite, and CORE SDI S.A.\n\n" "Permission is hereby granted, free of charge, to any person " "obtaining a copy of this software and associated documentation " @@ -3508,12 +3487,14 @@ void about_box(void *window) w, FALSE, FALSE, 5); gtk_widget_show(w); - w = gtk_label_new("Copyright 1997-2008 Simon Tatham. All rights reserved"); + w = gtk_label_new("Copyright 1997-2015 Simon Tatham. All rights reserved"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(aboutbox)->vbox), w, FALSE, FALSE, 5); gtk_widget_show(w); set_transient_window_pos(GTK_WIDGET(window), aboutbox); + gtk_window_set_transient_for(GTK_WINDOW(aboutbox), + GTK_WINDOW(window)); gtk_widget_show(aboutbox); } @@ -3536,6 +3517,7 @@ static void eventlog_destroy(GtkWidget *widget, gpointer data) es->window = NULL; sfree(es->seldata); + es->seldata = NULL; dlg_cleanup(&es->dp); ctrl_free_box(es->eventbox); } @@ -3758,7 +3740,7 @@ void logevent_dlg(void *estuff, const char *string) es->nevents++; } -int askappend(void *frontend, Filename filename, +int askappend(void *frontend, Filename *filename, void (*callback)(void *ctx, int result), void *ctx) { static const char msgtemplate[] = @@ -3770,7 +3752,7 @@ int askappend(void *frontend, Filename filename, char *mbtitle; int mbret; - message = dupprintf(msgtemplate, FILENAME_MAX, filename.path); + message = dupprintf(msgtemplate, FILENAME_MAX, filename->path); mbtitle = dupprintf("%s Log to File", appname); mbret = messagebox(get_window(frontend), mbtitle, message,