ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
Revision: 1.28
Committed: 2005-06-19T15:52:09Z (19 years, 2 months ago) by gbeauche
Branch: MAIN
Changes since 1.27: +8 -4 lines
Log Message:
gtk2 gui support

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    
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 gbeauche 1.28 static const gchar *get_file_entry_path(GtkWidget *entry)
193 cebix 1.21 {
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 cebix 1.25 "Copyright (C) 1997-2004 Christian Bauer",
310 cebix 1.21 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.25 "Copyright (C) 1997-2004 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 gbeauche 1.28 #if GTK_CHECK_VERSION(1,3,15)
391     gtk_window_add_accel_group(GTK_WINDOW(win), accel_group);
392     #else
393 cebix 1.1 gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
394 gbeauche 1.28 #endif
395 cebix 1.1 GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "<main>");
396     gtk_widget_show(menu_bar);
397     gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0);
398    
399     GtkWidget *notebook = gtk_notebook_new();
400     gtk_widget_show(notebook);
401     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
402 cebix 1.8 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
403 cebix 1.1 gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
404    
405     create_volumes_pane(notebook);
406     create_scsi_pane(notebook);
407     create_graphics_pane(notebook);
408 cebix 1.13 create_input_pane(notebook);
409 cebix 1.1 create_serial_pane(notebook);
410     create_memory_pane(notebook);
411 gbeauche 1.23 create_jit_pane(notebook);
412 cebix 1.1
413     static const opt_desc buttons[] = {
414     {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
415     {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
416     {0, NULL}
417     };
418     make_button_box(box, 4, buttons);
419    
420     // Show window and enter main loop
421     gtk_widget_show(win);
422     gtk_main();
423     return start_clicked;
424     }
425    
426    
427     /*
428     * "Volumes" pane
429     */
430    
431 cebix 1.6 static GtkWidget *volume_list, *w_extfs;
432 cebix 1.1 static int selected_volume;
433    
434     // Volume in list selected
435     static void cl_selected(GtkWidget *list, int row, int column)
436     {
437     selected_volume = row;
438     }
439    
440     struct file_req_assoc {
441     file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
442     GtkWidget *req;
443     GtkWidget *entry;
444     };
445    
446     // Volume selected for addition
447     static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
448     {
449 gbeauche 1.28 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
450 cebix 1.1 gtk_clist_append(GTK_CLIST(volume_list), &file);
451     gtk_widget_destroy(assoc->req);
452     delete assoc;
453     }
454    
455     // Volume selected for creation
456     static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
457     {
458 gbeauche 1.28 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
459 cebix 1.1
460 gbeauche 1.28 const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
461 cebix 1.1 int size = atoi(str);
462    
463     char cmd[1024];
464     sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size);
465     int ret = system(cmd);
466     if (ret == 0)
467     gtk_clist_append(GTK_CLIST(volume_list), &file);
468     gtk_widget_destroy(GTK_WIDGET(assoc->req));
469     delete assoc;
470     }
471    
472     // "Add Volume" button clicked
473     static void cb_add_volume(...)
474     {
475     GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE));
476     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
477     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL));
478     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
479     gtk_widget_show(req);
480     }
481    
482     // "Create Hardfile" button clicked
483     static void cb_create_volume(...)
484     {
485     GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE));
486    
487     GtkWidget *box = gtk_hbox_new(FALSE, 4);
488     gtk_widget_show(box);
489     GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL));
490     gtk_widget_show(label);
491     GtkWidget *entry = gtk_entry_new();
492     gtk_widget_show(entry);
493     char str[32];
494     sprintf(str, "%d", 40);
495     gtk_entry_set_text(GTK_ENTRY(entry), str);
496     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
497     gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
498     gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0);
499    
500     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
501     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry));
502     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
503     gtk_widget_show(req);
504     }
505    
506     // "Remove Volume" button clicked
507     static void cb_remove_volume(...)
508     {
509     gtk_clist_remove(GTK_CLIST(volume_list), selected_volume);
510     }
511    
512     // "Boot From" selected
513 cebix 1.14 static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
514     static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
515 cebix 1.1
516     // "No CD-ROM Driver" button toggled
517     static void tb_nocdrom(GtkWidget *widget)
518     {
519     PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
520     }
521    
522     // Read settings from widgets and set preferences
523     static void read_volumes_settings(void)
524     {
525     while (PrefsFindString("disk"))
526     PrefsRemoveItem("disk");
527    
528     for (int i=0; i<GTK_CLIST(volume_list)->rows; i++) {
529     char *str;
530     gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
531     PrefsAddString("disk", str);
532     }
533 cebix 1.6
534 cebix 1.21 PrefsReplaceString("extfs", get_file_entry_path(w_extfs));
535 cebix 1.1 }
536    
537     // Create "Volumes" pane
538     static void create_volumes_pane(GtkWidget *top)
539     {
540     GtkWidget *box, *scroll, *menu;
541    
542     box = make_pane(top, STR_VOLUMES_PANE_TITLE);
543    
544     scroll = gtk_scrolled_window_new(NULL, NULL);
545     gtk_widget_show(scroll);
546     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
547     volume_list = gtk_clist_new(1);
548     gtk_widget_show(volume_list);
549     gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE);
550     gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE);
551 cebix 1.5 gtk_clist_set_reorderable(GTK_CLIST(volume_list), true);
552 cebix 1.1 gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL);
553     char *str;
554     int32 index = 0;
555 cebix 1.21 while ((str = const_cast<char *>(PrefsFindString("disk", index++))) != NULL)
556 cebix 1.1 gtk_clist_append(GTK_CLIST(volume_list), &str);
557     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list);
558     gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
559     selected_volume = 0;
560    
561     static const opt_desc buttons[] = {
562     {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)},
563     {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)},
564     {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)},
565     {0, NULL},
566     };
567     make_button_box(box, 0, buttons);
568     make_separator(box);
569 cebix 1.6
570 cebix 1.21 w_extfs = make_file_entry(box, STR_EXTFS_CTRL, "extfs", true);
571 cebix 1.1
572     static const opt_desc options[] = {
573     {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)},
574     {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)},
575     {0, NULL}
576     };
577 cebix 1.14 int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
578 cebix 1.1 switch (bootdriver) {
579     case 0: active = 0; break;
580     case CDROMRefNum: active = 1; break;
581     }
582     menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
583    
584     make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
585     }
586    
587    
588     /*
589 gbeauche 1.23 * "JIT Compiler" pane
590     */
591    
592     static GtkWidget *w_jit_fpu;
593     static GtkWidget *w_jit_atraps;
594     static GtkWidget *w_jit_cache_size;
595     static GtkWidget *w_jit_lazy_flush;
596 gbeauche 1.27 static GtkWidget *w_jit_follow_const_jumps;
597 gbeauche 1.23
598     // Set sensitivity of widgets
599     static void set_jit_sensitive(void)
600     {
601     const bool jit_enabled = PrefsFindBool("jit");
602     gtk_widget_set_sensitive(w_jit_fpu, jit_enabled);
603     gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled);
604     gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled);
605 gbeauche 1.27 gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled);
606 gbeauche 1.23 }
607    
608     // "Use JIT Compiler" button toggled
609     static void tb_jit(GtkWidget *widget)
610     {
611     PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active);
612     set_jit_sensitive();
613     }
614    
615     // "Compile FPU Instructions" button toggled
616     static void tb_jit_fpu(GtkWidget *widget)
617     {
618     PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active);
619     }
620    
621     // "Lazy translation cache invalidation" button toggled
622     static void tb_jit_lazy_flush(GtkWidget *widget)
623     {
624     PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active);
625     }
626    
627 gbeauche 1.27 // "Translate through constant jumps (inline blocks)" button toggled
628     static void tb_jit_follow_const_jumps(GtkWidget *widget)
629     {
630     PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active);
631     }
632    
633 gbeauche 1.23 // Read settings from widgets and set preferences
634     static void read_jit_settings(void)
635     {
636     #if USE_JIT
637     bool jit_enabled = PrefsFindBool("jit");
638     if (jit_enabled) {
639     const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
640     PrefsReplaceInt32("jitcachesize", atoi(str));
641     }
642     #endif
643     }
644    
645     // Create "JIT Compiler" pane
646     static void create_jit_pane(GtkWidget *top)
647     {
648     #if USE_JIT
649     GtkWidget *box, *table, *label, *menu;
650     char str[32];
651    
652     box = make_pane(top, STR_JIT_PANE_TITLE);
653     make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
654    
655     w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu));
656    
657     // Translation cache size
658     static const combo_desc options[] = {
659     STR_JIT_CACHE_SIZE_2MB_LAB,
660     STR_JIT_CACHE_SIZE_4MB_LAB,
661     STR_JIT_CACHE_SIZE_8MB_LAB,
662     STR_JIT_CACHE_SIZE_16MB_LAB,
663     0
664     };
665     w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, "jitcachesize", options);
666    
667     // Lazy translation cache invalidation
668     w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush));
669 gbeauche 1.27
670     // Follow constant jumps (inline basic blocks)
671     w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
672    
673 gbeauche 1.23 set_jit_sensitive();
674     #endif
675     }
676    
677     /*
678 cebix 1.1 * "SCSI" pane
679     */
680    
681     static GtkWidget *w_scsi[7];
682    
683     // Read settings from widgets and set preferences
684     static void read_scsi_settings(void)
685     {
686     for (int id=0; id<7; id++) {
687     char prefs_name[32];
688     sprintf(prefs_name, "scsi%d", id);
689 cebix 1.21 const char *str = get_file_entry_path(w_scsi[id]);
690 cebix 1.1 if (str && strlen(str))
691     PrefsReplaceString(prefs_name, str);
692     else
693     PrefsRemoveItem(prefs_name);
694     }
695     }
696    
697     // Create "SCSI" pane
698     static void create_scsi_pane(GtkWidget *top)
699     {
700     GtkWidget *box;
701    
702     box = make_pane(top, STR_SCSI_PANE_TITLE);
703    
704     for (int id=0; id<7; id++) {
705     char prefs_name[32];
706     sprintf(prefs_name, "scsi%d", id);
707 cebix 1.21 w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name);
708 cebix 1.1 }
709     }
710    
711    
712     /*
713     * "Graphics/Sound" pane
714     */
715    
716     // Display types
717     enum {
718     DISPLAY_WINDOW,
719     DISPLAY_SCREEN
720     };
721    
722     static GtkWidget *w_frameskip, *w_display_x, *w_display_y;
723     static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
724     static int display_type;
725     static int dis_width, dis_height;
726    
727 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
728 cebix 1.7 static GtkWidget *w_fbdev_name, *w_fbdevice_file;
729     static GtkWidget *l_fbdev_name, *l_fbdevice_file;
730     static char fbdev_name[256];
731     #endif
732    
733 cebix 1.24 static GtkWidget *w_dspdevice_file, *w_mixerdevice_file;
734    
735 cebix 1.1 // Hide/show graphics widgets
736     static void hide_show_graphics_widgets(void)
737     {
738     switch (display_type) {
739     case DISPLAY_WINDOW:
740     gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
741 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
742 cebix 1.7 gtk_widget_show(w_display_x); gtk_widget_show(l_display_x);
743     gtk_widget_show(w_display_y); gtk_widget_show(l_display_y);
744     gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name);
745     #endif
746 cebix 1.1 break;
747     case DISPLAY_SCREEN:
748     gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
749 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
750 cebix 1.7 gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x);
751     gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y);
752     gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name);
753     #endif
754 cebix 1.1 break;
755     }
756     }
757    
758     // "Window" video type selected
759     static void mn_window(...)
760     {
761     display_type = DISPLAY_WINDOW;
762     hide_show_graphics_widgets();
763     }
764    
765     // "Fullscreen" video type selected
766     static void mn_fullscreen(...)
767     {
768     display_type = DISPLAY_SCREEN;
769     hide_show_graphics_widgets();
770     }
771    
772     // "5 Hz".."60Hz" selected
773     static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
774     static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
775     static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
776     static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
777     static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
778     static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
779 cebix 1.12 static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
780 cebix 1.1
781 cebix 1.24 // Set sensitivity of widgets
782     static void set_graphics_sensitive(void)
783     {
784     const bool sound_enabled = !PrefsFindBool("nosound");
785     gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled);
786     gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled);
787     }
788    
789 cebix 1.1 // "Disable Sound Output" button toggled
790     static void tb_nosound(GtkWidget *widget)
791     {
792     PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
793 cebix 1.24 set_graphics_sensitive();
794 cebix 1.1 }
795    
796     // Read graphics preferences
797     static void parse_graphics_prefs(void)
798     {
799     display_type = DISPLAY_WINDOW;
800     dis_width = 512;
801     dis_height = 384;
802 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
803 cebix 1.7 fbdev_name[0] = 0;
804     #endif
805 cebix 1.1
806     const char *str = PrefsFindString("screen");
807     if (str) {
808     if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
809     display_type = DISPLAY_WINDOW;
810 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
811 cebix 1.7 else if (sscanf(str, "dga/%255s", fbdev_name) == 1)
812     #else
813 cebix 1.2 else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
814 cebix 1.7 #endif
815 cebix 1.1 display_type = DISPLAY_SCREEN;
816     }
817     }
818    
819     // Read settings from widgets and set preferences
820     static void read_graphics_settings(void)
821     {
822     const char *str;
823    
824     str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
825     dis_width = atoi(str);
826    
827     str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
828     dis_height = atoi(str);
829    
830     char pref[256];
831     switch (display_type) {
832     case DISPLAY_WINDOW:
833     sprintf(pref, "win/%d/%d", dis_width, dis_height);
834     break;
835     case DISPLAY_SCREEN:
836 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
837 cebix 1.7 str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name));
838     sprintf(pref, "dga/%s", str);
839     #else
840 cebix 1.2 sprintf(pref, "dga/%d/%d", dis_width, dis_height);
841 cebix 1.7 #endif
842 cebix 1.1 break;
843     default:
844     PrefsRemoveItem("screen");
845     return;
846     }
847     PrefsReplaceString("screen", pref);
848 cebix 1.21
849     #ifdef ENABLE_FBDEV_DGA
850     str = get_file_entry_path(w_fbdevice_file);
851     if (str && strlen(str))
852     PrefsReplaceString("fbdevicefile", str);
853     else
854     PrefsRemoveItem("fbdevicefile");
855     #endif
856 cebix 1.24 PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file));
857     PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file));
858 cebix 1.1 }
859    
860     // Create "Graphics/Sound" pane
861     static void create_graphics_pane(GtkWidget *top)
862     {
863 cebix 1.2 GtkWidget *box, *table, *label, *opt, *menu, *combo;
864 cebix 1.1 char str[32];
865    
866     parse_graphics_prefs();
867    
868     box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
869 cebix 1.7 table = make_table(box, 2, 5);
870 cebix 1.1
871     label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
872     gtk_widget_show(label);
873     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
874    
875     opt = gtk_option_menu_new();
876     gtk_widget_show(opt);
877     menu = gtk_menu_new();
878     add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window));
879     add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen));
880     switch (display_type) {
881     case DISPLAY_WINDOW:
882     gtk_menu_set_active(GTK_MENU(menu), 0);
883     break;
884     case DISPLAY_SCREEN:
885     gtk_menu_set_active(GTK_MENU(menu), 1);
886     break;
887     }
888     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
889     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
890    
891     l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
892     gtk_widget_show(l_frameskip);
893     gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
894    
895     w_frameskip = gtk_option_menu_new();
896     gtk_widget_show(w_frameskip);
897     menu = gtk_menu_new();
898     add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
899     add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
900     add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
901     add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
902     add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
903     add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
904 cebix 1.12 add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic));
905 cebix 1.1 int frameskip = PrefsFindInt32("frameskip");
906 cebix 1.12 int item = -1;
907 cebix 1.1 switch (frameskip) {
908 cebix 1.12 case 12: item = 0; break;
909     case 8: item = 1; break;
910     case 6: item = 2; break;
911     case 4: item = 3; break;
912     case 2: item = 4; break;
913     case 1: item = 5; break;
914     case 0: item = 6; break;
915 cebix 1.1 }
916 cebix 1.12 if (item >= 0)
917     gtk_menu_set_active(GTK_MENU(menu), item);
918 cebix 1.1 gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
919     gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
920    
921     l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
922     gtk_widget_show(l_display_x);
923     gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
924    
925 cebix 1.2 combo = gtk_combo_new();
926     gtk_widget_show(combo);
927     GList *glist1 = NULL;
928 cebix 1.4 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
929     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
930     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
931     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
932     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
933 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
934     if (dis_width)
935     sprintf(str, "%d", dis_width);
936     else
937 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
938 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
939     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
940     w_display_x = GTK_COMBO(combo)->entry;
941 cebix 1.1
942     l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
943     gtk_widget_show(l_display_y);
944     gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
945    
946 cebix 1.2 combo = gtk_combo_new();
947     gtk_widget_show(combo);
948     GList *glist2 = NULL;
949 cebix 1.4 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
950     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
951     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
952     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
953     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
954 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
955     if (dis_height)
956     sprintf(str, "%d", dis_height);
957     else
958 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
959 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
960     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
961     w_display_y = GTK_COMBO(combo)->entry;
962 cebix 1.7
963 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
964 cebix 1.7 l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL));
965     gtk_widget_show(l_fbdev_name);
966     gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
967    
968     w_fbdev_name = gtk_entry_new();
969     gtk_widget_show(w_fbdev_name);
970     gtk_entry_set_text(GTK_ENTRY(w_fbdev_name), fbdev_name);
971     gtk_table_attach(GTK_TABLE(table), w_fbdev_name, 1, 2, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
972    
973 cebix 1.21 w_fbdevice_file = make_file_entry(box, STR_FBDEVICE_FILE_CTRL, "fbdevicefile");
974 cebix 1.7 #endif
975 cebix 1.1
976 cebix 1.13 make_separator(box);
977 cebix 1.1 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
978 cebix 1.24 w_dspdevice_file = make_file_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp");
979     w_mixerdevice_file = make_file_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer");
980    
981     set_graphics_sensitive();
982 cebix 1.1
983     hide_show_graphics_widgets();
984     }
985    
986    
987     /*
988 cebix 1.13 * "Input" pane
989     */
990    
991     static GtkWidget *w_keycode_file;
992     static GtkWidget *w_mouse_wheel_lines;
993    
994     // Set sensitivity of widgets
995     static void set_input_sensitive(void)
996     {
997     gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
998 cebix 1.14 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
999 cebix 1.13 }
1000    
1001     // "Use Raw Keycodes" button toggled
1002     static void tb_keycodes(GtkWidget *widget)
1003     {
1004     PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
1005     set_input_sensitive();
1006     }
1007    
1008     // "Mouse Wheel Mode" selected
1009 cebix 1.14 static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
1010     static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
1011 cebix 1.13
1012     // Read settings from widgets and set preferences
1013     static void read_input_settings(void)
1014     {
1015 cebix 1.21 const char *str = get_file_entry_path(w_keycode_file);
1016 cebix 1.13 if (str && strlen(str))
1017     PrefsReplaceString("keycodefile", str);
1018     else
1019     PrefsRemoveItem("keycodefile");
1020    
1021 cebix 1.14 PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
1022 cebix 1.13 }
1023    
1024     // Create "Input" pane
1025     static void create_input_pane(GtkWidget *top)
1026     {
1027     GtkWidget *box, *hbox, *menu, *label;
1028     GtkObject *adj;
1029    
1030     box = make_pane(top, STR_INPUT_PANE_TITLE);
1031    
1032     make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1033 cebix 1.21 w_keycode_file = make_file_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
1034 cebix 1.13
1035     make_separator(box);
1036    
1037     static const opt_desc options[] = {
1038     {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
1039     {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
1040     {0, NULL}
1041     };
1042 cebix 1.14 int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
1043 cebix 1.13 switch (wheelmode) {
1044     case 0: active = 0; break;
1045     case 1: active = 1; break;
1046     }
1047     menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
1048    
1049     hbox = gtk_hbox_new(FALSE, 4);
1050     gtk_widget_show(hbox);
1051     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1052    
1053     label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
1054     gtk_widget_show(label);
1055     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1056    
1057 cebix 1.14 adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
1058 cebix 1.13 w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1059     gtk_widget_show(w_mouse_wheel_lines);
1060     gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
1061    
1062     set_input_sensitive();
1063     }
1064    
1065    
1066     /*
1067 cebix 1.1 * "Serial/Network" pane
1068     */
1069    
1070 cebix 1.18 static GtkWidget *w_seriala, *w_serialb, *w_ether, *w_udp_port;
1071    
1072     // Set sensitivity of widgets
1073     static void set_serial_sensitive(void)
1074     {
1075     #if SUPPORTS_UDP_TUNNEL
1076     gtk_widget_set_sensitive(w_ether, !PrefsFindBool("udptunnel"));
1077     gtk_widget_set_sensitive(w_udp_port, PrefsFindBool("udptunnel"));
1078     #endif
1079     }
1080    
1081     // "Tunnel AppleTalk over IP" button toggled
1082     static void tb_udptunnel(GtkWidget *widget)
1083     {
1084     PrefsReplaceBool("udptunnel", GTK_TOGGLE_BUTTON(widget)->active);
1085     set_serial_sensitive();
1086     }
1087 cebix 1.1
1088     // Read settings from widgets and set preferences
1089     static void read_serial_settings(void)
1090     {
1091     const char *str;
1092    
1093     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1094     PrefsReplaceString("seriala", str);
1095    
1096     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1097     PrefsReplaceString("serialb", str);
1098    
1099     str = gtk_entry_get_text(GTK_ENTRY(w_ether));
1100     if (str && strlen(str))
1101     PrefsReplaceString("ether", str);
1102     else
1103     PrefsRemoveItem("ether");
1104 cebix 1.18
1105     #if SUPPORTS_UDP_TUNNEL
1106     PrefsReplaceInt32("udpport", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_udp_port)));
1107     #endif
1108 cebix 1.1 }
1109    
1110     // Add names of serial devices
1111     static gint gl_str_cmp(gconstpointer a, gconstpointer b)
1112     {
1113     return strcmp((char *)a, (char *)b);
1114     }
1115    
1116     static GList *add_serial_names(void)
1117     {
1118     GList *glist = NULL;
1119    
1120     // Search /dev for ttyS* and lp*
1121     DIR *d = opendir("/dev");
1122     if (d) {
1123     struct dirent *de;
1124     while ((de = readdir(d)) != NULL) {
1125     #if defined(__linux__)
1126     if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
1127     #elif defined(__FreeBSD__)
1128     if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1129 cebix 1.4 #elif defined(__NetBSD__)
1130     if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1131 cebix 1.1 #elif defined(sgi)
1132     if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) {
1133     #else
1134     if (false) {
1135     #endif
1136     char *str = new char[64];
1137     sprintf(str, "/dev/%s", de->d_name);
1138     glist = g_list_append(glist, str);
1139     }
1140     }
1141     closedir(d);
1142     }
1143     if (glist)
1144     g_list_sort(glist, gl_str_cmp);
1145     else
1146 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1147 cebix 1.1 return glist;
1148     }
1149    
1150     // Add names of ethernet interfaces
1151     static GList *add_ether_names(void)
1152     {
1153     GList *glist = NULL;
1154    
1155     // Get list of all Ethernet interfaces
1156     int s = socket(PF_INET, SOCK_DGRAM, 0);
1157     if (s >= 0) {
1158     char inbuf[8192];
1159     struct ifconf ifc;
1160     ifc.ifc_len = sizeof(inbuf);
1161     ifc.ifc_buf = inbuf;
1162     if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
1163     struct ifreq req, *ifr = ifc.ifc_req;
1164     for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
1165     req = *ifr;
1166 cebix 1.4 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(sgi)
1167 cebix 1.1 if (ioctl(s, SIOCGIFADDR, &req) == 0 && (req.ifr_addr.sa_family == ARPHRD_ETHER || req.ifr_addr.sa_family == ARPHRD_ETHER+1)) {
1168 cebix 1.4 #elif defined(__linux__)
1169     if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
1170 cebix 1.1 #else
1171 cebix 1.4 if (false) {
1172 cebix 1.1 #endif
1173     char *str = new char[64];
1174     strncpy(str, ifr->ifr_name, 63);
1175     glist = g_list_append(glist, str);
1176     }
1177     }
1178     }
1179     close(s);
1180     }
1181 gbeauche 1.27 #ifdef HAVE_SLIRP
1182     static char s_slirp[] = "slirp";
1183     glist = g_list_append(glist, s_slirp);
1184     #endif
1185 cebix 1.1 if (glist)
1186     g_list_sort(glist, gl_str_cmp);
1187     else
1188 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1189 cebix 1.1 return glist;
1190     }
1191    
1192     // Create "Serial/Network" pane
1193     static void create_serial_pane(GtkWidget *top)
1194     {
1195 cebix 1.18 GtkWidget *box, *hbox, *table, *label, *combo, *sep;
1196     GtkObject *adj;
1197 cebix 1.1
1198     box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
1199 cebix 1.13 table = make_table(box, 2, 4);
1200 cebix 1.1
1201     label = gtk_label_new(GetString(STR_SERIALA_CTRL));
1202     gtk_widget_show(label);
1203     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1204    
1205 cebix 1.18 GList *glist = add_serial_names();
1206 cebix 1.1 combo = gtk_combo_new();
1207     gtk_widget_show(combo);
1208     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1209     const char *str = PrefsFindString("seriala");
1210     if (str == NULL)
1211     str = "";
1212     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1213     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1214     w_seriala = GTK_COMBO(combo)->entry;
1215    
1216     label = gtk_label_new(GetString(STR_SERIALB_CTRL));
1217     gtk_widget_show(label);
1218     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1219    
1220     combo = gtk_combo_new();
1221     gtk_widget_show(combo);
1222     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1223     str = PrefsFindString("serialb");
1224     if (str == NULL)
1225     str = "";
1226     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1227     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1228     w_serialb = GTK_COMBO(combo)->entry;
1229    
1230 cebix 1.13 sep = gtk_hseparator_new();
1231     gtk_widget_show(sep);
1232     gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1233    
1234 cebix 1.1 label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1235     gtk_widget_show(label);
1236 cebix 1.13 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1237 cebix 1.1
1238     glist = add_ether_names();
1239     combo = gtk_combo_new();
1240     gtk_widget_show(combo);
1241     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1242     str = PrefsFindString("ether");
1243     if (str == NULL)
1244     str = "";
1245     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1246 cebix 1.13 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1247 cebix 1.1 w_ether = GTK_COMBO(combo)->entry;
1248 cebix 1.18
1249     #if SUPPORTS_UDP_TUNNEL
1250     make_checkbox(box, STR_UDPTUNNEL_CTRL, "udptunnel", GTK_SIGNAL_FUNC(tb_udptunnel));
1251    
1252     hbox = gtk_hbox_new(FALSE, 4);
1253     gtk_widget_show(hbox);
1254     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1255    
1256     label = gtk_label_new(GetString(STR_UDPPORT_CTRL));
1257     gtk_widget_show(label);
1258     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1259    
1260     adj = gtk_adjustment_new(PrefsFindInt32("udpport"), 1, 65535, 1, 5, 0);
1261     w_udp_port = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1262     gtk_widget_show(w_udp_port);
1263     gtk_box_pack_start(GTK_BOX(hbox), w_udp_port, FALSE, FALSE, 0);
1264     #endif
1265    
1266     set_serial_sensitive();
1267 cebix 1.1 }
1268    
1269    
1270     /*
1271     * "Memory/Misc" pane
1272     */
1273    
1274     static GtkObject *w_ramsize_adj;
1275     static GtkWidget *w_rom_file;
1276    
1277 gbeauche 1.22 // "Ignore SEGV" button toggled
1278     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1279     static void tb_ignoresegv(GtkWidget *widget)
1280     {
1281     PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1282     }
1283     #endif
1284    
1285 cebix 1.1 // Model ID selected
1286     static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1287     static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1288    
1289 cebix 1.9 // CPU/FPU type
1290     static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1291     static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1292     static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1293     static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1294     static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1295 cebix 1.8
1296 cebix 1.1 // Read settings from widgets and set preferences
1297     static void read_memory_settings(void)
1298     {
1299     PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
1300    
1301 cebix 1.21 const char *str = get_file_entry_path(w_rom_file);
1302 cebix 1.1 if (str && strlen(str))
1303     PrefsReplaceString("rom", str);
1304     else
1305     PrefsRemoveItem("rom");
1306    
1307     }
1308    
1309     // Create "Memory/Misc" pane
1310     static void create_memory_pane(GtkWidget *top)
1311     {
1312 cebix 1.17 GtkWidget *box, *hbox, *vbox, *hbox2, *label, *scale;
1313 cebix 1.1
1314     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1315    
1316     hbox = gtk_hbox_new(FALSE, 4);
1317     gtk_widget_show(hbox);
1318    
1319     label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1320     gtk_widget_show(label);
1321     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1322    
1323     vbox = gtk_vbox_new(FALSE, 4);
1324     gtk_widget_show(vbox);
1325    
1326     gfloat min, max;
1327     min = 1;
1328     max = 1024;
1329     w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1330     gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1331    
1332     scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1333     gtk_widget_show(scale);
1334     gtk_scale_set_digits(GTK_SCALE(scale), 0);
1335     gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1336    
1337     hbox2 = gtk_hbox_new(FALSE, 4);
1338     gtk_widget_show(hbox2);
1339    
1340     char val[32];
1341     sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1342     label = gtk_label_new(val);
1343     gtk_widget_show(label);
1344     gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1345    
1346     sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1347     label = gtk_label_new(val);
1348     gtk_widget_show(label);
1349     gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1350     gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1351     gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1352     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1353    
1354 cebix 1.9 static const opt_desc model_options[] = {
1355 cebix 1.1 {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1356     {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1357     {0, NULL}
1358     };
1359     int modelid = PrefsFindInt32("modelid"), active = 0;
1360     switch (modelid) {
1361     case 5: active = 0; break;
1362     case 14: active = 1; break;
1363     }
1364 cebix 1.9 make_option_menu(box, STR_MODELID_CTRL, model_options, active);
1365    
1366 cebix 1.11 #if EMULATED_68K
1367 cebix 1.9 static const opt_desc cpu_options[] = {
1368     {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1369     {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1370     {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1371     {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1372     {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1373     {0, NULL}
1374     };
1375     int cpu = PrefsFindInt32("cpu");
1376     bool fpu = PrefsFindBool("fpu");
1377     active = 0;
1378     switch (cpu) {
1379     case 2: active = fpu ? 1 : 0; break;
1380     case 3: active = fpu ? 3 : 2; break;
1381     case 4: active = 4;
1382     }
1383     make_option_menu(box, STR_CPU_CTRL, cpu_options, active);
1384 cebix 1.11 #endif
1385 cebix 1.1
1386 cebix 1.21 w_rom_file = make_file_entry(box, STR_ROM_FILE_CTRL, "rom");
1387 gbeauche 1.22
1388     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1389     make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1390     #endif
1391 cebix 1.1 }
1392    
1393    
1394     /*
1395     * Read settings from widgets and set preferences
1396     */
1397    
1398     static void read_settings(void)
1399     {
1400     read_volumes_settings();
1401     read_scsi_settings();
1402     read_graphics_settings();
1403 cebix 1.13 read_input_settings();
1404 cebix 1.1 read_serial_settings();
1405     read_memory_settings();
1406 gbeauche 1.23 read_jit_settings();
1407 cebix 1.1 }