ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/prefs_editor_gtk.cpp
Revision: 1.3
Committed: 2005-11-20T17:26:16Z (18 years, 7 months ago) by gbeauche
Branch: MAIN
Changes since 1.2: +113 -106 lines
Log Message:
GUI cosmetics

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