~ubuntu-branches/ubuntu/feisty/basilisk2/feisty

« back to all changes in this revision

Viewing changes to src/Unix/prefs_editor_gtk.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2006-06-01 01:11:16 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060601011116-xjhegbgyfsxag5fl
Tags: 0.9.20060529-1
* New upstream CVS snapshot.
* Update local cdbs snippet copyright-check.mk:
  + Broaden scan to also look for "(c)" by default.
  + Make egrep options configurable.
  + Ignore auto-tools files.
* Bump up standards-version to 3.7.2 (no changes needed).
* Let dh_strip do the stripping (not the make install target).

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
#include "prefs.h"
40
40
#include "prefs_editor.h"
41
41
 
 
42
#define DEBUG 0
 
43
#include "debug.h"
 
44
 
42
45
 
43
46
// Global variables
44
47
static GtkWidget *win;                          // Preferences window
45
 
static bool start_clicked = true;       // Return value of PrefsEditor() function
 
48
static bool start_clicked = false;      // Return value of PrefsEditor() function
46
49
 
47
50
 
48
51
// Prototypes
60
63
 *  Utility functions
61
64
 */
62
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
 
63
72
struct opt_desc {
64
73
        int label_id;
65
74
        GtkSignalFunc func;
69
78
        int label_id;
70
79
};
71
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
 
72
114
static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func)
73
115
{
74
116
        GtkWidget *item = gtk_menu_item_new_with_label(GetString(label_id));
82
124
        GtkWidget *frame, *label, *box;
83
125
 
84
126
        frame = gtk_frame_new(NULL);
85
 
        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);
90
128
 
91
129
        box = gtk_vbox_new(FALSE, 4);
92
 
        gtk_widget_show(box);
93
130
        gtk_container_set_border_width(GTK_CONTAINER(box), 4);
94
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);
95
137
        return box;
96
138
}
97
139
 
132
174
        return table;
133
175
}
134
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
 
135
257
static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
136
258
{
137
259
        GtkWidget *box, *label, *opt, *menu;
306
428
        dialog = gnome_about_new(
307
429
                "Basilisk II",
308
430
                version,
309
 
                "Copyright (C) 1997-2004 Christian Bauer",
 
431
                "Copyright (C) 1997-2005 Christian Bauer",
310
432
                authors,
311
433
                "Basilisk II comes with ABSOLUTELY NO WARRANTY."
312
434
                "This is free software, and you are welcome to redistribute it"
322
444
        char str[512];
323
445
        sprintf(str,
324
446
                "Basilisk II\nVersion %d.%d\n\n"
325
 
                "Copyright (C) 1997-2004 Christian Bauer et al.\n"
 
447
                "Copyright (C) 1997-2005 Christian Bauer et al.\n"
326
448
                "E-mail: Christian.Bauer@uni-mainz.de\n"
327
449
                "http://www.uni-mainz.de/~bauec002/B2Main.html\n\n"
328
450
                "Basilisk II comes with ABSOLUTELY NO\n"
363
485
// Menu item descriptions
364
486
static GtkItemFactoryEntry menu_items[] = {
365
487
        {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK),           NULL,                   NULL,                                                   0, "<Branch>"},
366
 
        {(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},
367
489
        {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK),       NULL,                   GTK_SIGNAL_FUNC(mn_zap_pram),   0, NULL},
368
490
        {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK),           NULL,                   NULL,                                                   0, "<Separator>"},
369
491
        {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK),           "<control>Q",   GTK_SIGNAL_FUNC(cb_quit),               0, NULL},
397
519
        gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0);
398
520
 
399
521
        GtkWidget *notebook = gtk_notebook_new();
400
 
        gtk_widget_show(notebook);
401
522
        gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
402
523
        gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
403
524
        gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
 
525
        gtk_widget_realize(notebook);
404
526
 
405
527
        create_volumes_pane(notebook);
406
528
        create_scsi_pane(notebook);
409
531
        create_serial_pane(notebook);
410
532
        create_memory_pane(notebook);
411
533
        create_jit_pane(notebook);
 
534
        gtk_widget_show(notebook);
412
535
 
