ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
Revision: 1.24
Committed: 2002-10-15T16:25:04Z (21 years, 8 months ago) by cebix
Branch: MAIN
CVS Tags: nigel-build-12, nigel-build-13
Changes since 1.23: +17 -0 lines
Log Message:
Unix: new prefs options "dsp" and "mixer" to set the OSS device names instead
of the hardcoded '/dev/dsp' and '/dev/mixer'

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