ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/prefs_editor_gtk.cpp
Revision: 1.3
Committed: 2005-11-20T17:26:16Z (18 years, 6 months ago) by gbeauche
Branch: MAIN
Changes since 1.2: +113 -106 lines
Log Message:
GUI cosmetics

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