ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
Revision: 1.27
Committed: 2005-06-06T20:11:50Z (19 years, 1 month ago) by gbeauche
Branch: MAIN
Changes since 1.26: +16 -1 lines
Log Message:
Update GTK Prefs Editor with support for "jitinline" and "slirp" ethernet.

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 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 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     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 gbeauche 1.27 static GtkWidget *w_jit_follow_const_jumps;
593 gbeauche 1.23
594     // Set sensitivity of widgets
595     static void set_jit_sensitive(void)
596     {
597     const bool jit_enabled = PrefsFindBool("jit");
598     gtk_widget_set_sensitive(w_jit_fpu, jit_enabled);
599     gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled);
600     gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled);
601 gbeauche 1.27 gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled);
602 gbeauche 1.23 }
603    
604     // "Use JIT Compiler" button toggled
605     static void tb_jit(GtkWidget *widget)
606     {
607     PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active);
608     set_jit_sensitive();
609     }
610    
611     // "Compile FPU Instructions" button toggled
612     static void tb_jit_fpu(GtkWidget *widget)
613     {
614     PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active);
615     }
616    
617     // "Lazy translation cache invalidation" button toggled
618     static void tb_jit_lazy_flush(GtkWidget *widget)
619     {
620     PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active);
621     }
622    
623 gbeauche 1.27 // "Translate through constant jumps (inline blocks)" button toggled
624     static void tb_jit_follow_const_jumps(GtkWidget *widget)
625     {
626     PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active);
627     }
628    
629 gbeauche 1.23 // Read settings from widgets and set preferences
630     static void read_jit_settings(void)
631     {
632     #if USE_JIT
633     bool jit_enabled = PrefsFindBool("jit");
634     if (jit_enabled) {
635     const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
636     PrefsReplaceInt32("jitcachesize", atoi(str));
637     }
638     #endif
639     }
640    
641     // Create "JIT Compiler" pane
642     static void create_jit_pane(GtkWidget *top)
643     {
644     #if USE_JIT
645     GtkWidget *box, *table, *label, *menu;
646     char str[32];
647    
648     box = make_pane(top, STR_JIT_PANE_TITLE);
649     make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
650    
651     w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu));
652    
653     // Translation cache size
654     static const combo_desc options[] = {
655     STR_JIT_CACHE_SIZE_2MB_LAB,
656     STR_JIT_CACHE_SIZE_4MB_LAB,
657     STR_JIT_CACHE_SIZE_8MB_LAB,
658     STR_JIT_CACHE_SIZE_16MB_LAB,
659     0
660     };
661     w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, "jitcachesize", options);
662    
663     // Lazy translation cache invalidation
664     w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush));
665 gbeauche 1.27
666     // Follow constant jumps (inline basic blocks)
667     w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
668    
669 gbeauche 1.23 set_jit_sensitive();
670     #endif
671     }
672    
673     /*
674 cebix 1.1 * "SCSI" pane
675     */
676    
677     static GtkWidget *w_scsi[7];
678    
679     // Read settings from widgets and set preferences
680     static void read_scsi_settings(void)
681     {
682     for (int id=0; id<7; id++) {
683     char prefs_name[32];
684     sprintf(prefs_name, "scsi%d", id);
685 cebix 1.21 const char *str = get_file_entry_path(w_scsi[id]);
686 cebix 1.1 if (str && strlen(str))
687     PrefsReplaceString(prefs_name, str);
688     else
689     PrefsRemoveItem(prefs_name);
690     }
691     }
692    
693     // Create "SCSI" pane
694     static void create_scsi_pane(GtkWidget *top)
695     {
696     GtkWidget *box;
697    
698     box = make_pane(top, STR_SCSI_PANE_TITLE);
699    
700     for (int id=0; id<7; id++) {
701     char prefs_name[32];
702     sprintf(prefs_name, "scsi%d", id);
703 cebix 1.21 w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name);
704 cebix 1.1 }
705     }
706    
707    
708     /*
709     * "Graphics/Sound" pane
710     */
711    
712     // Display types
713     enum {
714     DISPLAY_WINDOW,
715     DISPLAY_SCREEN
716     };
717    
718     static GtkWidget *w_frameskip, *w_display_x, *w_display_y;
719     static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
720     static int display_type;
721     static int dis_width, dis_height;
722    
723 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
724 cebix 1.7 static GtkWidget *w_fbdev_name, *w_fbdevice_file;
725     static GtkWidget *l_fbdev_name, *l_fbdevice_file;
726     static char fbdev_name[256];
727     #endif
728    
729 cebix 1.24 static GtkWidget *w_dspdevice_file, *w_mixerdevice_file;
730    
731 cebix 1.1 // Hide/show graphics widgets
732     static void hide_show_graphics_widgets(void)
733     {
734     switch (display_type) {
735     case DISPLAY_WINDOW:
736     gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
737 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
738 cebix 1.7 gtk_widget_show(w_display_x); gtk_widget_show(l_display_x);
739     gtk_widget_show(w_display_y); gtk_widget_show(l_display_y);
740     gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name);
741     #endif
742 cebix 1.1 break;
743     case DISPLAY_SCREEN:
744     gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
745 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
746 cebix 1.7 gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x);
747     gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y);
748     gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name);
749     #endif
750 cebix 1.1 break;
751     }
752     }
753    
754     // "Window" video type selected
755     static void mn_window(...)
756     {
757     display_type = DISPLAY_WINDOW;
758     hide_show_graphics_widgets();
759     }
760    
761     // "Fullscreen" video type selected
762     static void mn_fullscreen(...)
763     {
764     display_type = DISPLAY_SCREEN;
765     hide_show_graphics_widgets();
766     }
767    
768     // "5 Hz".."60Hz" selected
769     static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
770     static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
771     static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
772     static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
773     static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
774     static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
775 cebix 1.12 static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
776 cebix 1.1
777 cebix 1.24 // Set sensitivity of widgets
778     static void set_graphics_sensitive(void)
779     {
780     const bool sound_enabled = !PrefsFindBool("nosound");
781     gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled);
782     gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled);
783     }
784    
785 cebix 1.1 // "Disable Sound Output" button toggled
786     static void tb_nosound(GtkWidget *widget)
787     {
788     PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
789 cebix 1.24 set_graphics_sensitive();
790 cebix 1.1 }
791    
792     // Read graphics preferences
793     static void parse_graphics_prefs(void)
794     {
795     display_type = DISPLAY_WINDOW;
796     dis_width = 512;
797     dis_height = 384;
798 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
799 cebix 1.7 fbdev_name[0] = 0;
800     #endif
801 cebix 1.1
802     const char *str = PrefsFindString("screen");
803     if (str) {
804     if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
805     display_type = DISPLAY_WINDOW;
806 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
807 cebix 1.7 else if (sscanf(str, "dga/%255s", fbdev_name) == 1)
808     #else
809 cebix 1.2 else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
810 cebix 1.7 #endif
811 cebix 1.1 display_type = DISPLAY_SCREEN;
812     }
813     }
814    
815     // Read settings from widgets and set preferences
816     static void read_graphics_settings(void)
817     {
818     const char *str;
819    
820     str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
821     dis_width = atoi(str);
822    
823     str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
824     dis_height = atoi(str);
825    
826     char pref[256];
827     switch (display_type) {
828     case DISPLAY_WINDOW:
829     sprintf(pref, "win/%d/%d", dis_width, dis_height);
830     break;
831     case DISPLAY_SCREEN:
832 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
833 cebix 1.7 str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name));
834     sprintf(pref, "dga/%s", str);
835     #else
836 cebix 1.2 sprintf(pref, "dga/%d/%d", dis_width, dis_height);
837 cebix 1.7 #endif
838 cebix 1.1 break;
839     default:
840     PrefsRemoveItem("screen");
841     return;
842     }
843     PrefsReplaceString("screen", pref);
844 cebix 1.21
845     #ifdef ENABLE_FBDEV_DGA
846     str = get_file_entry_path(w_fbdevice_file);
847     if (str && strlen(str))
848     PrefsReplaceString("fbdevicefile", str);
849     else
850     PrefsRemoveItem("fbdevicefile");
851     #endif
852 cebix 1.24 PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file));
853     PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file));
854 cebix 1.1 }
855    
856     // Create "Graphics/Sound" pane
857     static void create_graphics_pane(GtkWidget *top)
858     {
859 cebix 1.2 GtkWidget *box, *table, *label, *opt, *menu, *combo;
860 cebix 1.1 char str[32];
861    
862     parse_graphics_prefs();
863    
864     box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
865 cebix 1.7 table = make_table(box, 2, 5);
866 cebix 1.1
867     label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
868     gtk_widget_show(label);
869     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
870    
871     opt = gtk_option_menu_new();
872     gtk_widget_show(opt);
873     menu = gtk_menu_new();
874     add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window));
875     add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen));
876     switch (display_type) {
877     case DISPLAY_WINDOW:
878     gtk_menu_set_active(GTK_MENU(menu), 0);
879     break;
880     case DISPLAY_SCREEN:
881     gtk_menu_set_active(GTK_MENU(menu), 1);
882     break;
883     }
884     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
885     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
886    
887     l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
888     gtk_widget_show(l_frameskip);
889     gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
890    
891     w_frameskip = gtk_option_menu_new();
892     gtk_widget_show(w_frameskip);
893     menu = gtk_menu_new();
894     add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
895     add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
896     add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
897     add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
898     add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
899     add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
900 cebix 1.12 add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic));
901 cebix 1.1 int frameskip = PrefsFindInt32("frameskip");
902 cebix 1.12 int item = -1;
903 cebix 1.1 switch (frameskip) {
904 cebix 1.12 case 12: item = 0; break;
905     case 8: item = 1; break;
906     case 6: item = 2; break;
907     case 4: item = 3; break;
908     case 2: item = 4; break;
909     case 1: item = 5; break;
910     case 0: item = 6; break;
911 cebix 1.1 }
912 cebix 1.12 if (item >= 0)
913     gtk_menu_set_active(GTK_MENU(menu), item);
914 cebix 1.1 gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
915     gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
916    
917     l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
918     gtk_widget_show(l_display_x);
919     gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
920    
921 cebix 1.2 combo = gtk_combo_new();
922     gtk_widget_show(combo);
923     GList *glist1 = NULL;
924 cebix 1.4 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
925     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
926     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
927     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
928     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
929 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
930     if (dis_width)
931     sprintf(str, "%d", dis_width);
932     else
933 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
934 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
935     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
936     w_display_x = GTK_COMBO(combo)->entry;
937 cebix 1.1
938     l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
939     gtk_widget_show(l_display_y);
940     gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
941    
942 cebix 1.2 combo = gtk_combo_new();
943     gtk_widget_show(combo);
944     GList *glist2 = NULL;
945 cebix 1.4 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
946     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
947     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
948     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
949     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
950 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
951     if (dis_height)
952     sprintf(str, "%d", dis_height);
953     else
954 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
955 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
956     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
957     w_display_y = GTK_COMBO(combo)->entry;
958 cebix 1.7
959 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
960 cebix 1.7 l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL));
961     gtk_widget_show(l_fbdev_name);
962     gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
963    
964     w_fbdev_name = gtk_entry_new();
965     gtk_widget_show(w_fbdev_name);
966     gtk_entry_set_text(GTK_ENTRY(w_fbdev_name), fbdev_name);
967     gtk_table_attach(GTK_TABLE(table), w_fbdev_name, 1, 2, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
968    
969 cebix 1.21 w_fbdevice_file = make_file_entry(box, STR_FBDEVICE_FILE_CTRL, "fbdevicefile");
970 cebix 1.7 #endif
971 cebix 1.1
972 cebix 1.13 make_separator(box);
973 cebix 1.1 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
974 cebix 1.24 w_dspdevice_file = make_file_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp");
975     w_mixerdevice_file = make_file_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer");
976    
977     set_graphics_sensitive();
978 cebix 1.1
979     hide_show_graphics_widgets();
980     }
981    
982    
983     /*
984 cebix 1.13 * "Input" pane
985     */
986    
987     static GtkWidget *w_keycode_file;
988     static GtkWidget *w_mouse_wheel_lines;
989    
990     // Set sensitivity of widgets
991     static void set_input_sensitive(void)
992     {
993     gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
994 cebix 1.14 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
995 cebix 1.13 }
996    
997     // "Use Raw Keycodes" button toggled
998     static void tb_keycodes(GtkWidget *widget)
999     {
1000     PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
1001     set_input_sensitive();
1002     }
1003    
1004     // "Mouse Wheel Mode" selected
1005 cebix 1.14 static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
1006     static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
1007 cebix 1.13
1008     // Read settings from widgets and set preferences
1009     static void read_input_settings(void)
1010     {
1011 cebix 1.21 const char *str = get_file_entry_path(w_keycode_file);
1012 cebix 1.13 if (str && strlen(str))
1013     PrefsReplaceString("keycodefile", str);
1014     else
1015     PrefsRemoveItem("keycodefile");
1016    
1017 cebix 1.14 PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
1018 cebix 1.13 }
1019    
1020     // Create "Input" pane
1021     static void create_input_pane(GtkWidget *top)
1022     {
1023     GtkWidget *box, *hbox, *menu, *label;
1024     GtkObject *adj;
1025    
1026     box = make_pane(top, STR_INPUT_PANE_TITLE);
1027    
1028     make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1029 cebix 1.21 w_keycode_file = make_file_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
1030 cebix 1.13
1031     make_separator(box);
1032    
1033     static const opt_desc options[] = {
1034     {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
1035     {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
1036     {0, NULL}
1037     };
1038 cebix 1.14 int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
1039 cebix 1.13 switch (wheelmode) {
1040     case 0: active = 0; break;
1041     case 1: active = 1; break;
1042     }
1043     menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
1044    
1045     hbox = gtk_hbox_new(FALSE, 4);
1046     gtk_widget_show(hbox);
1047     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1048    
1049     label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
1050     gtk_widget_show(label);
1051     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1052    
1053 cebix 1.14 adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
1054 cebix 1.13 w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1055     gtk_widget_show(w_mouse_wheel_lines);
1056     gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
1057    
1058     set_input_sensitive();
1059     }
1060    
1061    
1062     /*
1063 cebix 1.1 * "Serial/Network" pane
1064     */
1065    
1066 cebix 1.18 static GtkWidget *w_seriala, *w_serialb, *w_ether, *w_udp_port;
1067    
1068     // Set sensitivity of widgets
1069     static void set_serial_sensitive(void)
1070     {
1071     #if SUPPORTS_UDP_TUNNEL
1072     gtk_widget_set_sensitive(w_ether, !PrefsFindBool("udptunnel"));
1073     gtk_widget_set_sensitive(w_udp_port, PrefsFindBool("udptunnel"));
1074     #endif
1075     }
1076    
1077     // "Tunnel AppleTalk over IP" button toggled
1078     static void tb_udptunnel(GtkWidget *widget)
1079     {
1080     PrefsReplaceBool("udptunnel", GTK_TOGGLE_BUTTON(widget)->active);
1081     set_serial_sensitive();
1082     }
1083 cebix 1.1
1084     // Read settings from widgets and set preferences
1085     static void read_serial_settings(void)
1086     {
1087     const char *str;
1088    
1089     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1090     PrefsReplaceString("seriala", str);
1091    
1092     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1093     PrefsReplaceString("serialb", str);
1094    
1095     str = gtk_entry_get_text(GTK_ENTRY(w_ether));
1096     if (str && strlen(str))
1097     PrefsReplaceString("ether", str);
1098     else
1099     PrefsRemoveItem("ether");
1100 cebix 1.18
1101     #if SUPPORTS_UDP_TUNNEL
1102     PrefsReplaceInt32("udpport", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_udp_port)));
1103     #endif
1104 cebix 1.1 }
1105    
1106     // Add names of serial devices
1107     static gint gl_str_cmp(gconstpointer a, gconstpointer b)
1108     {
1109     return strcmp((char *)a, (char *)b);
1110     }
1111    
1112     static GList *add_serial_names(void)
1113     {
1114     GList *glist = NULL;
1115    
1116     // Search /dev for ttyS* and lp*
1117     DIR *d = opendir("/dev");
1118     if (d) {
1119     struct dirent *de;
1120     while ((de = readdir(d)) != NULL) {
1121     #if defined(__linux__)
1122     if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
1123     #elif defined(__FreeBSD__)
1124     if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1125 cebix 1.4 #elif defined(__NetBSD__)
1126     if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1127 cebix 1.1 #elif defined(sgi)
1128     if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) {
1129     #else
1130     if (false) {
1131     #endif
1132     char *str = new char[64];
1133     sprintf(str, "/dev/%s", de->d_name);
1134     glist = g_list_append(glist, str);
1135     }
1136     }
1137     closedir(d);
1138     }
1139     if (glist)
1140     g_list_sort(glist, gl_str_cmp);
1141     else
1142 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1143 cebix 1.1 return glist;
1144     }
1145    
1146     // Add names of ethernet interfaces
1147     static GList *add_ether_names(void)
1148     {
1149     GList *glist = NULL;
1150    
1151     // Get list of all Ethernet interfaces
1152     int s = socket(PF_INET, SOCK_DGRAM, 0);
1153     if (s >= 0) {
1154     char inbuf[8192];
1155     struct ifconf ifc;
1156     ifc.ifc_len = sizeof(inbuf);
1157     ifc.ifc_buf = inbuf;
1158     if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
1159     struct ifreq req, *ifr = ifc.ifc_req;
1160     for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
1161     req = *ifr;
1162 cebix 1.4 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(sgi)
1163 cebix 1.1 if (ioctl(s, SIOCGIFADDR, &req) == 0 && (req.ifr_addr.sa_family == ARPHRD_ETHER || req.ifr_addr.sa_family == ARPHRD_ETHER+1)) {
1164 cebix 1.4 #elif defined(__linux__)
1165     if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
1166 cebix 1.1 #else
1167 cebix 1.4 if (false) {
1168 cebix 1.1 #endif
1169     char *str = new char[64];
1170     strncpy(str, ifr->ifr_name, 63);
1171     glist = g_list_append(glist, str);
1172     }
1173     }
1174     }
1175     close(s);
1176     }
1177 gbeauche 1.27 #ifdef HAVE_SLIRP
1178     static char s_slirp[] = "slirp";
1179     glist = g_list_append(glist, s_slirp);
1180     #endif
1181 cebix 1.1 if (glist)
1182     g_list_sort(glist, gl_str_cmp);
1183     else
1184 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1185 cebix 1.1 return glist;
1186     }
1187    
1188     // Create "Serial/Network" pane
1189     static void create_serial_pane(GtkWidget *top)
1190     {
1191 cebix 1.18 GtkWidget *box, *hbox, *table, *label, *combo, *sep;
1192     GtkObject *adj;
1193 cebix 1.1
1194     box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
1195 cebix 1.13 table = make_table(box, 2, 4);
1196 cebix 1.1
1197     label = gtk_label_new(GetString(STR_SERIALA_CTRL));
1198     gtk_widget_show(label);
1199     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1200    
1201 cebix 1.18 GList *glist = add_serial_names();
1202 cebix 1.1 combo = gtk_combo_new();
1203     gtk_widget_show(combo);
1204     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1205     const char *str = PrefsFindString("seriala");
1206     if (str == NULL)
1207     str = "";
1208     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1209     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1210     w_seriala = GTK_COMBO(combo)->entry;
1211    
1212     label = gtk_label_new(GetString(STR_SERIALB_CTRL));
1213     gtk_widget_show(label);
1214     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1215    
1216     combo = gtk_combo_new();
1217     gtk_widget_show(combo);
1218     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1219     str = PrefsFindString("serialb");
1220     if (str == NULL)
1221     str = "";
1222     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1223     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1224     w_serialb = GTK_COMBO(combo)->entry;
1225    
1226 cebix 1.13 sep = gtk_hseparator_new();
1227     gtk_widget_show(sep);
1228     gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1229    
1230 cebix 1.1 label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1231     gtk_widget_show(label);
1232 cebix 1.13 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1233 cebix 1.1
1234     glist = add_ether_names();
1235     combo = gtk_combo_new();
1236     gtk_widget_show(combo);
1237     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1238     str = PrefsFindString("ether");
1239     if (str == NULL)
1240     str = "";
1241     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1242 cebix 1.13 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1243 cebix 1.1 w_ether = GTK_COMBO(combo)->entry;
1244 cebix 1.18
1245     #if SUPPORTS_UDP_TUNNEL
1246     make_checkbox(box, STR_UDPTUNNEL_CTRL, "udptunnel", GTK_SIGNAL_FUNC(tb_udptunnel));
1247    
1248     hbox = gtk_hbox_new(FALSE, 4);
1249     gtk_widget_show(hbox);
1250     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1251    
1252     label = gtk_label_new(GetString(STR_UDPPORT_CTRL));
1253     gtk_widget_show(label);
1254     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1255    
1256     adj = gtk_adjustment_new(PrefsFindInt32("udpport"), 1, 65535, 1, 5, 0);
1257     w_udp_port = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1258     gtk_widget_show(w_udp_port);
1259     gtk_box_pack_start(GTK_BOX(hbox), w_udp_port, FALSE, FALSE, 0);
1260     #endif
1261    
1262     set_serial_sensitive();
1263 cebix 1.1 }
1264    
1265    
1266     /*
1267     * "Memory/Misc" pane
1268     */
1269    
1270     static GtkObject *w_ramsize_adj;
1271     static GtkWidget *w_rom_file;
1272    
1273 gbeauche 1.22 // "Ignore SEGV" button toggled
1274     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1275     static void tb_ignoresegv(GtkWidget *widget)
1276     {
1277     PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1278     }
1279     #endif
1280    
1281 cebix 1.1 // Model ID selected
1282     static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1283     static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1284    
1285 cebix 1.9 // CPU/FPU type
1286     static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1287     static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1288     static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1289     static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1290     static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1291 cebix 1.8
1292 cebix 1.1 // Read settings from widgets and set preferences
1293     static void read_memory_settings(void)
1294     {
1295     PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
1296    
1297 cebix 1.21 const char *str = get_file_entry_path(w_rom_file);
1298 cebix 1.1 if (str && strlen(str))
1299     PrefsReplaceString("rom", str);
1300     else
1301     PrefsRemoveItem("rom");
1302    
1303     }
1304    
1305     // Create "Memory/Misc" pane
1306     static void create_memory_pane(GtkWidget *top)
1307     {
1308 cebix 1.17 GtkWidget *box, *hbox, *vbox, *hbox2, *label, *scale;
1309 cebix 1.1
1310     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1311    
1312     hbox = gtk_hbox_new(FALSE, 4);
1313     gtk_widget_show(hbox);
1314    
1315     label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1316     gtk_widget_show(label);
1317     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1318    
1319     vbox = gtk_vbox_new(FALSE, 4);
1320     gtk_widget_show(vbox);
1321    
1322     gfloat min, max;
1323     min = 1;
1324     max = 1024;
1325     w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1326     gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1327    
1328     scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1329     gtk_widget_show(scale);
1330     gtk_scale_set_digits(GTK_SCALE(scale), 0);
1331     gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1332    
1333     hbox2 = gtk_hbox_new(FALSE, 4);
1334     gtk_widget_show(hbox2);
1335    
1336     char val[32];
1337     sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1338     label = gtk_label_new(val);
1339     gtk_widget_show(label);
1340     gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1341    
1342     sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1343     label = gtk_label_new(val);
1344     gtk_widget_show(label);
1345     gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1346     gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1347     gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1348     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1349    
1350 cebix 1.9 static const opt_desc model_options[] = {
1351 cebix 1.1 {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1352     {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1353     {0, NULL}
1354     };
1355     int modelid = PrefsFindInt32("modelid"), active = 0;
1356     switch (modelid) {
1357     case 5: active = 0; break;
1358     case 14: active = 1; break;
1359     }
1360 cebix 1.9 make_option_menu(box, STR_MODELID_CTRL, model_options, active);
1361    
1362 cebix 1.11 #if EMULATED_68K
1363 cebix 1.9 static const opt_desc cpu_options[] = {
1364     {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1365     {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1366     {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1367     {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1368     {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1369     {0, NULL}
1370     };
1371     int cpu = PrefsFindInt32("cpu");
1372     bool fpu = PrefsFindBool("fpu");
1373     active = 0;
1374     switch (cpu) {
1375     case 2: active = fpu ? 1 : 0; break;
1376     case 3: active = fpu ? 3 : 2; break;
1377     case 4: active = 4;
1378     }
1379     make_option_menu(box, STR_CPU_CTRL, cpu_options, active);
1380 cebix 1.11 #endif
1381 cebix 1.1
1382 cebix 1.21 w_rom_file = make_file_entry(box, STR_ROM_FILE_CTRL, "rom");
1383 gbeauche 1.22
1384     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1385     make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1386     #endif
1387 cebix 1.1 }
1388    
1389    
1390     /*
1391     * Read settings from widgets and set preferences
1392     */
1393    
1394     static void read_settings(void)
1395     {
1396     read_volumes_settings();
1397     read_scsi_settings();
1398     read_graphics_settings();
1399 cebix 1.13 read_input_settings();
1400 cebix 1.1 read_serial_settings();
1401     read_memory_settings();
1402 gbeauche 1.23 read_jit_settings();
1403 cebix 1.1 }