base/config/kconfig/gconf.c

Go to the documentation of this file.
00001 /* Hey EMACS -*- linux-c -*- */
00002 /*
00003  *
00004  * Copyright (C) 2002-2003 Romain Lievin <roms@lpg.ticalc.org>
00005  * Released under the terms of the GNU GPL v2.0.
00006  *
00007  */
00008 
00009 #ifdef HAVE_CONFIG_H
00010 #  include <config.h>
00011 #endif
00012 
00013 #include "lkc.h"
00014 #include "images.c"
00015 
00016 #include <glade/glade.h>
00017 #include <gtk/gtk.h>
00018 #include <glib.h>
00019 #include <gdk/gdkkeysyms.h>
00020 
00021 #include <stdio.h>
00022 #include <string.h>
00023 #include <unistd.h>
00024 #include <time.h>
00025 #include <stdlib.h>
00026 
00027 //#define DEBUG
00028 
00029 enum {
00030     SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
00031 };
00032 
00033 static gint view_mode = FULL_VIEW;
00034 static gboolean show_name = TRUE;
00035 static gboolean show_range = TRUE;
00036 static gboolean show_value = TRUE;
00037 static gboolean show_all = FALSE;
00038 static gboolean show_debug = FALSE;
00039 static gboolean resizeable = FALSE;
00040 
00041 static gboolean config_changed = FALSE;
00042 
00043 static char nohelp_text[] =
00044     "Sorry, no help available for this option yet.\n";
00045 
00046 GtkWidget *main_wnd = NULL;
00047 GtkWidget *tree1_w = NULL;  // left  frame
00048 GtkWidget *tree2_w = NULL;  // right frame
00049 GtkWidget *text_w = NULL;
00050 GtkWidget *hpaned = NULL;
00051 GtkWidget *vpaned = NULL;
00052 GtkWidget *back_btn = NULL;
00053 
00054 GtkTextTag *tag1, *tag2;
00055 GdkColor color;
00056 
00057 GtkTreeStore *tree1, *tree2, *tree;
00058 GtkTreeModel *model1, *model2;
00059 static GtkTreeIter *parents[256];
00060 static gint indent;
00061 
00062 static struct menu *current; // current node for SINGLE view
00063 static struct menu *browsed; // browsed node for SPLIT view
00064 
00065 enum {
00066     COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
00067     COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
00068     COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
00069     COL_NUMBER
00070 };
00071 
00072 static void display_list(void);
00073 static void display_tree(struct menu *menu);
00074 static void display_tree_part(void);
00075 static void update_tree(struct menu *src, GtkTreeIter * dst);
00076 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
00077 static gchar **fill_row(struct menu *menu);
00078 
00079 
00080 /* Helping/Debugging Functions */
00081 
00082 
00083 const char *dbg_print_stype(int val)
00084 {
00085     static char buf[256];
00086 
00087     bzero(buf, 256);
00088 
00089     if (val == S_UNKNOWN)
00090         strcpy(buf, "unknown");
00091     if (val == S_BOOLEAN)
00092         strcpy(buf, "boolean");
00093     if (val == S_TRISTATE)
00094         strcpy(buf, "tristate");
00095     if (val == S_INT)
00096         strcpy(buf, "int");
00097     if (val == S_HEX)
00098         strcpy(buf, "hex");
00099     if (val == S_STRING)
00100         strcpy(buf, "string");
00101     if (val == S_OTHER)
00102         strcpy(buf, "other");
00103 
00104 #ifdef DEBUG
00105     printf("%s", buf);
00106 #endif
00107 
00108     return buf;
00109 }
00110 
00111 const char *dbg_print_flags(int val)
00112 {
00113     static char buf[256];
00114 
00115     bzero(buf, 256);
00116 
00117     if (val & SYMBOL_YES)
00118         strcat(buf, "yes/");
00119     if (val & SYMBOL_MOD)
00120         strcat(buf, "mod/");
00121     if (val & SYMBOL_NO)
00122         strcat(buf, "no/");
00123     if (val & SYMBOL_CONST)
00124         strcat(buf, "const/");
00125     if (val & SYMBOL_CHECK)
00126         strcat(buf, "check/");
00127     if (val & SYMBOL_CHOICE)
00128         strcat(buf, "choice/");
00129     if (val & SYMBOL_CHOICEVAL)
00130         strcat(buf, "choiceval/");
00131     if (val & SYMBOL_PRINTED)
00132         strcat(buf, "printed/");
00133     if (val & SYMBOL_VALID)
00134         strcat(buf, "valid/");
00135     if (val & SYMBOL_OPTIONAL)
00136         strcat(buf, "optional/");
00137     if (val & SYMBOL_WRITE)
00138         strcat(buf, "write/");
00139     if (val & SYMBOL_CHANGED)
00140         strcat(buf, "changed/");
00141     if (val & SYMBOL_NEW)
00142         strcat(buf, "new/");
00143     if (val & SYMBOL_AUTO)
00144         strcat(buf, "auto/");
00145 
00146     buf[strlen(buf) - 1] = '\0';
00147 #ifdef DEBUG
00148     printf("%s", buf);
00149 #endif
00150 
00151     return buf;
00152 }
00153 
00154 const char *dbg_print_ptype(int val)
00155 {
00156     static char buf[256];
00157 
00158     bzero(buf, 256);
00159 
00160     if (val == P_UNKNOWN)
00161         strcpy(buf, "unknown");
00162     if (val == P_PROMPT)
00163         strcpy(buf, "prompt");
00164     if (val == P_COMMENT)
00165         strcpy(buf, "comment");
00166     if (val == P_MENU)
00167         strcpy(buf, "menu");
00168     if (val == P_DEFAULT)
00169         strcpy(buf, "default");
00170     if (val == P_CHOICE)
00171         strcpy(buf, "choice");
00172 
00173 #ifdef DEBUG
00174     printf("%s", buf);
00175 #endif
00176 
00177     return buf;
00178 }
00179 
00180 
00181 /* Main Window Initialization */
00182 
00183 
00184 void init_main_window(const gchar * glade_file)
00185 {
00186     GladeXML *xml;
00187     GtkWidget *widget;
00188     GtkTextBuffer *txtbuf;
00189     GdkPixmap *pixmap;
00190     GdkBitmap *mask;
00191     GtkStyle *style;
00192 
00193     xml = glade_xml_new(glade_file, "window1", NULL);
00194     if (!xml)
00195         g_error("GUI loading failed !\n");
00196     glade_xml_signal_autoconnect(xml);
00197 
00198     main_wnd = glade_xml_get_widget(xml, "window1");
00199     hpaned = glade_xml_get_widget(xml, "hpaned1");
00200     vpaned = glade_xml_get_widget(xml, "vpaned1");
00201     tree1_w = glade_xml_get_widget(xml, "treeview1");
00202     tree2_w = glade_xml_get_widget(xml, "treeview2");
00203     text_w = glade_xml_get_widget(xml, "textview3");
00204 
00205     back_btn = glade_xml_get_widget(xml, "button1");
00206     gtk_widget_set_sensitive(back_btn, FALSE);
00207 
00208     widget = glade_xml_get_widget(xml, "show_name1");
00209     gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
00210                        show_name);
00211 
00212     widget = glade_xml_get_widget(xml, "show_range1");
00213     gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
00214                        show_range);
00215 
00216     widget = glade_xml_get_widget(xml, "show_data1");
00217     gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
00218                        show_value);
00219 
00220     style = gtk_widget_get_style(main_wnd);
00221     widget = glade_xml_get_widget(xml, "toolbar1");
00222 
00223     pixmap = gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask,
00224                           &style->bg[GTK_STATE_NORMAL],
00225                           (gchar **) xpm_single_view);
00226     gtk_image_set_from_pixmap(GTK_IMAGE
00227                   (((GtkToolbarChild
00228                      *) (g_list_nth(GTK_TOOLBAR(widget)->
00229                             children,
00230                             5)->data))->icon),
00231                   pixmap, mask);
00232     pixmap =
00233         gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask,
00234                      &style->bg[GTK_STATE_NORMAL],
00235                      (gchar **) xpm_split_view);
00236     gtk_image_set_from_pixmap(GTK_IMAGE
00237                   (((GtkToolbarChild
00238                      *) (g_list_nth(GTK_TOOLBAR(widget)->
00239                             children,
00240                             6)->data))->icon),
00241                   pixmap, mask);
00242     pixmap =
00243         gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask,
00244                      &style->bg[GTK_STATE_NORMAL],
00245                      (gchar **) xpm_tree_view);
00246     gtk_image_set_from_pixmap(GTK_IMAGE
00247                   (((GtkToolbarChild
00248                      *) (g_list_nth(GTK_TOOLBAR(widget)->
00249                             children,
00250                             7)->data))->icon),
00251                   pixmap, mask);
00252 
00253     switch (view_mode) {
00254     case SINGLE_VIEW:
00255         widget = glade_xml_get_widget(xml, "button4");
00256         gtk_button_clicked(GTK_BUTTON(widget));
00257         break;
00258     case SPLIT_VIEW:
00259         widget = glade_xml_get_widget(xml, "button5");
00260         gtk_button_clicked(GTK_BUTTON(widget));
00261         break;
00262     case FULL_VIEW:
00263         widget = glade_xml_get_widget(xml, "button6");
00264         gtk_button_clicked(GTK_BUTTON(widget));
00265         break;
00266     }
00267 
00268     txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
00269     tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
00270                       "foreground", "red",
00271                       "weight", PANGO_WEIGHT_BOLD,
00272                       NULL);
00273     tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
00274                       /*"style", PANGO_STYLE_OBLIQUE, */
00275                       NULL);
00276 }
00277 
00278 void init_tree_model(void)
00279 {
00280     gint i;
00281 
00282     tree = tree2 = gtk_tree_store_new(COL_NUMBER,
00283                       G_TYPE_STRING, G_TYPE_STRING,
00284                       G_TYPE_STRING, G_TYPE_STRING,
00285                       G_TYPE_STRING, G_TYPE_STRING,
00286                       G_TYPE_POINTER, GDK_TYPE_COLOR,
00287                       G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
00288                       G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
00289                       G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
00290                       G_TYPE_BOOLEAN);
00291     model2 = GTK_TREE_MODEL(tree2);
00292 
00293     for (parents[0] = NULL, i = 1; i < 256; i++)
00294         parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
00295 
00296     tree1 = gtk_tree_store_new(COL_NUMBER,
00297                    G_TYPE_STRING, G_TYPE_STRING,
00298                    G_TYPE_STRING, G_TYPE_STRING,
00299                    G_TYPE_STRING, G_TYPE_STRING,
00300                    G_TYPE_POINTER, GDK_TYPE_COLOR,
00301                    G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
00302                    G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
00303                    G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
00304                    G_TYPE_BOOLEAN);
00305     model1 = GTK_TREE_MODEL(tree1);
00306 }
00307 
00308 void init_left_tree(void)
00309 {
00310     GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
00311     GtkCellRenderer *renderer;
00312     GtkTreeSelection *sel;
00313     GtkTreeViewColumn *column;
00314 
00315     gtk_tree_view_set_model(view, model1);
00316     gtk_tree_view_set_headers_visible(view, TRUE);
00317     gtk_tree_view_set_rules_hint(view, FALSE);
00318     
00319     column = gtk_tree_view_column_new();
00320     gtk_tree_view_append_column(view, column);
00321     gtk_tree_view_column_set_title(column, "Options");
00322 
00323     renderer = gtk_cell_renderer_toggle_new();
00324     gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
00325                     renderer, FALSE);
00326     gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
00327                         renderer,
00328                         "active", COL_BTNACT,
00329                         "inconsistent", COL_BTNINC,
00330                         "visible", COL_BTNVIS, 
00331                         "radio", COL_BTNRAD, NULL);
00332     renderer = gtk_cell_renderer_text_new();
00333     gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
00334                     renderer, FALSE);   
00335     gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
00336                         renderer,
00337                         "text", COL_OPTION,
00338                         "foreground-gdk",
00339                         COL_COLOR, NULL);
00340 
00341     sel = gtk_tree_view_get_selection(view);
00342     gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
00343     gtk_widget_realize(tree1_w);
00344 }
00345 
00346 static void renderer_edited(GtkCellRendererText * cell,
00347                 const gchar * path_string,
00348                 const gchar * new_text, gpointer user_data);
00349 static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
00350                  gchar * arg1, gpointer user_data);
00351 
00352 void init_right_tree(void)
00353 {
00354     GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
00355     GtkCellRenderer *renderer;
00356     GtkTreeSelection *sel;
00357     GtkTreeViewColumn *column;
00358     gint i;
00359 
00360     gtk_tree_view_set_model(view, model2);
00361     gtk_tree_view_set_headers_visible(view, TRUE);
00362     gtk_tree_view_set_rules_hint(view, FALSE);
00363 
00364     column = gtk_tree_view_column_new();
00365     gtk_tree_view_append_column(view, column);
00366     gtk_tree_view_column_set_title(column, "Options");
00367 
00368     renderer = gtk_cell_renderer_pixbuf_new();
00369     gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
00370                     renderer, FALSE);
00371     gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
00372                         renderer,
00373                         "pixbuf", COL_PIXBUF,
00374                         "visible", COL_PIXVIS, NULL);
00375     renderer = gtk_cell_renderer_toggle_new();
00376     gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
00377                     renderer, FALSE);
00378     gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
00379                         renderer,
00380                         "active", COL_BTNACT,
00381                         "inconsistent", COL_BTNINC,
00382                         "visible", COL_BTNVIS, 
00383                         "radio", COL_BTNRAD, NULL);
00384     /*g_signal_connect(G_OBJECT(renderer), "toggled",
00385        G_CALLBACK(renderer_toggled), NULL); */
00386     renderer = gtk_cell_renderer_text_new();
00387     gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
00388                     renderer, FALSE);
00389     gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
00390                         renderer,
00391                         "text", COL_OPTION,
00392                         "foreground-gdk",
00393                         COL_COLOR, NULL);
00394 
00395     renderer = gtk_cell_renderer_text_new();
00396     gtk_tree_view_insert_column_with_attributes(view, -1,
00397                             "Name", renderer,
00398                             "text", COL_NAME,
00399                             "foreground-gdk",
00400                             COL_COLOR, NULL);
00401     renderer = gtk_cell_renderer_text_new();
00402     gtk_tree_view_insert_column_with_attributes(view, -1,
00403                             "N", renderer,
00404                             "text", COL_NO,
00405                             "foreground-gdk",
00406                             COL_COLOR, NULL);
00407     renderer = gtk_cell_renderer_text_new();
00408     gtk_tree_view_insert_column_with_attributes(view, -1,
00409                             "M", renderer,
00410                             "text", COL_MOD,
00411                             "foreground-gdk",
00412                             COL_COLOR, NULL);
00413     renderer = gtk_cell_renderer_text_new();
00414     gtk_tree_view_insert_column_with_attributes(view, -1,
00415                             "Y", renderer,
00416                             "text", COL_YES,
00417                             "foreground-gdk",
00418                             COL_COLOR, NULL);
00419     renderer = gtk_cell_renderer_text_new();
00420     gtk_tree_view_insert_column_with_attributes(view, -1,
00421                             "Value", renderer,
00422                             "text", COL_VALUE,
00423                             "editable",
00424                             COL_EDIT,
00425                             "foreground-gdk",
00426                             COL_COLOR, NULL);
00427     g_signal_connect(G_OBJECT(renderer), "edited",
00428              G_CALLBACK(renderer_edited), NULL);
00429 
00430     column = gtk_tree_view_get_column(view, COL_NAME);
00431     gtk_tree_view_column_set_visible(column, show_name);
00432     column = gtk_tree_view_get_column(view, COL_NO);
00433     gtk_tree_view_column_set_visible(column, show_range);
00434     column = gtk_tree_view_get_column(view, COL_MOD);
00435     gtk_tree_view_column_set_visible(column, show_range);
00436     column = gtk_tree_view_get_column(view, COL_YES);
00437     gtk_tree_view_column_set_visible(column, show_range);
00438     column = gtk_tree_view_get_column(view, COL_VALUE);
00439     gtk_tree_view_column_set_visible(column, show_value);
00440 
00441     if (resizeable) {
00442         for (i = 0; i < COL_VALUE; i++) {
00443             column = gtk_tree_view_get_column(view, i);
00444             gtk_tree_view_column_set_resizable(column, TRUE);
00445         }
00446     }
00447 
00448     sel = gtk_tree_view_get_selection(view);
00449     gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
00450 }
00451 
00452 
00453 /* Utility Functions */
00454 
00455 
00456 static void text_insert_help(struct menu *menu)
00457 {
00458     GtkTextBuffer *buffer;
00459     GtkTextIter start, end;
00460     const char *prompt = menu_get_prompt(menu);
00461     gchar *name;
00462     const char *help = nohelp_text;
00463 
00464     if (!menu->sym)
00465         help = "";
00466     else if (menu->sym->help)
00467         help = menu->sym->help;
00468 
00469     if (menu->sym && menu->sym->name)
00470         name = g_strdup_printf(menu->sym->name);
00471     else
00472         name = g_strdup("");
00473 
00474     buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
00475     gtk_text_buffer_get_bounds(buffer, &start, &end);
00476     gtk_text_buffer_delete(buffer, &start, &end);
00477     gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
00478 
00479     gtk_text_buffer_get_end_iter(buffer, &end);
00480     gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
00481                      NULL);
00482     gtk_text_buffer_insert_at_cursor(buffer, " ", 1);
00483     gtk_text_buffer_get_end_iter(buffer, &end);
00484     gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1,
00485                      NULL);
00486     gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
00487     gtk_text_buffer_get_end_iter(buffer, &end);
00488     gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2,
00489                      NULL);
00490 }
00491 
00492 
00493 static void text_insert_msg(const char *title, const char *message)
00494 {
00495     GtkTextBuffer *buffer;
00496     GtkTextIter start, end;
00497     const char *msg = message;
00498 
00499     buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
00500     gtk_text_buffer_get_bounds(buffer, &start, &end);
00501     gtk_text_buffer_delete(buffer, &start, &end);
00502     gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
00503 
00504     gtk_text_buffer_get_end_iter(buffer, &end);
00505     gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
00506                      NULL);
00507     gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
00508     gtk_text_buffer_get_end_iter(buffer, &end);
00509     gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
00510                      NULL);
00511 }
00512 
00513 
00514 /* Main Windows Callbacks */
00515 
00516 void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data);
00517 gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
00518                  gpointer user_data)
00519 {
00520     GtkWidget *dialog, *label;
00521     gint result;
00522 
00523     if (config_changed == FALSE)
00524         return FALSE;
00525 
00526     dialog = gtk_dialog_new_with_buttons("Warning !",
00527                          GTK_WINDOW(main_wnd),
00528                          (GtkDialogFlags)
00529                          (GTK_DIALOG_MODAL |
00530                           GTK_DIALOG_DESTROY_WITH_PARENT),
00531                          GTK_STOCK_OK,
00532                          GTK_RESPONSE_YES,
00533                          GTK_STOCK_NO,
00534                          GTK_RESPONSE_NO,
00535                          GTK_STOCK_CANCEL,
00536                          GTK_RESPONSE_CANCEL, NULL);
00537     gtk_dialog_set_default_response(GTK_DIALOG(dialog),
00538                     GTK_RESPONSE_CANCEL);
00539 
00540     label = gtk_label_new("\nSave configuration ?\n");
00541     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
00542     gtk_widget_show(label);
00543 
00544     result = gtk_dialog_run(GTK_DIALOG(dialog));
00545     switch (result) {
00546     case GTK_RESPONSE_YES:
00547         on_save1_activate(NULL, NULL);
00548         return FALSE;
00549     case GTK_RESPONSE_NO:
00550         return FALSE;
00551     case GTK_RESPONSE_CANCEL:
00552     case GTK_RESPONSE_DELETE_EVENT:
00553     default:
00554         gtk_widget_destroy(dialog);
00555         return TRUE;
00556     }
00557 
00558     return FALSE;
00559 }
00560 
00561 
00562 void on_window1_destroy(GtkObject * object, gpointer user_data)
00563 {
00564     gtk_main_quit();
00565 }
00566 
00567 
00568 void
00569 on_window1_size_request(GtkWidget * widget,
00570             GtkRequisition * requisition, gpointer user_data)
00571 {
00572     static gint old_h;
00573     gint w, h;
00574 
00575     if (widget->window == NULL)
00576         gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
00577     else
00578         gdk_window_get_size(widget->window, &w, &h);
00579 
00580     if (h == old_h)
00581         return;
00582     old_h = h;
00583 
00584     gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
00585 }
00586 
00587 
00588 /* Menu & Toolbar Callbacks */
00589 
00590 
00591 static void
00592 load_filename(GtkFileSelection * file_selector, gpointer user_data)
00593 {
00594     const gchar *fn;
00595 
00596     fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
00597                          (user_data));
00598 
00599     if (conf_read(fn))
00600         text_insert_msg("Error", "Unable to load configuration !");
00601     else
00602         display_tree(&rootmenu);
00603 }
00604 
00605 void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
00606 {
00607     GtkWidget *fs;
00608 
00609     fs = gtk_file_selection_new("Load file...");
00610     g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
00611              "clicked",
00612              G_CALLBACK(load_filename), (gpointer) fs);
00613     g_signal_connect_swapped(GTK_OBJECT
00614                  (GTK_FILE_SELECTION(fs)->ok_button),
00615                  "clicked", G_CALLBACK(gtk_widget_destroy),
00616                  (gpointer) fs);
00617     g_signal_connect_swapped(GTK_OBJECT
00618                  (GTK_FILE_SELECTION(fs)->cancel_button),
00619                  "clicked", G_CALLBACK(gtk_widget_destroy),
00620                  (gpointer) fs);
00621     gtk_widget_show(fs);
00622 }
00623 
00624 
00625 void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data)
00626 {
00627     if (conf_write(NULL))
00628         text_insert_msg("Error", "Unable to save configuration !");
00629 
00630     config_changed = FALSE;
00631 }
00632 
00633 
00634 static void
00635 store_filename(GtkFileSelection * file_selector, gpointer user_data)
00636 {
00637     const gchar *fn;
00638 
00639     fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
00640                          (user_data));
00641 
00642     if (conf_write(fn))
00643         text_insert_msg("Error", "Unable to save configuration !");
00644 
00645     gtk_widget_destroy(GTK_WIDGET(user_data));
00646 }
00647 
00648 void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
00649 {
00650     GtkWidget *fs;
00651 
00652     fs = gtk_file_selection_new("Save file as...");
00653     g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
00654              "clicked",
00655              G_CALLBACK(store_filename), (gpointer) fs);
00656     g_signal_connect_swapped(GTK_OBJECT
00657                  (GTK_FILE_SELECTION(fs)->ok_button),
00658                  "clicked", G_CALLBACK(gtk_widget_destroy),
00659                  (gpointer) fs);
00660     g_signal_connect_swapped(GTK_OBJECT
00661                  (GTK_FILE_SELECTION(fs)->cancel_button),
00662                  "clicked", G_CALLBACK(gtk_widget_destroy),
00663                  (gpointer) fs);
00664     gtk_widget_show(fs);
00665 }
00666 
00667 
00668 void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
00669 {
00670     if (!on_window1_delete_event(NULL, NULL, NULL))
00671         gtk_widget_destroy(GTK_WIDGET(main_wnd));
00672 }
00673 
00674 
00675 void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
00676 {
00677     GtkTreeViewColumn *col;
00678 
00679     show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
00680     col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
00681     if (col)
00682         gtk_tree_view_column_set_visible(col, show_name);
00683 }
00684 
00685 
00686 void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
00687 {
00688     GtkTreeViewColumn *col;
00689 
00690     show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
00691     col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
00692     if (col)
00693         gtk_tree_view_column_set_visible(col, show_range);
00694     col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
00695     if (col)
00696         gtk_tree_view_column_set_visible(col, show_range);
00697     col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
00698     if (col)
00699         gtk_tree_view_column_set_visible(col, show_range);
00700 
00701 }
00702 
00703 
00704 void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
00705 {
00706     GtkTreeViewColumn *col;
00707 
00708     show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
00709     col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
00710     if (col)
00711         gtk_tree_view_column_set_visible(col, show_value);
00712 }
00713 
00714 
00715 void
00716 on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
00717 {
00718     show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
00719 
00720     gtk_tree_store_clear(tree2);
00721     display_tree(&rootmenu);    // instead of update_tree to speed-up
00722 }
00723 
00724 
00725 void
00726 on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
00727 {
00728     show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
00729     update_tree(&rootmenu, NULL);
00730 }
00731 
00732 
00733 void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
00734 {
00735     GtkWidget *dialog;
00736     const gchar *intro_text =
00737         "Welcome to gkc, the GTK+ graphical configuration tool\n"
00738         "for RTAI.\n"
00739         "For each option, a blank box indicates the feature is disabled, a\n"
00740         "check indicates it is enabled, and a dot indicates that it is to\n"
00741         "be compiled as a module.  Clicking on the box will cycle through the three states.\n"
00742         "\n"
00743         "If you do not see an option (e.g., a feature) that you\n"
00744         "believe should be present, try turning on Show All Options\n"
00745         "under the Options menu.\n"
00746         "Although there is no cross reference yet to help you figure out\n"
00747         "what other options must be enabled to support the option you\n"
00748         "are interested in, you can still view the help of a grayed-out\n"
00749         "option.\n"
00750         "\n"
00751         "Toggling Show Debug Info under the Options menu will show \n"
00752         "the dependencies, which you can then match by examining other options.";
00753 
00754     dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
00755                     GTK_DIALOG_DESTROY_WITH_PARENT,
00756                     GTK_MESSAGE_INFO,
00757                     GTK_BUTTONS_CLOSE, intro_text);
00758     g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
00759                  G_CALLBACK(gtk_widget_destroy),
00760                  GTK_OBJECT(dialog));
00761     gtk_widget_show_all(dialog);
00762 }
00763 
00764 
00765 void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
00766 {
00767     GtkWidget *dialog;
00768     const gchar *about_text =
00769         "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
00770         "Based on the source code from Roman Zippel.\n";
00771 
00772     dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
00773                     GTK_DIALOG_DESTROY_WITH_PARENT,
00774                     GTK_MESSAGE_INFO,
00775                     GTK_BUTTONS_CLOSE, about_text);
00776     g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
00777                  G_CALLBACK(gtk_widget_destroy),
00778                  GTK_OBJECT(dialog));
00779     gtk_widget_show_all(dialog);
00780 }
00781 
00782 
00783 void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
00784 {
00785     GtkWidget *dialog;
00786     const gchar *license_text =
00787         "gkc is released under the terms of the GNU GPL v2.\n"
00788         "For more information, please see the source code or\n"
00789         "visit http://www.fsf.org/licenses/licenses.html\n";
00790 
00791     dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
00792                     GTK_DIALOG_DESTROY_WITH_PARENT,
00793                     GTK_MESSAGE_INFO,
00794                     GTK_BUTTONS_CLOSE, license_text);
00795     g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
00796                  G_CALLBACK(gtk_widget_destroy),
00797                  GTK_OBJECT(dialog));
00798     gtk_widget_show_all(dialog);
00799 }
00800 
00801 
00802 void on_back_pressed(GtkButton * button, gpointer user_data)
00803 {
00804     enum prop_type ptype;
00805 
00806     current = current->parent;
00807     ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
00808     if (ptype != P_MENU)
00809         current = current->parent;
00810     display_tree_part();
00811 
00812     if (current == &rootmenu)
00813         gtk_widget_set_sensitive(back_btn, FALSE);
00814 }
00815 
00816 
00817 void on_load_pressed(GtkButton * button, gpointer user_data)
00818 {
00819     on_load1_activate(NULL, user_data);
00820 }
00821 
00822 
00823 void on_save_pressed(GtkButton * button, gpointer user_data)
00824 {
00825     on_save1_activate(NULL, user_data);
00826 }
00827 
00828 
00829 void on_single_clicked(GtkButton * button, gpointer user_data)
00830 {
00831     view_mode = SINGLE_VIEW;
00832     gtk_paned_set_position(GTK_PANED(hpaned), 0);
00833     gtk_widget_hide(tree1_w);
00834     current = &rootmenu;
00835     display_tree_part();
00836 }
00837 
00838 
00839 void on_split_clicked(GtkButton * button, gpointer user_data)
00840 {
00841     gint w, h;
00842     view_mode = SPLIT_VIEW;
00843     gtk_widget_show(tree1_w);
00844     gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
00845     gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
00846     if (tree2)  
00847         gtk_tree_store_clear(tree2);
00848     display_list();
00849 }
00850 
00851 
00852 void on_full_clicked(GtkButton * button, gpointer user_data)
00853 {
00854     view_mode = FULL_VIEW;
00855     gtk_paned_set_position(GTK_PANED(hpaned), 0);
00856     gtk_widget_hide(tree1_w);
00857     if (tree2)
00858         gtk_tree_store_clear(tree2);
00859     display_tree(&rootmenu);
00860     gtk_widget_set_sensitive(back_btn, FALSE);
00861 }
00862 
00863 
00864 void on_collapse_pressed(GtkButton * button, gpointer user_data)
00865 {
00866     gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
00867 }
00868 
00869 
00870 void on_expand_pressed(GtkButton * button, gpointer user_data)
00871 {
00872     gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
00873 }
00874 
00875 
00876 /* CTree Callbacks */
00877 
00878 /* Change hex/int/string value in the cell */
00879 static void renderer_edited(GtkCellRendererText * cell,
00880                 const gchar * path_string,
00881                 const gchar * new_text, gpointer user_data)
00882 {
00883     GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
00884     GtkTreeIter iter;
00885     const char *old_def, *new_def;
00886     struct menu *menu;
00887     struct symbol *sym;
00888 
00889     if (!gtk_tree_model_get_iter(model2, &iter, path))
00890         return;
00891 
00892     gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
00893     sym = menu->sym;
00894 
00895     gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
00896     new_def = new_text;
00897 
00898     sym_set_string_value(sym, new_def);
00899 
00900     config_changed = TRUE;
00901     update_tree(&rootmenu, NULL);
00902 
00903     gtk_tree_path_free(path);
00904 }
00905 
00906 /* Change the value of a symbol and update the tree */
00907 static void change_sym_value(struct menu *menu, gint col)
00908 {
00909     struct symbol *sym = menu->sym;
00910     tristate oldval, newval;
00911 
00912     if (!sym)
00913         return;
00914 
00915     if (col == COL_NO)
00916         newval = no;
00917     else if (col == COL_MOD)
00918         newval = mod;
00919     else if (col == COL_YES)
00920         newval = yes;
00921     else
00922         return;
00923 
00924     switch (sym_get_type(sym)) {
00925     case S_BOOLEAN:
00926     case S_TRISTATE:
00927         oldval = sym_get_tristate_value(sym);
00928         if (!sym_tristate_within_range(sym, newval))
00929             newval = yes;
00930         sym_set_tristate_value(sym, newval);
00931         config_changed = TRUE;
00932         if (view_mode == FULL_VIEW)
00933             update_tree(&rootmenu, NULL);
00934         else if (view_mode == SPLIT_VIEW) {
00935             update_tree(browsed, NULL);
00936             display_list();
00937         }
00938         else if (view_mode == SINGLE_VIEW)
00939             display_tree_part();    //fixme: keep exp/coll
00940         break;
00941     case S_INT:
00942     case S_HEX:
00943     case S_STRING:
00944     default:
00945         break;
00946     }
00947 }
00948 
00949 static void toggle_sym_value(struct menu *menu)
00950 {
00951     const tristate next_val[3] = { no, mod, yes };
00952     tristate newval;
00953 
00954     if (!menu->sym)
00955         return;
00956 
00957     newval = next_val[(sym_get_tristate_value(menu->sym) + 1) % 3];
00958     if (!sym_tristate_within_range(menu->sym, newval))
00959         newval = yes;
00960     sym_set_tristate_value(menu->sym, newval);
00961     if (view_mode == FULL_VIEW)
00962         update_tree(&rootmenu, NULL);
00963     else if (view_mode == SPLIT_VIEW) {
00964         update_tree(browsed, NULL);
00965         display_list();
00966     }
00967     else if (view_mode == SINGLE_VIEW)
00968         display_tree_part();    //fixme: keep exp/coll
00969 }
00970 
00971 static void renderer_toggled(GtkCellRendererToggle * cell,
00972                  gchar * path_string, gpointer user_data)
00973 {
00974     GtkTreePath *path, *sel_path = NULL;
00975     GtkTreeIter iter, sel_iter;
00976     GtkTreeSelection *sel;
00977     struct menu *menu;
00978 
00979     path = gtk_tree_path_new_from_string(path_string);
00980     if (!gtk_tree_model_get_iter(model2, &iter, path))
00981         return;
00982 
00983     sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
00984     if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
00985         sel_path = gtk_tree_model_get_path(model2, &sel_iter);
00986     if (!sel_path)
00987         goto out1;
00988     if (gtk_tree_path_compare(path, sel_path))
00989         goto out2;
00990 
00991     gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
00992     toggle_sym_value(menu);
00993 
00994       out2:
00995     gtk_tree_path_free(sel_path);
00996       out1:
00997     gtk_tree_path_free(path);
00998 }
00999 
01000 static gint column2index(GtkTreeViewColumn * column)
01001 {
01002     gint i;
01003 
01004     for (i = 0; i < COL_NUMBER; i++) {
01005         GtkTreeViewColumn *col;
01006 
01007         col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
01008         if (col == column)
01009             return i;
01010     }
01011 
01012     return -1;
01013 }
01014 
01015 
01016 /* User click: update choice (full) or goes down (single) */
01017 gboolean
01018 on_treeview2_button_press_event(GtkWidget * widget,
01019                 GdkEventButton * event, gpointer user_data)
01020 {
01021     GtkTreeView *view = GTK_TREE_VIEW(widget);
01022     GtkTreePath *path;
01023     GtkTreeViewColumn *column;
01024     GtkTreeIter iter;
01025     struct menu *menu;
01026     gint col;
01027 
01028 #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
01029     gint tx = (gint) event->x;
01030     gint ty = (gint) event->y;
01031     gint cx, cy;
01032 
01033     gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
01034                       &cy);
01035 #else
01036     gtk_tree_view_get_cursor(view, &path, &column);
01037 #endif
01038     if (path == NULL)
01039         return FALSE;
01040 
01041     gtk_tree_model_get_iter(model2, &iter, path);
01042     gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
01043 
01044     col = column2index(column);
01045     if (event->type == GDK_2BUTTON_PRESS) {
01046         enum prop_type ptype;
01047         ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
01048 
01049         if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
01050             // goes down into menu
01051             current = menu;
01052             display_tree_part();
01053             gtk_widget_set_sensitive(back_btn, TRUE);
01054         } else if ((col == COL_OPTION)) {
01055             toggle_sym_value(menu);
01056             gtk_tree_view_expand_row(view, path, TRUE);
01057         }
01058     } else {
01059         if (col == COL_VALUE) {
01060             toggle_sym_value(menu);
01061             gtk_tree_view_expand_row(view, path, TRUE);
01062         } else if (col == COL_NO || col == COL_MOD
01063                || col == COL_YES) {
01064             change_sym_value(menu, col);
01065             gtk_tree_view_expand_row(view, path, TRUE);
01066         }
01067     }
01068 
01069     return FALSE;
01070 }
01071 
01072 /* Key pressed: update choice */
01073 gboolean
01074 on_treeview2_key_press_event(GtkWidget * widget,
01075                  GdkEventKey * event, gpointer user_data)
01076 {
01077     GtkTreeView *view = GTK_TREE_VIEW(widget);
01078     GtkTreePath *path;
01079     GtkTreeViewColumn *column;
01080     GtkTreeIter iter;
01081     struct menu *menu;
01082     gint col;
01083 
01084     gtk_tree_view_get_cursor(view, &path, &column);
01085     if (path == NULL)
01086         return FALSE;
01087 
01088     if (event->keyval == GDK_space) {
01089         if (gtk_tree_view_row_expanded(view, path))
01090             gtk_tree_view_collapse_row(view, path);
01091         else
01092             gtk_tree_view_expand_row(view, path, FALSE);
01093         return TRUE;
01094     }
01095     if (event->keyval == GDK_KP_Enter) {
01096     }
01097     if (widget == tree1_w)
01098         return FALSE;
01099 
01100     gtk_tree_model_get_iter(model2, &iter, path);
01101     gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
01102 
01103     if (!strcasecmp(event->string, "n"))
01104         col = COL_NO;
01105     else if (!strcasecmp(event->string, "m"))
01106         col = COL_MOD;
01107     else if (!strcasecmp(event->string, "y"))
01108         col = COL_YES;
01109     else
01110         col = -1;
01111     change_sym_value(menu, col);
01112 
01113     return FALSE;
01114 }
01115 
01116 
01117 /* Row selection changed: update help */
01118 void
01119 on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
01120 {
01121     GtkTreeSelection *selection;
01122     GtkTreeIter iter;
01123     struct menu *menu;
01124 
01125     selection = gtk_tree_view_get_selection(treeview);
01126     if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
01127         gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
01128         text_insert_help(menu);
01129     }
01130 }
01131 
01132 
01133 /* User click: display sub-tree in the right frame. */
01134 gboolean
01135 on_treeview1_button_press_event(GtkWidget * widget,
01136                 GdkEventButton * event, gpointer user_data)
01137 {
01138     GtkTreeView *view = GTK_TREE_VIEW(widget);
01139     GtkTreePath *path;
01140     GtkTreeViewColumn *column;
01141     GtkTreeIter iter;
01142     struct menu *menu;
01143 
01144     gint tx = (gint) event->x;
01145     gint ty = (gint) event->y;
01146     gint cx, cy;
01147 
01148     gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
01149                       &cy);
01150     if (path == NULL)
01151         return FALSE;
01152 
01153     gtk_tree_model_get_iter(model1, &iter, path);
01154     gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
01155 
01156     if (event->type == GDK_2BUTTON_PRESS) {
01157         toggle_sym_value(menu);
01158         current = menu;
01159         display_tree_part();
01160     } else {
01161         browsed = menu;
01162         display_tree_part();
01163     }
01164 
01165     gtk_widget_realize(tree2_w);
01166     gtk_tree_view_set_cursor(view, path, NULL, FALSE);
01167     gtk_widget_grab_focus(GTK_TREE_VIEW(tree2_w));
01168 
01169     return FALSE;
01170 }
01171 
01172 
01173 /* Conf management */
01174 
01175 
01176 /* Fill a row of strings */
01177 static gchar **fill_row(struct menu *menu)
01178 {
01179     static gchar *row[COL_NUMBER];
01180     struct symbol *sym = menu->sym;
01181     const char *def;
01182     int stype;
01183     tristate val;
01184     enum prop_type ptype;
01185     int i;
01186 
01187     for (i = COL_OPTION; i <= COL_COLOR; i++)
01188         g_free(row[i]);
01189     bzero(row, sizeof(row));
01190 
01191     row[COL_OPTION] =
01192         g_strdup_printf("%s %s", menu_get_prompt(menu),
01193                 sym ? (sym->
01194                    flags & SYMBOL_NEW ? "(NEW)" : "") :
01195                 "");
01196 
01197     if (show_all && !menu_is_visible(menu))
01198         row[COL_COLOR] = g_strdup("DarkGray");
01199     else
01200         row[COL_COLOR] = g_strdup("Black");
01201 
01202     ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
01203     switch (ptype) {
01204     case P_MENU:
01205         row[COL_PIXBUF] = (gchar *) xpm_menu;
01206         if (view_mode == SINGLE_VIEW)
01207             row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
01208         row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
01209         break;
01210     case P_COMMENT:
01211         row[COL_PIXBUF] = (gchar *) xpm_void;
01212         row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
01213         row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
01214         break;
01215     default:
01216         row[COL_PIXBUF] = (gchar *) xpm_void;
01217         row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
01218         row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
01219         break;
01220     }
01221 
01222     if (!sym)
01223         return row;
01224     row[COL_NAME] = g_strdup(sym->name);
01225 
01226     sym_calc_value(sym);
01227     sym->flags &= ~SYMBOL_CHANGED;
01228 
01229     if (sym_is_choice(sym)) {   // parse childs for getting final value
01230         struct menu *child;
01231         struct symbol *def_sym = sym_get_choice_value(sym);
01232         struct menu *def_menu = NULL;
01233 
01234         row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
01235 
01236         for (child = menu->list; child; child = child->next) {
01237             if (menu_is_visible(child)
01238                 && child->sym == def_sym)
01239                 def_menu = child;
01240         }
01241 
01242         if (def_menu)
01243             row[COL_VALUE] =
01244                 g_strdup(menu_get_prompt(def_menu));
01245     }
01246     if(sym->flags & SYMBOL_CHOICEVAL)
01247         row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
01248 
01249     stype = sym_get_type(sym);
01250     switch (stype) {
01251     case S_BOOLEAN:
01252         if(GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
01253             row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
01254         if (sym_is_choice(sym))
01255             break;
01256     case S_TRISTATE:
01257         val = sym_get_tristate_value(sym);
01258         switch (val) {
01259         case no:
01260             row[COL_NO] = g_strdup("N");
01261             row[COL_VALUE] = g_strdup("N");
01262             row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
01263             row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
01264             break;
01265         case mod:
01266             row[COL_MOD] = g_strdup("M");
01267             row[COL_VALUE] = g_strdup("M");
01268             row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
01269             break;
01270         case yes:
01271             row[COL_YES] = g_strdup("Y");
01272             row[COL_VALUE] = g_strdup("Y");
01273             row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
01274             row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
01275             break;
01276         }
01277 
01278         if (val != no && sym_tristate_within_range(sym, no))
01279             row[COL_NO] = g_strdup("_");
01280         if (val != mod && sym_tristate_within_range(sym, mod))
01281             row[COL_MOD] = g_strdup("_");
01282         if (val != yes && sym_tristate_within_range(sym, yes))
01283             row[COL_YES] = g_strdup("_");
01284         break;
01285     case S_INT:
01286     case S_HEX:
01287     case S_STRING:
01288         def = sym_get_string_value(sym);
01289         row[COL_VALUE] = g_strdup(def);
01290         row[COL_EDIT] = GINT_TO_POINTER(TRUE);
01291         row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
01292         break;
01293     }
01294 
01295     return row;
01296 }
01297 
01298 
01299 /* Set the node content with a row of strings */
01300 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
01301 {
01302     GdkColor color;
01303     gboolean success;
01304     GdkPixbuf *pix;
01305 
01306     pix = gdk_pixbuf_new_from_xpm_data((const char **)
01307                        row[COL_PIXBUF]);
01308 
01309     gdk_color_parse(row[COL_COLOR], &color);
01310     gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
01311                   FALSE, FALSE, &success);
01312 
01313     gtk_tree_store_set(tree, node,
01314                COL_OPTION, row[COL_OPTION],
01315                COL_NAME, row[COL_NAME],
01316                COL_NO, row[COL_NO],
01317                COL_MOD, row[COL_MOD],
01318                COL_YES, row[COL_YES],
01319                COL_VALUE, row[COL_VALUE],
01320                COL_MENU, (gpointer) menu,
01321                COL_COLOR, &color,
01322                COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
01323                COL_PIXBUF, pix,
01324                COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
01325                COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
01326                COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
01327                COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
01328                COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
01329                -1);
01330 
01331     g_object_unref(pix);
01332 }
01333 
01334 
01335 /* Add a node to the tree */
01336 static void place_node(struct menu *menu, char **row)
01337 {
01338     GtkTreeIter *parent = parents[indent - 1];
01339     GtkTreeIter *node = parents[indent];
01340 
01341     gtk_tree_store_append(tree, node, parent);
01342     set_node(node, menu, row);
01343 }
01344 
01345 
01346 /* Find a node in the GTK+ tree */
01347 static GtkTreeIter found;
01348 
01349 /*
01350  * Find a menu in the GtkTree starting at parent.
01351  */
01352 GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
01353                     struct menu *tofind)
01354 {
01355     GtkTreeIter iter;
01356     GtkTreeIter *child = &iter;
01357     gboolean valid;
01358     GtkTreeIter *ret;
01359 
01360     valid = gtk_tree_model_iter_children(model2, child, parent);
01361     while (valid) {
01362         struct menu *menu;
01363 
01364         gtk_tree_model_get(model2, child, 6, &menu, -1);
01365 
01366         if (menu == tofind) {
01367             memcpy(&found, child, sizeof(GtkTreeIter));
01368             return &found;
01369         }
01370 
01371         ret = gtktree_iter_find_node(child, tofind);
01372         if (ret)
01373             return ret;
01374 
01375         valid = gtk_tree_model_iter_next(model2, child);
01376     }
01377 
01378     return NULL;
01379 }
01380 
01381 
01382 /*
01383  * Update the tree by adding/removing entries
01384  * Does not change other nodes
01385  */
01386 static void update_tree(struct menu *src, GtkTreeIter * dst)
01387 {
01388     struct menu *child1;
01389     GtkTreeIter iter, tmp;
01390     GtkTreeIter *child2 = &iter;
01391     gboolean valid;
01392     GtkTreeIter *sibling;
01393     struct symbol *sym;
01394     struct property *prop;
01395     struct menu *menu1, *menu2;
01396     static GtkTreePath *path = NULL;
01397 
01398     if (src == &rootmenu)
01399         indent = 1;
01400 
01401     valid = gtk_tree_model_iter_children(model2, child2, dst);
01402     for (child1 = src->list; child1; child1 = child1->next) {
01403 
01404         prop = child1->prompt;
01405         sym = child1->sym;
01406 
01407           reparse:
01408         menu1 = child1;
01409         if (valid)
01410             gtk_tree_model_get(model2, child2, COL_MENU,
01411                        &menu2, -1);
01412         else
01413             menu2 = NULL;   // force adding of a first child
01414 
01415 #ifdef DEBUG
01416         printf("%*c%s | %s\n", indent, ' ',
01417                menu1 ? menu_get_prompt(menu1) : "nil",
01418                menu2 ? menu_get_prompt(menu2) : "nil");
01419 #endif
01420 
01421         if (!menu_is_visible(child1) && !show_all) {    // remove node
01422             if (gtktree_iter_find_node(dst, menu1) != NULL) {
01423                 memcpy(&tmp, child2, sizeof(GtkTreeIter));
01424                 valid = gtk_tree_model_iter_next(model2,
01425                                  child2);
01426                 gtk_tree_store_remove(tree2, &tmp);
01427                 if (!valid)
01428                     return; // next parent 
01429                 else
01430                     goto reparse;   // next child
01431             } else
01432                 continue;
01433         }
01434 
01435         if (menu1 != menu2) {
01436             if (gtktree_iter_find_node(dst, menu1) == NULL) {   // add node
01437                 if (!valid && !menu2)
01438                     sibling = NULL;
01439                 else
01440                     sibling = child2;
01441                 gtk_tree_store_insert_before(tree2,
01442                                  child2,
01443                                  dst, sibling);
01444                 set_node(child2, menu1, fill_row(menu1));
01445                 if (menu2 == NULL)
01446                     valid = TRUE;
01447             } else {    // remove node
01448                 memcpy(&tmp, child2, sizeof(GtkTreeIter));
01449                 valid = gtk_tree_model_iter_next(model2,
01450                                  child2);
01451                 gtk_tree_store_remove(tree2, &tmp);
01452                 if (!valid)
01453                     return; // next parent 
01454                 else
01455                     goto reparse;   // next child
01456             }
01457         } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
01458             set_node(child2, menu1, fill_row(menu1));
01459         }
01460 
01461         indent++;
01462         update_tree(child1, child2);
01463         indent--;
01464 
01465         valid = gtk_tree_model_iter_next(model2, child2);
01466     }
01467 }
01468 
01469 
01470 /* Display the whole tree (single/split/full view) */
01471 static void display_tree(struct menu *menu)
01472 {
01473     struct symbol *sym;
01474     struct property *prop;
01475     struct menu *child;
01476     enum prop_type ptype;
01477 
01478     if (menu == &rootmenu) {
01479         indent = 1;
01480         current = &rootmenu;
01481     }
01482 
01483     for (child = menu->list; child; child = child->next) {
01484         prop = child->prompt;
01485         sym = child->sym;
01486         ptype = prop ? prop->type : P_UNKNOWN;
01487 
01488         if (sym)
01489             sym->flags &= ~SYMBOL_CHANGED;
01490 
01491         if ((view_mode == SPLIT_VIEW) && !(child->flags & MENU_ROOT) &&
01492             (tree == tree1))
01493             continue;
01494 
01495         if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) &&
01496             (tree == tree2))
01497             continue;
01498 
01499         if (menu_is_visible(child) || show_all)
01500             place_node(child, fill_row(child));
01501 #ifdef DEBUG
01502         printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
01503         printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
01504         dbg_print_ptype(ptype);
01505         printf(" | ");
01506         if (sym) {
01507             dbg_print_stype(sym->type);
01508             printf(" | ");
01509             dbg_print_flags(sym->flags);
01510             printf("\n");
01511         } else
01512             printf("\n");
01513 #endif
01514         if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
01515             && (tree == tree2))
01516             continue;
01517 /*
01518         if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) ||
01519             (view_mode == FULL_VIEW)
01520             || (view_mode == SPLIT_VIEW))*/
01521         if ((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT) 
01522         || (view_mode == FULL_VIEW) || (view_mode == SPLIT_VIEW)) {
01523             indent++;
01524             display_tree(child);
01525             indent--;
01526         }
01527     }
01528 }
01529 
01530 /* Display a part of the tree starting at current node (single/split view) */
01531 static void display_tree_part(void)
01532 {
01533     if (tree2)
01534         gtk_tree_store_clear(tree2);
01535     if(view_mode == SINGLE_VIEW)
01536         display_tree(current);
01537     else if(view_mode == SPLIT_VIEW)
01538         display_tree(browsed);
01539     gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
01540 }
01541 
01542 /* Display the list in the left frame (split view) */
01543 static void display_list(void)
01544 {
01545     if (tree1)
01546         gtk_tree_store_clear(tree1);
01547 
01548     tree = tree1;
01549     display_tree(&rootmenu);
01550     gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
01551     tree = tree2;
01552 }
01553 
01554 void fixup_rootmenu(struct menu *menu)
01555 {
01556         struct menu *child;
01557         static int menu_cnt = 0;
01558 
01559         menu->flags |= MENU_ROOT;
01560         for (child = menu->list; child; child = child->next) {
01561                 if (child->prompt && child->prompt->type == P_MENU) {
01562                         menu_cnt++;
01563                         fixup_rootmenu(child);
01564                         menu_cnt--;
01565                 } else if (!menu_cnt)
01566                         fixup_rootmenu(child);
01567         }
01568 }
01569 
01570 
01571 /* Main */
01572 
01573 
01574 int main(int ac, char *av[])
01575 {
01576     const char *name, *srctree;
01577     gchar *cur_dir, *exe_path;
01578     gchar *glade_file;
01579     struct symbol *sym;
01580     char title[256];
01581 
01582 #ifndef LKC_DIRECT_LINK
01583     kconfig_load();
01584 #endif
01585 
01586     /* GTK stuffs */
01587     gtk_set_locale();
01588     gtk_init(&ac, &av);
01589     glade_init();
01590 
01591     //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
01592     //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
01593 
01594     /* Determine GUI path */
01595 
01596     srctree = getenv(SRCTREE);
01597     glade_file = g_strconcat(srctree ?: ".", "/base/config/kconfig/",av[0], ".glade", NULL);
01598 
01599     /* Load the interface and connect signals */
01600     init_main_window(glade_file);
01601     gtk_widget_show(main_wnd);
01602     init_tree_model();
01603     init_left_tree();
01604     init_right_tree();
01605 
01606     /* Conf stuffs */
01607     if (ac > 1 && av[1][0] == '-') {
01608         switch (av[1][1]) {
01609         case 'a':
01610             //showAll = 1;
01611             break;
01612         case 'h':
01613         case '?':
01614             printf("%s <config>\n", av[0]);
01615             exit(0);
01616         }
01617         name = av[2];
01618     } else
01619         name = av[1];
01620 
01621     conf_parse(name);
01622     fixup_rootmenu(&rootmenu);
01623     conf_read(NULL);
01624 
01625     switch (view_mode) {
01626     case SINGLE_VIEW:
01627         display_tree_part();
01628         break;
01629     case SPLIT_VIEW:
01630         display_list();
01631         break;
01632     case FULL_VIEW:
01633         display_tree(&rootmenu);
01634         break;
01635     }
01636 
01637     sym = sym_lookup("RTAI_VERSION",0);
01638     sym_calc_value(sym);
01639     sprintf(title, "RTAI Configuration [ %s ]",sym_get_string_value(sym));
01640     gtk_window_set_title(GTK_WINDOW(main_wnd), title);
01641 
01642     gtk_main();
01643 
01644     return 0;
01645 }

Generated on Tue Feb 2 17:46:04 2010 for RTAI API by  doxygen 1.4.7