ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/prefs_editor_gtk.cpp
Revision: 1.14
Committed: 2005-03-28T09:05:28Z (19 years, 2 months ago) by gbeauche
Branch: MAIN
Changes since 1.13: +17 -3 lines
Log Message:
Handle "screen fbdev/WIDTH/HEIGHT" to force use of FBDev DGA instead of XF86
DGA mode. In other words, root user can now use FBDev DGA though it's always
recommended to run SheepShaver with a normal user. Increase "ramsize" bounds
in the GUI and fully migrate to new "screen" modes. Remove "windowmodes" and
"screenmodes" defaults.

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 gbeauche 1.14 static bool is_fbdev_dga_mode = false;
573 cebix 1.1
574 gbeauche 1.4 static GtkWidget *w_dspdevice_file, *w_mixerdevice_file;
575    
576 gbeauche 1.13 // Hide/show graphics widgets
577     static void hide_show_graphics_widgets(void)
578     {
579     switch (display_type) {
580     case DISPLAY_WINDOW:
581     gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
582     break;
583     case DISPLAY_SCREEN:
584     gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
585     break;
586     }
587     }
588    
589     // "Window" video type selected
590     static void mn_window(...)
591     {
592     display_type = DISPLAY_WINDOW;
593     hide_show_graphics_widgets();
594     }
595    
596     // "Fullscreen" video type selected
597     static void mn_fullscreen(...)
598     {
599     display_type = DISPLAY_SCREEN;
600     hide_show_graphics_widgets();
601     }
602    
603 cebix 1.1 // "5 Hz".."60Hz" selected
604     static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
605     static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
606     static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
607     static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
608     static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
609     static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
610    
611 gbeauche 1.9 // QuickDraw acceleration
612     static void tb_gfxaccel(GtkWidget *widget)
613     {
614     PrefsReplaceBool("gfxaccel", GTK_TOGGLE_BUTTON(widget)->active);
615     }
616    
617 gbeauche 1.4 // Set sensitivity of widgets
618     static void set_graphics_sensitive(void)
619     {
620     const bool sound_enabled = !PrefsFindBool("nosound");
621     gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled);
622     gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled);
623     }
624    
625 cebix 1.1 // "Disable Sound Output" button toggled
626     static void tb_nosound(GtkWidget *widget)
627     {
628     PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
629 gbeauche 1.4 set_graphics_sensitive();
630 cebix 1.1 }
631    
632 gbeauche 1.13 // Read and convert graphics preferences
633     static void parse_graphics_prefs(void)
634     {
635     display_type = DISPLAY_WINDOW;
636     dis_width = 640;
637     dis_height = 480;
638    
639     const char *str = PrefsFindString("screen");
640     if (str) {
641     if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
642     display_type = DISPLAY_WINDOW;
643     else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
644     display_type = DISPLAY_SCREEN;
645 gbeauche 1.14 #ifdef ENABLE_FBDEV_DGA
646     else if (sscanf(str, "fbdev/%d/%d", &dis_width, &dis_height) == 2) {
647     is_fbdev_dga_mode = true;
648     display_type = DISPLAY_SCREEN;
649     }
650     #endif
651 gbeauche 1.13 }
652     else {
653     uint32 window_modes = PrefsFindInt32("windowmodes");
654     uint32 screen_modes = PrefsFindInt32("screenmodes");
655     if (screen_modes) {
656     display_type = DISPLAY_SCREEN;
657     static const struct {
658     int id;
659     int width;
660     int height;
661     }
662     modes[] = {
663     { 1, 640, 480 },
664     { 2, 800, 600 },
665     { 4, 1024, 768 },
666     { 64, 1152, 768 },
667     { 8, 1152, 900 },
668     { 16, 1280, 1024 },
669     { 32, 1600, 1200 },
670     { 0, }
671     };
672     for (int i = 0; modes[i].id != 0; i++) {
673     if (screen_modes & modes[i].id) {
674     if (modes[i].width <= screen_width && modes[i].height <= screen_height) {
675     dis_width = modes[i].width;
676     dis_height = modes[i].height;
677     }
678     }
679     }
680     }
681     else if (window_modes) {
682     display_type = DISPLAY_WINDOW;
683     if (window_modes & 1)
684     dis_width = 640, dis_height = 480;
685     if (window_modes & 2)
686     dis_width = 800, dis_height = 600;
687     }
688     }
689     if (dis_width == screen_width)
690     dis_width = 0;
691     if (dis_height == screen_height)
692     dis_height = 0;
693     }
694    
695 cebix 1.1 // Read settings from widgets and set preferences
696     static void read_graphics_settings(void)
697     {
698 gbeauche 1.13 const char *str;
699    
700     str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
701     dis_width = atoi(str);
702    
703     str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
704     dis_height = atoi(str);
705    
706     char pref[256];
707 gbeauche 1.14 bool use_screen_mode = true;
708 gbeauche 1.13 switch (display_type) {
709     case DISPLAY_WINDOW:
710     sprintf(pref, "win/%d/%d", dis_width, dis_height);
711     break;
712     case DISPLAY_SCREEN:
713     sprintf(pref, "dga/%d/%d", dis_width, dis_height);
714     break;
715     default:
716 gbeauche 1.14 use_screen_mode = false;
717 gbeauche 1.13 PrefsRemoveItem("screen");
718     return;
719     }
720 gbeauche 1.14 if (use_screen_mode) {
721     PrefsReplaceString("screen", pref);
722     // Old prefs are now migrated
723     PrefsRemoveItem("windowmodes");
724     PrefsRemoveItem("screenmodes");
725     }
726 gbeauche 1.13
727 gbeauche 1.4 PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file));
728     PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file));
729 cebix 1.1 }
730    
731     // Create "Graphics/Sound" pane
732     static void create_graphics_pane(GtkWidget *top)
733     {
734 gbeauche 1.13 GtkWidget *box, *table, *label, *opt, *menu, *combo;
735     char str[32];
736    
737     parse_graphics_prefs();
738 cebix 1.1
739     box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
740 gbeauche 1.13 table = make_table(box, 2, 4);
741    
742     label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
743     gtk_widget_show(label);
744     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
745 cebix 1.1
746 gbeauche 1.13 opt = gtk_option_menu_new();
747     gtk_widget_show(opt);
748     menu = gtk_menu_new();
749     add_menu_item(menu, STR_WINDOW_CTRL, GTK_SIGNAL_FUNC(mn_window));
750     add_menu_item(menu, STR_FULLSCREEN_CTRL, GTK_SIGNAL_FUNC(mn_fullscreen));
751     switch (display_type) {
752     case DISPLAY_WINDOW:
753     gtk_menu_set_active(GTK_MENU(menu), 0);
754     break;
755     case DISPLAY_SCREEN:
756     gtk_menu_set_active(GTK_MENU(menu), 1);
757     break;
758     }
759     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
760     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
761    
762     l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
763     gtk_widget_show(l_frameskip);
764     gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
765    
766     w_frameskip = gtk_option_menu_new();
767     gtk_widget_show(w_frameskip);
768     menu = gtk_menu_new();
769     add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
770     add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
771     add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
772     add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
773     add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
774     add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
775     int frameskip = PrefsFindInt32("frameskip");
776     int item = -1;
777 cebix 1.1 switch (frameskip) {
778 gbeauche 1.13 case 12: item = 0; break;
779     case 8: item = 1; break;
780     case 6: item = 2; break;
781     case 4: item = 3; break;
782     case 2: item = 4; break;
783     case 1: item = 5; break;
784     case 0: item = 5; break;
785 cebix 1.1 }
786 gbeauche 1.13 if (item >= 0)
787     gtk_menu_set_active(GTK_MENU(menu), item);
788     gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
789     gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
790    
791     l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
792     gtk_widget_show(l_display_x);
793     gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
794 cebix 1.1
795 gbeauche 1.13 combo = gtk_combo_new();
796     gtk_widget_show(combo);
797     GList *glist1 = NULL;
798     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
799     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
800     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
801     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
802     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
803     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
804     if (dis_width)
805     sprintf(str, "%d", dis_width);
806     else
807     strcpy(str, GetString(STR_SIZE_MAX_LAB));
808     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
809     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
810     w_display_x = GTK_COMBO(combo)->entry;
811 gbeauche 1.9
812 gbeauche 1.13 l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
813     gtk_widget_show(l_display_y);
814     gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
815 cebix 1.1
816 gbeauche 1.13 combo = gtk_combo_new();
817     gtk_widget_show(combo);
818     GList *glist2 = NULL;
819     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
820     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
821     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
822     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
823     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
824     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
825     if (dis_height)
826     sprintf(str, "%d", dis_height);
827     else
828     strcpy(str, GetString(STR_SIZE_MAX_LAB));
829     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
830     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
831     w_display_y = GTK_COMBO(combo)->entry;
832 cebix 1.1
833 gbeauche 1.13 make_checkbox(box, STR_GFXACCEL_CTRL, PrefsFindBool("gfxaccel"), GTK_SIGNAL_FUNC(tb_gfxaccel));
834 cebix 1.1
835 gbeauche 1.4 make_separator(box);
836 cebix 1.1 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
837 gbeauche 1.4 w_dspdevice_file = make_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp");
838     w_mixerdevice_file = make_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer");
839    
840     set_graphics_sensitive();
841 gbeauche 1.13
842     hide_show_graphics_widgets();
843 gbeauche 1.2 }
844    
845    
846     /*
847     * "Input" pane
848     */
849    
850     static GtkWidget *w_keycode_file;
851 gbeauche 1.5 static GtkWidget *w_mouse_wheel_lines;
852 gbeauche 1.2
853     // Set sensitivity of widgets
854     static void set_input_sensitive(void)
855     {
856     gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
857 gbeauche 1.5 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
858 gbeauche 1.2 }
859    
860     // "Use Raw Keycodes" button toggled
861     static void tb_keycodes(GtkWidget *widget)
862     {
863     PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
864     set_input_sensitive();
865     }
866    
867 gbeauche 1.5 // "Mouse Wheel Mode" selected
868     static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
869     static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
870    
871 gbeauche 1.2 // Read settings from widgets and set preferences
872     static void read_input_settings(void)
873     {
874     const char *str = get_file_entry_path(w_keycode_file);
875     if (str && strlen(str))
876     PrefsReplaceString("keycodefile", str);
877     else
878     PrefsRemoveItem("keycodefile");
879 gbeauche 1.5
880     PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
881 gbeauche 1.2 }
882    
883     // Create "Input" pane
884     static void create_input_pane(GtkWidget *top)
885     {
886     GtkWidget *box, *hbox, *menu, *label;
887     GtkObject *adj;
888    
889     box = make_pane(top, STR_INPUT_PANE_TITLE);
890    
891     make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
892     w_keycode_file = make_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
893 gbeauche 1.5
894     make_separator(box);
895    
896     static const opt_desc options[] = {
897     {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
898     {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
899     {0, NULL}
900     };
901     int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
902     switch (wheelmode) {
903     case 0: active = 0; break;
904     case 1: active = 1; break;
905     }
906     menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
907    
908     hbox = gtk_hbox_new(FALSE, 4);
909     gtk_widget_show(hbox);
910     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
911    
912     label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
913     gtk_widget_show(label);
914     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
915    
916     adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
917     w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
918     gtk_widget_show(w_mouse_wheel_lines);
919     gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
920 gbeauche 1.2
921     set_input_sensitive();
922 cebix 1.1 }
923    
924    
925     /*
926     * "Serial/Network" pane
927     */
928    
929     static GtkWidget *w_seriala, *w_serialb, *w_ether;
930    
931     // Read settings from widgets and set preferences
932     static void read_serial_settings(void)
933     {
934     const char *str;
935    
936     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
937     PrefsReplaceString("seriala", str);
938    
939     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
940     PrefsReplaceString("serialb", str);
941    
942     str = gtk_entry_get_text(GTK_ENTRY(w_ether));
943     if (str && strlen(str))
944     PrefsReplaceString("ether", str);
945     else
946     PrefsRemoveItem("ether");
947     }
948    
949     // Add names of serial devices
950     static gint gl_str_cmp(gconstpointer a, gconstpointer b)
951     {
952     return strcmp((char *)a, (char *)b);
953     }
954    
955     static GList *add_serial_names(void)
956     {
957     GList *glist = NULL;
958    
959     // Search /dev for ttyS* and lp*
960     DIR *d = opendir("/dev");
961     if (d) {
962     struct dirent *de;
963     while ((de = readdir(d)) != NULL) {
964 gbeauche 1.7 #if defined(__linux__)
965 cebix 1.1 if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
966 gbeauche 1.7 #elif defined(__FreeBSD__)
967     if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
968     #elif defined(__NetBSD__)
969     if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
970     #elif defined(sgi)
971     if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) {
972     #else
973     if (false) {
974     #endif
975 cebix 1.1 char *str = new char[64];
976     sprintf(str, "/dev/%s", de->d_name);
977     glist = g_list_append(glist, str);
978     }
979     }
980     closedir(d);
981     }
982     if (glist)
983     g_list_sort(glist, gl_str_cmp);
984     else
985     glist = g_list_append(glist, (void *)"<none>");
986     return glist;
987     }
988    
989     // Add names of ethernet interfaces
990     static GList *add_ether_names(void)
991     {
992     GList *glist = NULL;
993    
994     // Get list of all Ethernet interfaces
995     int s = socket(PF_INET, SOCK_DGRAM, 0);
996     if (s >= 0) {
997     char inbuf[8192];
998     struct ifconf ifc;
999     ifc.ifc_len = sizeof(inbuf);
1000     ifc.ifc_buf = inbuf;
1001     if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
1002     struct ifreq req, *ifr = ifc.ifc_req;
1003     for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
1004     req = *ifr;
1005 gbeauche 1.7 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(sgi)
1006     if (ioctl(s, SIOCGIFADDR, &req) == 0 && (req.ifr_addr.sa_family == ARPHRD_ETHER || req.ifr_addr.sa_family == ARPHRD_ETHER+1)) {
1007     #elif defined(__linux__)
1008 cebix 1.1 if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
1009 gbeauche 1.7 #else
1010     if (false) {
1011     #endif
1012 cebix 1.1 char *str = new char[64];
1013     strncpy(str, ifr->ifr_name, 63);
1014     glist = g_list_append(glist, str);
1015     }
1016     }
1017     }
1018     close(s);
1019     }
1020     if (glist)
1021     g_list_sort(glist, gl_str_cmp);
1022     else
1023     glist = g_list_append(glist, (void *)"<none>");
1024     return glist;
1025     }
1026    
1027     // Create "Serial/Network" pane
1028     static void create_serial_pane(GtkWidget *top)
1029     {
1030     GtkWidget *box, *table, *label, *combo;
1031     GList *glist = add_serial_names();
1032    
1033     box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
1034     table = make_table(box, 2, 3);
1035    
1036     label = gtk_label_new(GetString(STR_SERPORTA_CTRL));
1037     gtk_widget_show(label);
1038     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (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     const char *str = PrefsFindString("seriala");
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, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1048     w_seriala = GTK_COMBO(combo)->entry;
1049    
1050     label = gtk_label_new(GetString(STR_SERPORTB_CTRL));
1051     gtk_widget_show(label);
1052     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1053    
1054     combo = gtk_combo_new();
1055     gtk_widget_show(combo);
1056     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1057     str = PrefsFindString("serialb");
1058     if (str == NULL)
1059     str = "";
1060     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1061     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1062     w_serialb = GTK_COMBO(combo)->entry;
1063    
1064     label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1065     gtk_widget_show(label);
1066     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1067    
1068     glist = add_ether_names();
1069     combo = gtk_combo_new();
1070     gtk_widget_show(combo);
1071     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1072     str = PrefsFindString("ether");
1073     if (str == NULL)
1074     str = "";
1075     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1076     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1077     w_ether = GTK_COMBO(combo)->entry;
1078     }
1079    
1080    
1081     /*
1082     * "Memory/Misc" pane
1083     */
1084    
1085     static GtkObject *w_ramsize_adj;
1086     static GtkWidget *w_rom_file;
1087    
1088 gbeauche 1.9 // Don't use CPU when idle?
1089     static void tb_idlewait(GtkWidget *widget)
1090     {
1091     PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active);
1092     }
1093    
1094 cebix 1.1 // "Ignore SEGV" button toggled
1095     static void tb_ignoresegv(GtkWidget *widget)
1096     {
1097     PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1098     }
1099    
1100     // Read settings from widgets and set preferences
1101     static void read_memory_settings(void)
1102     {
1103     PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
1104    
1105     const char *str = gtk_entry_get_text(GTK_ENTRY(w_rom_file));
1106     if (str && strlen(str))
1107     PrefsReplaceString("rom", str);
1108     else
1109     PrefsRemoveItem("rom");
1110     }
1111    
1112     // Create "Memory/Misc" pane
1113     static void create_memory_pane(GtkWidget *top)
1114     {
1115     GtkWidget *box, *vbox, *hbox, *hbox2, *label, *scale;
1116    
1117     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1118    
1119     hbox = gtk_hbox_new(FALSE, 4);
1120     gtk_widget_show(hbox);
1121    
1122     label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1123     gtk_widget_show(label);
1124     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1125    
1126     vbox = gtk_vbox_new(FALSE, 4);
1127     gtk_widget_show(vbox);
1128    
1129     gfloat min, max;
1130 gbeauche 1.14 min = 4;
1131     max = 512;
1132 cebix 1.1 w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1133     gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1134    
1135     scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1136     gtk_widget_show(scale);
1137     gtk_scale_set_digits(GTK_SCALE(scale), 0);
1138     gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1139    
1140     hbox2 = gtk_hbox_new(FALSE, 4);
1141     gtk_widget_show(hbox2);
1142    
1143     char val[32];
1144     sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1145     label = gtk_label_new(val);
1146     gtk_widget_show(label);
1147     gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1148    
1149     sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1150     label = gtk_label_new(val);
1151     gtk_widget_show(label);
1152     gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1153     gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1154     gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1155     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1156    
1157     w_rom_file = make_entry(box, STR_ROM_FILE_CTRL, "rom");
1158    
1159     make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1160 gbeauche 1.9 make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1161 cebix 1.1 }
1162    
1163    
1164     /*
1165     * Read settings from widgets and set preferences
1166     */
1167    
1168     static void read_settings(void)
1169     {
1170     read_volumes_settings();
1171     read_graphics_settings();
1172     read_serial_settings();
1173     read_memory_settings();
1174 gbeauche 1.3 read_jit_settings();
1175 cebix 1.1 }