Annotation of qemu/roms/seabios/tools/kconfig/gconf.c, revision 1.1.1.1

1.1       root        1: /* Hey EMACS -*- linux-c -*- */
                      2: /*
                      3:  *
                      4:  * Copyright (C) 2002-2003 Romain Lievin <[email protected]>
                      5:  * Released under the terms of the GNU GPL v2.0.
                      6:  *
                      7:  */
                      8: 
                      9: #ifdef HAVE_CONFIG_H
                     10: #  include <config.h>
                     11: #endif
                     12: 
                     13: #include "lkc.h"
                     14: #include "images.c"
                     15: 
                     16: #include <glade/glade.h>
                     17: #include <gtk/gtk.h>
                     18: #include <glib.h>
                     19: #include <gdk/gdkkeysyms.h>
                     20: 
                     21: #include <stdio.h>
                     22: #include <string.h>
                     23: #include <unistd.h>
                     24: #include <time.h>
                     25: #include <stdlib.h>
                     26: 
                     27: //#define DEBUG
                     28: 
                     29: enum {
                     30:        SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
                     31: };
                     32: 
                     33: enum {
                     34:        OPT_NORMAL, OPT_ALL, OPT_PROMPT
                     35: };
                     36: 
                     37: static gint view_mode = FULL_VIEW;
                     38: static gboolean show_name = TRUE;
                     39: static gboolean show_range = TRUE;
                     40: static gboolean show_value = TRUE;
                     41: static gboolean resizeable = FALSE;
                     42: static int opt_mode = OPT_NORMAL;
                     43: 
                     44: GtkWidget *main_wnd = NULL;
                     45: GtkWidget *tree1_w = NULL;     // left  frame
                     46: GtkWidget *tree2_w = NULL;     // right frame
                     47: GtkWidget *text_w = NULL;
                     48: GtkWidget *hpaned = NULL;
                     49: GtkWidget *vpaned = NULL;
                     50: GtkWidget *back_btn = NULL;
                     51: GtkWidget *save_btn = NULL;
                     52: GtkWidget *save_menu_item = NULL;
                     53: 
                     54: GtkTextTag *tag1, *tag2;
                     55: GdkColor color;
                     56: 
                     57: GtkTreeStore *tree1, *tree2, *tree;
                     58: GtkTreeModel *model1, *model2;
                     59: static GtkTreeIter *parents[256];
                     60: static gint indent;
                     61: 
                     62: static struct menu *current; // current node for SINGLE view
                     63: static struct menu *browsed; // browsed node for SPLIT view
                     64: 
                     65: enum {
                     66:        COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
                     67:        COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
                     68:        COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
                     69:        COL_NUMBER
                     70: };
                     71: 
                     72: static void display_list(void);
                     73: static void display_tree(struct menu *menu);
                     74: static void display_tree_part(void);
                     75: static void update_tree(struct menu *src, GtkTreeIter * dst);
                     76: static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
                     77: static gchar **fill_row(struct menu *menu);
                     78: static void conf_changed(void);
                     79: 
                     80: /* Helping/Debugging Functions */
                     81: 
                     82: const char *dbg_sym_flags(int val)
                     83: {
                     84:        static char buf[256];
                     85: 
                     86:        bzero(buf, 256);
                     87: 
                     88:        if (val & SYMBOL_CONST)
                     89:                strcat(buf, "const/");
                     90:        if (val & SYMBOL_CHECK)
                     91:                strcat(buf, "check/");
                     92:        if (val & SYMBOL_CHOICE)
                     93:                strcat(buf, "choice/");
                     94:        if (val & SYMBOL_CHOICEVAL)
                     95:                strcat(buf, "choiceval/");
                     96:        if (val & SYMBOL_VALID)
                     97:                strcat(buf, "valid/");
                     98:        if (val & SYMBOL_OPTIONAL)
                     99:                strcat(buf, "optional/");
                    100:        if (val & SYMBOL_WRITE)
                    101:                strcat(buf, "write/");
                    102:        if (val & SYMBOL_CHANGED)
                    103:                strcat(buf, "changed/");
                    104:        if (val & SYMBOL_AUTO)
                    105:                strcat(buf, "auto/");
                    106: 
                    107:        buf[strlen(buf) - 1] = '\0';
                    108: 
                    109:        return buf;
                    110: }
                    111: 
                    112: void replace_button_icon(GladeXML * xml, GdkDrawable * window,
                    113:                         GtkStyle * style, gchar * btn_name, gchar ** xpm)
                    114: {
                    115:        GdkPixmap *pixmap;
                    116:        GdkBitmap *mask;
                    117:        GtkToolButton *button;
                    118:        GtkWidget *image;
                    119: 
                    120:        pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
                    121:                                              &style->bg[GTK_STATE_NORMAL],
                    122:                                              xpm);
                    123: 
                    124:        button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
                    125:        image = gtk_image_new_from_pixmap(pixmap, mask);
                    126:        gtk_widget_show(image);
                    127:        gtk_tool_button_set_icon_widget(button, image);
                    128: }
                    129: 
                    130: /* Main Window Initialization */
                    131: void init_main_window(const gchar * glade_file)
                    132: {
                    133:        GladeXML *xml;
                    134:        GtkWidget *widget;
                    135:        GtkTextBuffer *txtbuf;
                    136:        GtkStyle *style;
                    137: 
                    138:        xml = glade_xml_new(glade_file, "window1", NULL);
                    139:        if (!xml)
                    140:                g_error(_("GUI loading failed !\n"));
                    141:        glade_xml_signal_autoconnect(xml);
                    142: 
                    143:        main_wnd = glade_xml_get_widget(xml, "window1");
                    144:        hpaned = glade_xml_get_widget(xml, "hpaned1");
                    145:        vpaned = glade_xml_get_widget(xml, "vpaned1");
                    146:        tree1_w = glade_xml_get_widget(xml, "treeview1");
                    147:        tree2_w = glade_xml_get_widget(xml, "treeview2");
                    148:        text_w = glade_xml_get_widget(xml, "textview3");
                    149: 
                    150:        back_btn = glade_xml_get_widget(xml, "button1");
                    151:        gtk_widget_set_sensitive(back_btn, FALSE);
                    152: 
                    153:        widget = glade_xml_get_widget(xml, "show_name1");
                    154:        gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
                    155:                                       show_name);
                    156: 
                    157:        widget = glade_xml_get_widget(xml, "show_range1");
                    158:        gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
                    159:                                       show_range);
                    160: 
                    161:        widget = glade_xml_get_widget(xml, "show_data1");
                    162:        gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
                    163:                                       show_value);
                    164: 
                    165:        save_btn = glade_xml_get_widget(xml, "button3");
                    166:        save_menu_item = glade_xml_get_widget(xml, "save1");
                    167:        conf_set_changed_callback(conf_changed);
                    168: 
                    169:        style = gtk_widget_get_style(main_wnd);
                    170:        widget = glade_xml_get_widget(xml, "toolbar1");
                    171: 
                    172: #if 0  /* Use stock Gtk icons instead */
                    173:        replace_button_icon(xml, main_wnd->window, style,
                    174:                            "button1", (gchar **) xpm_back);
                    175:        replace_button_icon(xml, main_wnd->window, style,
                    176:                            "button2", (gchar **) xpm_load);
                    177:        replace_button_icon(xml, main_wnd->window, style,
                    178:                            "button3", (gchar **) xpm_save);
                    179: #endif
                    180:        replace_button_icon(xml, main_wnd->window, style,
                    181:                            "button4", (gchar **) xpm_single_view);
                    182:        replace_button_icon(xml, main_wnd->window, style,
                    183:                            "button5", (gchar **) xpm_split_view);
                    184:        replace_button_icon(xml, main_wnd->window, style,
                    185:                            "button6", (gchar **) xpm_tree_view);
                    186: 
                    187: #if 0
                    188:        switch (view_mode) {
                    189:        case SINGLE_VIEW:
                    190:                widget = glade_xml_get_widget(xml, "button4");
                    191:                g_signal_emit_by_name(widget, "clicked");
                    192:                break;
                    193:        case SPLIT_VIEW:
                    194:                widget = glade_xml_get_widget(xml, "button5");
                    195:                g_signal_emit_by_name(widget, "clicked");
                    196:                break;
                    197:        case FULL_VIEW:
                    198:                widget = glade_xml_get_widget(xml, "button6");
                    199:                g_signal_emit_by_name(widget, "clicked");
                    200:                break;
                    201:        }
                    202: #endif
                    203:        txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
                    204:        tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
                    205:                                          "foreground", "red",
                    206:                                          "weight", PANGO_WEIGHT_BOLD,
                    207:                                          NULL);
                    208:        tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
                    209:                                          /*"style", PANGO_STYLE_OBLIQUE, */
                    210:                                          NULL);
                    211: 
                    212:        gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
                    213: 
                    214:        gtk_widget_show(main_wnd);
                    215: }
                    216: 
                    217: void init_tree_model(void)
                    218: {
                    219:        gint i;
                    220: 
                    221:        tree = tree2 = gtk_tree_store_new(COL_NUMBER,
                    222:                                          G_TYPE_STRING, G_TYPE_STRING,
                    223:                                          G_TYPE_STRING, G_TYPE_STRING,
                    224:                                          G_TYPE_STRING, G_TYPE_STRING,
                    225:                                          G_TYPE_POINTER, GDK_TYPE_COLOR,
                    226:                                          G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
                    227:                                          G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
                    228:                                          G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
                    229:                                          G_TYPE_BOOLEAN);
                    230:        model2 = GTK_TREE_MODEL(tree2);
                    231: 
                    232:        for (parents[0] = NULL, i = 1; i < 256; i++)
                    233:                parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
                    234: 
                    235:        tree1 = gtk_tree_store_new(COL_NUMBER,
                    236:                                   G_TYPE_STRING, G_TYPE_STRING,
                    237:                                   G_TYPE_STRING, G_TYPE_STRING,
                    238:                                   G_TYPE_STRING, G_TYPE_STRING,
                    239:                                   G_TYPE_POINTER, GDK_TYPE_COLOR,
                    240:                                   G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
                    241:                                   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
                    242:                                   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
                    243:                                   G_TYPE_BOOLEAN);
                    244:        model1 = GTK_TREE_MODEL(tree1);
                    245: }
                    246: 
                    247: void init_left_tree(void)
                    248: {
                    249:        GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
                    250:        GtkCellRenderer *renderer;
                    251:        GtkTreeSelection *sel;
                    252:        GtkTreeViewColumn *column;
                    253: 
                    254:        gtk_tree_view_set_model(view, model1);
                    255:        gtk_tree_view_set_headers_visible(view, TRUE);
                    256:        gtk_tree_view_set_rules_hint(view, FALSE);
                    257: 
                    258:        column = gtk_tree_view_column_new();
                    259:        gtk_tree_view_append_column(view, column);
                    260:        gtk_tree_view_column_set_title(column, _("Options"));
                    261: 
                    262:        renderer = gtk_cell_renderer_toggle_new();
                    263:        gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
                    264:                                        renderer, FALSE);
                    265:        gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
                    266:                                            renderer,
                    267:                                            "active", COL_BTNACT,
                    268:                                            "inconsistent", COL_BTNINC,
                    269:                                            "visible", COL_BTNVIS,
                    270:                                            "radio", COL_BTNRAD, NULL);
                    271:        renderer = gtk_cell_renderer_text_new();
                    272:        gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
                    273:                                        renderer, FALSE);
                    274:        gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
                    275:                                            renderer,
                    276:                                            "text", COL_OPTION,
                    277:                                            "foreground-gdk",
                    278:                                            COL_COLOR, NULL);
                    279: 
                    280:        sel = gtk_tree_view_get_selection(view);
                    281:        gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
                    282:        gtk_widget_realize(tree1_w);
                    283: }
                    284: 
                    285: static void renderer_edited(GtkCellRendererText * cell,
                    286:                            const gchar * path_string,
                    287:                            const gchar * new_text, gpointer user_data);
                    288: static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
                    289:                             gchar * arg1, gpointer user_data);
                    290: 
                    291: void init_right_tree(void)
                    292: {
                    293:        GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
                    294:        GtkCellRenderer *renderer;
                    295:        GtkTreeSelection *sel;
                    296:        GtkTreeViewColumn *column;
                    297:        gint i;
                    298: 
                    299:        gtk_tree_view_set_model(view, model2);
                    300:        gtk_tree_view_set_headers_visible(view, TRUE);
                    301:        gtk_tree_view_set_rules_hint(view, FALSE);
                    302: 
                    303:        column = gtk_tree_view_column_new();
                    304:        gtk_tree_view_append_column(view, column);
                    305:        gtk_tree_view_column_set_title(column, _("Options"));
                    306: 
                    307:        renderer = gtk_cell_renderer_pixbuf_new();
                    308:        gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
                    309:                                        renderer, FALSE);
                    310:        gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
                    311:                                            renderer,
                    312:                                            "pixbuf", COL_PIXBUF,
                    313:                                            "visible", COL_PIXVIS, NULL);
                    314:        renderer = gtk_cell_renderer_toggle_new();
                    315:        gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
                    316:                                        renderer, FALSE);
                    317:        gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
                    318:                                            renderer,
                    319:                                            "active", COL_BTNACT,
                    320:                                            "inconsistent", COL_BTNINC,
                    321:                                            "visible", COL_BTNVIS,
                    322:                                            "radio", COL_BTNRAD, NULL);
                    323:        /*g_signal_connect(G_OBJECT(renderer), "toggled",
                    324:           G_CALLBACK(renderer_toggled), NULL); */
                    325:        renderer = gtk_cell_renderer_text_new();
                    326:        gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
                    327:                                        renderer, FALSE);
                    328:        gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
                    329:                                            renderer,
                    330:                                            "text", COL_OPTION,
                    331:                                            "foreground-gdk",
                    332:                                            COL_COLOR, NULL);
                    333: 
                    334:        renderer = gtk_cell_renderer_text_new();
                    335:        gtk_tree_view_insert_column_with_attributes(view, -1,
                    336:                                                    _("Name"), renderer,
                    337:                                                    "text", COL_NAME,
                    338:                                                    "foreground-gdk",
                    339:                                                    COL_COLOR, NULL);
                    340:        renderer = gtk_cell_renderer_text_new();
                    341:        gtk_tree_view_insert_column_with_attributes(view, -1,
                    342:                                                    "N", renderer,
                    343:                                                    "text", COL_NO,
                    344:                                                    "foreground-gdk",
                    345:                                                    COL_COLOR, NULL);
                    346:        renderer = gtk_cell_renderer_text_new();
                    347:        gtk_tree_view_insert_column_with_attributes(view, -1,
                    348:                                                    "M", renderer,
                    349:                                                    "text", COL_MOD,
                    350:                                                    "foreground-gdk",
                    351:                                                    COL_COLOR, NULL);
                    352:        renderer = gtk_cell_renderer_text_new();
                    353:        gtk_tree_view_insert_column_with_attributes(view, -1,
                    354:                                                    "Y", renderer,
                    355:                                                    "text", COL_YES,
                    356:                                                    "foreground-gdk",
                    357:                                                    COL_COLOR, NULL);
                    358:        renderer = gtk_cell_renderer_text_new();
                    359:        gtk_tree_view_insert_column_with_attributes(view, -1,
                    360:                                                    _("Value"), renderer,
                    361:                                                    "text", COL_VALUE,
                    362:                                                    "editable",
                    363:                                                    COL_EDIT,
                    364:                                                    "foreground-gdk",
                    365:                                                    COL_COLOR, NULL);
                    366:        g_signal_connect(G_OBJECT(renderer), "edited",
                    367:                         G_CALLBACK(renderer_edited), NULL);
                    368: 
                    369:        column = gtk_tree_view_get_column(view, COL_NAME);
                    370:        gtk_tree_view_column_set_visible(column, show_name);
                    371:        column = gtk_tree_view_get_column(view, COL_NO);
                    372:        gtk_tree_view_column_set_visible(column, show_range);
                    373:        column = gtk_tree_view_get_column(view, COL_MOD);
                    374:        gtk_tree_view_column_set_visible(column, show_range);
                    375:        column = gtk_tree_view_get_column(view, COL_YES);
                    376:        gtk_tree_view_column_set_visible(column, show_range);
                    377:        column = gtk_tree_view_get_column(view, COL_VALUE);
                    378:        gtk_tree_view_column_set_visible(column, show_value);
                    379: 
                    380:        if (resizeable) {
                    381:                for (i = 0; i < COL_VALUE; i++) {
                    382:                        column = gtk_tree_view_get_column(view, i);
                    383:                        gtk_tree_view_column_set_resizable(column, TRUE);
                    384:                }
                    385:        }
                    386: 
                    387:        sel = gtk_tree_view_get_selection(view);
                    388:        gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
                    389: }
                    390: 
                    391: 
                    392: /* Utility Functions */
                    393: 
                    394: 
                    395: static void text_insert_help(struct menu *menu)
                    396: {
                    397:        GtkTextBuffer *buffer;
                    398:        GtkTextIter start, end;
                    399:        const char *prompt = _(menu_get_prompt(menu));
                    400:        struct gstr help = str_new();
                    401: 
                    402:        menu_get_ext_help(menu, &help);
                    403: 
                    404:        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
                    405:        gtk_text_buffer_get_bounds(buffer, &start, &end);
                    406:        gtk_text_buffer_delete(buffer, &start, &end);
                    407:        gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
                    408: 
                    409:        gtk_text_buffer_get_end_iter(buffer, &end);
                    410:        gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
                    411:                                         NULL);
                    412:        gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
                    413:        gtk_text_buffer_get_end_iter(buffer, &end);
                    414:        gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
                    415:                                         NULL);
                    416:        str_free(&help);
                    417: }
                    418: 
                    419: 
                    420: static void text_insert_msg(const char *title, const char *message)
                    421: {
                    422:        GtkTextBuffer *buffer;
                    423:        GtkTextIter start, end;
                    424:        const char *msg = message;
                    425: 
                    426:        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
                    427:        gtk_text_buffer_get_bounds(buffer, &start, &end);
                    428:        gtk_text_buffer_delete(buffer, &start, &end);
                    429:        gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
                    430: 
                    431:        gtk_text_buffer_get_end_iter(buffer, &end);
                    432:        gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
                    433:                                         NULL);
                    434:        gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
                    435:        gtk_text_buffer_get_end_iter(buffer, &end);
                    436:        gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
                    437:                                         NULL);
                    438: }
                    439: 
                    440: 
                    441: /* Main Windows Callbacks */
                    442: 
                    443: void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
                    444: gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
                    445:                                 gpointer user_data)
                    446: {
                    447:        GtkWidget *dialog, *label;
                    448:        gint result;
                    449: 
                    450:        if (!conf_get_changed())
                    451:                return FALSE;
                    452: 
                    453:        dialog = gtk_dialog_new_with_buttons(_("Warning !"),
                    454:                                             GTK_WINDOW(main_wnd),
                    455:                                             (GtkDialogFlags)
                    456:                                             (GTK_DIALOG_MODAL |
                    457:                                              GTK_DIALOG_DESTROY_WITH_PARENT),
                    458:                                             GTK_STOCK_OK,
                    459:                                             GTK_RESPONSE_YES,
                    460:                                             GTK_STOCK_NO,
                    461:                                             GTK_RESPONSE_NO,
                    462:                                             GTK_STOCK_CANCEL,
                    463:                                             GTK_RESPONSE_CANCEL, NULL);
                    464:        gtk_dialog_set_default_response(GTK_DIALOG(dialog),
                    465:                                        GTK_RESPONSE_CANCEL);
                    466: 
                    467:        label = gtk_label_new(_("\nSave configuration ?\n"));
                    468:        gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
                    469:        gtk_widget_show(label);
                    470: 
                    471:        result = gtk_dialog_run(GTK_DIALOG(dialog));
                    472:        switch (result) {
                    473:        case GTK_RESPONSE_YES:
                    474:                on_save_activate(NULL, NULL);
                    475:                return FALSE;
                    476:        case GTK_RESPONSE_NO:
                    477:                return FALSE;
                    478:        case GTK_RESPONSE_CANCEL:
                    479:        case GTK_RESPONSE_DELETE_EVENT:
                    480:        default:
                    481:                gtk_widget_destroy(dialog);
                    482:                return TRUE;
                    483:        }
                    484: 
                    485:        return FALSE;
                    486: }
                    487: 
                    488: 
                    489: void on_window1_destroy(GtkObject * object, gpointer user_data)
                    490: {
                    491:        gtk_main_quit();
                    492: }
                    493: 
                    494: 
                    495: void
                    496: on_window1_size_request(GtkWidget * widget,
                    497:                        GtkRequisition * requisition, gpointer user_data)
                    498: {
                    499:        static gint old_h;
                    500:        gint w, h;
                    501: 
                    502:        if (widget->window == NULL)
                    503:                gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
                    504:        else
                    505:                gdk_window_get_size(widget->window, &w, &h);
                    506: 
                    507:        if (h == old_h)
                    508:                return;
                    509:        old_h = h;
                    510: 
                    511:        gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
                    512: }
                    513: 
                    514: 
                    515: /* Menu & Toolbar Callbacks */
                    516: 
                    517: 
                    518: static void
                    519: load_filename(GtkFileSelection * file_selector, gpointer user_data)
                    520: {
                    521:        const gchar *fn;
                    522: 
                    523:        fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
                    524:                                             (user_data));
                    525: 
                    526:        if (conf_read(fn))
                    527:                text_insert_msg(_("Error"), _("Unable to load configuration !"));
                    528:        else
                    529:                display_tree(&rootmenu);
                    530: }
                    531: 
                    532: void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
                    533: {
                    534:        GtkWidget *fs;
                    535: 
                    536:        fs = gtk_file_selection_new(_("Load file..."));
                    537:        g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
                    538:                         "clicked",
                    539:                         G_CALLBACK(load_filename), (gpointer) fs);
                    540:        g_signal_connect_swapped(GTK_OBJECT
                    541:                                 (GTK_FILE_SELECTION(fs)->ok_button),
                    542:                                 "clicked", G_CALLBACK(gtk_widget_destroy),
                    543:                                 (gpointer) fs);
                    544:        g_signal_connect_swapped(GTK_OBJECT
                    545:                                 (GTK_FILE_SELECTION(fs)->cancel_button),
                    546:                                 "clicked", G_CALLBACK(gtk_widget_destroy),
                    547:                                 (gpointer) fs);
                    548:        gtk_widget_show(fs);
                    549: }
                    550: 
                    551: 
                    552: void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
                    553: {
                    554:        if (conf_write(NULL))
                    555:                text_insert_msg(_("Error"), _("Unable to save configuration !"));
                    556: }
                    557: 
                    558: 
                    559: static void
                    560: store_filename(GtkFileSelection * file_selector, gpointer user_data)
                    561: {
                    562:        const gchar *fn;
                    563: 
                    564:        fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
                    565:                                             (user_data));
                    566: 
                    567:        if (conf_write(fn))
                    568:                text_insert_msg(_("Error"), _("Unable to save configuration !"));
                    569: 
                    570:        gtk_widget_destroy(GTK_WIDGET(user_data));
                    571: }
                    572: 
                    573: void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
                    574: {
                    575:        GtkWidget *fs;
                    576: 
                    577:        fs = gtk_file_selection_new(_("Save file as..."));
                    578:        g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
                    579:                         "clicked",
                    580:                         G_CALLBACK(store_filename), (gpointer) fs);
                    581:        g_signal_connect_swapped(GTK_OBJECT
                    582:                                 (GTK_FILE_SELECTION(fs)->ok_button),
                    583:                                 "clicked", G_CALLBACK(gtk_widget_destroy),
                    584:                                 (gpointer) fs);
                    585:        g_signal_connect_swapped(GTK_OBJECT
                    586:                                 (GTK_FILE_SELECTION(fs)->cancel_button),
                    587:                                 "clicked", G_CALLBACK(gtk_widget_destroy),
                    588:                                 (gpointer) fs);
                    589:        gtk_widget_show(fs);
                    590: }
                    591: 
                    592: 
                    593: void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
                    594: {
                    595:        if (!on_window1_delete_event(NULL, NULL, NULL))
                    596:                gtk_widget_destroy(GTK_WIDGET(main_wnd));
                    597: }
                    598: 
                    599: 
                    600: void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
                    601: {
                    602:        GtkTreeViewColumn *col;
                    603: 
                    604:        show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
                    605:        col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
                    606:        if (col)
                    607:                gtk_tree_view_column_set_visible(col, show_name);
                    608: }
                    609: 
                    610: 
                    611: void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
                    612: {
                    613:        GtkTreeViewColumn *col;
                    614: 
                    615:        show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
                    616:        col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
                    617:        if (col)
                    618:                gtk_tree_view_column_set_visible(col, show_range);
                    619:        col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
                    620:        if (col)
                    621:                gtk_tree_view_column_set_visible(col, show_range);
                    622:        col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
                    623:        if (col)
                    624:                gtk_tree_view_column_set_visible(col, show_range);
                    625: 
                    626: }
                    627: 
                    628: 
                    629: void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
                    630: {
                    631:        GtkTreeViewColumn *col;
                    632: 
                    633:        show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
                    634:        col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
                    635:        if (col)
                    636:                gtk_tree_view_column_set_visible(col, show_value);
                    637: }
                    638: 
                    639: 
                    640: void
                    641: on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
                    642: {
                    643:        opt_mode = OPT_NORMAL;
                    644:        gtk_tree_store_clear(tree2);
                    645:        display_tree(&rootmenu);        /* instead of update_tree to speed-up */
                    646: }
                    647: 
                    648: 
                    649: void
                    650: on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
                    651: {
                    652:        opt_mode = OPT_ALL;
                    653:        gtk_tree_store_clear(tree2);
                    654:        display_tree(&rootmenu);        /* instead of update_tree to speed-up */
                    655: }
                    656: 
                    657: 
                    658: void
                    659: on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
                    660: {
                    661:        opt_mode = OPT_PROMPT;
                    662:        gtk_tree_store_clear(tree2);
                    663:        display_tree(&rootmenu);        /* instead of update_tree to speed-up */
                    664: }
                    665: 
                    666: 
                    667: void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
                    668: {
                    669:        GtkWidget *dialog;
                    670:        const gchar *intro_text = _(
                    671:            "Welcome to gkc, the GTK+ graphical configuration tool\n"
                    672:            "For each option, a blank box indicates the feature is disabled, a\n"
                    673:            "check indicates it is enabled, and a dot indicates that it is to\n"
                    674:            "be compiled as a module.  Clicking on the box will cycle through the three states.\n"
                    675:            "\n"
                    676:            "If you do not see an option (e.g., a device driver) that you\n"
                    677:            "believe should be present, try turning on Show All Options\n"
                    678:            "under the Options menu.\n"
                    679:            "Although there is no cross reference yet to help you figure out\n"
                    680:            "what other options must be enabled to support the option you\n"
                    681:            "are interested in, you can still view the help of a grayed-out\n"
                    682:            "option.\n"
                    683:            "\n"
                    684:            "Toggling Show Debug Info under the Options menu will show \n"
                    685:            "the dependencies, which you can then match by examining other options.");
                    686: 
                    687:        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
                    688:                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                    689:                                        GTK_MESSAGE_INFO,
                    690:                                        GTK_BUTTONS_CLOSE, intro_text);
                    691:        g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
                    692:                                 G_CALLBACK(gtk_widget_destroy),
                    693:                                 GTK_OBJECT(dialog));
                    694:        gtk_widget_show_all(dialog);
                    695: }
                    696: 
                    697: 
                    698: void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
                    699: {
                    700:        GtkWidget *dialog;
                    701:        const gchar *about_text =
                    702:            _("gkc is copyright (c) 2002 Romain Lievin <[email protected]>.\n"
                    703:              "Based on the source code from Roman Zippel.\n");
                    704: 
                    705:        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
                    706:                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                    707:                                        GTK_MESSAGE_INFO,
                    708:                                        GTK_BUTTONS_CLOSE, about_text);
                    709:        g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
                    710:                                 G_CALLBACK(gtk_widget_destroy),
                    711:                                 GTK_OBJECT(dialog));
                    712:        gtk_widget_show_all(dialog);
                    713: }
                    714: 
                    715: 
                    716: void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
                    717: {
                    718:        GtkWidget *dialog;
                    719:        const gchar *license_text =
                    720:            _("gkc is released under the terms of the GNU GPL v2.\n"
                    721:              "For more information, please see the source code or\n"
                    722:              "visit http://www.fsf.org/licenses/licenses.html\n");
                    723: 
                    724:        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
                    725:                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                    726:                                        GTK_MESSAGE_INFO,
                    727:                                        GTK_BUTTONS_CLOSE, license_text);
                    728:        g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
                    729:                                 G_CALLBACK(gtk_widget_destroy),
                    730:                                 GTK_OBJECT(dialog));
                    731:        gtk_widget_show_all(dialog);
                    732: }
                    733: 
                    734: 
                    735: void on_back_clicked(GtkButton * button, gpointer user_data)
                    736: {
                    737:        enum prop_type ptype;
                    738: 
                    739:        current = current->parent;
                    740:        ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
                    741:        if (ptype != P_MENU)
                    742:                current = current->parent;
                    743:        display_tree_part();
                    744: 
                    745:        if (current == &rootmenu)
                    746:                gtk_widget_set_sensitive(back_btn, FALSE);
                    747: }
                    748: 
                    749: 
                    750: void on_load_clicked(GtkButton * button, gpointer user_data)
                    751: {
                    752:        on_load1_activate(NULL, user_data);
                    753: }
                    754: 
                    755: 
                    756: void on_single_clicked(GtkButton * button, gpointer user_data)
                    757: {
                    758:        view_mode = SINGLE_VIEW;
                    759:        gtk_paned_set_position(GTK_PANED(hpaned), 0);
                    760:        gtk_widget_hide(tree1_w);
                    761:        current = &rootmenu;
                    762:        display_tree_part();
                    763: }
                    764: 
                    765: 
                    766: void on_split_clicked(GtkButton * button, gpointer user_data)
                    767: {
                    768:        gint w, h;
                    769:        view_mode = SPLIT_VIEW;
                    770:        gtk_widget_show(tree1_w);
                    771:        gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
                    772:        gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
                    773:        if (tree2)
                    774:                gtk_tree_store_clear(tree2);
                    775:        display_list();
                    776: 
                    777:        /* Disable back btn, like in full mode. */
                    778:        gtk_widget_set_sensitive(back_btn, FALSE);
                    779: }
                    780: 
                    781: 
                    782: void on_full_clicked(GtkButton * button, gpointer user_data)
                    783: {
                    784:        view_mode = FULL_VIEW;
                    785:        gtk_paned_set_position(GTK_PANED(hpaned), 0);
                    786:        gtk_widget_hide(tree1_w);
                    787:        if (tree2)
                    788:                gtk_tree_store_clear(tree2);
                    789:        display_tree(&rootmenu);
                    790:        gtk_widget_set_sensitive(back_btn, FALSE);
                    791: }
                    792: 
                    793: 
                    794: void on_collapse_clicked(GtkButton * button, gpointer user_data)
                    795: {
                    796:        gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
                    797: }
                    798: 
                    799: 
                    800: void on_expand_clicked(GtkButton * button, gpointer user_data)
                    801: {
                    802:        gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
                    803: }
                    804: 
                    805: 
                    806: /* CTree Callbacks */
                    807: 
                    808: /* Change hex/int/string value in the cell */
                    809: static void renderer_edited(GtkCellRendererText * cell,
                    810:                            const gchar * path_string,
                    811:                            const gchar * new_text, gpointer user_data)
                    812: {
                    813:        GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
                    814:        GtkTreeIter iter;
                    815:        const char *old_def, *new_def;
                    816:        struct menu *menu;
                    817:        struct symbol *sym;
                    818: 
                    819:        if (!gtk_tree_model_get_iter(model2, &iter, path))
                    820:                return;
                    821: 
                    822:        gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
                    823:        sym = menu->sym;
                    824: 
                    825:        gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
                    826:        new_def = new_text;
                    827: 
                    828:        sym_set_string_value(sym, new_def);
                    829: 
                    830:        update_tree(&rootmenu, NULL);
                    831: 
                    832:        gtk_tree_path_free(path);
                    833: }
                    834: 
                    835: /* Change the value of a symbol and update the tree */
                    836: static void change_sym_value(struct menu *menu, gint col)
                    837: {
                    838:        struct symbol *sym = menu->sym;
                    839:        tristate oldval, newval;
                    840: 
                    841:        if (!sym)
                    842:                return;
                    843: 
                    844:        if (col == COL_NO)
                    845:                newval = no;
                    846:        else if (col == COL_MOD)
                    847:                newval = mod;
                    848:        else if (col == COL_YES)
                    849:                newval = yes;
                    850:        else
                    851:                return;
                    852: 
                    853:        switch (sym_get_type(sym)) {
                    854:        case S_BOOLEAN:
                    855:        case S_TRISTATE:
                    856:                oldval = sym_get_tristate_value(sym);
                    857:                if (!sym_tristate_within_range(sym, newval))
                    858:                        newval = yes;
                    859:                sym_set_tristate_value(sym, newval);
                    860:                if (view_mode == FULL_VIEW)
                    861:                        update_tree(&rootmenu, NULL);
                    862:                else if (view_mode == SPLIT_VIEW) {
                    863:                        update_tree(browsed, NULL);
                    864:                        display_list();
                    865:                }
                    866:                else if (view_mode == SINGLE_VIEW)
                    867:                        display_tree_part();    //fixme: keep exp/coll
                    868:                break;
                    869:        case S_INT:
                    870:        case S_HEX:
                    871:        case S_STRING:
                    872:        default:
                    873:                break;
                    874:        }
                    875: }
                    876: 
                    877: static void toggle_sym_value(struct menu *menu)
                    878: {
                    879:        if (!menu->sym)
                    880:                return;
                    881: 
                    882:        sym_toggle_tristate_value(menu->sym);
                    883:        if (view_mode == FULL_VIEW)
                    884:                update_tree(&rootmenu, NULL);
                    885:        else if (view_mode == SPLIT_VIEW) {
                    886:                update_tree(browsed, NULL);
                    887:                display_list();
                    888:        }
                    889:        else if (view_mode == SINGLE_VIEW)
                    890:                display_tree_part();    //fixme: keep exp/coll
                    891: }
                    892: 
                    893: static void renderer_toggled(GtkCellRendererToggle * cell,
                    894:                             gchar * path_string, gpointer user_data)
                    895: {
                    896:        GtkTreePath *path, *sel_path = NULL;
                    897:        GtkTreeIter iter, sel_iter;
                    898:        GtkTreeSelection *sel;
                    899:        struct menu *menu;
                    900: 
                    901:        path = gtk_tree_path_new_from_string(path_string);
                    902:        if (!gtk_tree_model_get_iter(model2, &iter, path))
                    903:                return;
                    904: 
                    905:        sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
                    906:        if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
                    907:                sel_path = gtk_tree_model_get_path(model2, &sel_iter);
                    908:        if (!sel_path)
                    909:                goto out1;
                    910:        if (gtk_tree_path_compare(path, sel_path))
                    911:                goto out2;
                    912: 
                    913:        gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
                    914:        toggle_sym_value(menu);
                    915: 
                    916:       out2:
                    917:        gtk_tree_path_free(sel_path);
                    918:       out1:
                    919:        gtk_tree_path_free(path);
                    920: }
                    921: 
                    922: static gint column2index(GtkTreeViewColumn * column)
                    923: {
                    924:        gint i;
                    925: 
                    926:        for (i = 0; i < COL_NUMBER; i++) {
                    927:                GtkTreeViewColumn *col;
                    928: 
                    929:                col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
                    930:                if (col == column)
                    931:                        return i;
                    932:        }
                    933: 
                    934:        return -1;
                    935: }
                    936: 
                    937: 
                    938: /* User click: update choice (full) or goes down (single) */
                    939: gboolean
                    940: on_treeview2_button_press_event(GtkWidget * widget,
                    941:                                GdkEventButton * event, gpointer user_data)
                    942: {
                    943:        GtkTreeView *view = GTK_TREE_VIEW(widget);
                    944:        GtkTreePath *path;
                    945:        GtkTreeViewColumn *column;
                    946:        GtkTreeIter iter;
                    947:        struct menu *menu;
                    948:        gint col;
                    949: 
                    950: #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
                    951:        gint tx = (gint) event->x;
                    952:        gint ty = (gint) event->y;
                    953:        gint cx, cy;
                    954: 
                    955:        gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
                    956:                                      &cy);
                    957: #else
                    958:        gtk_tree_view_get_cursor(view, &path, &column);
                    959: #endif
                    960:        if (path == NULL)
                    961:                return FALSE;
                    962: 
                    963:        if (!gtk_tree_model_get_iter(model2, &iter, path))
                    964:                return FALSE;
                    965:        gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
                    966: 
                    967:        col = column2index(column);
                    968:        if (event->type == GDK_2BUTTON_PRESS) {
                    969:                enum prop_type ptype;
                    970:                ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
                    971: 
                    972:                if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
                    973:                        // goes down into menu
                    974:                        current = menu;
                    975:                        display_tree_part();
                    976:                        gtk_widget_set_sensitive(back_btn, TRUE);
                    977:                } else if ((col == COL_OPTION)) {
                    978:                        toggle_sym_value(menu);
                    979:                        gtk_tree_view_expand_row(view, path, TRUE);
                    980:                }
                    981:        } else {
                    982:                if (col == COL_VALUE) {
                    983:                        toggle_sym_value(menu);
                    984:                        gtk_tree_view_expand_row(view, path, TRUE);
                    985:                } else if (col == COL_NO || col == COL_MOD
                    986:                           || col == COL_YES) {
                    987:                        change_sym_value(menu, col);
                    988:                        gtk_tree_view_expand_row(view, path, TRUE);
                    989:                }
                    990:        }
                    991: 
                    992:        return FALSE;
                    993: }
                    994: 
                    995: /* Key pressed: update choice */
                    996: gboolean
                    997: on_treeview2_key_press_event(GtkWidget * widget,
                    998:                             GdkEventKey * event, gpointer user_data)
                    999: {
                   1000:        GtkTreeView *view = GTK_TREE_VIEW(widget);
                   1001:        GtkTreePath *path;
                   1002:        GtkTreeViewColumn *column;
                   1003:        GtkTreeIter iter;
                   1004:        struct menu *menu;
                   1005:        gint col;
                   1006: 
                   1007:        gtk_tree_view_get_cursor(view, &path, &column);
                   1008:        if (path == NULL)
                   1009:                return FALSE;
                   1010: 
                   1011:        if (event->keyval == GDK_space) {
                   1012:                if (gtk_tree_view_row_expanded(view, path))
                   1013:                        gtk_tree_view_collapse_row(view, path);
                   1014:                else
                   1015:                        gtk_tree_view_expand_row(view, path, FALSE);
                   1016:                return TRUE;
                   1017:        }
                   1018:        if (event->keyval == GDK_KP_Enter) {
                   1019:        }
                   1020:        if (widget == tree1_w)
                   1021:                return FALSE;
                   1022: 
                   1023:        gtk_tree_model_get_iter(model2, &iter, path);
                   1024:        gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
                   1025: 
                   1026:        if (!strcasecmp(event->string, "n"))
                   1027:                col = COL_NO;
                   1028:        else if (!strcasecmp(event->string, "m"))
                   1029:                col = COL_MOD;
                   1030:        else if (!strcasecmp(event->string, "y"))
                   1031:                col = COL_YES;
                   1032:        else
                   1033:                col = -1;
                   1034:        change_sym_value(menu, col);
                   1035: 
                   1036:        return FALSE;
                   1037: }
                   1038: 
                   1039: 
                   1040: /* Row selection changed: update help */
                   1041: void
                   1042: on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
                   1043: {
                   1044:        GtkTreeSelection *selection;
                   1045:        GtkTreeIter iter;
                   1046:        struct menu *menu;
                   1047: 
                   1048:        selection = gtk_tree_view_get_selection(treeview);
                   1049:        if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
                   1050:                gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
                   1051:                text_insert_help(menu);
                   1052:        }
                   1053: }
                   1054: 
                   1055: 
                   1056: /* User click: display sub-tree in the right frame. */
                   1057: gboolean
                   1058: on_treeview1_button_press_event(GtkWidget * widget,
                   1059:                                GdkEventButton * event, gpointer user_data)
                   1060: {
                   1061:        GtkTreeView *view = GTK_TREE_VIEW(widget);
                   1062:        GtkTreePath *path;
                   1063:        GtkTreeViewColumn *column;
                   1064:        GtkTreeIter iter;
                   1065:        struct menu *menu;
                   1066: 
                   1067:        gint tx = (gint) event->x;
                   1068:        gint ty = (gint) event->y;
                   1069:        gint cx, cy;
                   1070: 
                   1071:        gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
                   1072:                                      &cy);
                   1073:        if (path == NULL)
                   1074:                return FALSE;
                   1075: 
                   1076:        gtk_tree_model_get_iter(model1, &iter, path);
                   1077:        gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
                   1078: 
                   1079:        if (event->type == GDK_2BUTTON_PRESS) {
                   1080:                toggle_sym_value(menu);
                   1081:                current = menu;
                   1082:                display_tree_part();
                   1083:        } else {
                   1084:                browsed = menu;
                   1085:                display_tree_part();
                   1086:        }
                   1087: 
                   1088:        gtk_widget_realize(tree2_w);
                   1089:        gtk_tree_view_set_cursor(view, path, NULL, FALSE);
                   1090:        gtk_widget_grab_focus(tree2_w);
                   1091: 
                   1092:        return FALSE;
                   1093: }
                   1094: 
                   1095: 
                   1096: /* Fill a row of strings */
                   1097: static gchar **fill_row(struct menu *menu)
                   1098: {
                   1099:        static gchar *row[COL_NUMBER];
                   1100:        struct symbol *sym = menu->sym;
                   1101:        const char *def;
                   1102:        int stype;
                   1103:        tristate val;
                   1104:        enum prop_type ptype;
                   1105:        int i;
                   1106: 
                   1107:        for (i = COL_OPTION; i <= COL_COLOR; i++)
                   1108:                g_free(row[i]);
                   1109:        bzero(row, sizeof(row));
                   1110: 
                   1111:        row[COL_OPTION] =
                   1112:            g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
                   1113:                            sym && !sym_has_value(sym) ? "(NEW)" : "");
                   1114: 
                   1115:        if (opt_mode == OPT_ALL && !menu_is_visible(menu))
                   1116:                row[COL_COLOR] = g_strdup("DarkGray");
                   1117:        else if (opt_mode == OPT_PROMPT &&
                   1118:                        menu_has_prompt(menu) && !menu_is_visible(menu))
                   1119:                row[COL_COLOR] = g_strdup("DarkGray");
                   1120:        else
                   1121:                row[COL_COLOR] = g_strdup("Black");
                   1122: 
                   1123:        ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
                   1124:        switch (ptype) {
                   1125:        case P_MENU:
                   1126:                row[COL_PIXBUF] = (gchar *) xpm_menu;
                   1127:                if (view_mode == SINGLE_VIEW)
                   1128:                        row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
                   1129:                row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
                   1130:                break;
                   1131:        case P_COMMENT:
                   1132:                row[COL_PIXBUF] = (gchar *) xpm_void;
                   1133:                row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
                   1134:                row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
                   1135:                break;
                   1136:        default:
                   1137:                row[COL_PIXBUF] = (gchar *) xpm_void;
                   1138:                row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
                   1139:                row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
                   1140:                break;
                   1141:        }
                   1142: 
                   1143:        if (!sym)
                   1144:                return row;
                   1145:        row[COL_NAME] = g_strdup(sym->name);
                   1146: 
                   1147:        sym_calc_value(sym);
                   1148:        sym->flags &= ~SYMBOL_CHANGED;
                   1149: 
                   1150:        if (sym_is_choice(sym)) {       // parse childs for getting final value
                   1151:                struct menu *child;
                   1152:                struct symbol *def_sym = sym_get_choice_value(sym);
                   1153:                struct menu *def_menu = NULL;
                   1154: 
                   1155:                row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
                   1156: 
                   1157:                for (child = menu->list; child; child = child->next) {
                   1158:                        if (menu_is_visible(child)
                   1159:                            && child->sym == def_sym)
                   1160:                                def_menu = child;
                   1161:                }
                   1162: 
                   1163:                if (def_menu)
                   1164:                        row[COL_VALUE] =
                   1165:                            g_strdup(_(menu_get_prompt(def_menu)));
                   1166:        }
                   1167:        if (sym->flags & SYMBOL_CHOICEVAL)
                   1168:                row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
                   1169: 
                   1170:        stype = sym_get_type(sym);
                   1171:        switch (stype) {
                   1172:        case S_BOOLEAN:
                   1173:                if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
                   1174:                        row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
                   1175:                if (sym_is_choice(sym))
                   1176:                        break;
                   1177:        case S_TRISTATE:
                   1178:                val = sym_get_tristate_value(sym);
                   1179:                switch (val) {
                   1180:                case no:
                   1181:                        row[COL_NO] = g_strdup("N");
                   1182:                        row[COL_VALUE] = g_strdup("N");
                   1183:                        row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
                   1184:                        row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
                   1185:                        break;
                   1186:                case mod:
                   1187:                        row[COL_MOD] = g_strdup("M");
                   1188:                        row[COL_VALUE] = g_strdup("M");
                   1189:                        row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
                   1190:                        break;
                   1191:                case yes:
                   1192:                        row[COL_YES] = g_strdup("Y");
                   1193:                        row[COL_VALUE] = g_strdup("Y");
                   1194:                        row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
                   1195:                        row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
                   1196:                        break;
                   1197:                }
                   1198: 
                   1199:                if (val != no && sym_tristate_within_range(sym, no))
                   1200:                        row[COL_NO] = g_strdup("_");
                   1201:                if (val != mod && sym_tristate_within_range(sym, mod))
                   1202:                        row[COL_MOD] = g_strdup("_");
                   1203:                if (val != yes && sym_tristate_within_range(sym, yes))
                   1204:                        row[COL_YES] = g_strdup("_");
                   1205:                break;
                   1206:        case S_INT:
                   1207:        case S_HEX:
                   1208:        case S_STRING:
                   1209:                def = sym_get_string_value(sym);
                   1210:                row[COL_VALUE] = g_strdup(def);
                   1211:                row[COL_EDIT] = GINT_TO_POINTER(TRUE);
                   1212:                row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
                   1213:                break;
                   1214:        }
                   1215: 
                   1216:        return row;
                   1217: }
                   1218: 
                   1219: 
                   1220: /* Set the node content with a row of strings */
                   1221: static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
                   1222: {
                   1223:        GdkColor color;
                   1224:        gboolean success;
                   1225:        GdkPixbuf *pix;
                   1226: 
                   1227:        pix = gdk_pixbuf_new_from_xpm_data((const char **)
                   1228:                                           row[COL_PIXBUF]);
                   1229: 
                   1230:        gdk_color_parse(row[COL_COLOR], &color);
                   1231:        gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
                   1232:                                  FALSE, FALSE, &success);
                   1233: 
                   1234:        gtk_tree_store_set(tree, node,
                   1235:                           COL_OPTION, row[COL_OPTION],
                   1236:                           COL_NAME, row[COL_NAME],
                   1237:                           COL_NO, row[COL_NO],
                   1238:                           COL_MOD, row[COL_MOD],
                   1239:                           COL_YES, row[COL_YES],
                   1240:                           COL_VALUE, row[COL_VALUE],
                   1241:                           COL_MENU, (gpointer) menu,
                   1242:                           COL_COLOR, &color,
                   1243:                           COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
                   1244:                           COL_PIXBUF, pix,
                   1245:                           COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
                   1246:                           COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
                   1247:                           COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
                   1248:                           COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
                   1249:                           COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
                   1250:                           -1);
                   1251: 
                   1252:        g_object_unref(pix);
                   1253: }
                   1254: 
                   1255: 
                   1256: /* Add a node to the tree */
                   1257: static void place_node(struct menu *menu, char **row)
                   1258: {
                   1259:        GtkTreeIter *parent = parents[indent - 1];
                   1260:        GtkTreeIter *node = parents[indent];
                   1261: 
                   1262:        gtk_tree_store_append(tree, node, parent);
                   1263:        set_node(node, menu, row);
                   1264: }
                   1265: 
                   1266: 
                   1267: /* Find a node in the GTK+ tree */
                   1268: static GtkTreeIter found;
                   1269: 
                   1270: /*
                   1271:  * Find a menu in the GtkTree starting at parent.
                   1272:  */
                   1273: GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
                   1274:                                    struct menu *tofind)
                   1275: {
                   1276:        GtkTreeIter iter;
                   1277:        GtkTreeIter *child = &iter;
                   1278:        gboolean valid;
                   1279:        GtkTreeIter *ret;
                   1280: 
                   1281:        valid = gtk_tree_model_iter_children(model2, child, parent);
                   1282:        while (valid) {
                   1283:                struct menu *menu;
                   1284: 
                   1285:                gtk_tree_model_get(model2, child, 6, &menu, -1);
                   1286: 
                   1287:                if (menu == tofind) {
                   1288:                        memcpy(&found, child, sizeof(GtkTreeIter));
                   1289:                        return &found;
                   1290:                }
                   1291: 
                   1292:                ret = gtktree_iter_find_node(child, tofind);
                   1293:                if (ret)
                   1294:                        return ret;
                   1295: 
                   1296:                valid = gtk_tree_model_iter_next(model2, child);
                   1297:        }
                   1298: 
                   1299:        return NULL;
                   1300: }
                   1301: 
                   1302: 
                   1303: /*
                   1304:  * Update the tree by adding/removing entries
                   1305:  * Does not change other nodes
                   1306:  */
                   1307: static void update_tree(struct menu *src, GtkTreeIter * dst)
                   1308: {
                   1309:        struct menu *child1;
                   1310:        GtkTreeIter iter, tmp;
                   1311:        GtkTreeIter *child2 = &iter;
                   1312:        gboolean valid;
                   1313:        GtkTreeIter *sibling;
                   1314:        struct symbol *sym;
                   1315:        struct property *prop;
                   1316:        struct menu *menu1, *menu2;
                   1317: 
                   1318:        if (src == &rootmenu)
                   1319:                indent = 1;
                   1320: 
                   1321:        valid = gtk_tree_model_iter_children(model2, child2, dst);
                   1322:        for (child1 = src->list; child1; child1 = child1->next) {
                   1323: 
                   1324:                prop = child1->prompt;
                   1325:                sym = child1->sym;
                   1326: 
                   1327:              reparse:
                   1328:                menu1 = child1;
                   1329:                if (valid)
                   1330:                        gtk_tree_model_get(model2, child2, COL_MENU,
                   1331:                                           &menu2, -1);
                   1332:                else
                   1333:                        menu2 = NULL;   // force adding of a first child
                   1334: 
                   1335: #ifdef DEBUG
                   1336:                printf("%*c%s | %s\n", indent, ' ',
                   1337:                       menu1 ? menu_get_prompt(menu1) : "nil",
                   1338:                       menu2 ? menu_get_prompt(menu2) : "nil");
                   1339: #endif
                   1340: 
                   1341:                if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
                   1342:                    (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
                   1343:                    (opt_mode == OPT_ALL    && !menu_get_prompt(child1))) {
                   1344: 
                   1345:                        /* remove node */
                   1346:                        if (gtktree_iter_find_node(dst, menu1) != NULL) {
                   1347:                                memcpy(&tmp, child2, sizeof(GtkTreeIter));
                   1348:                                valid = gtk_tree_model_iter_next(model2,
                   1349:                                                                 child2);
                   1350:                                gtk_tree_store_remove(tree2, &tmp);
                   1351:                                if (!valid)
                   1352:                                        return;         /* next parent */
                   1353:                                else
                   1354:                                        goto reparse;   /* next child */
                   1355:                        } else
                   1356:                                continue;
                   1357:                }
                   1358: 
                   1359:                if (menu1 != menu2) {
                   1360:                        if (gtktree_iter_find_node(dst, menu1) == NULL) {       // add node
                   1361:                                if (!valid && !menu2)
                   1362:                                        sibling = NULL;
                   1363:                                else
                   1364:                                        sibling = child2;
                   1365:                                gtk_tree_store_insert_before(tree2,
                   1366:                                                             child2,
                   1367:                                                             dst, sibling);
                   1368:                                set_node(child2, menu1, fill_row(menu1));
                   1369:                                if (menu2 == NULL)
                   1370:                                        valid = TRUE;
                   1371:                        } else {        // remove node
                   1372:                                memcpy(&tmp, child2, sizeof(GtkTreeIter));
                   1373:                                valid = gtk_tree_model_iter_next(model2,
                   1374:                                                                 child2);
                   1375:                                gtk_tree_store_remove(tree2, &tmp);
                   1376:                                if (!valid)
                   1377:                                        return; // next parent
                   1378:                                else
                   1379:                                        goto reparse;   // next child
                   1380:                        }
                   1381:                } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
                   1382:                        set_node(child2, menu1, fill_row(menu1));
                   1383:                }
                   1384: 
                   1385:                indent++;
                   1386:                update_tree(child1, child2);
                   1387:                indent--;
                   1388: 
                   1389:                valid = gtk_tree_model_iter_next(model2, child2);
                   1390:        }
                   1391: }
                   1392: 
                   1393: 
                   1394: /* Display the whole tree (single/split/full view) */
                   1395: static void display_tree(struct menu *menu)
                   1396: {
                   1397:        struct symbol *sym;
                   1398:        struct property *prop;
                   1399:        struct menu *child;
                   1400:        enum prop_type ptype;
                   1401: 
                   1402:        if (menu == &rootmenu) {
                   1403:                indent = 1;
                   1404:                current = &rootmenu;
                   1405:        }
                   1406: 
                   1407:        for (child = menu->list; child; child = child->next) {
                   1408:                prop = child->prompt;
                   1409:                sym = child->sym;
                   1410:                ptype = prop ? prop->type : P_UNKNOWN;
                   1411: 
                   1412:                if (sym)
                   1413:                        sym->flags &= ~SYMBOL_CHANGED;
                   1414: 
                   1415:                if ((view_mode == SPLIT_VIEW)
                   1416:                    && !(child->flags & MENU_ROOT) && (tree == tree1))
                   1417:                        continue;
                   1418: 
                   1419:                if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
                   1420:                    && (tree == tree2))
                   1421:                        continue;
                   1422: 
                   1423:                if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
                   1424:                    (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
                   1425:                    (opt_mode == OPT_ALL    && menu_get_prompt(child)))
                   1426:                        place_node(child, fill_row(child));
                   1427: #ifdef DEBUG
                   1428:                printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
                   1429:                printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
                   1430:                printf("%s", prop_get_type_name(ptype));
                   1431:                printf(" | ");
                   1432:                if (sym) {
                   1433:                        printf("%s", sym_type_name(sym->type));
                   1434:                        printf(" | ");
                   1435:                        printf("%s", dbg_sym_flags(sym->flags));
                   1436:                        printf("\n");
                   1437:                } else
                   1438:                        printf("\n");
                   1439: #endif
                   1440:                if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
                   1441:                    && (tree == tree2))
                   1442:                        continue;
                   1443: /*
                   1444:                 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
                   1445:                    || (view_mode == FULL_VIEW)
                   1446:                    || (view_mode == SPLIT_VIEW))*/
                   1447:                if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
                   1448:                    || (view_mode == FULL_VIEW)
                   1449:                    || (view_mode == SPLIT_VIEW)) {
                   1450:                        indent++;
                   1451:                        display_tree(child);
                   1452:                        indent--;
                   1453:                }
                   1454:        }
                   1455: }
                   1456: 
                   1457: /* Display a part of the tree starting at current node (single/split view) */
                   1458: static void display_tree_part(void)
                   1459: {
                   1460:        if (tree2)
                   1461:                gtk_tree_store_clear(tree2);
                   1462:        if (view_mode == SINGLE_VIEW)
                   1463:                display_tree(current);
                   1464:        else if (view_mode == SPLIT_VIEW)
                   1465:                display_tree(browsed);
                   1466:        gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
                   1467: }
                   1468: 
                   1469: /* Display the list in the left frame (split view) */
                   1470: static void display_list(void)
                   1471: {
                   1472:        if (tree1)
                   1473:                gtk_tree_store_clear(tree1);
                   1474: 
                   1475:        tree = tree1;
                   1476:        display_tree(&rootmenu);
                   1477:        gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
                   1478:        tree = tree2;
                   1479: }
                   1480: 
                   1481: void fixup_rootmenu(struct menu *menu)
                   1482: {
                   1483:        struct menu *child;
                   1484:        static int menu_cnt = 0;
                   1485: 
                   1486:        menu->flags |= MENU_ROOT;
                   1487:        for (child = menu->list; child; child = child->next) {
                   1488:                if (child->prompt && child->prompt->type == P_MENU) {
                   1489:                        menu_cnt++;
                   1490:                        fixup_rootmenu(child);
                   1491:                        menu_cnt--;
                   1492:                } else if (!menu_cnt)
                   1493:                        fixup_rootmenu(child);
                   1494:        }
                   1495: }
                   1496: 
                   1497: 
                   1498: /* Main */
                   1499: int main(int ac, char *av[])
                   1500: {
                   1501:        const char *name;
                   1502:        char *env;
                   1503:        gchar *glade_file;
                   1504: 
                   1505: #ifndef LKC_DIRECT_LINK
                   1506:        kconfig_load();
                   1507: #endif
                   1508: 
                   1509:        bindtextdomain(PACKAGE, LOCALEDIR);
                   1510:        bind_textdomain_codeset(PACKAGE, "UTF-8");
                   1511:        textdomain(PACKAGE);
                   1512: 
                   1513:        /* GTK stuffs */
                   1514:        gtk_set_locale();
                   1515:        gtk_init(&ac, &av);
                   1516:        glade_init();
                   1517: 
                   1518:        //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
                   1519:        //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
                   1520: 
                   1521:        /* Determine GUI path */
                   1522:        env = getenv(SRCTREE);
                   1523:        if (env)
                   1524:                glade_file = g_strconcat(env, "/tools/kconfig/gconf.glade", NULL);
                   1525:        else if (av[0][0] == '/')
                   1526:                glade_file = g_strconcat(av[0], ".glade", NULL);
                   1527:        else
                   1528:                glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
                   1529: 
                   1530:        /* Conf stuffs */
                   1531:        if (ac > 1 && av[1][0] == '-') {
                   1532:                switch (av[1][1]) {
                   1533:                case 'a':
                   1534:                        //showAll = 1;
                   1535:                        break;
                   1536:                case 'h':
                   1537:                case '?':
                   1538:                        printf("%s <config>\n", av[0]);
                   1539:                        exit(0);
                   1540:                }
                   1541:                name = av[2];
                   1542:        } else
                   1543:                name = av[1];
                   1544: 
                   1545:        conf_parse(name);
                   1546:        fixup_rootmenu(&rootmenu);
                   1547:        conf_read(NULL);
                   1548: 
                   1549:        /* Load the interface and connect signals */
                   1550:        init_main_window(glade_file);
                   1551:        init_tree_model();
                   1552:        init_left_tree();
                   1553:        init_right_tree();
                   1554: 
                   1555:        switch (view_mode) {
                   1556:        case SINGLE_VIEW:
                   1557:                display_tree_part();
                   1558:                break;
                   1559:        case SPLIT_VIEW:
                   1560:                display_list();
                   1561:                break;
                   1562:        case FULL_VIEW:
                   1563:                display_tree(&rootmenu);
                   1564:                break;
                   1565:        }
                   1566: 
                   1567:        gtk_main();
                   1568: 
                   1569:        return 0;
                   1570: }
                   1571: 
                   1572: static void conf_changed(void)
                   1573: {
                   1574:        bool changed = conf_get_changed();
                   1575:        gtk_widget_set_sensitive(save_btn, changed);
                   1576:        gtk_widget_set_sensitive(save_menu_item, changed);
                   1577: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.