ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/prefs_editor_gtk.cpp
Revision: 1.13
Committed: 2005-03-27T22:32:46Z (19 years, 2 months ago) by gbeauche
Branch: MAIN
Changes since 1.12: +214 -109 lines
Log Message:
Use "screen TYPE/WIDTH/HEIGHT" prefs item by default on Unix systems. The
former options (windowmodes/screenmodes) are migrated if the user uses the
GUI. Also make a note about EXPERIMENTAL state for jit68k.

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs_editor_linux.cpp - Preferences editor, Linux implementation using GTK+
3     *
4 gbeauche 1.11 * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "sysdeps.h"
22    
23     #include <gtk/gtk.h>
24     #include <stdlib.h>
25     #include <dirent.h>
26     #include <sys/socket.h>
27     #include <sys/ioctl.h>
28     #include <net/if.h>
29     #include <net/if_arp.h>
30    
31     #include "user_strings.h"
32     #include "version.h"
33     #include "cdrom.h"
34     #include "xpram.h"
35     #include "prefs.h"
36     #include "prefs_editor.h"
37    
38    
39     // Global variables
40     static GtkWidget *win; // Preferences window
41     static bool start_clicked = true; // Return value of PrefsEditor() function
42 gbeauche 1.13 static int screen_width, screen_height; // Screen dimensions
43 cebix 1.1
44    
45     // Prototypes
46     static void create_volumes_pane(GtkWidget *top);
47     static void create_graphics_pane(GtkWidget *top);
48 gbeauche 1.2 static void create_input_pane(GtkWidget *top);
49 cebix 1.1 static void create_serial_pane(GtkWidget *top);
50     static void create_memory_pane(GtkWidget *top);
51 gbeauche 1.3 static void create_jit_pane(GtkWidget *top);
52 cebix 1.1 static void read_settings(void);
53    
54    
55     /*
56     * Utility functions
57     */
58    
59     struct opt_desc {
60     int label_id;
61     GtkSignalFunc func;
62     };
63    
64     static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func)
65     {
66     GtkWidget *item = gtk_menu_item_new_with_label(GetString(label_id));
67     gtk_widget_show(item);
68     gtk_signal_connect(GTK_OBJECT(item), "activate", func, NULL);
69     gtk_menu_append(GTK_MENU(menu), item);
70     }
71    
72     static GtkWidget *make_pane(GtkWidget *notebook, int title_id)
73     {
74     GtkWidget *frame, *label, *box;
75    
76     frame = gtk_frame_new(NULL);
77     gtk_widget_show(frame);
78     gtk_container_border_width(GTK_CONTAINER(frame), 4);
79    
80     label = gtk_label_new(GetString(title_id));
81     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
82    
83     box = gtk_vbox_new(FALSE, 4);
84     gtk_widget_show(box);
85     gtk_container_set_border_width(GTK_CONTAINER(box), 4);
86     gtk_container_add(GTK_CONTAINER(frame), box);
87     return box;
88     }
89    
90     static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons)
91     {
92     GtkWidget *bb, *button;
93    
94     bb = gtk_hbutton_box_new();
95     gtk_widget_show(bb);
96     gtk_container_set_border_width(GTK_CONTAINER(bb), border);
97     gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE);
98     gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4);
99     gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0);
100    
101     while (buttons->label_id) {
102     button = gtk_button_new_with_label(GetString(buttons->label_id));
103     gtk_widget_show(button);
104     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL);
105     gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0);
106     buttons++;
107     }
108     return bb;
109     }
110    
111     static GtkWidget *make_separator(GtkWidget *top)
112     {
113     GtkWidget *sep = gtk_hseparator_new();
114     gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0);
115     gtk_widget_show(sep);
116     return sep;
117     }
118    
119     static GtkWidget *make_table(GtkWidget *top, int x, int y)
120     {
121     GtkWidget *table = gtk_table_new(x, y, FALSE);
122     gtk_widget_show(table);
123     gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0);
124     return table;
125     }
126    
127     static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
128     {
129     GtkWidget *box, *label, *opt, *menu;
130    
131     box = gtk_hbox_new(FALSE, 4);
132     gtk_widget_show(box);
133     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
134    
135     label = gtk_label_new(GetString(label_id));
136     gtk_widget_show(label);
137     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
138    
139     opt = gtk_option_menu_new();
140     gtk_widget_show(opt);
141     menu = gtk_menu_new();
142    
143     while (options->label_id) {
144     add_menu_item(menu, options->label_id, options->func);
145     options++;
146     }
147     gtk_menu_set_active(GTK_MENU(menu), active);
148    
149     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
150     gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0);
151     return menu;
152     }
153    
154     static GtkWidget *make_entry(GtkWidget *top, int label_id, const char *prefs_item)
155     {
156     GtkWidget *box, *label, *entry;
157    
158     box = gtk_hbox_new(FALSE, 4);
159     gtk_widget_show(box);
160     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
161    
162     label = gtk_label_new(GetString(label_id));
163     gtk_widget_show(label);
164     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
165    
166     entry = gtk_entry_new();
167     gtk_widget_show(entry);
168     const char *str = PrefsFindString(prefs_item);
169     if (str == NULL)
170     str = "";
171     gtk_entry_set_text(GTK_ENTRY(entry), str);
172     gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
173     return entry;
174     }
175    
176 gbeauche 1.12 static const gchar *get_file_entry_path(GtkWidget *entry)
177 gbeauche 1.2 {
178     return gtk_entry_get_text(GTK_ENTRY(entry));
179     }
180    
181 cebix 1.1 static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func)
182     {
183     GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
184     gtk_widget_show(button);
185     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item));
186     gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button);
187     gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0);
188     return button;
189     }
190    
191     static GtkWidget *make_checkbox(GtkWidget *top, int label_id, bool active, GtkSignalFunc func)
192     {
193     GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
194     gtk_widget_show(button);
195     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), active);
196     gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button);
197     gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0);
198     return button;
199     }
200    
201    
202     /*
203     * Show preferences editor
204     * Returns true when user clicked on "Start", false otherwise
205     */
206    
207     // Window closed
208     static gint window_closed(void)
209     {
210     return FALSE;
211     }
212    
213     // Window destroyed
214     static void window_destroyed(void)
215     {
216     gtk_main_quit();
217     }
218    
219     // "Start" button clicked
220     static void cb_start(...)
221     {
222     start_clicked = true;
223     read_settings();
224     SavePrefs();
225     gtk_widget_destroy(win);
226     }
227    
228     // "Quit" button clicked
229     static void cb_quit(...)
230     {
231     start_clicked = false;
232     gtk_widget_destroy(win);
233     }
234    
235     // "OK" button of "About" dialog clicked
236     static void dl_quit(GtkWidget *dialog)
237     {
238     gtk_widget_destroy(dialog);
239     }
240    
241     // "About" selected
242     static void mn_about(...)
243     {
244     GtkWidget *dialog, *label, *button;
245    
246     char str[512];
247     sprintf(str,
248     "SheepShaver\nVersion %d.%d\n\n"
249 cebix 1.6 "Copyright (C) 1997-2004 Christian Bauer and Marc Hellwig\n"
250 cebix 1.1 "E-mail: Christian.Bauer@uni-mainz.de\n"
251     "http://www.uni-mainz.de/~bauec002/\n\n"
252     "SheepShaver comes with ABSOLUTELY NO\n"
253     "WARRANTY. This is free software, and\n"
254     "you are welcome to redistribute it\n"
255     "under the terms of the GNU General\n"
256     "Public License.\n",
257     VERSION_MAJOR, VERSION_MINOR
258     );
259    
260     dialog = gtk_dialog_new();
261     gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE));
262     gtk_container_border_width(GTK_CONTAINER(dialog), 5);
263     gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
264    
265     label = gtk_label_new(str);
266     gtk_widget_show(label);
267     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
268    
269     button = gtk_button_new_with_label(GetString(STR_OK_BUTTON));
270     gtk_widget_show(button);
271     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
272     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
273     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
274     gtk_widget_grab_default(button);
275     gtk_widget_show(dialog);
276     }
277    
278     // "Zap NVRAM" selected
279     static void mn_zap_pram(...)
280     {
281     ZapPRAM();
282     }
283    
284     // Menu item descriptions
285     static GtkItemFactoryEntry menu_items[] = {
286     {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, "<Branch>"},
287     {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), NULL, GTK_SIGNAL_FUNC(cb_start), 0, NULL},
288     {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(mn_zap_pram), 0, NULL},
289     {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, "<Separator>"},
290     {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "<control>Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL},
291     {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, "<LastBranch>"},
292     {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), NULL, GTK_SIGNAL_FUNC(mn_about), 0, NULL}
293     };
294    
295     bool PrefsEditor(void)
296     {
297 gbeauche 1.13 // Get screen dimensions
298     screen_width = gdk_screen_width();
299     screen_height = gdk_screen_height();
300    
301 cebix 1.1 // Create window
302     win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
303     gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE));
304     gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL);
305     gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL);
306    
307     // Create window contents
308     GtkWidget *box = gtk_vbox_new(FALSE, 4);
309     gtk_widget_show(box);
310     gtk_container_add(GTK_CONTAINER(win), box);
311    
312     GtkAccelGroup *accel_group = gtk_accel_group_new();
313     GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
314     gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL);
315 gbeauche 1.12 #if GTK_CHECK_VERSION(1,3,15)
316     gtk_window_add_accel_group(GTK_WINDOW(win), accel_group);
317     #else
318 cebix 1.1 gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
319 gbeauche 1.12 #endif
320 cebix 1.1 GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "<main>");
321     gtk_widget_show(menu_bar);
322     gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0);
323    
324     GtkWidget *notebook = gtk_notebook_new();
325     gtk_widget_show(notebook);
326     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
327     gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
328     gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
329    
330     create_volumes_pane(notebook);
331     create_graphics_pane(notebook);
332 gbeauche 1.2 create_input_pane(notebook);
333 cebix 1.1 create_serial_pane(notebook);
334     create_memory_pane(notebook);
335 gbeauche 1.3 create_jit_pane(notebook);
336 cebix 1.1
337     static const opt_desc buttons[] = {
338     {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
339     {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
340     {0, NULL}
341     };
342     make_button_box(box, 4, buttons);
343    
344     // Show window and enter main loop
345     gtk_widget_show(win);
346     gtk_main();
347     return start_clicked;
348     }
349    
350    
351     /*
352     * "Volumes" pane
353     */
354    
355     static GtkWidget *volume_list, *w_extfs;
356     static int selected_volume;
357    
358     // Volume in list selected
359     static void cl_selected(GtkWidget *list, int row, int column)
360     {
361     selected_volume = row;
362     }
363    
364     struct file_req_assoc {
365     file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
366     GtkWidget *req;
367     GtkWidget *entry;
368     };
369    
370     // Volume selected for addition
371     static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
372     {
373 gbeauche 1.12 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
374 cebix 1.1 gtk_clist_append(GTK_CLIST(volume_list), &file);
375     gtk_widget_destroy(assoc->req);
376     delete assoc;
377     }
378    
379     // Volume selected for creation
380     static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
381     {
382 gbeauche 1.12 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
383 cebix 1.1
384 gbeauche 1.12 const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
385 cebix 1.1 int size = atoi(str);
386    
387     char cmd[1024];
388     sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size);
389     int ret = system(cmd);
390     if (ret == 0)
391     gtk_clist_append(GTK_CLIST(volume_list), &file);
392     gtk_widget_destroy(GTK_WIDGET(assoc->req));
393     delete assoc;
394     }
395    
396     // "Add Volume" button clicked
397     static void cb_add_volume(...)
398     {
399     GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE));
400     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
401     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL));
402     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
403     gtk_widget_show(req);
404     }
405    
406     // "Create Hardfile" button clicked
407     static void cb_create_volume(...)
408     {
409     GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE));
410    
411     GtkWidget *box = gtk_hbox_new(FALSE, 4);
412     gtk_widget_show(box);
413     GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL));
414     gtk_widget_show(label);
415     GtkWidget *entry = gtk_entry_new();
416     gtk_widget_show(entry);
417     char str[32];
418     sprintf(str, "%d", 40);
419     gtk_entry_set_text(GTK_ENTRY(entry), str);
420     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
421     gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
422     gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0);
423    
424     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
425     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry));
426     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
427     gtk_widget_show(req);
428     }
429    
430     // "Remove Volume" button clicked
431     static void cb_remove_volume(...)
432     {
433     gtk_clist_remove(GTK_CLIST(volume_list), selected_volume);
434     }
435    
436     // "Boot From" selected
437     static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
438     static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
439    
440     // "No CD-ROM Driver" button toggled
441     static void tb_nocdrom(GtkWidget *widget)
442     {
443     PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
444     }
445    
446     // Read settings from widgets and set preferences
447     static void read_volumes_settings(void)
448     {
449     while (PrefsFindString("disk"))
450     PrefsRemoveItem("disk");
451    
452     for (int i=0; i<GTK_CLIST(volume_list)->rows; i++) {
453     char *str;
454     gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
455     PrefsAddString("disk", str);
456     }
457    
458     PrefsReplaceString("extfs", gtk_entry_get_text(GTK_ENTRY(w_extfs)));
459     }
460    
461     // Create "Volumes" pane
462     static void create_volumes_pane(GtkWidget *top)
463     {
464     GtkWidget *box, *scroll, *menu;
465    
466     box = make_pane(top, STR_VOLUMES_PANE_TITLE);
467    
468     scroll = gtk_scrolled_window_new(NULL, NULL);
469     gtk_widget_show(scroll);
470     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
471     volume_list = gtk_clist_new(1);
472     gtk_widget_show(volume_list);
473     gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE);
474     gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE);
475     gtk_clist_set_reorderable(GTK_CLIST(volume_list), true);
476     gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL);
477     char *str;
478     int32 index = 0;
479     while ((str = (char *)PrefsFindString("disk", index++)) != NULL)
480     gtk_clist_append(GTK_CLIST(volume_list), &str);
481     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list);
482     gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
483     selected_volume = 0;
484    
485     static const opt_desc buttons[] = {
486     {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)},
487     {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)},
488     {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)},
489     {0, NULL},
490     };
491     make_button_box(box, 0, buttons);
492     make_separator(box);
493    
494     w_extfs = make_entry(box, STR_EXTFS_CTRL, "extfs");
495    
496     static const opt_desc options[] = {
497     {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)},
498     {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)},
499     {0, NULL}
500     };
501     int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
502     switch (bootdriver) {
503     case 0: active = 0; break;
504     case CDROMRefNum: active = 1; break;
505     }
506     menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
507    
508     make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
509     }
510    
511    
512     /*
513 gbeauche 1.3 * "JIT Compiler" pane
514     */
515    
516     // Set sensitivity of widgets
517     static void set_jit_sensitive(void)
518     {
519     const bool jit_enabled = PrefsFindBool("jit");
520     }
521    
522     // "Use JIT Compiler" button toggled
523     static void tb_jit(GtkWidget *widget)
524     {
525     PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active);
526     set_jit_sensitive();
527     }
528    
529     // Read settings from widgets and set preferences
530     static void read_jit_settings(void)
531     {
532     #if USE_JIT
533     bool jit_enabled = PrefsFindBool("jit");
534     #endif
535     }
536    
537 gbeauche 1.10 // "Use built-in 68k DR emulator" button toggled
538     static void tb_jit_68k(GtkWidget *widget)
539     {
540     PrefsReplaceBool("jit68k", GTK_TOGGLE_BUTTON(widget)->active);
541     }
542    
543 gbeauche 1.3 // Create "JIT Compiler" pane
544     static void create_jit_pane(GtkWidget *top)
545     {
546     GtkWidget *box, *table, *label, *menu;
547     char str[32];
548    
549     box = make_pane(top, STR_JIT_PANE_TITLE);
550 gbeauche 1.10 #if USE_JIT
551 gbeauche 1.3 make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
552     set_jit_sensitive();
553     #endif
554 gbeauche 1.10 make_checkbox(box, STR_JIT_68K_CTRL, "jit68k", GTK_SIGNAL_FUNC(tb_jit_68k));
555 gbeauche 1.3 }
556    
557    
558     /*
559 cebix 1.1 * "Graphics/Sound" pane
560     */
561    
562 gbeauche 1.13 // Display types
563     enum {
564     DISPLAY_WINDOW,
565     DISPLAY_SCREEN
566     };
567    
568     static GtkWidget *w_frameskip, *w_display_x, *w_display_y;
569     static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
570     static int display_type;
571     static int dis_width, dis_height;
572 cebix 1.1
573 gbeauche 1.4 static GtkWidget *w_dspdevice_file, *w_mixerdevice_file;
574    
575 gbeauche 1.13 // Hide/show graphics widgets
576     static void hide_show_graphics_widgets(void)
577     {
578     switch (display_type) {
579     case DISPLAY_WINDOW:
580     gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
581     break;
582     case DISPLAY_SCREEN:
583     gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
584     break;
585     }
586     }
587    
588     // "Window" video type selected
589     static void mn_window(...)
590     {
591     display_type = DISPLAY_WINDOW;
592     hide_show_graphics_widgets();
593     }
594    
595     // "Fullscreen" video type selected
596     static void mn_fullscreen(...)
597     {
598     display_type = DISPLAY_SCREEN;
599     hide_show_graphics_widgets();
600     }
601    
602 cebix 1.1 // "5 Hz".."60Hz" selected
603     static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
604     static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
605     static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
606     static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
607     static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
608     static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
609    
610 gbeauche 1.9 // QuickDraw acceleration
611     static void tb_gfxaccel(GtkWidget *widget)
612     {
613     PrefsReplaceBool("gfxaccel", GTK_TOGGLE_BUTTON(widget)->active);
614     }
615    
616 gbeauche 1.4 // Set sensitivity of widgets
617     static void set_graphics_sensitive(void)
618     {
619     const bool sound_enabled = !PrefsFindBool("nosound");
620     gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled);
621     gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled);
622     }
623    
624 cebix 1.1 // "Disable Sound Output" button toggled
625     static void tb_nosound(GtkWidget *widget)
626     {
627     PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
628 gbeauche 1.4 set_graphics_sensitive();
629 cebix 1.1 }
630    
631 gbeauche 1.13 // Read and convert graphics preferences
632     static void parse_graphics_prefs(void)
633     {
634     display_type = DISPLAY_WINDOW;
635     dis_width = 640;
636     dis_height = 480;
637    
638     const char *str = PrefsFindString("screen");
639     if (str) {
640     if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
641     display_type = DISPLAY_WINDOW;
642     else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
643     display_type = DISPLAY_SCREEN;
644     }
645     else {
646     uint32 window_modes = PrefsFindInt32("windowmodes");
647     uint32 screen_modes = PrefsFindInt32("screenmodes");
648     if (screen_modes) {
649     display_type = DISPLAY_SCREEN;
650     static const struct {
651     int id;
652     int width;
653     int height;
654     }
655     modes[] = {
656     { 1, 640, 480 },
657     { 2, 800, 600 },
658     { 4, 1024, 768 },
659     { 64, 1152, 768 },
660     { 8, 1152, 900 },
661     { 16, 1280, 1024 },
662     { 32, 1600, 1200 },
663     { 0, }
664     };
665     for (int i = 0; modes[i].id != 0; i++) {
666     if (screen_modes & modes[i].id) {
667     if (modes[i].width <= screen_width && modes[i].height <= screen_height) {
668     dis_width = modes[i].width;
669     dis_height = modes[i].height;
670     }
671     }
672     }
673     }
674     else if (window_modes) {
675     display_type = DISPLAY_WINDOW;
676     if (window_modes & 1)
677     dis_width = 640, dis_height = 480;
678     if (window_modes & 2)
679     dis_width = 800, dis_height = 600;
680     }
681     }
682     if (dis_width == screen_width)
683     dis_width = 0;
684     if (dis_height == screen_height)
685     dis_height = 0;
686     }
687    
688 cebix 1.1 // Read settings from widgets and set preferences
689     static void read_graphics_settings(void)
690     {
691 gbeauche 1.13 const char *str;
692    
693     str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
694     dis_width = atoi(str);
695    
696     str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
697     dis_height = atoi(str);
698    
699     char pref[256];
700     switch (display_type) {
701     case DISPLAY_WINDOW:
702     sprintf(pref, "win/%d/%d", dis_width, dis_height);
703     break;
704     case DISPLAY_SCREEN:
705     sprintf(pref, "dga/%d/%d", dis_width, dis_height);
706     break;
707     default:
708     PrefsRemoveItem("screen");
709     return;
710     }
711     PrefsReplaceString("screen", pref);
712    
713 gbeauche 1.4 PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file));
714     PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file));
715 cebix 1.1 }
716    
717     // Create "Graphics/Sound" pane
718     static void create_graphics_pane(GtkWidget *top)
719     {
720 gbeauche 1.13 GtkWidget *box, *table, *label, *opt, *menu, *combo;
721     char str[32];
722    
723     parse_graphics_prefs();
724 cebix 1.1
725     box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
726 gbeauche 1.13 table = make_table(box, 2, 4);
727    
728     label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
729     gtk_widget_show(label);
730     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
731 cebix 1.1
732 gbeauche 1.13 opt = gtk_option_menu_new();
733     gtk_widget_show(opt);
734     menu = gtk_menu_new();
735     add_menu_item(menu, STR_WINDOW_CTRL, GTK_SIGNAL_FUNC(mn_window));
736     add_menu_item(menu, STR_FULLSCREEN_CTRL, GTK_SIGNAL_FUNC(mn_fullscreen));
737     switch (display_type) {
738     case DISPLAY_WINDOW:
739     gtk_menu_set_active(GTK_MENU(menu), 0);
740     break;
741     case DISPLAY_SCREEN:
742     gtk_menu_set_active(GTK_MENU(menu), 1);
743     break;
744     }
745     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
746     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
747    
748     l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
749     gtk_widget_show(l_frameskip);
750     gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
751    
752     w_frameskip = gtk_option_menu_new();
753     gtk_widget_show(w_frameskip);
754     menu = gtk_menu_new();
755     add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
756     add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
757     add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
758     add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
759     add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
760     add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
761     int frameskip = PrefsFindInt32("frameskip");
762     int item = -1;
763 cebix 1.1 switch (frameskip) {
764 gbeauche 1.13 case 12: item = 0; break;
765     case 8: item = 1; break;
766     case 6: item = 2; break;
767     case 4: item = 3; break;
768     case 2: item = 4; break;
769     case 1: item = 5; break;
770     case 0: item = 5; break;
771 cebix 1.1 }
772 gbeauche 1.13 if (item >= 0)
773     gtk_menu_set_active(GTK_MENU(menu), item);
774     gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
775     gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
776    
777     l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
778     gtk_widget_show(l_display_x);
779     gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
780 cebix 1.1
781 gbeauche 1.13 combo = gtk_combo_new();
782     gtk_widget_show(combo);
783     GList *glist1 = NULL;
784     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
785     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
786     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
787     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
788     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
789     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
790     if (dis_width)
791     sprintf(str, "%d", dis_width);
792     else
793     strcpy(str, GetString(STR_SIZE_MAX_LAB));
794     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
795     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
796     w_display_x = GTK_COMBO(combo)->entry;
797 gbeauche 1.9
798 gbeauche 1.13 l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
799     gtk_widget_show(l_display_y);
800     gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
801 cebix 1.1
802 gbeauche 1.13 combo = gtk_combo_new();
803     gtk_widget_show(combo);
804     GList *glist2 = NULL;
805     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
806     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
807     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
808     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
809     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
810     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
811     if (dis_height)
812     sprintf(str, "%d", dis_height);
813     else
814     strcpy(str, GetString(STR_SIZE_MAX_LAB));
815     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
816     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
817     w_display_y = GTK_COMBO(combo)->entry;
818 cebix 1.1
819 gbeauche 1.13 make_checkbox(box, STR_GFXACCEL_CTRL, PrefsFindBool("gfxaccel"), GTK_SIGNAL_FUNC(tb_gfxaccel));
820 cebix 1.1
821 gbeauche 1.4 make_separator(box);
822 cebix 1.1 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
823 gbeauche 1.4 w_dspdevice_file = make_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp");
824     w_mixerdevice_file = make_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer");
825    
826     set_graphics_sensitive();
827 gbeauche 1.13
828     hide_show_graphics_widgets();
829 gbeauche 1.2 }
830    
831    
832     /*
833     * "Input" pane
834     */
835    
836     static GtkWidget *w_keycode_file;
837 gbeauche 1.5 static GtkWidget *w_mouse_wheel_lines;
838 gbeauche 1.2
839     // Set sensitivity of widgets
840     static void set_input_sensitive(void)
841     {
842     gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
843 gbeauche 1.5 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
844 gbeauche 1.2 }
845    
846     // "Use Raw Keycodes" button toggled
847     static void tb_keycodes(GtkWidget *widget)
848     {
849     PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
850     set_input_sensitive();
851     }
852    
853 gbeauche 1.5 // "Mouse Wheel Mode" selected
854     static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
855     static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
856    
857 gbeauche 1.2 // Read settings from widgets and set preferences
858     static void read_input_settings(void)
859     {
860     const char *str = get_file_entry_path(w_keycode_file);
861     if (str && strlen(str))
862     PrefsReplaceString("keycodefile", str);
863     else
864     PrefsRemoveItem("keycodefile");
865 gbeauche 1.5
866     PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
867 gbeauche 1.2 }
868    
869     // Create "Input" pane
870     static void create_input_pane(GtkWidget *top)
871     {
872     GtkWidget *box, *hbox, *menu, *label;
873     GtkObject *adj;
874    
875     box = make_pane(top, STR_INPUT_PANE_TITLE);
876    
877     make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
878     w_keycode_file = make_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
879 gbeauche 1.5
880     make_separator(box);
881    
882     static const opt_desc options[] = {
883     {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
884     {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
885     {0, NULL}
886     };
887     int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
888     switch (wheelmode) {
889     case 0: active = 0; break;
890     case 1: active = 1; break;
891     }
892     menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
893    
894     hbox = gtk_hbox_new(FALSE, 4);
895     gtk_widget_show(hbox);
896     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
897    
898     label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
899     gtk_widget_show(label);
900     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
901    
902     adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
903     w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
904     gtk_widget_show(w_mouse_wheel_lines);
905     gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
906 gbeauche 1.2
907     set_input_sensitive();
908 cebix 1.1 }
909    
910    
911     /*
912     * "Serial/Network" pane
913     */
914    
915     static GtkWidget *w_seriala, *w_serialb, *w_ether;
916    
917     // Read settings from widgets and set preferences
918     static void read_serial_settings(void)
919     {
920     const char *str;
921    
922     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
923     PrefsReplaceString("seriala", str);
924    
925     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
926     PrefsReplaceString("serialb", str);
927    
928     str = gtk_entry_get_text(GTK_ENTRY(w_ether));
929     if (str && strlen(str))
930     PrefsReplaceString("ether", str);
931     else
932     PrefsRemoveItem("ether");
933     }
934    
935     // Add names of serial devices
936     static gint gl_str_cmp(gconstpointer a, gconstpointer b)
937     {
938     return strcmp((char *)a, (char *)b);
939     }
940    
941     static GList *add_serial_names(void)
942     {
943     GList *glist = NULL;
944    
945     // Search /dev for ttyS* and lp*
946     DIR *d = opendir("/dev");
947     if (d) {
948     struct dirent *de;
949     while ((de = readdir(d)) != NULL) {
950 gbeauche 1.7 #if defined(__linux__)
951 cebix 1.1 if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
952 gbeauche 1.7 #elif defined(__FreeBSD__)
953     if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
954     #elif defined(__NetBSD__)
955     if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
956     #elif defined(sgi)
957     if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) {
958     #else
959     if (false) {
960     #endif
961 cebix 1.1 char *str = new char[64];
962     sprintf(str, "/dev/%s", de->d_name);
963     glist = g_list_append(glist, str);
964     }
965     }
966     closedir(d);
967     }
968     if (glist)
969     g_list_sort(glist, gl_str_cmp);
970     else
971     glist = g_list_append(glist, (void *)"<none>");
972     return glist;
973     }
974    
975     // Add names of ethernet interfaces
976     static GList *add_ether_names(void)
977     {
978     GList *glist = NULL;
979    
980     // Get list of all Ethernet interfaces
981     int s = socket(PF_INET, SOCK_DGRAM, 0);
982     if (s >= 0) {
983     char inbuf[8192];
984     struct ifconf ifc;
985     ifc.ifc_len = sizeof(inbuf);
986     ifc.ifc_buf = inbuf;
987     if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
988     struct ifreq req, *ifr = ifc.ifc_req;
989     for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
990     req = *ifr;
991 gbeauche 1.7 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(sgi)
992     if (ioctl(s, SIOCGIFADDR, &req) == 0 && (req.ifr_addr.sa_family == ARPHRD_ETHER || req.ifr_addr.sa_family == ARPHRD_ETHER+1)) {
993     #elif defined(__linux__)
994 cebix 1.1 if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
995 gbeauche 1.7 #else
996     if (false) {
997     #endif
998 cebix 1.1 char *str = new char[64];
999     strncpy(str, ifr->ifr_name, 63);
1000     glist = g_list_append(glist, str);
1001     }
1002     }
1003     }
1004     close(s);
1005     }
1006     if (glist)
1007     g_list_sort(glist, gl_str_cmp);
1008     else
1009     glist = g_list_append(glist, (void *)"<none>");
1010     return glist;
1011     }
1012    
1013     // Create "Serial/Network" pane
1014     static void create_serial_pane(GtkWidget *top)
1015     {
1016     GtkWidget *box, *table, *label, *combo;
1017     GList *glist = add_serial_names();
1018    
1019     box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
1020     table = make_table(box, 2, 3);
1021    
1022     label = gtk_label_new(GetString(STR_SERPORTA_CTRL));
1023     gtk_widget_show(label);
1024     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1025    
1026     combo = gtk_combo_new();
1027     gtk_widget_show(combo);
1028     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1029     const char *str = PrefsFindString("seriala");
1030     if (str == NULL)
1031     str = "";
1032     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1033     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1034     w_seriala = GTK_COMBO(combo)->entry;
1035    
1036     label = gtk_label_new(GetString(STR_SERPORTB_CTRL));
1037     gtk_widget_show(label);
1038     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1039    
1040     combo = gtk_combo_new();
1041     gtk_widget_show(combo);
1042     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1043     str = PrefsFindString("serialb");
1044     if (str == NULL)
1045     str = "";
1046     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1047     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1048     w_serialb = GTK_COMBO(combo)->entry;
1049    
1050     label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1051     gtk_widget_show(label);
1052     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1053    
1054     glist = add_ether_names();
1055     combo = gtk_combo_new();
1056     gtk_widget_show(combo);
1057     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1058     str = PrefsFindString("ether");
1059     if (str == NULL)
1060     str = "";
1061     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1062     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1063     w_ether = GTK_COMBO(combo)->entry;
1064     }
1065    
1066    
1067     /*
1068     * "Memory/Misc" pane
1069     */
1070    
1071     static GtkObject *w_ramsize_adj;
1072     static GtkWidget *w_rom_file;
1073    
1074 gbeauche 1.9 // Don't use CPU when idle?
1075     static void tb_idlewait(GtkWidget *widget)
1076     {
1077     PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active);
1078     }
1079    
1080 cebix 1.1 // "Ignore SEGV" button toggled
1081     static void tb_ignoresegv(GtkWidget *widget)
1082     {
1083     PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1084     }
1085    
1086     // Read settings from widgets and set preferences
1087     static void read_memory_settings(void)
1088     {
1089     PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
1090    
1091     const char *str = gtk_entry_get_text(GTK_ENTRY(w_rom_file));
1092     if (str && strlen(str))
1093     PrefsReplaceString("rom", str);
1094     else
1095     PrefsRemoveItem("rom");
1096     }
1097    
1098     // Create "Memory/Misc" pane
1099     static void create_memory_pane(GtkWidget *top)
1100     {
1101     GtkWidget *box, *vbox, *hbox, *hbox2, *label, *scale;
1102    
1103     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1104    
1105     hbox = gtk_hbox_new(FALSE, 4);
1106     gtk_widget_show(hbox);
1107    
1108     label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1109     gtk_widget_show(label);
1110     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1111    
1112     vbox = gtk_vbox_new(FALSE, 4);
1113     gtk_widget_show(vbox);
1114    
1115     gfloat min, max;
1116     min = 1;
1117     max = 256;
1118     w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1119     gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1120    
1121     scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1122     gtk_widget_show(scale);
1123     gtk_scale_set_digits(GTK_SCALE(scale), 0);
1124     gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1125    
1126     hbox2 = gtk_hbox_new(FALSE, 4);
1127     gtk_widget_show(hbox2);
1128    
1129     char val[32];
1130     sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1131     label = gtk_label_new(val);
1132     gtk_widget_show(label);
1133     gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1134    
1135     sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1136     label = gtk_label_new(val);
1137     gtk_widget_show(label);
1138     gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1139     gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1140     gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1141     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1142    
1143     w_rom_file = make_entry(box, STR_ROM_FILE_CTRL, "rom");
1144    
1145     make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1146 gbeauche 1.9 make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1147 cebix 1.1 }
1148    
1149    
1150     /*
1151     * Read settings from widgets and set preferences
1152     */
1153    
1154     static void read_settings(void)
1155     {
1156     read_volumes_settings();
1157     read_graphics_settings();
1158     read_serial_settings();
1159     read_memory_settings();
1160 gbeauche 1.3 read_jit_settings();
1161 cebix 1.1 }