Annotation of uae/src/gui-gtk/gtkui.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * UAE - the Un*x Amiga Emulator
        !             3:  *
        !             4:  * Yet Another User Interface for the X11 version
        !             5:  *
        !             6:  * Copyright 1997, 1998 Bernd Schmidt
        !             7:  * Copyright 1998 Michael Krause
        !             8:  *
        !             9:  * The Tk GUI doesn't work.
        !            10:  * The X Forms Library isn't available as source, and there aren't any
        !            11:  * binaries compiled against glibc
        !            12:  *
        !            13:  * So let's try this...
        !            14:  */
        !            15: 
        !            16: #include "sysconfig.h"
        !            17: #include "sysdeps.h"
        !            18: 
        !            19: #include "options.h"
        !            20: #include "uae.h"
        !            21: #include "memory.h"
        !            22: #include "custom.h"
        !            23: #include "audio.h"
        !            24: #include "gui.h"
        !            25: #include "newcpu.h"
        !            26: #include "autoconf.h"
        !            27: #include "filesys.h"
        !            28: #include "threaddep/thread.h"
        !            29: #include "sounddep/sound.h"
        !            30: #include "savestate.h"
        !            31: #include "debug.h"
        !            32: #include "inputdevice.h"
        !            33: #include "romlist.h"
        !            34: #include "zfile.h"
        !            35: 
        !            36: #include <gtk/gtk.h>
        !            37: #include <gdk/gdk.h>
        !            38: 
        !            39: /* One of the 1.1.6 "features" is a gratuitous name change */
        !            40: #ifndef HAVE_GTK_FEATURES_1_1_6
        !            41: #define gtk_container_set_border_width gtk_container_border_width
        !            42: #endif
        !            43: /* Likewise for 1.1.8.  */
        !            44: #ifndef HAVE_GTK_FEATURES_1_1_8
        !            45: #define gtk_label_set_text gtk_label_set
        !            46: #endif
        !            47: /* This is beginning to suck... */
        !            48: #ifndef HAVE_GTK_FEATURES_1_1_13
        !            49: #define gtk_toggle_button_set_active gtk_toggle_button_set_state
        !            50: #endif
        !            51: 
        !            52: #include "util.h"
        !            53: 
        !            54: static int gui_active, gui_available;
        !            55: 
        !            56: static GtkWidget *gui_window;
        !            57: 
        !            58: static GtkWidget *pause_uae_widget, *snap_save_widget, *snap_load_widget;
        !            59: 
        !            60: static GtkWidget *chipsize_widget[5];
        !            61: static GtkWidget *bogosize_widget[4];
        !            62: static GtkWidget *fastsize_widget[5];
        !            63: static GtkWidget *z3size_widget[10];
        !            64: static GtkWidget *p96size_widget[7];
        !            65: static GtkWidget *rom_text_widget, *rom_path_widget, *key_text_widget;
        !            66: static GtkWidget *romlist_widget, *romsel_button;
        !            67: static int romlist_nr_entries;
        !            68: 
        !            69: static GtkWidget *disk_insert_widget[4], *disk_eject_widget[4], *disk_text_widget[4];
        !            70: static GtkWidget *dftype_widget[4];
        !            71: static GtkWidget *disk_type_widget[4];
        !            72: 
        !            73: static GtkAdjustment *cpuspeed_adj;
        !            74: static GtkWidget *cpuspeed_widgets[4], *cpuspeed_scale;
        !            75: static GtkWidget *cpu_widget[7], *fpu_widget[5];
        !            76: static GtkWidget *sound_widget[4], *sound_ch_widget[3], *sound_interpol_widget[5];
        !            77: static GtkWidget *sound_filter_widget[5];
        !            78: static GtkAdjustment *stereo_sep_adj, *stereo_delay_adj;
        !            79: static GtkWidget *stereo_sep_scale, *stereo_delay_scale;
        !            80: 
        !            81: static GtkWidget *coll_widget[4], *cslevel_widget[4], *ntsc_widget[2];
        !            82: static GtkWidget *mbtype_widget, *mbtype_labelled;
        !            83: static GtkWidget *fcop_widget;
        !            84: 
        !            85: static GtkAdjustment *framerate_adj;
        !            86: static GtkWidget *bimm_widget, *b32_widget, *afscr_widget, *pfscr_widget;
        !            87: 
        !            88: struct scrmode_widgets
        !            89: {
        !            90:     GtkWidget *frame, *modelist;
        !            91:     GtkWidget *hcenter, *vcenter, *aspect, *linedbl, *leds;
        !            92:     GtkWidget *hc_label, *vc_label, *ld_label;
        !            93: };
        !            94: 
        !            95: static struct scrmode_widgets gw_windowed, gw_fullscreen;
        !            96: 
        !            97: static GtkWidget *joy_widget[2][6], *legacy_widget, *kbdlang_widget;
        !            98: 
        !            99: static GtkWidget *led_widgets[5];
        !           100: static GdkColor led_on[5], led_off[5];
        !           101: static unsigned int prevledstate;
        !           102: 
        !           103: static GtkListStore *hd_store;
        !           104: static GtkWidget *hdlist_widget, *bootrom_widget;
        !           105: static GtkWidget *hdchange_button, *hddel_button;
        !           106: static GtkTreeSelection *hd_selection;
        !           107: 
        !           108: static GtkWidget *preset_list, *preset_button;
        !           109: static GtkTreeSelection *preset_selection;
        !           110: 
        !           111: static GtkWidget *req68020, *req68ec020, *req68030, *reqa4000, *reqa1000;
        !           112: static int rom_req;
        !           113: 
        !           114: static GtkWidget *lab_info;
        !           115: static GtkWidget *notebook;
        !           116: 
        !           117: GtkWidget *disk_selector;
        !           118: 
        !           119: static uae_sem_t gui_sem;
        !           120: 
        !           121: /* Copies of certain changed_prefs elements, local to the GUI thread and
        !           122:    protected by the gui_sem.  */
        !           123: static struct gfx_params gfx_w, gfx_f;
        !           124: static char *gui_snapname, *gui_romname, *gui_keyname;
        !           125: static char *new_disk_string[4];
        !           126: 
        !           127: 
        !           128: static smp_comm_pipe to_gui_pipe, from_gui_pipe;
        !           129: 
        !           130: /* Set to ignore the widget callbacks while we're in the process of updating
        !           131:    them with new data.  */
        !           132: static int ignore_gui_changes;
        !           133: 
        !           134: /*
        !           135:  * Messages sent to GUI from UAE via to_gui_pipe
        !           136:  */
        !           137: enum gui_commands {
        !           138:     GUICMD_SHOW,                 // Show yourself
        !           139:     GUICMD_UPDATE,               // Refresh your state from changed preferences
        !           140:     GUICMD_DISKCHANGE,           // Hey! A disk has been changed. Do something!
        !           141:     GUICMD_MSGBOX,               // Display a message box for me, please
        !           142:     GUICMD_NEW_ROMLIST,          // The ROM list has been updated.
        !           143:     GUICMD_FLOPPYDLG,            // Open a floppy insert dialog
        !           144:     GUICMD_FULLSCREEN,           // Fullscreen mode was toggled; update checkboxes
        !           145:     GUICMD_PAUSE,                // We're now paused, in case you didn't notice
        !           146:     GUICMD_UNPAUSE               // We're now running.
        !           147: };
        !           148: 
        !           149: static uae_sem_t gui_sem, gui_init_sem, gui_quit_sem; /* gui_sem protects the DFx fields */
        !           150: 
        !           151: static volatile int quit_gui = 0;
        !           152: 
        !           153: /* Message box functions.  */
        !           154: 
        !           155: 
        !           156: static GtkWidget *make_labelled_button (guchar *label, GtkAccelGroup *accel_group)
        !           157: {
        !           158:     return gtk_button_new_with_mnemonic (label);
        !           159: }
        !           160: 
        !           161: static int find_current_toggle (GtkWidget **widgets, int count)
        !           162: {
        !           163:     int i;
        !           164:     for (i = 0; i < count; i++)
        !           165:        if (GTK_TOGGLE_BUTTON (*widgets++)->active)
        !           166:            return i;
        !           167:     write_log ("GTKUI: Can't happen!\n");
        !           168:     return -1;
        !           169: }
        !           170: 
        !           171: /*
        !           172:  * make_message_box()
        !           173:  *
        !           174:  * This does the actual work of constructing the message dialog.
        !           175:  *
        !           176:  * title   - displayed in the dialog's titlebar
        !           177:  * message - the message itself
        !           178:  * modal   - whether the dialog should block input to the rest of the GUI
        !           179:  * sem     - semaphore used for signalling that the dialog's finished
        !           180:  *
        !           181:  * TODO: Make that semaphore go away. We shouldn't need to know about it here.
        !           182:  */
        !           183: 
        !           184: static void make_message_box (const char *title, const char *message, int modal)
        !           185: {
        !           186:     GtkWidget *dialog;
        !           187:     GtkWidget *vbox, *hbox;
        !           188:     GtkWidget *label;
        !           189: 
        !           190:     if (title == NULL || strlen (title) == 0)
        !           191:        title = PACKAGE_NAME " information";
        !           192:     dialog = gtk_dialog_new_with_buttons (title, NULL,
        !           193:                                          (modal ? GTK_DIALOG_MODAL : 0),
        !           194:                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
        !           195:                                          NULL);
        !           196: 
        !           197:     gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
        !           198: 
        !           199:     vbox = GTK_DIALOG (dialog)->vbox;
        !           200: 
        !           201:     hbox = gtk_hbox_new (FALSE, 0);
        !           202:     gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 20);
        !           203:     gtk_widget_show (hbox);
        !           204: 
        !           205:     label = gtk_label_new (message);
        !           206:     gtk_widget_show (label);
        !           207:     gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 20);
        !           208:     gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
        !           209: 
        !           210:     gtk_dialog_run (GTK_DIALOG (dialog));
        !           211: 
        !           212:     gtk_widget_destroy (dialog);
        !           213: }
        !           214: 
        !           215: static void mkmsgbox (const char *title, const char *message)
        !           216: {
        !           217:     make_message_box (title, message, 1);
        !           218: }
        !           219: 
        !           220: /*
        !           221:  * handle_message_box_request()
        !           222:  *
        !           223:  * This is called from the GUI's context in repsonse to do_message_box()
        !           224:  * to actually create the dialog box
        !           225:  */
        !           226: static void handle_message_box_request (smp_comm_pipe *msg_pipe)
        !           227: {
        !           228:     const char *title = (const char *) read_comm_pipe_pvoid_blocking (msg_pipe);
        !           229:     const char *msg = (const char *) read_comm_pipe_pvoid_blocking (msg_pipe);
        !           230:     int modal = read_comm_pipe_int_blocking (msg_pipe);
        !           231:     uae_sem_t *msg_quit_sem = (uae_sem_t *) read_comm_pipe_pvoid_blocking (msg_pipe);
        !           232: 
        !           233:     make_message_box (title, msg, modal);
        !           234:     uae_sem_post (msg_quit_sem);
        !           235: }
        !           236: 
        !           237: /*
        !           238:  * do_message_box()
        !           239:  *
        !           240:  * This makes up for GTK's lack of a function for creating simple message dialogs.
        !           241:  * It can be called from any context. gui_init() must have been called at some point
        !           242:  * previously.
        !           243:  *
        !           244:  * title   - will be displayed in the dialog's titlebar (or NULL for default)
        !           245:  * message - the message itself
        !           246:  * modal   - should the dialog block input to the rest of the GUI
        !           247:  * wait    - should the dialog wait until the user has acknowledged it
        !           248:  */
        !           249: static void do_message_box (const guchar *title, const guchar *message, gboolean modal, gboolean wait)
        !           250: {
        !           251:     uae_sem_t msg_quit_sem;
        !           252: 
        !           253:     // If we a need reply, then this semaphore which will be used
        !           254:     // to signal us when the dialog has been exited.
        !           255:     uae_sem_init (&msg_quit_sem, 0, 0);
        !           256: 
        !           257:     write_comm_pipe_int   (&to_gui_pipe, GUICMD_MSGBOX, 0);
        !           258:     write_comm_pipe_pvoid (&to_gui_pipe, (void *) title, 0);
        !           259:     write_comm_pipe_pvoid (&to_gui_pipe, (void *) message, 0);
        !           260:     write_comm_pipe_int   (&to_gui_pipe, (int) modal, 0);
        !           261:     write_comm_pipe_pvoid (&to_gui_pipe, wait?&msg_quit_sem:NULL, 1);
        !           262: 
        !           263:     if (wait)
        !           264:        uae_sem_wait (&msg_quit_sem);
        !           265: }
        !           266: 
        !           267: void gui_message (const char *format, ...)
        !           268: {
        !           269:     char msg[2048];
        !           270:     va_list parms;
        !           271: 
        !           272:     va_start (parms,format);
        !           273:     vsprintf ( msg, format, parms);
        !           274:     va_end (parms);
        !           275: 
        !           276:     if (gui_available)
        !           277:        do_message_box (NULL, msg, TRUE, TRUE);
        !           278: 
        !           279:     write_log (msg);
        !           280: }
        !           281: 
        !           282: /* Config save/load.  */
        !           283: 
        !           284: static void save_config (void)
        !           285: {
        !           286:     FILE *f;
        !           287:     char tmp[257];
        !           288: 
        !           289:     /* Backup the options file.  */
        !           290:     strcpy (tmp, optionsfile);
        !           291:     strcat (tmp, "~");
        !           292:     rename (optionsfile, tmp);
        !           293: 
        !           294:     f = fopen (optionsfile, "w");
        !           295:     if (f == NULL) {
        !           296:        write_log ("Error saving options file!\n");
        !           297:        return;
        !           298:     }
        !           299:     save_options (f, &changed_prefs);
        !           300:     fclose (f);
        !           301: }
        !           302: 
        !           303: static int nr_for_led (GtkWidget *led)
        !           304: {
        !           305:     int i;
        !           306:     i = 0;
        !           307:     while (led_widgets[i] != led)
        !           308:        i++;
        !           309:     return i;
        !           310: }
        !           311: 
        !           312: static void enable_disk_buttons (int enable)
        !           313: {
        !           314:     int i;
        !           315:     for (i = 0; i < 4; i++) {
        !           316:        drive_type t = changed_prefs.dfxtype[i];
        !           317:        gtk_widget_set_sensitive (disk_insert_widget[i], enable && t != DRV_NONE);
        !           318:        gtk_widget_set_sensitive (disk_eject_widget[i], enable && t != DRV_NONE);
        !           319:        gtk_widget_set_sensitive (dftype_widget[i], enable);
        !           320:     }
        !           321: }
        !           322: 
        !           323: static void set_disk_state (void)
        !           324: {
        !           325:     int i;
        !           326:     ignore_gui_changes++;
        !           327:     for (i = 0; i < 4; i++) {
        !           328:        drive_type t = changed_prefs.dfxtype[i];
        !           329:        int n;
        !           330:        if (i == 0)
        !           331:            n = t == DRV_35_DD ? 0 : 1;
        !           332:        else
        !           333:            n = t == DRV_35_DD ? 1 : t == DRV_35_HD ? 2 : 0;
        !           334:        gtk_combo_box_set_active (GTK_COMBO_BOX (dftype_widget[i]), n);
        !           335:     }
        !           336:     ignore_gui_changes--;
        !           337: }
        !           338: 
        !           339: static void set_romlist_state (void)
        !           340: {
        !           341:     int i;
        !           342:     int active_entry = 0;
        !           343: 
        !           344:     for (i = 1; i < romlist_nr_entries; i++)
        !           345:        gtk_combo_box_remove_text (GTK_COMBO_BOX (romlist_widget), 1);
        !           346:     romlist_nr_entries = 1;
        !           347: 
        !           348:     for (i = 0;; i++) {
        !           349:        struct romlist *rl = romlist_from_idx (i, ROMTYPE_KICK, 1);
        !           350:        if (!rl)
        !           351:            break;
        !           352:        if ((changed_prefs.rom_crc32 != 0 && rl->rd->crc32 == changed_prefs.rom_crc32)
        !           353:            || (changed_prefs.rom_crc32 == 0 && strcmp (rl->path, changed_prefs.romfile) == 0))
        !           354:            active_entry = romlist_nr_entries;
        !           355:        gtk_combo_box_append_text (GTK_COMBO_BOX (romlist_widget), rl->rd->name);
        !           356:        romlist_nr_entries++;
        !           357:     }
        !           358:     gtk_combo_box_set_active (GTK_COMBO_BOX (romlist_widget), active_entry);
        !           359:     gtk_widget_set_sensitive (romsel_button, active_entry == 0);
        !           360:     gtk_widget_set_sensitive (rom_text_widget, active_entry == 0);
        !           361: }
        !           362: 
        !           363: static void set_cpu_state (void)
        !           364: {
        !           365:     gtk_widget_set_sensitive (cpuspeed_scale, changed_prefs.m68k_speed > 0);
        !           366: 
        !           367:     gtk_widget_set_sensitive (fpu_widget[0], changed_prefs.cpu_model != 68040 && changed_prefs.cpu_model != 68060);
        !           368:     gtk_widget_set_sensitive (fpu_widget[1], changed_prefs.cpu_model == 68020 || changed_prefs.cpu_model == 68030);
        !           369:     gtk_widget_set_sensitive (fpu_widget[2], changed_prefs.cpu_model == 68020 || changed_prefs.cpu_model == 68030);
        !           370:     gtk_widget_set_sensitive (fpu_widget[3], changed_prefs.cpu_model == 68040);
        !           371:     gtk_widget_set_sensitive (fpu_widget[4], changed_prefs.cpu_model == 68060);
        !           372: }
        !           373: 
        !           374: static void set_cpu_widget (void)
        !           375: {
        !           376:     int nr = (changed_prefs.cpu_model == 68000 ? 0
        !           377:              : changed_prefs.cpu_model == 68010 ? 1
        !           378:              : changed_prefs.cpu_model == 68020 ? 2
        !           379:              : changed_prefs.cpu_model == 68030 ? 4
        !           380:              : changed_prefs.cpu_model == 68040 ? 5
        !           381:              : 6);
        !           382: 
        !           383:     if (nr == 2 && !changed_prefs.address_space_24)
        !           384:        nr++;
        !           385:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cpu_widget[nr]), TRUE);
        !           386: 
        !           387:     nr = (changed_prefs.fpu_model == 68881 ? 1
        !           388:          : changed_prefs.fpu_model == 68882 ? 2
        !           389:          : changed_prefs.cpu_model == 68040 ? 3
        !           390:          : changed_prefs.cpu_model == 68060 ? 4
        !           391:          : 0);
        !           392:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fpu_widget[nr]), TRUE);
        !           393:     nr = changed_prefs.m68k_speed + 1 < 3 ? changed_prefs.m68k_speed + 1 : 2;
        !           394:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cpuspeed_widgets[nr]), TRUE);
        !           395: }
        !           396: 
        !           397: /* The idea behind this is to keep entries in aspect/centering boxes even
        !           398:    if a screen mode is selected where they are unnecessary, but set the
        !           399:    prefs to sane values.  */
        !           400: static void adjust_gfx_prefs (struct gfx_params *gp, struct scrmode_widgets *w)
        !           401: {
        !           402:     int need_hcenter, need_vcenter, need_aspect, need_linedbl;
        !           403:     need_hcenter = gp->width < 400 || (gp->width > 512 && gp->width < 800);
        !           404:     need_vcenter = gp->height <= 256 || (gp->height > 300 && gp->height <= 512);
        !           405:     need_linedbl = gp->height >= 400;
        !           406:     need_aspect = ((gp->height < 256 || (gp->height > 300 && gp->height < 512))
        !           407:                   && gp->height * 5 / 4 < gp->width);
        !           408: 
        !           409:     gtk_widget_set_sensitive (w->vc_label, need_vcenter);
        !           410:     gtk_widget_set_sensitive (w->hc_label, need_hcenter);
        !           411:     gtk_widget_set_sensitive (w->aspect, need_aspect);
        !           412:     gtk_widget_set_sensitive (w->ld_label, need_linedbl);
        !           413: 
        !           414:     if (!need_linedbl)
        !           415:        gp->linedbl = 0;
        !           416:     if (!need_aspect)
        !           417:        gp->correct_aspect = FALSE;
        !           418:     if (!need_vcenter)
        !           419:        gp->ycenter = 0;
        !           420:     if (!need_hcenter)
        !           421:        gp->xcenter = 0;
        !           422: }
        !           423: 
        !           424: static void set_gfx_mode_state (struct gfx_params *gp, struct scrmode_widgets *w)
        !           425: {
        !           426:     ignore_gui_changes++;
        !           427: 
        !           428:     gtk_combo_box_set_active (GTK_COMBO_BOX (w->linedbl), gp->linedbl ? gp->linedbl - 1 : 1);
        !           429:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w->aspect), gp->correct_aspect);
        !           430:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w->leds), gp->leds_on_screen);
        !           431: 
        !           432:     gtk_combo_box_set_active (GTK_COMBO_BOX (w->hcenter), gp->xcenter);
        !           433:     gtk_combo_box_set_active (GTK_COMBO_BOX (w->vcenter), gp->ycenter);
        !           434:     ignore_gui_changes--;
        !           435: }
        !           436: 
        !           437: static void set_fullscreen_state (void)
        !           438: {
        !           439:     ignore_gui_changes++;
        !           440:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (afscr_widget), changed_prefs.gfx_afullscreen != 0);
        !           441:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pfscr_widget), changed_prefs.gfx_pfullscreen != 0);
        !           442:     ignore_gui_changes--;
        !           443: }
        !           444: 
        !           445: static void set_gfx_state (void)
        !           446: {
        !           447:     int t;
        !           448: 
        !           449:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bimm_widget), changed_prefs.immediate_blits != 0);
        !           450: 
        !           451:     ignore_gui_changes++;
        !           452:     uae_sem_wait (&gui_sem);
        !           453:     t = fixup_prefs_dimensions (&gfx_w, gfx_windowed_modes, n_windowed_modes);
        !           454:     gtk_combo_box_set_active (GTK_COMBO_BOX (gw_windowed.modelist), t);
        !           455:     t = fixup_prefs_dimensions (&gfx_f, gfx_fullscreen_modes, n_fullscreen_modes);
        !           456:     gtk_combo_box_set_active (GTK_COMBO_BOX (gw_fullscreen.modelist), t);
        !           457:     ignore_gui_changes--;
        !           458: 
        !           459:     adjust_gfx_prefs (&gfx_w, &gw_windowed);
        !           460:     adjust_gfx_prefs (&gfx_f, &gw_fullscreen);
        !           461:     uae_sem_post (&gui_sem);
        !           462: 
        !           463:     set_gfx_mode_state (&gfx_w, &gw_windowed);
        !           464:     set_gfx_mode_state (&gfx_f, &gw_fullscreen);
        !           465: 
        !           466:     set_fullscreen_state ();
        !           467: #if 0
        !           468:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b32_widget), changed_prefs.blits_32bit_enabled != 0);
        !           469: #endif
        !           470: }
        !           471: 
        !           472: /* The intended behaviour here is that on startup, and when loading a state
        !           473:    file, we examine the prefs to see if they match a given motherboard, and
        !           474:    initialize the combo box accordingly.  When the user changes it, default
        !           475:    settings are automatically chosen unless the user sets "Generic", in which
        !           476:    case he has control over all the options.  */
        !           477: static void discover_cstype (void)
        !           478: {
        !           479:     int t0;
        !           480:     int cstype = cstype_from_prefs (&changed_prefs);
        !           481: 
        !           482:     t0 = (cstype == CP_GENERIC ? 0
        !           483:          : cstype == CP_A1000 ? 1
        !           484:          : cstype == CP_A500 || cstype == CP_A500P ? 2
        !           485:          : cstype == CP_A600 ? 3
        !           486:          : cstype == CP_A1200 ? 4
        !           487:          : cstype == CP_A3000 ? 5
        !           488:          : 6);
        !           489: 
        !           490:     ignore_gui_changes++;
        !           491:     gtk_combo_box_set_active (GTK_COMBO_BOX (mbtype_widget), t0);
        !           492:     ignore_gui_changes--;
        !           493: }
        !           494: 
        !           495: static void set_chipset_state (void)
        !           496: {
        !           497:     int t0 = 0;
        !           498: 
        !           499:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (coll_widget[changed_prefs.collision_level]), TRUE);
        !           500:     if (changed_prefs.chipset_mask & CSMASK_AGA)
        !           501:        t0 = 3;
        !           502:     else if (changed_prefs.chipset_mask & CSMASK_ECS_DENISE)
        !           503:        t0 = 2;
        !           504:     else if (changed_prefs.chipset_mask & CSMASK_ECS_AGNUS)
        !           505:        t0 = 1;
        !           506:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cslevel_widget[t0]), TRUE);
        !           507: }
        !           508: 
        !           509: static void set_sound_state (void)
        !           510: {
        !           511:     int n;
        !           512:     int stereo = changed_prefs.sound_stereo;
        !           513: 
        !           514:     gtk_widget_set_sensitive (stereo_sep_scale, changed_prefs.sound_stereo != SND_MONO);
        !           515:     gtk_widget_set_sensitive (stereo_delay_scale, changed_prefs.sound_stereo != SND_MONO);
        !           516: 
        !           517:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_widget[changed_prefs.produce_sound]), 1);
        !           518:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_ch_widget[stereo]), 1);
        !           519:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_interpol_widget[changed_prefs.sound_interpol]), 1);
        !           520:     n = (changed_prefs.sound_filter == FILTER_SOUND_OFF ? 0
        !           521:         : ((changed_prefs.sound_filter == FILTER_SOUND_EMUL ? 1 : 2)
        !           522:            + (changed_prefs.sound_filter_type == FILTER_SOUND_TYPE_A500 ? 0 : 2)));
        !           523:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_filter_widget[n]), 1);
        !           524: }
        !           525: 
        !           526: static void set_mem_state (void)
        !           527: {
        !           528:     int bogo2m_ok;
        !           529:     int t, t2, i;
        !           530: 
        !           531:     for (i = 0; i < 10; i++)
        !           532:        gtk_widget_set_sensitive (z3size_widget[i], ! changed_prefs.address_space_24);
        !           533:     for (i = 0; i < 7; i++)
        !           534:        gtk_widget_set_sensitive (p96size_widget[i],
        !           535:                                  changed_prefs.bootrom && ! changed_prefs.address_space_24);
        !           536: 
        !           537:     bogo2m_ok = !((changed_prefs.chipset_mask & CSMASK_AGA) || changed_prefs.cpu_model >= 68020);
        !           538:     gtk_widget_set_sensitive (bogosize_widget[3], bogo2m_ok);
        !           539:                              
        !           540:     t = 0;
        !           541:     t2 = changed_prefs.chipmem_size;
        !           542:     while (t < 4 && t2 > 0x80000)
        !           543:        t++, t2 >>= 1;
        !           544:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chipsize_widget[t]), 1);
        !           545: 
        !           546:     t = 0;
        !           547:     t2 = changed_prefs.bogomem_size;
        !           548:     if (t2 > 0x100000 && !bogo2m_ok)
        !           549:        t2 = 0x100000;
        !           550:     changed_prefs.bogomem_size = t2;
        !           551:     while (t < 3 && t2 >= 0x80000)
        !           552:        t++, t2 >>= 1;
        !           553:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bogosize_widget[t]), 1);
        !           554: 
        !           555:     t = 0;
        !           556:     t2 = changed_prefs.fastmem_size;
        !           557:     while (t < 4 && t2 >= 0x100000)
        !           558:        t++, t2 >>= 1;
        !           559:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fastsize_widget[t]), 1);
        !           560: 
        !           561:     t = 0;
        !           562:     t2 = changed_prefs.z3fastmem_size;
        !           563:     while (t < 9 && t2 >= 0x100000)
        !           564:        t++, t2 >>= 1;
        !           565:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (z3size_widget[t]), 1);
        !           566: 
        !           567:     t = 0;
        !           568:     t2 = changed_prefs.gfxmem_size;
        !           569:     while (t < 6 && t2 >= 0x100000)
        !           570:        t++, t2 >>= 1;
        !           571:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (p96size_widget[t]), 1);
        !           572: 
        !           573:     gtk_label_set_text (GTK_LABEL (rom_path_widget), changed_prefs.path_rom);
        !           574:     gtk_label_set_text (GTK_LABEL (rom_text_widget), changed_prefs.romfile);
        !           575:     gtk_label_set_text (GTK_LABEL (key_text_widget), changed_prefs.keyfile);
        !           576: }
        !           577: 
        !           578: static void set_joy_state (void)
        !           579: {
        !           580:     int joy_count = inputdevice_get_device_total (IDTYPE_JOYSTICK);
        !           581:     int j0j = jsem_isjoy (0, &changed_prefs);
        !           582:     int j0m = jsem_ismouse (0, &changed_prefs);
        !           583:     int j0k = jsem_iskbdjoy (0, &changed_prefs);
        !           584:     int j1j = jsem_isjoy (1, &changed_prefs);
        !           585:     int j1m = jsem_ismouse (1, &changed_prefs);
        !           586:     int j1k = jsem_iskbdjoy (1, &changed_prefs);
        !           587:     int j0t = (j0j == 0 || j0j == 1 ? j0j
        !           588:               : j0m == 0 ? 2
        !           589:               : j0k + 3);
        !           590:     int j1t = (j1j == 0 || j1j == 1 ? j1j
        !           591:               : j1m == 0 ? 2
        !           592:               : j1k + 3);
        !           593:     int i;
        !           594: 
        !           595:     if (j0t == j1t) {
        !           596:        /* Can't happen */
        !           597:        j0t++;
        !           598:        j0t %= 6;
        !           599:     }
        !           600: 
        !           601:     for (i = 0; i < 6; i++) {
        !           602:        int available = i >= 2 || joy_count > i;
        !           603:        if (changed_prefs.input_selected_setting != 0)
        !           604:            available = 0;
        !           605:        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (joy_widget[0][i]), j0t == i);
        !           606:        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (joy_widget[1][i]), j1t == i);
        !           607:        gtk_widget_set_sensitive (joy_widget[0][i], available && j1t != i);
        !           608:        gtk_widget_set_sensitive (joy_widget[1][i], available && j0t != i);
        !           609:     }
        !           610: 
        !           611:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (legacy_widget),
        !           612:                                  changed_prefs.input_selected_setting == 0);
        !           613: 
        !           614:     gtk_combo_box_set_active (GTK_COMBO_BOX (kbdlang_widget),
        !           615:                              changed_prefs.keyboard_lang);
        !           616: }
        !           617: 
        !           618: static void set_hd_state (void)
        !           619: {
        !           620:     char texts[9][256];
        !           621:     int nr = nr_units (currprefs.mountinfo);
        !           622:     int i;
        !           623: 
        !           624:     gtk_list_store_clear (hd_store);
        !           625:     for (i = 0; i < nr; i++) {
        !           626:        GtkTreeIter iter;
        !           627:        int secspertrack, surfaces, reserved, blocksize, size;
        !           628:        int cylinders, readonly, pri;
        !           629:        char *volname, *rootdir, *devname;
        !           630:        char *failure;
        !           631: 
        !           632:        /* We always use currprefs.mountinfo for the GUI.  The filesystem
        !           633:           code makes a private copy which is updated every reset.  */
        !           634:        failure = get_filesys_unit (currprefs.mountinfo, i,
        !           635:                                    &devname, &volname, &rootdir, &readonly,
        !           636:                                    &secspertrack, &surfaces, &reserved,
        !           637:                                    &cylinders, &size, &blocksize, &pri);
        !           638: 
        !           639:        if (is_hardfile (currprefs.mountinfo, i)) {
        !           640:            sprintf (texts[0], "DH%d", i );
        !           641:            sprintf (texts[3], "%d", surfaces);
        !           642:            sprintf (texts[4], "%d", cylinders);
        !           643:            sprintf (texts[5], "%d", secspertrack);
        !           644:            sprintf (texts[6], "%d", reserved);
        !           645:            sprintf (texts[7], "%d", size);
        !           646:            sprintf (texts[8], "%d", blocksize);
        !           647:        } else {
        !           648:            strcpy (texts[0], volname);
        !           649:            strcpy (texts[3], "n/a");
        !           650:            strcpy (texts[4], "n/a");
        !           651:            strcpy (texts[5], "n/a");
        !           652:            strcpy (texts[6], "n/a");
        !           653:            strcpy (texts[7], "n/a");
        !           654:            strcpy (texts[8], "n/a");
        !           655:        }
        !           656:        strcpy (texts[1], rootdir);
        !           657:        gtk_list_store_append (hd_store, &iter);
        !           658: 
        !           659:        gtk_list_store_set (hd_store, &iter,
        !           660:                            0, i,
        !           661:                            1, texts[0],
        !           662:                            2, texts[1],
        !           663:                            3, readonly,
        !           664:                            4, texts[3],
        !           665:                            5, texts[4],
        !           666:                            6, texts[5],
        !           667:                            7, texts[6],
        !           668:                            8, texts[7],
        !           669:                            9, texts[8],
        !           670:                            10, pri,
        !           671:                            -1);
        !           672:        if (volname)
        !           673:            free (volname);
        !           674:        if (devname)
        !           675:            free (devname);
        !           676:        if (rootdir)
        !           677:            free (rootdir);
        !           678:     }
        !           679:     gtk_widget_set_sensitive (hdchange_button, FALSE);
        !           680:     gtk_widget_set_sensitive (hddel_button, FALSE);
        !           681: 
        !           682:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bootrom_widget),
        !           683:                                  changed_prefs.bootrom != 0);
        !           684: }
        !           685: 
        !           686: static void rom_requirements_change (void)
        !           687: {
        !           688:     int i, min_widget = 0;
        !           689: 
        !           690:     gtk_widget_hide (req68020);
        !           691:     gtk_widget_hide (req68ec020);
        !           692:     gtk_widget_hide (req68030);
        !           693:     gtk_widget_hide (reqa1000);
        !           694:     gtk_widget_hide (reqa4000);
        !           695:     if ((rom_req & ROMREQ_CPUMASK) == ROMREQ_68EC020) {
        !           696:        min_widget = 2;
        !           697:        gtk_widget_show (req68ec020);
        !           698:     } else if ((rom_req & ROMREQ_CPUMASK) == ROMREQ_68020) {
        !           699:        min_widget = 3;
        !           700:        gtk_widget_show (req68020);
        !           701:     } else if ((rom_req & ROMREQ_CPUMASK) == ROMREQ_68030) {
        !           702:        min_widget = 4;
        !           703:        gtk_widget_show (req68030);
        !           704:     }
        !           705:     if (rom_req & ROMREQ_A4000MB) {
        !           706:        gtk_widget_show (reqa4000);
        !           707:        gtk_combo_box_set_active (GTK_COMBO_BOX (mbtype_widget), 6);
        !           708:        gtk_widget_set_sensitive (mbtype_labelled, 0);
        !           709:     } else if (rom_req & ROMREQ_A1000) {
        !           710:        gtk_widget_show (reqa1000);
        !           711:        gtk_combo_box_set_active (GTK_COMBO_BOX (mbtype_widget), 1);
        !           712:        gtk_widget_set_sensitive (mbtype_labelled, 0);
        !           713:     } else
        !           714:        gtk_widget_set_sensitive (mbtype_labelled, 1);
        !           715: 
        !           716:     i = find_current_toggle (cpu_widget, 7);
        !           717:     if (i < min_widget)
        !           718:        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cpu_widget[min_widget]), TRUE);
        !           719: 
        !           720:     for (i = 0; i < 7; i++)
        !           721:        gtk_widget_set_sensitive (cpu_widget[i], i >= min_widget);
        !           722: }
        !           723: 
        !           724: static void draw_led (int nr)
        !           725: {
        !           726:     GtkWidget *thing = led_widgets[nr];
        !           727:     GdkWindow *window = thing->window;
        !           728:     GdkGC *gc = gdk_gc_new (window);
        !           729:     GdkColor *col;
        !           730: 
        !           731:     if (gui_ledstate & (1 << nr))
        !           732:        col = led_on + nr;
        !           733:     else
        !           734:        col = led_off + nr;
        !           735:     gdk_gc_set_foreground (gc, col);
        !           736:     gdk_draw_rectangle (window, gc, 1, 0, 0, -1, -1);
        !           737:     gdk_gc_destroy (gc);
        !           738: }
        !           739: 
        !           740: static void set_widgets_from_config (void)
        !           741: {
        !           742:     gfx_w = changed_prefs.gfx_w;
        !           743:     gfx_f = changed_prefs.gfx_f;
        !           744:     set_disk_state ();
        !           745:     enable_disk_buttons (1);
        !           746:     set_romlist_state ();
        !           747:     set_cpu_widget ();
        !           748:     set_cpu_state ();
        !           749:     set_gfx_state ();
        !           750:     set_joy_state ();
        !           751:     set_sound_state ();
        !           752:     set_mem_state ();
        !           753:     set_hd_state ();
        !           754:     discover_cstype ();
        !           755:     set_chipset_state ();
        !           756:     rom_requirements_change ();
        !           757: }
        !           758: 
        !           759: static int my_idle (void)
        !           760: {
        !           761:     unsigned int leds = gui_ledstate;
        !           762:     int i;
        !           763: 
        !           764:     if (quit_gui) {    
        !           765:        gui_active = 0;
        !           766:        gtk_main_quit ();
        !           767:        goto out;
        !           768:     }
        !           769: 
        !           770:     while (comm_pipe_has_data (&to_gui_pipe)) {
        !           771:        int cmd = read_comm_pipe_int_blocking (&to_gui_pipe);
        !           772:        int n;
        !           773:        switch (cmd) {
        !           774:        case GUICMD_DISKCHANGE:
        !           775:            n = read_comm_pipe_int_blocking (&to_gui_pipe);
        !           776:            gtk_label_set_text (GTK_LABEL (disk_text_widget[n]), currprefs.df[n]);
        !           777:            break;
        !           778:        case GUICMD_UPDATE:
        !           779:            /* Initialization.  */
        !           780:            set_widgets_from_config ();
        !           781: 
        !           782:            gtk_widget_show (gui_window);
        !           783:            uae_sem_post (&gui_init_sem);
        !           784:            gui_active = 1;
        !           785:            break;
        !           786:        case GUICMD_PAUSE:
        !           787:            /* Set Pause-Button active */
        !           788:            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pause_uae_widget), TRUE);
        !           789:            break;
        !           790:        case GUICMD_UNPAUSE:
        !           791:            /* Set Pause-Button inactive */
        !           792:            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pause_uae_widget), FALSE);
        !           793:            break;
        !           794:        case GUICMD_NEW_ROMLIST:
        !           795:            set_romlist_state ();
        !           796:            break;
        !           797:        case GUICMD_FULLSCREEN:
        !           798:            set_fullscreen_state ();
        !           799:            break;
        !           800:        case GUICMD_MSGBOX:
        !           801:            handle_message_box_request(&to_gui_pipe);
        !           802:            break;
        !           803:        }
        !           804:     }
        !           805: 
        !           806:     if (gui_active) {
        !           807:        int n = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)) == 0 ? 5 : 1;
        !           808:        for (i = 0; i < n; i++) {
        !           809:            unsigned int mask = 1 << i;
        !           810:            unsigned int on = leds & mask;
        !           811: 
        !           812:            if (on == (prevledstate & mask))
        !           813:                continue;
        !           814: 
        !           815:            /*  printf(": %d %d\n", i, on);*/
        !           816:            draw_led (i);
        !           817:        }
        !           818:        prevledstate = leds;
        !           819:     }
        !           820:   out:
        !           821:     return 1;
        !           822: }
        !           823: 
        !           824: static gint gui_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
        !           825: {
        !           826:     gui_active = gui_available = 0;
        !           827:     gtk_widget_destroy (disk_selector);
        !           828:     disk_selector = 0;
        !           829:     return FALSE;
        !           830: }
        !           831: 
        !           832: static void dftype_changed (GtkWidget *w, gpointer data)
        !           833: {
        !           834:     int i;
        !           835: 
        !           836:     if (ignore_gui_changes)
        !           837:        return;
        !           838:     for (i = 0; i < 4; i++) {
        !           839:        int which = gtk_combo_box_get_active (GTK_COMBO_BOX (dftype_widget[i]));
        !           840:        if (i == 0)
        !           841:            which++;
        !           842:        changed_prefs.dfxtype[i] = (which == 0 ? DRV_NONE : which == 1 ? DRV_35_DD : DRV_35_HD);
        !           843:     }
        !           844:     enable_disk_buttons (1);
        !           845: }
        !           846: 
        !           847: static void kbdlang_changed (GtkWidget *w, gpointer data)
        !           848: {
        !           849:     int which = gtk_combo_box_get_active (GTK_COMBO_BOX (kbdlang_widget));
        !           850:     changed_prefs.keyboard_lang = which;
        !           851: }
        !           852: 
        !           853: static void joy_changed (void)
        !           854: {
        !           855:     int j0t, j1t;
        !           856:     if (! gui_active)
        !           857:        return;
        !           858: 
        !           859:     j0t = find_current_toggle (joy_widget[0], 6);
        !           860:     j1t = find_current_toggle (joy_widget[1], 6);
        !           861:     changed_prefs.jport0 = (j0t == 0 || j0t == 1 ? JSEM_JOYS + j0t
        !           862:                            : j0t == 2 ? JSEM_MICE
        !           863:                            : JSEM_KBDLAYOUT + j0t - 3);
        !           864:     changed_prefs.jport1 = (j1t == 0 || j1t == 1 ? JSEM_JOYS + j1t
        !           865:                            : j1t == 2 ? JSEM_MICE
        !           866:                            : JSEM_KBDLAYOUT + j1t - 3);
        !           867: 
        !           868:     changed_prefs.input_selected_setting = GTK_TOGGLE_BUTTON (legacy_widget)->active ? 0 : 1;
        !           869: 
        !           870:     if (changed_prefs.input_selected_setting != currprefs.input_selected_setting
        !           871:        || changed_prefs.jport0 != currprefs.jport0
        !           872:        || changed_prefs.jport1 != currprefs.jport1)
        !           873:        inputdevice_config_change ();
        !           874: 
        !           875:     set_joy_state ();
        !           876: }
        !           877: 
        !           878: static void coll_changed (void)
        !           879: {
        !           880:     changed_prefs.collision_level = find_current_toggle (coll_widget, 4);
        !           881: }
        !           882: 
        !           883: static void cslevel_changed (void)
        !           884: {
        !           885:     int t = find_current_toggle (cslevel_widget, 4);
        !           886:     int t1 = 0;
        !           887:     if (t > 0)
        !           888:        t1 |= CSMASK_ECS_AGNUS;
        !           889:     if (t > 1)
        !           890:        t1 |= CSMASK_ECS_DENISE;
        !           891:     if (t > 2)
        !           892:        t1 |= CSMASK_AGA;
        !           893:     changed_prefs.chipset_mask = t1;
        !           894:     set_mem_state ();
        !           895: }
        !           896: 
        !           897: static void custom_changed (void)
        !           898: {
        !           899:     if (ignore_gui_changes)
        !           900:        return;
        !           901:     changed_prefs.gfx_framerate = framerate_adj->value;
        !           902:     changed_prefs.immediate_blits = GTK_TOGGLE_BUTTON (bimm_widget)->active;
        !           903:     changed_prefs.gfx_afullscreen = GTK_TOGGLE_BUTTON (afscr_widget)->active;
        !           904:     changed_prefs.gfx_pfullscreen = GTK_TOGGLE_BUTTON (pfscr_widget)->active;
        !           905: #if 0
        !           906:     changed_prefs.blits_32bit_enabled = GTK_TOGGLE_BUTTON (b32_widget)->active;
        !           907: #endif
        !           908: }
        !           909: 
        !           910: static void leds_changed (void)
        !           911: {
        !           912:     int w_leds = GTK_TOGGLE_BUTTON (gw_windowed.leds)->active;
        !           913:     int f_leds = GTK_TOGGLE_BUTTON (gw_fullscreen.leds)->active;
        !           914:     gfx_w.leds_on_screen = w_leds;
        !           915:     gfx_f.leds_on_screen = f_leds;
        !           916:     write_comm_pipe_int (&from_gui_pipe, 11, 1);
        !           917: }
        !           918: 
        !           919: static void aspect_changed (void)
        !           920: {
        !           921:     int w_aspect = GTK_TOGGLE_BUTTON (gw_windowed.aspect)->active;
        !           922:     int f_aspect = GTK_TOGGLE_BUTTON (gw_fullscreen.aspect)->active;
        !           923:     int w_ldbl = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_windowed.linedbl)) + 1;
        !           924:     int f_ldbl = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_fullscreen.linedbl)) + 1;
        !           925:     int w_hc = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_windowed.hcenter));
        !           926:     int f_hc = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_fullscreen.hcenter));
        !           927:     int w_vc = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_windowed.vcenter));
        !           928:     int f_vc = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_fullscreen.vcenter));
        !           929: 
        !           930:     if (ignore_gui_changes)
        !           931:        return;
        !           932: 
        !           933:     uae_sem_wait (&gui_sem);
        !           934:     gfx_w.ycenter = w_vc;
        !           935:     gfx_w.xcenter = w_hc;
        !           936:     gfx_w.correct_aspect = w_aspect;
        !           937:     gfx_w.linedbl = w_ldbl;
        !           938:     gfx_f.ycenter = f_vc;
        !           939:     gfx_f.xcenter = f_hc;
        !           940:     gfx_f.correct_aspect = f_aspect;
        !           941:     gfx_f.linedbl = f_ldbl;
        !           942: 
        !           943:     adjust_gfx_prefs (&gfx_w, &gw_windowed);
        !           944:     adjust_gfx_prefs (&gfx_f, &gw_fullscreen);
        !           945:     uae_sem_post (&gui_sem);
        !           946:     write_comm_pipe_int (&from_gui_pipe, 11, 1);
        !           947: }
        !           948: 
        !           949: static void screenmode_changed (void)
        !           950: {
        !           951:     int w = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_windowed.modelist));
        !           952:     int f = gtk_combo_box_get_active (GTK_COMBO_BOX (gw_fullscreen.modelist));
        !           953:     int need_set_w = 0, need_set_f = 0;
        !           954: 
        !           955:     if (ignore_gui_changes)
        !           956:        return;
        !           957: 
        !           958:     uae_sem_wait (&gui_sem);
        !           959:     if (w != -1) {
        !           960:        need_set_w = (gfx_w.width != gfx_windowed_modes[w].w
        !           961:                      || gfx_w.height != gfx_windowed_modes[w].h);
        !           962:        gfx_w.width = gfx_windowed_modes[w].w;
        !           963:        gfx_w.height = gfx_windowed_modes[w].h;
        !           964:     }
        !           965:     if (f != -1) {
        !           966:        need_set_f = (gfx_f.width != gfx_fullscreen_modes[f].w
        !           967:                      || gfx_f.height != gfx_fullscreen_modes[f].h);
        !           968:        gfx_f.width = gfx_fullscreen_modes[f].w;
        !           969:        gfx_f.height = gfx_fullscreen_modes[f].h;
        !           970:     }
        !           971:     if (need_set_w) {
        !           972:        fixup_prefs_dimensions (&gfx_w, gfx_windowed_modes, n_windowed_modes);
        !           973:     }
        !           974:     if (need_set_f) {
        !           975:        fixup_prefs_dimensions (&gfx_f, gfx_fullscreen_modes, n_fullscreen_modes);
        !           976:     }
        !           977:     uae_sem_post (&gui_sem);
        !           978: 
        !           979:     if (!need_set_w && !need_set_f)
        !           980:        return;
        !           981: 
        !           982:     /* We may have switched to a screenmode that has centering or other
        !           983:        modifiers enabled; re-set the members of the prefs structure
        !           984:        according to the new mode.  See comment before adjust_gfx_prefs.
        !           985: 
        !           986:        aspect_changed also sends the message to the main thread.  */
        !           987:     aspect_changed ();
        !           988: }
        !           989: 
        !           990: static void cpuspeed_changed (void)
        !           991: {
        !           992:     int which = find_current_toggle (cpuspeed_widgets, 3);
        !           993:     changed_prefs.m68k_speed = (which == 0 ? -1
        !           994:                                : which == 1 ? 0
        !           995:                                : cpuspeed_adj->value);
        !           996:     set_cpu_state ();
        !           997: }
        !           998: 
        !           999: static void cputype_changed (void)
        !          1000: {
        !          1001:     int i, oldcl;
        !          1002:     int whichtoggle;
        !          1003:     if (! gui_active)
        !          1004:        return;
        !          1005: 
        !          1006:     whichtoggle = find_current_toggle (cpu_widget, 7);
        !          1007:     changed_prefs.address_space_24 = whichtoggle < 3;
        !          1008:     if (whichtoggle >= 3)
        !          1009:        whichtoggle--;
        !          1010: 
        !          1011:     if (whichtoggle == 5)
        !          1012:        whichtoggle = 6;
        !          1013:     changed_prefs.cpu_model = 68000 + 10 * whichtoggle;
        !          1014: 
        !          1015:     if (changed_prefs.cpu_model == 68060) {
        !          1016:        changed_prefs.fpu_model = 68060;
        !          1017:        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fpu_widget[4]), 1);
        !          1018:     } else if (changed_prefs.cpu_model == 68040) {
        !          1019:        changed_prefs.fpu_model = 68040;
        !          1020:        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fpu_widget[3]), 1);
        !          1021:     } else if ((changed_prefs.cpu_model != 68020 && changed_prefs.cpu_model != 68030)
        !          1022:               || changed_prefs.fpu_model == 68040
        !          1023:               || changed_prefs.fpu_model == 68060) {
        !          1024:        changed_prefs.fpu_model = 0;
        !          1025:        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fpu_widget[0]), 1);
        !          1026:     } else {
        !          1027:        whichtoggle = find_current_toggle (fpu_widget, 5);
        !          1028:        changed_prefs.fpu_model = (whichtoggle == 0 ? 0
        !          1029:                                   : whichtoggle == 1 ? 68881
        !          1030:                                   : whichtoggle == 2 ? 68882
        !          1031:                                   : whichtoggle == 3 ? 68040
        !          1032:                                   : 68060);
        !          1033:     }
        !          1034: 
        !          1035:     set_cpu_state ();
        !          1036:     /* May influence bogomem size and Z3/GFXcard memory.  */
        !          1037:     set_mem_state();
        !          1038: }
        !          1039: 
        !          1040: static void chipsize_changed (void)
        !          1041: {
        !          1042:     int t = find_current_toggle (chipsize_widget, 5);
        !          1043:     changed_prefs.chipmem_size = 0x80000 << t;
        !          1044:     for (t = 0; t < 5; t++)
        !          1045:        gtk_widget_set_sensitive (fastsize_widget[t], changed_prefs.chipmem_size <= 0x200000);
        !          1046:     if (changed_prefs.chipmem_size > 0x200000) {
        !          1047:        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fastsize_widget[0]), 1);
        !          1048:        changed_prefs.fastmem_size = 0;
        !          1049:     }
        !          1050: }
        !          1051: 
        !          1052: static void bogosize_changed (void)
        !          1053: {
        !          1054:     int t = find_current_toggle (bogosize_widget, 4);
        !          1055:     changed_prefs.bogomem_size = (0x40000 << t) & ~0x40000;
        !          1056: }
        !          1057: 
        !          1058: static void fastsize_changed (void)
        !          1059: {
        !          1060:     int t = find_current_toggle (fastsize_widget, 5);
        !          1061:     changed_prefs.fastmem_size = (0x80000 << t) & ~0x80000;
        !          1062: }
        !          1063: 
        !          1064: static void z3size_changed (void)
        !          1065: {
        !          1066:     int t = find_current_toggle (z3size_widget, 10);
        !          1067:     changed_prefs.z3fastmem_size = (0x80000 << t) & ~0x80000;
        !          1068: }
        !          1069: 
        !          1070: static void p96size_changed (void)
        !          1071: {
        !          1072:     int t = find_current_toggle (p96size_widget, 7);
        !          1073:     changed_prefs.gfxmem_size = (0x80000 << t) & ~0x80000;
        !          1074: }
        !          1075: 
        !          1076: static void rom_combo_changed (void)
        !          1077: {
        !          1078:     int t = gtk_combo_box_get_active (GTK_COMBO_BOX (romlist_widget));
        !          1079:     gtk_widget_set_sensitive (romsel_button, t == 0);
        !          1080:     gtk_widget_set_sensitive (rom_text_widget, t == 0);
        !          1081: 
        !          1082:     rom_req = 0;
        !          1083: 
        !          1084:     if (t == 0) {
        !          1085:        changed_prefs.rom_crc32 = 0;
        !          1086:     } else {
        !          1087:        struct romlist *rl = romlist_from_idx (t - 1, ROMTYPE_KICK, 1);
        !          1088:        if (rl) {
        !          1089:            changed_prefs.rom_crc32 = rl->rd->crc32;
        !          1090:            rom_req = rl->rd->cpu;
        !          1091:        }
        !          1092:     }
        !          1093:     rom_requirements_change ();
        !          1094: }
        !          1095: 
        !          1096: static void sound_changed (void)
        !          1097: {
        !          1098:     int n;
        !          1099: 
        !          1100:     changed_prefs.produce_sound = find_current_toggle (sound_widget, 4);
        !          1101:     n = find_current_toggle (sound_ch_widget, 3);
        !          1102:     changed_prefs.sound_stereo = n == 0 ? SND_MONO : SND_STEREO;
        !          1103:     changed_prefs.sound_interpol = find_current_toggle (sound_interpol_widget, 5);
        !          1104:     n = find_current_toggle (sound_filter_widget, 5);
        !          1105:     if (n == 0)
        !          1106:        changed_prefs.sound_filter = FILTER_SOUND_OFF;
        !          1107:     else {
        !          1108:        changed_prefs.sound_filter = (n & 1) ? FILTER_SOUND_EMUL : FILTER_SOUND_ON;
        !          1109:        changed_prefs.sound_filter_type = (n > 2 ? FILTER_SOUND_TYPE_A1200 : FILTER_SOUND_TYPE_A500);
        !          1110:     }
        !          1111:     changed_prefs.sound_mixed_stereo_delay = stereo_delay_adj->value;
        !          1112:     changed_prefs.sound_stereo_separation = stereo_sep_adj->value;
        !          1113: 
        !          1114:     gtk_widget_set_sensitive (stereo_sep_scale, changed_prefs.sound_stereo == SND_STEREO);
        !          1115:     gtk_widget_set_sensitive (stereo_delay_scale, changed_prefs.sound_stereo == SND_STEREO);
        !          1116: }
        !          1117: 
        !          1118: static void bootrom_changed (void)
        !          1119: {
        !          1120:     changed_prefs.bootrom = GTK_TOGGLE_BUTTON (bootrom_widget)->active ? 1 : 0;
        !          1121:     set_mem_state ();
        !          1122: }
        !          1123: 
        !          1124: static void ntsc_changed (void)
        !          1125: {
        !          1126:     changed_prefs.ntscmode = find_current_toggle (ntsc_widget, 2);
        !          1127: }
        !          1128: 
        !          1129: static void mbtype_changed (void)
        !          1130: {
        !          1131:     int needs_aga, allows_ocs, allows_ecs;
        !          1132:     int n, cstype;
        !          1133: 
        !          1134:     if (ignore_gui_changes)
        !          1135:        return;
        !          1136: 
        !          1137:     n = gtk_combo_box_get_active (GTK_COMBO_BOX (mbtype_widget));
        !          1138:     cstype = (n == 0 ? CP_GENERIC
        !          1139:              : n == 1 ? CP_A1000
        !          1140:              : n == 2 ? CP_A500
        !          1141:              : n == 3 ? CP_A600
        !          1142:              : n == 4 ? CP_A1200
        !          1143:              : n == 5 ? CP_A3000
        !          1144:              : CP_A4000);
        !          1145:     if (cstype != CP_GENERIC)
        !          1146:        built_in_chipset_prefs (&changed_prefs, cstype);
        !          1147: 
        !          1148:     needs_aga = cstype == CP_A1200 || cstype == CP_A4000 || cstype == CP_A4000T || cstype == CP_CD32;
        !          1149:     allows_ocs = cstype == CP_A1000 || cstype == CP_A500 || cstype == CP_A2000;
        !          1150:     allows_ecs = !needs_aga && cstype != CP_A1000;
        !          1151: 
        !          1152:     gtk_widget_set_sensitive (cslevel_widget[0], cstype == CP_GENERIC || allows_ocs);
        !          1153:     gtk_widget_set_sensitive (cslevel_widget[1], cstype == CP_GENERIC || allows_ecs);
        !          1154:     gtk_widget_set_sensitive (cslevel_widget[2], cstype == CP_GENERIC || allows_ecs);
        !          1155:     gtk_widget_set_sensitive (cslevel_widget[3], cstype == CP_GENERIC || needs_aga);
        !          1156: 
        !          1157:     if (cstype != CP_GENERIC) {
        !          1158:        if (needs_aga)
        !          1159:            changed_prefs.chipset_mask = CSMASK_AGA | CSMASK_FULL_ECS;
        !          1160:        else if (! allows_ecs)
        !          1161:            changed_prefs.chipset_mask = 0;
        !          1162:     }
        !          1163:     set_chipset_state ();
        !          1164: }
        !          1165: 
        !          1166: static void did_reset (void)
        !          1167: {
        !          1168:     if (quit_gui)
        !          1169:        return;
        !          1170: 
        !          1171:     write_comm_pipe_int (&from_gui_pipe, 2, 1);
        !          1172: }
        !          1173: 
        !          1174: static void did_debug (void)
        !          1175: {
        !          1176:     if (quit_gui)
        !          1177:        return;
        !          1178: 
        !          1179:     write_comm_pipe_int (&from_gui_pipe, 3, 1);
        !          1180: }
        !          1181: 
        !          1182: static void did_quit (void)
        !          1183: {
        !          1184:     if (quit_gui)
        !          1185:        return;
        !          1186: 
        !          1187:     write_comm_pipe_int (&from_gui_pipe, 4, 1);
        !          1188: }
        !          1189: 
        !          1190: static void did_eject (GtkWidget *w, gpointer data_p)
        !          1191: {
        !          1192:     int data = GPOINTER_TO_INT (data_p);
        !          1193:     if (quit_gui)
        !          1194:        return;
        !          1195: 
        !          1196:     write_comm_pipe_int (&from_gui_pipe, 0, 0);
        !          1197:     write_comm_pipe_int (&from_gui_pipe, data, 1);
        !          1198:     gtk_label_set_text (GTK_LABEL (disk_text_widget[data]), "");
        !          1199: }
        !          1200: 
        !          1201: static void pause_uae (void)
        !          1202: {
        !          1203:     if (quit_gui)
        !          1204:        return;
        !          1205: 
        !          1206:     write_comm_pipe_int (&from_gui_pipe, GTK_TOGGLE_BUTTON (pause_uae_widget)->active ? 5 : 6, 1);
        !          1207:     if (! GTK_TOGGLE_BUTTON (pause_uae_widget)->active)
        !          1208:        gtk_widget_hide (lab_info);
        !          1209: }
        !          1210: 
        !          1211: static void end_pause_uae (void)
        !          1212: {
        !          1213:     write_comm_pipe_int (&to_gui_pipe, GUICMD_UNPAUSE, 1);
        !          1214: }
        !          1215: 
        !          1216: static char fsbuffer[100];
        !          1217: 
        !          1218: static GtkWidget *make_file_selector (const char *title,
        !          1219:                                      GtkFileChooserAction action)
        !          1220: {
        !          1221:     GtkWidget *p = gtk_file_chooser_dialog_new (title, GTK_WINDOW (gui_window), action,
        !          1222:                                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
        !          1223:                                                action == GTK_FILE_CHOOSER_ACTION_SAVE ? GTK_STOCK_SAVE : GTK_STOCK_OPEN,
        !          1224:                                                GTK_RESPONSE_ACCEPT,
        !          1225:                                                NULL);
        !          1226: 
        !          1227:     return p;
        !          1228: }
        !          1229: 
        !          1230: static void filesel_set_path (GtkWidget *p, const char *path)
        !          1231: {
        !          1232:     size_t len = strlen (path);
        !          1233:     if (len > 0 && ! access (path, R_OK)) {
        !          1234:        char *tmp = xmalloc (len + 2);
        !          1235:        strcpy (tmp, path);
        !          1236:        strcat (tmp, "/");
        !          1237:        gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (p), tmp);
        !          1238:     }
        !          1239: }
        !          1240: 
        !          1241: static void make_disk_selector (void)
        !          1242: {
        !          1243:     if (disk_selector)
        !          1244:        return;
        !          1245:     disk_selector = make_file_selector ("Select a disk image file to mount",
        !          1246:                                        GTK_FILE_CHOOSER_ACTION_OPEN);
        !          1247:     filesel_set_path (disk_selector, currprefs.path_floppy);
        !          1248: }
        !          1249: 
        !          1250: static void did_insert (GtkWidget *w, gpointer data)
        !          1251: {
        !          1252:     int n = GPOINTER_TO_INT (data);
        !          1253: 
        !          1254:     make_disk_selector ();
        !          1255:     sprintf (fsbuffer, "Select a disk image file for DF%d", n);
        !          1256:     gtk_window_set_title (GTK_WINDOW (disk_selector), fsbuffer);
        !          1257: 
        !          1258:     if (gtk_dialog_run (GTK_DIALOG (disk_selector)) == GTK_RESPONSE_ACCEPT) {
        !          1259:        char *filename;
        !          1260: 
        !          1261:        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (disk_selector));
        !          1262: 
        !          1263:        uae_sem_wait (&gui_sem);
        !          1264:        if (new_disk_string[n] != 0)
        !          1265:            free (new_disk_string[n]);
        !          1266:        new_disk_string[n] = strdup (filename);
        !          1267:        uae_sem_post (&gui_sem);
        !          1268:        write_comm_pipe_int (&from_gui_pipe, 1, 0);
        !          1269:        write_comm_pipe_int (&from_gui_pipe, n, 1);
        !          1270:        gtk_label_set_text (GTK_LABEL (disk_text_widget[n]), filename);
        !          1271: 
        !          1272:        g_free (filename);
        !          1273:     }
        !          1274:     gtk_widget_hide (disk_selector);
        !          1275: }
        !          1276: 
        !          1277: static gint driveled_event (GtkWidget *thing, GdkEvent *event)
        !          1278: {
        !          1279:     int lednr = nr_for_led (thing);
        !          1280: 
        !          1281:     switch (event->type) {
        !          1282:      case GDK_MAP:
        !          1283:        draw_led (lednr);
        !          1284:        break;
        !          1285:      case GDK_EXPOSE:
        !          1286:        draw_led (lednr);
        !          1287:        break;
        !          1288:      default:
        !          1289:        break;
        !          1290:     }
        !          1291: 
        !          1292:   return 0;
        !          1293: }
        !          1294: 
        !          1295: static GtkWidget *snap_selector;
        !          1296: 
        !          1297: static void did_loadstate (void)
        !          1298: {
        !          1299:     GtkWidget *dialog;
        !          1300: 
        !          1301:     dialog = make_file_selector ("Select a state file to restore", GTK_FILE_CHOOSER_ACTION_OPEN);
        !          1302: 
        !          1303:     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
        !          1304:        char *filename;
        !          1305: 
        !          1306:        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
        !          1307: 
        !          1308:        uae_sem_wait (&gui_sem);
        !          1309:        gui_snapname = strdup (filename);
        !          1310:        uae_sem_post (&gui_sem);
        !          1311:        write_comm_pipe_int (&from_gui_pipe, 7, 0);
        !          1312:        write_comm_pipe_int (&from_gui_pipe, STATE_DORESTORE, 1);
        !          1313: 
        !          1314:        g_free (filename);
        !          1315:     }
        !          1316: 
        !          1317:     gtk_widget_destroy (dialog);
        !          1318: }
        !          1319: 
        !          1320: static void did_savestate (void)
        !          1321: {
        !          1322:     GtkWidget *dialog;
        !          1323: 
        !          1324:     dialog = make_file_selector ("Select a filename for the state file",
        !          1325:                                 GTK_FILE_CHOOSER_ACTION_SAVE);
        !          1326: 
        !          1327:     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
        !          1328:        char *filename;
        !          1329: 
        !          1330:        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
        !          1331: 
        !          1332:        uae_sem_wait (&gui_sem);
        !          1333:        gui_snapname = strdup (filename);
        !          1334:        uae_sem_post (&gui_sem);
        !          1335:        write_comm_pipe_int (&from_gui_pipe, 7, 0);
        !          1336:        write_comm_pipe_int (&from_gui_pipe, STATE_DOSAVE, 1);
        !          1337: 
        !          1338:        g_free (filename);
        !          1339:     }
        !          1340: 
        !          1341:     gtk_widget_destroy (dialog);
        !          1342: }
        !          1343: 
        !          1344: static void did_rompathchange (GtkWidget *w, gpointer data)
        !          1345: {
        !          1346:     GtkWidget *pathsel;
        !          1347:     pathsel = make_file_selector ("Select a ROM path",
        !          1348:                                  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
        !          1349:     filesel_set_path (pathsel, currprefs.path_rom);
        !          1350:     if (gtk_dialog_run (GTK_DIALOG (pathsel)) == GTK_RESPONSE_ACCEPT) {
        !          1351:        char *filename;
        !          1352: 
        !          1353:        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (pathsel));
        !          1354: 
        !          1355:        uae_sem_wait (&gui_sem);
        !          1356:        gui_romname = strdup (filename);
        !          1357:        uae_sem_post (&gui_sem);
        !          1358:        write_comm_pipe_int (&from_gui_pipe, 10, 0);
        !          1359:        gtk_label_set_text (GTK_LABEL (rom_path_widget), gui_romname);
        !          1360: 
        !          1361:        g_free (filename);
        !          1362:     }
        !          1363: 
        !          1364:     gtk_widget_destroy (pathsel);
        !          1365: }
        !          1366: 
        !          1367: static void did_romchange (GtkWidget *w, gpointer data)
        !          1368: {
        !          1369:     GtkWidget *romsel;
        !          1370: 
        !          1371:     romsel = make_file_selector ("Select a ROM file",
        !          1372:                                 GTK_FILE_CHOOSER_ACTION_OPEN);
        !          1373:     filesel_set_path (romsel, currprefs.path_rom);
        !          1374:     if (gtk_dialog_run (GTK_DIALOG (romsel)) == GTK_RESPONSE_ACCEPT) {
        !          1375:        char *filename;
        !          1376: 
        !          1377:        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (romsel));
        !          1378:        rom_req = 0;
        !          1379:        rom_requirements_change ();
        !          1380: 
        !          1381:        uae_sem_wait (&gui_sem);
        !          1382:        gui_romname = strdup (filename);
        !          1383:        uae_sem_post (&gui_sem);
        !          1384:        write_comm_pipe_int (&from_gui_pipe, 8, 0);
        !          1385:        gtk_label_set_text (GTK_LABEL (rom_text_widget), gui_romname);
        !          1386: 
        !          1387:        g_free (filename);
        !          1388:     }
        !          1389: 
        !          1390:     gtk_widget_destroy (romsel);
        !          1391: }
        !          1392: 
        !          1393: static void did_keychange (GtkWidget *w, gpointer data)
        !          1394: {
        !          1395:     GtkWidget *keysel;
        !          1396: 
        !          1397:     keysel = make_file_selector ("Select a Kickstart key file",
        !          1398:                                 GTK_FILE_CHOOSER_ACTION_OPEN);
        !          1399:     filesel_set_path (keysel, currprefs.path_rom);
        !          1400: 
        !          1401:     if (gtk_dialog_run (GTK_DIALOG (keysel)) == GTK_RESPONSE_ACCEPT) {
        !          1402:        char *filename;
        !          1403: 
        !          1404:        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (keysel));
        !          1405:        uae_sem_wait (&gui_sem);
        !          1406:        gui_keyname = strdup (filename);
        !          1407:        uae_sem_post (&gui_sem);
        !          1408:        write_comm_pipe_int (&from_gui_pipe, 9, 0);
        !          1409:        gtk_label_set_text (GTK_LABEL (key_text_widget), gui_keyname);
        !          1410: 
        !          1411:        g_free (filename);
        !          1412:     }
        !          1413:     
        !          1414:     gtk_widget_destroy (keysel);
        !          1415: }
        !          1416: 
        !          1417: static void add_empty_vbox (GtkWidget *tobox)
        !          1418: {
        !          1419:     GtkWidget *thing = gtk_vbox_new (FALSE, 0);
        !          1420:     gtk_widget_show (thing);
        !          1421:     gtk_box_pack_start (GTK_BOX (tobox), thing, TRUE, TRUE, 0);
        !          1422: }
        !          1423: 
        !          1424: static void add_centered_to_vbox (GtkWidget *vbox, GtkWidget *w, int vexpand)
        !          1425: {
        !          1426:     GtkWidget *hbox = gtk_hbox_new (TRUE, 0);
        !          1427:     gtk_widget_show (hbox);
        !          1428:     gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, FALSE, 0);
        !          1429:     gtk_box_pack_start (GTK_BOX (vbox), hbox, vexpand, vexpand, 0);
        !          1430: }
        !          1431: 
        !          1432: static GtkWidget *make_labelled_widget (const char *str, GtkWidget *thing, int expand)
        !          1433: {
        !          1434:     GtkWidget *label = gtk_label_new (str);
        !          1435:     GtkWidget *hbox2 = gtk_hbox_new (FALSE, 4);
        !          1436: 
        !          1437:     gtk_widget_show (label);
        !          1438:     gtk_widget_show (thing);
        !          1439: 
        !          1440:     gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
        !          1441:     gtk_box_pack_start (GTK_BOX (hbox2), thing, expand, TRUE, 0);
        !          1442: 
        !          1443:     return hbox2;
        !          1444: }
        !          1445: 
        !          1446: static GtkWidget *add_labelled_widget_centered (const char *str, GtkWidget *thing, GtkWidget *vbox)
        !          1447: {
        !          1448:     GtkWidget *w = make_labelled_widget (str, thing, FALSE);
        !          1449:     gtk_widget_show (w);
        !          1450:     add_centered_to_vbox (vbox, w, 0);
        !          1451:     return w;
        !          1452: }
        !          1453: 
        !          1454: static int make_radio_group (const char **labels, GtkWidget *tobox,
        !          1455:                              GtkWidget **saveptr, gint t1, gint t2,
        !          1456:                              void (*sigfunc) (void), int count, GSList *group)
        !          1457: {
        !          1458:     int t = 0;
        !          1459: 
        !          1460:     while (*labels && (count == -1 || count-- > 0)) {
        !          1461:        GtkWidget *thing = gtk_radio_button_new_with_label (group, *labels++);
        !          1462:        group = gtk_radio_button_group (GTK_RADIO_BUTTON (thing));
        !          1463: 
        !          1464:        *saveptr++ = thing;
        !          1465:        gtk_widget_show (thing);
        !          1466:        gtk_box_pack_start (GTK_BOX (tobox), thing, t1, t2, 0);
        !          1467:        gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) sigfunc, NULL);
        !          1468:        t++;
        !          1469:     }
        !          1470:     return t;
        !          1471: }
        !          1472: 
        !          1473: static GtkWidget *make_radio_group_box (const char *title, const char **labels,
        !          1474:                                        GtkWidget **saveptr, int horiz,
        !          1475:                                        void (*sigfunc) (void), GtkWidget **boxp)
        !          1476: {
        !          1477:     GtkWidget *frame, *newbox;
        !          1478: 
        !          1479:     frame = gtk_frame_new (title);
        !          1480:     newbox = (horiz ? gtk_hbox_new : gtk_vbox_new) (FALSE, 4);
        !          1481:     gtk_widget_show (newbox);
        !          1482:     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
        !          1483:     gtk_container_add (GTK_CONTAINER (frame), newbox);
        !          1484:     make_radio_group (labels, newbox, saveptr, horiz, !horiz, sigfunc, -1, NULL);
        !          1485:     if (boxp)
        !          1486:        *boxp = newbox;
        !          1487:     return frame;
        !          1488: }
        !          1489: 
        !          1490: static GtkWidget *make_radio_group_box_1 (const char *title, const char **labels,
        !          1491:                                          GtkWidget **saveptr, int horiz,
        !          1492:                                          void (*sigfunc) (void), int elts_per_column)
        !          1493: {
        !          1494:     GtkWidget *frame, *newbox;
        !          1495:     GtkWidget *column;
        !          1496:     GSList *group = 0;
        !          1497: 
        !          1498:     frame = gtk_frame_new (title);
        !          1499:     column = (horiz ? gtk_vbox_new : gtk_hbox_new) (FALSE, 4);
        !          1500:     gtk_container_add (GTK_CONTAINER (frame), column);
        !          1501:     gtk_widget_show (column);
        !          1502: 
        !          1503:     while (*labels) {
        !          1504:        int count;
        !          1505:        newbox = (horiz ? gtk_hbox_new : gtk_vbox_new) (FALSE, 4);
        !          1506:        gtk_widget_show (newbox);
        !          1507:        gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
        !          1508:        gtk_container_add (GTK_CONTAINER (column), newbox);
        !          1509:        count = make_radio_group (labels, newbox, saveptr, horiz, !horiz, sigfunc, elts_per_column, group);
        !          1510:        labels += count;
        !          1511:        saveptr += count;
        !          1512:        group = gtk_radio_button_group (GTK_RADIO_BUTTON (saveptr[-1]));
        !          1513:     }
        !          1514:     return frame;
        !          1515: }
        !          1516: 
        !          1517: static GtkWidget *make_led (int nr)
        !          1518: {
        !          1519:     GtkWidget *subframe, *the_led, *thing;
        !          1520:     GdkColormap *colormap;
        !          1521: 
        !          1522:     the_led = gtk_vbox_new (FALSE, 0);
        !          1523:     gtk_widget_show (the_led);
        !          1524: 
        !          1525:     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
        !          1526:     gtk_box_pack_start (GTK_BOX (the_led), thing, TRUE, TRUE, 0);
        !          1527:     gtk_widget_show (thing);
        !          1528: 
        !          1529:     subframe = gtk_frame_new (NULL);
        !          1530:     gtk_box_pack_start (GTK_BOX (the_led), subframe, TRUE, TRUE, 0);
        !          1531:     gtk_widget_show (subframe);
        !          1532: 
        !          1533:     thing = gtk_drawing_area_new ();
        !          1534:     gtk_drawing_area_size (GTK_DRAWING_AREA (thing), 20, 5);
        !          1535:     gtk_widget_set_events (thing, GDK_EXPOSURE_MASK);
        !          1536:     gtk_container_add (GTK_CONTAINER (subframe), thing);
        !          1537:     colormap = gtk_widget_get_colormap (thing);
        !          1538:     led_on[nr].red = nr == 0 ? 0xEEEE : 0xCCCC;
        !          1539:     led_on[nr].green = nr == 0 ? 0: 0xFFFF;
        !          1540:     led_on[nr].blue = 0;
        !          1541:     led_on[nr].pixel = 0;
        !          1542:     led_off[nr].red = 0;
        !          1543:     led_off[nr].green = 0;
        !          1544:     led_off[nr].blue = 0;
        !          1545:     led_off[nr].pixel = 0;
        !          1546:     gdk_color_alloc (colormap, led_on + nr);
        !          1547:     gdk_color_alloc (colormap, led_off + nr);
        !          1548:     led_widgets[nr] = thing;
        !          1549:     gtk_signal_connect (GTK_OBJECT (thing), "event",
        !          1550:                        (GtkSignalFunc) driveled_event, (gpointer) thing);
        !          1551:     gtk_widget_show (thing);
        !          1552: 
        !          1553:     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
        !          1554:     gtk_box_pack_start (GTK_BOX (the_led), thing, TRUE, TRUE, 0);
        !          1555:     gtk_widget_show (thing);
        !          1556: 
        !          1557:     return the_led;
        !          1558: }
        !          1559: 
        !          1560: static GtkWidget *make_file_container (const char *title, GtkWidget *vbox, int vertical)
        !          1561: {
        !          1562:     GtkWidget *thing = gtk_frame_new (title);
        !          1563:     GtkWidget *file_vbox = vertical ? gtk_vbox_new (FALSE, 4) : gtk_hbox_new (FALSE, 4);
        !          1564: 
        !          1565:     gtk_container_set_border_width (GTK_CONTAINER (file_vbox), 4);
        !          1566:     gtk_container_add (GTK_CONTAINER (thing), file_vbox);
        !          1567:     gtk_box_pack_start (GTK_BOX (vbox), thing, FALSE, TRUE, 0);
        !          1568:     gtk_widget_show (file_vbox);
        !          1569:     gtk_widget_show (thing);
        !          1570: 
        !          1571:     return file_vbox;
        !          1572: }
        !          1573: 
        !          1574: static GtkWidget *make_file_widget (GtkWidget *buttonbox)
        !          1575: {
        !          1576:     GtkWidget *thing, *subthing;
        !          1577:     GtkWidget *subframe = gtk_frame_new (NULL);
        !          1578: 
        !          1579:     gtk_frame_set_shadow_type (GTK_FRAME (subframe), GTK_SHADOW_ETCHED_OUT);
        !          1580:     gtk_box_pack_start (GTK_BOX (buttonbox), subframe, TRUE, TRUE, 0);
        !          1581:     gtk_widget_show (subframe);
        !          1582:     subthing = gtk_vbox_new (FALSE, 0);
        !          1583:     gtk_widget_show (subthing);
        !          1584:     gtk_container_add (GTK_CONTAINER (subframe), subthing);
        !          1585:     thing = gtk_label_new ("");
        !          1586:     gtk_widget_show (thing);
        !          1587:     gtk_box_pack_start (GTK_BOX (subthing), thing, TRUE, TRUE, 0);
        !          1588: 
        !          1589:     return thing;
        !          1590: }
        !          1591: 
        !          1592: static void make_floppy_disks (GtkWidget *vbox)
        !          1593: {
        !          1594:     GtkWidget *thing, *subthing, *subframe, *buttonbox, *file_vbox;
        !          1595:     char buf[5];
        !          1596:     int i;
        !          1597: 
        !          1598:     add_empty_vbox (vbox);
        !          1599: 
        !          1600:     for (i = 0; i < 4; i++) {
        !          1601:        /* Frame with an hbox and the "DFx:" title */
        !          1602:        sprintf (buf, "DF%d:", i);
        !          1603:        file_vbox = make_file_container (buf, vbox, 1);
        !          1604: 
        !          1605:        buttonbox = gtk_hbox_new (FALSE, 4);
        !          1606:        gtk_box_pack_start (GTK_BOX (file_vbox), buttonbox, FALSE, TRUE, 0);
        !          1607:        gtk_widget_show (buttonbox);
        !          1608: 
        !          1609:        /* LED */
        !          1610:        subthing = make_led (i + 1);
        !          1611:        gtk_box_pack_start (GTK_BOX (buttonbox), subthing, FALSE, TRUE, 0);
        !          1612: 
        !          1613:        /* Current file display */
        !          1614:        disk_text_widget[i] = make_file_widget (buttonbox);
        !          1615: 
        !          1616:        /* Now, the buttons.  */
        !          1617:        thing = gtk_button_new_with_label ("Eject");
        !          1618:        gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
        !          1619:        gtk_widget_show (thing);
        !          1620:        disk_eject_widget[i] = thing;
        !          1621:        gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_eject,
        !          1622:                            GINT_TO_POINTER (i));
        !          1623: 
        !          1624:        thing = gtk_button_new_with_label ("Insert");
        !          1625:        gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
        !          1626:        gtk_widget_show (thing);
        !          1627:        disk_insert_widget[i] = thing;
        !          1628:        gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_insert,
        !          1629:                            GINT_TO_POINTER (i));
        !          1630: 
        !          1631:        buttonbox = gtk_hbox_new (FALSE, 4);
        !          1632:        gtk_box_pack_start (GTK_BOX (file_vbox), buttonbox, FALSE, FALSE, 0);
        !          1633:        gtk_widget_show (buttonbox);
        !          1634: 
        !          1635:        if (i == 0)
        !          1636:            thing = make_chooser (2, "3.5 DD", "3.5 HD");
        !          1637:        else
        !          1638:            thing = make_chooser (3, "Disabled", "3.5 DD", "3.5 HD");
        !          1639:        gtk_signal_connect (GTK_OBJECT (thing), "changed", (GtkSignalFunc) dftype_changed,
        !          1640:                            GINT_TO_POINTER (i));
        !          1641:        dftype_widget[i] = thing;
        !          1642: 
        !          1643:        thing = make_labelled_widget ("Type:", thing, 0);
        !          1644:        gtk_box_pack_end (GTK_BOX (buttonbox), thing, FALSE, FALSE, 0);
        !          1645:        gtk_widget_show (thing);
        !          1646:     }
        !          1647: 
        !          1648:     add_empty_vbox (vbox);
        !          1649: }
        !          1650: 
        !          1651: static GtkWidget *make_cpu_speed_sel (void)
        !          1652: {
        !          1653:     int t;
        !          1654:     static const char *labels[] = {
        !          1655:        "Optimize for host CPU speed", "Approximate 68000/7MHz speed", "Adjustable",
        !          1656:        NULL
        !          1657:     };
        !          1658:     GtkWidget *frame, *newbox;
        !          1659: 
        !          1660:     frame = gtk_frame_new ("CPU speed");
        !          1661:     newbox = gtk_vbox_new (FALSE, 4);
        !          1662:     gtk_widget_show (newbox);
        !          1663:     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
        !          1664:     gtk_container_add (GTK_CONTAINER (frame), newbox);
        !          1665:     make_radio_group (labels, newbox, cpuspeed_widgets, 0, 1, cpuspeed_changed, -1, NULL);
        !          1666: 
        !          1667:     t = currprefs.m68k_speed > 0 ? currprefs.m68k_speed : 4 * CYCLE_UNIT;
        !          1668:     cpuspeed_adj = GTK_ADJUSTMENT (gtk_adjustment_new (t, 1.0, 5120.0, 1.0, 1.0, 1.0));
        !          1669:     gtk_signal_connect (GTK_OBJECT (cpuspeed_adj), "value_changed",
        !          1670:                        GTK_SIGNAL_FUNC (cpuspeed_changed), NULL);
        !          1671: 
        !          1672:     cpuspeed_scale = gtk_hscale_new (cpuspeed_adj);
        !          1673:     gtk_range_set_update_policy (GTK_RANGE (cpuspeed_scale), GTK_UPDATE_DELAYED);
        !          1674:     gtk_scale_set_digits (GTK_SCALE (cpuspeed_scale), 0);
        !          1675:     gtk_scale_set_value_pos (GTK_SCALE (cpuspeed_scale), GTK_POS_RIGHT);
        !          1676:     cpuspeed_scale = make_labelled_widget ("Cycles/insn:", cpuspeed_scale, TRUE);
        !          1677:     gtk_widget_show (cpuspeed_scale);
        !          1678:     gtk_box_pack_start (GTK_BOX (newbox), cpuspeed_scale, FALSE, FALSE, 0);
        !          1679: 
        !          1680:     return frame;
        !          1681: }
        !          1682: 
        !          1683: static void make_cpu_widgets (GtkWidget *vbox)
        !          1684: {
        !          1685:     int i;
        !          1686:     GtkWidget *newbox, *hbox, *frame;
        !          1687:     GtkWidget *thing, *label;
        !          1688:     static const char *cpulabels[] = {
        !          1689:        "68000", "68010", "68EC020", "68020", "68030", "68040", "68060",
        !          1690:        NULL
        !          1691:     };
        !          1692:     static const char *fpulabels[] = {
        !          1693:        "None", "68881", "68882", "68040", "68060",
        !          1694:        NULL
        !          1695:     };
        !          1696: 
        !          1697:     add_empty_vbox (vbox);
        !          1698: 
        !          1699:     hbox = gtk_hbox_new (FALSE, 0);
        !          1700:     add_empty_vbox (hbox);
        !          1701: 
        !          1702:     newbox = make_radio_group_box ("CPU type", cpulabels, cpu_widget, 0, cputype_changed, NULL);
        !          1703:     gtk_widget_show (newbox);
        !          1704:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
        !          1705: 
        !          1706:     newbox = make_radio_group_box ("FPU type", fpulabels, fpu_widget, 0, cputype_changed, NULL);
        !          1707:     gtk_widget_show (newbox);
        !          1708:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
        !          1709: 
        !          1710:     newbox = make_cpu_speed_sel ();
        !          1711:     gtk_widget_show (newbox);
        !          1712:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
        !          1713: 
        !          1714:     add_empty_vbox (hbox);
        !          1715:     gtk_widget_show (hbox);
        !          1716:     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
        !          1717: 
        !          1718:     req68ec020 = gtk_label_new ("The selected ROM requires at least a 68ec020.");
        !          1719:     add_centered_to_vbox (vbox, req68ec020, 0);
        !          1720: 
        !          1721:     req68020 = gtk_label_new ("The selected ROM requires at least a 68020.");
        !          1722:     add_centered_to_vbox (vbox, req68020, 0);
        !          1723: 
        !          1724:     req68030 = gtk_label_new ("The selected ROM requires at least a 68030.");
        !          1725:     add_centered_to_vbox (vbox, req68030, 0);
        !          1726: 
        !          1727:     add_empty_vbox (vbox);
        !          1728: 
        !          1729:     label = gtk_label_new ("CPU type settings take effect after the next reset.");
        !          1730:     gtk_widget_show (label);
        !          1731:     add_centered_to_vbox (vbox, label, 0);
        !          1732: }
        !          1733: 
        !          1734: static GtkWidget *make_screenmode_box (const char *title, struct scrmode_widgets *mw,
        !          1735:                                       struct uae_rect *modes, int n_modes)
        !          1736: {
        !          1737:     GtkWidget *vbox;
        !          1738:     int i;
        !          1739: 
        !          1740:     mw->frame = gtk_frame_new (title);
        !          1741:     gtk_widget_show (mw->frame);
        !          1742: 
        !          1743:     vbox = gtk_vbox_new (FALSE, 10);
        !          1744:     gtk_widget_show (vbox);
        !          1745:     gtk_container_add (GTK_CONTAINER (mw->frame), vbox);
        !          1746:     gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
        !          1747: 
        !          1748:     mw->modelist = gtk_combo_box_new_text ();
        !          1749:     gtk_widget_show (mw->modelist);
        !          1750:     gtk_box_pack_start (GTK_BOX (vbox), mw->modelist, FALSE, TRUE, 0);
        !          1751: 
        !          1752:     for (i = 0; i < n_modes; i++) {
        !          1753:        char t[200];
        !          1754:        sprintf (t, "%dx%d", modes[i].w, modes[i].h);
        !          1755:        gtk_combo_box_append_text (GTK_COMBO_BOX (mw->modelist), t);
        !          1756:     }
        !          1757:     if (n_modes == 0)
        !          1758:        gtk_widget_set_sensitive (mw->frame, FALSE);
        !          1759: 
        !          1760:     mw->hcenter = make_chooser (3, "Off", "Simple", "Smart");
        !          1761:     mw->hc_label = make_labelled_widget ("Horizontal bounds detect:", mw->hcenter, TRUE);
        !          1762:     gtk_widget_show (mw->hc_label);
        !          1763:     gtk_box_pack_start (GTK_BOX (vbox), mw->hc_label, FALSE, TRUE, 0);
        !          1764:     
        !          1765:     mw->vcenter = make_chooser (3, "Off", "Simple", "Smart");
        !          1766:     mw->vc_label = make_labelled_widget ("Vertical bounds detect:", mw->vcenter, TRUE);
        !          1767:     gtk_widget_show (mw->vc_label);
        !          1768:     gtk_box_pack_start (GTK_BOX (vbox), mw->vc_label, FALSE, TRUE, 0);
        !          1769: 
        !          1770:     mw->linedbl = make_chooser (2, "Double", "Scanlines");
        !          1771:     mw->ld_label = make_labelled_widget ("Line doubling:", mw->linedbl, TRUE);
        !          1772:     gtk_widget_show (mw->ld_label);
        !          1773:     gtk_box_pack_start (GTK_BOX (vbox), mw->ld_label, FALSE, TRUE, 0);
        !          1774: 
        !          1775:     mw->aspect = gtk_check_button_new_with_label ("Correct aspect ratio");
        !          1776:     gtk_widget_show (mw->aspect);
        !          1777:     gtk_box_pack_start (GTK_BOX (vbox), mw->aspect, FALSE, TRUE, 0);
        !          1778: 
        !          1779:     mw->leds = gtk_check_button_new_with_label ("Show LEDs on screen");
        !          1780:     gtk_widget_show (mw->leds);
        !          1781:     gtk_box_pack_start (GTK_BOX (vbox), mw->leds, FALSE, TRUE, 0);
        !          1782: 
        !          1783:     gtk_signal_connect (GTK_OBJECT (mw->leds), "clicked",
        !          1784:                        (GtkSignalFunc) leds_changed, NULL);
        !          1785:     gtk_signal_connect (GTK_OBJECT (mw->aspect), "clicked",
        !          1786:                        (GtkSignalFunc) aspect_changed, NULL);
        !          1787:     gtk_signal_connect (GTK_OBJECT (mw->linedbl), "changed",
        !          1788:                        (GtkSignalFunc) aspect_changed, NULL);
        !          1789:     gtk_signal_connect (GTK_OBJECT (mw->hcenter), "changed",
        !          1790:                        (GtkSignalFunc) aspect_changed, NULL);
        !          1791:     gtk_signal_connect (GTK_OBJECT (mw->vcenter), "changed",
        !          1792:                        (GtkSignalFunc) aspect_changed, NULL);
        !          1793:     gtk_signal_connect (GTK_OBJECT (mw->modelist), "changed",
        !          1794:                        (GtkSignalFunc) screenmode_changed, NULL);
        !          1795: 
        !          1796:     return mw->frame;
        !          1797: }
        !          1798: 
        !          1799: static void make_gfx_widgets (GtkWidget *vbox)
        !          1800: {
        !          1801:     GtkWidget *thing, *frame, *newbox, *hbox;
        !          1802: 
        !          1803:     add_empty_vbox (vbox);
        !          1804: 
        !          1805:     hbox = gtk_hbox_new (FALSE, 10);
        !          1806:     gtk_widget_show (hbox);
        !          1807:     add_centered_to_vbox (vbox, hbox, 0);
        !          1808: 
        !          1809:     thing = make_screenmode_box ("Fullscreen mode", &gw_fullscreen, gfx_fullscreen_modes, n_fullscreen_modes);
        !          1810:     gtk_box_pack_start (GTK_BOX (hbox), thing, FALSE, FALSE, 0);
        !          1811:     thing = make_screenmode_box ("Windowed mode", &gw_windowed, gfx_windowed_modes, n_windowed_modes);
        !          1812:     gtk_box_pack_start (GTK_BOX (hbox), thing, FALSE, FALSE, 0);
        !          1813:     
        !          1814:     hbox = gtk_hbox_new (FALSE, 10);
        !          1815:     gtk_widget_show (hbox);
        !          1816:     add_centered_to_vbox (vbox, hbox, 0);
        !          1817: 
        !          1818:     frame = gtk_frame_new ("Miscellaneous");
        !          1819:     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
        !          1820: 
        !          1821:     gtk_widget_show (frame);
        !          1822:     newbox = gtk_vbox_new (FALSE, 4);
        !          1823:     gtk_widget_show (newbox);
        !          1824:     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
        !          1825:     gtk_container_add (GTK_CONTAINER (frame), newbox);
        !          1826: 
        !          1827:     framerate_adj = GTK_ADJUSTMENT (gtk_adjustment_new (currprefs.gfx_framerate, 1, 21, 1, 1, 1));
        !          1828:     gtk_signal_connect (GTK_OBJECT (framerate_adj), "value_changed",
        !          1829:                        GTK_SIGNAL_FUNC (custom_changed), NULL);
        !          1830: 
        !          1831:     thing = gtk_hscale_new (framerate_adj);
        !          1832:     gtk_range_set_update_policy (GTK_RANGE (thing), GTK_UPDATE_DELAYED);
        !          1833:     gtk_scale_set_digits (GTK_SCALE (thing), 0);
        !          1834:     gtk_scale_set_value_pos (GTK_SCALE (thing), GTK_POS_RIGHT);
        !          1835:     thing = make_labelled_widget ("Framerate:", thing, TRUE);
        !          1836:     gtk_widget_show (thing);
        !          1837:     gtk_box_pack_start (GTK_BOX (newbox), thing, FALSE, FALSE, 0);
        !          1838: 
        !          1839:     b32_widget = gtk_check_button_new_with_label ("32 bit blitter");
        !          1840:     add_centered_to_vbox (newbox, b32_widget, 0);
        !          1841: #if 0
        !          1842:     gtk_widget_show (b32_widget);
        !          1843: #endif
        !          1844:     bimm_widget = gtk_check_button_new_with_label ("Immediate blits");
        !          1845:     gtk_box_pack_start (GTK_BOX (newbox), bimm_widget, FALSE, FALSE, 0);
        !          1846:     gtk_widget_show (bimm_widget);
        !          1847: 
        !          1848:     afscr_widget = gtk_check_button_new_with_label ("Amiga modes fullscreen");
        !          1849:     gtk_box_pack_start (GTK_BOX (newbox), afscr_widget, FALSE, FALSE, 0);
        !          1850:     gtk_widget_show (afscr_widget);
        !          1851:     pfscr_widget = gtk_check_button_new_with_label ("Picasso modes fullscreen");
        !          1852:     gtk_box_pack_start (GTK_BOX (newbox), pfscr_widget, FALSE, FALSE, 0);
        !          1853:     gtk_widget_show (pfscr_widget);
        !          1854:     add_empty_vbox (vbox);
        !          1855: 
        !          1856:     gtk_signal_connect (GTK_OBJECT (bimm_widget), "clicked",
        !          1857:                        (GtkSignalFunc) custom_changed, NULL);
        !          1858:     gtk_signal_connect (GTK_OBJECT (afscr_widget), "clicked",
        !          1859:                        (GtkSignalFunc) custom_changed, NULL);
        !          1860:     gtk_signal_connect (GTK_OBJECT (pfscr_widget), "clicked",
        !          1861:                        (GtkSignalFunc) custom_changed, NULL);
        !          1862: #if 0
        !          1863:     gtk_signal_connect (GTK_OBJECT (b32_widget), "clicked",
        !          1864:                        (GtkSignalFunc) custom_changed, NULL);
        !          1865: #endif
        !          1866: }
        !          1867: 
        !          1868: static void make_chipset_widgets (GtkWidget *vbox)
        !          1869: {
        !          1870:     GtkWidget *newbox, *hbox, *thing, *tmpbox;
        !          1871:     static const char *colllabels[] = {
        !          1872:        "None (fastest)", "Sprites only", "Sprites & playfields", "Full (very slow)",
        !          1873:        NULL
        !          1874:     };
        !          1875:     static const char *cslevellabels[] = {
        !          1876:        "OCS", "ECS Agnus", "Full ECS", "AGA", NULL
        !          1877:     };
        !          1878:     static const char *ntsclabels[] = {
        !          1879:        "PAL (European)", "NTSC (American)", NULL
        !          1880:     };
        !          1881: 
        !          1882:     add_empty_vbox (vbox);
        !          1883: 
        !          1884:     mbtype_widget = make_chooser (7, "Generic", "A1000", "A500/A2000", "A600", "A1200", "A3000", "A4000");
        !          1885:     gtk_widget_show (mbtype_widget);
        !          1886:     gtk_signal_connect (GTK_OBJECT (mbtype_widget), "changed", (GtkSignalFunc) mbtype_changed,
        !          1887:                        NULL);
        !          1888:     mbtype_labelled = make_labelled_widget ("Motherboard type:", mbtype_widget, TRUE);
        !          1889:     gtk_widget_show (mbtype_labelled);
        !          1890:     add_centered_to_vbox (vbox, mbtype_labelled, 0);
        !          1891: 
        !          1892:     hbox = gtk_hbox_new (FALSE, 10);
        !          1893:     gtk_widget_show (hbox);
        !          1894:     add_centered_to_vbox (vbox, hbox, 0);
        !          1895: 
        !          1896:     newbox = make_radio_group_box ("Sprite collisions", colllabels, coll_widget, 0, coll_changed, NULL);
        !          1897:     gtk_widget_show (newbox);
        !          1898:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
        !          1899: 
        !          1900:     newbox = make_radio_group_box ("Chipset", cslevellabels, cslevel_widget, 0, cslevel_changed, NULL);
        !          1901:     gtk_widget_show (newbox);
        !          1902:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
        !          1903: 
        !          1904:     newbox = make_radio_group_box ("Chipset video output", ntsclabels, ntsc_widget, 0, ntsc_changed, NULL);
        !          1905:     gtk_widget_show (newbox);
        !          1906:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
        !          1907: 
        !          1908:     reqa4000 = gtk_label_new ("The selected ROM requires at least an A4000.");
        !          1909:     add_centered_to_vbox (vbox, reqa4000, 0);
        !          1910: 
        !          1911:     reqa1000 = gtk_label_new ("The selected ROM requires an A1000 motherboard.");
        !          1912:     add_centered_to_vbox (vbox, reqa1000, 0);
        !          1913: 
        !          1914:     add_empty_vbox (vbox);
        !          1915: 
        !          1916:     thing = gtk_label_new ("Chipset type settings take effect after the next reset.");
        !          1917:     gtk_widget_show (thing);
        !          1918:     add_centered_to_vbox (vbox, thing, 0);
        !          1919: }
        !          1920: 
        !          1921: static void make_sound_widgets (GtkWidget *vbox)
        !          1922: {
        !          1923:     GtkWidget *frame, *newbox;
        !          1924:     int t;
        !          1925:     GtkWidget *hbox, *inner_vbox, *outer_hbox;
        !          1926:     static const char *soundlabels1[] = {
        !          1927:        "None", "No output", "Normal", "Accurate",
        !          1928:        NULL
        !          1929:     }, *soundlabels2[] = {
        !          1930:        "None", "RH", "BS", "Sinc", "Anti",
        !          1931:        NULL
        !          1932:     }, *soundlabels3[] = {
        !          1933:        "Mono", "Stereo",
        !          1934:        NULL
        !          1935:     }, *soundlabels4[] = {
        !          1936:        "Off", "A500 (power LED)", "A500 (always on)",
        !          1937:        "A1200 (power LED)", "A1200 (always on)",
        !          1938:        NULL
        !          1939:     };
        !          1940: 
        !          1941:     add_empty_vbox (vbox);
        !          1942: 
        !          1943:     outer_hbox = gtk_hbox_new (FALSE, 0);
        !          1944:     gtk_widget_show (outer_hbox);
        !          1945:     add_centered_to_vbox (vbox, outer_hbox, 0);
        !          1946:     
        !          1947:     inner_vbox = gtk_vbox_new (FALSE, 0);
        !          1948:     gtk_widget_show (inner_vbox);
        !          1949:     gtk_box_pack_start (GTK_BOX (outer_hbox), inner_vbox, FALSE, TRUE, 0);
        !          1950: 
        !          1951:     hbox = gtk_hbox_new (FALSE, 0);
        !          1952:     add_empty_vbox (hbox);
        !          1953: 
        !          1954:     newbox = make_radio_group_box ("Mode", soundlabels1, sound_widget, 0, sound_changed, NULL);
        !          1955:     gtk_widget_show (newbox);
        !          1956:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
        !          1957: 
        !          1958:     frame = gtk_frame_new ("Channels");
        !          1959:     gtk_widget_show (frame);
        !          1960:     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
        !          1961:     newbox = gtk_vbox_new (FALSE, 4);
        !          1962:     gtk_widget_show (newbox);
        !          1963:     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
        !          1964:     gtk_container_add (GTK_CONTAINER (frame), newbox);
        !          1965:     make_radio_group (soundlabels3, newbox, sound_ch_widget, 0, 1, sound_changed, -1, NULL);
        !          1966: 
        !          1967:     newbox = make_radio_group_box ("Interpolation", soundlabels2, sound_interpol_widget, 0, sound_changed, NULL);
        !          1968:     gtk_widget_show (newbox);
        !          1969:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
        !          1970: 
        !          1971:     newbox = make_radio_group_box ("Filter", soundlabels4, sound_filter_widget, 0, sound_changed, NULL);
        !          1972:     gtk_widget_show (newbox);
        !          1973:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
        !          1974: 
        !          1975:     add_empty_vbox (hbox);
        !          1976:     gtk_widget_show (hbox);
        !          1977:     gtk_box_pack_start (GTK_BOX (inner_vbox), hbox, FALSE, FALSE, 0);
        !          1978: 
        !          1979:     t = currprefs.sound_stereo_separation;
        !          1980:     if (t == 0)
        !          1981:        t = MIXED_STEREO_MAX;
        !          1982:     stereo_sep_adj = GTK_ADJUSTMENT (gtk_adjustment_new (t, 1, MIXED_STEREO_MAX, 1, 1, 0));
        !          1983:     gtk_signal_connect (GTK_OBJECT (stereo_sep_adj), "value_changed",
        !          1984:                        GTK_SIGNAL_FUNC (sound_changed), NULL);
        !          1985: 
        !          1986:     stereo_sep_scale = gtk_hscale_new (stereo_sep_adj);
        !          1987:     gtk_range_set_update_policy (GTK_RANGE (stereo_sep_scale), GTK_UPDATE_DELAYED);
        !          1988:     gtk_scale_set_digits (GTK_SCALE (stereo_sep_scale), 0);
        !          1989:     gtk_scale_set_value_pos (GTK_SCALE (stereo_sep_scale), GTK_POS_RIGHT);
        !          1990:     stereo_sep_scale = make_labelled_widget ("Stereo separation:", stereo_sep_scale, TRUE);
        !          1991:     gtk_widget_show (stereo_sep_scale);
        !          1992:     gtk_box_pack_start (GTK_BOX (inner_vbox), stereo_sep_scale, FALSE, FALSE, 0);
        !          1993: 
        !          1994:     t = currprefs.sound_mixed_stereo_delay;
        !          1995:     stereo_delay_adj = GTK_ADJUSTMENT (gtk_adjustment_new (t, 0, SOUND_MAX_LOG_DELAY, 1, 1, 1));
        !          1996:     gtk_signal_connect (GTK_OBJECT (stereo_delay_adj), "value_changed",
        !          1997:                        GTK_SIGNAL_FUNC (sound_changed), NULL);
        !          1998: 
        !          1999:     stereo_delay_scale = gtk_hscale_new (stereo_delay_adj);
        !          2000:     gtk_range_set_update_policy (GTK_RANGE (stereo_delay_scale), GTK_UPDATE_DELAYED);
        !          2001:     gtk_scale_set_digits (GTK_SCALE (stereo_delay_scale), 0);
        !          2002:     gtk_scale_set_value_pos (GTK_SCALE (stereo_delay_scale), GTK_POS_RIGHT);
        !          2003:     stereo_delay_scale = make_labelled_widget ("Stereo mixing delay:", stereo_delay_scale, TRUE);
        !          2004:     gtk_widget_show (stereo_delay_scale);
        !          2005:     gtk_box_pack_start (GTK_BOX (inner_vbox), stereo_delay_scale, FALSE, FALSE, 0);
        !          2006: 
        !          2007:     add_empty_vbox (vbox);
        !          2008: }
        !          2009: 
        !          2010: static void make_rom_widgets (GtkWidget *dvbox)
        !          2011: {
        !          2012:     GtkWidget *hbox = gtk_hbox_new (FALSE, 10);
        !          2013:     GtkWidget *label, *frame;
        !          2014: 
        !          2015:     rom_req = 0;
        !          2016: 
        !          2017:     add_empty_vbox (dvbox);
        !          2018: 
        !          2019:     {
        !          2020:        GtkWidget *buttonbox = make_file_container ("ROM search path:", dvbox, 0);
        !          2021:        GtkWidget *thing = gtk_button_new_with_label ("Change");
        !          2022: 
        !          2023:        /* Current file display */
        !          2024:        rom_path_widget = make_file_widget (buttonbox);
        !          2025: 
        !          2026:        gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
        !          2027:        gtk_widget_show (thing);
        !          2028:        gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_rompathchange, 0);
        !          2029:     }
        !          2030: 
        !          2031:     {
        !          2032:        GtkWidget *buttonbox = make_file_container ("Kickstart ROM file:", dvbox, 1);
        !          2033:        GtkWidget *hbox, *thing;
        !          2034: 
        !          2035:        romlist_widget = gtk_combo_box_new_text ();
        !          2036:        gtk_widget_show (romlist_widget);
        !          2037:        gtk_box_pack_start (GTK_BOX (buttonbox), romlist_widget, FALSE, TRUE, 0);
        !          2038:        gtk_combo_box_append_text (GTK_COMBO_BOX (romlist_widget),
        !          2039:                                   "Manually select a ROM file");
        !          2040:        romlist_nr_entries = 1;
        !          2041:        gtk_signal_connect (GTK_OBJECT (romlist_widget), "changed", (GtkSignalFunc) rom_combo_changed, 0);
        !          2042: 
        !          2043:        hbox = gtk_hbox_new (FALSE, 0);
        !          2044:        gtk_box_pack_start (GTK_BOX (buttonbox), hbox, FALSE, TRUE, 0);
        !          2045:        gtk_widget_show (hbox);
        !          2046: 
        !          2047:        /* Current file display */
        !          2048:        rom_text_widget = make_file_widget (hbox);
        !          2049: 
        !          2050:        romsel_button = gtk_button_new_with_label ("Change");
        !          2051:        gtk_box_pack_start (GTK_BOX (hbox), romsel_button, FALSE, TRUE, 0);
        !          2052:        gtk_widget_show (romsel_button);
        !          2053:        gtk_signal_connect (GTK_OBJECT (romsel_button), "clicked", (GtkSignalFunc) did_romchange, 0);
        !          2054:     }
        !          2055: 
        !          2056:     {
        !          2057:        GtkWidget *buttonbox = make_file_container ("ROM key file for Cloanto Amiga Forever:", dvbox, 0);
        !          2058:        GtkWidget *thing = gtk_button_new_with_label ("Change");
        !          2059: 
        !          2060:        /* Current file display */
        !          2061:        key_text_widget = make_file_widget (buttonbox);
        !          2062: 
        !          2063:        gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
        !          2064:        gtk_widget_show (thing);
        !          2065:        gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_keychange, 0);
        !          2066:     }
        !          2067: 
        !          2068:     label = gtk_label_new ("These settings take effect after the next reset.");
        !          2069:     gtk_widget_show (label);
        !          2070:     add_centered_to_vbox (dvbox, label, 0);
        !          2071: 
        !          2072:     add_empty_vbox (dvbox);
        !          2073: }
        !          2074: 
        !          2075: static void make_ram_widgets (GtkWidget *dvbox)
        !          2076: {
        !          2077:     GtkWidget *hbox = gtk_hbox_new (FALSE, 10);
        !          2078:     GtkWidget *label, *frame;
        !          2079: 
        !          2080:     static const char *chiplabels[] = {
        !          2081:        "512 KB", "1 MB", "2 MB", "4 MB", "8 MB", NULL
        !          2082:     };
        !          2083:     static const char *bogolabels[] = {
        !          2084:        "None", "512 KB", "1 MB", "1.8 MB", NULL
        !          2085:     };
        !          2086:     static const char *fastlabels[] = {
        !          2087:        "None", "1 MB", "2 MB", "4 MB", "8 MB", NULL
        !          2088:     };
        !          2089:     static const char *z3labels[] = {
        !          2090:        "None", "1 MB", "2 MB", "4 MB", "8 MB",
        !          2091:        "16 MB", "32 MB", "64 MB", "128 MB", "256 MB",
        !          2092:        NULL
        !          2093:     };
        !          2094:     static const char *p96labels[] = {
        !          2095:        "None", "1 MB", "2 MB", "4 MB", "8 MB", "16 MB", "32 MB", NULL
        !          2096:     };
        !          2097: 
        !          2098:     add_empty_vbox (dvbox);
        !          2099: 
        !          2100:     gtk_widget_show (hbox);
        !          2101:     add_centered_to_vbox (dvbox, hbox, 0);
        !          2102: 
        !          2103:     add_empty_vbox (dvbox);
        !          2104: 
        !          2105:     label = gtk_label_new ("These settings take effect after the next reset.");
        !          2106:     gtk_widget_show (label);
        !          2107:     add_centered_to_vbox (dvbox, label, 0);
        !          2108: 
        !          2109:     frame = make_radio_group_box ("Chip Mem", chiplabels, chipsize_widget, 0, chipsize_changed, NULL);
        !          2110:     gtk_widget_show (frame);
        !          2111:     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
        !          2112: 
        !          2113:     frame = make_radio_group_box ("Slow Mem", bogolabels, bogosize_widget, 0, bogosize_changed, NULL);
        !          2114:     gtk_widget_show (frame);
        !          2115:     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
        !          2116: 
        !          2117:     frame = make_radio_group_box ("Fast Mem", fastlabels, fastsize_widget, 0, fastsize_changed, NULL);
        !          2118:     gtk_widget_show (frame);
        !          2119:     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
        !          2120: 
        !          2121:     frame = make_radio_group_box_1 ("Z3 Mem", z3labels, z3size_widget, 0, z3size_changed, 5);
        !          2122:     gtk_widget_show (frame);
        !          2123:     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
        !          2124: 
        !          2125:     frame = make_radio_group_box_1 ("P96 RAM", p96labels, p96size_widget, 0, p96size_changed, 4);
        !          2126:     gtk_widget_show (frame);
        !          2127:     gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
        !          2128: }
        !          2129: 
        !          2130: static void make_joy_widgets (GtkWidget *dvbox)
        !          2131: {
        !          2132:     int i;
        !          2133:     GtkWidget *hbox = gtk_hbox_new (FALSE, 10);
        !          2134:     GtkWidget *thing;
        !          2135:     static const char *joylabels[] = {
        !          2136:        "Joystick 0", "Joystick 1", "Mouse", "Numeric pad",
        !          2137:        "Cursor keys/Right Ctrl", "T/F/H/B/Left Alt",
        !          2138:        NULL
        !          2139:     };
        !          2140: 
        !          2141:     add_empty_vbox (dvbox);
        !          2142:     gtk_widget_show (hbox);
        !          2143:     add_centered_to_vbox (dvbox, hbox, 0);
        !          2144: 
        !          2145:     legacy_widget = gtk_check_button_new_with_label ("Use legacy configuration");
        !          2146:     add_centered_to_vbox (dvbox, legacy_widget, 0);
        !          2147:     gtk_widget_show (legacy_widget);
        !          2148:     gtk_signal_connect (GTK_OBJECT (legacy_widget), "clicked",
        !          2149:                        (GtkSignalFunc) joy_changed, NULL);
        !          2150: 
        !          2151:     for (i = 0; i < 2; i++) {
        !          2152:        GtkWidget *vbox, *frame;
        !          2153:        char buffer[20];
        !          2154:        int j;
        !          2155: 
        !          2156:        sprintf (buffer, "Port %d", i);
        !          2157:        frame = make_radio_group_box (buffer, joylabels, joy_widget[i], 0, joy_changed, NULL);
        !          2158:        gtk_widget_show (frame);
        !          2159:        gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
        !          2160:     }
        !          2161: 
        !          2162:     thing = make_chooser (7, "English (QWERTY)", "Danish", "Deutsch (QWERTZ)", "Swedish",
        !          2163:                          "Francais (AZERTY)", "Italian", "Spanish");
        !          2164:     gtk_signal_connect (GTK_OBJECT (thing), "changed", (GtkSignalFunc) kbdlang_changed,
        !          2165:                        GINT_TO_POINTER (i));
        !          2166:     kbdlang_widget = thing;
        !          2167:     thing = add_labelled_widget_centered ("Keyboard language:", thing, dvbox);
        !          2168: 
        !          2169:     add_empty_vbox (dvbox);
        !          2170: }
        !          2171: 
        !          2172: static GtkWidget *leftalign (GtkWidget *thing)
        !          2173: {
        !          2174:     GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
        !          2175:     gtk_box_pack_start (GTK_BOX (hbox), thing, FALSE, FALSE, 0);
        !          2176:     return hbox;
        !          2177: }
        !          2178: 
        !          2179: static GtkWidget *create_dirdlg (const char *title, int row)
        !          2180: {
        !          2181:     GtkWidget *vbox, *pathsel, *dirdlg;
        !          2182:     GtkWidget *path_entry, *volname_entry, *pri_entry;
        !          2183: 
        !          2184:     dirdlg = gtk_dialog_new_with_buttons (title, GTK_WINDOW (gui_window),
        !          2185:                                          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
        !          2186:                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
        !          2187:                                          GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
        !          2188:                                          NULL);
        !          2189: 
        !          2190:     gtk_window_set_position (GTK_WINDOW (dirdlg), GTK_WIN_POS_MOUSE);
        !          2191: 
        !          2192:     vbox = GTK_DIALOG (dirdlg)->vbox;
        !          2193: 
        !          2194:     pathsel = make_file_selector ("Select a path to mount",
        !          2195:                                  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
        !          2196: 
        !          2197:     gtkutil_add_table (GTK_WIDGET (vbox),
        !          2198:                       leftalign (gtk_label_new ("Path:")), 1, 1, GTK_FILL,
        !          2199:                       leftalign (path_entry = gtk_file_chooser_button_new_with_dialog (pathsel)), 2, 1, GTK_FILL,
        !          2200:                       GTKUTIL_ROW_END,
        !          2201:                       leftalign (gtk_label_new ("Volume name:")), 1, 1, GTK_FILL,
        !          2202:                       leftalign (volname_entry = gtk_entry_new_with_max_length (32)), 2, 1, GTK_FILL,
        !          2203:                       GTKUTIL_ROW_END,
        !          2204:                       leftalign (gtk_label_new ("Boot priority:")), 1, 1, GTK_FILL,
        !          2205:                       leftalign (pri_entry = gtk_entry_new_with_max_length (2)), 2, 1, GTK_FILL,
        !          2206:                       GTKUTIL_TABLE_END);
        !          2207: 
        !          2208:     if (row != -1) {
        !          2209:        char *failure;
        !          2210:        char t[20];
        !          2211:        int secspertrack, surfaces, reserved, blocksize, size;
        !          2212:        int cylinders, readonly, pri;
        !          2213:        char *volname, *rootdir, *devname;
        !          2214: 
        !          2215:        failure = get_filesys_unit (currprefs.mountinfo, row,
        !          2216:                                    &devname, &volname, &rootdir, &readonly,
        !          2217:                                    &secspertrack, &surfaces, &reserved,
        !          2218:                                    &cylinders, &size, &blocksize, &pri);
        !          2219:        if (failure) {
        !          2220:            mkmsgbox ("Error", failure);
        !          2221:            goto out;
        !          2222:        }
        !          2223:        gtk_entry_set_text (GTK_ENTRY (volname_entry), volname);
        !          2224:        gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (path_entry), rootdir);
        !          2225:        sprintf (t, "%d", pri);
        !          2226:        gtk_entry_set_text (GTK_ENTRY (pri_entry), t);
        !          2227:        if (volname)
        !          2228:            free (volname);
        !          2229:        if (devname)
        !          2230:            free (devname);
        !          2231:        if (rootdir)
        !          2232:            free (rootdir);
        !          2233:     }
        !          2234: 
        !          2235:   retry:
        !          2236:     if (gtk_dialog_run (GTK_DIALOG (dirdlg)) == GTK_RESPONSE_ACCEPT) {
        !          2237:        const char *failure;
        !          2238:        const char *pathname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (path_entry));
        !          2239:        const char *volname = gtk_entry_get_text (GTK_ENTRY (volname_entry));
        !          2240:        const char *bprstr = gtk_entry_get_text (GTK_ENTRY (pri_entry));
        !          2241:        char fixed_volname[256];
        !          2242:        int n, bpr;
        !          2243: 
        !          2244:        if (pathname == NULL || strlen (pathname) == 0 || access (pathname, R_OK) != 0) {
        !          2245:            mkmsgbox ("Error", "You must select a valid path.");
        !          2246:            goto retry;
        !          2247:        }
        !          2248:        n = volname == NULL ? 0 : strlen (volname);
        !          2249:        if (n > 255) {
        !          2250:            mkmsgbox ("Error", "Volume name too long.");
        !          2251:            goto retry;
        !          2252:        }
        !          2253:        /* Strip colons from the end.  */
        !          2254:        if (n > 0) {
        !          2255:            strcpy (fixed_volname, volname);
        !          2256:            if (fixed_volname[n - 1] == ':') {
        !          2257:                fixed_volname[n - 1] = '\0';
        !          2258:                n--;
        !          2259:            }
        !          2260:        }
        !          2261: 
        !          2262:        if (n == 0) {
        !          2263:            mkmsgbox ("Error", "You must enter a volume name.");
        !          2264:            goto retry;
        !          2265:        }
        !          2266: 
        !          2267:        if (strlen (bprstr) == 0) {
        !          2268:            mkmsgbox ("Error", "You must enter a valid number of surfaces.");
        !          2269:            goto retry;
        !          2270:        }
        !          2271:        bpr = atoi (bprstr);
        !          2272: 
        !          2273:        if (row == -1) {
        !          2274:            failure = add_filesys_unit (currprefs.mountinfo, NULL, fixed_volname, pathname,
        !          2275:                                        0, 0, 0, 0, 0, bpr);
        !          2276:        } else {
        !          2277:            failure = set_filesys_unit (currprefs.mountinfo, row, NULL, fixed_volname, pathname,
        !          2278:                                        0, 0, 0, 0, 0, bpr);
        !          2279:        }
        !          2280:        if (failure) {
        !          2281:            mkmsgbox ("Error", failure);
        !          2282:            goto retry;
        !          2283:        }
        !          2284:        set_hd_state ();
        !          2285:     }
        !          2286: 
        !          2287:   out:
        !          2288:     gtk_widget_destroy (dirdlg);
        !          2289:     return 0;
        !          2290: }
        !          2291: 
        !          2292: static void create_hdfdlg (const char *title, int row)
        !          2293: {
        !          2294:     GtkWidget *vbox, *pathsel;
        !          2295:     GtkWidget *hdfdlg;
        !          2296:     static GtkWidget *bpt_entry, *surfaces_entry, *pri_entry;
        !          2297:     static GtkWidget *blocksize_entry, *reserved_entry, *path_entry;
        !          2298: 
        !          2299:     int readonly = 0;
        !          2300: 
        !          2301:     hdfdlg = gtk_dialog_new_with_buttons (title, GTK_WINDOW (gui_window),
        !          2302:                                          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
        !          2303:                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
        !          2304:                                          GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
        !          2305:                                          NULL);
        !          2306: 
        !          2307:     gtk_window_set_position (GTK_WINDOW (hdfdlg), GTK_WIN_POS_MOUSE);
        !          2308: 
        !          2309:     pathsel = make_file_selector ("Select a path to mount",
        !          2310:                                  GTK_FILE_CHOOSER_ACTION_OPEN);
        !          2311: 
        !          2312:     vbox = GTK_DIALOG (hdfdlg)->vbox;
        !          2313: 
        !          2314:     gtkutil_add_table (GTK_WIDGET (vbox),
        !          2315:                       leftalign (gtk_label_new ("File:")), 1, 1, GTK_FILL,
        !          2316:                       leftalign (path_entry = gtk_file_chooser_button_new_with_dialog (pathsel)), 2, 1, GTK_FILL,
        !          2317:                       GTKUTIL_ROW_END,
        !          2318:                       leftalign (gtk_label_new ("Reserved blocks:")), 1, 1, GTK_FILL,
        !          2319:                       leftalign (reserved_entry = gtk_entry_new_with_max_length (6)), 2, 1, GTK_FILL,
        !          2320:                       GTKUTIL_ROW_END,
        !          2321:                       leftalign (gtk_label_new ("Surfaces:")), 1, 1, GTK_FILL,
        !          2322:                       leftalign (surfaces_entry = gtk_entry_new_with_max_length (2)), 2, 1, GTK_FILL,
        !          2323:                       GTKUTIL_ROW_END,
        !          2324:                       leftalign (gtk_label_new ("Blocksize:")), 1, 1, GTK_FILL,
        !          2325:                       leftalign (blocksize_entry = gtk_entry_new_with_max_length (6)), 2, 1, GTK_FILL,
        !          2326:                       GTKUTIL_ROW_END,                
        !          2327:                       leftalign (gtk_label_new ("Blocks per track:")), 1, 1, GTK_FILL,
        !          2328:                       leftalign (bpt_entry = gtk_entry_new_with_max_length (6)), 2, 1, GTK_FILL,
        !          2329:                       GTKUTIL_ROW_END,
        !          2330:                       leftalign (gtk_label_new ("Boot priority:")), 1, 1, GTK_FILL,
        !          2331:                       leftalign (pri_entry = gtk_entry_new_with_max_length (2)), 2, 1, GTK_FILL,
        !          2332: 
        !          2333:                       GTKUTIL_TABLE_END);
        !          2334: 
        !          2335:     gtk_file_chooser_button_set_width_chars (GTK_FILE_CHOOSER_BUTTON (path_entry), 40);
        !          2336: 
        !          2337:     if (row != -1) {
        !          2338:        char *failure;
        !          2339:        char *devname, *volname, *rootdir;
        !          2340:        int secspertrack, surfaces, reserved, blocksize, size;
        !          2341:        int cylinders, pri;
        !          2342:        char t[20];
        !          2343: 
        !          2344:        failure = get_filesys_unit (currprefs.mountinfo, row,
        !          2345:                                    &devname, &volname, &rootdir, &readonly,
        !          2346:                                    &secspertrack, &surfaces, &reserved,
        !          2347:                                    &cylinders, &size, &blocksize, &pri);
        !          2348:        if (failure) {
        !          2349:            mkmsgbox ("Error", failure);
        !          2350:            goto out;
        !          2351:        }
        !          2352:        gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (path_entry), rootdir);
        !          2353:        sprintf (t, "%d", blocksize);
        !          2354:        gtk_entry_set_text (GTK_ENTRY (blocksize_entry), t);
        !          2355:        sprintf (t, "%d", secspertrack);
        !          2356:        gtk_entry_set_text (GTK_ENTRY (bpt_entry), t);
        !          2357:        sprintf (t, "%d", surfaces);
        !          2358:        gtk_entry_set_text (GTK_ENTRY (surfaces_entry), t);
        !          2359:        sprintf (t, "%d", reserved);
        !          2360:        gtk_entry_set_text (GTK_ENTRY (reserved_entry), t);
        !          2361:        sprintf (t, "%d", pri);
        !          2362:        gtk_entry_set_text (GTK_ENTRY (pri_entry), t);
        !          2363:        if (volname)
        !          2364:            free (volname);
        !          2365:        if (devname)
        !          2366:            free (devname);
        !          2367:        if (rootdir)
        !          2368:            free (rootdir);
        !          2369:     }
        !          2370: 
        !          2371:   retry:
        !          2372:     if (gtk_dialog_run (GTK_DIALOG (hdfdlg)) == GTK_RESPONSE_ACCEPT) {
        !          2373:        const char *failure;
        !          2374:        const char *new_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (path_entry));
        !          2375:        const char *bptstr = gtk_entry_get_text (GTK_ENTRY (bpt_entry));
        !          2376:        const char *sfstr = gtk_entry_get_text (GTK_ENTRY (surfaces_entry));
        !          2377:        const char *bsstr = gtk_entry_get_text (GTK_ENTRY (blocksize_entry));
        !          2378:        const char *rsrvstr = gtk_entry_get_text (GTK_ENTRY (reserved_entry));
        !          2379:        const char *bprstr = gtk_entry_get_text (GTK_ENTRY (pri_entry));
        !          2380:        int n, sf, bpt, bs, rsrv, bpr;
        !          2381: 
        !          2382:        if (new_filename == NULL || strlen (new_filename) == 0) {
        !          2383:            mkmsgbox ("Error", "You must enter a valid filename.");
        !          2384:            goto retry;
        !          2385:        }
        !          2386: 
        !          2387:        if (strlen (bptstr) == 0 || (bpt = atoi (bptstr)) == 0) {
        !          2388:            mkmsgbox ("Error", "You must enter a valid number of blocks per track.");
        !          2389:            goto retry;
        !          2390:        }
        !          2391:        if (strlen (rsrvstr) == 0) {
        !          2392:            mkmsgbox ("Error", "You must enter the number of reserved blocks.");
        !          2393:            goto retry;
        !          2394:        }
        !          2395:        rsrv = atoi (rsrvstr);
        !          2396:        if (strlen (sfstr) == 0 || (sf = atoi (sfstr)) == 0) {
        !          2397:            mkmsgbox ("Error", "You must enter a valid number of surfaces.");
        !          2398:            goto retry;
        !          2399:        }
        !          2400:        if (strlen (bsstr) == 0 || (bs = atoi (bsstr)) == 0) {
        !          2401:            mkmsgbox ("Error", "You must enter a valid number of surfaces.");
        !          2402:            goto retry;
        !          2403:        }
        !          2404:        if (strlen (bprstr) == 0) {
        !          2405:            mkmsgbox ("Error", "You must enter a valid number of surfaces.");
        !          2406:            goto retry;
        !          2407:        }
        !          2408:        bpr = atoi (bprstr);
        !          2409: 
        !          2410:        if (row == -1) {
        !          2411:            failure = add_filesys_unit (currprefs.mountinfo, NULL, NULL, new_filename,
        !          2412:                                        readonly, bpt, sf, rsrv, bs, bpr);
        !          2413:        } else {
        !          2414:            failure = set_filesys_unit (currprefs.mountinfo, row, NULL, NULL, new_filename,
        !          2415:                                        readonly, bpt, sf, rsrv, bs, bpr);
        !          2416:        }
        !          2417:        if (failure) {
        !          2418:            mkmsgbox ("Error", failure);
        !          2419:            goto retry;
        !          2420:        }
        !          2421:        set_hd_state ();
        !          2422:     }
        !          2423:   out:
        !          2424:     gtk_widget_destroy (hdfdlg);
        !          2425:     return;
        !          2426: }
        !          2427: 
        !          2428: static void did_newdir (void)
        !          2429: {
        !          2430:     create_dirdlg ("Add a new mounted directory", -1);
        !          2431: }
        !          2432: 
        !          2433: static void did_newhdf (void)
        !          2434: {
        !          2435:     create_hdfdlg ("Add a new hardfile", -1);
        !          2436: }
        !          2437: 
        !          2438: static void did_newadf (void)
        !          2439: {
        !          2440:     make_disk_selector ();
        !          2441: 
        !          2442:     if (gtk_dialog_run (GTK_DIALOG (disk_selector)) == GTK_RESPONSE_ACCEPT) {
        !          2443:        char *filename;
        !          2444:        struct zfile *f;
        !          2445:        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (disk_selector));
        !          2446: 
        !          2447:        f = zfile_open (filename, "rb");
        !          2448:        if (f) {
        !          2449:            const char *failure;
        !          2450:            char buf[512];
        !          2451:            long size;
        !          2452:            zfile_fread (buf, 1, 512, f);
        !          2453:            zfile_fseek (f, 0, SEEK_END);
        !          2454:            size = zfile_ftell (f);
        !          2455:            if (buf[0] != 'D' || buf[1] != 'O' || buf[2] != 'S'
        !          2456:                || (buf[3] != 0 && buf[3] != 1)
        !          2457:                || size != 901120)
        !          2458:            {
        !          2459:                mkmsgbox ("Error", "Not an ADF diskfile.");
        !          2460:            } else {
        !          2461:                failure = add_filesys_unit (currprefs.mountinfo, NULL, NULL, filename,
        !          2462:                                            0, 11, 2, 2, 512, -2);
        !          2463:                if (failure)
        !          2464:                    mkmsgbox ("Error", failure);
        !          2465:                else
        !          2466:                    set_hd_state ();
        !          2467:            }
        !          2468:            zfile_fclose (f);
        !          2469:        }
        !          2470: 
        !          2471:        g_free (filename);
        !          2472:     }
        !          2473: 
        !          2474:     gtk_widget_hide (disk_selector);
        !          2475: }
        !          2476: 
        !          2477: static void did_hdchange (void)
        !          2478: {
        !          2479:     GtkTreeIter iter;
        !          2480:     GtkTreeModel *model;
        !          2481:     int idx;
        !          2482: 
        !          2483:     if (gtk_tree_selection_get_selected (hd_selection, &model, &iter))
        !          2484:        gtk_tree_model_get (model, &iter, 0, &idx, -1);
        !          2485:     else
        !          2486:        return;
        !          2487: 
        !          2488:     if (is_hardfile (currprefs.mountinfo, idx)) {
        !          2489:        create_hdfdlg ("Change a hardfile", idx);
        !          2490:     } else {
        !          2491:        create_dirdlg ("Change a mounted directory", idx);
        !          2492:    }
        !          2493: }
        !          2494: static void did_hddel (void)
        !          2495: {
        !          2496:     GtkTreeIter iter;
        !          2497:     GtkTreeModel *model;
        !          2498:     int idx;
        !          2499: 
        !          2500:     if (gtk_tree_selection_get_selected (hd_selection, &model, &iter))
        !          2501:        gtk_tree_model_get (model, &iter, 0, &idx, -1);
        !          2502:     else
        !          2503:        return;
        !          2504: 
        !          2505:     kill_filesys_unit (currprefs.mountinfo, idx);
        !          2506:     set_hd_state ();
        !          2507: }
        !          2508: 
        !          2509: static void hdsel_changed (GtkWidget *widget, gint row, gint column, GdkEventButton *bevent,
        !          2510:                           gpointer user_data)
        !          2511: {
        !          2512:     GtkTreeIter iter;
        !          2513:     GtkTreeModel *model;
        !          2514: 
        !          2515:     if (gtk_tree_selection_get_selected (hd_selection, &model, &iter)) {
        !          2516:        gtk_widget_set_sensitive (hdchange_button, TRUE);
        !          2517:        gtk_widget_set_sensitive (hddel_button, TRUE);
        !          2518:     } else {
        !          2519:        gtk_widget_set_sensitive (hdchange_button, FALSE);
        !          2520:        gtk_widget_set_sensitive (hddel_button, FALSE);
        !          2521:     }
        !          2522: }
        !          2523: 
        !          2524: static void hdunselect (GtkWidget *widget, gint row, gint column, GdkEventButton *bevent,
        !          2525:                        gpointer user_data)
        !          2526: {
        !          2527:     gtk_widget_set_sensitive (hdchange_button, FALSE);
        !          2528:     gtk_widget_set_sensitive (hddel_button, FALSE);
        !          2529: }
        !          2530: 
        !          2531: static void preset_changed (GtkTreeSelection *selection, gpointer data)
        !          2532: {
        !          2533:     GtkTreeIter iter;
        !          2534:     GtkTreeModel *model;
        !          2535: 
        !          2536:     if (gtk_tree_selection_get_selected (selection, &model, &iter))
        !          2537:        gtk_widget_set_sensitive (preset_button, TRUE);
        !          2538:     else
        !          2539:        gtk_widget_set_sensitive (preset_button, FALSE);
        !          2540: }
        !          2541: 
        !          2542: static void did_set_preset (void)
        !          2543: {
        !          2544:     GtkTreeIter iter;
        !          2545:     GtkTreeModel *model;
        !          2546:     gchar *filename;
        !          2547: 
        !          2548:     if (gtk_tree_selection_get_selected (preset_selection, &model, &iter)) {
        !          2549:        gtk_tree_model_get (model, &iter, 1, &filename, -1);
        !          2550: 
        !          2551:        if (filename) {
        !          2552:            cfgfile_load (&changed_prefs, filename);
        !          2553:            set_widgets_from_config ();
        !          2554:        }
        !          2555:        g_free (filename);
        !          2556:     }
        !          2557: }
        !          2558: 
        !          2559: static GtkWidget *make_buttons_1 (const char *label, GtkWidget *box, void (*sigfunc) (void),
        !          2560:                                  GtkWidget *(*create)(const char *label), int expand)
        !          2561: {
        !          2562:     GtkWidget *thing = create (label);
        !          2563:     gtk_widget_show (thing);
        !          2564:     gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) sigfunc, NULL);
        !          2565:     gtk_box_pack_start (GTK_BOX (box), thing, expand, expand, 0);
        !          2566: 
        !          2567:     return thing;
        !          2568: }
        !          2569: #define make_buttons(label, box, sigfunc, create) make_buttons_1(label, box, sigfunc, create, 1)
        !          2570: #define make_button(label, box, sigfunc) make_buttons(label, box, sigfunc, gtk_button_new_with_label)
        !          2571: 
        !          2572: static void new_text_cell_renderer (GtkWidget *treeview, const char *title, int colnr,
        !          2573:                                    int expand, int ellipsize)
        !          2574: {
        !          2575:     GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
        !          2576:     GtkTreeViewColumn *column;
        !          2577:     column = gtk_tree_view_column_new_with_attributes (title, renderer,
        !          2578:                                                       "text", colnr, NULL);
        !          2579:     gtk_tree_view_column_set_expand (column, expand);
        !          2580:     gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
        !          2581:     if (ellipsize)
        !          2582:        g_object_set (renderer,
        !          2583:                      "ellipsize", PANGO_ELLIPSIZE_START,
        !          2584:                      "ellipsize-set", TRUE,
        !          2585:                      NULL);
        !          2586: }
        !          2587: 
        !          2588: static void make_hd_widgets (GtkWidget *dvbox)
        !          2589: {
        !          2590:     GtkCellRenderer *renderer;
        !          2591:     GtkTreeViewColumn *column;
        !          2592:     GtkAdjustment *adj;
        !          2593:     GtkWidget *scrolled, *buttonbox, *vbox, *hbox;
        !          2594:     int i;
        !          2595: 
        !          2596:     hd_store = gtk_list_store_new (11,
        !          2597:                                   G_TYPE_INT,
        !          2598:                                   G_TYPE_STRING, G_TYPE_STRING,
        !          2599:                                   G_TYPE_BOOLEAN,
        !          2600:                                   G_TYPE_STRING, G_TYPE_STRING,
        !          2601:                                   G_TYPE_STRING, G_TYPE_STRING,
        !          2602:                                   G_TYPE_STRING, G_TYPE_STRING,
        !          2603:                                   G_TYPE_INT);
        !          2604: 
        !          2605: #if 0
        !          2606:     add_empty_vbox (dvbox);
        !          2607: #endif
        !          2608: 
        !          2609:     hbox = gtk_hbox_new (FALSE, 0);
        !          2610:     gtk_box_pack_start (GTK_BOX (dvbox), hbox, TRUE, TRUE, 20);
        !          2611:     gtk_widget_show (hbox);
        !          2612: 
        !          2613:     vbox = gtk_vbox_new (FALSE, 4);
        !          2614:     gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
        !          2615:     gtk_widget_show (vbox);
        !          2616: 
        !          2617:     hdlist_widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL (hd_store));
        !          2618: 
        !          2619:     new_text_cell_renderer (hdlist_widget, "Volume", 1, 0, 0);
        !          2620:     new_text_cell_renderer (hdlist_widget, "Path/File", 2, 1, 1);
        !          2621:     
        !          2622:     renderer = gtk_cell_renderer_toggle_new ();
        !          2623:     column = gtk_tree_view_column_new_with_attributes ("R/O", renderer,
        !          2624:                                                       "active", 3, NULL);
        !          2625:     gtk_tree_view_column_set_expand (column, 0);
        !          2626:     gtk_tree_view_append_column (GTK_TREE_VIEW (hdlist_widget), column);
        !          2627: 
        !          2628:     new_text_cell_renderer (hdlist_widget, "Heads", 4, 0, 0);
        !          2629:     new_text_cell_renderer (hdlist_widget, "Cyl.", 5, 0, 0);
        !          2630:     new_text_cell_renderer (hdlist_widget, "Sec.", 6, 0, 0);
        !          2631:     new_text_cell_renderer (hdlist_widget, "Rsrvd", 7, 0, 0);
        !          2632:     new_text_cell_renderer (hdlist_widget, "Size", 8, 0, 0);
        !          2633:     new_text_cell_renderer (hdlist_widget, "Blksize", 9, 0, 0);
        !          2634:     new_text_cell_renderer (hdlist_widget, "Pri", 10, 0, 0);
        !          2635: 
        !          2636:     gtk_widget_show (hdlist_widget);
        !          2637: 
        !          2638:     scrolled = gtk_scrolled_window_new (NULL, NULL);
        !          2639:     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
        !          2640:                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
        !          2641:     gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
        !          2642:     gtk_widget_show (scrolled);
        !          2643: 
        !          2644:     gtk_container_add (GTK_CONTAINER (scrolled), hdlist_widget);
        !          2645: 
        !          2646:     hd_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (hdlist_widget));
        !          2647:     gtk_tree_selection_set_mode (hd_selection, GTK_SELECTION_SINGLE);
        !          2648:     g_signal_connect (G_OBJECT (hd_selection), "changed",
        !          2649:                      G_CALLBACK (hdsel_changed), NULL);
        !          2650: 
        !          2651:     /* The buttons */
        !          2652:     buttonbox = gtk_hbox_new (FALSE, 4);
        !          2653:     gtk_widget_show (buttonbox);
        !          2654:     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, FALSE, 0);
        !          2655:     make_button ("New filesystem...", buttonbox, did_newdir);
        !          2656:     make_button ("New hardfile...", buttonbox, did_newhdf);
        !          2657:     make_button ("Mount floppy as HD...", buttonbox, did_newadf);
        !          2658: 
        !          2659:     buttonbox = gtk_hbox_new (FALSE, 4);
        !          2660:     gtk_widget_show (buttonbox);
        !          2661:     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, FALSE, 0);
        !          2662:     hdchange_button = make_button ("Change...", buttonbox, did_hdchange);
        !          2663:     hddel_button = make_button ("Delete", buttonbox, did_hddel);
        !          2664: 
        !          2665:     bootrom_widget = gtk_check_button_new_with_label ("Enable bootrom - needed for filesystem, Picasso96 and better mouse support;\ndisable only in case of (unlikely) compatibility issues");
        !          2666:     add_centered_to_vbox (dvbox, bootrom_widget, 0);
        !          2667:     gtk_widget_show (bootrom_widget);
        !          2668:     gtk_signal_connect (GTK_OBJECT (bootrom_widget), "clicked",
        !          2669:                        (GtkSignalFunc) bootrom_changed, NULL);
        !          2670: #if 0
        !          2671:     add_empty_vbox (dvbox);
        !          2672: #endif
        !          2673: }
        !          2674: 
        !          2675: static void make_presets (GtkWidget *dvbox)
        !          2676: {
        !          2677:     GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
        !          2678:     GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
        !          2679:     GtkTreeViewColumn *column;
        !          2680:     GtkWidget *scrolled, *buttonbox, *vbox, *hbox;
        !          2681:     int i;
        !          2682: 
        !          2683:     add_empty_vbox (dvbox);
        !          2684: 
        !          2685:     hbox = gtk_hbox_new (FALSE, 0);
        !          2686:     gtk_box_pack_start (GTK_BOX (dvbox), hbox, TRUE, TRUE, 0);
        !          2687:     gtk_widget_show (hbox);
        !          2688: 
        !          2689:     add_empty_vbox (hbox);
        !          2690: 
        !          2691:     vbox = gtk_vbox_new (FALSE, 4);
        !          2692:     gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
        !          2693:     gtk_widget_show (vbox);
        !          2694: 
        !          2695:     for (i = 0; i < n_predef_configs; i++) {
        !          2696:        GtkTreeIter iter;
        !          2697:        gtk_list_store_append (store, &iter);
        !          2698: 
        !          2699:        gtk_list_store_set (store, &iter,
        !          2700:                            0, predef_configs[i].description,
        !          2701:                            1, predef_configs[i].filename,
        !          2702:                            -1);
        !          2703:     }
        !          2704:     preset_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
        !          2705:     gtk_widget_show (preset_list);
        !          2706: 
        !          2707:     new_text_cell_renderer (preset_list, "Hardware configuration presets", 0, 1, 0);
        !          2708: 
        !          2709:     scrolled = gtk_scrolled_window_new (NULL, NULL);
        !          2710:     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
        !          2711:                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
        !          2712:     gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
        !          2713:     gtk_widget_show (scrolled);
        !          2714: 
        !          2715:     gtk_container_add (GTK_CONTAINER (scrolled), preset_list);
        !          2716: 
        !          2717:     preset_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (preset_list));
        !          2718:     gtk_tree_selection_set_mode (preset_selection, GTK_SELECTION_SINGLE);
        !          2719:     g_signal_connect (G_OBJECT (preset_selection), "changed",
        !          2720:                      G_CALLBACK (preset_changed),
        !          2721:                      NULL);
        !          2722: 
        !          2723:     /* The buttons */
        !          2724:     buttonbox = gtk_hbox_new (FALSE, 4);
        !          2725:     gtk_widget_show (buttonbox);
        !          2726:     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, FALSE, 0);
        !          2727:     preset_button = make_buttons_1 ("Set configuration to chosen preset", buttonbox, did_set_preset,
        !          2728:                                    gtk_button_new_with_label, 0);
        !          2729: 
        !          2730:     add_empty_vbox (hbox);
        !          2731: 
        !          2732:     add_empty_vbox (dvbox);
        !          2733: }
        !          2734: 
        !          2735: static void make_about_widgets (GtkWidget *dvbox)
        !          2736: {
        !          2737:     GtkWidget *lab_version;
        !          2738:     GtkStyle *style;
        !          2739:     GdkFont *font;
        !          2740:     char t[20];
        !          2741: 
        !          2742:     add_empty_vbox (dvbox);
        !          2743: 
        !          2744:     sprintf (t, "%s %s", PACKAGE_NAME, PACKAGE_VERSION);
        !          2745:     lab_version = gtk_label_new (t);
        !          2746:     lab_info = gtk_label_new ("Choose your settings, then deselect the Pause button to start!");
        !          2747: 
        !          2748:     style = gtk_style_copy (GTK_WIDGET (lab_version)->style);
        !          2749:     pango_font_description_free (style->font_desc);
        !          2750:     style->font_desc = pango_font_description_from_string ("Sans 24");
        !          2751:     gtk_widget_set_style (lab_version, style);
        !          2752: 
        !          2753:     add_centered_to_vbox (dvbox, lab_version, 0);
        !          2754:     add_centered_to_vbox (dvbox, lab_info, 0);
        !          2755:     gtk_widget_show (lab_version);
        !          2756:     if (currprefs.start_gui == 1)
        !          2757:        gtk_widget_show (lab_info);
        !          2758: 
        !          2759:     add_empty_vbox (dvbox);
        !          2760: }
        !          2761: 
        !          2762: static void create_guidlg (void)
        !          2763: {
        !          2764:     GtkWidget *window;
        !          2765:     GtkWidget *buttonbox, *vbox, *hbox;
        !          2766:     GtkWidget *thing;
        !          2767:     unsigned int i;
        !          2768:     int argc = 1;
        !          2769:     char *a[] = {"UAE"};
        !          2770:     char **argv = a;
        !          2771:     static const struct _pages {
        !          2772:        const char *title;
        !          2773:        void (*createfunc)(GtkWidget *);
        !          2774:     } pages[] = {
        !          2775:        /* ??? If this isn't the first page, there are errors in draw_led.  */
        !          2776:        { "Floppies", make_floppy_disks },
        !          2777:        { "ROM", make_rom_widgets },
        !          2778:        { "RAM", make_ram_widgets },
        !          2779:        { "CPU", make_cpu_widgets },
        !          2780:        { "Graphics", make_gfx_widgets },
        !          2781:        { "Chipset", make_chipset_widgets },
        !          2782:        { "Sound", make_sound_widgets },
        !          2783:        { "Input devices", make_joy_widgets },
        !          2784:        { "Harddisks", make_hd_widgets },
        !          2785:        { "Presets", make_presets },
        !          2786:        { "About", make_about_widgets }
        !          2787:     };
        !          2788: 
        !          2789:     gtk_init (&argc, &argv);
        !          2790:     gtk_rc_parse ("uaegtkrc");
        !          2791: 
        !          2792:     gui_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        !          2793:     gtk_window_set_title (GTK_WINDOW (gui_window), "UAE control");
        !          2794: 
        !          2795:     gtk_signal_connect (GTK_OBJECT (gui_window), "delete_event",
        !          2796:                        GTK_SIGNAL_FUNC (gui_delete_event), NULL);
        !          2797: 
        !          2798:     vbox = gtk_vbox_new (FALSE, 4);
        !          2799:     gtk_container_add (GTK_CONTAINER (gui_window), vbox);
        !          2800:     gtk_container_set_border_width (GTK_CONTAINER (gui_window), 10);
        !          2801: 
        !          2802:     /* First line - buttons and power LED */
        !          2803:     hbox = gtk_hbox_new (FALSE, 10);
        !          2804:     gtk_widget_show (hbox);
        !          2805:     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
        !          2806: 
        !          2807:     /* The buttons */
        !          2808:     buttonbox = gtk_hbox_new (TRUE, 4);
        !          2809:     gtk_widget_show (buttonbox);
        !          2810:     gtk_box_pack_start (GTK_BOX (hbox), buttonbox, TRUE, TRUE, 0);
        !          2811:     make_button ("Reset", buttonbox, did_reset);
        !          2812:     make_button ("Debug", buttonbox, did_debug);
        !          2813:     make_button ("Quit", buttonbox, did_quit);
        !          2814:     make_button ("Save config", buttonbox, save_config);
        !          2815:     pause_uae_widget = make_buttons ("Pause", buttonbox, pause_uae, gtk_toggle_button_new_with_label);
        !          2816: 
        !          2817:     /* The LED */
        !          2818:     thing = make_led (0);
        !          2819:     thing = make_labelled_widget ("Power:", thing, FALSE);
        !          2820:     gtk_widget_show (thing);
        !          2821:     gtk_box_pack_start (GTK_BOX (hbox), thing, FALSE, TRUE, 0);
        !          2822: 
        !          2823:     /* More buttons */
        !          2824:     buttonbox = gtk_hbox_new (TRUE, 4);
        !          2825:     gtk_widget_show (buttonbox);
        !          2826:     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, TRUE, TRUE, 0);
        !          2827:     snap_save_widget = make_button ("Save state", buttonbox, did_savestate);
        !          2828:     snap_load_widget = make_button ("Load state", buttonbox, did_loadstate);
        !          2829: 
        !          2830:     /* Place a separator below those buttons.  */
        !          2831:     thing = gtk_hseparator_new ();
        !          2832:     gtk_box_pack_start (GTK_BOX (vbox), thing, FALSE, TRUE, 0);
        !          2833:     gtk_widget_show (thing);
        !          2834: 
        !          2835:     /* Now the notebook */
        !          2836:     notebook = gtk_notebook_new ();
        !          2837:     gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
        !          2838:     gtk_widget_show (notebook);
        !          2839: 
        !          2840:     for (i = 0; i < sizeof pages / sizeof (struct _pages); i++) {
        !          2841:        thing = gtk_vbox_new (FALSE, 4);
        !          2842:        gtk_widget_show (thing);
        !          2843:        gtk_container_set_border_width (GTK_CONTAINER (thing), 10);
        !          2844:        pages[i].createfunc (thing);
        !          2845:        gtk_notebook_append_page (GTK_NOTEBOOK (notebook), thing, gtk_label_new (pages[i].title));
        !          2846:     }
        !          2847: 
        !          2848:     /* Put "about" screen first.  */
        !          2849:     gtk_notebook_set_page (GTK_NOTEBOOK (notebook), i - 1);
        !          2850:     enable_disk_buttons (1);
        !          2851: 
        !          2852:     gtk_widget_show (vbox);
        !          2853: 
        !          2854:     gtk_timeout_add (1000, (GtkFunction)my_idle, 0);
        !          2855: }
        !          2856: 
        !          2857: static void *gtk_gui_thread (void *dummy)
        !          2858: {
        !          2859:     gui_available = 1;
        !          2860:     gtk_main ();
        !          2861: 
        !          2862:     gui_available = 0;
        !          2863:     uae_sem_post (&gui_quit_sem);
        !          2864:     return 0;
        !          2865: }
        !          2866: 
        !          2867: void gui_fps (int x)
        !          2868: {
        !          2869: }
        !          2870: 
        !          2871: void gui_display (int shortcut)
        !          2872: {
        !          2873:     if (shortcut == -1 && !gui_available) {
        !          2874:        gui_init (0);
        !          2875:     }
        !          2876: }
        !          2877: 
        !          2878: void gui_led (int num, int on)
        !          2879: {
        !          2880:     if (no_gui)
        !          2881:        return;
        !          2882: 
        !          2883: /*    if (num == 0)
        !          2884:        return;
        !          2885:     printf("LED %d %d\n", num, on);
        !          2886:     write_comm_pipe_int (&to_gui_pipe, 1, 0);
        !          2887:     write_comm_pipe_int (&to_gui_pipe, num == 0 ? 4 : num - 1, 0);
        !          2888:     write_comm_pipe_int (&to_gui_pipe, on, 1);
        !          2889:     printf("#LED %d %d\n", num, on);*/
        !          2890: }
        !          2891: 
        !          2892: void gui_filename (int num, const char *name)
        !          2893: {
        !          2894:     if (no_gui)
        !          2895:        return;
        !          2896: 
        !          2897:     write_comm_pipe_int (&to_gui_pipe, GUICMD_DISKCHANGE, 0);
        !          2898:     write_comm_pipe_int (&to_gui_pipe, num, 1);
        !          2899: 
        !          2900: /*    gui_update ();*/
        !          2901: }
        !          2902: 
        !          2903: void gui_handle_events (void)
        !          2904: {
        !          2905:     int pause_uae = FALSE;
        !          2906: 
        !          2907:     if (no_gui)
        !          2908:        return;
        !          2909: 
        !          2910:     do {
        !          2911:        while (pause_uae || comm_pipe_has_data (&from_gui_pipe)) {
        !          2912:            int cmd = read_comm_pipe_int_blocking (&from_gui_pipe);
        !          2913:            int n;
        !          2914:            switch (cmd) {
        !          2915:            case 0:
        !          2916:                n = read_comm_pipe_int_blocking (&from_gui_pipe);
        !          2917:                changed_prefs.df[n][0] = '\0';
        !          2918:                break;
        !          2919:            case 1:
        !          2920:                n = read_comm_pipe_int_blocking (&from_gui_pipe);
        !          2921:                uae_sem_wait (&gui_sem);
        !          2922:                strncpy (changed_prefs.df[n], new_disk_string[n], 255);
        !          2923:                free (new_disk_string[n]);
        !          2924:                new_disk_string[n] = 0;
        !          2925:                changed_prefs.df[n][255] = '\0';
        !          2926:                uae_sem_post (&gui_sem);
        !          2927:                break;
        !          2928:            case 2:
        !          2929:                uae_reset (1);
        !          2930:                end_pause_uae ();
        !          2931:                break;
        !          2932:            case 3:
        !          2933:                activate_debugger ();
        !          2934:                end_pause_uae ();
        !          2935:                break;
        !          2936:            case 4:
        !          2937:                uae_quit ();
        !          2938:                end_pause_uae ();
        !          2939:                break;
        !          2940:            case 5:
        !          2941:                pause_uae = TRUE;
        !          2942:                break;
        !          2943:            case 6:
        !          2944:                pause_uae = FALSE;
        !          2945:                break;
        !          2946:            case 7:
        !          2947:                printf ("STATESAVE\n");
        !          2948:                savestate_state = read_comm_pipe_int_blocking (&from_gui_pipe);
        !          2949:                uae_sem_wait (&gui_sem);
        !          2950:                savestate_filename = gui_snapname;
        !          2951:                uae_sem_post (&gui_sem);
        !          2952:                break;
        !          2953:            case 8:
        !          2954:                uae_sem_wait (&gui_sem);
        !          2955:                strncpy (changed_prefs.romfile, gui_romname, 255);
        !          2956:                changed_prefs.romfile[255] = '\0';
        !          2957:                free (gui_romname);
        !          2958:                uae_sem_post (&gui_sem);
        !          2959:                break;
        !          2960:            case 9:
        !          2961:                uae_sem_wait (&gui_sem);
        !          2962:                strncpy (changed_prefs.keyfile, gui_keyname, 255);
        !          2963:                changed_prefs.keyfile[255] = '\0';
        !          2964:                free (gui_keyname);
        !          2965:                uae_sem_post (&gui_sem);
        !          2966:                break;
        !          2967:            case 10:
        !          2968:                uae_sem_wait (&gui_sem);
        !          2969:                strncpy (changed_prefs.path_rom, gui_romname, 255);
        !          2970:                changed_prefs.path_rom[255] = '\0';
        !          2971:                free (gui_romname);
        !          2972:                uae_sem_post (&gui_sem);
        !          2973:                break;
        !          2974:            case 11:
        !          2975:                uae_sem_wait (&gui_sem);
        !          2976:                changed_prefs.gfx_w = gfx_w;
        !          2977:                changed_prefs.gfx_f = gfx_f;
        !          2978:                uae_sem_post (&gui_sem);
        !          2979:                break;
        !          2980:            }
        !          2981:        }
        !          2982:     } while (pause_uae);
        !          2983: }
        !          2984: 
        !          2985: void gui_update_gfx (void)
        !          2986: {
        !          2987:     if (no_gui)
        !          2988:        return;
        !          2989: 
        !          2990:     write_comm_pipe_int (&to_gui_pipe, GUICMD_FULLSCREEN, 1);
        !          2991: }
        !          2992: 
        !          2993: int gui_init (int at_start)
        !          2994: {
        !          2995:     uae_thread_id tid;
        !          2996: 
        !          2997:     if (gui_available)
        !          2998:        return 0;
        !          2999: 
        !          3000:     if (at_start) {
        !          3001:        init_comm_pipe (&to_gui_pipe, 20, 1);
        !          3002:        init_comm_pipe (&from_gui_pipe, 20, 1);
        !          3003:        uae_sem_init (&gui_sem, 0, 1);
        !          3004:        uae_sem_init (&gui_init_sem, 0, 0);
        !          3005:        uae_sem_init (&gui_quit_sem, 0, 0);
        !          3006:     }
        !          3007: 
        !          3008:     create_guidlg ();
        !          3009:     if (at_start)
        !          3010:        uae_start_thread (gtk_gui_thread, NULL, &tid);
        !          3011: 
        !          3012:     gui_update ();
        !          3013: 
        !          3014:     if (at_start && currprefs.start_gui == 1) {
        !          3015:        write_comm_pipe_int (&to_gui_pipe, GUICMD_PAUSE, 1);
        !          3016:        write_comm_pipe_int (&from_gui_pipe, 5, 1);
        !          3017:        /* Handle events until Pause is unchecked.  */
        !          3018:        gui_handle_events ();
        !          3019:        /* Quit requested?  */
        !          3020:        if (quit_program == -1) {
        !          3021:            gui_exit ();
        !          3022:            return -2;
        !          3023:        }
        !          3024:     }
        !          3025: 
        !          3026:     return 1;
        !          3027: }
        !          3028: 
        !          3029: int gui_update (void)
        !          3030: {
        !          3031:     if (!gui_available)
        !          3032:        return 0;
        !          3033: 
        !          3034:     write_comm_pipe_int (&to_gui_pipe, GUICMD_UPDATE, 1);
        !          3035:     uae_sem_wait (&gui_init_sem);
        !          3036:     return 0;
        !          3037: }
        !          3038: 
        !          3039: void gui_romlist_changed (void)
        !          3040: {
        !          3041:     if (!gui_available)
        !          3042:        return;
        !          3043: 
        !          3044:     write_comm_pipe_int (&to_gui_pipe, GUICMD_NEW_ROMLIST, 1);
        !          3045:     return;
        !          3046: }
        !          3047: 
        !          3048: void gui_exit (void)
        !          3049: {
        !          3050:     if (!gui_available)
        !          3051:        return;
        !          3052: 
        !          3053:     quit_gui = 1;
        !          3054:     uae_sem_wait (&gui_quit_sem);
        !          3055: }
        !          3056: 
        !          3057: void gui_lock (void)
        !          3058: {
        !          3059:     if (!gui_available)
        !          3060:        return;
        !          3061:     uae_sem_wait (&gui_sem);
        !          3062: }
        !          3063: 
        !          3064: void gui_unlock (void)
        !          3065: {
        !          3066:     if (!gui_available)
        !          3067:        return;
        !          3068: 
        !          3069:     uae_sem_post (&gui_sem);
        !          3070: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.