ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/prefs_editor_gtk.cpp
Revision: 1.17
Committed: 2009-07-23T19:19:13Z (14 years, 10 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.16: +1 -1 lines
Log Message:
BasiliskII side of changes to support .sheepvm bundles for SheepShaver

File Contents

# Content
1 /*
2 * prefs_editor_gtk.cpp - Preferences editor, Unix implementation using GTK+
3 *
4 * Basilisk II (C) 1997-2008 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 <stdlib.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <sys/stat.h>
27 #include <gtk/gtk.h>
28
29 #include "user_strings.h"
30 #include "version.h"
31 #include "cdrom.h"
32 #include "xpram.h"
33 #include "prefs.h"
34 #include "prefs_editor.h"
35 #include "util_windows.h"
36 #include "b2ether/inc/b2ether_hl.h"
37
38
39 // Global variables
40 static GtkWidget *win; // Preferences window
41 static bool start_clicked = true; // Return value of PrefsEditor() function
42
43
44 // Prototypes
45 static void create_volumes_pane(GtkWidget *top);
46 static void create_scsi_pane(GtkWidget *top);
47 static void create_graphics_pane(GtkWidget *top);
48 static void create_input_pane(GtkWidget *top);
49 static void create_serial_pane(GtkWidget *top);
50 static void create_ethernet_pane(GtkWidget *top);
51 static void create_memory_pane(GtkWidget *top);
52 static void create_jit_pane(GtkWidget *top);
53 static void read_settings(void);
54
55
56 /*
57 * SheepShaver glue
58 */
59
60 #ifdef SHEEPSHAVER
61 #define DISABLE_SCSI 1
62 #define PROGRAM_NAME "SheepShaver"
63 enum {
64 STR_WINDOW_LAB = STR_WINDOW_CTRL,
65 STR_FULLSCREEN_LAB = STR_FULLSCREEN_CTRL,
66 STR_SERIALA_CTRL = STR_SERPORTA_CTRL,
67 STR_SERIALB_CTRL = STR_SERPORTB_CTRL,
68 };
69 #else
70 #define DISABLE_SCSI 1 /* XXX merge code from original Basilisk II for Windows */
71 #define PROGRAM_NAME "BasiliskII"
72 #endif
73
74
75 /*
76 * Utility functions
77 */
78
79 struct opt_desc {
80 int label_id;
81 GtkSignalFunc func;
82 };
83
84 struct combo_desc {
85 int label_id;
86 };
87
88 struct file_req_assoc {
89 file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
90 GtkWidget *req;
91 GtkWidget *entry;
92 };
93
94 static void cb_browse_ok(GtkWidget *button, file_req_assoc *assoc)
95 {
96 gchar *file = (char *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
97 gtk_entry_set_text(GTK_ENTRY(assoc->entry), file);
98 gtk_widget_destroy(assoc->req);
99 delete assoc;
100 }
101
102 static void cb_browse(GtkWidget *widget, void *user_data)
103 {
104 GtkWidget *req = gtk_file_selection_new(GetString(STR_BROWSE_TITLE));
105 gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
106 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));
107 gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
108 gtk_widget_show(req);
109 }
110
111 static GtkWidget *make_browse_button(GtkWidget *entry)
112 {
113 GtkWidget *button;
114
115 button = gtk_button_new_with_label(GetString(STR_BROWSE_CTRL));
116 gtk_widget_show(button);
117 gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)cb_browse, (void *)entry);
118 return button;
119 }
120
121 static void add_menu_item(GtkWidget *menu, const char *label, GtkSignalFunc func, gpointer data = NULL)
122 {
123 GtkWidget *item = gtk_menu_item_new_with_label(label);
124 gtk_widget_show(item);
125 gtk_signal_connect(GTK_OBJECT(item), "activate", func, data);
126 gtk_menu_append(GTK_MENU(menu), item);
127 }
128
129 static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func)
130 {
131 add_menu_item(menu, GetString(label_id), func, NULL);
132 }
133
134 static GtkWidget *make_pane(GtkWidget *notebook, int title_id)
135 {
136 GtkWidget *frame, *label, *box;
137
138 frame = gtk_frame_new(NULL);
139 gtk_widget_show(frame);
140 gtk_container_border_width(GTK_CONTAINER(frame), 4);
141
142 label = gtk_label_new(GetString(title_id));
143 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
144
145 box = gtk_vbox_new(FALSE, 4);
146 gtk_widget_show(box);
147 gtk_container_set_border_width(GTK_CONTAINER(box), 4);
148 gtk_container_add(GTK_CONTAINER(frame), box);
149 return box;
150 }
151
152 static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons)
153 {
154 GtkWidget *bb, *button;
155
156 bb = gtk_hbutton_box_new();
157 gtk_widget_show(bb);
158 gtk_container_set_border_width(GTK_CONTAINER(bb), border);
159 gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE);
160 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4);
161 gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0);
162
163 while (buttons->label_id) {
164 button = gtk_button_new_with_label(GetString(buttons->label_id));
165 gtk_widget_show(button);
166 gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL);
167 gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0);
168 buttons++;
169 }
170 return bb;
171 }
172
173 static GtkWidget *make_separator(GtkWidget *top)
174 {
175 GtkWidget *sep = gtk_hseparator_new();
176 gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0);
177 gtk_widget_show(sep);
178 return sep;
179 }
180
181 static GtkWidget *make_table(GtkWidget *top, int x, int y)
182 {
183 GtkWidget *table = gtk_table_new(x, y, FALSE);
184 gtk_widget_show(table);
185 gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0);
186 return table;
187 }
188
189 static GtkWidget *table_make_option_menu(GtkWidget *table, int row, int label_id, const opt_desc *options, int active)
190 {
191 GtkWidget *label, *opt, *menu;
192
193 label = gtk_label_new(GetString(label_id));
194 gtk_widget_show(label);
195 gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
196
197 opt = gtk_option_menu_new();
198 gtk_widget_show(opt);
199 menu = gtk_menu_new();
200
201 while (options->label_id) {
202 add_menu_item(menu, options->label_id, options->func);
203 options++;
204 }
205 gtk_menu_set_active(GTK_MENU(menu), active);
206
207 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
208 gtk_table_attach(GTK_TABLE(table), opt, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
209 return menu;
210 }
211
212 static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, GList *glist)
213 {
214 GtkWidget *label, *combo;
215 char str[32];
216
217 label = gtk_label_new(GetString(label_id));
218 gtk_widget_show(label);
219 gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
220
221 combo = gtk_combo_new();
222 gtk_widget_show(combo);
223 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
224
225 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value);
226 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
227
228 return combo;
229 }
230
231 static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, const combo_desc *options)
232 {
233 GList *glist = NULL;
234 while (options->label_id) {
235 glist = g_list_append(glist, (void *)GetString(options->label_id));
236 options++;
237 }
238
239 return table_make_combobox(table, row, label_id, default_value, glist);
240 }
241
242 static GtkWidget *table_make_file_entry(GtkWidget *table, int row, int label_id, const char *prefs_item, bool only_dirs = false)
243 {
244 GtkWidget *box, *label, *entry, *button;
245
246 label = gtk_label_new(GetString(label_id));
247 gtk_widget_show(label);
248 gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
249
250 const char *str = PrefsFindString(prefs_item);
251 if (str == NULL)
252 str = "";
253
254 box = gtk_hbox_new(FALSE, 4);
255 gtk_widget_show(box);
256 gtk_table_attach(GTK_TABLE(table), box, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
257
258 entry = gtk_entry_new();
259 gtk_entry_set_text(GTK_ENTRY(entry), str);
260 gtk_widget_show(entry);
261 gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
262
263 button = make_browse_button(entry);
264 gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
265 g_object_set_data(G_OBJECT(entry), "chooser_button", button);
266 return entry;
267 }
268
269 static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
270 {
271 GtkWidget *box, *label, *opt, *menu;
272
273 box = gtk_hbox_new(FALSE, 4);
274 gtk_widget_show(box);
275 gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
276
277 label = gtk_label_new(GetString(label_id));
278 gtk_widget_show(label);
279 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
280
281 opt = gtk_option_menu_new();
282 gtk_widget_show(opt);
283 menu = gtk_menu_new();
284
285 while (options->label_id) {
286 add_menu_item(menu, options->label_id, options->func);
287 options++;
288 }
289 gtk_menu_set_active(GTK_MENU(menu), active);
290
291 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
292 gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0);
293 return menu;
294 }
295
296 static GtkWidget *make_file_entry(GtkWidget *top, int label_id, const char *prefs_item, bool only_dirs = false)
297 {
298 GtkWidget *box, *label, *entry;
299
300 box = gtk_hbox_new(FALSE, 4);
301 gtk_widget_show(box);
302 gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
303
304 label = gtk_label_new(GetString(label_id));
305 gtk_widget_show(label);
306 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
307
308 const char *str = PrefsFindString(prefs_item);
309 if (str == NULL)
310 str = "";
311
312 entry = gtk_entry_new();
313 gtk_entry_set_text(GTK_ENTRY(entry), str);
314 gtk_widget_show(entry);
315 gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
316 return entry;
317 }
318
319 static const gchar *get_file_entry_path(GtkWidget *entry)
320 {
321 return gtk_entry_get_text(GTK_ENTRY(entry));
322 }
323
324 static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func)
325 {
326 GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
327 gtk_widget_show(button);
328 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item));
329 gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button);
330 gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0);
331 return button;
332 }
333
334 static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, GList *glist)
335 {
336 GtkWidget *box, *label, *combo;
337
338 box = gtk_hbox_new(FALSE, 4);
339 gtk_widget_show(box);
340 gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
341
342 label = gtk_label_new(GetString(label_id));
343 gtk_widget_show(label);
344 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
345
346 combo = gtk_combo_new();
347 gtk_widget_show(combo);
348 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
349
350 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value);
351 gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0);
352
353 return combo;
354 }
355
356 static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, const combo_desc *options)
357 {
358 GList *glist = NULL;
359 while (options->label_id) {
360 glist = g_list_append(glist, (void *)GetString(options->label_id));
361 options++;
362 }
363
364 return make_combobox(top, label_id, default_value, glist);
365 }
366
367
368 /*
369 * Show preferences editor
370 * Returns true when user clicked on "Start", false otherwise
371 */
372
373 // Window closed
374 static gint window_closed(void)
375 {
376 return FALSE;
377 }
378
379 // Window destroyed
380 static void window_destroyed(void)
381 {
382 gtk_main_quit();
383 }
384
385 // "Start" button clicked
386 static void cb_start(...)
387 {
388 start_clicked = true;
389 read_settings();
390 SavePrefs();
391 gtk_widget_destroy(win);
392 }
393
394 // "Zap PRAM" button clicked
395 static void cb_zap_pram(...)
396 {
397 ZapPRAM();
398 }
399
400 // "Quit" button clicked
401 static void cb_quit(...)
402 {
403 start_clicked = false;
404 gtk_widget_destroy(win);
405 }
406
407 // "OK" button of "About" dialog clicked
408 static void dl_quit(GtkWidget *dialog)
409 {
410 gtk_widget_destroy(dialog);
411 }
412
413 // "About" button clicked
414 static void cb_about(...)
415 {
416 GtkWidget *dialog;
417
418 GtkWidget *label, *button;
419
420 char str[512];
421 sprintf(str,
422 PROGRAM_NAME "\nVersion %d.%d\n\n"
423 "Copyright (C) 1997-2008 Christian Bauer et al.\n"
424 "E-mail: cb@cebix.net\n"
425 #ifdef SHEEPSHAVER
426 "http://sheepshaver.cebix.net/\n\n"
427 #else
428 "http://basilisk.cebix.net/\n\n"
429 #endif
430 PROGRAM_NAME " comes with ABSOLUTELY NO\n"
431 "WARRANTY. This is free software, and\n"
432 "you are welcome to redistribute it\n"
433 "under the terms of the GNU General\n"
434 "Public License.\n",
435 VERSION_MAJOR, VERSION_MINOR
436 );
437
438 dialog = gtk_dialog_new();
439 gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE));
440 gtk_container_border_width(GTK_CONTAINER(dialog), 5);
441 gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
442
443 label = gtk_label_new(str);
444 gtk_widget_show(label);
445 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
446
447 button = gtk_button_new_with_label(GetString(STR_OK_BUTTON));
448 gtk_widget_show(button);
449 gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
450 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
451 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
452 gtk_widget_grab_default(button);
453
454 gtk_widget_show(dialog);
455 }
456
457 // Menu item descriptions
458 static GtkItemFactoryEntry menu_items[] = {
459 {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, "<Branch>"},
460 {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), "<control>S", GTK_SIGNAL_FUNC(cb_start), 0, NULL},
461 {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(cb_zap_pram), 0, NULL},
462 {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, "<Separator>"},
463 {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "<control>Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL},
464 {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, "<LastBranch>"},
465 {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), "<control>H", GTK_SIGNAL_FUNC(cb_about), 0, NULL}
466 };
467
468 void PrefsMigrate(void)
469 {
470 // Ethernet
471 const char *ether = PrefsFindString("ether");
472 if (ether && ether[0] == '{') {
473 PrefsReplaceString("etherguid", ether);
474 PrefsReplaceString("ether", "b2ether");
475 }
476 if (PrefsFindBool("routerenabled")) {
477 PrefsRemoveItem("etherguid");
478 PrefsReplaceString("ether", "router");
479 }
480 }
481
482 bool PrefsEditor(void)
483 {
484 // Create window
485 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
486 gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE));
487 gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL);
488 gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL);
489
490 // Create window contents
491 GtkWidget *box = gtk_vbox_new(FALSE, 4);
492 gtk_widget_show(box);
493 gtk_container_add(GTK_CONTAINER(win), box);
494
495 GtkAccelGroup *accel_group = gtk_accel_group_new();
496 GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
497 gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL);
498 #if GTK_CHECK_VERSION(1,3,15)
499 gtk_window_add_accel_group(GTK_WINDOW(win), accel_group);
500 #else
501 gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
502 #endif
503 GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "<main>");
504 gtk_widget_show(menu_bar);
505 gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0);
506
507 GtkWidget *notebook = gtk_notebook_new();
508 gtk_widget_show(notebook);
509 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
510 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
511 gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
512
513 create_volumes_pane(notebook);
514 #ifndef DISABLE_SCSI
515 create_scsi_pane(notebook);
516 #endif
517 create_graphics_pane(notebook);
518 create_input_pane(notebook);
519 create_serial_pane(notebook);
520 create_ethernet_pane(notebook);
521 create_memory_pane(notebook);
522 create_jit_pane(notebook);
523
524 static const opt_desc buttons[] = {
525 {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
526 {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
527 {0, NULL}
528 };
529 make_button_box(box, 4, buttons);
530
531 // Show window and enter main loop
532 gtk_widget_show(win);
533 gtk_main();
534 return start_clicked;
535 }
536
537
538 /*
539 * "Volumes" pane
540 */
541
542 static GtkWidget *w_enableextfs, *w_extdrives, *w_cdrom_drive;
543 static GtkWidget *volume_list;
544 static int selected_volume;
545
546 // Set sensitivity of widgets
547 static void set_volumes_sensitive(void)
548 {
549 const bool enable_extfs = PrefsFindBool("enableextfs");
550 gtk_widget_set_sensitive(w_extdrives, enable_extfs);
551 const bool no_cdrom = PrefsFindBool("nocdrom");
552 gtk_widget_set_sensitive(w_cdrom_drive, !no_cdrom);
553 }
554
555 // Volume in list selected
556 static void cl_selected(GtkWidget *list, int row, int column)
557 {
558 selected_volume = row;
559 }
560
561 // Volume selected for addition
562 static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
563 {
564 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
565 gtk_clist_append(GTK_CLIST(volume_list), &file);
566 gtk_widget_destroy(assoc->req);
567 delete assoc;
568 }
569
570 // Volume selected for creation
571 static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
572 {
573 gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
574
575 const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
576 size_t size = atoi(str) << 20;
577
578 int fd = _open(file, _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE);
579 if (fd >= 0) {
580 if (_chsize(fd, size) == 0)
581 gtk_clist_append(GTK_CLIST(volume_list), &file);
582 _close(fd);
583 }
584 gtk_widget_destroy(GTK_WIDGET(assoc->req));
585 delete assoc;
586 }
587
588 // "Add Volume" button clicked
589 static void cb_add_volume(...)
590 {
591 GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE));
592 gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
593 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL));
594 gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
595 gtk_widget_show(req);
596 }
597
598 // "Create Hardfile" button clicked
599 static void cb_create_volume(...)
600 {
601 GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE));
602
603 GtkWidget *box = gtk_hbox_new(FALSE, 4);
604 gtk_widget_show(box);
605 GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL));
606 gtk_widget_show(label);
607 GtkWidget *entry = gtk_entry_new();
608 gtk_widget_show(entry);
609 char str[32];
610 sprintf(str, "%d", 40);
611 gtk_entry_set_text(GTK_ENTRY(entry), str);
612 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
613 gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
614 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0);
615
616 gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
617 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry));
618 gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
619 gtk_widget_show(req);
620 }
621
622 // "Remove Volume" button clicked
623 static void cb_remove_volume(...)
624 {
625 gtk_clist_remove(GTK_CLIST(volume_list), selected_volume);
626 }
627
628 // "Boot From" selected
629 static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
630 static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
631
632 // "Enable external file system" button toggled
633 static void tb_enableextfs(GtkWidget *widget)
634 {
635 PrefsReplaceBool("enableextfs", GTK_TOGGLE_BUTTON(widget)->active);
636 set_volumes_sensitive();
637 }
638
639 // "No CD-ROM Driver" button toggled
640 static void tb_nocdrom(GtkWidget *widget)
641 {
642 PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
643 set_volumes_sensitive();
644 }
645
646 // Add names of CD-ROM devices
647 static GList *add_cdrom_names(void)
648 {
649 GList *glist = NULL;
650
651 char rootdir[4] = "X:\\";
652 for (char letter = 'C'; letter <= 'Z'; letter++) {
653 rootdir[0] = letter;
654 if (GetDriveType(rootdir) == DRIVE_CDROM)
655 glist = g_list_append(glist, strdup(rootdir));
656 }
657
658 return glist;
659 }
660
661 // "Enable polling" button toggled
662 static void tb_pollmedia(GtkWidget *widget)
663 {
664 PrefsReplaceBool("pollmedia", GTK_TOGGLE_BUTTON(widget)->active);
665 }
666
667 // Read settings from widgets and set preferences
668 static void read_volumes_settings(void)
669 {
670 while (PrefsFindString("disk"))
671 PrefsRemoveItem("disk");
672
673 for (int i=0; i<GTK_CLIST(volume_list)->rows; i++) {
674 char *str;
675 gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
676 PrefsAddString("disk", str);
677 }
678
679 const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_cdrom_drive)->entry));
680 if (str && strlen(str))
681 PrefsReplaceString("cdrom", str);
682 else
683 PrefsRemoveItem("cdrom");
684
685 PrefsReplaceString("extdrives", get_file_entry_path(w_extdrives));
686 }
687
688 // Create "Volumes" pane
689 static void create_volumes_pane(GtkWidget *top)
690 {
691 GtkWidget *box, *scroll, *menu;
692
693 box = make_pane(top, STR_VOLUMES_PANE_TITLE);
694
695 scroll = gtk_scrolled_window_new(NULL, NULL);
696 gtk_widget_show(scroll);
697 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
698 volume_list = gtk_clist_new(1);
699 gtk_widget_show(volume_list);
700 gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE);
701 gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE);
702 gtk_clist_set_reorderable(GTK_CLIST(volume_list), true);
703 gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL);
704 char *str;
705 int32 index = 0;
706 while ((str = const_cast<char *>(PrefsFindString("disk", index++))) != NULL)
707 gtk_clist_append(GTK_CLIST(volume_list), &str);
708 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list);
709 gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
710 selected_volume = 0;
711
712 static const opt_desc buttons[] = {
713 {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)},
714 {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)},
715 {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)},
716 {0, NULL},
717 };
718 make_button_box(box, 0, buttons);
719 make_separator(box);
720
721 static const opt_desc options[] = {
722 {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)},
723 {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)},
724 {0, NULL}
725 };
726 int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
727 switch (bootdriver) {
728 case 0: active = 0; break;
729 case CDROMRefNum: active = 1; break;
730 }
731 menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
732
733 make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
734
735 GList *glist = add_cdrom_names();
736 str = const_cast<char *>(PrefsFindString("cdrom"));
737 if (str == NULL)
738 str = "";
739 w_cdrom_drive = make_combobox(box, STR_CDROM_DRIVE_CTRL, str, glist);
740
741 make_checkbox(box, STR_POLLMEDIA_CTRL, "pollmedia", GTK_SIGNAL_FUNC(tb_pollmedia));
742
743 make_separator(box);
744 w_enableextfs = make_checkbox(box, STR_EXTFS_ENABLE_CTRL, "enableextfs", GTK_SIGNAL_FUNC(tb_enableextfs));
745 w_extdrives = make_file_entry(box, STR_EXTFS_DRIVES_CTRL, "extdrives", true);
746
747 set_volumes_sensitive();
748 }
749
750
751 /*
752 * "JIT Compiler" pane
753 */
754
755 #ifndef SHEEPSHAVER
756 static GtkWidget *w_jit_fpu;
757 static GtkWidget *w_jit_atraps;
758 static GtkWidget *w_jit_cache_size;
759 static GtkWidget *w_jit_lazy_flush;
760 static GtkWidget *w_jit_follow_const_jumps;
761 #endif
762
763 // Set sensitivity of widgets
764 static void set_jit_sensitive(void)
765 {
766 #ifndef SHEEPSHAVER
767 const bool jit_enabled = PrefsFindBool("jit");
768 gtk_widget_set_sensitive(w_jit_fpu, jit_enabled);
769 gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled);
770 gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled);
771 gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled);
772 #endif
773 }
774
775 // "Use JIT Compiler" button toggled
776 static void tb_jit(GtkWidget *widget)
777 {
778 PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active);
779 set_jit_sensitive();
780 }
781
782 // "Compile FPU Instructions" button toggled
783 #ifndef SHEEPSHAVER
784 static void tb_jit_fpu(GtkWidget *widget)
785 {
786 PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active);
787 }
788 #endif
789
790 // "Lazy translation cache invalidation" button toggled
791 #ifndef SHEEPSHAVER
792 static void tb_jit_lazy_flush(GtkWidget *widget)
793 {
794 PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active);
795 }
796 #endif
797
798 // "Translate through constant jumps (inline blocks)" button toggled
799 #ifndef SHEEPSHAVER
800 static void tb_jit_follow_const_jumps(GtkWidget *widget)
801 {
802 PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active);
803 }
804 #endif
805
806 // Read settings from widgets and set preferences
807 static void read_jit_settings(void)
808 {
809 #if USE_JIT
810 bool jit_enabled = PrefsFindBool("jit");
811 if (jit_enabled) {
812 #ifndef SHEEPSHAVER
813 const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry));
814 PrefsReplaceInt32("jitcachesize", atoi(str));
815 #endif
816 }
817 #endif
818 }
819
820 // "Use built-in 68k DR emulator" button toggled
821 #ifdef SHEEPSHAVER
822 static void tb_jit_68k(GtkWidget *widget)
823 {
824 PrefsReplaceBool("jit68k", GTK_TOGGLE_BUTTON(widget)->active);
825 }
826 #endif
827
828 // Create "JIT Compiler" pane
829 static void create_jit_pane(GtkWidget *top)
830 {
831 #if USE_JIT
832 GtkWidget *box, *table, *label, *menu;
833 char str[32];
834
835 box = make_pane(top, STR_JIT_PANE_TITLE);
836 make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit));
837
838 #ifndef SHEEPSHAVER
839 w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu));
840
841 // Translation cache size
842 static const combo_desc options[] = {
843 STR_JIT_CACHE_SIZE_2MB_LAB,
844 STR_JIT_CACHE_SIZE_4MB_LAB,
845 STR_JIT_CACHE_SIZE_8MB_LAB,
846 STR_JIT_CACHE_SIZE_16MB_LAB,
847 0
848 };
849 sprintf(str, "%d", PrefsFindInt32("jitcachesize"));
850 w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, str, options);
851
852 // Lazy translation cache invalidation
853 w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush));
854
855 // Follow constant jumps (inline basic blocks)
856 w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps));
857 #endif
858
859 set_jit_sensitive();
860 #endif
861
862 #ifdef SHEEPSHAVER
863 make_checkbox(box, STR_JIT_68K_CTRL, "jit68k", GTK_SIGNAL_FUNC(tb_jit_68k));
864 #endif
865 }
866
867 /*
868 * "SCSI" pane
869 */
870
871 static GtkWidget *w_scsi[7];
872
873 // Read settings from widgets and set preferences
874 static void read_scsi_settings(void)
875 {
876 #ifndef DISABLE_SCSI
877 for (int id=0; id<7; id++) {
878 char prefs_name[32];
879 sprintf(prefs_name, "scsi%d", id);
880 const char *str = get_file_entry_path(w_scsi[id]);
881 if (str && strlen(str))
882 PrefsReplaceString(prefs_name, str);
883 else
884 PrefsRemoveItem(prefs_name);
885 }
886 #endif
887 }
888
889 // Create "SCSI" pane
890 static void create_scsi_pane(GtkWidget *top)
891 {
892 #ifndef DISABLE_SCSI
893 GtkWidget *box;
894
895 box = make_pane(top, STR_SCSI_PANE_TITLE);
896
897 for (int id=0; id<7; id++) {
898 char prefs_name[32];
899 sprintf(prefs_name, "scsi%d", id);
900 w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name);
901 }
902 #endif
903 }
904
905
906 /*
907 * "Graphics/Sound" pane
908 */
909
910 // Display types
911 enum {
912 DISPLAY_WINDOW,
913 DISPLAY_SCREEN
914 };
915
916 static GtkWidget *w_frameskip, *w_display_x, *w_display_y;
917 static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
918 static int display_type;
919 static int dis_width, dis_height;
920
921 // Hide/show graphics widgets
922 static void hide_show_graphics_widgets(void)
923 {
924 switch (display_type) {
925 case DISPLAY_WINDOW:
926 gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
927 break;
928 case DISPLAY_SCREEN:
929 gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
930 break;
931 }
932 }
933
934 // "Window" video type selected
935 static void mn_window(...)
936 {
937 display_type = DISPLAY_WINDOW;
938 hide_show_graphics_widgets();
939 }
940
941 // "Fullscreen" video type selected
942 static void mn_fullscreen(...)
943 {
944 display_type = DISPLAY_SCREEN;
945 hide_show_graphics_widgets();
946 PrefsReplaceInt32("frameskip", 1);
947 }
948
949 // "5 Hz".."60Hz" selected
950 static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
951 static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
952 static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
953 static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
954 static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
955 static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
956 static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
957
958 // QuickDraw acceleration
959 #ifdef SHEEPSHAVER
960 static void tb_gfxaccel(GtkWidget *widget)
961 {
962 PrefsReplaceBool("gfxaccel", GTK_TOGGLE_BUTTON(widget)->active);
963 }
964 #endif
965
966 // Set sensitivity of widgets
967 static void set_graphics_sensitive(void)
968 {
969 const bool sound_enabled = !PrefsFindBool("nosound");
970 }
971
972 // "Disable Sound Output" button toggled
973 static void tb_nosound(GtkWidget *widget)
974 {
975 PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
976 set_graphics_sensitive();
977 }
978
979 // Read graphics preferences
980 static void parse_graphics_prefs(void)
981 {
982 display_type = DISPLAY_WINDOW;
983 #ifdef SHEEPSHAVER
984 dis_width = 640;
985 dis_height = 480;
986 #else
987 dis_width = 512;
988 dis_height = 384;
989 #endif
990
991 const char *str = PrefsFindString("screen");
992 if (str) {
993 if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
994 display_type = DISPLAY_WINDOW;
995 else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
996 display_type = DISPLAY_SCREEN;
997 }
998 }
999
1000 // Read settings from widgets and set preferences
1001 static void read_graphics_settings(void)
1002 {
1003 const char *str;
1004
1005 str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
1006 dis_width = atoi(str);
1007
1008 str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
1009 dis_height = atoi(str);
1010
1011 char pref[256];
1012 switch (display_type) {
1013 case DISPLAY_WINDOW:
1014 sprintf(pref, "win/%d/%d", dis_width, dis_height);
1015 break;
1016 case DISPLAY_SCREEN:
1017 sprintf(pref, "dga/%d/%d", dis_width, dis_height);
1018 break;
1019 default:
1020 PrefsRemoveItem("screen");
1021 return;
1022 }
1023 PrefsReplaceString("screen", pref);
1024 }
1025
1026 // Create "Graphics/Sound" pane
1027 static void create_graphics_pane(GtkWidget *top)
1028 {
1029 GtkWidget *box, *table, *label, *opt, *menu, *combo;
1030 char str[32];
1031
1032 parse_graphics_prefs();
1033
1034 box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
1035 table = make_table(box, 2, 5);
1036
1037 label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
1038 gtk_widget_show(label);
1039 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1040
1041 opt = gtk_option_menu_new();
1042 gtk_widget_show(opt);
1043 menu = gtk_menu_new();
1044 add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window));
1045 add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen));
1046 switch (display_type) {
1047 case DISPLAY_WINDOW:
1048 gtk_menu_set_active(GTK_MENU(menu), 0);
1049 break;
1050 case DISPLAY_SCREEN:
1051 gtk_menu_set_active(GTK_MENU(menu), 1);
1052 break;
1053 }
1054 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
1055 gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1056
1057 l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
1058 gtk_widget_show(l_frameskip);
1059 gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1060
1061 w_frameskip = gtk_option_menu_new();
1062 gtk_widget_show(w_frameskip);
1063 menu = gtk_menu_new();
1064 add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
1065 add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
1066 add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
1067 add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
1068 add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
1069 add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
1070 add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic));
1071 int frameskip = PrefsFindInt32("frameskip");
1072 int item = -1;
1073 switch (frameskip) {
1074 case 12: item = 0; break;
1075 case 8: item = 1; break;
1076 case 6: item = 2; break;
1077 case 4: item = 3; break;
1078 case 2: item = 4; break;
1079 case 1: item = 5; break;
1080 case 0: item = 6; break;
1081 }
1082 if (item >= 0)
1083 gtk_menu_set_active(GTK_MENU(menu), item);
1084 gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
1085 gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1086
1087 l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
1088 gtk_widget_show(l_display_x);
1089 gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1090
1091 combo = gtk_combo_new();
1092 gtk_widget_show(combo);
1093 GList *glist1 = NULL;
1094 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
1095 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
1096 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
1097 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
1098 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
1099 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
1100 if (dis_width)
1101 sprintf(str, "%d", dis_width);
1102 else
1103 strcpy(str, GetString(STR_SIZE_MAX_LAB));
1104 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1105 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1106 w_display_x = GTK_COMBO(combo)->entry;
1107
1108 l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
1109 gtk_widget_show(l_display_y);
1110 gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1111
1112 combo = gtk_combo_new();
1113 gtk_widget_show(combo);
1114 GList *glist2 = NULL;
1115 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
1116 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
1117 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
1118 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
1119 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
1120 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
1121 if (dis_height)
1122 sprintf(str, "%d", dis_height);
1123 else
1124 strcpy(str, GetString(STR_SIZE_MAX_LAB));
1125 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1126 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
1127 w_display_y = GTK_COMBO(combo)->entry;
1128
1129 #ifdef SHEEPSHAVER
1130 make_checkbox(box, STR_GFXACCEL_CTRL, "gfxaccel", GTK_SIGNAL_FUNC(tb_gfxaccel));
1131 #endif
1132
1133 make_separator(box);
1134 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
1135
1136 set_graphics_sensitive();
1137
1138 hide_show_graphics_widgets();
1139 }
1140
1141
1142 /*
1143 * "Input" pane
1144 */
1145
1146 static GtkWidget *w_keycode_file;
1147 static GtkWidget *w_mouse_wheel_lines;
1148
1149 // Set sensitivity of widgets
1150 static void set_input_sensitive(void)
1151 {
1152 const bool use_keycodes = PrefsFindBool("keycodes");
1153 gtk_widget_set_sensitive(w_keycode_file, use_keycodes);
1154 gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes);
1155 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
1156 }
1157
1158 // "Use Raw Keycodes" button toggled
1159 static void tb_keycodes(GtkWidget *widget)
1160 {
1161 PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
1162 set_input_sensitive();
1163 }
1164
1165 // "Mouse Wheel Mode" selected
1166 static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
1167 static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
1168
1169 // Read settings from widgets and set preferences
1170 static void read_input_settings(void)
1171 {
1172 const char *str = get_file_entry_path(w_keycode_file);
1173 if (str && strlen(str))
1174 PrefsReplaceString("keycodefile", str);
1175 else
1176 PrefsRemoveItem("keycodefile");
1177
1178 PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
1179 }
1180
1181 // Create "Input" pane
1182 static void create_input_pane(GtkWidget *top)
1183 {
1184 GtkWidget *box, *hbox, *menu, *label, *button;
1185 GtkObject *adj;
1186
1187 box = make_pane(top, STR_INPUT_PANE_TITLE);
1188
1189 make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
1190
1191 hbox = gtk_hbox_new(FALSE, 4);
1192 gtk_widget_show(hbox);
1193 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1194
1195 label = gtk_label_new(GetString(STR_KEYCODES_CTRL));
1196 gtk_widget_show(label);
1197 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1198
1199 const char *str = PrefsFindString("keycodefile");
1200 if (str == NULL)
1201 str = "";
1202
1203 w_keycode_file = gtk_entry_new();
1204 gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str);
1205 gtk_widget_show(w_keycode_file);
1206 gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0);
1207
1208 button = make_browse_button(w_keycode_file);
1209 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1210 g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button);
1211
1212 make_separator(box);
1213
1214 static const opt_desc options[] = {
1215 {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
1216 {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
1217 {0, NULL}
1218 };
1219 int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
1220 switch (wheelmode) {
1221 case 0: active = 0; break;
1222 case 1: active = 1; break;
1223 }
1224 menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
1225
1226 hbox = gtk_hbox_new(FALSE, 4);
1227 gtk_widget_show(hbox);
1228 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1229
1230 label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
1231 gtk_widget_show(label);
1232 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1233
1234 adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
1235 w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1236 gtk_widget_show(w_mouse_wheel_lines);
1237 gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
1238
1239 set_input_sensitive();
1240 }
1241
1242
1243 /*
1244 * "Serial" pane
1245 */
1246
1247 static GtkWidget *w_seriala, *w_portfile0;
1248 static GtkWidget *w_serialb, *w_portfile1;
1249
1250 // Set sensitivity of widgets
1251 static void set_serial_sensitive(void)
1252 {
1253 const char *str;
1254 bool is_file;
1255
1256 str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1257 is_file = strcmp(str, "FILE") == 0;
1258 gtk_widget_set_sensitive(w_portfile0, is_file);
1259 gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile0), "chooser_button")), is_file);
1260
1261 str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1262 is_file = strcmp(str, "FILE") == 0;
1263 gtk_widget_set_sensitive(w_portfile1, is_file);
1264 gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile1), "chooser_button")), is_file);
1265 }
1266
1267 // Read settings from widgets and set preferences
1268 static void read_serial_settings(void)
1269 {
1270 const char *str;
1271
1272 str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
1273 PrefsReplaceString("seriala", str);
1274
1275 str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
1276 PrefsReplaceString("serialb", str);
1277
1278 str = gtk_entry_get_text(GTK_ENTRY(w_portfile0));
1279 PrefsReplaceString("portfile0", str);
1280
1281 str = gtk_entry_get_text(GTK_ENTRY(w_portfile1));
1282 PrefsReplaceString("portfile1", str);
1283 }
1284
1285 // Port changed in combo
1286 static void cb_serial_port_changed(...)
1287 {
1288 set_serial_sensitive();
1289 }
1290
1291 // Add names of serial devices
1292 static GList *add_serial_names(void)
1293 {
1294 GList *glist = NULL;
1295
1296 static const char *port_names[] = {
1297 "COM1", "COM2", "COM3", "COM4", "COM5", "COM6",
1298 "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6",
1299 "FILE",
1300 NULL
1301 };
1302
1303 for (int i = 0; port_names[i] != NULL; i++)
1304 glist = g_list_append(glist, (void *)port_names[i]);
1305
1306 return glist;
1307 }
1308
1309 // Create "Serial" pane
1310 static void create_serial_pane(GtkWidget *top)
1311 {
1312 GtkWidget *box, *hbox, *table, *label, *combo, *sep, *entry;
1313 GtkObject *adj;
1314
1315 box = make_pane(top, STR_SERIAL_PANE_TITLE);
1316 table = make_table(box, 2, 5);
1317
1318 GList *glist = add_serial_names();
1319 const char *str = PrefsFindString("seriala");
1320 combo = table_make_combobox(table, 0, STR_SERIALA_CTRL, str, glist);
1321 w_seriala = GTK_COMBO(combo)->entry;
1322 gtk_signal_connect(GTK_OBJECT(w_seriala), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL);
1323
1324 w_portfile0 = table_make_file_entry(table, 1, STR_FILE_CTRL, "portfile0");
1325
1326 sep = gtk_hseparator_new();
1327 gtk_widget_show(sep);
1328 gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1329
1330 str = PrefsFindString("serialb");
1331 combo = table_make_combobox(table, 3, STR_SERIALB_CTRL, str, glist);
1332 w_serialb = GTK_COMBO(combo)->entry;
1333 gtk_signal_connect(GTK_OBJECT(w_serialb), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL);
1334
1335 w_portfile1 = table_make_file_entry(table, 4, STR_FILE_CTRL, "portfile1");
1336
1337 set_serial_sensitive();
1338 }
1339
1340
1341 /*
1342 * "Ethernet" pane
1343 */
1344
1345 static GtkWidget *w_ftp_port_list, *w_tcp_port_list;
1346
1347 // Set sensitivity of widgets
1348 static void set_ethernet_sensitive(void)
1349 {
1350 const char *str = PrefsFindString("ether");
1351
1352 bool is_router = str && strcmp(str, "router") == 0;
1353 gtk_widget_set_sensitive(w_ftp_port_list, is_router);
1354 gtk_widget_set_sensitive(w_tcp_port_list, is_router);
1355 }
1356
1357 // Read settings from widgets and set preferences
1358 static void read_ethernet_settings(void)
1359 {
1360 const char *str = PrefsFindString("ether");
1361
1362 bool is_router = str && strcmp(str, "router") == 0;
1363 if (is_router) {
1364 str = gtk_entry_get_text(GTK_ENTRY(w_ftp_port_list));
1365 PrefsReplaceString("ftp_port_list", str);
1366 str = gtk_entry_get_text(GTK_ENTRY(w_tcp_port_list));
1367 PrefsReplaceString("tcp_port", str);
1368 }
1369 }
1370
1371 // Ethernet emulation type changed in menulist
1372 static void cb_ether_changed(...)
1373 {
1374 set_ethernet_sensitive();
1375 }
1376
1377 // Ethernet option "None" selected
1378 static void mn_ether_none(void)
1379 {
1380 PrefsRemoveItem("ether");
1381 PrefsRemoveItem("etherguid");
1382 }
1383
1384 // Ethernet option "Basilisk II Router" selected
1385 static void mn_ether_router(void)
1386 {
1387 PrefsReplaceString("ether", "router");
1388 PrefsRemoveItem("etherguid");
1389 }
1390
1391 // Ethernet option "Basilisk II Slirp" selected
1392 static void mn_ether_slirp(void)
1393 {
1394 PrefsReplaceString("ether", "slirp");
1395 PrefsRemoveItem("etherguid");
1396 }
1397
1398 // Ethernet option for Basilisk II driver selected
1399 static void mn_ether_b2ether(GtkWidget *, const char *guid)
1400 {
1401 PrefsReplaceString("ether", "b2ether");
1402 PrefsReplaceString("etherguid", guid);
1403 }
1404
1405 // Ethernet option for Basilisk II driver selected
1406 static void mn_ether_tap(GtkWidget *, const char *guid)
1407 {
1408 PrefsReplaceString("ether", "tap");
1409 PrefsReplaceString("etherguid", guid);
1410 }
1411
1412 // Create ethernet interfaces menu
1413 static int create_ether_menu(GtkWidget *menu)
1414 {
1415 int active = -1;
1416 int n_items = 0;
1417 const char *ether = PrefsFindString("ether");
1418 const char *etherguid = PrefsFindString("etherguid");
1419
1420 // No Ethernet
1421 add_menu_item(menu, STR_NONE_LAB, (GtkSignalFunc)mn_ether_none);
1422 if (ether == NULL)
1423 active = n_items;
1424 n_items++;
1425
1426 // Basilisk II Router
1427 add_menu_item(menu, "Basilisk II Router", (GtkSignalFunc)mn_ether_router);
1428 if (ether && strcmp(ether, "router") == 0)
1429 active = n_items;
1430 n_items++;
1431
1432 // Basilisk II Slirp
1433 add_menu_item(menu, "Basilisk II Slirp", (GtkSignalFunc)mn_ether_slirp);
1434 if (ether && strcmp(ether, "slirp") == 0)
1435 active = n_items;
1436 n_items++;
1437
1438 // Basilisk II Ethernet Adapter
1439 PacketOpenAdapter("", 0);
1440 {
1441 ULONG sz;
1442 char names[1024];
1443 sz = sizeof(names);
1444 if (PacketGetAdapterNames(NULL, names, &sz) == ERROR_SUCCESS) {
1445 char *p = names;
1446 while (*p) {
1447 const char DEVICE_HEADER[] = "\\Device\\B2ether_";
1448 if (strnicmp(p, DEVICE_HEADER, sizeof(DEVICE_HEADER) - 1) == 0) {
1449 LPADAPTER fd = PacketOpenAdapter(p + sizeof(DEVICE_HEADER) - 1, 0);
1450 if (fd) {
1451 char guid[256];
1452 sprintf(guid, "%s", p + sizeof(DEVICE_HEADER) - 1);
1453 const char *name = ether_guid_to_name(guid);
1454 if (name && (name = g_locale_to_utf8(name, -1, NULL, NULL, NULL))) {
1455 add_menu_item(menu, name, (GtkSignalFunc)mn_ether_b2ether, strdup(guid));
1456 if (etherguid && strcmp(guid, etherguid) == 0 &&
1457 ether && strcmp(ether, "b2ether") == 0)
1458 active = n_items;
1459 n_items++;
1460 }
1461 PacketCloseAdapter(fd);
1462 }
1463 }
1464 p += strlen(p) + 1;
1465 }
1466 }
1467 }
1468 PacketCloseAdapter(NULL);
1469
1470 // TAP-Win32
1471 const char *tap_devices;
1472 if ((tap_devices = ether_tap_devices()) != NULL) {
1473 const char *guid = tap_devices;
1474 while (*guid) {
1475 const char *name = ether_guid_to_name(guid);
1476 if (name && (name = g_locale_to_utf8(name, -1, NULL, NULL, NULL))) {
1477 add_menu_item(menu, name, (GtkSignalFunc)mn_ether_tap, strdup(guid));
1478 if (etherguid && strcmp(guid, etherguid) == 0 &&
1479 ether && strcmp(ether, "tap") == 0)
1480 active = n_items;
1481 n_items++;
1482 }
1483 guid += strlen(guid) + 1;
1484 }
1485 free((char *)tap_devices);
1486 }
1487
1488 return active;
1489 }
1490
1491 // Create "Ethernet" pane
1492 static void create_ethernet_pane(GtkWidget *top)
1493 {
1494 GtkWidget *box, *hbox, *table, *label, *sep, *entry, *opt, *menu, *item;
1495
1496 box = make_pane(top, STR_NETWORK_PANE_TITLE);
1497 table = make_table(box, 2, 5);
1498
1499 label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1500 gtk_widget_show(label);
1501 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1502
1503 opt = gtk_option_menu_new();
1504 gtk_widget_show(opt);
1505 menu = gtk_menu_new();
1506 int active = create_ether_menu(menu);
1507 if (active >= 0)
1508 gtk_menu_set_active(GTK_MENU(menu), active);
1509 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
1510 gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1511 gtk_signal_connect(GTK_OBJECT(opt), "changed", GTK_SIGNAL_FUNC(cb_ether_changed), NULL);
1512
1513 sep = gtk_hseparator_new();
1514 gtk_widget_show(sep);
1515 gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1516
1517 label = gtk_label_new(GetString(STR_ETHER_FTP_PORT_LIST_CTRL));
1518 gtk_widget_show(label);
1519 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1520
1521 entry = gtk_entry_new();
1522 const char *str = PrefsFindString("ftp_port_list");
1523 if (str == NULL)
1524 str = "";
1525 gtk_entry_set_text(GTK_ENTRY(entry), str);
1526 gtk_widget_show(entry);
1527 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1528 w_ftp_port_list = entry;
1529
1530 label = gtk_label_new(GetString(STR_ETHER_TCP_PORT_LIST_CTRL));
1531 gtk_widget_show(label);
1532 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1533
1534 entry = gtk_entry_new();
1535 str = PrefsFindString("tcp_port");
1536 if (str == NULL)
1537 str = "";
1538 gtk_entry_set_text(GTK_ENTRY(entry), str);
1539 gtk_widget_show(entry);
1540 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1541 w_tcp_port_list = entry;
1542
1543 set_ethernet_sensitive();
1544 }
1545
1546
1547 /*
1548 * "Memory/Misc" pane
1549 */
1550
1551 static GtkWidget *w_ramsize;
1552 static GtkWidget *w_rom_file;
1553
1554 // Don't use CPU when idle?
1555 static void tb_idlewait(GtkWidget *widget)
1556 {
1557 PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active);
1558 }
1559
1560 // "Ignore SEGV" button toggled
1561 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1562 static void tb_ignoresegv(GtkWidget *widget)
1563 {
1564 PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
1565 }
1566 #endif
1567
1568 // Model ID selected
1569 static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1570 static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1571
1572 // CPU/FPU type
1573 static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1574 static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1575 static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1576 static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1577 static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1578
1579 // Read settings from widgets and set preferences
1580 static void read_memory_settings(void)
1581 {
1582 const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry));
1583 PrefsReplaceInt32("ramsize", atoi(str) << 20);
1584
1585 str = get_file_entry_path(w_rom_file);
1586 if (str && strlen(str))
1587 PrefsReplaceString("rom", str);
1588 else
1589 PrefsRemoveItem("rom");
1590
1591 }
1592
1593 // Create "Memory/Misc" pane
1594 static void create_memory_pane(GtkWidget *top)
1595 {
1596 GtkWidget *box, *hbox, *table, *label, *scale, *menu;
1597
1598 box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1599 table = make_table(box, 2, 5);
1600
1601 static const combo_desc options[] = {
1602 #ifndef SHEEPSHAVER
1603 STR_RAMSIZE_2MB_LAB,
1604 #endif
1605 STR_RAMSIZE_4MB_LAB,
1606 STR_RAMSIZE_8MB_LAB,
1607 STR_RAMSIZE_16MB_LAB,
1608 STR_RAMSIZE_32MB_LAB,
1609 STR_RAMSIZE_64MB_LAB,
1610 STR_RAMSIZE_128MB_LAB,
1611 STR_RAMSIZE_256MB_LAB,
1612 STR_RAMSIZE_512MB_LAB,
1613 STR_RAMSIZE_1024MB_LAB,
1614 0
1615 };
1616 char default_ramsize[16];
1617 sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20);
1618 w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options);
1619
1620 #ifndef SHEEPSHAVER
1621 static const opt_desc model_options[] = {
1622 {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1623 {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1624 {0, NULL}
1625 };
1626 int modelid = PrefsFindInt32("modelid"), active = 0;
1627 switch (modelid) {
1628 case 5: active = 0; break;
1629 case 14: active = 1; break;
1630 }
1631 table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active);
1632 #endif
1633
1634 #if EMULATED_68K
1635 static const opt_desc cpu_options[] = {
1636 {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1637 {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1638 {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1639 {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1640 {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1641 {0, NULL}
1642 };
1643 int cpu = PrefsFindInt32("cpu");
1644 bool fpu = PrefsFindBool("fpu");
1645 active = 0;
1646 switch (cpu) {
1647 case 2: active = fpu ? 1 : 0; break;
1648 case 3: active = fpu ? 3 : 2; break;
1649 case 4: active = 4;
1650 }
1651 table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active);
1652 #endif
1653
1654 w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom");
1655
1656 make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait));
1657
1658 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
1659 make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
1660 #endif
1661 }
1662
1663
1664 /*
1665 * Read settings from widgets and set preferences
1666 */
1667
1668 static void read_settings(void)
1669 {
1670 read_volumes_settings();
1671 read_scsi_settings();
1672 read_graphics_settings();
1673 read_input_settings();
1674 read_serial_settings();
1675 read_ethernet_settings();
1676 read_memory_settings();
1677 read_jit_settings();
1678 }
1679
1680
1681 /*
1682 * Fake unused data and functions
1683 */
1684
1685 uint8 XPRAM[XPRAM_SIZE];
1686 void MountVolume(void *fh) { }
1687 void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { }
1688 void recycle_write_packet(LPPACKET) { }
1689 VOID CALLBACK packet_read_completion(DWORD, DWORD, LPOVERLAPPED) { }
1690
1691
1692 /*
1693 * Add default serial prefs (must be added, even if no ports present)
1694 */
1695
1696 void SysAddSerialPrefs(void)
1697 {
1698 PrefsAddString("seriala", "COM1");
1699 PrefsAddString("serialb", "COM2");
1700 }
1701
1702
1703 /*
1704 * Display alerts
1705 */
1706
1707 static void display_alert(int title_id, const char *text, int flags)
1708 {
1709 MessageBox(NULL, text, GetString(title_id), MB_OK | flags);
1710 }
1711
1712 void ErrorAlert(const char *text)
1713 {
1714 display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP);
1715 }
1716
1717 void WarningAlert(const char *text)
1718 {
1719 display_alert(STR_WARNING_ALERT_TITLE, text, MB_ICONSTOP);
1720 }
1721
1722
1723 /*
1724 * Start standalone GUI
1725 */
1726
1727 int main(int argc, char *argv[])
1728 {
1729 // Init GTK
1730 gtk_set_locale();
1731 gtk_init(&argc, &argv);
1732
1733 // Read preferences
1734 PrefsInit(NULL, argc, argv);
1735
1736 // Migrate preferences
1737 PrefsMigrate();
1738
1739 // Show preferences editor
1740 bool start = PrefsEditor();
1741
1742 // Exit preferences
1743 PrefsExit();
1744
1745 // Transfer control to the executable
1746 if (start) {
1747 char path[_MAX_PATH];
1748 bool ok = GetModuleFileName(NULL, path, sizeof(path)) != 0;
1749 if (ok) {
1750 char b2_path[_MAX_PATH];
1751 char *p = strrchr(path, '\\');
1752 *++p = '\0';
1753 SetCurrentDirectory(path);
1754 strcpy(b2_path, path);
1755 strcat(b2_path, PROGRAM_NAME);
1756 strcat(b2_path, ".exe");
1757 HINSTANCE h = ShellExecute(GetDesktopWindow(), "open",
1758 b2_path, "", path, SW_SHOWNORMAL);
1759 if ((int)h <= 32)
1760 ok = false;
1761 }
1762 if (!ok) {
1763 ErrorAlert("Coult not start " PROGRAM_NAME " executable");
1764 return 1;
1765 }
1766 }
1767
1768 return 0;
1769 }