* gtkdlg.c - GTK implementation of the PuTTY configuration box.
*/
+/*
+ * TODO:
+ *
+ * - event handling, in general!
+ *
+ * - keyboard stuff
+ * + accelerators
+ * + tab order
+ * + default button
+ *
+ * - cosmetics:
+ * + can't we _somehow_ have less leading between radio buttons?
+ * + wrapping text widgets, the horror, the horror
+ * + labels and their associated edit boxes don't line up
+ * properly
+ */
+
#include <assert.h>
#include <gtk/gtk.h>
#include "putty.h"
#include "dialog.h"
-
void *dlg_get_privdata(union control *ctrl, void *dlg)
{
return NULL; /* FIXME */
* definitely a GtkWidget and should probably be added to a
* GtkVbox.)
*/
-GtkWidget *layout_ctrls(struct controlset *s)
+GtkWidget *layout_ctrls(struct controlset *s, int listitemheight)
{
Columns *cols;
GtkWidget *ret;
w = container;
}
break;
+ case CTRL_FILESELECT:
+ case CTRL_FONTSELECT:
+ {
+ GtkWidget *ww;
+ GtkRequisition req;
+ char *browsebtn =
+ (ctrl->generic.type == CTRL_FILESELECT ?
+ "Browse..." : "Change...");
+
+ gint percentages[] = { 75, 25 };
+ w = columns_new(4);
+ columns_set_cols(COLUMNS(w), 2, percentages);
+
+ if (ctrl->generic.label) {
+ ww = gtk_label_new(ctrl->generic.label);
+ columns_add(COLUMNS(w), ww, 0, 2);
+ columns_force_left_align(COLUMNS(w), ww);
+ gtk_widget_show(ww);
+ }
+
+ ww = gtk_entry_new();
+ gtk_widget_size_request(ww, &req);
+ gtk_widget_set_usize(ww, 10, req.height);
+ columns_add(COLUMNS(w), ww, 0, 1);
+ gtk_widget_show(ww);
+
+ ww = gtk_button_new_with_label(browsebtn);
+ columns_add(COLUMNS(w), ww, 1, 1);
+ gtk_widget_show(ww);
+ }
+ break;
+ case CTRL_LISTBOX:
+ if (ctrl->listbox.height == 0) {
+ w = gtk_option_menu_new();
+ } else {
+ GtkWidget *list;
+ list = gtk_list_new();
+ gtk_list_set_selection_mode(GTK_LIST(list),
+ (ctrl->listbox.multisel ?
+ GTK_SELECTION_MULTIPLE :
+ GTK_SELECTION_SINGLE));
+ w = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(w),
+ list);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_widget_show(list);
+
+ /*
+ * Adjust the height of the scrolled window to the
+ * minimum given by the height parameter.
+ *
+ * This piece of guesswork is a horrid hack based
+ * on looking inside the GTK 1.2 sources
+ * (specifically gtkviewport.c, which appears to be
+ * the widget which provides the border around the
+ * scrolling area). Anyone lets me know how I can
+ * do this in a way which isn't at risk from GTK
+ * upgrades, I'd be grateful.
+ */
+ {
+ int edge = GTK_WIDGET(list)->style->klass->ythickness;
+ gtk_widget_set_usize(w, 10,
+ 2*edge + (ctrl->listbox.height *
+ listitemheight));
+ }
+#if 1
+/* here is an example of a percentage-based tabbed list item */
+{ int i; for (i=0; i<10; i++) {
+ GtkWidget *listitem = gtk_list_item_new();
+ GtkWidget *cols = columns_new(4);
+ GtkWidget *label1 = gtk_label_new("left");
+ GtkWidget *label2 = gtk_label_new("right");
+ GList *itemlist;
+ static const gint percents[] = { 50, 50 };
+ columns_set_cols(COLUMNS(cols), 2, percents);
+ columns_add(COLUMNS(cols), label1, 0, 1);
+ columns_force_left_align(COLUMNS(cols), label1);
+ columns_add(COLUMNS(cols), label2, 1, 1);
+ columns_force_left_align(COLUMNS(cols), label2);
+ gtk_widget_show(label1);
+ gtk_widget_show(label2);
+ gtk_widget_show(cols);
+ gtk_container_add(GTK_CONTAINER(listitem), cols);
+ itemlist = g_list_append(NULL, listitem);
+ gtk_list_append_items(GTK_LIST(list), itemlist);
+ gtk_widget_show(listitem);
+} }
+#endif
+
+ if (ctrl->listbox.draglist) {
+ /*
+ * GTK doesn't appear to make it easy to
+ * implement a proper draggable list; so
+ * instead I'm just going to have to put an Up
+ * and a Down button to the right of the actual
+ * list box. Ah well.
+ */
+ GtkWidget *cols, *button;
+ static const gint percentages[2] = { 80, 20 };
+
+ cols = columns_new(4);
+ columns_set_cols(COLUMNS(cols), 2, percentages);
+ columns_add(COLUMNS(cols), w, 0, 1);
+ gtk_widget_show(w);
+ button = gtk_button_new_with_label("Up");
+ columns_add(COLUMNS(cols), button, 1, 1);
+ gtk_widget_show(button);
+ button = gtk_button_new_with_label("Down");
+ columns_add(COLUMNS(cols), button, 1, 1);
+ gtk_widget_show(button);
+
+ 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);
+
+ w = container;
+ }
+ break;
case CTRL_TEXT:
w = gtk_label_new(ctrl->generic.label);
gtk_label_set_line_wrap(GTK_LABEL(w), TRUE);
- gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_FILL);
+ /* FIXME: deal with wrapping! */
break;
}
if (w) {
{
GtkWidget *window, *hbox, *vbox, *cols, *label,
*tree, *treescroll, *panels, *panelvbox;
- int index, level;
+ int index, level, listitemheight;
struct controlbox *ctrlbox;
char *path;
GtkTreeItem *treeitemlevels[8];
do_defaults(NULL, &cfg);
+ {
+ GtkWidget *listitem = gtk_list_item_new_with_label("foo");
+ GtkRequisition req;
+ gtk_widget_size_request(listitem, &req);
+ listitemheight = req.height;
+ gtk_widget_unref(listitem);
+ }
+
ctrlbox = ctrl_new_box();
setup_config_box(ctrlbox, NULL, FALSE, 0);
+ unix_setup_config_box(ctrlbox, FALSE);
window = gtk_dialog_new();
- gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(window)->vbox), 4);
hbox = gtk_hbox_new(FALSE, 4);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), hbox, TRUE, TRUE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
gtk_widget_show(hbox);
vbox = gtk_vbox_new(FALSE, 4);
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
treescroll = gtk_scrolled_window_new(NULL, NULL);
tree = gtk_tree_new();
gtk_tree_set_view_mode(GTK_TREE(tree), GTK_TREE_VIEW_ITEM);
+ gtk_tree_set_selection_mode(GTK_TREE(tree), GTK_SELECTION_BROWSE);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(treescroll),
tree);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(treescroll),
level = 0;
for (index = 0; index < ctrlbox->nctrlsets; index++) {
struct controlset *s = ctrlbox->ctrlsets[index];
- GtkWidget *w = layout_ctrls(s);
+ GtkWidget *w = layout_ctrls(s, listitemheight);
if (!*s->pathname) {
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area),
}
gtk_box_pack_start(GTK_BOX(panelvbox), w, FALSE, FALSE, 0);
+ gtk_widget_show(w);
}
}
/* Compile command for testing:
- gcc -o gtkdlg gtk{dlg,cols,panel}.c ../{config,dialog,settings}.c \
- ../{misc,tree234,be_none}.c ux{store,misc,print}.c \
+gcc -g -o gtkdlg gtk{dlg,cols,panel}.c ../{config,dialog,settings}.c \
+ ../{misc,tree234,be_none}.c ux{store,misc,print,cfg}.c \
-I. -I.. -I../charset -DTESTMODE `gtk-config --cflags --libs`
*/
--- /dev/null
+/*
+ * uxcfg.c - the Unix-specific parts of the PuTTY configuration
+ * box.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "putty.h"
+#include "dialog.h"
+#include "storage.h"
+
+void unix_setup_config_box(struct controlbox *b, int midsession)
+{
+ struct controlset *s, *s2;
+ union control *c;
+ int i;
+
+#ifdef FIXME
+ if (!midsession) {
+ /*
+ * Add the About button to the standard panel.
+ */
+ s = ctrl_getset(b, "", "", "");
+ c = ctrl_pushbutton(s, "About", 'a', HELPCTX(no_help),
+ about_handler, P(hwndp));
+ c->generic.column = 0;
+ }
+#endif
+
+ /*
+ * The Config structure contains two Unix-specific elements
+ * which are not configured in here: stamp_utmp and
+ * login_shell. This is because pterm does not put up a
+ * configuration box right at the start, which is the only time
+ * when these elements would be useful to configure.
+ */
+
+ /*
+ * GTK makes it rather easier to put the scrollbar on the left
+ * than Windows does!
+ */
+ s = ctrl_getset(b, "Window", "scrollback",
+ "Control the scrollback in the window");
+ ctrl_checkbox(s, "Scrollbar on left", 'l',
+ HELPCTX(no_help),
+ dlg_stdcheckbox_handler,
+ I(offsetof(Config,scrollbar_on_left)));
+ /*
+ * Really this wants to go just after `Display scrollbar'. See
+ * if we can find that control, and do some shuffling.
+ */
+ for (i = 0; i < s->ncontrols; i++) {
+ c = s->ctrls[i];
+ if (c->generic.type == CTRL_CHECKBOX &&
+ c->generic.context.i == offsetof(Config,scrollbar)) {
+ /*
+ * Control i is the scrollbar checkbox.
+ * Control s->ncontrols-1 is the scrollbar-on-left one.
+ */
+ if (i < s->ncontrols-2) {
+ c = s->ctrls[s->ncontrols-1];
+ memmove(s->ctrls+i+2, s->ctrls+i+1,
+ (s->ncontrols-i-2)*sizeof(union control *));
+ s->ctrls[i+1] = c;
+ }
+ break;
+ }
+ }
+
+ /*
+ * X requires three more fonts: bold, wide, and wide-bold; also
+ * we need the fiddly shadow-bold-offset control. This would
+ * make the Window/Appearance panel rather unwieldy and large,
+ * so I think the sensible thing here is to _move_ this
+ * controlset into a separate Window/Fonts panel!
+ */
+ s2 = ctrl_getset(b, "Window/Appearance", "font",
+ "Font settings");
+ /* Remove this controlset from b. */
+ for (i = 0; i < b->nctrlsets; i++) {
+ if (b->ctrlsets[i] == s2) {
+ memmove(b->ctrlsets+i, b->ctrlsets+i+1,
+ (b->nctrlsets-i-1) * sizeof(*b->ctrlsets));
+ b->nctrlsets--;
+ break;
+ }
+ }
+ ctrl_settitle(b, "Window/Fonts", "Options controlling font usage");
+ s = ctrl_getset(b, "Window/Fonts", "font",
+ "Fonts for displaying non-bold text");
+ ctrl_fontsel(s, "Font used for ordinary text", 'w',
+ HELPCTX(no_help),
+ dlg_stdfontsel_handler, I(offsetof(Config,font)));
+ ctrl_fontsel(s, "Font used for wide (CJK) text", 'w',
+ HELPCTX(no_help),
+ dlg_stdfontsel_handler, I(offsetof(Config,widefont)));
+ s = ctrl_getset(b, "Window/Fonts", "fontbold",
+ "Fonts for displaying bolded text");
+ ctrl_fontsel(s, "Font used for bolded text", 'b',
+ HELPCTX(no_help),
+ dlg_stdfontsel_handler, I(offsetof(Config,boldfont)));
+ ctrl_fontsel(s, "Font used for bold wide text", 'i',
+ HELPCTX(no_help),
+ dlg_stdfontsel_handler, I(offsetof(Config,wideboldfont)));
+ ctrl_text(s, "If you leave the bold font selectors blank, bold text"
+ " will be displayed by overprinting (\"shadow bold\"). Note"
+ " that this only applies if you have not requested bolding"
+ " to be done by changing the text colour.",
+ HELPCTX(no_help));
+ ctrl_editbox(s, "Horizontal offset for shadow bold:", 'z', 20,
+ HELPCTX(no_help), dlg_stdeditbox_handler,
+ I(offsetof(Config,shadowboldoffset)), I(-1));
+}