ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
Revision: 1.34
Committed: 2006-04-17T14:25:57Z (18 years, 5 months ago) by gbeauche
Branch: MAIN
Changes since 1.33: +10 -9 lines
Log Message:
Fixes for GTK+1.2 GUI on MacOS X

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs_editor_gtk.cpp - Preferences editor, Unix implementation using GTK+
3     *
4 gbeauche 1.26 * Basilisk II (C) 1997-2005 Christian Bauer
5 cebix 1.1 *
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
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "sysdeps.h"
22    
23     #include <gtk/gtk.h>
24     #include <stdlib.h>
25     #include <dirent.h>
26     #include <sys/socket.h>
27     #include <sys/ioctl.h>
28     #include <net/if.h>
29     #include <net/if_arp.h>
30    
31 cebix 1.21 #ifdef HAVE_GNOMEUI
32     #include <gnome.h>
33     #endif
34    
35 cebix 1.1 #include "user_strings.h"
36     #include "version.h"
37     #include "cdrom.h"
38     #include "xpram.h"
39     #include "prefs.h"
40     #include "prefs_editor.h"
41    
42 gbeauche 1.33 #define DEBUG 0
43     #include "debug.h"
44    
45 cebix 1.1
46     // Global variables
47     static GtkWidget *win; // Preferences window
48     static bool start_clicked = true; // Return value of PrefsEditor() function
49    
50    
51     // Prototypes
52     static void create_volumes_pane(GtkWidget *top);
53     static void create_scsi_pane(GtkWidget *top);
54     static void create_graphics_pane(GtkWidget *top);
55 cebix 1.13 static void create_input_pane(GtkWidget *top);
56 cebix 1.1 static void create_serial_pane(GtkWidget *top);
57     static void create_memory_pane(GtkWidget *top);
58 gbeauche 1.23 static void create_jit_pane(GtkWidget *top);
59 cebix 1.1 static void read_settings(void);
60    
61    
62     /*
63     * Utility functions
64     */
65    
66 gbeauche 1.31 #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 cebix 1.1 struct opt_desc {
73     int label_id;
74     GtkSignalFunc func;
75     };
76    
77 gbeauche 1.23 struct combo_desc {
78     int label_id;
79     };
80    
81 gbeauche 1.29 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 cebix 1.1 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));
117     gtk_widget_show(item);
118     gtk_signal_connect(GTK_OBJECT(item), "activate", func, NULL);
119     gtk_menu_append(GTK_MENU(menu), item);
120     }
121    
122     static GtkWidget *make_pane(GtkWidget *notebook, int title_id)
123     {
124     GtkWidget *frame, *label, *box;
125    
126     frame = gtk_frame_new(NULL);
127 gbeauche 1.34 gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
128 cebix 1.1
129     box = gtk_vbox_new(FALSE, 4);
130     gtk_container_set_border_width(GTK_CONTAINER(box), 4);
131     gtk_container_add(GTK_CONTAINER(frame), box);
132 gbeauche 1.34
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 cebix 1.1 return box;
138     }
139    
140     static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons)
141     {
142     GtkWidget *bb, *button;
143    
144     bb = gtk_hbutton_box_new();
145     gtk_widget_show(bb);
146     gtk_container_set_border_width(GTK_CONTAINER(bb), border);
147     gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE);
148     gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4);
149     gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0);
150    
151     while (buttons->label_id) {
152     button = gtk_button_new_with_label(GetString(buttons->label_id));
153     gtk_widget_show(button);
154     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL);
155     gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0);
156     buttons++;
157     }
158     return bb;
159     }
160    
161     static GtkWidget *make_separator(GtkWidget *top)
162     {
163     GtkWidget *sep = gtk_hseparator_new();
164     gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0);
165     gtk_widget_show(sep);
166     return sep;
167     }
168    
169     static GtkWidget *make_table(GtkWidget *top, int x, int y)
170     {
171     GtkWidget *table = gtk_table_new(x, y, FALSE);
172     gtk_widget_show(table);
173     gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0);
174     return table;
175     }
176    
177 gbeauche 1.29 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 cebix 1.1 static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
258     {
259     GtkWidget *box, *label, *opt, *menu;
260    
261     box = gtk_hbox_new(FALSE, 4);
262     gtk_widget_show(box);
263     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
264    
265     label = gtk_label_new(GetString(label_id));
266     gtk_widget_show(label);
267     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
268    
269     opt = gtk_option_menu_new();
270     gtk_widget_show(opt);
271     menu = gtk_menu_new();
272    
273     while (options->label_id) {
274     add_menu_item(menu, options->label_id, options->func);
275     options++;
276     }
277     gtk_menu_set_active(GTK_MENU(menu), active);
278    
279     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
280     gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0);
281     return menu;
282     }
283    
284 cebix 1.21 static GtkWidget *make_file_entry(GtkWidget *top, int label_id, const char *prefs_item, bool only_dirs = false)
285 cebix 1.1 {
286     GtkWidget *box, *label, *entry;
287    
288     box = gtk_hbox_new(FALSE, 4);
289     gtk_widget_show(box);
290     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
291    
292     label = gtk_label_new(GetString(label_id));
293     gtk_widget_show(label);
294     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
295    
296     const char *str = PrefsFindString(prefs_item);
297     if (str == NULL)
298     str = "";
299 cebix 1.21
300     #ifdef HAVE_GNOMEUI
301     entry = gnome_file_entry_new(NULL, GetString(label_id));
302     if (only_dirs)
303     gnome_file_entry_set_directory(GNOME_FILE_ENTRY(entry), true);
304     gtk_entry_set_text(GTK_ENTRY(gnome_file_entry_gtk_entry(GNOME_FILE_ENTRY(entry))), str);
305     #else
306     entry = gtk_entry_new();
307 cebix 1.1 gtk_entry_set_text(GTK_ENTRY(entry), str);
308 cebix 1.21 #endif
309     gtk_widget_show(entry);
310 cebix 1.1 gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
311     return entry;
312     }
313    
314 gbeauche 1.28 static const gchar *get_file_entry_path(GtkWidget *entry)
315 cebix 1.21 {
316     #ifdef HAVE_GNOMEUI
317     return gnome_file_entry_get_full_path(GNOME_FILE_ENTRY(entry), false);
318     #else
319     return gtk_entry_get_text(GTK_ENTRY(entry));
320     #endif
321     }
322    
323 cebix 1.1 static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func)
324     {
325     GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
326     gtk_widget_show(button);
327     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item));
328     gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button);
329     gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0);
330     return button;
331     }
332    
333 gbeauche 1.23 static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *prefs_item, const combo_desc *options)
334     {
335     GtkWidget *box, *label, *combo;
336     char str[32];
337    
338     box = gtk_hbox_new(FALSE, 4);
339     gtk_widget_show(box);
340     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
341    
342     label = gtk_label_new(GetString(label_id));
343     gtk_widget_show(label);
344     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
345    
346     GList *glist = NULL;
347     while (options->label_id) {
348     glist = g_list_append(glist, (void *)GetString(options->label_id));
349     options++;
350     }
351    
352     combo = gtk_combo_new();
353     gtk_widget_show(combo);
354     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
355    
356     sprintf(str, "%d", PrefsFindInt32(prefs_item));
357     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
358     gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0);
359    
360     return combo;
361     }
362 cebix 1.1
363 gbeauche 1.23
364 cebix 1.1 /*
365     * Show preferences editor
366     * Returns true when user clicked on "Start", false otherwise
367     */
368    
369     // Window closed
370     static gint window_closed(void)
371     {
372     return FALSE;
373     }
374    
375     // Window destroyed
376     static void window_destroyed(void)
377     {
378     gtk_main_quit();
379     }
380    
381     // "Start" button clicked
382     static void cb_start(...)
383     {
384     start_clicked = true;
385     read_settings();
386     SavePrefs();
387     gtk_widget_destroy(win);
388     }
389    
390     // "Quit" button clicked
391     static void cb_quit(...)
392     {
393     start_clicked = false;
394     gtk_widget_destroy(win);
395     }
396    
397     // "OK" button of "About" dialog clicked
398     static void dl_quit(GtkWidget *dialog)
399     {
400     gtk_widget_destroy(dialog);
401     }
402    
403     // "About" selected
404     static void mn_about(...)
405     {
406 cebix 1.21 GtkWidget *dialog;
407    
408     #ifdef HAVE_GNOMEUI
409    
410     char version[32];
411     sprintf(version, "Version %d.%d", VERSION_MAJOR, VERSION_MINOR);
412     const char *authors[] = {
413     "Christian Bauer",
414     "Orlando Bassotto",
415     "Gwenolé Beauchesne",
416     "Marc Chabanas",
417     "Marc Hellwig",
418     "Biill Huey",
419     "Brian J. Johnson",
420     "Jürgen Lachmann",
421     "Samuel Lander",
422     "David Lawrence",
423     "Lauri Pesonen",
424     "Bernd Schmidt",
425     "and others",
426     NULL
427     };
428     dialog = gnome_about_new(
429     "Basilisk II",
430     version,
431 gbeauche 1.30 "Copyright (C) 1997-2005 Christian Bauer",
432 cebix 1.21 authors,
433     "Basilisk II comes with ABSOLUTELY NO WARRANTY."
434     "This is free software, and you are welcome to redistribute it"
435     "under the terms of the GNU General Public License.",
436     NULL
437     );
438     gnome_dialog_set_parent(GNOME_DIALOG(dialog), GTK_WINDOW(win));
439    
440     #else
441    
442     GtkWidget *label, *button;
443 cebix 1.1
444 cebix 1.16 char str[512];
445     sprintf(str,
446     "Basilisk II\nVersion %d.%d\n\n"
447 gbeauche 1.30 "Copyright (C) 1997-2005 Christian Bauer et al.\n"
448 cebix 1.16 "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"
451     "WARRANTY. This is free software, and\n"
452     "you are welcome to redistribute it\n"
453     "under the terms of the GNU General\n"
454     "Public License.\n",
455     VERSION_MAJOR, VERSION_MINOR
456     );
457 cebix 1.1
458     dialog = gtk_dialog_new();
459     gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE));
460     gtk_container_border_width(GTK_CONTAINER(dialog), 5);
461     gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
462    
463     label = gtk_label_new(str);
464     gtk_widget_show(label);
465     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
466    
467     button = gtk_button_new_with_label(GetString(STR_OK_BUTTON));
468     gtk_widget_show(button);
469     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
470     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
471     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
472     gtk_widget_grab_default(button);
473 cebix 1.21
474     #endif
475    
476 cebix 1.1 gtk_widget_show(dialog);
477     }
478    
479     // "Zap PRAM" selected
480     static void mn_zap_pram(...)
481     {
482     ZapPRAM();
483     }
484    
485     // Menu item descriptions
486     static GtkItemFactoryEntry menu_items[] = {
487 cebix 1.4 {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, "<Branch>"},
488 gbeauche 1.29 {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), "<control>S", GTK_SIGNAL_FUNC(cb_start), 0, NULL},
489 cebix 1.4 {(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},
492     {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, "<LastBranch>"},
493     {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), NULL, GTK_SIGNAL_FUNC(mn_about), 0, NULL}
494 cebix 1.1 };
495    
496     bool PrefsEditor(void)
497     {
498     // Create window
499     win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
500     gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE));
501     gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL);
502     gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL);
503    
504     // Create window contents
505     GtkWidget *box = gtk_vbox_new(FALSE, 4);
506     gtk_widget_show(box);
507     gtk_container_add(GTK_CONTAINER(win), box);
508    
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 gbeauche 1.28 #if GTK_CHECK_VERSION(1,3,15)
513     gtk_window_add_accel_group(GTK_WINDOW(win), accel_group);
514     #else
515 cebix 1.1 gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
516 gbeauche 1.28 #endif
517 cebix 1.1 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();
522     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
523 cebix 1.8 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
524 cebix 1.1 gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
525 gbeauche 1.34 gtk_widget_realize(notebook);
526 cebix 1.1
527     create_volumes_pane(notebook);
528     create_scsi_pane(notebook);
529     create_graphics_pane(notebook);
530 cebix 1.13 create_input_pane(notebook);
531 cebix 1.1 create_serial_pane(notebook);
532     create_memory_pane(notebook);
533 gbeauche 1.23 create_jit_pane(notebook);
534 gbeauche 1.34 gtk_widget_show(notebook);
535 cebix 1.1
536     static const opt_desc buttons[] = {
537     {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
538     {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
539     {0, NULL}
540     };
541     make_button_box(box, 4, buttons);
542    
543     // Show window and enter main loop
544     gtk_widget_show(win);
545     gtk_main();
546     return start_clicked;
547     }
548    
549    
550     /*
551     * "Volumes" pane
552     */
553    
554 cebix 1.6 static GtkWidget *volume_list, *w_extfs;
555 cebix 1.1 static int selected_volume;
556    
557     // Volume in list selected
558     static void cl_selected(GtkWidget *list, int row, int column)
559     {
560     selected_volume = row;
561     }
562    
563     // Volume selected for addition
564     static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
565     {
566 gbeauche 1.28 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
567 cebix 1.1 gtk_clist_append(GTK_CLIST(volume_list), &file);
568     gtk_widget_destroy(assoc->req);
569     delete assoc;
570     }
571    
572     // Volume selected for creation
573     static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
574     {
575 gbeauche 1.28 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
576 cebix 1.1
577 gbeauche 1.28 const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
578 cebix 1.1 int size = atoi(str);
579    
580     char cmd[1024];
581     sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size);
582     int ret = system(cmd);
583     if (ret == 0)
584     gtk_clist_append(GTK_CLIST(volume_list), &file);
585     gtk_widget_destroy(GTK_WIDGET(assoc->req));
586     delete assoc;
587     }
588    
589     // "Add Volume" button clicked
590     static void cb_add_volume(...)
591     {
592     GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE));
593     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
594     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL));
595     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
596     gtk_widget_show(req);
597     }
598    
599     // "Create Hardfile" button clicked
600     static void cb_create_volume(...)
601     {
602     GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE));
603    
604     GtkWidget *box = gtk_hbox_new(FALSE, 4);
605     gtk_widget_show(box);
606     GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL));
607     gtk_widget_show(label);
608     GtkWidget *entry = gtk_entry_new();
609     gtk_widget_show(entry);
610     char str[32];
611     sprintf(str, "%d", 40);
612     gtk_entry_set_text(GTK_ENTRY(entry), str);
613     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
614     gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
615     gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0);
616    
617     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
618     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry));
619     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
620     gtk_widget_show(req);
621     }
622    
623     // "Remove Volume" button clicked
624     static void cb_remove_volume(...)
625     {
626     gtk_clist_remove(GTK_CLIST(volume_list), selected_volume);
627     }
628    
629     // "Boot From" selected
630 cebix 1.14 static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
631     static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
632 cebix 1.1
633     // "No CD-ROM Driver" button toggled
634     static void tb_nocdrom(GtkWidget *widget)
635     {
636     PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
637     }
638    
639     // Read settings from widgets and set preferences
640     static void read_volumes_settings(void)
641     {
642     while (PrefsFindString("disk"))
643     PrefsRemoveItem("disk");
644    
645     for (int i=0; i<GTK_CLIST(volume_list)->rows; i++) {
646     char *str;
647     gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
648     PrefsAddString("disk", str);
649     }
650 cebix 1.6
651 cebix 1.21 PrefsReplaceString("extfs", get_file_entry_path(w_extfs));
652 cebix 1.1 }
653    
654     // Create "Volumes" pane
655     static void create_volumes_pane(GtkWidget *top)
656     {
657     GtkWidget *box, *scroll, *menu;
658    
659     box = make_pane(top, STR_VOLUMES_PANE_TITLE);
660    
661     scroll = gtk_scrolled_window_new(NULL, NULL);
662     gtk_widget_show(scroll);
663     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
664     volume_list = gtk_clist_new(1);
665     gtk_widget_show(volume_list);
666     gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE);
667     gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE);
668 cebix 1.5 gtk_clist_set_reorderable(GTK_CLIST(volume_list), true);
669 cebix 1.1 gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL);
670     char *str;
671     int32 index = 0;
672 cebix 1.21 while ((str = const_cast<char *>(PrefsFindString("disk", index++))) != NULL)
673 cebix 1.1 gtk_clist_append(GTK_CLIST(volume_list), &str);
674     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list);
675     gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
676     selected_volume = 0;
677    
678     static const opt_desc buttons[] = {
679     {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)},
680     {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)},
681     {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)},
682     {0, NULL},
683     };
684     make_button_box(box, 0, buttons);
685     make_separator(box);
686 cebix 1.6
687 cebix 1.21 w_extfs = make_file_entry(box, STR_EXTFS_CTRL, "extfs", true);
688 cebix 1.1
689     static const opt_desc options[] = {
690     {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)},
691     {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)},
692     {0, NULL}
693     };
694 cebix 1.14 int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
695 cebix 1.1 switch (bootdriver) {
696     case 0: active = 0; break;
697     case CDROMRefNum: active = 1; break;
698     }
699     menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
700    
701     make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
702     }
703    
704    
705     /*
706 gbeauche 1.23 * "JIT Compiler" pane
707     */
708    
709     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 gbeauche 1.27 static GtkWidget *w_jit_follow_const_jumps;
714 gbeauche 1.23
715     // Set sensitivity of widgets
716     static void set_jit_sensitive(void)
717     {
718     const bool jit_enabled = PrefsFindBool("jit");
719     gtk_widget_set_sensitive(w_jit_fpu, jit_enabled);
720     gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled);
721     gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled);
722 gbeauche 1.27 gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled);
723 gbeauche 1.23 }
724    
725     // "Use JIT Compiler" button toggled
726     static void tb_jit(GtkWidget *widget)
727     {
728     PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active);
729     set_jit_sensitive();
730     }
731    
732     // "Compile FPU Instructions" button toggled
733     static void tb_jit_fpu(GtkWidget *widget)
734     {
735     PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active);
736     }
737    
738     // "Lazy translation cache invalidation" button toggled
739     static void tb_jit_lazy_flush(GtkWidget *widget)
740     {
741     PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active);
742     }
743    
744 gbeauche 1.27 // "Translate through constant jumps (inline blocks)" button toggled
745     static void tb_jit_follow_const_jumps(GtkWidget *widget)
746     {
747     PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active);
748     }
749    
750 gbeauche 1.23 // Read settings from widgets and set preferences
751     static void read_jit_settings(void)
752     {
753     #if USE_JIT
754     bool jit_enabled = PrefsFindBool("jit");
755     if (jit_enabled) {
756     const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
757     PrefsReplaceInt32("jitcachesize", atoi(str));
758     }
759     #endif
760     }
761    
762     // Create "JIT Compiler" pane
763     static void create_jit_pane(GtkWidget *top)
764     {
765     #if USE_JIT
766     GtkWidget *box, *table, *label, *menu;
767     char str[32];
768    
769     box = make_pane(top, STR_JIT_PANE_TITLE);
770     make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
771    
772     w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu));
773    
774     // Translation cache size
775     static const combo_desc options[] = {
776     STR_JIT_CACHE_SIZE_2MB_LAB,
777     STR_JIT_CACHE_SIZE_4MB_LAB,
778     STR_JIT_CACHE_SIZE_8MB_LAB,
779     STR_JIT_CACHE_SIZE_16MB_LAB,
780     0
781     };
782     w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, "jitcachesize", options);
783    
784     // Lazy translation cache invalidation
785     w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush));
786 gbeauche 1.27
787     // Follow constant jumps (inline basic blocks)
788     w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
789    
790 gbeauche 1.23 set_jit_sensitive();
791     #endif
792     }
793    
794     /*
795 cebix 1.1 * "SCSI" pane
796     */
797    
798     static GtkWidget *w_scsi[7];
799    
800     // Read settings from widgets and set preferences
801     static void read_scsi_settings(void)
802     {
803     for (int id=0; id<7; id++) {
804     char prefs_name[32];
805     sprintf(prefs_name, "scsi%d", id);
806 cebix 1.21 const char *str = get_file_entry_path(w_scsi[id]);
807 cebix 1.1 if (str && strlen(str))
808     PrefsReplaceString(prefs_name, str);
809     else
810     PrefsRemoveItem(prefs_name);
811     }
812     }
813    
814     // Create "SCSI" pane
815     static void create_scsi_pane(GtkWidget *top)
816     {
817     GtkWidget *box;
818    
819     box = make_pane(top, STR_SCSI_PANE_TITLE);
820    
821     for (int id=0; id<7; id++) {
822     char prefs_name[32];
823     sprintf(prefs_name, "scsi%d", id);
824 cebix 1.21 w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name);
825 cebix 1.1 }
826     }
827    
828    
829     /*
830     * "Graphics/Sound" pane
831     */
832    
833     // Display types
834     enum {
835     DISPLAY_WINDOW,
836     DISPLAY_SCREEN
837     };
838    
839     static GtkWidget *w_frameskip, *w_display_x, *w_display_y;
840     static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
841     static int display_type;
842     static int dis_width, dis_height;
843    
844 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
845 cebix 1.7 static GtkWidget *w_fbdev_name, *w_fbdevice_file;
846     static GtkWidget *l_fbdev_name, *l_fbdevice_file;
847     static char fbdev_name[256];
848     #endif
849    
850 cebix 1.24 static GtkWidget *w_dspdevice_file, *w_mixerdevice_file;
851    
852 cebix 1.1 // Hide/show graphics widgets
853     static void hide_show_graphics_widgets(void)
854     {
855     switch (display_type) {
856     case DISPLAY_WINDOW:
857     gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
858 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
859 cebix 1.7 gtk_widget_show(w_display_x); gtk_widget_show(l_display_x);
860     gtk_widget_show(w_display_y); gtk_widget_show(l_display_y);
861     gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name);
862     #endif
863 cebix 1.1 break;
864     case DISPLAY_SCREEN:
865     gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
866 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
867 cebix 1.7 gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x);
868     gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y);
869     gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name);
870     #endif
871 cebix 1.1 break;
872     }
873     }
874    
875     // "Window" video type selected
876     static void mn_window(...)
877     {
878     display_type = DISPLAY_WINDOW;
879     hide_show_graphics_widgets();
880     }
881    
882     // "Fullscreen" video type selected
883     static void mn_fullscreen(...)
884     {
885     display_type = DISPLAY_SCREEN;
886     hide_show_graphics_widgets();
887     }
888    
889     // "5 Hz".."60Hz" selected
890     static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
891     static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
892     static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
893     static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
894     static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
895     static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
896 cebix 1.12 static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
897 cebix 1.1
898 cebix 1.24 // Set sensitivity of widgets
899     static void set_graphics_sensitive(void)
900     {
901     const bool sound_enabled = !PrefsFindBool("nosound");
902     gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled);
903     gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled);
904     }
905    
906 cebix 1.1 // "Disable Sound Output" button toggled
907     static void tb_nosound(GtkWidget *widget)
908     {
909     PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
910 cebix 1.24 set_graphics_sensitive();
911 cebix 1.1 }
912    
913     // Read graphics preferences
914     static void parse_graphics_prefs(void)
915     {
916     display_type = DISPLAY_WINDOW;
917     dis_width = 512;
918     dis_height = 384;
919 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
920 cebix 1.7 fbdev_name[0] = 0;
921     #endif
922 cebix 1.1
923     const char *str = PrefsFindString("screen");
924     if (str) {
925     if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
926     display_type = DISPLAY_WINDOW;
927 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
928 cebix 1.7 else if (sscanf(str, "dga/%255s", fbdev_name) == 1)
929     #else
930 cebix 1.2 else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
931 cebix 1.7 #endif
932 cebix 1.1 display_type = DISPLAY_SCREEN;
933     }
934     }
935    
936     // Read settings from widgets and set preferences
937     static void read_graphics_settings(void)
938     {
939     const char *str;
940    
941     str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
942     dis_width = atoi(str);
943    
944     str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
945     dis_height = atoi(str);
946    
947     char pref[256];
948     switch (display_type) {
949     case DISPLAY_WINDOW:
950     sprintf(pref, "win/%d/%d", dis_width, dis_height);
951     break;
952     case DISPLAY_SCREEN:
953 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
954 cebix 1.7 str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name));
955     sprintf(pref, "dga/%s", str);
956     #else
957 cebix 1.2 sprintf(pref, "dga/%d/%d", dis_width, dis_height);
958 cebix 1.7 #endif
959 cebix 1.1 break;
960     default:
961     PrefsRemoveItem("screen");
962     return;
963     }
964     PrefsReplaceString("screen", pref);
965 cebix 1.21
966     #ifdef ENABLE_FBDEV_DGA
967     str = get_file_entry_path(w_fbdevice_file);
968     if (str && strlen(str))
969     PrefsReplaceString("fbdevicefile", str);
970     else
971     PrefsRemoveItem("fbdevicefile");
972     #endif
973 cebix 1.24 PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file));
974     PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file));
975 cebix 1.1 }
976    
977     // Create "Graphics/Sound" pane
978     static void create_graphics_pane(GtkWidget *top)
979     {
980 cebix 1.2 GtkWidget *box, *table, *label, *opt, *menu, *combo;
981 cebix 1.1 char str[32];
982    
983     parse_graphics_prefs();
984    
985     box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
986 cebix 1.7 table = make_table(box, 2, 5);
987 cebix 1.1
988     label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
989     gtk_widget_show(label);
990     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
991    
992     opt = gtk_option_menu_new();
993     gtk_widget_show(opt);
994     menu = gtk_menu_new();
995     add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window));
996     add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen));
997     switch (display_type) {
998     case DISPLAY_WINDOW:
999     gtk_menu_set_active(GTK_MENU(menu), 0);
1000     break;
1001     case DISPLAY_SCREEN:
1002     gtk_menu_set_active(GTK_MENU(menu), 1);
1003     break;
1004     }
1005     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
1006     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1007    
1008     l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
1009     gtk_widget_show(l_frameskip);
1010     gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1011    
1012     w_frameskip = gtk_option_menu_new();
1013     gtk_widget_show(w_frameskip);
1014     menu = gtk_menu_new();
1015     add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
1016     add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
1017     add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
1018     add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
1019     add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
1020     add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
1021 cebix 1.12 add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic));
1022 cebix 1.1 int frameskip = PrefsFindInt32("frameskip");
1023 cebix 1.12 int item = -1;
1024 cebix 1.1 switch (frameskip) {
1025 cebix 1.12 case 12: item = 0; break;
1026     case 8: item = 1; break;
1027     case 6: item = 2; break;
1028     case 4: item = 3; break;
1029     case 2: item = 4; break;
1030     case 1: item = 5; break;
1031     case 0: item = 6; break;
1032 cebix 1.1 }
1033 cebix 1.12 if (item >= 0)
1034     gtk_menu_set_active(GTK_MENU(menu), item);
1035 cebix 1.1 gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
1036     gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1037    
1038     l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
1039     gtk_widget_show(l_display_x);
1040     gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1041    
1042 cebix 1.2 combo = gtk_combo_new();
1043     gtk_widget_show(combo);
1044     GList *glist1 = NULL;
1045 cebix 1.4 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
1046     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
1047     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
1048     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
1049     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
1050 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
1051     if (dis_width)
1052     sprintf(str, "%d", dis_width);
1053     else
1054 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
1055 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1056     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1057     w_display_x = GTK_COMBO(combo)->entry;
1058 cebix 1.1
1059     l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
1060     gtk_widget_show(l_display_y);
1061     gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1062    
1063 cebix 1.2 combo = gtk_combo_new();
1064     gtk_widget_show(combo);
1065     GList *glist2 = NULL;
1066 cebix 1.4 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
1067     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
1068     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
1069     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
1070     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
1071 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
1072     if (dis_height)
1073     sprintf(str, "%d", dis_height);
1074     else
1075 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
1076 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1077     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1078     w_display_y = GTK_COMBO(combo)->entry;
1079 cebix 1.7
1080 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
1081 cebix 1.7 l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL));
1082     gtk_widget_show(l_fbdev_name);
1083     gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1084    
1085     w_fbdev_name = gtk_entry_new();
1086     gtk_widget_show(w_fbdev_name);
1087     gtk_entry_set_text(GTK_ENTRY(w_fbdev_name), fbdev_name);
1088     gtk_table_attach(GTK_TABLE(table), w_fbdev_name, 1, 2, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1089    
1090 cebix 1.21 w_fbdevice_file = make_file_entry(box, STR_FBDEVICE_FILE_CTRL, "fbdevicefile");
1091 cebix 1.7 #endif
1092 cebix 1.1
1093 cebix 1.13 make_separator(box);
1094 cebix 1.1 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
1095 cebix 1.24 w_dspdevice_file = make_file_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp");
1096     w_mixerdevice_file = make_file_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer");
1097    
1098     set_graphics_sensitive();
1099 cebix 1.1
1100     hide_show_graphics_widgets();
1101     }
1102    
1103    
1104     /*
1105 cebix 1.13 * "Input" pane
1106     */
1107    
1108     static GtkWidget *w_keycode_file;
1109     static GtkWidget *w_mouse_wheel_lines;
1110    
1111     // Set sensitivity of widgets
1112     static void set_input_sensitive(void)
1113     {
1114 gbeauche 1.29 const bool use_keycodes = PrefsFindBool("keycodes");
1115     gtk_widget_set_sensitive(w_keycode_file, use_keycodes);
1116     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes);
1117 cebix 1.14 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
1118 cebix 1.13 }
1119    
1120     // "Use Raw Keycodes" button toggled
1121     static void tb_keycodes(GtkWidget *widget)
1122     {
1123     PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
1124     set_input_sensitive();
1125     }
1126    
1127     // "Mouse Wheel Mode" selected
1128 cebix 1.14 static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
1129     static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
1130 cebix 1.13
1131     // Read settings from widgets and set preferences
1132     static void read_input_settings(void)
1133     {
1134 cebix 1.21 const char *str = get_file_entry_path(w_keycode_file);
1135 cebix 1.13 if (str && strlen(str))
1136     PrefsReplaceString("keycodefile", str);
1137     else
1138     PrefsRemoveItem("keycodefile");
1139    
1140 cebix 1.14 PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
1141 cebix 1.13 }
1142    
1143     // Create "Input" pane
1144     static void create_input_pane(GtkWidget *top)
1145     {
1146 gbeauche 1.29 GtkWidget *box, *hbox, *menu, *label, *button;
1147 cebix 1.13 GtkObject *adj;
1148    
1149     box = make_pane(top, STR_INPUT_PANE_TITLE);
1150    
1151     make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1152 gbeauche 1.29
1153     hbox = gtk_hbox_new(FALSE, 4);
1154     gtk_widget_show(hbox);
1155     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1156    
1157     label = gtk_label_new(GetString(STR_KEYCODES_CTRL));
1158     gtk_widget_show(label);
1159     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1160    
1161     const char *str = PrefsFindString("keycodefile");
1162     if (str == NULL)
1163     str = "";
1164    
1165     w_keycode_file = gtk_entry_new();
1166     gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str);
1167     gtk_widget_show(w_keycode_file);
1168     gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0);
1169    
1170     button = make_browse_button(w_keycode_file);
1171     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1172     g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button);
1173 cebix 1.13
1174     make_separator(box);
1175    
1176     static const opt_desc options[] = {
1177     {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
1178     {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
1179     {0, NULL}
1180     };
1181 cebix 1.14 int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
1182 cebix 1.13 switch (wheelmode) {
1183     case 0: active = 0; break;
1184     case 1: active = 1; break;
1185     }
1186     menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
1187    
1188     hbox = gtk_hbox_new(FALSE, 4);
1189     gtk_widget_show(hbox);
1190     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1191    
1192     label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
1193     gtk_widget_show(label);
1194     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1195    
1196 cebix 1.14 adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
1197 cebix 1.13 w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1198     gtk_widget_show(w_mouse_wheel_lines);
1199     gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
1200    
1201     set_input_sensitive();
1202     }
1203    
1204    
1205     /*
1206 cebix 1.1 * "Serial/Network" pane
1207     */
1208    
1209 cebix 1.18 static GtkWidget *w_seriala, *w_serialb, *w_ether, *w_udp_port;
1210    
1211     // Set sensitivity of widgets
1212     static void set_serial_sensitive(void)
1213     {
1214     #if SUPPORTS_UDP_TUNNEL
1215     gtk_widget_set_sensitive(w_ether, !PrefsFindBool("udptunnel"));
1216     gtk_widget_set_sensitive(w_udp_port, PrefsFindBool("udptunnel"));
1217     #endif
1218     }
1219    
1220     // "Tunnel AppleTalk over IP" button toggled
1221     static void tb_udptunnel(GtkWidget *widget)
1222     {
1223     PrefsReplaceBool("udptunnel", GTK_TOGGLE_BUTTON(widget)->active);
1224     set_serial_sensitive();
1225     }
1226 cebix 1.1
1227     // Read settings from widgets and set preferences
1228     static void read_serial_settings(void)
1229     {
1230     const char *str;
1231    
1232     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1233     PrefsReplaceString("seriala", str);
1234    
1235     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1236     PrefsReplaceString("serialb", str);
1237    
1238     str = gtk_entry_get_text(GTK_ENTRY(w_ether));
1239     if (str && strlen(str))
1240     PrefsReplaceString("ether", str);
1241     else
1242     PrefsRemoveItem("ether");
1243 cebix 1.18
1244     #if SUPPORTS_UDP_TUNNEL
1245     PrefsReplaceInt32("udpport", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_udp_port)));
1246     #endif
1247 cebix 1.1 }
1248    
1249     // Add names of serial devices
1250     static gint gl_str_cmp(gconstpointer a, gconstpointer b)
1251     {
1252     return strcmp((char *)a, (char *)b);
1253     }
1254    
1255     static GList *add_serial_names(void)
1256     {
1257     GList *glist = NULL;
1258    
1259     // Search /dev for ttyS* and lp*
1260     DIR *d = opendir("/dev");
1261     if (d) {
1262     struct dirent *de;
1263     while ((de = readdir(d)) != NULL) {
1264     #if defined(__linux__)
1265     if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
1266     #elif defined(__FreeBSD__)
1267     if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1268 cebix 1.4 #elif defined(__NetBSD__)
1269     if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1270 cebix 1.1 #elif defined(sgi)
1271     if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) {
1272     #else
1273     if (false) {
1274     #endif
1275     char *str = new char[64];
1276     sprintf(str, "/dev/%s", de->d_name);
1277     glist = g_list_append(glist, str);
1278     }
1279     }
1280     closedir(d);
1281     }
1282     if (glist)
1283     g_list_sort(glist, gl_str_cmp);
1284     else
1285 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1286 cebix 1.1 return glist;
1287     }
1288    
1289     // Add names of ethernet interfaces
1290     static GList *add_ether_names(void)
1291     {
1292     GList *glist = NULL;
1293    
1294     // Get list of all Ethernet interfaces
1295     int s = socket(PF_INET, SOCK_DGRAM, 0);
1296     if (s >= 0) {
1297     char inbuf[8192];
1298     struct ifconf ifc;
1299     ifc.ifc_len = sizeof(inbuf);
1300     ifc.ifc_buf = inbuf;
1301     if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
1302     struct ifreq req, *ifr = ifc.ifc_req;
1303     for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
1304     req = *ifr;
1305 cebix 1.4 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(sgi)
1306 cebix 1.1 if (ioctl(s, SIOCGIFADDR, &req) == 0 && (req.ifr_addr.sa_family == ARPHRD_ETHER || req.ifr_addr.sa_family == ARPHRD_ETHER+1)) {
1307 cebix 1.4 #elif defined(__linux__)
1308     if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
1309 cebix 1.1 #else
1310 cebix 1.4 if (false) {
1311 cebix 1.1 #endif
1312     char *str = new char[64];
1313     strncpy(str, ifr->ifr_name, 63);
1314     glist = g_list_append(glist, str);
1315     }
1316     }
1317     }
1318     close(s);
1319     }
1320 gbeauche 1.27 #ifdef HAVE_SLIRP
1321     static char s_slirp[] = "slirp";
1322     glist = g_list_append(glist, s_slirp);
1323     #endif
1324 cebix 1.1 if (glist)
1325     g_list_sort(glist, gl_str_cmp);
1326     else
1327 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1328 cebix 1.1 return glist;
1329     }
1330    
1331     // Create "Serial/Network" pane
1332     static void create_serial_pane(GtkWidget *top)
1333     {
1334 cebix 1.18 GtkWidget *box, *hbox, *table, *label, *combo, *sep;
1335     GtkObject *adj;
1336 cebix 1.1
1337     box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
1338 cebix 1.13 table = make_table(box, 2, 4);
1339 cebix 1.1
1340     label = gtk_label_new(GetString(STR_SERIALA_CTRL));
1341     gtk_widget_show(label);
1342     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1343    
1344 cebix 1.18 GList *glist = add_serial_names();
1345 cebix 1.1 combo = gtk_combo_new();
1346     gtk_widget_show(combo);
1347     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1348     const char *str = PrefsFindString("seriala");
1349     if (str == NULL)
1350     str = "";
1351     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1352     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1353     w_seriala = GTK_COMBO(combo)->entry;
1354    
1355     label = gtk_label_new(GetString(STR_SERIALB_CTRL));
1356     gtk_widget_show(label);
1357     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1358    
1359     combo = gtk_combo_new();
1360     gtk_widget_show(combo);
1361     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1362     str = PrefsFindString("serialb");
1363     if (str == NULL)
1364     str = "";
1365     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1366     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1367     w_serialb = GTK_COMBO(combo)->entry;
1368    
1369 cebix 1.13 sep = gtk_hseparator_new();
1370     gtk_widget_show(sep);
1371     gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1372    
1373 cebix 1.1 label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1374     gtk_widget_show(label);
1375 cebix 1.13 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1376 cebix 1.1
1377     glist = add_ether_names();
1378     combo = gtk_combo_new();
1379     gtk_widget_show(combo);
1380     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1381     str = PrefsFindString("ether");
1382     if (str == NULL)
1383     str = "";
1384     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1385 cebix 1.13 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1386 cebix 1.1 w_ether = GTK_COMBO(combo)->entry;
1387 cebix 1.18
1388     #if SUPPORTS_UDP_TUNNEL
1389     make_checkbox(box, STR_UDPTUNNEL_CTRL, "udptunnel", GTK_SIGNAL_FUNC(tb_udptunnel));
1390    
1391     hbox = gtk_hbox_new(FALSE, 4);
1392     gtk_widget_show(hbox);
1393     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1394    
1395     label = gtk_label_new(GetString(STR_UDPPORT_CTRL));
1396     gtk_widget_show(label);
1397     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1398    
1399     adj = gtk_adjustment_new(PrefsFindInt32("udpport"), 1, 65535, 1, 5, 0);
1400     w_udp_port = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1401     gtk_widget_show(w_udp_port);
1402     gtk_box_pack_start(GTK_BOX(hbox), w_udp_port, FALSE, FALSE, 0);
1403     #endif
1404    
1405     set_serial_sensitive();
1406 cebix 1.1 }
1407    
1408    
1409     /*
1410     * "Memory/Misc" pane
1411     */
1412    
1413 gbeauche 1.29 static GtkWidget *w_ramsize;
1414 cebix 1.1 static GtkWidget *w_rom_file;
1415    
1416 gbeauche 1.22 // "Ignore SEGV" button toggled
1417     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1418     static void tb_ignoresegv(GtkWidget *widget)
1419     {
1420     PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1421     }
1422     #endif
1423    
1424 cebix 1.1 // Model ID selected
1425     static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1426     static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1427    
1428 cebix 1.9 // CPU/FPU type
1429     static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1430     static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1431     static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1432     static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1433     static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1434 cebix 1.8
1435 cebix 1.1 // Read settings from widgets and set preferences
1436     static void read_memory_settings(void)
1437     {
1438 gbeauche 1.29 const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry));
1439     PrefsReplaceInt32("ramsize", atoi(str) << 20);
1440 cebix 1.1
1441 gbeauche 1.29 str = get_file_entry_path(w_rom_file);
1442 cebix 1.1 if (str && strlen(str))
1443     PrefsReplaceString("rom", str);
1444     else
1445     PrefsRemoveItem("rom");
1446    
1447     }
1448    
1449     // Create "Memory/Misc" pane
1450     static void create_memory_pane(GtkWidget *top)
1451     {
1452 gbeauche 1.29 GtkWidget *box, *hbox, *table, *label, *menu;
1453 cebix 1.1
1454     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1455 gbeauche 1.29 table = make_table(box, 2, 5);
1456 cebix 1.1
1457 gbeauche 1.29 static const combo_desc options[] = {
1458     STR_RAMSIZE_2MB_LAB,
1459     STR_RAMSIZE_4MB_LAB,
1460     STR_RAMSIZE_8MB_LAB,
1461     STR_RAMSIZE_16MB_LAB,
1462     STR_RAMSIZE_32MB_LAB,
1463     STR_RAMSIZE_64MB_LAB,
1464     STR_RAMSIZE_128MB_LAB,
1465     STR_RAMSIZE_256MB_LAB,
1466     STR_RAMSIZE_512MB_LAB,
1467     STR_RAMSIZE_1024MB_LAB,
1468     0
1469     };
1470     char default_ramsize[10];
1471     sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20);
1472     w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options);
1473 cebix 1.1
1474 cebix 1.9 static const opt_desc model_options[] = {
1475 cebix 1.1 {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1476     {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1477     {0, NULL}
1478     };
1479     int modelid = PrefsFindInt32("modelid"), active = 0;
1480     switch (modelid) {
1481     case 5: active = 0; break;
1482     case 14: active = 1; break;
1483     }
1484 gbeauche 1.29 table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active);
1485 cebix 1.9
1486 cebix 1.11 #if EMULATED_68K
1487 cebix 1.9 static const opt_desc cpu_options[] = {
1488     {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1489     {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1490     {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1491     {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1492     {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1493     {0, NULL}
1494     };
1495     int cpu = PrefsFindInt32("cpu");
1496     bool fpu = PrefsFindBool("fpu");
1497     active = 0;
1498     switch (cpu) {
1499     case 2: active = fpu ? 1 : 0; break;
1500     case 3: active = fpu ? 3 : 2; break;
1501     case 4: active = 4;
1502     }
1503 gbeauche 1.29 table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active);
1504 cebix 1.11 #endif
1505 cebix 1.1
1506 gbeauche 1.29 w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom");
1507 gbeauche 1.22
1508     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1509     make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1510     #endif
1511 cebix 1.1 }
1512    
1513    
1514     /*
1515     * Read settings from widgets and set preferences
1516     */
1517    
1518     static void read_settings(void)
1519     {
1520     read_volumes_settings();
1521     read_scsi_settings();
1522     read_graphics_settings();
1523 cebix 1.13 read_input_settings();
1524 cebix 1.1 read_serial_settings();
1525     read_memory_settings();
1526 gbeauche 1.23 read_jit_settings();
1527 cebix 1.1 }
1528 gbeauche 1.32
1529    
1530     #ifdef STANDALONE_GUI
1531     #include <errno.h>
1532 gbeauche 1.33 #include <sys/wait.h>
1533     #include "rpc.h"
1534 gbeauche 1.32
1535     /*
1536     * Fake unused data and functions
1537     */
1538    
1539     uint8 XPRAM[XPRAM_SIZE];
1540     void MountVolume(void *fh) { }
1541     void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { }
1542    
1543    
1544     /*
1545     * Display alert
1546     */
1547    
1548     static void dl_destroyed(void)
1549     {
1550     gtk_main_quit();
1551     }
1552    
1553     static void display_alert(int title_id, int prefix_id, int button_id, const char *text)
1554     {
1555     char str[256];
1556     sprintf(str, GetString(prefix_id), text);
1557    
1558     GtkWidget *dialog = gtk_dialog_new();
1559     gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id));
1560     gtk_container_border_width(GTK_CONTAINER(dialog), 5);
1561     gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
1562     gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL);
1563    
1564     GtkWidget *label = gtk_label_new(str);
1565     gtk_widget_show(label);
1566     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
1567    
1568     GtkWidget *button = gtk_button_new_with_label(GetString(button_id));
1569     gtk_widget_show(button);
1570     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
1571     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
1572     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1573     gtk_widget_grab_default(button);
1574     gtk_widget_show(dialog);
1575    
1576     gtk_main();
1577     }
1578    
1579    
1580     /*
1581     * Display error alert
1582     */
1583    
1584 gbeauche 1.33 void ErrorAlert(const char *text)
1585 gbeauche 1.32 {
1586     display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text);
1587     }
1588    
1589    
1590     /*
1591 gbeauche 1.33 * Display warning alert
1592     */
1593    
1594     void WarningAlert(const char *text)
1595     {
1596     display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text);
1597     }
1598    
1599    
1600     /*
1601     * RPC handlers
1602     */
1603    
1604     static int handle_ErrorAlert(rpc_connection_t *connection)
1605     {
1606     D(bug("handle_ErrorAlert\n"));
1607    
1608     int error;
1609     char *str;
1610     if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
1611     return error;
1612    
1613     ErrorAlert(str);
1614     free(str);
1615     return RPC_ERROR_NO_ERROR;
1616     }
1617    
1618     static int handle_WarningAlert(rpc_connection_t *connection)
1619     {
1620     D(bug("handle_WarningAlert\n"));
1621    
1622     int error;
1623     char *str;
1624     if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
1625     return error;
1626    
1627     WarningAlert(str);
1628     free(str);
1629     return RPC_ERROR_NO_ERROR;
1630     }
1631    
1632     static int handle_Exit(rpc_connection_t *connection)
1633     {
1634     D(bug("handle_Exit\n"));
1635    
1636     return RPC_ERROR_NO_ERROR;
1637     }
1638    
1639    
1640     /*
1641 gbeauche 1.32 * Start standalone GUI
1642     */
1643    
1644     int main(int argc, char *argv[])
1645     {
1646     #ifdef HAVE_GNOMEUI
1647     // Init GNOME/GTK
1648     char version[16];
1649     sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR);
1650     gnome_init("Basilisk II", version, argc, argv);
1651     #else
1652     // Init GTK
1653     gtk_set_locale();
1654     gtk_init(&argc, &argv);
1655     #endif
1656    
1657     // Read preferences
1658     PrefsInit(argc, argv);
1659    
1660     // Show preferences editor
1661     bool start = PrefsEditor();
1662    
1663     // Exit preferences
1664     PrefsExit();
1665    
1666     // Transfer control to the executable
1667     if (start) {
1668 gbeauche 1.33 char gui_connection_path[64];
1669     sprintf(gui_connection_path, "/org/BasiliskII/GUI/%d", getpid());
1670    
1671     int pid = fork();
1672     if (pid == 0) { // Child
1673     char b2_path[PATH_MAX];
1674     strcpy(b2_path, argv[0]);
1675     char *p = strrchr(b2_path, '/');
1676     p = p ? p + 1 : b2_path;
1677     *p = '\0';
1678     strcat(b2_path, "BasiliskII");
1679     execl(b2_path, b2_path, "--gui-connection", gui_connection_path, (char *)NULL);
1680    
1681     char str[256];
1682     sprintf(str, GetString(STR_NO_B2_EXE_FOUND), b2_path, strerror(errno));
1683     ErrorAlert(str);
1684     return 1;
1685     }
1686     else { // Parent
1687     rpc_connection_t *connection;
1688     if ((connection = rpc_init_server(gui_connection_path)) == NULL) {
1689 gbeauche 1.34 printf("ERROR: failed to initialize GUI-side RPC server connection\n");
1690     return 1;
1691 gbeauche 1.33 }
1692    
1693     static const rpc_method_descriptor_t vtable[] = {
1694     { RPC_METHOD_ERROR_ALERT, handle_ErrorAlert },
1695     { RPC_METHOD_WARNING_ALERT, handle_WarningAlert },
1696     { RPC_METHOD_EXIT, handle_Exit }
1697     };
1698     if (rpc_method_add_callbacks(connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
1699     printf("ERROR: failed to setup GUI method callbacks\n");
1700     return 1;
1701     }
1702    
1703     if (rpc_listen(connection) < 0) {
1704     printf("ERROR: failed to initialize RPC server thread\n");
1705     return 1;
1706     }
1707    
1708     int status, ret = -1;
1709     while (waitpid(pid, &status, 0) != pid)
1710     ;
1711     if (WIFEXITED(status))
1712     ret = WEXITSTATUS(status);
1713    
1714     rpc_exit(connection);
1715     return ret;
1716     }
1717 gbeauche 1.32 }
1718    
1719     return 0;
1720     }
1721     #endif