ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
Revision: 1.33
Committed: 2006-04-16T21:25:41Z (18 years, 4 months ago) by gbeauche
Branch: MAIN
Changes since 1.32: +105 -15 lines
Log Message:
Make Basilisk II main application not use GTK libraries when compiling with
STANDALONE_GUI. This is the second step towards a more interesting GUI alike
to VMware. Communication from/to the GUI is held by some lightweight RPC.

Note: The step should be enough to provide a tiny GTK GUI for 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     gtk_widget_show(frame);
128     gtk_container_border_width(GTK_CONTAINER(frame), 4);
129    
130     label = gtk_label_new(GetString(title_id));
131     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
132    
133     box = gtk_vbox_new(FALSE, 4);
134     gtk_widget_show(box);
135     gtk_container_set_border_width(GTK_CONTAINER(box), 4);
136     gtk_container_add(GTK_CONTAINER(frame), box);
137     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_widget_show(notebook);
523     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
524 cebix 1.8 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
525 cebix 1.1 gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
526    
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 cebix 1.1
535     static const opt_desc buttons[] = {
536     {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
537     {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
538     {0, NULL}
539     };
540     make_button_box(box, 4, buttons);
541    
542     // Show window and enter main loop
543     gtk_widget_show(win);
544     gtk_main();
545     return start_clicked;
546     }
547    
548    
549     /*
550     * "Volumes" pane
551     */
552    
553 cebix 1.6 static GtkWidget *volume_list, *w_extfs;
554 cebix 1.1 static int selected_volume;
555    
556     // Volume in list selected
557     static void cl_selected(GtkWidget *list, int row, int column)
558     {
559     selected_volume = row;
560     }
561    
562     // Volume selected for addition
563     static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
564     {
565 gbeauche 1.28 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
566 cebix 1.1 gtk_clist_append(GTK_CLIST(volume_list), &file);
567     gtk_widget_destroy(assoc->req);
568     delete assoc;
569     }
570    
571     // Volume selected for creation
572     static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
573     {
574 gbeauche 1.28 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
575 cebix 1.1
576 gbeauche 1.28 const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
577 cebix 1.1 int size = atoi(str);
578    
579     char cmd[1024];
580     sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size);
581     int ret = system(cmd);
582     if (ret == 0)
583     gtk_clist_append(GTK_CLIST(volume_list), &file);
584     gtk_widget_destroy(GTK_WIDGET(assoc->req));
585     delete assoc;
586     }
587    
588     // "Add Volume" button clicked
589     static void cb_add_volume(...)
590     {
591     GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE));
592     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
593     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL));
594     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
595     gtk_widget_show(req);
596     }
597    
598     // "Create Hardfile" button clicked
599     static void cb_create_volume(...)
600     {
601     GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE));
602    
603     GtkWidget *box = gtk_hbox_new(FALSE, 4);
604     gtk_widget_show(box);
605     GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL));
606     gtk_widget_show(label);
607     GtkWidget *entry = gtk_entry_new();
608     gtk_widget_show(entry);
609     char str[32];
610     sprintf(str, "%d", 40);
611     gtk_entry_set_text(GTK_ENTRY(entry), str);
612     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
613     gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
614     gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0);
615    
616     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
617     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry));
618     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
619     gtk_widget_show(req);
620     }
621    
622     // "Remove Volume" button clicked
623     static void cb_remove_volume(...)
624     {
625     gtk_clist_remove(GTK_CLIST(volume_list), selected_volume);
626     }
627    
628     // "Boot From" selected
629 cebix 1.14 static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
630     static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
631 cebix 1.1
632     // "No CD-ROM Driver" button toggled
633     static void tb_nocdrom(GtkWidget *widget)
634     {
635     PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
636     }
637    
638     // Read settings from widgets and set preferences
639     static void read_volumes_settings(void)
640     {
641     while (PrefsFindString("disk"))
642     PrefsRemoveItem("disk");
643    
644     for (int i=0; i<GTK_CLIST(volume_list)->rows; i++) {
645     char *str;
646     gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
647     PrefsAddString("disk", str);
648     }
649 cebix 1.6
650 cebix 1.21 PrefsReplaceString("extfs", get_file_entry_path(w_extfs));
651 cebix 1.1 }
652    
653     // Create "Volumes" pane
654     static void create_volumes_pane(GtkWidget *top)
655     {
656     GtkWidget *box, *scroll, *menu;
657    
658     box = make_pane(top, STR_VOLUMES_PANE_TITLE);
659    
660     scroll = gtk_scrolled_window_new(NULL, NULL);
661     gtk_widget_show(scroll);
662     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
663     volume_list = gtk_clist_new(1);
664     gtk_widget_show(volume_list);
665     gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE);
666     gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE);
667 cebix 1.5 gtk_clist_set_reorderable(GTK_CLIST(volume_list), true);
668 cebix 1.1 gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL);
669     char *str;
670     int32 index = 0;
671 cebix 1.21 while ((str = const_cast<char *>(PrefsFindString("disk", index++))) != NULL)
672 cebix 1.1 gtk_clist_append(GTK_CLIST(volume_list), &str);
673     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list);
674     gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
675     selected_volume = 0;
676    
677     static const opt_desc buttons[] = {
678     {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)},
679     {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)},
680     {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)},
681     {0, NULL},
682     };
683     make_button_box(box, 0, buttons);
684     make_separator(box);
685 cebix 1.6
686 cebix 1.21 w_extfs = make_file_entry(box, STR_EXTFS_CTRL, "extfs", true);
687 cebix 1.1
688     static const opt_desc options[] = {
689     {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)},
690     {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)},
691     {0, NULL}
692     };
693 cebix 1.14 int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
694 cebix 1.1 switch (bootdriver) {
695     case 0: active = 0; break;
696     case CDROMRefNum: active = 1; break;
697     }
698     menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
699    
700     make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
701     }
702    
703    
704     /*
705 gbeauche 1.23 * "JIT Compiler" pane
706     */
707    
708     static GtkWidget *w_jit_fpu;
709     static GtkWidget *w_jit_atraps;
710     static GtkWidget *w_jit_cache_size;
711     static GtkWidget *w_jit_lazy_flush;
712 gbeauche 1.27 static GtkWidget *w_jit_follow_const_jumps;
713 gbeauche 1.23
714     // Set sensitivity of widgets
715     static void set_jit_sensitive(void)
716     {
717     const bool jit_enabled = PrefsFindBool("jit");
718     gtk_widget_set_sensitive(w_jit_fpu, jit_enabled);
719     gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled);
720     gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled);
721 gbeauche 1.27 gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled);
722 gbeauche 1.23 }
723    
724     // "Use JIT Compiler" button toggled
725     static void tb_jit(GtkWidget *widget)
726     {
727     PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active);
728     set_jit_sensitive();
729     }
730    
731     // "Compile FPU Instructions" button toggled
732     static void tb_jit_fpu(GtkWidget *widget)
733     {
734     PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active);
735     }
736    
737     // "Lazy translation cache invalidation" button toggled
738     static void tb_jit_lazy_flush(GtkWidget *widget)
739     {
740     PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active);
741     }
742    
743 gbeauche 1.27 // "Translate through constant jumps (inline blocks)" button toggled
744     static void tb_jit_follow_const_jumps(GtkWidget *widget)
745     {
746     PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active);
747     }
748    
749 gbeauche 1.23 // Read settings from widgets and set preferences
750     static void read_jit_settings(void)
751     {
752     #if USE_JIT
753     bool jit_enabled = PrefsFindBool("jit");
754     if (jit_enabled) {
755     const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
756     PrefsReplaceInt32("jitcachesize", atoi(str));
757     }
758     #endif
759     }
760    
761     // Create "JIT Compiler" pane
762     static void create_jit_pane(GtkWidget *top)
763     {
764     #if USE_JIT
765     GtkWidget *box, *table, *label, *menu;
766     char str[32];
767    
768     box = make_pane(top, STR_JIT_PANE_TITLE);
769     make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
770    
771     w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu));
772    
773     // Translation cache size
774     static const combo_desc options[] = {
775     STR_JIT_CACHE_SIZE_2MB_LAB,
776     STR_JIT_CACHE_SIZE_4MB_LAB,
777     STR_JIT_CACHE_SIZE_8MB_LAB,
778     STR_JIT_CACHE_SIZE_16MB_LAB,
779     0
780     };
781     w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, "jitcachesize", options);
782    
783     // Lazy translation cache invalidation
784     w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush));
785 gbeauche 1.27
786     // Follow constant jumps (inline basic blocks)
787     w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
788    
789 gbeauche 1.23 set_jit_sensitive();
790     #endif
791     }
792    
793     /*
794 cebix 1.1 * "SCSI" pane
795     */
796    
797     static GtkWidget *w_scsi[7];
798    
799     // Read settings from widgets and set preferences
800     static void read_scsi_settings(void)
801     {
802     for (int id=0; id<7; id++) {
803     char prefs_name[32];
804     sprintf(prefs_name, "scsi%d", id);
805 cebix 1.21 const char *str = get_file_entry_path(w_scsi[id]);
806 cebix 1.1 if (str && strlen(str))
807     PrefsReplaceString(prefs_name, str);
808     else
809     PrefsRemoveItem(prefs_name);
810     }
811     }
812    
813     // Create "SCSI" pane
814     static void create_scsi_pane(GtkWidget *top)
815     {
816     GtkWidget *box;
817    
818     box = make_pane(top, STR_SCSI_PANE_TITLE);
819    
820     for (int id=0; id<7; id++) {
821     char prefs_name[32];
822     sprintf(prefs_name, "scsi%d", id);
823 cebix 1.21 w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name);
824 cebix 1.1 }
825     }
826    
827    
828     /*
829     * "Graphics/Sound" pane
830     */
831    
832     // Display types
833     enum {
834     DISPLAY_WINDOW,
835     DISPLAY_SCREEN
836     };
837    
838     static GtkWidget *w_frameskip, *w_display_x, *w_display_y;
839     static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
840     static int display_type;
841     static int dis_width, dis_height;
842    
843 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
844 cebix 1.7 static GtkWidget *w_fbdev_name, *w_fbdevice_file;
845     static GtkWidget *l_fbdev_name, *l_fbdevice_file;
846     static char fbdev_name[256];
847     #endif
848    
849 cebix 1.24 static GtkWidget *w_dspdevice_file, *w_mixerdevice_file;
850    
851 cebix 1.1 // Hide/show graphics widgets
852     static void hide_show_graphics_widgets(void)
853     {
854     switch (display_type) {
855     case DISPLAY_WINDOW:
856     gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
857 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
858 cebix 1.7 gtk_widget_show(w_display_x); gtk_widget_show(l_display_x);
859     gtk_widget_show(w_display_y); gtk_widget_show(l_display_y);
860     gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name);
861     #endif
862 cebix 1.1 break;
863     case DISPLAY_SCREEN:
864     gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
865 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
866 cebix 1.7 gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x);
867     gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y);
868     gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name);
869     #endif
870 cebix 1.1 break;
871     }
872     }
873    
874     // "Window" video type selected
875     static void mn_window(...)
876     {
877     display_type = DISPLAY_WINDOW;
878     hide_show_graphics_widgets();
879     }
880    
881     // "Fullscreen" video type selected
882     static void mn_fullscreen(...)
883     {
884     display_type = DISPLAY_SCREEN;
885     hide_show_graphics_widgets();
886     }
887    
888     // "5 Hz".."60Hz" selected
889     static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
890     static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
891     static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
892     static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
893     static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
894     static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
895 cebix 1.12 static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
896 cebix 1.1
897 cebix 1.24 // Set sensitivity of widgets
898     static void set_graphics_sensitive(void)
899     {
900     const bool sound_enabled = !PrefsFindBool("nosound");
901     gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled);
902     gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled);
903     }
904    
905 cebix 1.1 // "Disable Sound Output" button toggled
906     static void tb_nosound(GtkWidget *widget)
907     {
908     PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
909 cebix 1.24 set_graphics_sensitive();
910 cebix 1.1 }
911    
912     // Read graphics preferences
913     static void parse_graphics_prefs(void)
914     {
915     display_type = DISPLAY_WINDOW;
916     dis_width = 512;
917     dis_height = 384;
918 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
919 cebix 1.7 fbdev_name[0] = 0;
920     #endif
921 cebix 1.1
922     const char *str = PrefsFindString("screen");
923     if (str) {
924     if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
925     display_type = DISPLAY_WINDOW;
926 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
927 cebix 1.7 else if (sscanf(str, "dga/%255s", fbdev_name) == 1)
928     #else
929 cebix 1.2 else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
930 cebix 1.7 #endif
931 cebix 1.1 display_type = DISPLAY_SCREEN;
932     }
933     }
934    
935     // Read settings from widgets and set preferences
936     static void read_graphics_settings(void)
937     {
938     const char *str;
939    
940     str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
941     dis_width = atoi(str);
942    
943     str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
944     dis_height = atoi(str);
945    
946     char pref[256];
947     switch (display_type) {
948     case DISPLAY_WINDOW:
949     sprintf(pref, "win/%d/%d", dis_width, dis_height);
950     break;
951     case DISPLAY_SCREEN:
952 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
953 cebix 1.7 str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name));
954     sprintf(pref, "dga/%s", str);
955     #else
956 cebix 1.2 sprintf(pref, "dga/%d/%d", dis_width, dis_height);
957 cebix 1.7 #endif
958 cebix 1.1 break;
959     default:
960     PrefsRemoveItem("screen");
961     return;
962     }
963     PrefsReplaceString("screen", pref);
964 cebix 1.21
965     #ifdef ENABLE_FBDEV_DGA
966     str = get_file_entry_path(w_fbdevice_file);
967     if (str && strlen(str))
968     PrefsReplaceString("fbdevicefile", str);
969     else
970     PrefsRemoveItem("fbdevicefile");
971     #endif
972 cebix 1.24 PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file));
973     PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file));
974 cebix 1.1 }
975    
976     // Create "Graphics/Sound" pane
977     static void create_graphics_pane(GtkWidget *top)
978     {
979 cebix 1.2 GtkWidget *box, *table, *label, *opt, *menu, *combo;
980 cebix 1.1 char str[32];
981    
982     parse_graphics_prefs();
983    
984     box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
985 cebix 1.7 table = make_table(box, 2, 5);
986 cebix 1.1
987     label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
988     gtk_widget_show(label);
989     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
990    
991     opt = gtk_option_menu_new();
992     gtk_widget_show(opt);
993     menu = gtk_menu_new();
994     add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window));
995     add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen));
996     switch (display_type) {
997     case DISPLAY_WINDOW:
998     gtk_menu_set_active(GTK_MENU(menu), 0);
999     break;
1000     case DISPLAY_SCREEN:
1001     gtk_menu_set_active(GTK_MENU(menu), 1);
1002     break;
1003     }
1004     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
1005     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1006    
1007     l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
1008     gtk_widget_show(l_frameskip);
1009     gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1010    
1011     w_frameskip = gtk_option_menu_new();
1012     gtk_widget_show(w_frameskip);
1013     menu = gtk_menu_new();
1014     add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
1015     add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
1016     add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
1017     add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
1018     add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
1019     add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
1020 cebix 1.12 add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic));
1021 cebix 1.1 int frameskip = PrefsFindInt32("frameskip");
1022 cebix 1.12 int item = -1;
1023 cebix 1.1 switch (frameskip) {
1024 cebix 1.12 case 12: item = 0; break;
1025     case 8: item = 1; break;
1026     case 6: item = 2; break;
1027     case 4: item = 3; break;
1028     case 2: item = 4; break;
1029     case 1: item = 5; break;
1030     case 0: item = 6; break;
1031 cebix 1.1 }
1032 cebix 1.12 if (item >= 0)
1033     gtk_menu_set_active(GTK_MENU(menu), item);
1034 cebix 1.1 gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
1035     gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1036    
1037     l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
1038     gtk_widget_show(l_display_x);
1039     gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1040    
1041 cebix 1.2 combo = gtk_combo_new();
1042     gtk_widget_show(combo);
1043     GList *glist1 = NULL;
1044 cebix 1.4 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
1045     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
1046     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
1047     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
1048     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
1049 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
1050     if (dis_width)
1051     sprintf(str, "%d", dis_width);
1052     else
1053 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
1054 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1055     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1056     w_display_x = GTK_COMBO(combo)->entry;
1057 cebix 1.1
1058     l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
1059     gtk_widget_show(l_display_y);
1060     gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1061    
1062 cebix 1.2 combo = gtk_combo_new();
1063     gtk_widget_show(combo);
1064     GList *glist2 = NULL;
1065 cebix 1.4 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
1066     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
1067     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
1068     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
1069     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
1070 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
1071     if (dis_height)
1072     sprintf(str, "%d", dis_height);
1073     else
1074 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
1075 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1076     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1077     w_display_y = GTK_COMBO(combo)->entry;
1078 cebix 1.7
1079 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
1080 cebix 1.7 l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL));
1081     gtk_widget_show(l_fbdev_name);
1082     gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1083    
1084     w_fbdev_name = gtk_entry_new();
1085     gtk_widget_show(w_fbdev_name);
1086     gtk_entry_set_text(GTK_ENTRY(w_fbdev_name), fbdev_name);
1087     gtk_table_attach(GTK_TABLE(table), w_fbdev_name, 1, 2, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1088    
1089 cebix 1.21 w_fbdevice_file = make_file_entry(box, STR_FBDEVICE_FILE_CTRL, "fbdevicefile");
1090 cebix 1.7 #endif
1091 cebix 1.1
1092 cebix 1.13 make_separator(box);
1093 cebix 1.1 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
1094 cebix 1.24 w_dspdevice_file = make_file_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp");
1095     w_mixerdevice_file = make_file_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer");
1096    
1097     set_graphics_sensitive();
1098 cebix 1.1
1099     hide_show_graphics_widgets();
1100     }
1101    
1102    
1103     /*
1104 cebix 1.13 * "Input" pane
1105     */
1106    
1107     static GtkWidget *w_keycode_file;
1108     static GtkWidget *w_mouse_wheel_lines;
1109    
1110     // Set sensitivity of widgets
1111     static void set_input_sensitive(void)
1112     {
1113 gbeauche 1.29 const bool use_keycodes = PrefsFindBool("keycodes");
1114     gtk_widget_set_sensitive(w_keycode_file, use_keycodes);
1115     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes);
1116 cebix 1.14 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
1117 cebix 1.13 }
1118    
1119     // "Use Raw Keycodes" button toggled
1120     static void tb_keycodes(GtkWidget *widget)
1121     {
1122     PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
1123     set_input_sensitive();
1124     }
1125    
1126     // "Mouse Wheel Mode" selected
1127 cebix 1.14 static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
1128     static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
1129 cebix 1.13
1130     // Read settings from widgets and set preferences
1131     static void read_input_settings(void)
1132     {
1133 cebix 1.21 const char *str = get_file_entry_path(w_keycode_file);
1134 cebix 1.13 if (str && strlen(str))
1135     PrefsReplaceString("keycodefile", str);
1136     else
1137     PrefsRemoveItem("keycodefile");
1138    
1139 cebix 1.14 PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
1140 cebix 1.13 }
1141    
1142     // Create "Input" pane
1143     static void create_input_pane(GtkWidget *top)
1144     {
1145 gbeauche 1.29 GtkWidget *box, *hbox, *menu, *label, *button;
1146 cebix 1.13 GtkObject *adj;
1147    
1148     box = make_pane(top, STR_INPUT_PANE_TITLE);
1149    
1150     make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1151 gbeauche 1.29
1152     hbox = gtk_hbox_new(FALSE, 4);
1153     gtk_widget_show(hbox);
1154     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1155    
1156     label = gtk_label_new(GetString(STR_KEYCODES_CTRL));
1157     gtk_widget_show(label);
1158     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1159    
1160     const char *str = PrefsFindString("keycodefile");
1161     if (str == NULL)
1162     str = "";
1163    
1164     w_keycode_file = gtk_entry_new();
1165     gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str);
1166     gtk_widget_show(w_keycode_file);
1167     gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0);
1168    
1169     button = make_browse_button(w_keycode_file);
1170     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1171     g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button);
1172 cebix 1.13
1173     make_separator(box);
1174    
1175     static const opt_desc options[] = {
1176     {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
1177     {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
1178     {0, NULL}
1179     };
1180 cebix 1.14 int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
1181 cebix 1.13 switch (wheelmode) {
1182     case 0: active = 0; break;
1183     case 1: active = 1; break;
1184     }
1185     menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
1186    
1187     hbox = gtk_hbox_new(FALSE, 4);
1188     gtk_widget_show(hbox);
1189     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1190    
1191     label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
1192     gtk_widget_show(label);
1193     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1194    
1195 cebix 1.14 adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
1196 cebix 1.13 w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1197     gtk_widget_show(w_mouse_wheel_lines);
1198     gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
1199    
1200     set_input_sensitive();
1201     }
1202    
1203    
1204     /*
1205 cebix 1.1 * "Serial/Network" pane
1206     */
1207    
1208 cebix 1.18 static GtkWidget *w_seriala, *w_serialb, *w_ether, *w_udp_port;
1209    
1210     // Set sensitivity of widgets
1211     static void set_serial_sensitive(void)
1212     {
1213     #if SUPPORTS_UDP_TUNNEL
1214     gtk_widget_set_sensitive(w_ether, !PrefsFindBool("udptunnel"));
1215     gtk_widget_set_sensitive(w_udp_port, PrefsFindBool("udptunnel"));
1216     #endif
1217     }
1218    
1219     // "Tunnel AppleTalk over IP" button toggled
1220     static void tb_udptunnel(GtkWidget *widget)
1221     {
1222     PrefsReplaceBool("udptunnel", GTK_TOGGLE_BUTTON(widget)->active);
1223     set_serial_sensitive();
1224     }
1225 cebix 1.1
1226     // Read settings from widgets and set preferences
1227     static void read_serial_settings(void)
1228     {
1229     const char *str;
1230    
1231     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1232     PrefsReplaceString("seriala", str);
1233    
1234     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1235     PrefsReplaceString("serialb", str);
1236    
1237     str = gtk_entry_get_text(GTK_ENTRY(w_ether));
1238     if (str && strlen(str))
1239     PrefsReplaceString("ether", str);
1240     else
1241     PrefsRemoveItem("ether");
1242 cebix 1.18
1243     #if SUPPORTS_UDP_TUNNEL
1244     PrefsReplaceInt32("udpport", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_udp_port)));
1245     #endif
1246 cebix 1.1 }
1247    
1248     // Add names of serial devices
1249     static gint gl_str_cmp(gconstpointer a, gconstpointer b)
1250     {
1251     return strcmp((char *)a, (char *)b);
1252     }
1253    
1254     static GList *add_serial_names(void)
1255     {
1256     GList *glist = NULL;
1257    
1258     // Search /dev for ttyS* and lp*
1259     DIR *d = opendir("/dev");
1260     if (d) {
1261     struct dirent *de;
1262     while ((de = readdir(d)) != NULL) {
1263     #if defined(__linux__)
1264     if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
1265     #elif defined(__FreeBSD__)
1266     if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1267 cebix 1.4 #elif defined(__NetBSD__)
1268     if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1269 cebix 1.1 #elif defined(sgi)
1270     if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) {
1271     #else
1272     if (false) {
1273     #endif
1274     char *str = new char[64];
1275     sprintf(str, "/dev/%s", de->d_name);
1276     glist = g_list_append(glist, str);
1277     }
1278     }
1279     closedir(d);
1280     }
1281     if (glist)
1282     g_list_sort(glist, gl_str_cmp);
1283     else
1284 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1285 cebix 1.1 return glist;
1286     }
1287    
1288     // Add names of ethernet interfaces
1289     static GList *add_ether_names(void)
1290     {
1291     GList *glist = NULL;
1292    
1293     // Get list of all Ethernet interfaces
1294     int s = socket(PF_INET, SOCK_DGRAM, 0);
1295     if (s >= 0) {
1296     char inbuf[8192];
1297     struct ifconf ifc;
1298     ifc.ifc_len = sizeof(inbuf);
1299     ifc.ifc_buf = inbuf;
1300     if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
1301     struct ifreq req, *ifr = ifc.ifc_req;
1302     for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
1303     req = *ifr;
1304 cebix 1.4 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(sgi)
1305 cebix 1.1 if (ioctl(s, SIOCGIFADDR, &req) == 0 && (req.ifr_addr.sa_family == ARPHRD_ETHER || req.ifr_addr.sa_family == ARPHRD_ETHER+1)) {
1306 cebix 1.4 #elif defined(__linux__)
1307     if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
1308 cebix 1.1 #else
1309 cebix 1.4 if (false) {
1310 cebix 1.1 #endif
1311     char *str = new char[64];
1312     strncpy(str, ifr->ifr_name, 63);
1313     glist = g_list_append(glist, str);
1314     }
1315     }
1316     }
1317     close(s);
1318     }
1319 gbeauche 1.27 #ifdef HAVE_SLIRP
1320     static char s_slirp[] = "slirp";
1321     glist = g_list_append(glist, s_slirp);
1322     #endif
1323 cebix 1.1 if (glist)
1324     g_list_sort(glist, gl_str_cmp);
1325     else
1326 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1327 cebix 1.1 return glist;
1328     }
1329    
1330     // Create "Serial/Network" pane
1331     static void create_serial_pane(GtkWidget *top)
1332     {
1333 cebix 1.18 GtkWidget *box, *hbox, *table, *label, *combo, *sep;
1334     GtkObject *adj;
1335 cebix 1.1
1336     box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
1337 cebix 1.13 table = make_table(box, 2, 4);
1338 cebix 1.1
1339     label = gtk_label_new(GetString(STR_SERIALA_CTRL));
1340     gtk_widget_show(label);
1341     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1342    
1343 cebix 1.18 GList *glist = add_serial_names();
1344 cebix 1.1 combo = gtk_combo_new();
1345     gtk_widget_show(combo);
1346     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1347     const char *str = PrefsFindString("seriala");
1348     if (str == NULL)
1349     str = "";
1350     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1351     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1352     w_seriala = GTK_COMBO(combo)->entry;
1353    
1354     label = gtk_label_new(GetString(STR_SERIALB_CTRL));
1355     gtk_widget_show(label);
1356     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1357    
1358     combo = gtk_combo_new();
1359     gtk_widget_show(combo);
1360     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1361     str = PrefsFindString("serialb");
1362     if (str == NULL)
1363     str = "";
1364     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1365     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1366     w_serialb = GTK_COMBO(combo)->entry;
1367    
1368 cebix 1.13 sep = gtk_hseparator_new();
1369     gtk_widget_show(sep);
1370     gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1371    
1372 cebix 1.1 label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1373     gtk_widget_show(label);
1374 cebix 1.13 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1375 cebix 1.1
1376     glist = add_ether_names();
1377     combo = gtk_combo_new();
1378     gtk_widget_show(combo);
1379     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1380     str = PrefsFindString("ether");
1381     if (str == NULL)
1382     str = "";
1383     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1384 cebix 1.13 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1385 cebix 1.1 w_ether = GTK_COMBO(combo)->entry;
1386 cebix 1.18
1387     #if SUPPORTS_UDP_TUNNEL
1388     make_checkbox(box, STR_UDPTUNNEL_CTRL, "udptunnel", GTK_SIGNAL_FUNC(tb_udptunnel));
1389    
1390     hbox = gtk_hbox_new(FALSE, 4);
1391     gtk_widget_show(hbox);
1392     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1393    
1394     label = gtk_label_new(GetString(STR_UDPPORT_CTRL));
1395     gtk_widget_show(label);
1396     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1397    
1398     adj = gtk_adjustment_new(PrefsFindInt32("udpport"), 1, 65535, 1, 5, 0);
1399     w_udp_port = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1400     gtk_widget_show(w_udp_port);
1401     gtk_box_pack_start(GTK_BOX(hbox), w_udp_port, FALSE, FALSE, 0);
1402     #endif
1403    
1404     set_serial_sensitive();
1405 cebix 1.1 }
1406    
1407    
1408     /*
1409     * "Memory/Misc" pane
1410     */
1411    
1412 gbeauche 1.29 static GtkWidget *w_ramsize;
1413 cebix 1.1 static GtkWidget *w_rom_file;
1414    
1415 gbeauche 1.22 // "Ignore SEGV" button toggled
1416     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1417     static void tb_ignoresegv(GtkWidget *widget)
1418     {
1419     PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1420     }
1421     #endif
1422    
1423 cebix 1.1 // Model ID selected
1424     static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1425     static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1426    
1427 cebix 1.9 // CPU/FPU type
1428     static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1429     static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1430     static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1431     static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1432     static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1433 cebix 1.8
1434 cebix 1.1 // Read settings from widgets and set preferences
1435     static void read_memory_settings(void)
1436     {
1437 gbeauche 1.29 const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry));
1438     PrefsReplaceInt32("ramsize", atoi(str) << 20);
1439 cebix 1.1
1440 gbeauche 1.29 str = get_file_entry_path(w_rom_file);
1441 cebix 1.1 if (str && strlen(str))
1442     PrefsReplaceString("rom", str);
1443     else
1444     PrefsRemoveItem("rom");
1445    
1446     }
1447    
1448     // Create "Memory/Misc" pane
1449     static void create_memory_pane(GtkWidget *top)
1450     {
1451 gbeauche 1.29 GtkWidget *box, *hbox, *table, *label, *menu;
1452 cebix 1.1
1453     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1454 gbeauche 1.29 table = make_table(box, 2, 5);
1455 cebix 1.1
1456 gbeauche 1.29 static const combo_desc options[] = {
1457     STR_RAMSIZE_2MB_LAB,
1458     STR_RAMSIZE_4MB_LAB,
1459     STR_RAMSIZE_8MB_LAB,
1460     STR_RAMSIZE_16MB_LAB,
1461     STR_RAMSIZE_32MB_LAB,
1462     STR_RAMSIZE_64MB_LAB,
1463     STR_RAMSIZE_128MB_LAB,
1464     STR_RAMSIZE_256MB_LAB,
1465     STR_RAMSIZE_512MB_LAB,
1466     STR_RAMSIZE_1024MB_LAB,
1467     0
1468     };
1469     char default_ramsize[10];
1470     sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20);
1471     w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options);
1472 cebix 1.1
1473 cebix 1.9 static const opt_desc model_options[] = {
1474 cebix 1.1 {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1475     {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1476     {0, NULL}
1477     };
1478     int modelid = PrefsFindInt32("modelid"), active = 0;
1479     switch (modelid) {
1480     case 5: active = 0; break;
1481     case 14: active = 1; break;
1482     }
1483 gbeauche 1.29 table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active);
1484 cebix 1.9
1485 cebix 1.11 #if EMULATED_68K
1486 cebix 1.9 static const opt_desc cpu_options[] = {
1487     {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1488     {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1489     {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1490     {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1491     {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1492     {0, NULL}
1493     };
1494     int cpu = PrefsFindInt32("cpu");
1495     bool fpu = PrefsFindBool("fpu");
1496     active = 0;
1497     switch (cpu) {
1498     case 2: active = fpu ? 1 : 0; break;
1499     case 3: active = fpu ? 3 : 2; break;
1500     case 4: active = 4;
1501     }
1502 gbeauche 1.29 table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active);
1503 cebix 1.11 #endif
1504 cebix 1.1
1505 gbeauche 1.29 w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom");
1506 gbeauche 1.22
1507     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1508     make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1509     #endif
1510 cebix 1.1 }
1511    
1512    
1513     /*
1514     * Read settings from widgets and set preferences
1515     */
1516    
1517     static void read_settings(void)
1518     {
1519     read_volumes_settings();
1520     read_scsi_settings();
1521     read_graphics_settings();
1522 cebix 1.13 read_input_settings();
1523 cebix 1.1 read_serial_settings();
1524     read_memory_settings();
1525 gbeauche 1.23 read_jit_settings();
1526 cebix 1.1 }
1527 gbeauche 1.32
1528    
1529     #ifdef STANDALONE_GUI
1530     #include <errno.h>
1531 gbeauche 1.33 #include <sys/wait.h>
1532     #include "rpc.h"
1533 gbeauche 1.32
1534     /*
1535     * Fake unused data and functions
1536     */
1537    
1538     uint8 XPRAM[XPRAM_SIZE];
1539     void MountVolume(void *fh) { }
1540     void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { }
1541    
1542    
1543     /*
1544     * Display alert
1545     */
1546    
1547     static void dl_destroyed(void)
1548     {
1549     gtk_main_quit();
1550     }
1551    
1552     static void display_alert(int title_id, int prefix_id, int button_id, const char *text)
1553     {
1554     char str[256];
1555     sprintf(str, GetString(prefix_id), text);
1556    
1557     GtkWidget *dialog = gtk_dialog_new();
1558     gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id));
1559     gtk_container_border_width(GTK_CONTAINER(dialog), 5);
1560     gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
1561     gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL);
1562    
1563     GtkWidget *label = gtk_label_new(str);
1564     gtk_widget_show(label);
1565     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
1566    
1567     GtkWidget *button = gtk_button_new_with_label(GetString(button_id));
1568     gtk_widget_show(button);
1569     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
1570     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
1571     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1572     gtk_widget_grab_default(button);
1573     gtk_widget_show(dialog);
1574    
1575     gtk_main();
1576     }
1577    
1578    
1579     /*
1580     * Display error alert
1581     */
1582    
1583 gbeauche 1.33 void ErrorAlert(const char *text)
1584 gbeauche 1.32 {
1585     display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text);
1586     }
1587    
1588    
1589     /*
1590 gbeauche 1.33 * Display warning alert
1591     */
1592    
1593     void WarningAlert(const char *text)
1594     {
1595     display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text);
1596     }
1597    
1598    
1599     /*
1600     * RPC handlers
1601     */
1602    
1603     static int handle_ErrorAlert(rpc_connection_t *connection)
1604     {
1605     D(bug("handle_ErrorAlert\n"));
1606    
1607     int error;
1608     char *str;
1609     if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
1610     return error;
1611    
1612     ErrorAlert(str);
1613     free(str);
1614     return RPC_ERROR_NO_ERROR;
1615     }
1616    
1617     static int handle_WarningAlert(rpc_connection_t *connection)
1618     {
1619     D(bug("handle_WarningAlert\n"));
1620    
1621     int error;
1622     char *str;
1623     if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0)
1624     return error;
1625    
1626     WarningAlert(str);
1627     free(str);
1628     return RPC_ERROR_NO_ERROR;
1629     }
1630    
1631     static int handle_Exit(rpc_connection_t *connection)
1632     {
1633     D(bug("handle_Exit\n"));
1634    
1635     return RPC_ERROR_NO_ERROR;
1636     }
1637    
1638    
1639     /*
1640 gbeauche 1.32 * Start standalone GUI
1641     */
1642    
1643     int main(int argc, char *argv[])
1644     {
1645     #ifdef HAVE_GNOMEUI
1646     // Init GNOME/GTK
1647     char version[16];
1648     sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR);
1649     gnome_init("Basilisk II", version, argc, argv);
1650     #else
1651     // Init GTK
1652     gtk_set_locale();
1653     gtk_init(&argc, &argv);
1654     #endif
1655    
1656     // Read preferences
1657     PrefsInit(argc, argv);
1658    
1659     // Show preferences editor
1660     bool start = PrefsEditor();
1661    
1662     // Exit preferences
1663     PrefsExit();
1664    
1665     // Transfer control to the executable
1666     if (start) {
1667 gbeauche 1.33 char gui_connection_path[64];
1668     sprintf(gui_connection_path, "/org/BasiliskII/GUI/%d", getpid());
1669    
1670     int pid = fork();
1671     if (pid == 0) { // Child
1672     char b2_path[PATH_MAX];
1673     strcpy(b2_path, argv[0]);
1674     char *p = strrchr(b2_path, '/');
1675     p = p ? p + 1 : b2_path;
1676     *p = '\0';
1677     strcat(b2_path, "BasiliskII");
1678     execl(b2_path, b2_path, "--gui-connection", gui_connection_path, (char *)NULL);
1679    
1680     char str[256];
1681     sprintf(str, GetString(STR_NO_B2_EXE_FOUND), b2_path, strerror(errno));
1682     ErrorAlert(str);
1683     return 1;
1684     }
1685     else { // Parent
1686     rpc_connection_t *connection;
1687     if ((connection = rpc_init_server(gui_connection_path)) == NULL) {
1688     printf("ERROR: failed to initialize GUI-side RPC server connection\n");
1689     return 1;
1690     }
1691    
1692     static const rpc_method_descriptor_t vtable[] = {
1693     { RPC_METHOD_ERROR_ALERT, handle_ErrorAlert },
1694     { RPC_METHOD_WARNING_ALERT, handle_WarningAlert },
1695     { RPC_METHOD_EXIT, handle_Exit }
1696     };
1697     if (rpc_method_add_callbacks(connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
1698     printf("ERROR: failed to setup GUI method callbacks\n");
1699     return 1;
1700     }
1701    
1702     if (rpc_listen(connection) < 0) {
1703     printf("ERROR: failed to initialize RPC server thread\n");
1704     return 1;
1705     }
1706    
1707     int status, ret = -1;
1708     while (waitpid(pid, &status, 0) != pid)
1709     ;
1710     if (WIFEXITED(status))
1711     ret = WEXITSTATUS(status);
1712    
1713     rpc_exit(connection);
1714     return ret;
1715     }
1716 gbeauche 1.32 }
1717    
1718     return 0;
1719     }
1720     #endif