ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/prefs_editor_gtk.cpp
Revision: 1.1.1.1 (vendor branch)
Committed: 2002-02-04T16:58:13Z (22 years, 3 months ago) by cebix
Branch: cebix
CVS Tags: start
Changes since 1.1: +0 -0 lines
Log Message:
Imported sources

File Contents

# Content
1 /*
2 * prefs_editor_linux.cpp - Preferences editor, Linux implementation using GTK+
3 *
4 * SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "sysdeps.h"
22
23 #include <gtk/gtk.h>
24 #include <stdlib.h>
25 #include <dirent.h>
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
28 #include <net/if.h>
29 #include <net/if_arp.h>
30
31 #include "user_strings.h"
32 #include "version.h"
33 #include "cdrom.h"
34 #include "xpram.h"
35 #include "prefs.h"
36 #include "prefs_editor.h"
37
38
39 // Global variables
40 static GtkWidget *win; // Preferences window
41 static bool start_clicked = true; // Return value of PrefsEditor() function
42
43
44 // Prototypes
45 static void create_volumes_pane(GtkWidget *top);
46 static void create_graphics_pane(GtkWidget *top);
47 static void create_serial_pane(GtkWidget *top);
48 static void create_memory_pane(GtkWidget *top);
49 static void read_settings(void);
50
51
52 /*
53 * Utility functions
54 */
55
56 struct opt_desc {
57 int label_id;
58 GtkSignalFunc func;
59 };
60
61 static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func)
62 {
63 GtkWidget *item = gtk_menu_item_new_with_label(GetString(label_id));
64 gtk_widget_show(item);
65 gtk_signal_connect(GTK_OBJECT(item), "activate", func, NULL);
66 gtk_menu_append(GTK_MENU(menu), item);
67 }
68
69 static GtkWidget *make_pane(GtkWidget *notebook, int title_id)
70 {
71 GtkWidget *frame, *label, *box;
72
73 frame = gtk_frame_new(NULL);
74 gtk_widget_show(frame);
75 gtk_container_border_width(GTK_CONTAINER(frame), 4);
76
77 label = gtk_label_new(GetString(title_id));
78 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
79
80 box = gtk_vbox_new(FALSE, 4);
81 gtk_widget_show(box);
82 gtk_container_set_border_width(GTK_CONTAINER(box), 4);
83 gtk_container_add(GTK_CONTAINER(frame), box);
84 return box;
85 }
86
87 static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons)
88 {
89 GtkWidget *bb, *button;
90
91 bb = gtk_hbutton_box_new();
92 gtk_widget_show(bb);
93 gtk_container_set_border_width(GTK_CONTAINER(bb), border);
94 gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE);
95 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4);
96 gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0);
97
98 while (buttons->label_id) {
99 button = gtk_button_new_with_label(GetString(buttons->label_id));
100 gtk_widget_show(button);
101 gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL);
102 gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0);
103 buttons++;
104 }
105 return bb;
106 }
107
108 static GtkWidget *make_separator(GtkWidget *top)
109 {
110 GtkWidget *sep = gtk_hseparator_new();
111 gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0);
112 gtk_widget_show(sep);
113 return sep;
114 }
115
116 static GtkWidget *make_table(GtkWidget *top, int x, int y)
117 {
118 GtkWidget *table = gtk_table_new(x, y, FALSE);
119 gtk_widget_show(table);
120 gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0);
121 return table;
122 }
123
124 static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
125 {
126 GtkWidget *box, *label, *opt, *menu;
127
128 box = gtk_hbox_new(FALSE, 4);
129 gtk_widget_show(box);
130 gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
131
132 label = gtk_label_new(GetString(label_id));
133 gtk_widget_show(label);
134 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
135
136 opt = gtk_option_menu_new();
137 gtk_widget_show(opt);
138 menu = gtk_menu_new();
139
140 while (options->label_id) {
141 add_menu_item(menu, options->label_id, options->func);
142 options++;
143 }
144 gtk_menu_set_active(GTK_MENU(menu), active);
145
146 gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
147 gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0);
148 return menu;
149 }
150
151 static GtkWidget *make_entry(GtkWidget *top, int label_id, const char *prefs_item)
152 {
153 GtkWidget *box, *label, *entry;
154
155 box = gtk_hbox_new(FALSE, 4);
156 gtk_widget_show(box);
157 gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
158
159 label = gtk_label_new(GetString(label_id));
160 gtk_widget_show(label);
161 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
162
163 entry = gtk_entry_new();
164 gtk_widget_show(entry);
165 const char *str = PrefsFindString(prefs_item);
166 if (str == NULL)
167 str = "";
168 gtk_entry_set_text(GTK_ENTRY(entry), str);
169 gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
170 return entry;
171 }
172
173 static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func)
174 {
175 GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
176 gtk_widget_show(button);
177 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item));
178 gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button);
179 gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0);
180 return button;
181 }
182
183 static GtkWidget *make_checkbox(GtkWidget *top, int label_id, bool active, GtkSignalFunc func)
184 {
185 GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
186 gtk_widget_show(button);
187 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), active);
188 gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button);
189 gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0);
190 return button;
191 }
192
193
194 /*
195 * Show preferences editor
196 * Returns true when user clicked on "Start", false otherwise
197 */
198
199 // Window closed
200 static gint window_closed(void)
201 {
202 return FALSE;
203 }
204
205 // Window destroyed
206 static void window_destroyed(void)
207 {
208 gtk_main_quit();
209 }
210
211 // "Start" button clicked
212 static void cb_start(...)
213 {
214 start_clicked = true;
215 read_settings();
216 SavePrefs();
217 gtk_widget_destroy(win);
218 }
219
220 // "Quit" button clicked
221 static void cb_quit(...)
222 {
223 start_clicked = false;
224 gtk_widget_destroy(win);
225 }
226
227 // "OK" button of "About" dialog clicked
228 static void dl_quit(GtkWidget *dialog)
229 {
230 gtk_widget_destroy(dialog);
231 }
232
233 // "About" selected
234 static void mn_about(...)
235 {
236 GtkWidget *dialog, *label, *button;
237
238 char str[512];
239 sprintf(str,
240 "SheepShaver\nVersion %d.%d\n\n"
241 "Copyright (C) 1997-2002 Christian Bauer and Marc Hellwig\n"
242 "E-mail: Christian.Bauer@uni-mainz.de\n"
243 "http://www.uni-mainz.de/~bauec002/\n\n"
244 "SheepShaver comes with ABSOLUTELY NO\n"
245 "WARRANTY. This is free software, and\n"
246 "you are welcome to redistribute it\n"
247 "under the terms of the GNU General\n"
248 "Public License.\n",
249 VERSION_MAJOR, VERSION_MINOR
250 );
251
252 dialog = gtk_dialog_new();
253 gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE));
254 gtk_container_border_width(GTK_CONTAINER(dialog), 5);
255 gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
256
257 label = gtk_label_new(str);
258 gtk_widget_show(label);
259 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
260
261 button = gtk_button_new_with_label(GetString(STR_OK_BUTTON));
262 gtk_widget_show(button);
263 gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
264 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
265 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
266 gtk_widget_grab_default(button);
267 gtk_widget_show(dialog);
268 }
269
270 // "Zap NVRAM" selected
271 static void mn_zap_pram(...)
272 {
273 ZapPRAM();
274 }
275
276 // Menu item descriptions
277 static GtkItemFactoryEntry menu_items[] = {
278 {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, "<Branch>"},
279 {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), NULL, GTK_SIGNAL_FUNC(cb_start), 0, NULL},
280 {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(mn_zap_pram), 0, NULL},
281 {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, "<Separator>"},
282 {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "<control>Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL},
283 {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, "<LastBranch>"},
284 {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), NULL, GTK_SIGNAL_FUNC(mn_about), 0, NULL}
285 };
286
287 bool PrefsEditor(void)
288 {
289 // Create window
290 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
291 gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE));
292 gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL);
293 gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL);
294
295 // Create window contents
296 GtkWidget *box = gtk_vbox_new(FALSE, 4);
297 gtk_widget_show(box);
298 gtk_container_add(GTK_CONTAINER(win), box);
299
300 GtkAccelGroup *accel_group = gtk_accel_group_new();
301 GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
302 gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL);
303 gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
304 GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "<main>");
305 gtk_widget_show(menu_bar);
306 gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0);
307
308 GtkWidget *notebook = gtk_notebook_new();
309 gtk_widget_show(notebook);
310 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
311 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
312 gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
313
314 create_volumes_pane(notebook);
315 create_graphics_pane(notebook);
316 create_serial_pane(notebook);
317 create_memory_pane(notebook);
318
319 static const opt_desc buttons[] = {
320 {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
321 {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
322 {0, NULL}
323 };
324 make_button_box(box, 4, buttons);
325
326 // Show window and enter main loop
327 gtk_widget_show(win);
328 gtk_main();
329 return start_clicked;
330 }
331
332
333 /*
334 * "Volumes" pane
335 */
336
337 static GtkWidget *volume_list, *w_extfs;
338 static int selected_volume;
339
340 // Volume in list selected
341 static void cl_selected(GtkWidget *list, int row, int column)
342 {
343 selected_volume = row;
344 }
345
346 struct file_req_assoc {
347 file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
348 GtkWidget *req;
349 GtkWidget *entry;
350 };
351
352 // Volume selected for addition
353 static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
354 {
355 char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
356 gtk_clist_append(GTK_CLIST(volume_list), &file);
357 gtk_widget_destroy(assoc->req);
358 delete assoc;
359 }
360
361 // Volume selected for creation
362 static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
363 {
364 char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
365
366 char *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
367 int size = atoi(str);
368
369 char cmd[1024];
370 sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size);
371 int ret = system(cmd);
372 if (ret == 0)
373 gtk_clist_append(GTK_CLIST(volume_list), &file);
374 gtk_widget_destroy(GTK_WIDGET(assoc->req));
375 delete assoc;
376 }
377
378 // "Add Volume" button clicked
379 static void cb_add_volume(...)
380 {
381 GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE));
382 gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
383 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL));
384 gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
385 gtk_widget_show(req);
386 }
387
388 // "Create Hardfile" button clicked
389 static void cb_create_volume(...)
390 {
391 GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE));
392
393 GtkWidget *box = gtk_hbox_new(FALSE, 4);
394 gtk_widget_show(box);
395 GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL));
396 gtk_widget_show(label);
397 GtkWidget *entry = gtk_entry_new();
398 gtk_widget_show(entry);
399 char str[32];
400 sprintf(str, "%d", 40);
401 gtk_entry_set_text(GTK_ENTRY(entry), str);
402 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
403 gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
404 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0);
405
406 gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
407 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry));
408 gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
409 gtk_widget_show(req);
410 }
411
412 // "Remove Volume" button clicked
413 static void cb_remove_volume(...)
414 {
415 gtk_clist_remove(GTK_CLIST(volume_list), selected_volume);
416 }
417
418 // "Boot From" selected
419 static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
420 static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
421
422 // "No CD-ROM Driver" button toggled
423 static void tb_nocdrom(GtkWidget *widget)
424 {
425 PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
426 }
427
428 // Read settings from widgets and set preferences
429 static void read_volumes_settings(void)
430 {
431 while (PrefsFindString("disk"))
432 PrefsRemoveItem("disk");
433
434 for (int i=0; i<GTK_CLIST(volume_list)->rows; i++) {
435 char *str;
436 gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
437 PrefsAddString("disk", str);
438 }
439
440 PrefsReplaceString("extfs", gtk_entry_get_text(GTK_ENTRY(w_extfs)));
441 }
442
443 // Create "Volumes" pane
444 static void create_volumes_pane(GtkWidget *top)
445 {
446 GtkWidget *box, *scroll, *menu;
447
448 box = make_pane(top, STR_VOLUMES_PANE_TITLE);
449
450 scroll = gtk_scrolled_window_new(NULL, NULL);
451 gtk_widget_show(scroll);
452 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
453 volume_list = gtk_clist_new(1);
454 gtk_widget_show(volume_list);
455 gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE);
456 gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE);
457 gtk_clist_set_reorderable(GTK_CLIST(volume_list), true);
458 gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL);
459 char *str;
460 int32 index = 0;
461 while ((str = (char *)PrefsFindString("disk", index++)) != NULL)
462 gtk_clist_append(GTK_CLIST(volume_list), &str);
463 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list);
464 gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
465 selected_volume = 0;
466
467 static const opt_desc buttons[] = {
468 {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)},
469 {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)},
470 {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)},
471 {0, NULL},
472 };
473 make_button_box(box, 0, buttons);
474 make_separator(box);
475
476 w_extfs = make_entry(box, STR_EXTFS_CTRL, "extfs");
477
478 static const opt_desc options[] = {
479 {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)},
480 {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)},
481 {0, NULL}
482 };
483 int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
484 switch (bootdriver) {
485 case 0: active = 0; break;
486 case CDROMRefNum: active = 1; break;
487 }
488 menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
489
490 make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
491 }
492
493
494 /*
495 * "Graphics/Sound" pane
496 */
497
498 static GtkWidget *w_frameskip;
499
500 // "5 Hz".."60Hz" selected
501 static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
502 static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
503 static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
504 static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
505 static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
506 static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
507
508 // Video modes
509 static void tb_w640x480(GtkWidget *widget)
510 {
511 if (GTK_TOGGLE_BUTTON(widget)->active)
512 PrefsReplaceInt32("windowmodes", PrefsFindInt32("windowmodes") | 1);
513 else
514 PrefsReplaceInt32("windowmodes", PrefsFindInt32("windowmodes") & ~1);
515 }
516
517 static void tb_w800x600(GtkWidget *widget)
518 {
519 if (GTK_TOGGLE_BUTTON(widget)->active)
520 PrefsReplaceInt32("windowmodes", PrefsFindInt32("windowmodes") | 2);
521 else
522 PrefsReplaceInt32("windowmodes", PrefsFindInt32("windowmodes") & ~2);
523 }
524
525 static void tb_fs640x480(GtkWidget *widget)
526 {
527 if (GTK_TOGGLE_BUTTON(widget)->active)
528 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") | 1);
529 else
530 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") & ~1);
531 }
532
533 static void tb_fs800x600(GtkWidget *widget)
534 {
535 if (GTK_TOGGLE_BUTTON(widget)->active)
536 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") | 2);
537 else
538 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") & ~2);
539 }
540
541 static void tb_fs1024x768(GtkWidget *widget)
542 {
543 if (GTK_TOGGLE_BUTTON(widget)->active)
544 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") | 4);
545 else
546 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") & ~4);
547 }
548
549 static void tb_fs1152x900(GtkWidget *widget)
550 {
551 if (GTK_TOGGLE_BUTTON(widget)->active)
552 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") | 8);
553 else
554 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") & ~8);
555 }
556
557 static void tb_fs1280x1024(GtkWidget *widget)
558 {
559 if (GTK_TOGGLE_BUTTON(widget)->active)
560 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") | 16);
561 else
562 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") & ~16);
563 }
564
565 static void tb_fs1600x1200(GtkWidget *widget)
566 {
567 if (GTK_TOGGLE_BUTTON(widget)->active)
568 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") | 32);
569 else
570 PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") & ~32);
571 }
572
573 // "Disable Sound Output" button toggled
574 static void tb_nosound(GtkWidget *widget)
575 {
576 PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
577 }
578
579 // Read settings from widgets and set preferences
580 static void read_graphics_settings(void)
581 {
582 }
583
584 // Create "Graphics/Sound" pane
585 static void create_graphics_pane(GtkWidget *top)
586 {
587 GtkWidget *box, *vbox, *frame;
588
589 box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
590
591 static const opt_desc options[] = {
592 {STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz)},
593 {STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz)},
594 {STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz)},
595 {STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz)},
596 {STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz)},
597 {STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz)},
598 {0, NULL}
599 };
600 int frameskip = PrefsFindInt32("frameskip"), active = 0;
601 switch (frameskip) {
602 case 12: active = 0; break;
603 case 8: active = 1; break;
604 case 6: active = 2; break;
605 case 4: active = 3; break;
606 case 2: active = 4; break;
607 case 1: active = 5; break;
608 }
609 w_frameskip = make_option_menu(box, STR_FRAMESKIP_CTRL, options, active);
610
611 frame = gtk_frame_new (GetString(STR_VIDEO_MODE_CTRL));
612 gtk_widget_show(frame);
613 gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0);
614
615 vbox = gtk_vbox_new(FALSE, 4);
616 gtk_widget_show(vbox);
617 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
618 gtk_container_add(GTK_CONTAINER(frame), vbox);
619
620 make_checkbox(vbox, STR_W_640x480_CTRL, PrefsFindInt32("windowmodes") & 1, GTK_SIGNAL_FUNC(tb_w640x480));
621 make_checkbox(vbox, STR_W_800x600_CTRL, PrefsFindInt32("windowmodes") & 2, GTK_SIGNAL_FUNC(tb_w800x600));
622 make_checkbox(vbox, STR_640x480_CTRL, PrefsFindInt32("screenmodes") & 1, GTK_SIGNAL_FUNC(tb_fs640x480));
623 make_checkbox(vbox, STR_800x600_CTRL, PrefsFindInt32("screenmodes") & 2, GTK_SIGNAL_FUNC(tb_fs800x600));
624 make_checkbox(vbox, STR_1024x768_CTRL, PrefsFindInt32("screenmodes") & 4, GTK_SIGNAL_FUNC(tb_fs1024x768));
625 make_checkbox(vbox, STR_1152x900_CTRL, PrefsFindInt32("screenmodes") & 8, GTK_SIGNAL_FUNC(tb_fs1152x900));
626 make_checkbox(vbox, STR_1280x1024_CTRL, PrefsFindInt32("screenmodes") & 16, GTK_SIGNAL_FUNC(tb_fs1280x1024));
627 make_checkbox(vbox, STR_1600x1200_CTRL, PrefsFindInt32("screenmodes") & 32, GTK_SIGNAL_FUNC(tb_fs1600x1200));
628
629 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
630 }
631
632
633 /*
634 * "Serial/Network" pane
635 */
636
637 static GtkWidget *w_seriala, *w_serialb, *w_ether;
638
639 // Read settings from widgets and set preferences
640 static void read_serial_settings(void)
641 {
642 const char *str;
643
644 str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
645 PrefsReplaceString("seriala", str);
646
647 str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
648 PrefsReplaceString("serialb", str);
649
650 str = gtk_entry_get_text(GTK_ENTRY(w_ether));
651 if (str && strlen(str))
652 PrefsReplaceString("ether", str);
653 else
654 PrefsRemoveItem("ether");
655 }
656
657 // Add names of serial devices
658 static gint gl_str_cmp(gconstpointer a, gconstpointer b)
659 {
660 return strcmp((char *)a, (char *)b);
661 }
662
663 static GList *add_serial_names(void)
664 {
665 GList *glist = NULL;
666
667 // Search /dev for ttyS* and lp*
668 DIR *d = opendir("/dev");
669 if (d) {
670 struct dirent *de;
671 while ((de = readdir(d)) != NULL) {
672 if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
673 char *str = new char[64];
674 sprintf(str, "/dev/%s", de->d_name);
675 glist = g_list_append(glist, str);
676 }
677 }
678 closedir(d);
679 }
680 if (glist)
681 g_list_sort(glist, gl_str_cmp);
682 else
683 glist = g_list_append(glist, (void *)"<none>");
684 return glist;
685 }
686
687 // Add names of ethernet interfaces
688 static GList *add_ether_names(void)
689 {
690 GList *glist = NULL;
691
692 // Get list of all Ethernet interfaces
693 int s = socket(PF_INET, SOCK_DGRAM, 0);
694 if (s >= 0) {
695 char inbuf[8192];
696 struct ifconf ifc;
697 ifc.ifc_len = sizeof(inbuf);
698 ifc.ifc_buf = inbuf;
699 if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
700 struct ifreq req, *ifr = ifc.ifc_req;
701 for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
702 req = *ifr;
703 if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
704 char *str = new char[64];
705 strncpy(str, ifr->ifr_name, 63);
706 glist = g_list_append(glist, str);
707 }
708 }
709 }
710 close(s);
711 }
712 if (glist)
713 g_list_sort(glist, gl_str_cmp);
714 else
715 glist = g_list_append(glist, (void *)"<none>");
716 return glist;
717 }
718
719 // Create "Serial/Network" pane
720 static void create_serial_pane(GtkWidget *top)
721 {
722 GtkWidget *box, *table, *label, *combo;
723 GList *glist = add_serial_names();
724
725 box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
726 table = make_table(box, 2, 3);
727
728 label = gtk_label_new(GetString(STR_SERPORTA_CTRL));
729 gtk_widget_show(label);
730 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
731
732 combo = gtk_combo_new();
733 gtk_widget_show(combo);
734 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
735 const char *str = PrefsFindString("seriala");
736 if (str == NULL)
737 str = "";
738 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
739 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
740 w_seriala = GTK_COMBO(combo)->entry;
741
742 label = gtk_label_new(GetString(STR_SERPORTB_CTRL));
743 gtk_widget_show(label);
744 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
745
746 combo = gtk_combo_new();
747 gtk_widget_show(combo);
748 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
749 str = PrefsFindString("serialb");
750 if (str == NULL)
751 str = "";
752 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
753 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
754 w_serialb = GTK_COMBO(combo)->entry;
755
756 label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
757 gtk_widget_show(label);
758 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
759
760 glist = add_ether_names();
761 combo = gtk_combo_new();
762 gtk_widget_show(combo);
763 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
764 str = PrefsFindString("ether");
765 if (str == NULL)
766 str = "";
767 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
768 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
769 w_ether = GTK_COMBO(combo)->entry;
770 }
771
772
773 /*
774 * "Memory/Misc" pane
775 */
776
777 static GtkObject *w_ramsize_adj;
778 static GtkWidget *w_rom_file;
779
780 // "Ignore SEGV" button toggled
781 static void tb_ignoresegv(GtkWidget *widget)
782 {
783 PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active);
784 }
785
786 // Read settings from widgets and set preferences
787 static void read_memory_settings(void)
788 {
789 PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
790
791 const char *str = gtk_entry_get_text(GTK_ENTRY(w_rom_file));
792 if (str && strlen(str))
793 PrefsReplaceString("rom", str);
794 else
795 PrefsRemoveItem("rom");
796 }
797
798 // Create "Memory/Misc" pane
799 static void create_memory_pane(GtkWidget *top)
800 {
801 GtkWidget *box, *vbox, *hbox, *hbox2, *label, *scale;
802
803 box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
804
805 hbox = gtk_hbox_new(FALSE, 4);
806 gtk_widget_show(hbox);
807
808 label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
809 gtk_widget_show(label);
810 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
811
812 vbox = gtk_vbox_new(FALSE, 4);
813 gtk_widget_show(vbox);
814
815 gfloat min, max;
816 min = 1;
817 max = 256;
818 w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
819 gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
820
821 scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
822 gtk_widget_show(scale);
823 gtk_scale_set_digits(GTK_SCALE(scale), 0);
824 gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
825
826 hbox2 = gtk_hbox_new(FALSE, 4);
827 gtk_widget_show(hbox2);
828
829 char val[32];
830 sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
831 label = gtk_label_new(val);
832 gtk_widget_show(label);
833 gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
834
835 sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
836 label = gtk_label_new(val);
837 gtk_widget_show(label);
838 gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
839 gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
840 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
841 gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
842
843 w_rom_file = make_entry(box, STR_ROM_FILE_CTRL, "rom");
844
845 make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv));
846 }
847
848
849 /*
850 * Read settings from widgets and set preferences
851 */
852
853 static void read_settings(void)
854 {
855 read_volumes_settings();
856 read_graphics_settings();
857 read_serial_settings();
858 read_memory_settings();
859 }