ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/prefs_editor_gtk.cpp
Revision: 1.15
Committed: 2006-05-14T16:13:54Z (18 years ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-19
Changes since 1.14: +1 -3 lines
Log Message:
Support up to 1GB in SheepShaver for Windows now.

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 gbeauche 1.14 // Ethernet option for Basilisk II driver selected
1406     static void mn_ether_tap(GtkWidget *, const char *guid)
1407     {
1408     PrefsReplaceString("ether", "tap");
1409     PrefsReplaceString("etherguid", guid);
1410     }
1411    
1412 gbeauche 1.11 // Create ethernet interfaces menu
1413     static int create_ether_menu(GtkWidget *menu)
1414     {
1415     int active = -1;
1416     int n_items = 0;
1417     const char *ether = PrefsFindString("ether");
1418     const char *etherguid = PrefsFindString("etherguid");
1419    
1420 gbeauche 1.14 // No Ethernet
1421 gbeauche 1.11 add_menu_item(menu, STR_NONE_LAB, (GtkSignalFunc)mn_ether_none);
1422     if (ether == NULL)
1423     active = n_items;
1424     n_items++;
1425    
1426 gbeauche 1.14 // Basilisk II Router
1427 gbeauche 1.11 add_menu_item(menu, "Basilisk II Router", (GtkSignalFunc)mn_ether_router);
1428     if (ether && strcmp(ether, "router") == 0)
1429     active = n_items;
1430     n_items++;
1431    
1432 gbeauche 1.14 // Basilisk II Slirp
1433     add_menu_item(menu, "Basilisk II Slirp", (GtkSignalFunc)mn_ether_slirp);
1434 gbeauche 1.12 if (ether && strcmp(ether, "slirp") == 0)
1435     active = n_items;
1436     n_items++;
1437    
1438 gbeauche 1.14 // Basilisk II Ethernet Adapter
1439 gbeauche 1.11 PacketOpenAdapter("", 0);
1440     {
1441     ULONG sz;
1442     char names[1024];
1443     sz = sizeof(names);
1444     if (PacketGetAdapterNames(NULL, names, &sz) == ERROR_SUCCESS) {
1445     char *p = names;
1446     while (*p) {
1447     const char DEVICE_HEADER[] = "\\Device\\B2ether_";
1448     if (strnicmp(p, DEVICE_HEADER, sizeof(DEVICE_HEADER) - 1) == 0) {
1449     LPADAPTER fd = PacketOpenAdapter(p + sizeof(DEVICE_HEADER) - 1, 0);
1450     if (fd) {
1451     char guid[256];
1452     sprintf(guid, "%s", p + sizeof(DEVICE_HEADER) - 1);
1453     const char *name = ether_guid_to_name(guid);
1454     if (name && (name = g_locale_to_utf8(name, -1, NULL, NULL, NULL))) {
1455     add_menu_item(menu, name, (GtkSignalFunc)mn_ether_b2ether, strdup(guid));
1456     if (etherguid && strcmp(guid, etherguid) == 0 &&
1457     ether && strcmp(ether, "b2ether") == 0)
1458     active = n_items;
1459     n_items++;
1460 gbeauche 1.10 }
1461 gbeauche 1.11 PacketCloseAdapter(fd);
1462 gbeauche 1.10 }
1463     }
1464 gbeauche 1.11 p += strlen(p) + 1;
1465 gbeauche 1.10 }
1466     }
1467     }
1468 gbeauche 1.11 PacketCloseAdapter(NULL);
1469    
1470 gbeauche 1.14 // TAP-Win32
1471     const char *tap_devices;
1472     if ((tap_devices = ether_tap_devices()) != NULL) {
1473     const char *guid = tap_devices;
1474     while (*guid) {
1475     const char *name = ether_guid_to_name(guid);
1476     if (name && (name = g_locale_to_utf8(name, -1, NULL, NULL, NULL))) {
1477     add_menu_item(menu, name, (GtkSignalFunc)mn_ether_tap, strdup(guid));
1478     if (etherguid && strcmp(guid, etherguid) == 0 &&
1479     ether && strcmp(ether, "tap") == 0)
1480     active = n_items;
1481     n_items++;
1482     }
1483     guid += strlen(guid) + 1;
1484     }
1485     free((char *)tap_devices);
1486     }
1487    
1488 gbeauche 1.11 return active;
1489 gbeauche 1.1 }
1490    
1491     // Create "Ethernet" pane
1492     static void create_ethernet_pane(GtkWidget *top)
1493     {
1494 gbeauche 1.11 GtkWidget *box, *hbox, *table, *label, *sep, *entry, *opt, *menu, *item;
1495 gbeauche 1.1
1496     box = make_pane(top, STR_NETWORK_PANE_TITLE);
1497     table = make_table(box, 2, 5);
1498    
1499     label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1500     gtk_widget_show(label);
1501     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1502    
1503 gbeauche 1.11 opt = gtk_option_menu_new();
1504     gtk_widget_show(opt);
1505     menu = gtk_menu_new();
1506     int active = create_ether_menu(menu);
1507     if (active >= 0)
1508     gtk_menu_set_active(GTK_MENU(menu), active);
1509     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
1510     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1511     gtk_signal_connect(GTK_OBJECT(opt), "changed", GTK_SIGNAL_FUNC(cb_ether_changed), NULL);
1512 gbeauche 1.5
1513     sep = gtk_hseparator_new();
1514     gtk_widget_show(sep);
1515     gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1516    
1517     label = gtk_label_new(GetString(STR_ETHER_FTP_PORT_LIST_CTRL));
1518     gtk_widget_show(label);
1519     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1520    
1521     entry = gtk_entry_new();
1522 gbeauche 1.11 const char *str = PrefsFindString("ftp_port_list");
1523 gbeauche 1.5 if (str == NULL)
1524     str = "";
1525     gtk_entry_set_text(GTK_ENTRY(entry), str);
1526     gtk_widget_show(entry);
1527     gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1528     w_ftp_port_list = entry;
1529    
1530     label = gtk_label_new(GetString(STR_ETHER_TCP_PORT_LIST_CTRL));
1531     gtk_widget_show(label);
1532     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1533    
1534     entry = gtk_entry_new();
1535     str = PrefsFindString("tcp_port");
1536     if (str == NULL)
1537     str = "";
1538     gtk_entry_set_text(GTK_ENTRY(entry), str);
1539     gtk_widget_show(entry);
1540     gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1541     w_tcp_port_list = entry;
1542 gbeauche 1.1
1543     set_ethernet_sensitive();
1544     }
1545    
1546    
1547     /*
1548     * "Memory/Misc" pane
1549     */
1550    
1551 gbeauche 1.3 static GtkWidget *w_ramsize;
1552 gbeauche 1.1 static GtkWidget *w_rom_file;
1553    
1554 gbeauche 1.8 // Don't use CPU when idle?
1555     static void tb_idlewait(GtkWidget *widget)
1556     {
1557     PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active);
1558     }
1559    
1560 gbeauche 1.1 // "Ignore SEGV" button toggled
1561     #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1562     static void tb_ignoresegv(GtkWidget *widget)
1563     {
1564     PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1565     }
1566     #endif
1567    
1568     // Model ID selected
1569     static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1570     static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1571    
1572     // CPU/FPU type
1573     static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1574     static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1575     static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1576     static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1577     static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1578    
1579     // Read settings from widgets and set preferences
1580     static void read_memory_settings(void)
1581     {
1582 gbeauche 1.3 const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry));
1583     PrefsReplaceInt32("ramsize", atoi(str) << 20);
1584 gbeauche 1.1
1585 gbeauche 1.3 str = get_file_entry_path(w_rom_file);
1586 gbeauche 1.1 if (str && strlen(str))
1587     PrefsReplaceString("rom", str);
1588     else
1589     PrefsRemoveItem("rom");
1590    
1591     }
1592    
1593     // Create "Memory/Misc" pane
1594     static void create_memory_pane(GtkWidget *top)
1595     {
1596 gbeauche 1.3 GtkWidget *box, *hbox, *table, *label, *scale, *menu;
1597 gbeauche 1.1
1598     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1599 gbeauche 1.3 table = make_table(box, 2, 5);
1600 gbeauche 1.1
1601 gbeauche 1.3 static const combo_desc options[] = {
1602 gbeauche 1.8 #ifndef SHEEPSHAVER
1603 gbeauche 1.3 STR_RAMSIZE_2MB_LAB,
1604 gbeauche 1.8 #endif
1605 gbeauche 1.3 STR_RAMSIZE_4MB_LAB,
1606     STR_RAMSIZE_8MB_LAB,
1607     STR_RAMSIZE_16MB_LAB,
1608     STR_RAMSIZE_32MB_LAB,
1609     STR_RAMSIZE_64MB_LAB,
1610     STR_RAMSIZE_128MB_LAB,
1611     STR_RAMSIZE_256MB_LAB,
1612     STR_RAMSIZE_512MB_LAB,
1613     STR_RAMSIZE_1024MB_LAB,
1614     0
1615     };
1616 gbeauche 1.15 char default_ramsize[16];
1617 gbeauche 1.3 sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20);
1618     w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options);
1619 gbeauche 1.1
1620 gbeauche 1.8 #ifndef SHEEPSHAVER
1621 gbeauche 1.1 static const opt_desc model_options[] = {
1622     {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1623     {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1624     {0, NULL}
1625     };
1626     int modelid = PrefsFindInt32("modelid"), active = 0;
1627     switch (modelid) {
1628     case 5: active = 0; break;
1629     case 14: active = 1; break;
1630     }
1631 gbeauche 1.3 table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active);
1632 gbeauche 1.8 #endif
1633 gbeauche 1.1
1634     #if EMULATED_68K
1635     static const opt_desc cpu_options[] = {
1636     {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1637     {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1638     {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1639     {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1640     {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1641     {0, NULL}
1642     };
1643     int cpu = PrefsFindInt32("cpu");
1644     bool fpu = PrefsFindBool("fpu");
1645     active = 0;
1646     switch (cpu) {
1647     case 2: active = fpu ? 1 : 0; break;
1648     case 3: active = fpu ? 3 : 2; break;
1649     case 4: active = 4;
1650     }
1651 gbeauche 1.3 table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active);
1652 gbeauche 1.1 #endif
1653    
1654 gbeauche 1.3 w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom");
1655 gbeauche 1.1
1656 gbeauche 1.13 make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1657    
1658 gbeauche 1.1 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1659     make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1660     #endif
1661     }
1662    
1663    
1664     /*
1665     * Read settings from widgets and set preferences
1666     */
1667    
1668     static void read_settings(void)
1669     {
1670     read_volumes_settings();
1671     read_scsi_settings();
1672     read_graphics_settings();
1673     read_input_settings();
1674     read_serial_settings();
1675     read_ethernet_settings();
1676     read_memory_settings();
1677     read_jit_settings();
1678     }
1679    
1680    
1681     /*
1682     * Fake unused data and functions
1683     */
1684    
1685     uint8 XPRAM[XPRAM_SIZE];
1686     void MountVolume(void *fh) { }
1687     void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { }
1688 gbeauche 1.10 void recycle_write_packet(LPPACKET) { }
1689     VOID CALLBACK packet_read_completion(DWORD, DWORD, LPOVERLAPPED) { }
1690 gbeauche 1.1
1691    
1692     /*
1693     * Add default serial prefs (must be added, even if no ports present)
1694     */
1695    
1696     void SysAddSerialPrefs(void)
1697     {
1698     PrefsAddString("seriala", "COM1");
1699     PrefsAddString("serialb", "COM2");
1700     }
1701    
1702    
1703     /*
1704 gbeauche 1.5 * Display alerts
1705     */
1706    
1707     static void display_alert(int title_id, const char *text, int flags)
1708     {
1709     MessageBox(NULL, text, GetString(title_id), MB_OK | flags);
1710     }
1711    
1712 gbeauche 1.11 void ErrorAlert(const char *text)
1713 gbeauche 1.5 {
1714     display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP);
1715     }
1716    
1717 gbeauche 1.11 void WarningAlert(const char *text)
1718     {
1719     display_alert(STR_WARNING_ALERT_TITLE, text, MB_ICONSTOP);
1720     }
1721    
1722 gbeauche 1.5
1723     /*
1724 gbeauche 1.1 * Start standalone GUI
1725     */
1726    
1727     int main(int argc, char *argv[])
1728     {
1729     // Init GTK
1730     gtk_set_locale();
1731     gtk_init(&argc, &argv);
1732    
1733     // Read preferences
1734     PrefsInit(argc, argv);
1735    
1736 gbeauche 1.11 // Migrate preferences
1737     PrefsMigrate();
1738    
1739 gbeauche 1.1 // Show preferences editor
1740     bool start = PrefsEditor();
1741    
1742     // Exit preferences
1743     PrefsExit();
1744    
1745 gbeauche 1.8 // Transfer control to the executable
1746 gbeauche 1.1 if (start) {
1747 gbeauche 1.5 char path[_MAX_PATH];
1748     bool ok = GetModuleFileName(NULL, path, sizeof(path)) != 0;
1749     if (ok) {
1750     char b2_path[_MAX_PATH];
1751     char *p = strrchr(path, '\\');
1752     *++p = '\0';
1753     SetCurrentDirectory(path);
1754     strcpy(b2_path, path);
1755 gbeauche 1.8 strcat(b2_path, PROGRAM_NAME);
1756     strcat(b2_path, ".exe");
1757 gbeauche 1.5 HINSTANCE h = ShellExecute(GetDesktopWindow(), "open",
1758     b2_path, "", path, SW_SHOWNORMAL);
1759     if ((int)h <= 32)
1760     ok = false;
1761     }
1762     if (!ok) {
1763 gbeauche 1.8 ErrorAlert("Coult not start " PROGRAM_NAME " executable");
1764 gbeauche 1.5 return 1;
1765     }
1766 gbeauche 1.1 }
1767    
1768     return 0;
1769     }