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

# Content
1 /*
2 * prefs_editor_linux.cpp - Preferences editor, Linux implementation using GTK+
3 *
4 * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig
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 #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 static int screen_width, screen_height; // Screen dimensions
43
44
45 // Prototypes
46 static void create_volumes_pane(GtkWidget *top);
47 static void create_graphics_pane(GtkWidget *top);
48 static void create_input_pane(GtkWidget *top);
49 static void create_serial_pane(GtkWidget *top);
50 static void create_memory_pane(GtkWidget *top);
51 static void create_jit_pane(GtkWidget *top);
52 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 static const gchar *get_file_entry_path(GtkWidget *entry)
177 {
178 return gtk_entry_get_text(GTK_ENTRY(entry));
179 }
180
181 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 "Copyright (C) 1997-2004 Christian Bauer and Marc Hellwig\n"
250 "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 // Get screen dimensions
298 screen_width = gdk_screen_width();
299 screen_height = gdk_screen_height();
300
301 // 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 #if GTK_CHECK_VERSION(1,3,15)
316 gtk_window_add_accel_group(GTK_WINDOW(win), accel_group);
317 #else
318 gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
319 #endif
320 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 create_input_pane(notebook);
333 create_serial_pane(notebook);
334 create_memory_pane(notebook);
335 create_jit_pane(notebook);
336
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 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
374 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 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
383
384 const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
385 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 * "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 // "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 // 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 #if USE_JIT
551 make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
552 set_jit_sensitive();
553 #endif
554 make_checkbox(box, STR_JIT_68K_CTRL, "jit68k", GTK_SIGNAL_FUNC(tb_jit_68k));
555 }
556
557
558 /*
559 * "Graphics/Sound" pane
560 */
561
562 // 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
573 static GtkWidget *w_dspdevice_file, *w_mixerdevice_file;
574
575 // 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 // "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 // QuickDraw acceleration
611 static void tb_gfxaccel(GtkWidget *widget)
612 {
613 PrefsReplaceBool("gfxaccel", GTK_TOGGLE_BUTTON(widget)->active);
614 }
615
616 // 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 // "Disable Sound Output" button toggled
625 static void tb_nosound(GtkWidget *widget)
626 {
627 PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
628 set_graphics_sensitive();
629 }
630
631 // 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 // Read settings from widgets and set preferences
689 static void read_graphics_settings(void)
690 {
691 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 PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file));
714 PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file));
715 }
716
717 // Create "Graphics/Sound" pane
718 static void create_graphics_pane(GtkWidget *top)
719 {
720 GtkWidget *box, *table, *label, *opt, *menu, *combo;
721 char str[32];
722
723 parse_graphics_prefs();
724
725 box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
726 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
732 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 switch (frameskip) {
764 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 }
772 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
781 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
798 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
802 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
819 make_checkbox(box, STR_GFXACCEL_CTRL, PrefsFindBool("gfxaccel"), GTK_SIGNAL_FUNC(tb_gfxaccel));
820
821 make_separator(box);
822 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
823 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
828 hide_show_graphics_widgets();
829 }
830
831
832 /*
833 * "Input" pane
834 */
835
836 static GtkWidget *w_keycode_file;
837 static GtkWidget *w_mouse_wheel_lines;
838
839 // Set sensitivity of widgets
840 static void set_input_sensitive(void)
841 {
842 gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
843 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
844 }
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 // "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 // 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
866 PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
867 }
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
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
907 set_input_sensitive();
908 }
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 #if defined(__linux__)
951 if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
952 #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 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 #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 if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
995 #else
996 if (false) {
997 #endif
998 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 // 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 // "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 make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1147 }
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 read_jit_settings();
1161 }