ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
Revision: 1.23
Committed: 2002-09-17T16:06:37Z (21 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.22: +115 -0 lines
Log Message:
Update prefs editor with "JIT Compiler" pane

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 // Hide/show graphics widgets
719 static void hide_show_graphics_widgets(void)
720 {
721 switch (display_type) {
722 case DISPLAY_WINDOW:
723 gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
724 #ifdef ENABLE_FBDEV_DGA
725 gtk_widget_show(w_display_x); gtk_widget_show(l_display_x);
726 gtk_widget_show(w_display_y); gtk_widget_show(l_display_y);
727 gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name);
728 #endif
729 break;
730 case DISPLAY_SCREEN:
731 gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
732 #ifdef ENABLE_FBDEV_DGA
733 gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x);
734 gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y);
735 gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name);
736 #endif
737 break;
738 }
739 }
740
741 // "Window" video type selected
742 static void mn_window(...)
743 {
744 display_type = DISPLAY_WINDOW;
745 hide_show_graphics_widgets();
746 }
747
748 // "Fullscreen" video type selected
749 static void mn_fullscreen(...)
750 {
751 display_type = DISPLAY_SCREEN;
752 hide_show_graphics_widgets();
753 }
754
755 // "5 Hz".."60Hz" selected
756 static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
757 static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
758 static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
759 static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
760 static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
761 static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
762 static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
763
764 // "Disable Sound Output" button toggled
765 static void tb_nosound(GtkWidget *widget)
766 {
767 PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
768 }
769
770 // Read graphics preferences
771 static void parse_graphics_prefs(void)
772 {
773 display_type = DISPLAY_WINDOW;
774 dis_width = 512;
775 dis_height = 384;
776 #ifdef ENABLE_FBDEV_DGA
777 fbdev_name[0] = 0;
778 #endif
779
780 const char *str = PrefsFindString("screen");
781 if (str) {
782 if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
783 display_type = DISPLAY_WINDOW;
784 #ifdef ENABLE_FBDEV_DGA
785 else if (sscanf(str, "dga/%255s", fbdev_name) == 1)
786 #else
787 else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
788 #endif
789 display_type = DISPLAY_SCREEN;
790 }
791 }
792
793 // Read settings from widgets and set preferences
794 static void read_graphics_settings(void)
795 {
796 const char *str;
797
798 str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
799 dis_width = atoi(str);
800
801 str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
802 dis_height = atoi(str);
803
804 char pref[256];
805 switch (display_type) {
806 case DISPLAY_WINDOW:
807 sprintf(pref, "win/%d/%d", dis_width, dis_height);
808 break;
809 case DISPLAY_SCREEN:
810 #ifdef ENABLE_FBDEV_DGA
811 str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name));
812 sprintf(pref, "dga/%s", str);
813 #else
814 sprintf(pref, "dga/%d/%d", dis_width, dis_height);
815 #endif
816 break;
817 default:
818 PrefsRemoveItem("screen");
819 return;
820 }
821 PrefsReplaceString("screen", pref);
822
823 #ifdef ENABLE_FBDEV_DGA
824 str = get_file_entry_path(w_fbdevice_file);
825 if (str && strlen(str))
826 PrefsReplaceString("fbdevicefile", str);
827 else
828 PrefsRemoveItem("fbdevicefile");
829 #endif
830 }
831
832 // Create "Graphics/Sound" pane
833 static void create_graphics_pane(GtkWidget *top)
834 {
835 GtkWidget *box, *table, *label, *opt, *menu, *combo;
836 char str[32];
837
838 parse_graphics_prefs();
839
840 box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
841 table = make_table(box, 2, 5);
842
843 label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
844 gtk_widget_show(label);
845 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
846
847 opt = gtk_option_menu_new();
848 gtk_widget_show(opt);
849 menu = gtk_menu_new();
850 add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window));
851 add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen));
852 switch (display_type) {
853 case DISPLAY_WINDOW:
854 gtk_menu_set_active(GTK_MENU(menu), 0);
855 break;
856 case DISPLAY_SCREEN:
857 gtk_menu_set_active(GTK_MENU(menu), 1);
858 break;
859 }
860 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
861 gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
862
863 l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
864 gtk_widget_show(l_frameskip);
865 gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
866
867 w_frameskip = gtk_option_menu_new();
868 gtk_widget_show(w_frameskip);
869 menu = gtk_menu_new();
870 add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
871 add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
872 add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
873 add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
874 add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
875 add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
876 add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic));
877 int frameskip = PrefsFindInt32("frameskip");
878 int item = -1;
879 switch (frameskip) {
880 case 12: item = 0; break;
881 case 8: item = 1; break;
882 case 6: item = 2; break;
883 case 4: item = 3; break;
884 case 2: item = 4; break;
885 case 1: item = 5; break;
886 case 0: item = 6; break;
887 }
888 if (item >= 0)
889 gtk_menu_set_active(GTK_MENU(menu), item);
890 gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
891 gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
892
893 l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
894 gtk_widget_show(l_display_x);
895 gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
896
897 combo = gtk_combo_new();
898 gtk_widget_show(combo);
899 GList *glist1 = NULL;
900 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
901 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
902 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
903 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
904 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
905 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
906 if (dis_width)
907 sprintf(str, "%d", dis_width);
908 else
909 strcpy(str, GetString(STR_SIZE_MAX_LAB));
910 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
911 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
912 w_display_x = GTK_COMBO(combo)->entry;
913
914 l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
915 gtk_widget_show(l_display_y);
916 gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
917
918 combo = gtk_combo_new();
919 gtk_widget_show(combo);
920 GList *glist2 = NULL;
921 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
922 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
923 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
924 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
925 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
926 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
927 if (dis_height)
928 sprintf(str, "%d", dis_height);
929 else
930 strcpy(str, GetString(STR_SIZE_MAX_LAB));
931 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
932 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
933 w_display_y = GTK_COMBO(combo)->entry;
934
935 #ifdef ENABLE_FBDEV_DGA
936 l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL));
937 gtk_widget_show(l_fbdev_name);
938 gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
939
940 w_fbdev_name = gtk_entry_new();
941 gtk_widget_show(w_fbdev_name);
942 gtk_entry_set_text(GTK_ENTRY(w_fbdev_name), fbdev_name);
943 gtk_table_attach(GTK_TABLE(table), w_fbdev_name, 1, 2, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
944
945 w_fbdevice_file = make_file_entry(box, STR_FBDEVICE_FILE_CTRL, "fbdevicefile");
946 #endif
947
948 make_separator(box);
949 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
950
951 hide_show_graphics_widgets();
952 }
953
954
955 /*
956 * "Input" pane
957 */
958
959 static GtkWidget *w_keycode_file;
960 static GtkWidget *w_mouse_wheel_lines;
961
962 // Set sensitivity of widgets
963 static void set_input_sensitive(void)
964 {
965 gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
966 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
967 }
968
969 // "Use Raw Keycodes" button toggled
970 static void tb_keycodes(GtkWidget *widget)
971 {
972 PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
973 set_input_sensitive();
974 }
975
976 // "Mouse Wheel Mode" selected
977 static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
978 static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
979
980 // Read settings from widgets and set preferences
981 static void read_input_settings(void)
982 {
983 const char *str = get_file_entry_path(w_keycode_file);
984 if (str && strlen(str))
985 PrefsReplaceString("keycodefile", str);
986 else
987 PrefsRemoveItem("keycodefile");
988
989 PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
990 }
991
992 // Create "Input" pane
993 static void create_input_pane(GtkWidget *top)
994 {
995 GtkWidget *box, *hbox, *menu, *label;
996 GtkObject *adj;
997
998 box = make_pane(top, STR_INPUT_PANE_TITLE);
999
1000 make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1001 w_keycode_file = make_file_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
1002
1003 make_separator(box);
1004
1005 static const opt_desc options[] = {
1006 {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
1007 {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
1008 {0, NULL}
1009 };
1010 int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
1011 switch (wheelmode) {
1012 case 0: active = 0; break;
1013 case 1: active = 1; break;
1014 }
1015 menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
1016
1017 hbox = gtk_hbox_new(FALSE, 4);
1018 gtk_widget_show(hbox);
1019 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1020
1021 label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
1022 gtk_widget_show(label);
1023 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1024
1025 adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
1026 w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1027 gtk_widget_show(w_mouse_wheel_lines);
1028 gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
1029
1030 set_input_sensitive();
1031 }
1032
1033
1034 /*
1035 * "Serial/Network" pane
1036 */
1037
1038 static GtkWidget *w_seriala, *w_serialb, *w_ether, *w_udp_port;
1039
1040 // Set sensitivity of widgets
1041 static void set_serial_sensitive(void)
1042 {
1043 #if SUPPORTS_UDP_TUNNEL
1044 gtk_widget_set_sensitive(w_ether, !PrefsFindBool("udptunnel"));
1045 gtk_widget_set_sensitive(w_udp_port, PrefsFindBool("udptunnel"));
1046 #endif
1047 }
1048
1049 // "Tunnel AppleTalk over IP" button toggled
1050 static void tb_udptunnel(GtkWidget *widget)
1051 {
1052 PrefsReplaceBool("udptunnel", GTK_TOGGLE_BUTTON(widget)->active);
1053 set_serial_sensitive();
1054 }
1055
1056 // Read settings from widgets and set preferences
1057 static void read_serial_settings(void)
1058 {
1059 const char *str;
1060
1061 str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1062 PrefsReplaceString("seriala", str);
1063
1064 str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1065 PrefsReplaceString("serialb", str);
1066
1067 str = gtk_entry_get_text(GTK_ENTRY(w_ether));
1068 if (str && strlen(str))
1069 PrefsReplaceString("ether", str);
1070 else
1071 PrefsRemoveItem("ether");
1072
1073 #if SUPPORTS_UDP_TUNNEL
1074 PrefsReplaceInt32("udpport", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_udp_port)));
1075 #endif
1076 }
1077
1078 // Add names of serial devices
1079 static gint gl_str_cmp(gconstpointer a, gconstpointer b)
1080 {
1081 return strcmp((char *)a, (char *)b);
1082 }
1083
1084 static GList *add_serial_names(void)
1085 {
1086 GList *glist = NULL;
1087
1088 // Search /dev for ttyS* and lp*
1089 DIR *d = opendir("/dev");
1090 if (d) {
1091 struct dirent *de;
1092 while ((de = readdir(d)) != NULL) {
1093 #if defined(__linux__)
1094 if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
1095 #elif defined(__FreeBSD__)
1096 if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1097 #elif defined(__NetBSD__)
1098 if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
1099 #elif defined(sgi)
1100 if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) {
1101 #else
1102 if (false) {
1103 #endif
1104 char *str = new char[64];
1105 sprintf(str, "/dev/%s", de->d_name);
1106 glist = g_list_append(glist, str);
1107 }
1108 }
1109 closedir(d);
1110 }
1111 if (glist)
1112 g_list_sort(glist, gl_str_cmp);
1113 else
1114 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1115 return glist;
1116 }
1117
1118 // Add names of ethernet interfaces
1119 static GList *add_ether_names(void)
1120 {
1121 GList *glist = NULL;
1122
1123 // Get list of all Ethernet interfaces
1124 int s = socket(PF_INET, SOCK_DGRAM, 0);
1125 if (s >= 0) {
1126 char inbuf[8192];
1127 struct ifconf ifc;
1128 ifc.ifc_len = sizeof(inbuf);
1129 ifc.ifc_buf = inbuf;
1130 if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
1131 struct ifreq req, *ifr = ifc.ifc_req;
1132 for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
1133 req = *ifr;
1134 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(sgi)
1135 if (ioctl(s, SIOCGIFADDR, &req) == 0 && (req.ifr_addr.sa_family == ARPHRD_ETHER || req.ifr_addr.sa_family == ARPHRD_ETHER+1)) {
1136 #elif defined(__linux__)
1137 if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
1138 #else
1139 if (false) {
1140 #endif
1141 char *str = new char[64];
1142 strncpy(str, ifr->ifr_name, 63);
1143 glist = g_list_append(glist, str);
1144 }
1145 }
1146 }
1147 close(s);
1148 }
1149 if (glist)
1150 g_list_sort(glist, gl_str_cmp);
1151 else
1152 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
1153 return glist;
1154 }
1155
1156 // Create "Serial/Network" pane
1157 static void create_serial_pane(GtkWidget *top)
1158 {
1159 GtkWidget *box, *hbox, *table, *label, *combo, *sep;
1160 GtkObject *adj;
1161
1162 box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
1163 table = make_table(box, 2, 4);
1164
1165 label = gtk_label_new(GetString(STR_SERIALA_CTRL));
1166 gtk_widget_show(label);
1167 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1168
1169 GList *glist = add_serial_names();
1170 combo = gtk_combo_new();
1171 gtk_widget_show(combo);
1172 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1173 const char *str = PrefsFindString("seriala");
1174 if (str == NULL)
1175 str = "";
1176 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1177 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1178 w_seriala = GTK_COMBO(combo)->entry;
1179
1180 label = gtk_label_new(GetString(STR_SERIALB_CTRL));
1181 gtk_widget_show(label);
1182 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1183
1184 combo = gtk_combo_new();
1185 gtk_widget_show(combo);
1186 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1187 str = PrefsFindString("serialb");
1188 if (str == NULL)
1189 str = "";
1190 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1191 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1192 w_serialb = GTK_COMBO(combo)->entry;
1193
1194 sep = gtk_hseparator_new();
1195 gtk_widget_show(sep);
1196 gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1197
1198 label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1199 gtk_widget_show(label);
1200 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1201
1202 glist = add_ether_names();
1203 combo = gtk_combo_new();
1204 gtk_widget_show(combo);
1205 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1206 str = PrefsFindString("ether");
1207 if (str == NULL)
1208 str = "";
1209 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1210 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1211 w_ether = GTK_COMBO(combo)->entry;
1212
1213 #if SUPPORTS_UDP_TUNNEL
1214 make_checkbox(box, STR_UDPTUNNEL_CTRL, "udptunnel", GTK_SIGNAL_FUNC(tb_udptunnel));
1215
1216 hbox = gtk_hbox_new(FALSE, 4);
1217 gtk_widget_show(hbox);
1218 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1219
1220 label = gtk_label_new(GetString(STR_UDPPORT_CTRL));
1221 gtk_widget_show(label);
1222 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1223
1224 adj = gtk_adjustment_new(PrefsFindInt32("udpport"), 1, 65535, 1, 5, 0);
1225 w_udp_port = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1226 gtk_widget_show(w_udp_port);
1227 gtk_box_pack_start(GTK_BOX(hbox), w_udp_port, FALSE, FALSE, 0);
1228 #endif
1229
1230 set_serial_sensitive();
1231 }
1232
1233
1234 /*
1235 * "Memory/Misc" pane
1236 */
1237
1238 static GtkObject *w_ramsize_adj;
1239 static GtkWidget *w_rom_file;
1240
1241 // "Ignore SEGV" button toggled
1242 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1243 static void tb_ignoresegv(GtkWidget *widget)
1244 {
1245 PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1246 }
1247 #endif
1248
1249 // Model ID selected
1250 static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1251 static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1252
1253 // CPU/FPU type
1254 static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1255 static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1256 static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1257 static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1258 static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1259
1260 // Read settings from widgets and set preferences
1261 static void read_memory_settings(void)
1262 {
1263 PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
1264
1265 const char *str = get_file_entry_path(w_rom_file);
1266 if (str && strlen(str))
1267 PrefsReplaceString("rom", str);
1268 else
1269 PrefsRemoveItem("rom");
1270
1271 }
1272
1273 // Create "Memory/Misc" pane
1274 static void create_memory_pane(GtkWidget *top)
1275 {
1276 GtkWidget *box, *hbox, *vbox, *hbox2, *label, *scale;
1277
1278 box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1279
1280 hbox = gtk_hbox_new(FALSE, 4);
1281 gtk_widget_show(hbox);
1282
1283 label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1284 gtk_widget_show(label);
1285 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1286
1287 vbox = gtk_vbox_new(FALSE, 4);
1288 gtk_widget_show(vbox);
1289
1290 gfloat min, max;
1291 min = 1;
1292 max = 1024;
1293 w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1294 gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1295
1296 scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1297 gtk_widget_show(scale);
1298 gtk_scale_set_digits(GTK_SCALE(scale), 0);
1299 gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1300
1301 hbox2 = gtk_hbox_new(FALSE, 4);
1302 gtk_widget_show(hbox2);
1303
1304 char val[32];
1305 sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1306 label = gtk_label_new(val);
1307 gtk_widget_show(label);
1308 gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1309
1310 sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1311 label = gtk_label_new(val);
1312 gtk_widget_show(label);
1313 gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1314 gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1315 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1316 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1317
1318 static const opt_desc model_options[] = {
1319 {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1320 {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1321 {0, NULL}
1322 };
1323 int modelid = PrefsFindInt32("modelid"), active = 0;
1324 switch (modelid) {
1325 case 5: active = 0; break;
1326 case 14: active = 1; break;
1327 }
1328 make_option_menu(box, STR_MODELID_CTRL, model_options, active);
1329
1330 #if EMULATED_68K
1331 static const opt_desc cpu_options[] = {
1332 {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1333 {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1334 {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1335 {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1336 {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1337 {0, NULL}
1338 };
1339 int cpu = PrefsFindInt32("cpu");
1340 bool fpu = PrefsFindBool("fpu");
1341 active = 0;
1342 switch (cpu) {
1343 case 2: active = fpu ? 1 : 0; break;
1344 case 3: active = fpu ? 3 : 2; break;
1345 case 4: active = 4;
1346 }
1347 make_option_menu(box, STR_CPU_CTRL, cpu_options, active);
1348 #endif
1349
1350 w_rom_file = make_file_entry(box, STR_ROM_FILE_CTRL, "rom");
1351
1352 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1353 make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1354 #endif
1355 }
1356
1357
1358 /*
1359 * Read settings from widgets and set preferences
1360 */
1361
1362 static void read_settings(void)
1363 {
1364 read_volumes_settings();
1365 read_scsi_settings();
1366 read_graphics_settings();
1367 read_input_settings();
1368 read_serial_settings();
1369 read_memory_settings();
1370 read_jit_settings();
1371 }