413
536
        static const opt_desc buttons[] = {
414
537
                {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
437
560
        selected_volume = row;
438
561
}
439
562
 
440
 
struct file_req_assoc {
441
 
        file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
442
 
        GtkWidget *req;
443
 
        GtkWidget *entry;
444
 
};
445
 
 
446
563
// Volume selected for addition
447
564
static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
448
565
{
595
712
static GtkWidget *w_jit_lazy_flush;
596
713
static GtkWidget *w_jit_follow_const_jumps;
597
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
 
598
736
// Set sensitivity of widgets
599
737
static void set_jit_sensitive(void)
600
738
{
633
771
// Read settings from widgets and set preferences
634
772
static void read_jit_settings(void)
635
773
{
636
 
#if USE_JIT
637
 
        bool jit_enabled = PrefsFindBool("jit");
 
774
        bool jit_enabled = is_jit_capable() && PrefsFindBool("jit");
638
775
        if (jit_enabled) {
639
776
                const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
640
777
                PrefsReplaceInt32("jitcachesize", atoi(str));
641
778
        }
642
 
#endif
643
779
}
644
780
 
645
781
// Create "JIT Compiler" pane
646
782
static void create_jit_pane(GtkWidget *top)
647
783
{
648
 
#if USE_JIT
 
784
        if (!is_jit_capable())
 
785
                return;
 
786
 
649
787
        GtkWidget *box, *table, *label, *menu;
650
788
        char str[32];
651
789
        
671
809
        w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
672
810
 
673
811
        set_jit_sensitive();
674
 
#endif
675
812
}
676
813
 
677
814
/*
994
1131
// Set sensitivity of widgets
995
1132
static void set_input_sensitive(void)
996
1133
{
997
 
        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);
998
1137
        gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
999
1138
}
1000
1139
 
1024
1163
// Create "Input" pane
1025
1164
static void create_input_pane(GtkWidget *top)
1026
1165
{
1027
 
        GtkWidget *box, *hbox, *menu, *label;
 
1166
        GtkWidget *box, *hbox, *menu, *label, *button;
1028
1167
        GtkObject *adj;
1029
1168
 
1030
1169
        box = make_pane(top, STR_INPUT_PANE_TITLE);
1031
1170
 
1032
1171
        make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1033
 
        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);
1034
1193
 
1035
1194
        make_separator(box);
1036
1195
 
1271
1430
 *  "Memory/Misc" pane
1272
1431
 */
1273
1432
 
1274
 
static GtkObject *w_ramsize_adj;
 
1433
static GtkWidget *w_ramsize;
1275
1434
static GtkWidget *w_rom_file;
1276
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
 
1277
1442
// "Ignore SEGV" button toggled
1278
1443
#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1279
1444
static void tb_ignoresegv(GtkWidget *widget)
1296
1461
// Read settings from widgets and set preferences
1297
1462
static void read_memory_settings(void)
1298
1463
{
1299
 
        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);
1300
1466
 
1301
 
        const char *str = get_file_entry_path(w_rom_file);
 
1467
        str = get_file_entry_path(w_rom_file);
1302
1468
        if (str && strlen(str))
1303
1469
                PrefsReplaceString("rom", str);
1304
1470
        else
1309
1475
// Create "Memory/Misc" pane
1310
1476
static void create_memory_pane(GtkWidget *top)
1311
1477
{
1312
 
        GtkWidget *box, *hbox, *vbox, *hbox2, *label, *scale;
 
1478
        GtkWidget *box, *hbox, *table, *label, *menu;
1313
1479
 
1314
1480
        box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1315
 
 
1316
 
        hbox = gtk_hbox_new(FALSE, 4);
1317
 
        gtk_widget_show(hbox);
1318
 
 
1319
 
        label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1320
 
        gtk_widget_show(label);
1321
 
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1322
 
 
1323
 
        vbox = gtk_vbox_new(FALSE, 4);
1324
 
        gtk_widget_show(vbox);
1325
 
 
1326
 
        gfloat min, max;
1327
 
        min = 1;
1328
 
        max = 1024;
1329
 
        w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1330
 
        gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1331
 
 
1332
 
        scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1333
 
        gtk_widget_show(scale);
1334
 
        gtk_scale_set_digits(GTK_SCALE(scale), 0);
1335
 
        gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1336
 
 
1337
 
        hbox2 = gtk_hbox_new(FALSE, 4);
1338
 
        gtk_widget_show(hbox2);
1339
 
 
1340
 
        char val[32];
1341
 
        sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1342
 
        label = gtk_label_new(val);
1343
 
        gtk_widget_show(label);
1344
 
        gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1345
 
 
1346
 
        sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1347
 
        label = gtk_label_new(val);
1348
 
        gtk_widget_show(label);
1349
 
        gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1350
 
        gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1351
 
        gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1352
 
        gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
 
1481
        table = make_table(box, 2, 5);
 
1482
 
 
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);
1353
1499
 
1354
1500
        static const opt_desc model_options[] = {
1355
1501
                {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1361
1507
                case 5: active = 0; break;
1362
1508
                case 14: active = 1; break;
1363
1509
        }
1364
 
        make_option_menu(box, STR_MODELID_CTRL, model_options, active);
 
1510
        table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active);
1365
1511
 
1366
1512
#if EMULATED_68K
1367
1513
        static const opt_desc cpu_options[] = {
1380
1526
                case 3: active = fpu ? 3 : 2; break;
1381
1527
                case 4: active = 4;
1382
1528
        }
1383
 
        make_option_menu(box, STR_CPU_CTRL, cpu_options, active);
 
1529
        table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active);
1384
1530
#endif
1385
1531
 
1386
 
        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");
1387
1533
 
 
1534
        make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1388
1535
#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1389
1536
        make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1390
1537
#endif
1405
1552
        read_memory_settings();
1406
1553
        read_jit_settings();
1407
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