ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/prefs_editor_gtk.cpp
Revision: 1.12
Committed: 2006-04-29T14:15:01Z (18 years, 1 month ago) by gbeauche
Branch: MAIN
Changes since 1.11: +12 -0 lines
Log Message:
update GUI with ether "slirp" on win32

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * prefs_editor_gtk.cpp - Preferences editor, Unix implementation using GTK+
3     *
4     * Basilisk II (C) 1997-2005 Christian Bauer
5     *
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 gbeauche 1.5 #include <stdlib.h>
24     #include <string.h>
25 gbeauche 1.4 #include <fcntl.h>
26     #include <sys/stat.h>
27 gbeauche 1.1 #include <gtk/gtk.h>
28    
29     #include "user_strings.h"
30     #include "version.h"
31     #include "cdrom.h"
32     #include "xpram.h"
33     #include "prefs.h"
34     #include "prefs_editor.h"
35 gbeauche 1.11 #include "util_windows.h"
36 gbeauche 1.10 #include "b2ether/inc/b2ether_hl.h"
37 gbeauche 1.1
38    
39     // Global variables
40     static GtkWidget *win; // Preferences window
41     static bool start_clicked = true; // Return value of PrefsEditor() function
42    
43    
44     // Prototypes
45     static void create_volumes_pane(GtkWidget *top);
46     static void create_scsi_pane(GtkWidget *top);
47     static void create_graphics_pane(GtkWidget *top);
48     static void create_input_pane(GtkWidget *top);
49     static void create_serial_pane(GtkWidget *top);
50     static void create_ethernet_pane(GtkWidget *top);
51     static void create_memory_pane(GtkWidget *top);
52     static void create_jit_pane(GtkWidget *top);
53     static void read_settings(void);
54    
55    
56     /*
57 gbeauche 1.8 * SheepShaver glue
58     */
59    
60     #ifdef SHEEPSHAVER
61     #define DISABLE_SCSI 1
62     #define PROGRAM_NAME "SheepShaver"
63     enum {
64     STR_WINDOW_LAB = STR_WINDOW_CTRL,
65     STR_FULLSCREEN_LAB = STR_FULLSCREEN_CTRL,
66     STR_SERIALA_CTRL = STR_SERPORTA_CTRL,
67     STR_SERIALB_CTRL = STR_SERPORTB_CTRL,
68     };
69     #else
70 gbeauche 1.11 #define DISABLE_SCSI 1 /* XXX merge code from original Basilisk II for Windows */
71 gbeauche 1.8 #define PROGRAM_NAME "BasiliskII"
72     #endif
73    
74    
75     /*
76 gbeauche 1.1 * Utility functions
77     */
78    
79     struct opt_desc {
80     int label_id;
81     GtkSignalFunc func;
82     };
83    
84     struct combo_desc {
85     int label_id;
86     };
87    
88     struct file_req_assoc {
89     file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
90     GtkWidget *req;
91     GtkWidget *entry;
92     };
93    
94     static void cb_browse_ok(GtkWidget *button, file_req_assoc *assoc)
95     {
96     gchar *file = (char *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
97     gtk_entry_set_text(GTK_ENTRY(assoc->entry), file);
98     gtk_widget_destroy(assoc->req);
99     delete assoc;
100     }
101    
102     static void cb_browse(GtkWidget *widget, void *user_data)
103     {
104     GtkWidget *req = gtk_file_selection_new(GetString(STR_BROWSE_TITLE));
105     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
106     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(cb_browse_ok), new file_req_assoc(req, (GtkWidget *)user_data));
107     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
108     gtk_widget_show(req);
109     }
110    
111     static GtkWidget *make_browse_button(GtkWidget *entry)
112     {
113     GtkWidget *button;
114    
115     button = gtk_button_new_with_label(GetString(STR_BROWSE_CTRL));
116     gtk_widget_show(button);
117     gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)cb_browse, (void *)entry);
118     return button;
119     }
120    
121 gbeauche 1.11 static void add_menu_item(GtkWidget *menu, const char *label, GtkSignalFunc func, gpointer data = NULL)
122 gbeauche 1.1 {
123 gbeauche 1.11 GtkWidget *item = gtk_menu_item_new_with_label(label);
124 gbeauche 1.1 gtk_widget_show(item);
125 gbeauche 1.11 gtk_signal_connect(GTK_OBJECT(item), "activate", func, data);
126 gbeauche 1.1 gtk_menu_append(GTK_MENU(menu), item);
127     }
128    
129 gbeauche 1.11 static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func)
130     {
131     add_menu_item(menu, GetString(label_id), func, NULL);
132     }
133    
134 gbeauche 1.1 static GtkWidget *make_pane(GtkWidget *notebook, int title_id)
135     {
136     GtkWidget *frame, *label, *box;
137    
138     frame = gtk_frame_new(NULL);
139     gtk_widget_show(frame);
140     gtk_container_border_width(GTK_CONTAINER(frame), 4);
141    
142     label = gtk_label_new(GetString(title_id));
143     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
144    
145     box = gtk_vbox_new(FALSE, 4);
146     gtk_widget_show(box);
147     gtk_container_set_border_width(GTK_CONTAINER(box), 4);
148     gtk_container_add(GTK_CONTAINER(frame), box);
149     return box;
150     }
151    
152     static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons)
153     {
154     GtkWidget *bb, *button;
155    
156     bb = gtk_hbutton_box_new();
157     gtk_widget_show(bb);
158     gtk_container_set_border_width(GTK_CONTAINER(bb), border);
159     gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE);
160     gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4);
161     gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0);
162    
163     while (buttons->label_id) {
164     button = gtk_button_new_with_label(GetString(buttons->label_id));
165     gtk_widget_show(button);
166     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL);
167     gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0);
168     buttons++;
169     }
170     return bb;
171     }
172    
173     static GtkWidget *make_separator(GtkWidget *top)
174     {
175     GtkWidget *sep = gtk_hseparator_new();
176     gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0);
177     gtk_widget_show(sep);
178     return sep;
179     }
180    
181     static GtkWidget *make_table(GtkWidget *top, int x, int y)
182     {
183     GtkWidget *table = gtk_table_new(x, y, FALSE);
184     gtk_widget_show(table);
185     gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0);
186     return table;
187     }
188    
189 gbeauche 1.3 static GtkWidget *table_make_option_menu(GtkWidget *table, int row, int label_id, const opt_desc *options, int active)
190     {
191     GtkWidget *label, *opt, *menu;
192    
193     label = gtk_label_new(GetString(label_id));
194     gtk_widget_show(label);
195     gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
196    
197     opt = gtk_option_menu_new();
198     gtk_widget_show(opt);
199     menu = gtk_menu_new();
200    
201     while (options->label_id) {
202     add_menu_item(menu, options->label_id, options->func);
203     options++;
204     }
205     gtk_menu_set_active(GTK_MENU(menu), active);
206    
207     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
208     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
209     return menu;
210     }
211    
212     static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, GList *glist)
213     {
214     GtkWidget *label, *combo;
215     char str[32];
216    
217     label = gtk_label_new(GetString(label_id));
218     gtk_widget_show(label);
219     gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
220    
221     combo = gtk_combo_new();
222     gtk_widget_show(combo);
223     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
224    
225     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value);
226     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
227    
228     return combo;
229     }
230    
231     static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, const combo_desc *options)
232     {
233     GList *glist = NULL;
234     while (options->label_id) {
235     glist = g_list_append(glist, (void *)GetString(options->label_id));
236     options++;
237     }
238    
239     return table_make_combobox(table, row, label_id, default_value, glist);
240     }
241    
242     static GtkWidget *table_make_file_entry(GtkWidget *table, int row, int label_id, const char *prefs_item, bool only_dirs = false)
243     {
244     GtkWidget *box, *label, *entry, *button;
245    
246     label = gtk_label_new(GetString(label_id));
247     gtk_widget_show(label);
248     gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
249    
250     const char *str = PrefsFindString(prefs_item);
251     if (str == NULL)
252     str = "";
253    
254     box = gtk_hbox_new(FALSE, 4);
255     gtk_widget_show(box);
256     gtk_table_attach(GTK_TABLE(table), box, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
257    
258     entry = gtk_entry_new();
259     gtk_entry_set_text(GTK_ENTRY(entry), str);
260     gtk_widget_show(entry);
261     gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
262    
263     button = make_browse_button(entry);
264     gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
265     g_object_set_data(G_OBJECT(entry), "chooser_button", button);
266     return entry;
267     }
268    
269 gbeauche 1.1 static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
270     {
271     GtkWidget *box, *label, *opt, *menu;
272    
273     box = gtk_hbox_new(FALSE, 4);
274     gtk_widget_show(box);
275     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
276    
277     label = gtk_label_new(GetString(label_id));
278     gtk_widget_show(label);
279     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
280    
281     opt = gtk_option_menu_new();
282     gtk_widget_show(opt);
283     menu = gtk_menu_new();
284    
285     while (options->label_id) {
286     add_menu_item(menu, options->label_id, options->func);
287     options++;
288     }
289     gtk_menu_set_active(GTK_MENU(menu), active);
290    
291     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
292     gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0);
293     return menu;
294     }
295    
296     static GtkWidget *make_file_entry(GtkWidget *top, int label_id, const char *prefs_item, bool only_dirs = false)
297     {
298     GtkWidget *box, *label, *entry;
299    
300     box = gtk_hbox_new(FALSE, 4);
301     gtk_widget_show(box);
302     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
303    
304     label = gtk_label_new(GetString(label_id));
305     gtk_widget_show(label);
306     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
307    
308     const char *str = PrefsFindString(prefs_item);
309     if (str == NULL)
310     str = "";
311    
312     entry = gtk_entry_new();
313     gtk_entry_set_text(GTK_ENTRY(entry), str);
314     gtk_widget_show(entry);
315     gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
316     return entry;
317     }
318    
319     static const gchar *get_file_entry_path(GtkWidget *entry)
320     {
321     return gtk_entry_get_text(GTK_ENTRY(entry));
322     }
323    
324     static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func)
325     {
326     GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
327     gtk_widget_show(button);
328     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item));
329     gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button);
330     gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0);
331     return button;
332     }
333    
334 gbeauche 1.9 static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, GList *glist)
335 gbeauche 1.1 {
336     GtkWidget *box, *label, *combo;
337    
338     box = gtk_hbox_new(FALSE, 4);
339     gtk_widget_show(box);
340     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
341    
342     label = gtk_label_new(GetString(label_id));
343     gtk_widget_show(label);
344     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
345    
346     combo = gtk_combo_new();
347     gtk_widget_show(combo);
348     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
349    
350 gbeauche 1.9 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value);
351 gbeauche 1.1 gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0);
352    
353     return combo;
354     }
355    
356 gbeauche 1.9 static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, const combo_desc *options)
357     {
358     GList *glist = NULL;
359     while (options->label_id) {
360     glist = g_list_append(glist, (void *)GetString(options->label_id));
361     options++;
362     }
363    
364     return make_combobox(top, label_id, default_value, glist);
365     }
366    
367 gbeauche 1.1
368     /*
369     * Show preferences editor
370     * Returns true when user clicked on "Start", false otherwise
371     */
372    
373     // Window closed
374     static gint window_closed(void)
375     {
376     return FALSE;
377     }
378    
379     // Window destroyed
380     static void window_destroyed(void)
381     {
382     gtk_main_quit();
383     }
384    
385     // "Start" button clicked
386     static void cb_start(...)
387     {
388     start_clicked = true;
389     read_settings();
390     SavePrefs();
391     gtk_widget_destroy(win);
392     }
393    
394     // "Zap PRAM" button clicked
395     static void cb_zap_pram(...)
396     {
397     ZapPRAM();
398     }
399    
400     // "Quit" button clicked
401     static void cb_quit(...)
402     {
403     start_clicked = false;
404     gtk_widget_destroy(win);
405     }
406    
407     // "OK" button of "About" dialog clicked
408     static void dl_quit(GtkWidget *dialog)
409     {
410     gtk_widget_destroy(dialog);
411     }
412    
413     // "About" button clicked
414     static void cb_about(...)
415     {
416     GtkWidget *dialog;
417    
418     GtkWidget *label, *button;
419    
420     char str[512];
421     sprintf(str,
422 gbeauche 1.8 PROGRAM_NAME "\nVersion %d.%d\n\n"
423 gbeauche 1.1 "Copyright (C) 1997-2005 Christian Bauer et al.\n"
424 gbeauche 1.8 "E-mail: cb@cebix.net\n"
425     #ifdef SHEEPSHAVER
426     "http://sheepshaver.cebix.net/\n\n"
427     #else
428     "http://basilisk.cebix.net/\n\n"
429     #endif
430     PROGRAM_NAME " comes with ABSOLUTELY NO\n"
431 gbeauche 1.1 "WARRANTY. This is free software, and\n"
432     "you are welcome to redistribute it\n"
433     "under the terms of the GNU General\n"
434     "Public License.\n",
435     VERSION_MAJOR, VERSION_MINOR
436     );
437    
438     dialog = gtk_dialog_new();
439     gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE));
440     gtk_container_border_width(GTK_CONTAINER(dialog), 5);
441     gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
442    
443     label = gtk_label_new(str);
444     gtk_widget_show(label);
445     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
446    
447     button = gtk_button_new_with_label(GetString(STR_OK_BUTTON));
448     gtk_widget_show(button);
449     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
450     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
451     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
452     gtk_widget_grab_default(button);
453    
454     gtk_widget_show(dialog);
455     }
456    
457     // Menu item descriptions
458     static GtkItemFactoryEntry menu_items[] = {
459     {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, "<Branch>"},
460 gbeauche 1.6 {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), "<control>S", GTK_SIGNAL_FUNC(cb_start), 0, NULL},
461 gbeauche 1.1 {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(cb_zap_pram), 0, NULL},
462     {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, "<Separator>"},
463     {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "<control>Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL},
464     {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, "<LastBranch>"},
465 gbeauche 1.6 {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), "<control>H", GTK_SIGNAL_FUNC(cb_about), 0, NULL}
466 gbeauche 1.1 };
467    
468 gbeauche 1.11 void PrefsMigrate(void)
469     {
470     // Ethernet
471     const char *ether = PrefsFindString("ether");
472     if (ether && ether[0] == '{') {
473     PrefsReplaceString("etherguid", ether);
474     PrefsReplaceString("ether", "b2ether");
475     }
476     if (PrefsFindBool("routerenabled")) {
477     PrefsRemoveItem("etherguid");
478     PrefsReplaceString("ether", "router");
479     }
480     }
481    
482 gbeauche 1.1 bool PrefsEditor(void)
483     {
484     // Create window
485     win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
486     gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE));
487     gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL);
488     gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL);
489    
490     // Create window contents
491     GtkWidget *box = gtk_vbox_new(FALSE, 4);
492     gtk_widget_show(box);
493     gtk_container_add(GTK_CONTAINER(win), box);
494    
495     GtkAccelGroup *accel_group = gtk_accel_group_new();
496     GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
497     gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL);
498     #if GTK_CHECK_VERSION(1,3,15)
499     gtk_window_add_accel_group(GTK_WINDOW(win), accel_group);
500     #else
501     gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
502     #endif
503     GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "<main>");
504     gtk_widget_show(menu_bar);
505     gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0);
506    
507     GtkWidget *notebook = gtk_notebook_new();
508     gtk_widget_show(notebook);
509     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
510     gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
511     gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
512    
513     create_volumes_pane(notebook);
514 gbeauche 1.11 #ifndef DISABLE_SCSI
515     create_scsi_pane(notebook);
516     #endif
517 gbeauche 1.1 create_graphics_pane(notebook);
518     create_input_pane(notebook);
519     create_serial_pane(notebook);
520     create_ethernet_pane(notebook);
521     create_memory_pane(notebook);
522     create_jit_pane(notebook);
523    
524     static const opt_desc buttons[] = {
525     {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
526     {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
527     {0, NULL}
528     };
529     make_button_box(box, 4, buttons);
530    
531     // Show window and enter main loop
532     gtk_widget_show(win);
533     gtk_main();
534     return start_clicked;
535     }
536    
537    
538     /*
539     * "Volumes" pane
540     */
541    
542 gbeauche 1.9 static GtkWidget *w_enableextfs, *w_extdrives, *w_cdrom_drive;
543 gbeauche 1.1 static GtkWidget *volume_list;
544     static int selected_volume;
545    
546 gbeauche 1.4 // Set sensitivity of widgets
547     static void set_volumes_sensitive(void)
548     {
549     const bool enable_extfs = PrefsFindBool("enableextfs");
550     gtk_widget_set_sensitive(w_extdrives, enable_extfs);
551 gbeauche 1.9 const bool no_cdrom = PrefsFindBool("nocdrom");
552     gtk_widget_set_sensitive(w_cdrom_drive, !no_cdrom);
553 gbeauche 1.4 }
554    
555 gbeauche 1.1 // Volume in list selected
556     static void cl_selected(GtkWidget *list, int row, int column)
557     {
558     selected_volume = row;
559     }
560    
561     // Volume selected for addition
562     static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
563     {
564     gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
565     gtk_clist_append(GTK_CLIST(volume_list), &file);
566     gtk_widget_destroy(assoc->req);
567     delete assoc;
568     }
569    
570     // Volume selected for creation
571     static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
572     {
573     gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
574    
575     const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
576 gbeauche 1.4 size_t size = atoi(str) << 20;
577 gbeauche 1.1
578 gbeauche 1.4 int fd = _open(file, _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE);
579     if (fd >= 0) {
580     if (_chsize(fd, size) == 0)
581 gbeauche 1.1 gtk_clist_append(GTK_CLIST(volume_list), &file);
582 gbeauche 1.4 _close(fd);
583     }
584 gbeauche 1.1 gtk_widget_destroy(GTK_WIDGET(assoc->req));
585     delete assoc;
586     }
587    
588     // "Add Volume" button clicked
589     static void cb_add_volume(...)
590     {
591     GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE));
592     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
593     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL));
594     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
595     gtk_widget_show(req);
596     }
597    
598     // "Create Hardfile" button clicked
599     static void cb_create_volume(...)
600     {
601     GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE));
602    
603     GtkWidget *box = gtk_hbox_new(FALSE, 4);
604     gtk_widget_show(box);
605     GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL));
606     gtk_widget_show(label);
607     GtkWidget *entry = gtk_entry_new();
608     gtk_widget_show(entry);
609     char str[32];
610     sprintf(str, "%d", 40);
611     gtk_entry_set_text(GTK_ENTRY(entry), str);
612     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
613     gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
614     gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0);
615    
616     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
617     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry));
618     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
619     gtk_widget_show(req);
620     }
621    
622     // "Remove Volume" button clicked
623     static void cb_remove_volume(...)
624     {
625     gtk_clist_remove(GTK_CLIST(volume_list), selected_volume);
626     }
627    
628     // "Boot From" selected
629     static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
630     static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
631    
632 gbeauche 1.4 // "Enable external file system" button toggled
633     static void tb_enableextfs(GtkWidget *widget)
634     {
635     PrefsReplaceBool("enableextfs", GTK_TOGGLE_BUTTON(widget)->active);
636     set_volumes_sensitive();
637     }
638    
639 gbeauche 1.1 // "No CD-ROM Driver" button toggled
640     static void tb_nocdrom(GtkWidget *widget)
641     {
642     PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
643 gbeauche 1.9 set_volumes_sensitive();
644     }
645    
646     // Add names of CD-ROM devices
647     static GList *add_cdrom_names(void)
648     {
649     GList *glist = NULL;
650    
651     char rootdir[4] = "X:\\";
652     for (char letter = 'C'; letter <= 'Z'; letter++) {
653     rootdir[0] = letter;
654     if (GetDriveType(rootdir) == DRIVE_CDROM)
655     glist = g_list_append(glist, strdup(rootdir));
656     }
657    
658     return glist;
659 gbeauche 1.1 }
660    
661 gbeauche 1.4 // "Enable polling" button toggled
662     static void tb_pollmedia(GtkWidget *widget)
663     {
664     PrefsReplaceBool("pollmedia", GTK_TOGGLE_BUTTON(widget)->active);
665     }
666    
667 gbeauche 1.1 // Read settings from widgets and set preferences
668     static void read_volumes_settings(void)
669     {
670     while (PrefsFindString("disk"))
671     PrefsRemoveItem("disk");
672    
673     for (int i=0; i<GTK_CLIST(volume_list)->rows; i++) {
674     char *str;
675     gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
676     PrefsAddString("disk", str);
677     }
678 gbeauche 1.4
679 gbeauche 1.9 const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_cdrom_drive)->entry));
680     if (str && strlen(str))
681     PrefsReplaceString("cdrom", str);
682     else
683     PrefsRemoveItem("cdrom");
684    
685 gbeauche 1.4 PrefsReplaceString("extdrives", get_file_entry_path(w_extdrives));
686 gbeauche 1.1 }
687    
688     // Create "Volumes" pane
689     static void create_volumes_pane(GtkWidget *top)
690     {
691     GtkWidget *box, *scroll, *menu;
692    
693     box = make_pane(top, STR_VOLUMES_PANE_TITLE);
694    
695     scroll = gtk_scrolled_window_new(NULL, NULL);
696     gtk_widget_show(scroll);
697     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
698     volume_list = gtk_clist_new(1);
699     gtk_widget_show(volume_list);
700     gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE);
701     gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE);
702     gtk_clist_set_reorderable(GTK_CLIST(volume_list), true);
703     gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL);
704     char *str;
705     int32 index = 0;
706     while ((str = const_cast<char *>(PrefsFindString("disk", index++))) != NULL)
707     gtk_clist_append(GTK_CLIST(volume_list), &str);
708     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list);
709     gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
710     selected_volume = 0;
711    
712     static const opt_desc buttons[] = {
713     {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)},
714     {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)},
715     {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)},
716     {0, NULL},
717     };
718     make_button_box(box, 0, buttons);
719     make_separator(box);
720    
721     static const opt_desc options[] = {
722     {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)},
723     {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)},
724     {0, NULL}
725     };
726     int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
727     switch (bootdriver) {
728     case 0: active = 0; break;
729     case CDROMRefNum: active = 1; break;
730     }
731     menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
732    
733     make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
734 gbeauche 1.4
735 gbeauche 1.9 GList *glist = add_cdrom_names();
736     str = const_cast<char *>(PrefsFindString("cdrom"));
737     if (str == NULL)
738     str = "";
739     w_cdrom_drive = make_combobox(box, STR_CDROM_DRIVE_CTRL, str, glist);
740    
741 gbeauche 1.4 make_checkbox(box, STR_POLLMEDIA_CTRL, "pollmedia", GTK_SIGNAL_FUNC(tb_pollmedia));
742    
743     make_separator(box);
744     w_enableextfs = make_checkbox(box, STR_EXTFS_ENABLE_CTRL, "enableextfs", GTK_SIGNAL_FUNC(tb_enableextfs));
745     w_extdrives = make_file_entry(box, STR_EXTFS_DRIVES_CTRL, "extdrives", true);
746    
747     set_volumes_sensitive();
748 gbeauche 1.1 }
749    
750    
751     /*
752     * "JIT Compiler" pane
753     */
754    
755 gbeauche 1.8 #ifndef SHEEPSHAVER
756 gbeauche 1.1 static GtkWidget *w_jit_fpu;
757     static GtkWidget *w_jit_atraps;
758     static GtkWidget *w_jit_cache_size;
759     static GtkWidget *w_jit_lazy_flush;
760     static GtkWidget *w_jit_follow_const_jumps;
761 gbeauche 1.8 #endif
762 gbeauche 1.1
763     // Set sensitivity of widgets
764     static void set_jit_sensitive(void)
765     {
766 gbeauche 1.8 #ifndef SHEEPSHAVER
767 gbeauche 1.1 const bool jit_enabled = PrefsFindBool("jit");
768     gtk_widget_set_sensitive(w_jit_fpu, jit_enabled);
769     gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled);
770     gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled);
771     gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled);
772 gbeauche 1.8 #endif
773 gbeauche 1.1 }
774    
775     // "Use JIT Compiler" button toggled
776     static void tb_jit(GtkWidget *widget)
777     {
778     PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active);
779     set_jit_sensitive();
780     }
781    
782     // "Compile FPU Instructions" button toggled
783 gbeauche 1.8 #ifndef SHEEPSHAVER
784 gbeauche 1.1 static void tb_jit_fpu(GtkWidget *widget)
785     {
786     PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active);
787     }
788 gbeauche 1.8 #endif
789 gbeauche 1.1
790     // "Lazy translation cache invalidation" button toggled
791 gbeauche 1.8 #ifndef SHEEPSHAVER
792 gbeauche 1.1 static void tb_jit_lazy_flush(GtkWidget *widget)
793     {
794     PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active);
795     }
796 gbeauche 1.8 #endif
797 gbeauche 1.1
798     // "Translate through constant jumps (inline blocks)" button toggled
799 gbeauche 1.8 #ifndef SHEEPSHAVER
800 gbeauche 1.1 static void tb_jit_follow_const_jumps(GtkWidget *widget)
801     {
802     PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active);
803     }
804 gbeauche 1.8 #endif
805 gbeauche 1.1
806     // Read settings from widgets and set preferences
807     static void read_jit_settings(void)
808     {
809     #if USE_JIT
810     bool jit_enabled = PrefsFindBool("jit");
811     if (jit_enabled) {
812 gbeauche 1.8 #ifndef SHEEPSHAVER
813 gbeauche 1.1 const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
814     PrefsReplaceInt32("jitcachesize", atoi(str));
815 gbeauche 1.8 #endif
816 gbeauche 1.1 }
817     #endif
818     }
819    
820 gbeauche 1.8 // "Use built-in 68k DR emulator" button toggled
821     #ifdef SHEEPSHAVER
822     static void tb_jit_68k(GtkWidget *widget)
823     {
824     PrefsReplaceBool("jit68k", GTK_TOGGLE_BUTTON(widget)->active);
825     }
826     #endif
827    
828 gbeauche 1.1 // Create "JIT Compiler" pane
829     static void create_jit_pane(GtkWidget *top)
830     {
831     #if USE_JIT
832     GtkWidget *box, *table, *label, *menu;
833     char str[32];
834    
835     box = make_pane(top, STR_JIT_PANE_TITLE);
836     make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
837    
838 gbeauche 1.8 #ifndef SHEEPSHAVER
839 gbeauche 1.1 w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu));
840    
841     // Translation cache size
842     static const combo_desc options[] = {
843     STR_JIT_CACHE_SIZE_2MB_LAB,
844     STR_JIT_CACHE_SIZE_4MB_LAB,
845     STR_JIT_CACHE_SIZE_8MB_LAB,
846     STR_JIT_CACHE_SIZE_16MB_LAB,
847     0
848     };
849 gbeauche 1.9 sprintf(str, "%d", PrefsFindInt32("jitcachesize"));
850     w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, str, options);
851 gbeauche 1.1
852     // Lazy translation cache invalidation
853     w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush));
854    
855     // Follow constant jumps (inline basic blocks)
856     w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
857 gbeauche 1.8 #endif
858 gbeauche 1.1
859     set_jit_sensitive();
860     #endif
861 gbeauche 1.8
862     #ifdef SHEEPSHAVER
863     make_checkbox(box, STR_JIT_68K_CTRL, "jit68k", GTK_SIGNAL_FUNC(tb_jit_68k));
864     #endif
865 gbeauche 1.1 }
866    
867     /*
868     * "SCSI" pane
869     */
870    
871     static GtkWidget *w_scsi[7];
872    
873     // Read settings from widgets and set preferences
874     static void read_scsi_settings(void)
875     {
876 gbeauche 1.8 #ifndef DISABLE_SCSI
877 gbeauche 1.1 for (int id=0; id<7; id++) {
878     char prefs_name[32];
879     sprintf(prefs_name, "scsi%d", id);
880     const char *str = get_file_entry_path(w_scsi[id]);
881     if (str && strlen(str))
882     PrefsReplaceString(prefs_name, str);
883     else
884     PrefsRemoveItem(prefs_name);
885     }
886 gbeauche 1.8 #endif
887 gbeauche 1.1 }
888    
889     // Create "SCSI" pane
890     static void create_scsi_pane(GtkWidget *top)
891     {
892 gbeauche 1.8 #ifndef DISABLE_SCSI
893 gbeauche 1.1 GtkWidget *box;
894    
895     box = make_pane(top, STR_SCSI_PANE_TITLE);
896    
897     for (int id=0; id<7; id++) {
898     char prefs_name[32];
899     sprintf(prefs_name, "scsi%d", id);
900     w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name);
901     }
902 gbeauche 1.8 #endif
903 gbeauche 1.1 }
904    
905    
906     /*
907     * "Graphics/Sound" pane
908     */
909    
910     // Display types
911     enum {
912     DISPLAY_WINDOW,
913     DISPLAY_SCREEN
914     };
915    
916     static GtkWidget *w_frameskip, *w_display_x, *w_display_y;
917     static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
918     static int display_type;
919     static int dis_width, dis_height;
920    
921     // Hide/show graphics widgets
922     static void hide_show_graphics_widgets(void)
923     {
924     switch (display_type) {
925     case DISPLAY_WINDOW:
926     gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
927     break;
928     case DISPLAY_SCREEN:
929     gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
930     break;
931     }
932     }
933    
934     // "Window" video type selected
935     static void mn_window(...)
936     {
937     display_type = DISPLAY_WINDOW;
938     hide_show_graphics_widgets();
939     }
940    
941     // "Fullscreen" video type selected
942     static void mn_fullscreen(...)
943     {
944     display_type = DISPLAY_SCREEN;
945     hide_show_graphics_widgets();
946 gbeauche 1.7 PrefsReplaceInt32("frameskip", 1);
947 gbeauche 1.1 }
948    
949     // "5 Hz".."60Hz" selected
950     static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
951     static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
952     static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
953     static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
954     static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
955     static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
956     static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
957    
958 gbeauche 1.8 // QuickDraw acceleration
959     #ifdef SHEEPSHAVER
960     static void tb_gfxaccel(GtkWidget *widget)
961     {
962     PrefsReplaceBool("gfxaccel", GTK_TOGGLE_BUTTON(widget)->active);
963     }
964     #endif
965    
966 gbeauche 1.1 // Set sensitivity of widgets
967     static void set_graphics_sensitive(void)
968     {
969     const bool sound_enabled = !PrefsFindBool("nosound");
970     }
971    
972     // "Disable Sound Output" button toggled
973     static void tb_nosound(GtkWidget *widget)
974     {
975     PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
976     set_graphics_sensitive();
977     }
978    
979     // Read graphics preferences
980     static void parse_graphics_prefs(void)
981     {
982     display_type = DISPLAY_WINDOW;
983 gbeauche 1.8 #ifdef SHEEPSHAVER
984     dis_width = 640;
985     dis_height = 480;
986     #else
987 gbeauche 1.1 dis_width = 512;
988     dis_height = 384;
989 gbeauche 1.8 #endif
990 gbeauche 1.1
991     const char *str = PrefsFindString("screen");
992     if (str) {
993     if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
994     display_type = DISPLAY_WINDOW;
995     else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
996     display_type = DISPLAY_SCREEN;
997     }
998     }
999    
1000     // Read settings from widgets and set preferences
1001     static void read_graphics_settings(void)
1002     {
1003     const char *str;
1004    
1005     str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
1006     dis_width = atoi(str);
1007    
1008     str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
1009     dis_height = atoi(str);
1010    
1011     char pref[256];
1012     switch (display_type) {
1013     case DISPLAY_WINDOW:
1014     sprintf(pref, "win/%d/%d", dis_width, dis_height);
1015     break;
1016     case DISPLAY_SCREEN:
1017     sprintf(pref, "dga/%d/%d", dis_width, dis_height);
1018     break;
1019     default:
1020     PrefsRemoveItem("screen");
1021     return;
1022     }
1023     PrefsReplaceString("screen", pref);
1024     }
1025    
1026     // Create "Graphics/Sound" pane
1027     static void create_graphics_pane(GtkWidget *top)
1028     {
1029     GtkWidget *box, *table, *label, *opt, *menu, *combo;
1030     char str[32];
1031    
1032     parse_graphics_prefs();
1033    
1034     box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
1035     table = make_table(box, 2, 5);
1036    
1037     label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
1038     gtk_widget_show(label);
1039     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1040    
1041     opt = gtk_option_menu_new();
1042     gtk_widget_show(opt);
1043     menu = gtk_menu_new();
1044     add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window));
1045     add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen));
1046     switch (display_type) {
1047     case DISPLAY_WINDOW:
1048     gtk_menu_set_active(GTK_MENU(menu), 0);
1049     break;
1050     case DISPLAY_SCREEN:
1051     gtk_menu_set_active(GTK_MENU(menu), 1);
1052     break;
1053     }
1054     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
1055     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1056    
1057     l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
1058     gtk_widget_show(l_frameskip);
1059     gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1060    
1061     w_frameskip = gtk_option_menu_new();
1062     gtk_widget_show(w_frameskip);
1063     menu = gtk_menu_new();
1064     add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
1065     add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
1066     add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
1067     add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
1068     add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
1069     add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
1070     add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic));
1071     int frameskip = PrefsFindInt32("frameskip");
1072     int item = -1;
1073     switch (frameskip) {
1074     case 12: item = 0; break;
1075     case 8: item = 1; break;
1076     case 6: item = 2; break;
1077     case 4: item = 3; break;
1078     case 2: item = 4; break;
1079     case 1: item = 5; break;
1080     case 0: item = 6; break;
1081     }
1082     if (item >= 0)
1083     gtk_menu_set_active(GTK_MENU(menu), item);
1084     gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
1085     gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1086    
1087     l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
1088     gtk_widget_show(l_display_x);
1089     gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1090    
1091     combo = gtk_combo_new();
1092     gtk_widget_show(combo);
1093     GList *glist1 = NULL;
1094     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
1095     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
1096     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
1097     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
1098     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
1099     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
1100     if (dis_width)
1101     sprintf(str, "%d", dis_width);
1102     else
1103     strcpy(str, GetString(STR_SIZE_MAX_LAB));
1104     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1105     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1106     w_display_x = GTK_COMBO(combo)->entry;
1107    
1108     l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
1109     gtk_widget_show(l_display_y);
1110     gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1111    
1112     combo = gtk_combo_new();
1113     gtk_widget_show(combo);
1114     GList *glist2 = NULL;
1115     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
1116     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
1117     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
1118     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
1119     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
1120     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
1121     if (dis_height)
1122     sprintf(str, "%d", dis_height);
1123     else
1124     strcpy(str, GetString(STR_SIZE_MAX_LAB));
1125     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1126     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1127     w_display_y = GTK_COMBO(combo)->entry;
1128    
1129 gbeauche 1.8 #ifdef SHEEPSHAVER
1130     make_checkbox(box, STR_GFXACCEL_CTRL, "gfxaccel", GTK_SIGNAL_FUNC(tb_gfxaccel));
1131     #endif
1132    
1133 gbeauche 1.1 make_separator(box);
1134     make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
1135    
1136     set_graphics_sensitive();
1137    
1138     hide_show_graphics_widgets();
1139     }
1140    
1141    
1142     /*
1143     * "Input" pane
1144     */
1145    
1146     static GtkWidget *w_keycode_file;
1147     static GtkWidget *w_mouse_wheel_lines;
1148    
1149     // Set sensitivity of widgets
1150     static void set_input_sensitive(void)
1151     {
1152 gbeauche 1.4 const bool use_keycodes = PrefsFindBool("keycodes");
1153     gtk_widget_set_sensitive(w_keycode_file, use_keycodes);
1154     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes);
1155 gbeauche 1.1 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
1156     }
1157    
1158     // "Use Raw Keycodes" button toggled
1159     static void tb_keycodes(GtkWidget *widget)
1160     {
1161     PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
1162     set_input_sensitive();
1163     }
1164    
1165     // "Mouse Wheel Mode" selected
1166     static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
1167     static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
1168    
1169     // Read settings from widgets and set preferences
1170     static void read_input_settings(void)
1171     {
1172     const char *str = get_file_entry_path(w_keycode_file);
1173     if (str && strlen(str))
1174     PrefsReplaceString("keycodefile", str);
1175     else
1176     PrefsRemoveItem("keycodefile");
1177    
1178     PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
1179     }
1180    
1181     // Create "Input" pane
1182     static void create_input_pane(GtkWidget *top)
1183     {
1184 gbeauche 1.4 GtkWidget *box, *hbox, *menu, *label, *button;
1185 gbeauche 1.1 GtkObject *adj;
1186    
1187     box = make_pane(top, STR_INPUT_PANE_TITLE);
1188    
1189     make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1190 gbeauche 1.4
1191     hbox = gtk_hbox_new(FALSE, 4);
1192     gtk_widget_show(hbox);
1193     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1194    
1195     label = gtk_label_new(GetString(STR_KEYCODES_CTRL));
1196     gtk_widget_show(label);
1197     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1198    
1199     const char *str = PrefsFindString("keycodefile");
1200     if (str == NULL)
1201     str = "";
1202    
1203     w_keycode_file = gtk_entry_new();
1204     gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str);
1205     gtk_widget_show(w_keycode_file);
1206     gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0);
1207    
1208     button = make_browse_button(w_keycode_file);
1209     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1210     g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button);
1211 gbeauche 1.1
1212     make_separator(box);
1213    
1214     static const opt_desc options[] = {
1215     {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
1216     {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
1217     {0, NULL}
1218     };
1219     int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
1220     switch (wheelmode) {
1221     case 0: active = 0; break;
1222     case 1: active = 1; break;
1223     }
1224     menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
1225    
1226     hbox = gtk_hbox_new(FALSE, 4);
1227     gtk_widget_show(hbox);
1228     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1229    
1230     label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
1231     gtk_widget_show(label);
1232     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1233    
1234     adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
1235     w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1236     gtk_widget_show(w_mouse_wheel_lines);
1237     gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
1238    
1239     set_input_sensitive();
1240     }
1241    
1242    
1243     /*
1244 gbeauche 1.2 * "Serial" pane
1245 gbeauche 1.1 */
1246    
1247 gbeauche 1.3 static GtkWidget *w_seriala, *w_portfile0;
1248     static GtkWidget *w_serialb, *w_portfile1;
1249 gbeauche 1.1
1250     // Set sensitivity of widgets
1251     static void set_serial_sensitive(void)
1252     {
1253     const char *str;
1254     bool is_file;
1255    
1256     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1257     is_file = strcmp(str, "FILE") == 0;
1258     gtk_widget_set_sensitive(w_portfile0, is_file);
1259 gbeauche 1.3 gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile0), "chooser_button")), is_file);
1260 gbeauche 1.1
1261     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1262     is_file = strcmp(str, "FILE") == 0;
1263     gtk_widget_set_sensitive(w_portfile1, is_file);
1264 gbeauche 1.3 gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile1), "chooser_button")), is_file);
1265 gbeauche 1.1 }
1266    
1267     // Read settings from widgets and set preferences
1268     static void read_serial_settings(void)
1269     {
1270     const char *str;
1271    
1272     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1273     PrefsReplaceString("seriala", str);
1274    
1275     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1276     PrefsReplaceString("serialb", str);
1277    
1278     str = gtk_entry_get_text(GTK_ENTRY(w_portfile0));
1279     PrefsReplaceString("portfile0", str);
1280    
1281     str = gtk_entry_get_text(GTK_ENTRY(w_portfile1));
1282     PrefsReplaceString("portfile1", str);
1283     }
1284    
1285     // Port changed in combo
1286     static void cb_serial_port_changed(...)
1287     {
1288     set_serial_sensitive();
1289     }
1290    
1291     // Add names of serial devices
1292     static GList *add_serial_names(void)
1293     {
1294     GList *glist = NULL;
1295    
1296     static const char *port_names[] = {
1297     "COM1", "COM2", "COM3", "COM4", "COM5", "COM6",
1298     "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6",
1299     "FILE",
1300     NULL
1301     };
1302    
1303     for (int i = 0; port_names[i] != NULL; i++)
1304     glist = g_list_append(glist, (void *)port_names[i]);
1305    
1306     return glist;
1307     }
1308    
1309 gbeauche 1.2 // Create "Serial" pane
1310 gbeauche 1.1 static void create_serial_pane(GtkWidget *top)
1311     {
1312     GtkWidget *box, *hbox, *table, *label, *combo, *sep, *entry;
1313     GtkObject *adj;
1314    
1315     box = make_pane(top, STR_SERIAL_PANE_TITLE);
1316     table = make_table(box, 2, 5);
1317    
1318     GList *glist = add_serial_names();
1319     const char *str = PrefsFindString("seriala");
1320 gbeauche 1.3 combo = table_make_combobox(table, 0, STR_SERIALA_CTRL, str, glist);
1321 gbeauche 1.1 w_seriala = GTK_COMBO(combo)->entry;
1322     gtk_signal_connect(GTK_OBJECT(w_seriala), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL);
1323    
1324 gbeauche 1.3 w_portfile0 = table_make_file_entry(table, 1, STR_FILE_CTRL, "portfile0");
1325 gbeauche 1.1
1326     sep = gtk_hseparator_new();
1327     gtk_widget_show(sep);
1328     gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1329    
1330     str = PrefsFindString("serialb");
1331 gbeauche 1.3 combo = table_make_combobox(table, 3, STR_SERIALB_CTRL, str, glist);
1332 gbeauche 1.1 w_serialb = GTK_COMBO(combo)->entry;
1333     gtk_signal_connect(GTK_OBJECT(w_serialb), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL);
1334    
1335 gbeauche 1.3 w_portfile1 = table_make_file_entry(table, 4, STR_FILE_CTRL, "portfile1");
1336 gbeauche 1.1
1337     set_serial_sensitive();
1338     }
1339    
1340    
1341     /*
1342     * "Ethernet" pane
1343     */
1344    
1345 gbeauche 1.5 static GtkWidget *w_ftp_port_list, *w_tcp_port_list;
1346 gbeauche 1.1
1347     // Set sensitivity of widgets
1348     static void set_ethernet_sensitive(void)
1349     {
1350 gbeauche 1.11 const char *str = PrefsFindString("ether");
1351 gbeauche 1.5
1352 gbeauche 1.11 bool is_router = str && strcmp(str, "router") == 0;
1353     gtk_widget_set_sensitive(w_ftp_port_list, is_router);
1354     gtk_widget_set_sensitive(w_tcp_port_list, is_router);
1355 gbeauche 1.1 }
1356    
1357     // Read settings from widgets and set preferences
1358     static void read_ethernet_settings(void)
1359     {
1360 gbeauche 1.11 const char *str = PrefsFindString("ether");
1361 gbeauche 1.5
1362 gbeauche 1.11 bool is_router = str && strcmp(str, "router") == 0;
1363     if (is_router) {
1364 gbeauche 1.5 str = gtk_entry_get_text(GTK_ENTRY(w_ftp_port_list));
1365     PrefsReplaceString("ftp_port_list", str);
1366     str = gtk_entry_get_text(GTK_ENTRY(w_tcp_port_list));
1367     PrefsReplaceString("tcp_port", str);
1368     }
1369     }
1370    
1371     // Ethernet emulation type changed in menulist
1372     static void cb_ether_changed(...)
1373     {
1374     set_ethernet_sensitive();
1375 gbeauche 1.1 }
1376    
1377 gbeauche 1.11 // Ethernet option "None" selected
1378     static void mn_ether_none(void)
1379 gbeauche 1.1 {
1380 gbeauche 1.11 PrefsRemoveItem("ether");
1381     PrefsRemoveItem("etherguid");
1382     }
1383 gbeauche 1.10
1384 gbeauche 1.11 // Ethernet option "Basilisk II Router" selected
1385     static void mn_ether_router(void)
1386     {
1387     PrefsReplaceString("ether", "router");
1388     PrefsRemoveItem("etherguid");
1389     }
1390    
1391 gbeauche 1.12 // Ethernet option "Basilisk II Slirp" selected
1392     static void mn_ether_slirp(void)
1393     {
1394     PrefsReplaceString("ether", "slirp");
1395     PrefsRemoveItem("etherguid");
1396     }
1397    
1398 gbeauche 1.11 // Ethernet option for Basilisk II driver selected
1399     static void mn_ether_b2ether(GtkWidget *, const char *guid)
1400     {
1401     PrefsReplaceString("ether", "b2ether");
1402     PrefsReplaceString("etherguid", guid);
1403     }
1404    
1405     // Create ethernet interfaces menu
1406     static int create_ether_menu(GtkWidget *menu)
1407     {
1408     int active = -1;
1409     int n_items = 0;
1410     const char *ether = PrefsFindString("ether");
1411     const char *etherguid = PrefsFindString("etherguid");
1412    
1413     add_menu_item(menu, STR_NONE_LAB, (GtkSignalFunc)mn_ether_none);
1414     if (ether == NULL)
1415     active = n_items;
1416     n_items++;
1417    
1418     add_menu_item(menu, "Basilisk II Router", (GtkSignalFunc)mn_ether_router);
1419     if (ether && strcmp(ether, "router") == 0)
1420     active = n_items;
1421     n_items++;
1422    
1423 gbeauche 1.12 add_menu_item(menu, "Basilisk II Slirp", (GtkSignalFunc)mn_ether_router);
1424     if (ether && strcmp(ether, "slirp") == 0)
1425     active = n_items;
1426     n_items++;
1427    
1428 gbeauche 1.11 PacketOpenAdapter("", 0);
1429     {
1430     ULONG sz;
1431     char names[1024];
1432     sz = sizeof(names);
1433     if (PacketGetAdapterNames(NULL, names, &sz) == ERROR_SUCCESS) {
1434     char *p = names;
1435     while (*p) {
1436     const char DEVICE_HEADER[] = "\\Device\\B2ether_";
1437     if (strnicmp(p, DEVICE_HEADER, sizeof(DEVICE_HEADER) - 1) == 0) {
1438     LPADAPTER fd = PacketOpenAdapter(p + sizeof(DEVICE_HEADER) - 1, 0);
1439     if (fd) {
1440     char guid[256];
1441     sprintf(guid, "%s", p + sizeof(DEVICE_HEADER) - 1);
1442     const char *name = ether_guid_to_name(guid);
1443     if (name && (name = g_locale_to_utf8(name, -1, NULL, NULL, NULL))) {
1444     add_menu_item(menu, name, (GtkSignalFunc)mn_ether_b2ether, strdup(guid));
1445     if (etherguid && strcmp(guid, etherguid) == 0 &&
1446     ether && strcmp(ether, "b2ether") == 0)
1447     active = n_items;
1448     n_items++;
1449 gbeauche 1.10 }
1450 gbeauche 1.11 PacketCloseAdapter(fd);
1451 gbeauche 1.10 }
1452     }
1453 gbeauche 1.11 p += strlen(p) + 1;
1454 gbeauche 1.10 }
1455     }
1456     }
1457 gbeauche 1.11 PacketCloseAdapter(NULL);
1458    
1459     return active;
1460 gbeauche 1.1 }
1461    
1462     // Create "Ethernet" pane
1463     static void create_ethernet_pane(GtkWidget *top)
1464     {
1465 gbeauche 1.11 GtkWidget *box, *hbox, *table, *label, *sep, *entry, *opt, *menu, *item;
1466 gbeauche 1.1
1467     box = make_pane(top, STR_NETWORK_PANE_TITLE);
1468     table = make_table(box, 2, 5);
1469    
1470     label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1471     gtk_widget_show(label);
1472     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1473    
1474 gbeauche 1.11 opt = gtk_option_menu_new();
1475     gtk_widget_show(opt);
1476     menu = gtk_menu_new();
1477     int active = create_ether_menu(menu);
1478     if (active >= 0)
1479     gtk_menu_set_active(GTK_MENU(menu), active);
1480     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
1481     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1482     gtk_signal_connect(GTK_OBJECT(opt), "changed", GTK_SIGNAL_FUNC(cb_ether_changed), NULL);
1483 gbeauche 1.5
1484     sep = gtk_hseparator_new();
1485     gtk_widget_show(sep);
1486     gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1487    
1488     label = gtk_label_new(GetString(STR_ETHER_FTP_PORT_LIST_CTRL));
1489     gtk_widget_show(label);
1490     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1491    
1492     entry = gtk_entry_new();
1493 gbeauche 1.11 const char *str = PrefsFindString("ftp_port_list");
1494 gbeauche 1.5 if (str == NULL)
1495     str = "";
1496     gtk_entry_set_text(GTK_ENTRY(entry), str);
1497     gtk_widget_show(entry);
1498     gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1499     w_ftp_port_list = entry;
1500    
1501     label = gtk_label_new(GetString(STR_ETHER_TCP_PORT_LIST_CTRL));
1502     gtk_widget_show(label);
1503     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1504    
1505     entry = gtk_entry_new();
1506     str = PrefsFindString("tcp_port");
1507     if (str == NULL)
1508     str = "";
1509     gtk_entry_set_text(GTK_ENTRY(entry), str);
1510     gtk_widget_show(entry);
1511     gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1512     w_tcp_port_list = entry;
1513 gbeauche 1.1
1514     set_ethernet_sensitive();
1515     }
1516    
1517    
1518     /*
1519     * "Memory/Misc" pane
1520     */
1521    
1522 gbeauche 1.3 static GtkWidget *w_ramsize;
1523 gbeauche 1.1 static GtkWidget *w_rom_file;
1524    
1525 gbeauche 1.8 // Don't use CPU when idle?
1526     #ifdef SHEEPSHAVER
1527     static void tb_idlewait(GtkWidget *widget)
1528     {
1529     PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active);
1530     }
1531     #endif
1532    
1533 gbeauche 1.1 // "Ignore SEGV" button toggled
1534     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1535     static void tb_ignoresegv(GtkWidget *widget)
1536     {
1537     PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1538     }
1539     #endif
1540    
1541     // Model ID selected
1542     static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1543     static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1544    
1545     // CPU/FPU type
1546     static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1547     static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1548     static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1549     static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1550     static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1551    
1552     // Read settings from widgets and set preferences
1553     static void read_memory_settings(void)
1554     {
1555 gbeauche 1.3 const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry));
1556     PrefsReplaceInt32("ramsize", atoi(str) << 20);
1557 gbeauche 1.1
1558 gbeauche 1.3 str = get_file_entry_path(w_rom_file);
1559 gbeauche 1.1 if (str && strlen(str))
1560     PrefsReplaceString("rom", str);
1561     else
1562     PrefsRemoveItem("rom");
1563    
1564     }
1565    
1566     // Create "Memory/Misc" pane
1567     static void create_memory_pane(GtkWidget *top)
1568     {
1569 gbeauche 1.3 GtkWidget *box, *hbox, *table, *label, *scale, *menu;
1570 gbeauche 1.1
1571     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1572 gbeauche 1.3 table = make_table(box, 2, 5);
1573 gbeauche 1.1
1574 gbeauche 1.3 static const combo_desc options[] = {
1575 gbeauche 1.8 #ifndef SHEEPSHAVER
1576 gbeauche 1.3 STR_RAMSIZE_2MB_LAB,
1577 gbeauche 1.8 #endif
1578 gbeauche 1.3 STR_RAMSIZE_4MB_LAB,
1579     STR_RAMSIZE_8MB_LAB,
1580     STR_RAMSIZE_16MB_LAB,
1581     STR_RAMSIZE_32MB_LAB,
1582     STR_RAMSIZE_64MB_LAB,
1583     STR_RAMSIZE_128MB_LAB,
1584     STR_RAMSIZE_256MB_LAB,
1585     STR_RAMSIZE_512MB_LAB,
1586 gbeauche 1.8 #ifndef SHEEPSHAVER
1587 gbeauche 1.3 STR_RAMSIZE_1024MB_LAB,
1588 gbeauche 1.8 #endif
1589 gbeauche 1.3 0
1590     };
1591     char default_ramsize[10];
1592     sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20);
1593     w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options);
1594 gbeauche 1.1
1595 gbeauche 1.8 #ifndef SHEEPSHAVER
1596 gbeauche 1.1 static const opt_desc model_options[] = {
1597     {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1598     {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1599     {0, NULL}
1600     };
1601     int modelid = PrefsFindInt32("modelid"), active = 0;
1602     switch (modelid) {
1603     case 5: active = 0; break;
1604     case 14: active = 1; break;
1605     }
1606 gbeauche 1.3 table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active);
1607 gbeauche 1.8 #endif
1608 gbeauche 1.1
1609     #if EMULATED_68K
1610     static const opt_desc cpu_options[] = {
1611     {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1612     {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1613     {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1614     {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1615     {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1616     {0, NULL}
1617     };
1618     int cpu = PrefsFindInt32("cpu");
1619     bool fpu = PrefsFindBool("fpu");
1620     active = 0;
1621     switch (cpu) {
1622     case 2: active = fpu ? 1 : 0; break;
1623     case 3: active = fpu ? 3 : 2; break;
1624     case 4: active = 4;
1625     }
1626 gbeauche 1.3 table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active);
1627 gbeauche 1.1 #endif
1628    
1629 gbeauche 1.3 w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom");
1630 gbeauche 1.1
1631     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1632     make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1633     #endif
1634 gbeauche 1.8
1635     #ifdef SHEEPSHAVER
1636     make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1637     #endif
1638 gbeauche 1.1 }
1639    
1640    
1641     /*
1642     * Read settings from widgets and set preferences
1643     */
1644    
1645     static void read_settings(void)
1646     {
1647     read_volumes_settings();
1648     read_scsi_settings();
1649     read_graphics_settings();
1650     read_input_settings();
1651     read_serial_settings();
1652     read_ethernet_settings();
1653     read_memory_settings();
1654     read_jit_settings();
1655     }
1656    
1657    
1658     /*
1659     * Fake unused data and functions
1660     */
1661    
1662     uint8 XPRAM[XPRAM_SIZE];
1663     void MountVolume(void *fh) { }
1664     void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { }
1665 gbeauche 1.10 void recycle_write_packet(LPPACKET) { }
1666     VOID CALLBACK packet_read_completion(DWORD, DWORD, LPOVERLAPPED) { }
1667 gbeauche 1.1
1668    
1669     /*
1670     * Add default serial prefs (must be added, even if no ports present)
1671     */
1672    
1673     void SysAddSerialPrefs(void)
1674     {
1675     PrefsAddString("seriala", "COM1");
1676     PrefsAddString("serialb", "COM2");
1677     }
1678    
1679    
1680     /*
1681 gbeauche 1.5 * Display alerts
1682     */
1683    
1684     static void display_alert(int title_id, const char *text, int flags)
1685     {
1686     MessageBox(NULL, text, GetString(title_id), MB_OK | flags);
1687     }
1688    
1689 gbeauche 1.11 void ErrorAlert(const char *text)
1690 gbeauche 1.5 {
1691     display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP);
1692     }
1693    
1694 gbeauche 1.11 void WarningAlert(const char *text)
1695     {
1696     display_alert(STR_WARNING_ALERT_TITLE, text, MB_ICONSTOP);
1697     }
1698    
1699 gbeauche 1.5
1700     /*
1701 gbeauche 1.1 * Start standalone GUI
1702     */
1703    
1704     int main(int argc, char *argv[])
1705     {
1706     // Init GTK
1707     gtk_set_locale();
1708     gtk_init(&argc, &argv);
1709    
1710     // Read preferences
1711     PrefsInit(argc, argv);
1712    
1713 gbeauche 1.11 // Migrate preferences
1714     PrefsMigrate();
1715    
1716 gbeauche 1.1 // Show preferences editor
1717     bool start = PrefsEditor();
1718    
1719     // Exit preferences
1720     PrefsExit();
1721    
1722 gbeauche 1.8 // Transfer control to the executable
1723 gbeauche 1.1 if (start) {
1724 gbeauche 1.5 char path[_MAX_PATH];
1725     bool ok = GetModuleFileName(NULL, path, sizeof(path)) != 0;
1726     if (ok) {
1727     char b2_path[_MAX_PATH];
1728     char *p = strrchr(path, '\\');
1729     *++p = '\0';
1730     SetCurrentDirectory(path);
1731     strcpy(b2_path, path);
1732 gbeauche 1.8 strcat(b2_path, PROGRAM_NAME);
1733     strcat(b2_path, ".exe");
1734 gbeauche 1.5 HINSTANCE h = ShellExecute(GetDesktopWindow(), "open",
1735     b2_path, "", path, SW_SHOWNORMAL);
1736     if ((int)h <= 32)
1737     ok = false;
1738     }
1739     if (!ok) {
1740 gbeauche 1.8 ErrorAlert("Coult not start " PROGRAM_NAME " executable");
1741 gbeauche 1.5 return 1;
1742     }
1743 gbeauche 1.1 }
1744    
1745     return 0;
1746     }