ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/prefs_editor_gtk.cpp
Revision: 1.2
Committed: 2005-06-20T08:43:50Z (19 years ago) by gbeauche
Branch: MAIN
Changes since 1.1: +2 -2 lines
Log Message:
Check for GTK for the GUI. Also add serial_windows.cpp to SRCS files

File Contents

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