ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
Revision: 1.18
Committed: 2001-07-12T19:48:27Z (23 years, 4 months ago) by cebix
Branch: MAIN
Changes since 1.17: +43 -3 lines
Log Message:
- Implemented AppleTalk-over-UDP tunnelling, activated by setting "udptunnel"
  to "true". This uses the BSD socket API, so it's fairly portable (currently
  only imeplemented under Unix, though). This works by sending raw Ethernet
  packets as UDP packets to a fixed port number ("udpport", default is 6066),
  using IP broadcasts to simulate Ethernet broad- and multicasts. Currently
  only tested with AppleTalk.

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs_editor_gtk.cpp - Preferences editor, Unix implementation using GTK+
3     *
4 cebix 1.15 * Basilisk II (C) 1997-2001 Christian Bauer
5 cebix 1.1 *
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_scsi_pane(GtkWidget *top);
47     static void create_graphics_pane(GtkWidget *top);
48 cebix 1.13 static void create_input_pane(GtkWidget *top);
49 cebix 1.1 static void create_serial_pane(GtkWidget *top);
50     static void create_memory_pane(GtkWidget *top);
51     static void read_settings(void);
52    
53    
54     /*
55     * Utility functions
56     */
57    
58     struct opt_desc {
59     int label_id;
60     GtkSignalFunc func;
61     };
62    
63     static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func)
64     {
65     GtkWidget *item = gtk_menu_item_new_with_label(GetString(label_id));
66     gtk_widget_show(item);
67     gtk_signal_connect(GTK_OBJECT(item), "activate", func, NULL);
68     gtk_menu_append(GTK_MENU(menu), item);
69     }
70    
71     static GtkWidget *make_pane(GtkWidget *notebook, int title_id)
72     {
73     GtkWidget *frame, *label, *box;
74    
75     frame = gtk_frame_new(NULL);
76     gtk_widget_show(frame);
77     gtk_container_border_width(GTK_CONTAINER(frame), 4);
78    
79     label = gtk_label_new(GetString(title_id));
80     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
81    
82     box = gtk_vbox_new(FALSE, 4);
83     gtk_widget_show(box);
84     gtk_container_set_border_width(GTK_CONTAINER(box), 4);
85     gtk_container_add(GTK_CONTAINER(frame), box);
86     return box;
87     }
88    
89     static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons)
90     {
91     GtkWidget *bb, *button;
92    
93     bb = gtk_hbutton_box_new();
94     gtk_widget_show(bb);
95     gtk_container_set_border_width(GTK_CONTAINER(bb), border);
96     gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE);
97     gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4);
98     gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0);
99    
100     while (buttons->label_id) {
101     button = gtk_button_new_with_label(GetString(buttons->label_id));
102     gtk_widget_show(button);
103     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL);
104     gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0);
105     buttons++;
106     }
107     return bb;
108     }
109    
110     static GtkWidget *make_separator(GtkWidget *top)
111     {
112     GtkWidget *sep = gtk_hseparator_new();
113     gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0);
114     gtk_widget_show(sep);
115     return sep;
116     }
117    
118     static GtkWidget *make_table(GtkWidget *top, int x, int y)
119     {
120     GtkWidget *table = gtk_table_new(x, y, FALSE);
121     gtk_widget_show(table);
122     gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0);
123     return table;
124     }
125    
126     static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active)
127     {
128     GtkWidget *box, *label, *opt, *menu;
129    
130     box = gtk_hbox_new(FALSE, 4);
131     gtk_widget_show(box);
132     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
133    
134     label = gtk_label_new(GetString(label_id));
135     gtk_widget_show(label);
136     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
137    
138     opt = gtk_option_menu_new();
139     gtk_widget_show(opt);
140     menu = gtk_menu_new();
141    
142     while (options->label_id) {
143     add_menu_item(menu, options->label_id, options->func);
144     options++;
145     }
146     gtk_menu_set_active(GTK_MENU(menu), active);
147    
148     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
149     gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0);
150     return menu;
151     }
152    
153     static GtkWidget *make_entry(GtkWidget *top, int label_id, const char *prefs_item)
154     {
155     GtkWidget *box, *label, *entry;
156    
157     box = gtk_hbox_new(FALSE, 4);
158     gtk_widget_show(box);
159     gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0);
160    
161     label = gtk_label_new(GetString(label_id));
162     gtk_widget_show(label);
163     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
164    
165     entry = gtk_entry_new();
166     gtk_widget_show(entry);
167     const char *str = PrefsFindString(prefs_item);
168     if (str == NULL)
169     str = "";
170     gtk_entry_set_text(GTK_ENTRY(entry), str);
171     gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
172     return entry;
173     }
174    
175     static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func)
176     {
177     GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
178     gtk_widget_show(button);
179     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item));
180     gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button);
181     gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0);
182     return button;
183     }
184    
185    
186     /*
187     * Show preferences editor
188     * Returns true when user clicked on "Start", false otherwise
189     */
190    
191     // Window closed
192     static gint window_closed(void)
193     {
194     return FALSE;
195     }
196    
197     // Window destroyed
198     static void window_destroyed(void)
199     {
200     gtk_main_quit();
201     }
202    
203     // "Start" button clicked
204     static void cb_start(...)
205     {
206     start_clicked = true;
207     read_settings();
208     SavePrefs();
209     gtk_widget_destroy(win);
210     }
211    
212     // "Quit" button clicked
213     static void cb_quit(...)
214     {
215     start_clicked = false;
216     gtk_widget_destroy(win);
217     }
218    
219     // "OK" button of "About" dialog clicked
220     static void dl_quit(GtkWidget *dialog)
221     {
222     gtk_widget_destroy(dialog);
223     }
224    
225     // "About" selected
226     static void mn_about(...)
227     {
228     GtkWidget *dialog, *label, *button;
229    
230 cebix 1.16 char str[512];
231     sprintf(str,
232     "Basilisk II\nVersion %d.%d\n\n"
233     "Copyright (C) 1997-2001 Christian Bauer et al.\n"
234     "E-mail: Christian.Bauer@uni-mainz.de\n"
235     "http://www.uni-mainz.de/~bauec002/B2Main.html\n\n"
236     "Basilisk II comes with ABSOLUTELY NO\n"
237     "WARRANTY. This is free software, and\n"
238     "you are welcome to redistribute it\n"
239     "under the terms of the GNU General\n"
240     "Public License.\n",
241     VERSION_MAJOR, VERSION_MINOR
242     );
243 cebix 1.1
244     dialog = gtk_dialog_new();
245     gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE));
246     gtk_container_border_width(GTK_CONTAINER(dialog), 5);
247     gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
248    
249     label = gtk_label_new(str);
250     gtk_widget_show(label);
251     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
252    
253     button = gtk_button_new_with_label(GetString(STR_OK_BUTTON));
254     gtk_widget_show(button);
255     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
256     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
257     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
258     gtk_widget_grab_default(button);
259     gtk_widget_show(dialog);
260     }
261    
262     // "Zap PRAM" selected
263     static void mn_zap_pram(...)
264     {
265     ZapPRAM();
266     }
267    
268     // Menu item descriptions
269     static GtkItemFactoryEntry menu_items[] = {
270 cebix 1.4 {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, "<Branch>"},
271     {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), NULL, GTK_SIGNAL_FUNC(cb_start), 0, NULL},
272     {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(mn_zap_pram), 0, NULL},
273     {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, "<Separator>"},
274     {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "<control>Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL},
275     {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, "<LastBranch>"},
276     {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), NULL, GTK_SIGNAL_FUNC(mn_about), 0, NULL}
277 cebix 1.1 };
278    
279     bool PrefsEditor(void)
280     {
281     // Create window
282     win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
283     gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE));
284     gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL);
285     gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL);
286    
287     // Create window contents
288     GtkWidget *box = gtk_vbox_new(FALSE, 4);
289     gtk_widget_show(box);
290     gtk_container_add(GTK_CONTAINER(win), box);
291    
292     GtkAccelGroup *accel_group = gtk_accel_group_new();
293     GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
294     gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL);
295     gtk_accel_group_attach(accel_group, GTK_OBJECT(win));
296     GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "<main>");
297     gtk_widget_show(menu_bar);
298     gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0);
299    
300     GtkWidget *notebook = gtk_notebook_new();
301     gtk_widget_show(notebook);
302     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
303 cebix 1.8 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE);
304 cebix 1.1 gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
305    
306     create_volumes_pane(notebook);
307     create_scsi_pane(notebook);
308     create_graphics_pane(notebook);
309 cebix 1.13 create_input_pane(notebook);
310 cebix 1.1 create_serial_pane(notebook);
311     create_memory_pane(notebook);
312    
313     static const opt_desc buttons[] = {
314     {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)},
315     {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)},
316     {0, NULL}
317     };
318     make_button_box(box, 4, buttons);
319    
320     // Show window and enter main loop
321     gtk_widget_show(win);
322     gtk_main();
323     return start_clicked;
324     }
325    
326    
327     /*
328     * "Volumes" pane
329     */
330    
331 cebix 1.6 static GtkWidget *volume_list, *w_extfs;
332 cebix 1.1 static int selected_volume;
333    
334     // Volume in list selected
335     static void cl_selected(GtkWidget *list, int row, int column)
336     {
337     selected_volume = row;
338     }
339    
340     struct file_req_assoc {
341     file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {}
342     GtkWidget *req;
343     GtkWidget *entry;
344     };
345    
346     // Volume selected for addition
347     static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc)
348     {
349     char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
350     gtk_clist_append(GTK_CLIST(volume_list), &file);
351     gtk_widget_destroy(assoc->req);
352     delete assoc;
353     }
354    
355     // Volume selected for creation
356     static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc)
357     {
358     char *file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req));
359    
360     char *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry));
361     int size = atoi(str);
362    
363     char cmd[1024];
364     sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size);
365     int ret = system(cmd);
366     if (ret == 0)
367     gtk_clist_append(GTK_CLIST(volume_list), &file);
368     gtk_widget_destroy(GTK_WIDGET(assoc->req));
369     delete assoc;
370     }
371    
372     // "Add Volume" button clicked
373     static void cb_add_volume(...)
374     {
375     GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE));
376     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
377     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL));
378     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
379     gtk_widget_show(req);
380     }
381    
382     // "Create Hardfile" button clicked
383     static void cb_create_volume(...)
384     {
385     GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE));
386    
387     GtkWidget *box = gtk_hbox_new(FALSE, 4);
388     gtk_widget_show(box);
389     GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL));
390     gtk_widget_show(label);
391     GtkWidget *entry = gtk_entry_new();
392     gtk_widget_show(entry);
393     char str[32];
394     sprintf(str, "%d", 40);
395     gtk_entry_set_text(GTK_ENTRY(entry), str);
396     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
397     gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
398     gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0);
399    
400     gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
401     gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry));
402     gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req));
403     gtk_widget_show(req);
404     }
405    
406     // "Remove Volume" button clicked
407     static void cb_remove_volume(...)
408     {
409     gtk_clist_remove(GTK_CLIST(volume_list), selected_volume);
410     }
411    
412     // "Boot From" selected
413 cebix 1.14 static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);}
414     static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);}
415 cebix 1.1
416     // "No CD-ROM Driver" button toggled
417     static void tb_nocdrom(GtkWidget *widget)
418     {
419     PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active);
420     }
421    
422     // Read settings from widgets and set preferences
423     static void read_volumes_settings(void)
424     {
425     while (PrefsFindString("disk"))
426     PrefsRemoveItem("disk");
427    
428     for (int i=0; i<GTK_CLIST(volume_list)->rows; i++) {
429     char *str;
430     gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str);
431     PrefsAddString("disk", str);
432     }
433 cebix 1.6
434     PrefsReplaceString("extfs", gtk_entry_get_text(GTK_ENTRY(w_extfs)));
435 cebix 1.1 }
436    
437     // Create "Volumes" pane
438     static void create_volumes_pane(GtkWidget *top)
439     {
440     GtkWidget *box, *scroll, *menu;
441    
442     box = make_pane(top, STR_VOLUMES_PANE_TITLE);
443    
444     scroll = gtk_scrolled_window_new(NULL, NULL);
445     gtk_widget_show(scroll);
446     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
447     volume_list = gtk_clist_new(1);
448     gtk_widget_show(volume_list);
449     gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE);
450     gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE);
451 cebix 1.5 gtk_clist_set_reorderable(GTK_CLIST(volume_list), true);
452 cebix 1.1 gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL);
453     char *str;
454     int32 index = 0;
455     while ((str = (char *)PrefsFindString("disk", index++)) != NULL)
456     gtk_clist_append(GTK_CLIST(volume_list), &str);
457     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list);
458     gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
459     selected_volume = 0;
460    
461     static const opt_desc buttons[] = {
462     {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)},
463     {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)},
464     {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)},
465     {0, NULL},
466     };
467     make_button_box(box, 0, buttons);
468     make_separator(box);
469 cebix 1.6
470     w_extfs = make_entry(box, STR_EXTFS_CTRL, "extfs");
471 cebix 1.1
472     static const opt_desc options[] = {
473     {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)},
474     {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)},
475     {0, NULL}
476     };
477 cebix 1.14 int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
478 cebix 1.1 switch (bootdriver) {
479     case 0: active = 0; break;
480     case CDROMRefNum: active = 1; break;
481     }
482     menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active);
483    
484     make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom));
485     }
486    
487    
488     /*
489     * "SCSI" pane
490     */
491    
492     static GtkWidget *w_scsi[7];
493    
494     // Read settings from widgets and set preferences
495     static void read_scsi_settings(void)
496     {
497     for (int id=0; id<7; id++) {
498     char prefs_name[32];
499     sprintf(prefs_name, "scsi%d", id);
500     const char *str = gtk_entry_get_text(GTK_ENTRY(w_scsi[id]));
501     if (str && strlen(str))
502     PrefsReplaceString(prefs_name, str);
503     else
504     PrefsRemoveItem(prefs_name);
505     }
506     }
507    
508     // Create "SCSI" pane
509     static void create_scsi_pane(GtkWidget *top)
510     {
511     GtkWidget *box;
512    
513     box = make_pane(top, STR_SCSI_PANE_TITLE);
514    
515     for (int id=0; id<7; id++) {
516     char prefs_name[32];
517     sprintf(prefs_name, "scsi%d", id);
518     w_scsi[id] = make_entry(box, STR_SCSI_ID_0 + id, prefs_name);
519     }
520     }
521    
522    
523     /*
524     * "Graphics/Sound" pane
525     */
526    
527     // Display types
528     enum {
529     DISPLAY_WINDOW,
530     DISPLAY_SCREEN
531     };
532    
533     static GtkWidget *w_frameskip, *w_display_x, *w_display_y;
534     static GtkWidget *l_frameskip, *l_display_x, *l_display_y;
535     static int display_type;
536     static int dis_width, dis_height;
537    
538 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
539 cebix 1.7 static GtkWidget *w_fbdev_name, *w_fbdevice_file;
540     static GtkWidget *l_fbdev_name, *l_fbdevice_file;
541     static char fbdev_name[256];
542     #endif
543    
544 cebix 1.1 // Hide/show graphics widgets
545     static void hide_show_graphics_widgets(void)
546     {
547     switch (display_type) {
548     case DISPLAY_WINDOW:
549     gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip);
550 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
551 cebix 1.7 gtk_widget_show(w_display_x); gtk_widget_show(l_display_x);
552     gtk_widget_show(w_display_y); gtk_widget_show(l_display_y);
553     gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name);
554     #endif
555 cebix 1.1 break;
556     case DISPLAY_SCREEN:
557     gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip);
558 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
559 cebix 1.7 gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x);
560     gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y);
561     gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name);
562     #endif
563 cebix 1.1 break;
564     }
565     }
566    
567     // "Window" video type selected
568     static void mn_window(...)
569     {
570     display_type = DISPLAY_WINDOW;
571     hide_show_graphics_widgets();
572     }
573    
574     // "Fullscreen" video type selected
575     static void mn_fullscreen(...)
576     {
577     display_type = DISPLAY_SCREEN;
578     hide_show_graphics_widgets();
579     }
580    
581     // "5 Hz".."60Hz" selected
582     static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);}
583     static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);}
584     static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);}
585     static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);}
586     static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);}
587     static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);}
588 cebix 1.12 static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);}
589 cebix 1.1
590     // "Disable Sound Output" button toggled
591     static void tb_nosound(GtkWidget *widget)
592     {
593     PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active);
594     }
595    
596     // Read graphics preferences
597     static void parse_graphics_prefs(void)
598     {
599     display_type = DISPLAY_WINDOW;
600     dis_width = 512;
601     dis_height = 384;
602 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
603 cebix 1.7 fbdev_name[0] = 0;
604     #endif
605 cebix 1.1
606     const char *str = PrefsFindString("screen");
607     if (str) {
608     if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
609     display_type = DISPLAY_WINDOW;
610 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
611 cebix 1.7 else if (sscanf(str, "dga/%255s", fbdev_name) == 1)
612     #else
613 cebix 1.2 else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
614 cebix 1.7 #endif
615 cebix 1.1 display_type = DISPLAY_SCREEN;
616     }
617     }
618    
619     // Read settings from widgets and set preferences
620     static void read_graphics_settings(void)
621     {
622     const char *str;
623    
624     str = gtk_entry_get_text(GTK_ENTRY(w_display_x));
625     dis_width = atoi(str);
626    
627     str = gtk_entry_get_text(GTK_ENTRY(w_display_y));
628     dis_height = atoi(str);
629    
630     char pref[256];
631     switch (display_type) {
632     case DISPLAY_WINDOW:
633     sprintf(pref, "win/%d/%d", dis_width, dis_height);
634     break;
635     case DISPLAY_SCREEN:
636 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
637 cebix 1.7 str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name));
638     sprintf(pref, "dga/%s", str);
639     #else
640 cebix 1.2 sprintf(pref, "dga/%d/%d", dis_width, dis_height);
641 cebix 1.7 #endif
642 cebix 1.1 break;
643     default:
644     PrefsRemoveItem("screen");
645     return;
646     }
647     PrefsReplaceString("screen", pref);
648     }
649    
650     // Create "Graphics/Sound" pane
651     static void create_graphics_pane(GtkWidget *top)
652     {
653 cebix 1.2 GtkWidget *box, *table, *label, *opt, *menu, *combo;
654 cebix 1.1 char str[32];
655    
656     parse_graphics_prefs();
657    
658     box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE);
659 cebix 1.7 table = make_table(box, 2, 5);
660 cebix 1.1
661     label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL));
662     gtk_widget_show(label);
663     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
664    
665     opt = gtk_option_menu_new();
666     gtk_widget_show(opt);
667     menu = gtk_menu_new();
668     add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window));
669     add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen));
670     switch (display_type) {
671     case DISPLAY_WINDOW:
672     gtk_menu_set_active(GTK_MENU(menu), 0);
673     break;
674     case DISPLAY_SCREEN:
675     gtk_menu_set_active(GTK_MENU(menu), 1);
676     break;
677     }
678     gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
679     gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
680    
681     l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL));
682     gtk_widget_show(l_frameskip);
683     gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
684    
685     w_frameskip = gtk_option_menu_new();
686     gtk_widget_show(w_frameskip);
687     menu = gtk_menu_new();
688     add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz));
689     add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz));
690     add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz));
691     add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz));
692     add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz));
693     add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz));
694 cebix 1.12 add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic));
695 cebix 1.1 int frameskip = PrefsFindInt32("frameskip");
696 cebix 1.12 int item = -1;
697 cebix 1.1 switch (frameskip) {
698 cebix 1.12 case 12: item = 0; break;
699     case 8: item = 1; break;
700     case 6: item = 2; break;
701     case 4: item = 3; break;
702     case 2: item = 4; break;
703     case 1: item = 5; break;
704     case 0: item = 6; break;
705 cebix 1.1 }
706 cebix 1.12 if (item >= 0)
707     gtk_menu_set_active(GTK_MENU(menu), item);
708 cebix 1.1 gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu);
709     gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
710    
711     l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL));
712     gtk_widget_show(l_display_x);
713     gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
714    
715 cebix 1.2 combo = gtk_combo_new();
716     gtk_widget_show(combo);
717     GList *glist1 = NULL;
718 cebix 1.4 glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB));
719     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB));
720     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB));
721     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB));
722     glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB));
723 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1);
724     if (dis_width)
725     sprintf(str, "%d", dis_width);
726     else
727 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
728 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
729     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
730     w_display_x = GTK_COMBO(combo)->entry;
731 cebix 1.1
732     l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL));
733     gtk_widget_show(l_display_y);
734     gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
735    
736 cebix 1.2 combo = gtk_combo_new();
737     gtk_widget_show(combo);
738     GList *glist2 = NULL;
739 cebix 1.4 glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB));
740     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB));
741     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB));
742     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB));
743     glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB));
744 cebix 1.2 gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2);
745     if (dis_height)
746     sprintf(str, "%d", dis_height);
747     else
748 cebix 1.3 strcpy(str, GetString(STR_SIZE_MAX_LAB));
749 cebix 1.2 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
750     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4);
751     w_display_y = GTK_COMBO(combo)->entry;
752 cebix 1.7
753 cebix 1.11 #ifdef ENABLE_FBDEV_DGA
754 cebix 1.7 l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL));
755     gtk_widget_show(l_fbdev_name);
756     gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
757    
758     w_fbdev_name = gtk_entry_new();
759     gtk_widget_show(w_fbdev_name);
760     gtk_entry_set_text(GTK_ENTRY(w_fbdev_name), fbdev_name);
761     gtk_table_attach(GTK_TABLE(table), w_fbdev_name, 1, 2, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
762    
763     w_fbdevice_file = make_entry(box, STR_FBDEVICE_FILE_CTRL, "fbdevicefile");
764     #endif
765 cebix 1.1
766 cebix 1.13 make_separator(box);
767 cebix 1.1 make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound));
768    
769     hide_show_graphics_widgets();
770     }
771    
772    
773     /*
774 cebix 1.13 * "Input" pane
775     */
776    
777     static GtkWidget *w_keycode_file;
778     static GtkWidget *w_mouse_wheel_lines;
779    
780     // Set sensitivity of widgets
781     static void set_input_sensitive(void)
782     {
783     gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
784 cebix 1.14 gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1);
785 cebix 1.13 }
786    
787     // "Use Raw Keycodes" button toggled
788     static void tb_keycodes(GtkWidget *widget)
789     {
790     PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
791     set_input_sensitive();
792     }
793    
794     // "Mouse Wheel Mode" selected
795 cebix 1.14 static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();}
796     static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();}
797 cebix 1.13
798     // Read settings from widgets and set preferences
799     static void read_input_settings(void)
800     {
801     const char *str = gtk_entry_get_text(GTK_ENTRY(w_keycode_file));
802     if (str && strlen(str))
803     PrefsReplaceString("keycodefile", str);
804     else
805     PrefsRemoveItem("keycodefile");
806    
807 cebix 1.14 PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines)));
808 cebix 1.13 }
809    
810     // Create "Input" pane
811     static void create_input_pane(GtkWidget *top)
812     {
813     GtkWidget *box, *hbox, *menu, *label;
814     GtkObject *adj;
815    
816     box = make_pane(top, STR_INPUT_PANE_TITLE);
817    
818     make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
819     w_keycode_file = make_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
820    
821     make_separator(box);
822    
823     static const opt_desc options[] = {
824     {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)},
825     {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)},
826     {0, NULL}
827     };
828 cebix 1.14 int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0;
829 cebix 1.13 switch (wheelmode) {
830     case 0: active = 0; break;
831     case 1: active = 1; break;
832     }
833     menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active);
834    
835     hbox = gtk_hbox_new(FALSE, 4);
836     gtk_widget_show(hbox);
837     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
838    
839     label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL));
840     gtk_widget_show(label);
841     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
842    
843 cebix 1.14 adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0);
844 cebix 1.13 w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
845     gtk_widget_show(w_mouse_wheel_lines);
846     gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0);
847    
848     set_input_sensitive();
849     }
850    
851    
852     /*
853 cebix 1.1 * "Serial/Network" pane
854     */
855    
856 cebix 1.18 static GtkWidget *w_seriala, *w_serialb, *w_ether, *w_udp_port;
857    
858     // Set sensitivity of widgets
859     static void set_serial_sensitive(void)
860     {
861     #if SUPPORTS_UDP_TUNNEL
862     gtk_widget_set_sensitive(w_ether, !PrefsFindBool("udptunnel"));
863     gtk_widget_set_sensitive(w_udp_port, PrefsFindBool("udptunnel"));
864     #endif
865     }
866    
867     // "Tunnel AppleTalk over IP" button toggled
868     static void tb_udptunnel(GtkWidget *widget)
869     {
870     PrefsReplaceBool("udptunnel", GTK_TOGGLE_BUTTON(widget)->active);
871     set_serial_sensitive();
872     }
873 cebix 1.1
874     // Read settings from widgets and set preferences
875     static void read_serial_settings(void)
876     {
877     const char *str;
878    
879     str = gtk_entry_get_text(GTK_ENTRY(w_seriala));
880     PrefsReplaceString("seriala", str);
881    
882     str = gtk_entry_get_text(GTK_ENTRY(w_serialb));
883     PrefsReplaceString("serialb", str);
884    
885     str = gtk_entry_get_text(GTK_ENTRY(w_ether));
886     if (str && strlen(str))
887     PrefsReplaceString("ether", str);
888     else
889     PrefsRemoveItem("ether");
890 cebix 1.18
891     #if SUPPORTS_UDP_TUNNEL
892     PrefsReplaceInt32("udpport", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_udp_port)));
893     #endif
894 cebix 1.1 }
895    
896     // Add names of serial devices
897     static gint gl_str_cmp(gconstpointer a, gconstpointer b)
898     {
899     return strcmp((char *)a, (char *)b);
900     }
901    
902     static GList *add_serial_names(void)
903     {
904     GList *glist = NULL;
905    
906     // Search /dev for ttyS* and lp*
907     DIR *d = opendir("/dev");
908     if (d) {
909     struct dirent *de;
910     while ((de = readdir(d)) != NULL) {
911     #if defined(__linux__)
912     if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) {
913     #elif defined(__FreeBSD__)
914     if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
915 cebix 1.4 #elif defined(__NetBSD__)
916     if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) {
917 cebix 1.1 #elif defined(sgi)
918     if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) {
919     #else
920     if (false) {
921     #endif
922     char *str = new char[64];
923     sprintf(str, "/dev/%s", de->d_name);
924     glist = g_list_append(glist, str);
925     }
926     }
927     closedir(d);
928     }
929     if (glist)
930     g_list_sort(glist, gl_str_cmp);
931     else
932 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
933 cebix 1.1 return glist;
934     }
935    
936     // Add names of ethernet interfaces
937     static GList *add_ether_names(void)
938     {
939     GList *glist = NULL;
940    
941     // Get list of all Ethernet interfaces
942     int s = socket(PF_INET, SOCK_DGRAM, 0);
943     if (s >= 0) {
944     char inbuf[8192];
945     struct ifconf ifc;
946     ifc.ifc_len = sizeof(inbuf);
947     ifc.ifc_buf = inbuf;
948     if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
949     struct ifreq req, *ifr = ifc.ifc_req;
950     for (int i=0; i<ifc.ifc_len; i+=sizeof(ifreq), ifr++) {
951     req = *ifr;
952 cebix 1.4 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(sgi)
953 cebix 1.1 if (ioctl(s, SIOCGIFADDR, &req) == 0 && (req.ifr_addr.sa_family == ARPHRD_ETHER || req.ifr_addr.sa_family == ARPHRD_ETHER+1)) {
954 cebix 1.4 #elif defined(__linux__)
955     if (ioctl(s, SIOCGIFHWADDR, &req) == 0 && req.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
956 cebix 1.1 #else
957 cebix 1.4 if (false) {
958 cebix 1.1 #endif
959     char *str = new char[64];
960     strncpy(str, ifr->ifr_name, 63);
961     glist = g_list_append(glist, str);
962     }
963     }
964     }
965     close(s);
966     }
967     if (glist)
968     g_list_sort(glist, gl_str_cmp);
969     else
970 cebix 1.4 glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB));
971 cebix 1.1 return glist;
972     }
973    
974     // Create "Serial/Network" pane
975     static void create_serial_pane(GtkWidget *top)
976     {
977 cebix 1.18 GtkWidget *box, *hbox, *table, *label, *combo, *sep;
978     GtkObject *adj;
979 cebix 1.1
980     box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE);
981 cebix 1.13 table = make_table(box, 2, 4);
982 cebix 1.1
983     label = gtk_label_new(GetString(STR_SERIALA_CTRL));
984     gtk_widget_show(label);
985     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
986    
987 cebix 1.18 GList *glist = add_serial_names();
988 cebix 1.1 combo = gtk_combo_new();
989     gtk_widget_show(combo);
990     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
991     const char *str = PrefsFindString("seriala");
992     if (str == NULL)
993     str = "";
994     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
995     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
996     w_seriala = GTK_COMBO(combo)->entry;
997    
998     label = gtk_label_new(GetString(STR_SERIALB_CTRL));
999     gtk_widget_show(label);
1000     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1001    
1002     combo = gtk_combo_new();
1003     gtk_widget_show(combo);
1004     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1005     str = PrefsFindString("serialb");
1006     if (str == NULL)
1007     str = "";
1008     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1009     gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1010     w_serialb = GTK_COMBO(combo)->entry;
1011    
1012 cebix 1.13 sep = gtk_hseparator_new();
1013     gtk_widget_show(sep);
1014     gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1015    
1016 cebix 1.1 label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL));
1017     gtk_widget_show(label);
1018 cebix 1.13 gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4);
1019 cebix 1.1
1020     glist = add_ether_names();
1021     combo = gtk_combo_new();
1022     gtk_widget_show(combo);
1023     gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
1024     str = PrefsFindString("ether");
1025     if (str == NULL)
1026     str = "";
1027     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str);
1028 cebix 1.13 gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4);
1029 cebix 1.1 w_ether = GTK_COMBO(combo)->entry;
1030 cebix 1.18
1031     #if SUPPORTS_UDP_TUNNEL
1032     make_checkbox(box, STR_UDPTUNNEL_CTRL, "udptunnel", GTK_SIGNAL_FUNC(tb_udptunnel));
1033    
1034     hbox = gtk_hbox_new(FALSE, 4);
1035     gtk_widget_show(hbox);
1036     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1037    
1038     label = gtk_label_new(GetString(STR_UDPPORT_CTRL));
1039     gtk_widget_show(label);
1040     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1041    
1042     adj = gtk_adjustment_new(PrefsFindInt32("udpport"), 1, 65535, 1, 5, 0);
1043     w_udp_port = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0);
1044     gtk_widget_show(w_udp_port);
1045     gtk_box_pack_start(GTK_BOX(hbox), w_udp_port, FALSE, FALSE, 0);
1046     #endif
1047    
1048     set_serial_sensitive();
1049 cebix 1.1 }
1050    
1051    
1052     /*
1053     * "Memory/Misc" pane
1054     */
1055    
1056     static GtkObject *w_ramsize_adj;
1057     static GtkWidget *w_rom_file;
1058    
1059     // Model ID selected
1060     static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);}
1061     static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);}
1062    
1063 cebix 1.9 // CPU/FPU type
1064     static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);}
1065     static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);}
1066     static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);}
1067     static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);}
1068     static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);}
1069 cebix 1.8
1070 cebix 1.1 // Read settings from widgets and set preferences
1071     static void read_memory_settings(void)
1072     {
1073     PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20);
1074    
1075     const char *str = gtk_entry_get_text(GTK_ENTRY(w_rom_file));
1076     if (str && strlen(str))
1077     PrefsReplaceString("rom", str);
1078     else
1079     PrefsRemoveItem("rom");
1080    
1081     }
1082    
1083     // Create "Memory/Misc" pane
1084     static void create_memory_pane(GtkWidget *top)
1085     {
1086 cebix 1.17 GtkWidget *box, *hbox, *vbox, *hbox2, *label, *scale;
1087 cebix 1.1
1088     box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE);
1089    
1090     hbox = gtk_hbox_new(FALSE, 4);
1091     gtk_widget_show(hbox);
1092    
1093     label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER));
1094     gtk_widget_show(label);
1095     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1096    
1097     vbox = gtk_vbox_new(FALSE, 4);
1098     gtk_widget_show(vbox);
1099    
1100     gfloat min, max;
1101     min = 1;
1102     max = 1024;
1103     w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0);
1104     gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20);
1105    
1106     scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj));
1107     gtk_widget_show(scale);
1108     gtk_scale_set_digits(GTK_SCALE(scale), 0);
1109     gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
1110    
1111     hbox2 = gtk_hbox_new(FALSE, 4);
1112     gtk_widget_show(hbox2);
1113    
1114     char val[32];
1115     sprintf(val, GetString(STR_RAMSIZE_FMT), int(min));
1116     label = gtk_label_new(val);
1117     gtk_widget_show(label);
1118     gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1119    
1120     sprintf(val, GetString(STR_RAMSIZE_FMT), int(max));
1121     label = gtk_label_new(val);
1122     gtk_widget_show(label);
1123     gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1124     gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0);
1125     gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
1126     gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
1127    
1128 cebix 1.9 static const opt_desc model_options[] = {
1129 cebix 1.1 {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)},
1130     {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)},
1131     {0, NULL}
1132     };
1133     int modelid = PrefsFindInt32("modelid"), active = 0;
1134     switch (modelid) {
1135     case 5: active = 0; break;
1136     case 14: active = 1; break;
1137     }
1138 cebix 1.9 make_option_menu(box, STR_MODELID_CTRL, model_options, active);
1139    
1140 cebix 1.11 #if EMULATED_68K
1141 cebix 1.9 static const opt_desc cpu_options[] = {
1142     {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)},
1143     {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)},
1144     {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)},
1145     {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)},
1146     {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)},
1147     {0, NULL}
1148     };
1149     int cpu = PrefsFindInt32("cpu");
1150     bool fpu = PrefsFindBool("fpu");
1151     active = 0;
1152     switch (cpu) {
1153     case 2: active = fpu ? 1 : 0; break;
1154     case 3: active = fpu ? 3 : 2; break;
1155     case 4: active = 4;
1156     }
1157     make_option_menu(box, STR_CPU_CTRL, cpu_options, active);
1158 cebix 1.11 #endif
1159 cebix 1.1
1160     w_rom_file = make_entry(box, STR_ROM_FILE_CTRL, "rom");
1161     }
1162    
1163    
1164     /*
1165     * Read settings from widgets and set preferences
1166     */
1167    
1168     static void read_settings(void)
1169     {
1170     read_volumes_settings();
1171     read_scsi_settings();
1172     read_graphics_settings();
1173 cebix 1.13 read_input_settings();
1174 cebix 1.1 read_serial_settings();
1175     read_memory_settings();
1176     }