ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
Revision: 1.22
Committed: 2002-05-12T11:10:50Z (22 years, 1 month ago) by gbeauche
Branch: MAIN
Changes since 1.21: +12 -0 lines
Log Message:
Implement the "ignoresegv" feature from SheepShaver. This is Unix-specific
so far. Target platform is currently Linux/x86.

File Contents

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