ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/prefs_editor_gtk.cpp
Revision: 1.4
Committed: 2005-11-20T21:56:06Z (18 years, 6 months ago) by gbeauche
Branch: MAIN
Changes since 1.3: +65 -9 lines
Log Message:
Windows GUI: fix creation of new volumes, handle "Enable external file system",
"Enable polling", add "Browse" button for keycodes file chooser.

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