ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/prefs_editor_gtk.cpp
Revision: 1.4
Committed: 2005-11-20T21:56:06Z (18 years, 6 months ago) by gbeauche
Branch: MAIN
Changes since 1.3: +65 -9 lines
Log Message:
Windows GUI: fix creation of new volumes, handle "Enable external file system",
"Enable polling", add "Browse" button for keycodes file chooser.

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