ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
Revision: 1.24
Committed: 2002-10-15T16:25:04Z (21 years, 8 months ago) by cebix
Branch: MAIN
CVS Tags: nigel-build-12, nigel-build-13
Changes since 1.23: +17 -0 lines
Log Message:
Unix: new prefs options "dsp" and "mixer" to set the OSS device names instead
of the hardcoded '/dev/dsp' and '/dev/mixer'

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs_editor_gtk.cpp - Preferences editor, Unix implementation using GTK+
3     *
4 cebix 1.19 * Basilisk II (C) 1997-2002 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    
43     // Global variables
44     static GtkWidget *win; // Preferences window
45     static bool start_clicked = true; // Return value of PrefsEditor() function
46    
47    
48     // Prototypes
49     static void create_volumes_pane(GtkWidget *top);
50     static void create_scsi_pane(GtkWidget *top);
51     static void create_graphics_pane(GtkWidget *top);
52 cebix 1.13 static void create_input_pane(GtkWidget *top);
53 cebix 1.1 static void create_serial_pane(GtkWidget *top);
54     static void create_memory_pane(GtkWidget *top);
55 gbeauche 1.23 static void create_jit_pane(GtkWidget *top);
56 cebix 1.1 static void read_settings(void);
57    
58    
59     /*
60     * Utility functions
61     */
62    
63     struct opt_desc {
64     int label_id;
65     GtkSignalFunc func;
66     };
67    
68 gbeauche 1.23 struct combo_desc {
69     int label_id;
70     };
71    
72 cebix 1.1 static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func)
73     {
74     GtkWidget *item = gtk_menu_item_new_with_label(GetString(label_id));
75     gtk_widget_show(item);
76     gtk_signal_connect(GTK_OBJECT(item), "activate", func, NULL);
77     gtk_menu_append(GTK_MENU(menu), item);
78     }
79    
80     static GtkWidget *make_pane(GtkWidget *notebook, int title_id)
81     {
82     GtkWidget *frame, *label, *box;
83    
84     frame = gtk_frame_new(NULL);
85     gtk_widget_show(frame);
86     gtk_container_border_width(GTK_CONTAINER(frame), 4);
87    
88     label = gtk_label_new(GetString(title_id));
89     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
90    
91     box = gtk_vbox_new(FALSE, 4);
92     gtk_widget_show(box);
93     gtk_container_set_border_width(GTK_CONTAINER(box), 4);
94     gtk_container_add(GTK_CONTAINER(frame), box);
95     return box;
96     }
97    
98     static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons)
99     {
100     GtkWidget *bb, *button;
101    
102     bb = gtk_hbutton_box_new();
103     gtk_widget_show(bb);
104     gtk_container_set_border_width(GTK_CONTAINER(bb), border);
105     gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE);
106     gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4);
107     gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0);
108    
109     while (buttons->label_id) {
110     button = gtk_button_new_with_label(GetString(buttons->label_id));
111     gtk_widget_show(button);
112     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL);
113     gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0);
114     buttons++;
115     }
116     return bb;
117     }
118    
119     static GtkWidget *make_separator(GtkWidget *top)
120     {
121     GtkWidget *sep = gtk_hseparator_new();
122     gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0);
123     gtk_widget_show(sep);
124     return sep;
125     }
126    
127     static GtkWidget *make_table(GtkWidget *top, int x, int y)
128     {
129     GtkWidget *table = gtk_table_new(x, y, FALSE);
130     gtk_widget_show(table);
131     gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0);
132     return table;
133     }
134    
135     static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
136     {
137     GtkWidget *box, *label, *opt, *menu;
138    
139     box = gtk_hbox_new(FALSE, 4);
140     gtk_widget_show(box);
141     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
142    
143     label = gtk_label_new(GetString(label_id));
144     gtk_widget_show(label);
145     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
146    
147     opt = gtk_option_menu_new();
148     gtk_widget_show(opt);
149     menu = gtk_menu_new();
150    
151     while (options->label_id) {
152     add_menu_item(menu, options->label_id, options->func);
153     options++;
154     }
155     gtk_menu_set_active(GTK_MENU(menu), active);
156    
157     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
158     gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0);
159     return menu;
160     }
161    
162 cebix 1.21 static GtkWidget *make_file_entry(GtkWidget *top, int label_id, const char *prefs_item, bool only_dirs = false)
163 cebix 1.1 {
164     GtkWidget *box, *label, *entry;
165    
166     box = gtk_hbox_new(FALSE, 4);
167     gtk_widget_show(box);
168     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
169    
170     label = gtk_label_new(GetString(label_id));
171     gtk_widget_show(label);
172     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
173    
174     const char *str = PrefsFindString(prefs_item);
175     if (str == NULL)
176     str = "";
177 cebix 1.21
178     #ifdef HAVE_GNOMEUI
179     entry = gnome_file_entry_new(NULL, GetString(label_id));
180     if (only_dirs)
181     gnome_file_entry_set_directory(GNOME_FILE_ENTRY(entry), true);
182     gtk_entry_set_text(GTK_ENTRY(gnome_file_entry_gtk_entry(GNOME_FILE_ENTRY(entry))), str);
183     #else
184     entry = gtk_entry_new();
185 cebix 1.1 gtk_entry_set_text(GTK_ENTRY(entry), str);
186 cebix 1.21 #endif
187     gtk_widget_show(entry);
188 cebix 1.1 gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
189     return entry;
190     }
191    
192 cebix 1.21 static char *get_file_entry_path(GtkWidget *entry)
193     {
194     #ifdef HAVE_GNOMEUI
195     return gnome_file_entry_get_full_path(GNOME_FILE_ENTRY(entry), false);
196     #else
197     return gtk_entry_get_text(GTK_ENTRY(entry));
198     #endif
199     }
200    
201 cebix 1.1 static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func)
202     {
203     GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
204     gtk_widget_show(button);
205     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item));
206     gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button);
207     gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0);
208     return button;
209     }
210    
211 gbeauche 1.23 static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *prefs_item, const combo_desc *options)
212     {
213     GtkWidget *box, *label, *combo;
214     char str[32];
215    
216     box = gtk_hbox_new(FALSE, 4);
217     gtk_widget_show(box);
218     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
219    
220     label = gtk_label_new(GetString(label_id));
221     gtk_widget_show(label);
222     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
223    
224     GList *glist = NULL;
225     while (options->label_id) {
226     glist = g_list_append(glist, (void *)GetString(options->label_id));
227     options++;
228     }
229    
230     combo = gtk_combo_new();
231     gtk_widget_show(combo);
232     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
233    
234     sprintf(str, "%d", PrefsFindInt32(prefs_item));
235     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
236     gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0);
237    
238     return combo;
239     }
240 cebix 1.1
241 gbeauche 1.23
242 cebix 1.1 /*
243     * Show preferences editor
244     * Returns true when user clicked on "Start", false otherwise
245     */
246    
247     // Window closed
248     static gint window_closed(void)
249     {
250     return FALSE;
251     }
252    
253     // Window destroyed
254     static void window_destroyed(void)
255     {
256     gtk_main_quit();
257     }
258    
259     // "Start" button clicked
260     static void cb_start(...)
261     {
262     start_clicked = true;
263     read_settings();
264     SavePrefs();
265     gtk_widget_destroy(win);
266     }
267    
268     // "Quit" button clicked
269     static void cb_quit(...)
270     {
271     start_clicked = false;
272     gtk_widget_destroy(win);
273     }
274    
275     // "OK" button of "About" dialog clicked
276     static void dl_quit(GtkWidget *dialog)
277     {
278     gtk_widget_destroy(dialog);
279     }
280    
281     // "About" selected
282     static void mn_about(...)
283     {
284 cebix 1.21 GtkWidget *dialog;
285    
286     #ifdef HAVE_GNOMEUI
287    
288     char version[32];
289     sprintf(version, "Version %d.%d", VERSION_MAJOR, VERSION_MINOR);
290     const char *authors[] = {
291     "Christian Bauer",
292     "Orlando Bassotto",
293     "Gwenolé Beauchesne",
294     "Marc Chabanas",
295     "Marc Hellwig",
296     "Biill Huey",
297     "Brian J. Johnson",
298     "Jürgen Lachmann",
299     "Samuel Lander",
300     "David Lawrence",
301     "Lauri Pesonen",
302     "Bernd Schmidt",
303     "and others",
304     NULL
305     };
306     dialog = gnome_about_new(
307     "Basilisk II",
308     version,
309     "Copyright (C) 1997-2002 Christian Bauer",
310     authors,
311     "Basilisk II comes with ABSOLUTELY NO WARRANTY."
312     "This is free software, and you are welcome to redistribute it"
313     "under the terms of the GNU General Public License.",
314     NULL
315     );
316     gnome_dialog_set_parent(GNOME_DIALOG(dialog), GTK_WINDOW(win));
317    
318     #else
319    
320     GtkWidget *label, *button;
321 cebix 1.1
322 cebix 1.16 char str[512];
323     sprintf(str,
324     "Basilisk II\nVersion %d.%d\n\n"
325 cebix 1.20 "Copyright (C) 1997-2002 Christian Bauer et al.\n"
326 cebix 1.16 "E-mail: Christian.Bauer@uni-mainz.de\n"
327     "http://www.uni-mainz.de/~bauec002/B2Main.html\n\n"
328     "Basilisk II comes with ABSOLUTELY NO\n"
329     "WARRANTY. This is free software, and\n"
330     "you are welcome to redistribute it\n"
331     "under the terms of the GNU General\n"
332     "Public License.\n",
333     VERSION_MAJOR, VERSION_MINOR
334     );
335 cebix 1.1
336     dialog = gtk_dialog_new();
337     gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE));
338     gtk_container_border_width(GTK_CONTAINER(dialog), 5);
339     gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
340    
341     label = gtk_label_new(str);
342     gtk_widget_show(label);
343     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
344    
345     button = gtk_button_new_with_label(GetString(STR_OK_BUTTON));
346     gtk_widget_show(button);
347     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
348     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
349     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
350     gtk_widget_grab_default(button);
351 cebix 1.21
352     #endif
353    
354 cebix 1.1 gtk_widget_show(dialog);
355     }
356    
357     // "Zap PRAM" selected
358     static void mn_zap_pram(...)
359     {
360     ZapPRAM();
361     }
362    
363     // Menu item descriptions
364     static GtkItemFactoryEntry menu_items[] = {
365 cebix 1.4 {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, "<Branch>"},
366     {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), NULL, GTK_SIGNAL_FUNC(cb_start), 0, NULL},
367     {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(mn_zap_pram), 0, NULL},
368     {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, "<Separator>"},
369     {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "<control>Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL},
370     {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, "<LastBranch>"},
371     {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), NULL, GTK_SIGNAL_FUNC(mn_about), 0, NULL}
372 cebix 1.1 };
373    
374     bool PrefsEditor(void)
375     {
376     // Create window
377     win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
378     gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE));
379     gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL);
380     gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL);
381    
382     // Create window contents
383     GtkWidget *box = gtk_vbox_new(FALSE, 4);
384     gtk_widget_show(box);
385     gtk_container_add(GTK_CONTAINER(win), box);
386    
387     GtkAccelGroup *accel_group = gtk_accel_group_new();
388     GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
389     gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL);
390     gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
391     GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "<main>");
392     gtk_widget_show(menu_bar);
393     gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0);
394    
395     GtkWidget *notebook = gtk_notebook_new();
396     gtk_widget_show(notebook);
397     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
398 cebix 1.8 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
399 cebix 1.1 gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
400    
401     create_volumes_pane(notebook);
402     create_scsi_pane(notebook);
403     create_graphics_pane(notebook);
404 cebix 1.13 create_input_pane(notebook);
405 cebix 1.1 create_serial_pane(notebook);
406     create_memory_pane(notebook);
407 gbeauche 1.23 create_jit_pane(notebook);
408 cebix 1.1
409     static const opt_desc buttons[] = {
410     {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
411     {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
412     {0, NULL}
413     };
414     make_button_box(box, 4, buttons);
415    
416     // Show window and enter main loop
417     gtk_widget_show(win);
418     gtk_main();
419     return start_clicked;
420     }
421    
422    
423     /*
424     * "Volumes" pane
425     */
426    
427 cebix 1.6 static GtkWidget *volume_list, *w_extfs;
428 cebix 1.1 static int selected_volume;
429    
430     // Volume in list selected
431     static void cl_selected(GtkWidget *list, int row, int column)
432     {
433     selected_volume = row;
434     }
435    
436     struct file_req_assoc {
437     file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
438     GtkWidget *req;
439     GtkWidget *entry;
440     };
441    
442     // Volume selected for addition
443     static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
444     {
445     char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
446     gtk_clist_append(GTK_CLIST(volume_list), &file);
447     gtk_widget_destroy(assoc->req);
448     delete assoc;
449     }
450    
451     // Volume selected for creation
452     static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
453     {
454     char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
455    
456     char *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
457     int size = atoi(str);
458    
459     char cmd[1024];
460     sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size);
461     int ret = system(cmd);
462     if (ret == 0)
463     gtk_clist_append(GTK_CLIST(volume_list), &file);
464     gtk_widget_destroy(GTK_WIDGET(assoc->req));
465     delete assoc;
466     }
467    
468     // "Add Volume" button clicked
469     static void cb_add_volume(...)
470     {
471     GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE));
472     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
473     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL));
474     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
475     gtk_widget_show(req);
476     }
477    
478     // "Create Hardfile" button clicked
479     static void cb_create_volume(...)
480     {
481     GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE));
482    
483     GtkWidget *box = gtk_hbox_new(FALSE, 4);
484     gtk_widget_show(box);
485     GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL));
486     gtk_widget_show(label);
487     GtkWidget *entry = gtk_entry_new();
488     gtk_widget_show(entry);
489     char str[32];
490     sprintf(str, "%d", 40);
491     gtk_entry_set_text(GTK_ENTRY(entry), str);
492     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
493     gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
494     gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0);
495    
496     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
497     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry));
498     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
499     gtk_widget_show(req);
500     }
501    
502     // "Remove Volume" button clicked
503     static void cb_remove_volume(...)
504     {
505     gtk_clist_remove(GTK_CLIST(volume_list), selected_volume);
506     }
507    
508     // "Boot From" selected
509 cebix 1.14 static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
510     static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
511 cebix 1.1
512     // "No CD-ROM Driver" button toggled
513     static void tb_nocdrom(GtkWidget *widget)
514     {
515     PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
516     }
517    
518     // Read settings from widgets and set preferences
519     static void read_volumes_settings(void)
520     {
521     while (PrefsFindString("disk"))
522     PrefsRemoveItem("disk");
523    
524     for (int i=0; i<GTK_CLIST(volume_list)->rows; i++) {
525     char *str;
526     gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
527     PrefsAddString("disk", str);
528     }
529 cebix 1.6
530 cebix 1.21 PrefsReplaceString("extfs", get_file_entry_path(w_extfs));
531 cebix 1.1 }
532    
533     // Create "Volumes" pane
534     static void create_volumes_pane(GtkWidget *top)
535     {
536     GtkWidget *box, *scroll, *menu;
537    
538     box = make_pane(top, STR_VOLUMES_PANE_TITLE);
539    
540     scroll = gtk_scrolled_window_new(NULL, NULL);
541     gtk_widget_show(scroll);
542     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
543     volume_list = gtk_clist_new(1);
544     gtk_widget_show(volume_list);
545     gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE);
546     gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE);
547 cebix 1.5 gtk_clist_set_reorderable(GTK_CLIST(volume_list), true);
548 cebix 1.1 gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL);
549     char *str;
550     int32 index = 0;
551 cebix 1.21 while ((str = const_cast<char *>(PrefsFindString("disk", index++))) != NULL)
552 cebix 1.1 gtk_clist_append(GTK_CLIST(volume_list), &str);
553     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list);
554     gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
555     selected_volume = 0;
556    
557     static const opt_desc buttons[] = {
558     {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)},
559     {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)},
560     {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)},
561     {0, NULL},
562     };
563     make_button_box(box, 0, buttons);
564     make_separator(box);
565 cebix 1.6
566 cebix 1.21 w_extfs = make_file_entry(box, STR_EXTFS_CTRL, "extfs", true);
567 cebix 1.1
568     static const opt_desc options[] = {
569     {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)},
570     {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)},
571     {0, NULL}
572     };
573 cebix 1.14 int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
574 cebix 1.1 switch (bootdriver) {
575     case 0: active = 0; break;
576     case CDROMRefNum: active = 1; break;
577     }
578     menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
579    
580     make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
581     }
582    
583    
584     /*
585 gbeauche 1.23 * "JIT Compiler" pane
586     */
587    
588     static GtkWidget *w_jit_fpu;
589     static GtkWidget *w_jit_atraps;
590     static GtkWidget *w_jit_cache_size;
591     static GtkWidget *w_jit_lazy_flush;
592    
593     // Set sensitivity of widgets
594     static void set_jit_sensitive(void)
595     {
596     const bool jit_enabled = PrefsFindBool("jit");
597     gtk_widget_set_sensitive(w_jit_fpu, jit_enabled);
598     gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled);
599     gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled);
600     }
601    
602     // "Use JIT Compiler" button toggled
603     static void tb_jit(GtkWidget *widget)
604     {
605     PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active);
606     set_jit_sensitive();
607     }
608    
609     // "Compile FPU Instructions" button toggled
610     static void tb_jit_fpu(GtkWidget *widget)
611     {
612     PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active);
613     }
614    
615     // "Lazy translation cache invalidation" button toggled
616     static void tb_jit_lazy_flush(GtkWidget *widget)
617     {
618     PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active);
619     }
620    
621     // Read settings from widgets and set preferences
622     static void read_jit_settings(void)
623     {
624     #if USE_JIT
625     bool jit_enabled = PrefsFindBool("jit");
626     if (jit_enabled) {
627     const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
628     PrefsReplaceInt32("jitcachesize", atoi(str));
629     }
630     #endif
631     }
632    
633     // Create "JIT Compiler" pane
634     static void create_jit_pane(GtkWidget *top)
635     {
636     #if USE_JIT
637     GtkWidget *box, *table, *label, *menu;
638     char str[32];
639    
640     box = make_pane(top, STR_JIT_PANE_TITLE);
641     make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
642    
643     w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu));
644    
645     // Translation cache size
646     static const combo_desc options[] = {
647     STR_JIT_CACHE_SIZE_2MB_LAB,
648     STR_JIT_CACHE_SIZE_4MB_LAB,
649     STR_JIT_CACHE_SIZE_8MB_LAB,
650     STR_JIT_CACHE_SIZE_16MB_LAB,
651     0
652     };
653     w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, "jitcachesize", options);
654    
655     // Lazy translation cache invalidation
656     w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush));
657    
658     set_jit_sensitive();
659     #endif
660     }
661    
662     /*
663 cebix 1.1 * "SCSI" pane
664     */
665    
666     static GtkWidget *w_scsi[7];
667    
668     // Read settings from widgets and set preferences
669     static void read_scsi_settings(void)
670     {
671     for (int id=0; id<7; id++) {
672     char prefs_name[32];
673     sprintf(prefs_name, "scsi%d", id);
674 cebix 1.21 const char *str = get_file_entry_path(w_scsi[id]);
675 cebix 1.1 if (str && strlen(str))
676     PrefsReplaceString(prefs_name, str);
677     else
678     PrefsRemoveItem(prefs_name);
679     }
680     }
681    
682     // Create "SCSI" pane
683     static void create_scsi_pane(GtkWidget *top)
684     {
685     GtkWidget *box;
686    
687     box = make_pane(top, STR_SCSI_PANE_TITLE);
688    
689     for (int id=0; id<7; id++) {
690     char prefs_name[32];
691     sprintf(prefs_name, "scsi%d", id);
692 cebix 1.21 w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name);
693 cebix 1.1 }
694     }
695    
696    
697     /*
698     * "Graphics/Sound" pane
699     */
700    
701     // Display types
702     enum {
703     DISPLAY_WINDOW,
704     DISPLAY_SCREEN
705     };
706    
707     static GtkWidget *w_frameskip, *w_display_x, *w_display_y;
708     static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
709     static int display_type;
710     static int dis_width, dis_height;
711    
712 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
713 cebix 1.7 static GtkWidget *w_fbdev_name, *w_fbdevice_file;
714     static GtkWidget *l_fbdev_name, *l_fbdevice_file;
715     static char fbdev_name[256];
716     #endif
717    
718 cebix 1.24 static GtkWidget *w_dspdevice_file, *w_mixerdevice_file;
719    
720 cebix 1.1 // Hide/show graphics widgets
721     static void hide_show_graphics_widgets(void)
722     {
723     switch (display_type) {
724     case DISPLAY_WINDOW:
725     gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
726 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
727 cebix 1.7 gtk_widget_show(w_display_x); gtk_widget_show(l_display_x);
728     gtk_widget_show(w_display_y); gtk_widget_show(l_display_y);
729     gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name);
730     #endif
731 cebix 1.1 break;
732     case DISPLAY_SCREEN:
733     gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
734 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
735 cebix 1.7 gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x);
736     gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y);
737     gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name);
738     #endif
739 cebix 1.1 break;
740     }
741     }
742    
743     // "Window" video type selected
744     static void mn_window(...)
745     {
746     display_type = DISPLAY_WINDOW;
747     hide_show_graphics_widgets();
748     }
749    
750     // "Fullscreen" video type selected
751     static void mn_fullscreen(...)
752     {
753     display_type = DISPLAY_SCREEN;
754     hide_show_graphics_widgets();
755     }
756    
757     // "5 Hz".."60Hz" selected
758     static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
759     static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
760     static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
761     static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
762     static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
763     static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
764 cebix 1.12 static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
765 cebix 1.1
766 cebix 1.24 // Set sensitivity of widgets
767     static void set_graphics_sensitive(void)
768     {
769     const bool sound_enabled = !PrefsFindBool("nosound");
770     gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled);
771     gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled);
772     }
773    
774 cebix 1.1 // "Disable Sound Output" button toggled
775     static void tb_nosound(GtkWidget *widget)
776     {
777     PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
778 cebix 1.24 set_graphics_sensitive();
779 cebix 1.1 }
780    
781     // Read graphics preferences
782     static void parse_graphics_prefs(void)
783     {
784     display_type = DISPLAY_WINDOW;
785     dis_width = 512;
786     dis_height = 384;
787 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
788 cebix 1.7 fbdev_name[0] = 0;
789     #endif
790 cebix 1.1
791     const char *str = PrefsFindString("screen");
792     if (str) {
793     if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
794     display_type = DISPLAY_WINDOW;
795 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
796 cebix 1.7 else if (sscanf(str, "dga/%255s", fbdev_name) == 1)
797     #else
798 cebix 1.2 else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
799 cebix 1.7 #endif
800 cebix 1.1 display_type = DISPLAY_SCREEN;
801     }
802     }
803    
804     // Read settings from widgets and set preferences
805     static void read_graphics_settings(void)
806     {
807     const char *str;
808    
809     str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
810     dis_width = atoi(str);
811    
812     str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
813     dis_height = atoi(str);
814    
815     char pref[256];
816     switch (display_type) {
817     case DISPLAY_WINDOW:
818     sprintf(pref, "win/%d/%d", dis_width, dis_height);
819     break;
820     case DISPLAY_SCREEN:
821 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
822 cebix 1.7 str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name));
823     sprintf(pref, "dga/%s", str);
824     #else
825 cebix 1.2 sprintf(pref, "dga/%d/%d", dis_width, dis_height);
826 cebix 1.7 #endif
827 cebix 1.1 break;
828     default:
829     PrefsRemoveItem("screen");
830     return;
831     }
832     PrefsReplaceString("screen", pref);
833 cebix 1.21
834     #ifdef ENABLE_FBDEV_DGA
835     str = get_file_entry_path(w_fbdevice_file);
836     if (str && strlen(str))
837     PrefsReplaceString("fbdevicefile", str);
838     else
839     PrefsRemoveItem("fbdevicefile");
840     #endif
841 cebix 1.24 PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file));
842     PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file));
843 cebix 1.1 }
844    
845     // Create "Graphics/Sound" pane
846     static void create_graphics_pane(GtkWidget *top)
847     {
848 cebix 1.2 GtkWidget *box, *table, *label, *opt, *menu, *combo;
849 cebix 1.1 char str[32];
850    
851     parse_graphics_prefs();
852    
853     box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
854 cebix 1.7 table = make_table(box, 2, 5);
855 cebix 1.1
856     label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
857     gtk_widget_show(label);
858     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
859    
860     opt = gtk_option_menu_new();
861     gtk_widget_show(opt);
862     menu = gtk_menu_new();
863     add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window));
864     add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen));
865     switch (display_type) {
866     case DISPLAY_WINDOW:
867     gtk_menu_set_active(GTK_MENU(menu), 0);
868     break;
869     case DISPLAY_SCREEN:
870     gtk_menu_set_active(GTK_MENU(menu), 1);
871     break;
872     }
873     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
874     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
875    
876     l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
877     gtk_widget_show(l_frameskip);
878     gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
879    
880     w_frameskip = gtk_option_menu_new();
881     gtk_widget_show(w_frameskip);
882     menu = gtk_menu_new();
883     add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
884     add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
885     add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
886     add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
887     add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
888     add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
889 cebix 1.12 add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic));
890 cebix 1.1 int frameskip = PrefsFindInt32("frameskip");
891 cebix 1.12 int item = -1;
892 cebix 1.1 switch (frameskip) {
893 cebix 1.12 case 12: item = 0; break;
894     case 8: item = 1; break;
895     case 6: item = 2; break;
896     case 4: item = 3; break;
897     case 2: item = 4; break;
898     case 1: item = 5; break;
899     case 0: item = 6; break;
900 cebix 1.1 }
901 cebix 1.12 if (item >= 0)
902     gtk_menu_set_active(GTK_MENU(menu), item);
903 cebix 1.1 gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
904     gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
905    
906     l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
907     gtk_widget_show(l_display_x);
908     gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
909    
910 cebix 1.2 combo = gtk_combo_new();
911     gtk_widget_show(combo);
912     GList *glist1 = NULL;
913 cebix 1.4 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
914     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
915     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
916     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
917     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
918 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
919     if (dis_width)
920     sprintf(str, "%d", dis_width);
921     else
922 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
923 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
924     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
925     w_display_x = GTK_COMBO(combo)->entry;
926 cebix 1.1
927     l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
928     gtk_widget_show(l_display_y);
929     gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
930    
931 cebix 1.2 combo = gtk_combo_new();
932     gtk_widget_show(combo);
933     GList *glist2 = NULL;
934 cebix 1.4 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
935     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
936     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
937     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
938     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
939 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
940     if (dis_height)
941     sprintf(str, "%d", dis_height);
942     else
943 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
944 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
945     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
946     w_display_y = GTK_COMBO(combo)->entry;
947 cebix 1.7
948 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
949 cebix 1.7 l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL));
950     gtk_widget_show(l_fbdev_name);
951     gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
952    
953     w_fbdev_name = gtk_entry_new();
954     gtk_widget_show(w_fbdev_name);
955     gtk_entry_set_text(GTK_ENTRY(w_fbdev_name), fbdev_name);
956     gtk_table_attach(GTK_TABLE(table), w_fbdev_name, 1, 2, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
957    
958 cebix 1.21 w_fbdevice_file = make_file_entry(box, STR_FBDEVICE_FILE_CTRL, "fbdevicefile");
959 cebix 1.7 #endif
960 cebix 1.1
961 cebix 1.13 make_separator(box);
962 cebix 1.1 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
963 cebix 1.24 w_dspdevice_file = make_file_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp");
964     w_mixerdevice_file = make_file_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer");
965    
966     set_graphics_sensitive();
967 cebix 1.1
968     hide_show_graphics_widgets();
969     }
970    
971    
972     /*
973 cebix 1.13 * "Input" pane
974     */
975    
976     static GtkWidget *w_keycode_file;
977     static GtkWidget *w_mouse_wheel_lines;
978    
979     // Set sensitivity of widgets
980     static void set_input_sensitive(void)
981     {
982     gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
983 cebix 1.14 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
984 cebix 1.13 }
985    
986     // "Use Raw Keycodes" button toggled
987     static void tb_keycodes(GtkWidget *widget)
988     {
989     PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
990     set_input_sensitive();
991     }
992    
993     // "Mouse Wheel Mode" selected
994 cebix 1.14 static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
995     static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
996 cebix 1.13
997     // Read settings from widgets and set preferences
998     static void read_input_settings(void)
999     {
1000 cebix 1.21 const char *str = get_file_entry_path(w_keycode_file);
1001 cebix 1.13 if (str && strlen(str))
1002     PrefsReplaceString("keycodefile", str);
1003     else
1004     PrefsRemoveItem("keycodefile");
1005    
1006 cebix 1.14 PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
1007 cebix 1.13 }
1008    
1009     // Create "Input" pane
1010     static void create_input_pane(GtkWidget *top)
1011     {
1012     GtkWidget *box, *hbox, *menu, *label;
1013     GtkObject *adj;
1014    
1015     box = make_pane(top, STR_INPUT_PANE_TITLE);
1016    
1017     make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1018 cebix 1.21 w_keycode_file = make_file_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
1019 cebix 1.13
1020     make_separator(box);
1021    
1022     static const opt_desc options[] = {
1023     {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
1024     {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
1025     {0, NULL}
1026     };
1027 cebix 1.14 int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
1028 cebix 1.13 switch (wheelmode) {
1029     case 0: active = 0; break;
1030     case 1: active = 1; break;
1031     }
1032     menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
1033    
1034     hbox = gtk_hbox_new(FALSE, 4);
1035     gtk_widget_show(hbox);
1036     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1037    
1038     label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
1039     gtk_widget_show(label);
1040     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1041    
1042 cebix 1.14 adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
1043 cebix 1.13 w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1044     gtk_widget_show(w_mouse_wheel_lines);
1045     gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
1046    
1047     set_input_sensitive();
1048     }
1049    
1050    
1051     /*
1052 cebix 1.1 * "Serial/Network" pane
1053     */
1054    
1055 cebix 1.18 static GtkWidget *w_seriala, *w_serialb, *w_ether, *w_udp_port;
1056    
1057     // Set sensitivity of widgets
1058     static void set_serial_sensitive(void)
1059     {
1060     #if SUPPORTS_UDP_TUNNEL
1061     gtk_widget_set_sensitive(w_ether, !PrefsFindBool("udptunnel"));
1062     gtk_widget_set_sensitive(w_udp_port, PrefsFindBool("udptunnel"));
1063     #endif
1064     }
1065    
1066     // "Tunnel AppleTalk over IP" button toggled
1067     static void tb_udptunnel(GtkWidget *widget)
1068     {
1069     PrefsReplaceBool("udptunnel", GTK_TOGGLE_BUTTON(widget)->active);
1070     set_serial_sensitive();
1071     }
1072 cebix 1.1
1073     // Read settings from widgets and set preferences
1074     static void read_serial_settings(void)
1075     {
1076     const char *str;
1077    
1078     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1079     PrefsReplaceString("seriala", str);
1080    
1081     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1082     PrefsReplaceString("serialb", str);
1083    
1084     str = gtk_entry_get_text(GTK_ENTRY(w_ether));
1085     if (str && strlen(str))
1086     PrefsReplaceString("ether", str);
1087     else
1088     PrefsRemoveItem("ether");
1089 cebix 1.18
1090     #if SUPPORTS_UDP_TUNNEL
1091     PrefsReplaceInt32("udpport", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_udp_port)));
1092     #endif
1093 cebix 1.1 }
1094    
1095     // Add names of serial devices
1096     static gint gl_str_cmp(gconstpointer a, gconstpointer b)
1097     {
1098     return strcmp((char *)a, (char *)b);
1099     }
1100    
1101     static GList *add_serial_names(void)
1102     {
1103     GList *glist = NULL;
1104    
1105     // Search /dev for ttyS* and lp*
1106     DIR *d = opendir("/dev");
1107     if (d) {
1108     struct dirent *de;
1109     while ((de = readdir(d)) != NULL) {
1110     #if defined(__linux__)
1111     if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
1112     #elif defined(__FreeBSD__)
1113     if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1114 cebix 1.4 #elif defined(__NetBSD__)
1115     if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1116 cebix 1.1 #elif defined(sgi)
1117     if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) {
1118     #else
1119     if (false) {
1120     #endif
1121     char *str = new char[64];
1122     sprintf(str, "/dev/%s", de->d_name);
1123     glist = g_list_append(glist, str);
1124     }
1125     }
1126     closedir(d);
1127     }
1128     if (glist)
1129     g_list_sort(glist, gl_str_cmp);
1130     else
1131 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1132 cebix 1.1 return glist;
1133     }
1134    
1135     // Add names of ethernet interfaces
1136     static GList *add_ether_names(void)
1137     {
1138     GList *glist = NULL;
1139    
1140     // Get list of all Ethernet interfaces
1141     int s = socket(PF_INET, SOCK_DGRAM, 0);
1142     if (s >= 0) {
1143     char inbuf[8192];
1144     struct ifconf ifc;
1145     ifc.ifc_len = sizeof(inbuf);
1146     ifc.ifc_buf = inbuf;
1147     if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
1148     struct ifreq req, *ifr = ifc.ifc_req;
1149     for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
1150     req = *ifr;
1151 cebix 1.4 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(sgi)
1152 cebix 1.1 if (ioctl(s, SIOCGIFADDR, &req) == 0 && (req.ifr_addr.sa_family == ARPHRD_ETHER || req.ifr_addr.sa_family == ARPHRD_ETHER+1)) {
1153 cebix 1.4 #elif defined(__linux__)
1154     if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
1155 cebix 1.1 #else
1156 cebix 1.4 if (false) {
1157 cebix 1.1 #endif
1158     char *str = new char[64];
1159     strncpy(str, ifr->ifr_name, 63);
1160     glist = g_list_append(glist, str);
1161     }
1162     }
1163     }
1164     close(s);
1165     }
1166     if (glist)
1167     g_list_sort(glist, gl_str_cmp);
1168     else
1169 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1170 cebix 1.1 return glist;
1171     }
1172    
1173     // Create "Serial/Network" pane
1174     static void create_serial_pane(GtkWidget *top)
1175     {
1176 cebix 1.18 GtkWidget *box, *hbox, *table, *label, *combo, *sep;
1177     GtkObject *adj;
1178 cebix 1.1
1179     box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
1180 cebix 1.13 table = make_table(box, 2, 4);
1181 cebix 1.1
1182     label = gtk_label_new(GetString(STR_SERIALA_CTRL));
1183     gtk_widget_show(label);
1184     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1185    
1186 cebix 1.18 GList *glist = add_serial_names();
1187 cebix 1.1 combo = gtk_combo_new();
1188     gtk_widget_show(combo);
1189     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1190     const char *str = PrefsFindString("seriala");
1191     if (str == NULL)
1192     str = "";
1193     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1194     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1195     w_seriala = GTK_COMBO(combo)->entry;
1196    
1197     label = gtk_label_new(GetString(STR_SERIALB_CTRL));
1198     gtk_widget_show(label);
1199     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1200    
1201     combo = gtk_combo_new();
1202     gtk_widget_show(combo);
1203     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1204     str = PrefsFindString("serialb");
1205     if (str == NULL)
1206     str = "";
1207     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1208     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1209     w_serialb = GTK_COMBO(combo)->entry;
1210    
1211 cebix 1.13 sep = gtk_hseparator_new();
1212     gtk_widget_show(sep);
1213     gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1214    
1215 cebix 1.1 label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1216     gtk_widget_show(label);
1217 cebix 1.13 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1218 cebix 1.1
1219     glist = add_ether_names();
1220     combo = gtk_combo_new();
1221     gtk_widget_show(combo);
1222     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1223     str = PrefsFindString("ether");
1224     if (str == NULL)
1225     str = "";
1226     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1227 cebix 1.13 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1228 cebix 1.1 w_ether = GTK_COMBO(combo)->entry;
1229 cebix 1.18
1230     #if SUPPORTS_UDP_TUNNEL
1231     make_checkbox(box, STR_UDPTUNNEL_CTRL, "udptunnel", GTK_SIGNAL_FUNC(tb_udptunnel));
1232    
1233     hbox = gtk_hbox_new(FALSE, 4);
1234     gtk_widget_show(hbox);
1235     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1236    
1237     label = gtk_label_new(GetString(STR_UDPPORT_CTRL));
1238     gtk_widget_show(label);
1239     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1240    
1241     adj = gtk_adjustment_new(PrefsFindInt32("udpport"), 1, 65535, 1, 5, 0);
1242     w_udp_port = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1243     gtk_widget_show(w_udp_port);
1244     gtk_box_pack_start(GTK_BOX(hbox), w_udp_port, FALSE, FALSE, 0);
1245     #endif
1246    
1247     set_serial_sensitive();
1248 cebix 1.1 }
1249    
1250    
1251     /*
1252     * "Memory/Misc" pane
1253     */
1254    
1255     static GtkObject *w_ramsize_adj;
1256     static GtkWidget *w_rom_file;
1257    
1258 gbeauche 1.22 // "Ignore SEGV" button toggled
1259     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1260     static void tb_ignoresegv(GtkWidget *widget)
1261     {
1262     PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1263     }
1264     #endif
1265    
1266 cebix 1.1 // Model ID selected
1267     static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1268     static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1269    
1270 cebix 1.9 // CPU/FPU type
1271     static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1272     static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1273     static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1274     static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1275     static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1276 cebix 1.8
1277 cebix 1.1 // Read settings from widgets and set preferences
1278     static void read_memory_settings(void)
1279     {
1280     PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
1281    
1282 cebix 1.21 const char *str = get_file_entry_path(w_rom_file);
1283 cebix 1.1 if (str && strlen(str))
1284     PrefsReplaceString("rom", str);
1285     else
1286     PrefsRemoveItem("rom");
1287    
1288     }
1289    
1290     // Create "Memory/Misc" pane
1291     static void create_memory_pane(GtkWidget *top)
1292     {
1293 cebix 1.17 GtkWidget *box, *hbox, *vbox, *hbox2, *label, *scale;
1294 cebix 1.1
1295     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1296    
1297     hbox = gtk_hbox_new(FALSE, 4);
1298     gtk_widget_show(hbox);
1299    
1300     label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1301     gtk_widget_show(label);
1302     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1303    
1304     vbox = gtk_vbox_new(FALSE, 4);
1305     gtk_widget_show(vbox);
1306    
1307     gfloat min, max;
1308     min = 1;
1309     max = 1024;
1310     w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1311     gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1312    
1313     scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1314     gtk_widget_show(scale);
1315     gtk_scale_set_digits(GTK_SCALE(scale), 0);
1316     gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1317    
1318     hbox2 = gtk_hbox_new(FALSE, 4);
1319     gtk_widget_show(hbox2);
1320    
1321     char val[32];
1322     sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1323     label = gtk_label_new(val);
1324     gtk_widget_show(label);
1325     gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1326    
1327     sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1328     label = gtk_label_new(val);
1329     gtk_widget_show(label);
1330     gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1331     gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1332     gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1333     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1334    
1335 cebix 1.9 static const opt_desc model_options[] = {
1336 cebix 1.1 {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1337     {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1338     {0, NULL}
1339     };
1340     int modelid = PrefsFindInt32("modelid"), active = 0;
1341     switch (modelid) {
1342     case 5: active = 0; break;
1343     case 14: active = 1; break;
1344     }
1345 cebix 1.9 make_option_menu(box, STR_MODELID_CTRL, model_options, active);
1346    
1347 cebix 1.11 #if EMULATED_68K
1348 cebix 1.9 static const opt_desc cpu_options[] = {
1349     {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1350     {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1351     {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1352     {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1353     {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1354     {0, NULL}
1355     };
1356     int cpu = PrefsFindInt32("cpu");
1357     bool fpu = PrefsFindBool("fpu");
1358     active = 0;
1359     switch (cpu) {
1360     case 2: active = fpu ? 1 : 0; break;
1361     case 3: active = fpu ? 3 : 2; break;
1362     case 4: active = 4;
1363     }
1364     make_option_menu(box, STR_CPU_CTRL, cpu_options, active);
1365 cebix 1.11 #endif
1366 cebix 1.1
1367 cebix 1.21 w_rom_file = make_file_entry(box, STR_ROM_FILE_CTRL, "rom");
1368 gbeauche 1.22
1369     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1370     make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1371     #endif
1372 cebix 1.1 }
1373    
1374    
1375     /*
1376     * Read settings from widgets and set preferences
1377     */
1378    
1379     static void read_settings(void)
1380     {
1381     read_volumes_settings();
1382     read_scsi_settings();
1383     read_graphics_settings();
1384 cebix 1.13 read_input_settings();
1385 cebix 1.1 read_serial_settings();
1386     read_memory_settings();
1387 gbeauche 1.23 read_jit_settings();
1388 cebix 1.1 }