ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/prefs_editor_gtk.cpp (file contents):
Revision 1.24 by cebix, 2002-10-15T16:25:04Z vs.
Revision 1.40 by gbeauche, 2008-01-01T09:40:33Z

# Line 1 | Line 1
1   /*
2   *  prefs_editor_gtk.cpp - Preferences editor, Unix implementation using GTK+
3   *
4 < *  Basilisk II (C) 1997-2002 Christian Bauer
4 > *  Basilisk II (C) 1997-2008 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 39 | Line 39
39   #include "prefs.h"
40   #include "prefs_editor.h"
41  
42 + #define DEBUG 0
43 + #include "debug.h"
44 +
45  
46   // Global variables
47   static GtkWidget *win;                          // Preferences window
48 < static bool start_clicked = true;       // Return value of PrefsEditor() function
48 > static bool start_clicked = false;      // Return value of PrefsEditor() function
49  
50  
51   // Prototypes
# Line 60 | Line 63 | static void read_settings(void);
63   *  Utility functions
64   */
65  
66 + #if ! GLIB_CHECK_VERSION(2,0,0)
67 + #define G_OBJECT(obj)                                                   GTK_OBJECT(obj)
68 + #define g_object_get_data(obj, key)                             gtk_object_get_data((obj), (key))
69 + #define g_object_set_data(obj, key, data)               gtk_object_set_data((obj), (key), (data))
70 + #endif
71 +
72   struct opt_desc {
73          int label_id;
74          GtkSignalFunc func;
# Line 69 | Line 78 | struct combo_desc {
78          int label_id;
79   };
80  
81 + struct file_req_assoc {
82 +        file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
83 +        GtkWidget *req;
84 +        GtkWidget *entry;
85 + };
86 +
87 + static void cb_browse_ok(GtkWidget *button, file_req_assoc *assoc)
88 + {
89 +        gchar *file = (char *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
90 +        gtk_entry_set_text(GTK_ENTRY(assoc->entry), file);
91 +        gtk_widget_destroy(assoc->req);
92 +        delete assoc;
93 + }
94 +
95 + static void cb_browse(GtkWidget *widget, void *user_data)
96 + {
97 +        GtkWidget *req = gtk_file_selection_new(GetString(STR_BROWSE_TITLE));
98 +        gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
99 +        gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(cb_browse_ok), new file_req_assoc(req, (GtkWidget *)user_data));
100 +        gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
101 +        gtk_widget_show(req);
102 + }
103 +
104 + static GtkWidget *make_browse_button(GtkWidget *entry)
105 + {
106 +        GtkWidget *button;
107 +
108 +        button = gtk_button_new_with_label(GetString(STR_BROWSE_CTRL));
109 +        gtk_widget_show(button);
110 +        gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)cb_browse, (void *)entry);
111 +        return button;
112 + }
113 +
114   static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func)
115   {
116          GtkWidget *item = gtk_menu_item_new_with_label(GetString(label_id));
# Line 82 | Line 124 | static GtkWidget *make_pane(GtkWidget *n
124          GtkWidget *frame, *label, *box;
125  
126          frame = gtk_frame_new(NULL);
127 <        gtk_widget_show(frame);
86 <        gtk_container_border_width(GTK_CONTAINER(frame), 4);
87 <
88 <        label = gtk_label_new(GetString(title_id));
89 <        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
127 >        gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
128  
129          box = gtk_vbox_new(FALSE, 4);
92        gtk_widget_show(box);
130          gtk_container_set_border_width(GTK_CONTAINER(box), 4);
131          gtk_container_add(GTK_CONTAINER(frame), box);
132 +
133 +        gtk_widget_show_all(frame);
134 +
135 +        label = gtk_label_new(GetString(title_id));
136 +        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
137          return box;
138   }
139  
# Line 132 | Line 174 | static GtkWidget *make_table(GtkWidget *
174          return table;
175   }
176  
177 + static GtkWidget *table_make_option_menu(GtkWidget *table, int row, int label_id, const opt_desc *options, int active)
178 + {
179 +        GtkWidget *label, *opt, *menu;
180 +
181 +        label = gtk_label_new(GetString(label_id));
182 +        gtk_widget_show(label);
183 +        gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
184 +
185 +        opt = gtk_option_menu_new();
186 +        gtk_widget_show(opt);
187 +        menu = gtk_menu_new();
188 +
189 +        while (options->label_id) {
190 +                add_menu_item(menu, options->label_id, options->func);
191 +                options++;
192 +        }
193 +        gtk_menu_set_active(GTK_MENU(menu), active);
194 +
195 +        gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
196 +        gtk_table_attach(GTK_TABLE(table), opt, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
197 +        return menu;
198 + }
199 +
200 + static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, GList *glist)
201 + {
202 +        GtkWidget *label, *combo;
203 +        char str[32];
204 +
205 +        label = gtk_label_new(GetString(label_id));
206 +        gtk_widget_show(label);
207 +        gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
208 +        
209 +        combo = gtk_combo_new();
210 +        gtk_widget_show(combo);
211 +        gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
212 +
213 +        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value);
214 +        gtk_table_attach(GTK_TABLE(table), combo, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
215 +        
216 +        return combo;
217 + }
218 +
219 + static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, const combo_desc *options)
220 + {
221 +        GList *glist = NULL;
222 +        while (options->label_id) {
223 +                glist = g_list_append(glist, (void *)GetString(options->label_id));
224 +                options++;
225 +        }
226 +
227 +        return table_make_combobox(table, row, label_id, default_value, glist);
228 + }
229 +
230 + static GtkWidget *table_make_file_entry(GtkWidget *table, int row, int label_id, const char *prefs_item, bool only_dirs = false)
231 + {
232 +        GtkWidget *box, *label, *entry, *button;
233 +
234 +        label = gtk_label_new(GetString(label_id));
235 +        gtk_widget_show(label);
236 +        gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
237 +
238 +        const char *str = PrefsFindString(prefs_item);
239 +        if (str == NULL)
240 +                str = "";
241 +
242 +        box = gtk_hbox_new(FALSE, 4);
243 +        gtk_widget_show(box);
244 +        gtk_table_attach(GTK_TABLE(table), box, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
245 +
246 +        entry = gtk_entry_new();
247 +        gtk_entry_set_text(GTK_ENTRY(entry), str);
248 +        gtk_widget_show(entry);
249 +        gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
250 +
251 +        button = make_browse_button(entry);
252 +        gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
253 +        g_object_set_data(G_OBJECT(entry), "chooser_button", button);
254 +        return entry;
255 + }
256 +
257   static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
258   {
259          GtkWidget *box, *label, *opt, *menu;
# Line 189 | Line 311 | static GtkWidget *make_file_entry(GtkWid
311          return entry;
312   }
313  
314 < static char *get_file_entry_path(GtkWidget *entry)
314 > static const gchar *get_file_entry_path(GtkWidget *entry)
315   {
316   #ifdef HAVE_GNOMEUI
317          return gnome_file_entry_get_full_path(GNOME_FILE_ENTRY(entry), false);
# Line 306 | Line 428 | static void mn_about(...)
428          dialog = gnome_about_new(
429                  "Basilisk II",
430                  version,
431 <                "Copyright (C) 1997-2002 Christian Bauer",
431 >                "Copyright (C) 1997-2008 Christian Bauer",
432                  authors,
433                  "Basilisk II comes with ABSOLUTELY NO WARRANTY."
434                  "This is free software, and you are welcome to redistribute it"
# Line 322 | Line 444 | static void mn_about(...)
444          char str[512];
445          sprintf(str,
446                  "Basilisk II\nVersion %d.%d\n\n"
447 <                "Copyright (C) 1997-2002 Christian Bauer et al.\n"
447 >                "Copyright (C) 1997-2008 Christian Bauer et al.\n"
448                  "E-mail: Christian.Bauer@uni-mainz.de\n"
449                  "http://www.uni-mainz.de/~bauec002/B2Main.html\n\n"
450                  "Basilisk II comes with ABSOLUTELY NO\n"
# Line 363 | Line 485 | static void mn_zap_pram(...)
485   // Menu item descriptions
486   static GtkItemFactoryEntry menu_items[] = {
487          {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK),           NULL,                   NULL,                                                   0, "<Branch>"},
488 <        {(gchar *)GetString(STR_PREFS_ITEM_START_GTK),          NULL,                   GTK_SIGNAL_FUNC(cb_start),              0, NULL},
488 >        {(gchar *)GetString(STR_PREFS_ITEM_START_GTK),          "<control>S",   GTK_SIGNAL_FUNC(cb_start),              0, NULL},
489          {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK),       NULL,                   GTK_SIGNAL_FUNC(mn_zap_pram),   0, NULL},
490          {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK),           NULL,                   NULL,                                                   0, "<Separator>"},
491          {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK),           "<control>Q",   GTK_SIGNAL_FUNC(cb_quit),               0, NULL},
# Line 387 | Line 509 | bool PrefsEditor(void)
509          GtkAccelGroup *accel_group = gtk_accel_group_new();
510          GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
511          gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL);
512 + #if GTK_CHECK_VERSION(1,3,15)
513 +        gtk_window_add_accel_group(GTK_WINDOW(win), accel_group);
514 + #else
515          gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
516 + #endif
517          GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "<main>");
518          gtk_widget_show(menu_bar);
519          gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0);
520  
521          GtkWidget *notebook = gtk_notebook_new();
396        gtk_widget_show(notebook);
522          gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
523          gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
524          gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
525 +        gtk_widget_realize(notebook);
526  
527          create_volumes_pane(notebook);
528          create_scsi_pane(notebook);
# Line 405 | Line 531 | bool PrefsEditor(void)
531          create_serial_pane(notebook);
532          create_memory_pane(notebook);
533          create_jit_pane(notebook);
534 +        gtk_widget_show(notebook);
535  
536          static const opt_desc buttons[] = {
537                  {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
# Line 433 | Line 560 | static void cl_selected(GtkWidget *list,
560          selected_volume = row;
561   }
562  
436 struct file_req_assoc {
437        file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
438        GtkWidget *req;
439        GtkWidget *entry;
440 };
441
563   // Volume selected for addition
564   static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
565   {
566 <        char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
566 >        gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
567          gtk_clist_append(GTK_CLIST(volume_list), &file);
568          gtk_widget_destroy(assoc->req);
569          delete assoc;
# Line 451 | Line 572 | static void add_volume_ok(GtkWidget *but
572   // Volume selected for creation
573   static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
574   {
575 <        char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
575 >        gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
576  
577 <        char *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
577 >        const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
578          int size = atoi(str);
579  
580          char cmd[1024];
# Line 589 | Line 710 | static GtkWidget *w_jit_fpu;
710   static GtkWidget *w_jit_atraps;
711   static GtkWidget *w_jit_cache_size;
712   static GtkWidget *w_jit_lazy_flush;
713 + static GtkWidget *w_jit_follow_const_jumps;
714 +
715 + // Are we running a JIT capable CPU?
716 + static bool is_jit_capable(void)
717 + {
718 + #if USE_JIT && (defined __i386__ || defined __x86_64__)
719 +        return true;
720 + #elif defined __APPLE__ && defined __MACH__
721 +        // XXX run-time detect so that we can use a PPC GUI prefs editor
722 +        static char cpu[10];
723 +        if (cpu[0] == 0) {
724 +                FILE *fp = popen("uname -p", "r");
725 +                if (fp == NULL)
726 +                        return false;
727 +                fgets(cpu, sizeof(cpu) - 1, fp);
728 +                fclose(fp);
729 +        }
730 +        if (cpu[0] == 'i' && cpu[2] == '8' && cpu[3] == '6') // XXX assuming i?86
731 +                return true;
732 + #endif
733 +        return false;
734 + }
735  
736   // Set sensitivity of widgets
737   static void set_jit_sensitive(void)
# Line 597 | Line 740 | static void set_jit_sensitive(void)
740          gtk_widget_set_sensitive(w_jit_fpu, jit_enabled);
741          gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled);
742          gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled);
743 +        gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled);
744   }
745  
746   // "Use JIT Compiler" button toggled
# Line 618 | Line 762 | static void tb_jit_lazy_flush(GtkWidget
762          PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active);
763   }
764  
765 + // "Translate through constant jumps (inline blocks)" button toggled
766 + static void tb_jit_follow_const_jumps(GtkWidget *widget)
767 + {
768 +        PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active);
769 + }
770 +
771   // Read settings from widgets and set preferences
772   static void read_jit_settings(void)
773   {
774 < #if USE_JIT
625 <        bool jit_enabled = PrefsFindBool("jit");
774 >        bool jit_enabled = is_jit_capable() && PrefsFindBool("jit");
775          if (jit_enabled) {
776                  const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
777                  PrefsReplaceInt32("jitcachesize", atoi(str));
778          }
630 #endif
779   }
780  
781   // Create "JIT Compiler" pane
782   static void create_jit_pane(GtkWidget *top)
783   {
784 < #if USE_JIT
784 >        if (!is_jit_capable())
785 >                return;
786 >
787          GtkWidget *box, *table, *label, *menu;
788          char str[32];
789          
# Line 654 | Line 804 | static void create_jit_pane(GtkWidget *t
804          
805          // Lazy translation cache invalidation
806          w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush));
807 <        
807 >
808 >        // Follow constant jumps (inline basic blocks)
809 >        w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
810 >
811          set_jit_sensitive();
659 #endif
812   }
813  
814   /*
# Line 979 | Line 1131 | static GtkWidget *w_mouse_wheel_lines;
1131   // Set sensitivity of widgets
1132   static void set_input_sensitive(void)
1133   {
1134 <        gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
1134 >        const bool use_keycodes = PrefsFindBool("keycodes");
1135 >        gtk_widget_set_sensitive(w_keycode_file, use_keycodes);
1136 >        gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes);
1137          gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
1138   }
1139  
# Line 1009 | Line 1163 | static void read_input_settings(void)
1163   // Create "Input" pane
1164   static void create_input_pane(GtkWidget *top)
1165   {
1166 <        GtkWidget *box, *hbox, *menu, *label;
1166 >        GtkWidget *box, *hbox, *menu, *label, *button;
1167          GtkObject *adj;
1168  
1169          box = make_pane(top, STR_INPUT_PANE_TITLE);
1170  
1171          make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1172 <        w_keycode_file = make_file_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
1172 >
1173 >        hbox = gtk_hbox_new(FALSE, 4);
1174 >        gtk_widget_show(hbox);
1175 >        gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1176 >
1177 >        label = gtk_label_new(GetString(STR_KEYCODES_CTRL));
1178 >        gtk_widget_show(label);
1179 >        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1180 >
1181 >        const char *str = PrefsFindString("keycodefile");
1182 >        if (str == NULL)
1183 >                str = "";
1184 >
1185 >        w_keycode_file = gtk_entry_new();
1186 >        gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str);
1187 >        gtk_widget_show(w_keycode_file);
1188 >        gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0);
1189 >
1190 >        button = make_browse_button(w_keycode_file);
1191 >        gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1192 >        g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button);
1193  
1194          make_separator(box);
1195  
# Line 1163 | Line 1337 | static GList *add_ether_names(void)
1337                  }
1338                  close(s);
1339          }
1340 + #ifdef HAVE_SLIRP
1341 +        static char s_slirp[] = "slirp";
1342 +        glist = g_list_append(glist, s_slirp);
1343 + #endif
1344          if (glist)
1345                  g_list_sort(glist, gl_str_cmp);
1346          else
# Line 1252 | Line 1430 | static void create_serial_pane(GtkWidget
1430   *  "Memory/Misc" pane
1431   */
1432  
1433 < static GtkObject *w_ramsize_adj;
1433 > static GtkWidget *w_ramsize;
1434   static GtkWidget *w_rom_file;
1435  
1436 + // Don't use CPU when idle?
1437 + static void tb_idlewait(GtkWidget *widget)
1438 + {
1439 +        PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active);
1440 + }
1441 +
1442   // "Ignore SEGV" button toggled
1443   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1444   static void tb_ignoresegv(GtkWidget *widget)
# Line 1277 | Line 1461 | static void mn_cpu_68040(...) {PrefsRepl
1461   // Read settings from widgets and set preferences
1462   static void read_memory_settings(void)
1463   {
1464 <        PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
1464 >        const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry));
1465 >        PrefsReplaceInt32("ramsize", atoi(str) << 20);
1466  
1467 <        const char *str = get_file_entry_path(w_rom_file);
1467 >        str = get_file_entry_path(w_rom_file);
1468          if (str && strlen(str))
1469                  PrefsReplaceString("rom", str);
1470          else
# Line 1290 | Line 1475 | static void read_memory_settings(void)
1475   // Create "Memory/Misc" pane
1476   static void create_memory_pane(GtkWidget *top)
1477   {
1478 <        GtkWidget *box, *hbox, *vbox, *hbox2, *label, *scale;
1478 >        GtkWidget *box, *hbox, *table, *label, *menu;
1479  
1480          box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1481 +        table = make_table(box, 2, 5);
1482  
1483 <        hbox = gtk_hbox_new(FALSE, 4);
1484 <        gtk_widget_show(hbox);
1485 <
1486 <        label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1487 <        gtk_widget_show(label);
1488 <        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1489 <
1490 <        vbox = gtk_vbox_new(FALSE, 4);
1491 <        gtk_widget_show(vbox);
1492 <
1493 <        gfloat min, max;
1494 <        min = 1;
1495 <        max = 1024;
1496 <        w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1497 <        gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1498 <
1313 <        scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1314 <        gtk_widget_show(scale);
1315 <        gtk_scale_set_digits(GTK_SCALE(scale), 0);
1316 <        gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1317 <
1318 <        hbox2 = gtk_hbox_new(FALSE, 4);
1319 <        gtk_widget_show(hbox2);
1320 <
1321 <        char val[32];
1322 <        sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1323 <        label = gtk_label_new(val);
1324 <        gtk_widget_show(label);
1325 <        gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1326 <
1327 <        sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1328 <        label = gtk_label_new(val);
1329 <        gtk_widget_show(label);
1330 <        gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1331 <        gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1332 <        gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1333 <        gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1483 >        static const combo_desc options[] = {
1484 >                STR_RAMSIZE_2MB_LAB,
1485 >                STR_RAMSIZE_4MB_LAB,
1486 >                STR_RAMSIZE_8MB_LAB,
1487 >                STR_RAMSIZE_16MB_LAB,
1488 >                STR_RAMSIZE_32MB_LAB,
1489 >                STR_RAMSIZE_64MB_LAB,
1490 >                STR_RAMSIZE_128MB_LAB,
1491 >                STR_RAMSIZE_256MB_LAB,
1492 >                STR_RAMSIZE_512MB_LAB,
1493 >                STR_RAMSIZE_1024MB_LAB,
1494 >                0
1495 >        };
1496 >        char default_ramsize[10];
1497 >        sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20);
1498 >        w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options);
1499  
1500          static const opt_desc model_options[] = {
1501                  {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
# Line 1342 | Line 1507 | static void create_memory_pane(GtkWidget
1507                  case 5: active = 0; break;
1508                  case 14: active = 1; break;
1509          }
1510 <        make_option_menu(box, STR_MODELID_CTRL, model_options, active);
1510 >        table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active);
1511  
1512   #if EMULATED_68K
1513          static const opt_desc cpu_options[] = {
# Line 1361 | Line 1526 | static void create_memory_pane(GtkWidget
1526                  case 3: active = fpu ? 3 : 2; break;
1527                  case 4: active = 4;
1528          }
1529 <        make_option_menu(box, STR_CPU_CTRL, cpu_options, active);
1529 >        table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active);
1530   #endif
1531  
1532 <        w_rom_file = make_file_entry(box, STR_ROM_FILE_CTRL, "rom");
1532 >        w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom");
1533  
1534 +        make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1535   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1536          make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1537   #endif
# Line 1386 | Line 1552 | static void read_settings(void)
1552          read_memory_settings();
1553          read_jit_settings();
1554   }
1555 +
1556 +
1557 + #ifdef STANDALONE_GUI
1558 + #include <errno.h>
1559 + #include <sys/wait.h>
1560 + #include "rpc.h"
1561 +
1562 + /*
1563 + *  Fake unused data and functions
1564 + */
1565 +
1566 + uint8 XPRAM[XPRAM_SIZE];
1567 + void MountVolume(void *fh) { }
1568 + void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { }
1569 +
1570 + #if defined __APPLE__ && defined __MACH__
1571 + void DarwinSysInit(void) { }
1572 + void DarwinSysExit(void) { }
1573 + void DarwinAddFloppyPrefs(void) { }
1574 + void DarwinAddSerialPrefs(void) { }
1575 + bool DarwinCDReadTOC(char *, uint8 *) { }
1576 + #endif
1577 +
1578 +
1579 + /*
1580 + *  Display alert
1581 + */
1582 +
1583 + static void dl_destroyed(void)
1584 + {
1585 +        gtk_main_quit();
1586 + }
1587 +
1588 + static void display_alert(int title_id, int prefix_id, int button_id, const char *text)
1589 + {
1590 +        char str[256];
1591 +        sprintf(str, GetString(prefix_id), text);
1592 +
1593 +        GtkWidget *dialog = gtk_dialog_new();
1594 +        gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id));
1595 +        gtk_container_border_width(GTK_CONTAINER(dialog), 5);
1596 +        gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
1597 +        gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL);
1598 +
1599 +        GtkWidget *label = gtk_label_new(str);
1600 +        gtk_widget_show(label);
1601 +        gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
1602 +
1603 +        GtkWidget *button = gtk_button_new_with_label(GetString(button_id));
1604 +        gtk_widget_show(button);
1605 +        gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
1606 +        gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
1607 +        GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1608 +        gtk_widget_grab_default(button);
1609 +        gtk_widget_show(dialog);
1610 +
1611 +        gtk_main();
1612 + }
1613 +
1614 +
1615 + /*
1616 + *  Display error alert
1617 + */
1618 +
1619 + void ErrorAlert(const char *text)
1620 + {
1621 +        display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text);
1622 + }
1623 +
1624 +
1625 + /*
1626 + *  Display warning alert
1627 + */
1628 +
1629 + void WarningAlert(const char *text)
1630 + {
1631 +        display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text);
1632 + }
1633 +
1634 +
1635 + /*
1636 + *  RPC handlers
1637 + */
1638 +
1639 + static GMainLoop *g_gui_loop;
1640 +
1641 + static int handle_ErrorAlert(rpc_connection_t *connection)
1642 + {
1643 +        D(bug("handle_ErrorAlert\n"));
1644 +
1645 +        int error;
1646 +        char *str;
1647 +        if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
1648 +                return error;
1649 +
1650 +        ErrorAlert(str);
1651 +        free(str);
1652 +        return RPC_ERROR_NO_ERROR;
1653 + }
1654 +
1655 + static int handle_WarningAlert(rpc_connection_t *connection)
1656 + {
1657 +        D(bug("handle_WarningAlert\n"));
1658 +
1659 +        int error;
1660 +        char *str;
1661 +        if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
1662 +                return error;
1663 +
1664 +        WarningAlert(str);
1665 +        free(str);
1666 +        return RPC_ERROR_NO_ERROR;
1667 + }
1668 +
1669 + static int handle_Exit(rpc_connection_t *connection)
1670 + {
1671 +        D(bug("handle_Exit\n"));
1672 +
1673 +        g_main_quit(g_gui_loop);
1674 +        return RPC_ERROR_NO_ERROR;
1675 + }
1676 +
1677 +
1678 + /*
1679 + *  SIGCHLD handler
1680 + */
1681 +
1682 + static char g_app_path[PATH_MAX];
1683 + static rpc_connection_t *g_gui_connection = NULL;
1684 +
1685 + static void sigchld_handler(int sig, siginfo_t *sip, void *)
1686 + {
1687 +        D(bug("Child %d exitted with status = %x\n", sip->si_pid, sip->si_status));
1688 +
1689 +        // XXX perform a new wait because sip->si_status is sometimes not
1690 +        // the exit _value_ on MacOS X but rather the usual status field
1691 +        // from waitpid() -- we could arrange this code in some other way...
1692 +        int status;
1693 +        if (waitpid(sip->si_pid, &status, 0) < 0)
1694 +                status = sip->si_status;
1695 +        if (WIFEXITED(status))
1696 +                status = WEXITSTATUS(status);
1697 +        if (status & 0x80)
1698 +                status |= -1 ^0xff;
1699 +
1700 +        if (status < 0) {       // negative -> execlp/-errno
1701 +                char str[256];
1702 +                sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(-status));
1703 +                ErrorAlert(str);
1704 +                status = 1;
1705 +        }
1706 +
1707 +        if (status != 0) {
1708 +                if (g_gui_connection)
1709 +                        rpc_exit(g_gui_connection);
1710 +                exit(status);
1711 +        }
1712 + }
1713 +
1714 +
1715 + /*
1716 + *  Start standalone GUI
1717 + */
1718 +
1719 + int main(int argc, char *argv[])
1720 + {
1721 + #ifdef HAVE_GNOMEUI
1722 +        // Init GNOME/GTK
1723 +        char version[16];
1724 +        sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR);
1725 +        gnome_init("Basilisk II", version, argc, argv);
1726 + #else
1727 +        // Init GTK
1728 +        gtk_set_locale();
1729 +        gtk_init(&argc, &argv);
1730 + #endif
1731 +
1732 +        // Read preferences
1733 +        PrefsInit(argc, argv);
1734 +
1735 +        // Show preferences editor
1736 +        bool start = PrefsEditor();
1737 +
1738 +        // Exit preferences
1739 +        PrefsExit();
1740 +
1741 +        // Transfer control to the executable
1742 +        if (start) {
1743 +                char gui_connection_path[64];
1744 +                sprintf(gui_connection_path, "/org/BasiliskII/GUI/%d", getpid());
1745 +
1746 +                // Catch exits from the child process
1747 +                struct sigaction sigchld_sa, old_sigchld_sa;
1748 +                sigemptyset(&sigchld_sa.sa_mask);
1749 +                sigchld_sa.sa_sigaction = sigchld_handler;
1750 +                sigchld_sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
1751 +                if (sigaction(SIGCHLD, &sigchld_sa, &old_sigchld_sa) < 0) {
1752 +                        char str[256];
1753 +                        sprintf(str, GetString(STR_SIG_INSTALL_ERR), SIGCHLD, strerror(errno));
1754 +                        ErrorAlert(str);
1755 +                        return 1;
1756 +                }
1757 +
1758 +                // Search and run the BasiliskII executable
1759 +                char *p;
1760 +                strcpy(g_app_path, argv[0]);
1761 +                if ((p = strstr(g_app_path, "BasiliskIIGUI.app/Contents/MacOS")) != NULL) {
1762 +                    strcpy(p, "BasiliskII.app/Contents/MacOS/BasiliskII");
1763 +                        if (access(g_app_path, X_OK) < 0) {
1764 +                                char str[256];
1765 +                                sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(errno));
1766 +                                WarningAlert(str);
1767 +                                strcpy(g_app_path, "/Applications/BasiliskII.app/Contents/MacOS/BasiliskII");
1768 +                        }
1769 +                } else {
1770 +                        p = strrchr(g_app_path, '/');
1771 +                        p = p ? p + 1 : g_app_path;
1772 +                        strcpy(p, "BasiliskII");
1773 +                }
1774 +
1775 +                int pid = fork();
1776 +                if (pid == 0) {
1777 +                        D(bug("Trying to execute %s\n", g_app_path));
1778 +                        execlp(g_app_path, g_app_path, "--gui-connection", gui_connection_path, (char *)NULL);
1779 + #ifdef _POSIX_PRIORITY_SCHEDULING
1780 +                        // XXX get a chance to run the parent process so that to not confuse/upset GTK...
1781 +                        sched_yield();
1782 + #endif
1783 +                        _exit(-errno);
1784 +                }
1785 +
1786 +                // Establish a connection to Basilisk II
1787 +                if ((g_gui_connection = rpc_init_server(gui_connection_path)) == NULL) {
1788 +                        printf("ERROR: failed to initialize GUI-side RPC server connection\n");
1789 +                        return 1;
1790 +                }
1791 +                static const rpc_method_descriptor_t vtable[] = {
1792 +                        { RPC_METHOD_ERROR_ALERT,                       handle_ErrorAlert },
1793 +                        { RPC_METHOD_WARNING_ALERT,                     handle_WarningAlert },
1794 +                        { RPC_METHOD_EXIT,                                      handle_Exit }
1795 +                };
1796 +                if (rpc_method_add_callbacks(g_gui_connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
1797 +                        printf("ERROR: failed to setup GUI method callbacks\n");
1798 +                        return 1;
1799 +                }
1800 +                int socket;
1801 +                if ((socket = rpc_listen_socket(g_gui_connection)) < 0) {
1802 +                        printf("ERROR: failed to initialize RPC server thread\n");
1803 +                        return 1;
1804 +                }
1805 +
1806 +                g_gui_loop = g_main_new(TRUE);
1807 +                while (g_main_is_running(g_gui_loop)) {
1808 +
1809 +                        // Process a few events pending
1810 +                        const int N_EVENTS_DISPATCH = 10;
1811 +                        for (int i = 0; i < N_EVENTS_DISPATCH; i++) {
1812 +                                if (!g_main_iteration(FALSE))
1813 +                                        break;
1814 +                        }
1815 +
1816 +                        // Check for RPC events (100 ms timeout)
1817 +                        int ret = rpc_wait_dispatch(g_gui_connection, 100000);
1818 +                        if (ret == 0)
1819 +                                continue;
1820 +                        if (ret < 0)
1821 +                                break;
1822 +                        rpc_dispatch(g_gui_connection);
1823 +                }
1824 +
1825 +                rpc_exit(g_gui_connection);
1826 +                return 0;
1827 +        }
1828 +
1829 +        return 0;
1830 + }
1831 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines