/* options.c: options dialog boxes
   Copyright (c) 2001-2013 Philip Kendall

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

   Author contact information:

   E-mail: philip-fuse@shadowmagic.org.uk

*/

/* This file is autogenerated from options.dat by options.pl.
   Do not edit unless you know what you're doing! */

#include <config.h>

#ifdef UI_GTK                /* Use this file if we're using GTK+ */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>

#include "compat.h"
#include "display.h"
#include "fuse.h"
#include "options.h"
#include "options_internals.h"
#include "periph.h"
#include "settings.h"
#include "ui/gtk/gtkcompat.h"
#include "ui/gtk/gtkinternals.h"
#include "utils.h"

static int
option_enumerate_combo( const char * const *options, char *value, guint count,
                        int def )
{
  guint i;
  if( value != NULL ) {
    for( i = 0; i < count; i++) {
      if( !strcmp( value, options[ i ] ) )
        return i;
    }
  }
  return def;
}

static void menu_options_general_done( GtkWidget *widget,
					  gpointer user_data );

void
menu_options_general( GtkWidget *widget GCC_UNUSED,
			 gpointer data GCC_UNUSED )
{
  GtkWidget *content_area;
  menu_options_general_t dialog;

  /* Firstly, stop emulation */
  fuse_emulation_pause();

  /* Create the necessary widgets */
  dialog.dialog = gtkstock_dialog_new( "Fuse - General Options", NULL );
  content_area = gtk_dialog_get_content_area( GTK_DIALOG( dialog.dialog ) );

  /* Create the various widgets */
  {
    GtkWidget *frame = gtk_frame_new( "Emulation speed" );
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *text = gtk_label_new( "%" );
    gchar buffer[80];

    gtk_box_pack_start( GTK_BOX( content_area ), frame, TRUE, TRUE, 0 );

    gtk_container_set_border_width( GTK_CONTAINER( hbox ), 4 );
    gtk_container_add( GTK_CONTAINER( frame ), hbox );

    dialog.emulation_speed = gtk_entry_new();
    gtk_entry_set_max_length( GTK_ENTRY( dialog.emulation_speed ),
                              5 );
    snprintf( buffer, 80, "%d", settings_current.emulation_speed );
    gtk_entry_set_text( GTK_ENTRY( dialog.emulation_speed ), buffer );

    gtk_box_pack_start( GTK_BOX( hbox ), dialog.emulation_speed, TRUE, TRUE, 0 );

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
  }

  {
    GtkWidget *frame = gtk_frame_new( "Frame rate 1:n" );
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *text = gtk_label_new( "frames" );
    gchar buffer[80];

    gtk_box_pack_start( GTK_BOX( content_area ), frame, TRUE, TRUE, 0 );

    gtk_container_set_border_width( GTK_CONTAINER( hbox ), 4 );
    gtk_container_add( GTK_CONTAINER( frame ), hbox );

    dialog.frame_rate = gtk_entry_new();
    gtk_entry_set_max_length( GTK_ENTRY( dialog.frame_rate ),
                              1 );
    snprintf( buffer, 80, "%d", settings_current.frame_rate );
    gtk_entry_set_text( GTK_ENTRY( dialog.frame_rate ), buffer );

    gtk_box_pack_start( GTK_BOX( hbox ), dialog.frame_rate, TRUE, TRUE, 0 );

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
  }

  dialog.issue2 =
    gtk_check_button_new_with_label( "Issue 2 keyboard" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.issue2 ),
                                settings_current.issue2 );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.issue2 );

  dialog.recreated_spectrum =
    gtk_check_button_new_with_label( "Recreated ZX Spectrum" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.recreated_spectrum ),
                                settings_current.recreated_spectrum );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.recreated_spectrum );

  dialog.keyboard_arrows_shifted =
    gtk_check_button_new_with_label( "Use shift with arrow keys" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.keyboard_arrows_shifted ),
                                settings_current.keyboard_arrows_shifted );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.keyboard_arrows_shifted );

  dialog.writable_roms =
    gtk_check_button_new_with_label( "Allow writes to ROM" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.writable_roms ),
                                settings_current.writable_roms );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.writable_roms );

  dialog.late_timings =
    gtk_check_button_new_with_label( "Late timings" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.late_timings ),
                                settings_current.late_timings );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.late_timings );

  dialog.z80_is_cmos =
    gtk_check_button_new_with_label( "Z80 is CMOS" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.z80_is_cmos ),
                                settings_current.z80_is_cmos );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.z80_is_cmos );

  dialog.rs232_handshake =
    gtk_check_button_new_with_label( "RS-232 handshake" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.rs232_handshake ),
                                settings_current.rs232_handshake );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.rs232_handshake );

  dialog.bw_tv =
    gtk_check_button_new_with_label( "Black and white TV" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.bw_tv ),
                                settings_current.bw_tv );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.bw_tv );

  dialog.pal_tv2x =
    gtk_check_button_new_with_label( "PAL-TV use TV2x effect" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.pal_tv2x ),
                                settings_current.pal_tv2x );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.pal_tv2x );

  dialog.statusbar =
    gtk_check_button_new_with_label( "Show statusbar" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.statusbar ),
                                settings_current.statusbar );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.statusbar );

  dialog.joy_prompt =
    gtk_check_button_new_with_label( "Snap joystick prompt" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.joy_prompt ),
                                settings_current.joy_prompt );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.joy_prompt );

  dialog.confirm_actions =
    gtk_check_button_new_with_label( "Confirm actions" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.confirm_actions ),
                                settings_current.confirm_actions );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.confirm_actions );

  dialog.autosave_settings =
    gtk_check_button_new_with_label( "Auto-save settings" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.autosave_settings ),
                                settings_current.autosave_settings );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.autosave_settings );

  /* Create the OK and Cancel buttons */
  gtkstock_create_ok_cancel( dialog.dialog, NULL,
                             G_CALLBACK( menu_options_general_done ),
                             (gpointer) &dialog, NULL, DEFAULT_DESTROY );

  /* Display the window */
  gtk_widget_show_all( dialog.dialog );

  /* Process events until the window is done with */
  gtk_main();

  /* And then carry on with emulation again */
  fuse_emulation_unpause();
}

static void
menu_options_general_done( GtkWidget *widget GCC_UNUSED,
			      gpointer user_data )
{
  menu_options_general_t *ptr = user_data;

  settings_current.emulation_speed =
    atoi( gtk_entry_get_text( GTK_ENTRY( ptr->emulation_speed ) ) );

  settings_current.frame_rate =
    atoi( gtk_entry_get_text( GTK_ENTRY( ptr->frame_rate ) ) );

  settings_current.issue2 =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->issue2 ) );

  settings_current.recreated_spectrum =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->recreated_spectrum ) );

  settings_current.keyboard_arrows_shifted =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->keyboard_arrows_shifted ) );

  settings_current.writable_roms =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->writable_roms ) );

  settings_current.late_timings =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->late_timings ) );

  settings_current.z80_is_cmos =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->z80_is_cmos ) );

  settings_current.rs232_handshake =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->rs232_handshake ) );

  settings_current.bw_tv =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->bw_tv ) );

  settings_current.pal_tv2x =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->pal_tv2x ) );

  settings_current.statusbar =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->statusbar ) );

  settings_current.joy_prompt =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->joy_prompt ) );

  settings_current.confirm_actions =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->confirm_actions ) );

  settings_current.autosave_settings =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->autosave_settings ) );

  gtk_widget_destroy( ptr->dialog );

  gtkstatusbar_set_visibility( settings_current.statusbar );
  display_refresh_all();

  gtk_main_quit();
}

static void menu_options_media_done( GtkWidget *widget,
					  gpointer user_data );

void
menu_options_media( GtkWidget *widget GCC_UNUSED,
			 gpointer data GCC_UNUSED )
{
  GtkWidget *content_area;
  menu_options_media_t dialog;

  /* Firstly, stop emulation */
  fuse_emulation_pause();

  /* Create the necessary widgets */
  dialog.dialog = gtkstock_dialog_new( "Fuse - Media Options", NULL );
  content_area = gtk_dialog_get_content_area( GTK_DIALOG( dialog.dialog ) );

  /* Create the various widgets */
  dialog.auto_load =
    gtk_check_button_new_with_label( "Auto-load media" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.auto_load ),
                                settings_current.auto_load );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.auto_load );

  dialog.detect_loader =
    gtk_check_button_new_with_label( "Detect loaders" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.detect_loader ),
                                settings_current.detect_loader );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.detect_loader );

  dialog.fastload =
    gtk_check_button_new_with_label( "Fastloading" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.fastload ),
                                settings_current.fastload );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.fastload );

  dialog.tape_traps =
    gtk_check_button_new_with_label( "Use tape traps" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.tape_traps ),
                                settings_current.tape_traps );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.tape_traps );

  dialog.accelerate_loader =
    gtk_check_button_new_with_label( "Accelerate loaders" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.accelerate_loader ),
                                settings_current.accelerate_loader );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.accelerate_loader );

  dialog.slt_traps =
    gtk_check_button_new_with_label( "Use .slt traps" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.slt_traps ),
                                settings_current.slt_traps );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.slt_traps );

  {
    GtkWidget *frame = gtk_frame_new( "MDR cartridge len" );
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *text = gtk_label_new( "blocks" );
    gchar buffer[80];

    gtk_box_pack_start( GTK_BOX( content_area ), frame, TRUE, TRUE, 0 );

    gtk_container_set_border_width( GTK_CONTAINER( hbox ), 4 );
    gtk_container_add( GTK_CONTAINER( frame ), hbox );

    dialog.mdr_len = gtk_entry_new();
    gtk_entry_set_max_length( GTK_ENTRY( dialog.mdr_len ),
                              3 );
    snprintf( buffer, 80, "%d", settings_current.mdr_len );
    gtk_entry_set_text( GTK_ENTRY( dialog.mdr_len ), buffer );

    gtk_box_pack_start( GTK_BOX( hbox ), dialog.mdr_len, TRUE, TRUE, 0 );

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
  }

  dialog.mdr_random_len =
    gtk_check_button_new_with_label( "Random length MDR cartridge" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.mdr_random_len ),
                                settings_current.mdr_random_len );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.mdr_random_len );

  /* Create the OK and Cancel buttons */
  gtkstock_create_ok_cancel( dialog.dialog, NULL,
                             G_CALLBACK( menu_options_media_done ),
                             (gpointer) &dialog, NULL, DEFAULT_DESTROY );

  /* Display the window */
  gtk_widget_show_all( dialog.dialog );

  /* Process events until the window is done with */
  gtk_main();

  /* And then carry on with emulation again */
  fuse_emulation_unpause();
}

static void
menu_options_media_done( GtkWidget *widget GCC_UNUSED,
			      gpointer user_data )
{
  menu_options_media_t *ptr = user_data;

  settings_current.auto_load =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->auto_load ) );

  settings_current.detect_loader =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->detect_loader ) );

  settings_current.fastload =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->fastload ) );

  settings_current.tape_traps =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->tape_traps ) );

  settings_current.accelerate_loader =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->accelerate_loader ) );

  settings_current.slt_traps =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->slt_traps ) );

  settings_current.mdr_len =
    atoi( gtk_entry_get_text( GTK_ENTRY( ptr->mdr_len ) ) );

  settings_current.mdr_random_len =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->mdr_random_len ) );

  gtk_widget_destroy( ptr->dialog );

  gtkstatusbar_set_visibility( settings_current.statusbar );
  display_refresh_all();

  gtk_main_quit();
}

static void menu_options_peripherals_general_done( GtkWidget *widget,
					  gpointer user_data );

void
menu_options_peripherals_general( GtkWidget *widget GCC_UNUSED,
			 gpointer data GCC_UNUSED )
{
  GtkWidget *content_area;
  menu_options_peripherals_general_t dialog;

  /* Firstly, stop emulation */
  fuse_emulation_pause();

  /* Create the necessary widgets */
  dialog.dialog = gtkstock_dialog_new( "Fuse - General Peripheral Options", NULL );
  content_area = gtk_dialog_get_content_area( GTK_DIALOG( dialog.dialog ) );

  /* Create the various widgets */
  dialog.joy_kempston =
    gtk_check_button_new_with_label( "Kempston joystick" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.joy_kempston ),
                                settings_current.joy_kempston );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.joy_kempston );

  dialog.kempston_mouse =
    gtk_check_button_new_with_label( "Kempston mouse" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.kempston_mouse ),
                                settings_current.kempston_mouse );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.kempston_mouse );

  dialog.mouse_swap_buttons =
    gtk_check_button_new_with_label( "Swap mouse buttons" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.mouse_swap_buttons ),
                                settings_current.mouse_swap_buttons );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.mouse_swap_buttons );

  dialog.fuller =
    gtk_check_button_new_with_label( "Fuller Box" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.fuller ),
                                settings_current.fuller );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.fuller );

  dialog.melodik =
    gtk_check_button_new_with_label( "Melodik" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.melodik ),
                                settings_current.melodik );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.melodik );

  dialog.interface1 =
    gtk_check_button_new_with_label( "Interface 1" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.interface1 ),
                                settings_current.interface1 );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.interface1 );

  dialog.interface2 =
    gtk_check_button_new_with_label( "Interface 2" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.interface2 ),
                                settings_current.interface2 );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.interface2 );

  dialog.multiface1 =
    gtk_check_button_new_with_label( "Multiface One" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.multiface1 ),
                                settings_current.multiface1 );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.multiface1 );

  dialog.multiface128 =
    gtk_check_button_new_with_label( "Multiface 128" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.multiface128 ),
                                settings_current.multiface128 );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.multiface128 );

  dialog.multiface3 =
    gtk_check_button_new_with_label( "Multiface 3" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.multiface3 ),
                                settings_current.multiface3 );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.multiface3 );

  dialog.multiface1_stealth =
    gtk_check_button_new_with_label( "Stealth Multiface One" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.multiface1_stealth ),
                                settings_current.multiface1_stealth );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.multiface1_stealth );

  dialog.printer =
    gtk_check_button_new_with_label( "Emulate printers" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.printer ),
                                settings_current.printer );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.printer );

  dialog.zxprinter =
    gtk_check_button_new_with_label( "ZX Printer" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.zxprinter ),
                                settings_current.zxprinter );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.zxprinter );

  dialog.speccyboot =
    gtk_check_button_new_with_label( "SpeccyBoot interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.speccyboot ),
                                settings_current.speccyboot );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.speccyboot );

  dialog.specdrum =
    gtk_check_button_new_with_label( "SpecDrum interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.specdrum ),
                                settings_current.specdrum );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.specdrum );

  dialog.spectranet =
    gtk_check_button_new_with_label( "Spectranet" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.spectranet ),
                                settings_current.spectranet );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.spectranet );

  dialog.spectranet_disable =
    gtk_check_button_new_with_label( "Spectranet disable" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.spectranet_disable ),
                                settings_current.spectranet_disable );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.spectranet_disable );

  dialog.usource =
    gtk_check_button_new_with_label( "uSource" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.usource ),
                                settings_current.usource );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.usource );

  dialog.covox =
    gtk_check_button_new_with_label( "Covox interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.covox ),
                                settings_current.covox );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.covox );

  /* Create the OK and Cancel buttons */
  gtkstock_create_ok_cancel( dialog.dialog, NULL,
                             G_CALLBACK( menu_options_peripherals_general_done ),
                             (gpointer) &dialog, NULL, DEFAULT_DESTROY );

  /* Display the window */
  gtk_widget_show_all( dialog.dialog );

  /* Process events until the window is done with */
  gtk_main();

  /* And then carry on with emulation again */
  fuse_emulation_unpause();
}

static void
menu_options_peripherals_general_done( GtkWidget *widget GCC_UNUSED,
			      gpointer user_data )
{
  menu_options_peripherals_general_t *ptr = user_data;

  /* Get a copy of current settings */
  settings_info original_settings;
  memset( &original_settings, 0, sizeof( settings_info ) );
  settings_copy( &original_settings, &settings_current );

  settings_current.joy_kempston =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->joy_kempston ) );

  settings_current.kempston_mouse =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->kempston_mouse ) );

  settings_current.mouse_swap_buttons =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->mouse_swap_buttons ) );

  settings_current.fuller =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->fuller ) );

  settings_current.melodik =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->melodik ) );

  settings_current.interface1 =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->interface1 ) );

  settings_current.interface2 =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->interface2 ) );

  settings_current.multiface1 =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->multiface1 ) );

  settings_current.multiface128 =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->multiface128 ) );

  settings_current.multiface3 =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->multiface3 ) );

  settings_current.multiface1_stealth =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->multiface1_stealth ) );

  settings_current.printer =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->printer ) );

  settings_current.zxprinter =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->zxprinter ) );

  settings_current.speccyboot =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->speccyboot ) );

  settings_current.specdrum =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->specdrum ) );

  settings_current.spectranet =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->spectranet ) );

  settings_current.spectranet_disable =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->spectranet_disable ) );

  settings_current.usource =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->usource ) );

  settings_current.covox =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->covox ) );

  int needs_hard_reset = periph_postcheck();

  /* Confirm reset */
  if( needs_hard_reset && !gtkui_confirm("Some options need to reset the machine. Reset?" ) ) {

    /* Cancel new settings */
    settings_copy( &settings_current, &original_settings );
    settings_free( &original_settings );
    return;
  }

  settings_free( &original_settings );

  gtk_widget_destroy( ptr->dialog );

  periph_posthook();

  gtkstatusbar_set_visibility( settings_current.statusbar );
  display_refresh_all();

  gtk_main_quit();
}

static void menu_options_peripherals_disk_done( GtkWidget *widget,
					  gpointer user_data );

void
menu_options_peripherals_disk( GtkWidget *widget GCC_UNUSED,
			 gpointer data GCC_UNUSED )
{
  GtkWidget *content_area;
  menu_options_peripherals_disk_t dialog;

  /* Firstly, stop emulation */
  fuse_emulation_pause();

  /* Create the necessary widgets */
  dialog.dialog = gtkstock_dialog_new( "Fuse - Disk Peripheral Options", NULL );
  content_area = gtk_dialog_get_content_area( GTK_DIALOG( dialog.dialog ) );

  /* Create the various widgets */
  dialog.simpleide_active =
    gtk_check_button_new_with_label( "Simple 8-bit IDE" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.simpleide_active ),
                                settings_current.simpleide_active );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.simpleide_active );

  dialog.zxatasp_active =
    gtk_check_button_new_with_label( "ZXATASP interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.zxatasp_active ),
                                settings_current.zxatasp_active );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.zxatasp_active );

  dialog.zxatasp_upload =
    gtk_check_button_new_with_label( "ZXATASP upload" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.zxatasp_upload ),
                                settings_current.zxatasp_upload );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.zxatasp_upload );

  dialog.zxatasp_wp =
    gtk_check_button_new_with_label( "ZXATASP write protect" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.zxatasp_wp ),
                                settings_current.zxatasp_wp );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.zxatasp_wp );

  dialog.zxcf_active =
    gtk_check_button_new_with_label( "ZXCF interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.zxcf_active ),
                                settings_current.zxcf_active );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.zxcf_active );

  dialog.zxcf_upload =
    gtk_check_button_new_with_label( "ZXCF upload" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.zxcf_upload ),
                                settings_current.zxcf_upload );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.zxcf_upload );

  dialog.divide_enabled =
    gtk_check_button_new_with_label( "DivIDE interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.divide_enabled ),
                                settings_current.divide_enabled );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.divide_enabled );

  dialog.divide_wp =
    gtk_check_button_new_with_label( "DivIDE write protect" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.divide_wp ),
                                settings_current.divide_wp );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.divide_wp );

  dialog.plusd =
    gtk_check_button_new_with_label( "+D interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.plusd ),
                                settings_current.plusd );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.plusd );

  dialog.didaktik80 =
    gtk_check_button_new_with_label( "Didaktik 80 interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.didaktik80 ),
                                settings_current.didaktik80 );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.didaktik80 );

  dialog.disciple =
    gtk_check_button_new_with_label( "DISCiPLE interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.disciple ),
                                settings_current.disciple );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.disciple );

  dialog.beta128 =
    gtk_check_button_new_with_label( "Beta 128 interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.beta128 ),
                                settings_current.beta128 );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.beta128 );

  dialog.beta128_48boot =
    gtk_check_button_new_with_label( "Beta 128 auto-boot in 48K machines" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.beta128_48boot ),
                                settings_current.beta128_48boot );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.beta128_48boot );

  dialog.opus =
    gtk_check_button_new_with_label( "Opus Discovery interface" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.opus ),
                                settings_current.opus );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.opus );

  /* Create the OK and Cancel buttons */
  gtkstock_create_ok_cancel( dialog.dialog, NULL,
                             G_CALLBACK( menu_options_peripherals_disk_done ),
                             (gpointer) &dialog, NULL, DEFAULT_DESTROY );

  /* Display the window */
  gtk_widget_show_all( dialog.dialog );

  /* Process events until the window is done with */
  gtk_main();

  /* And then carry on with emulation again */
  fuse_emulation_unpause();
}

static void
menu_options_peripherals_disk_done( GtkWidget *widget GCC_UNUSED,
			      gpointer user_data )
{
  menu_options_peripherals_disk_t *ptr = user_data;

  /* Get a copy of current settings */
  settings_info original_settings;
  memset( &original_settings, 0, sizeof( settings_info ) );
  settings_copy( &original_settings, &settings_current );

  settings_current.simpleide_active =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->simpleide_active ) );

  settings_current.zxatasp_active =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->zxatasp_active ) );

  settings_current.zxatasp_upload =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->zxatasp_upload ) );

  settings_current.zxatasp_wp =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->zxatasp_wp ) );

  settings_current.zxcf_active =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->zxcf_active ) );

  settings_current.zxcf_upload =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->zxcf_upload ) );

  settings_current.divide_enabled =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->divide_enabled ) );

  settings_current.divide_wp =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->divide_wp ) );

  settings_current.plusd =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->plusd ) );

  settings_current.didaktik80 =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->didaktik80 ) );

  settings_current.disciple =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->disciple ) );

  settings_current.beta128 =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->beta128 ) );

  settings_current.beta128_48boot =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->beta128_48boot ) );

  settings_current.opus =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->opus ) );

  int needs_hard_reset = periph_postcheck();

  /* Confirm reset */
  if( needs_hard_reset && !gtkui_confirm("Some options need to reset the machine. Reset?" ) ) {

    /* Cancel new settings */
    settings_copy( &settings_current, &original_settings );
    settings_free( &original_settings );
    return;
  }

  settings_free( &original_settings );

  gtk_widget_destroy( ptr->dialog );

  periph_posthook();

  gtkstatusbar_set_visibility( settings_current.statusbar );
  display_refresh_all();

  gtk_main_quit();
}

static void menu_options_rzx_done( GtkWidget *widget,
					  gpointer user_data );

void
menu_options_rzx( GtkWidget *widget GCC_UNUSED,
			 gpointer data GCC_UNUSED )
{
  GtkWidget *content_area;
  menu_options_rzx_t dialog;

  /* Firstly, stop emulation */
  fuse_emulation_pause();

  /* Create the necessary widgets */
  dialog.dialog = gtkstock_dialog_new( "Fuse - RZX Options", NULL );
  content_area = gtk_dialog_get_content_area( GTK_DIALOG( dialog.dialog ) );

  /* Create the various widgets */
  dialog.rzx_autosaves =
    gtk_check_button_new_with_label( "Create autosaves" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.rzx_autosaves ),
                                settings_current.rzx_autosaves );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.rzx_autosaves );

  dialog.rzx_compression =
    gtk_check_button_new_with_label( "Compress RZX data" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.rzx_compression ),
                                settings_current.rzx_compression );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.rzx_compression );

  dialog.competition_mode =
    gtk_check_button_new_with_label( "Competition mode" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.competition_mode ),
                                settings_current.competition_mode );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.competition_mode );

  {
    GtkWidget *frame = gtk_frame_new( "Competition code" );
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *text = gtk_label_new( "" );
    gchar buffer[80];

    gtk_box_pack_start( GTK_BOX( content_area ), frame, TRUE, TRUE, 0 );

    gtk_container_set_border_width( GTK_CONTAINER( hbox ), 4 );
    gtk_container_add( GTK_CONTAINER( frame ), hbox );

    dialog.competition_code = gtk_entry_new();
    gtk_entry_set_max_length( GTK_ENTRY( dialog.competition_code ),
                              8 );
    snprintf( buffer, 80, "%d", settings_current.competition_code );
    gtk_entry_set_text( GTK_ENTRY( dialog.competition_code ), buffer );

    gtk_box_pack_start( GTK_BOX( hbox ), dialog.competition_code, TRUE, TRUE, 0 );

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
  }

  dialog.embed_snapshot =
    gtk_check_button_new_with_label( "Always embed snapshot" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.embed_snapshot ),
                                settings_current.embed_snapshot );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.embed_snapshot );

  /* Create the OK and Cancel buttons */
  gtkstock_create_ok_cancel( dialog.dialog, NULL,
                             G_CALLBACK( menu_options_rzx_done ),
                             (gpointer) &dialog, NULL, DEFAULT_DESTROY );

  /* Display the window */
  gtk_widget_show_all( dialog.dialog );

  /* Process events until the window is done with */
  gtk_main();

  /* And then carry on with emulation again */
  fuse_emulation_unpause();
}

static void
menu_options_rzx_done( GtkWidget *widget GCC_UNUSED,
			      gpointer user_data )
{
  menu_options_rzx_t *ptr = user_data;

  settings_current.rzx_autosaves =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->rzx_autosaves ) );

  settings_current.rzx_compression =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->rzx_compression ) );

  settings_current.competition_mode =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->competition_mode ) );

  settings_current.competition_code =
    atoi( gtk_entry_get_text( GTK_ENTRY( ptr->competition_code ) ) );

  settings_current.embed_snapshot =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->embed_snapshot ) );

  gtk_widget_destroy( ptr->dialog );

  gtkstatusbar_set_visibility( settings_current.statusbar );
  display_refresh_all();

  gtk_main_quit();
}


static const char * const sound_stereo_ay_combo[] = {
  "None",
  "ACB",
  "ABC",
};

static const guint sound_stereo_ay_combo_count = 3;

int
option_enumerate_sound_stereo_ay( void )
{
  return option_enumerate_combo( sound_stereo_ay_combo,
                                 settings_current.stereo_ay,
                                 sound_stereo_ay_combo_count,
                                 0 );
}


static const char * const sound_speaker_type_combo[] = {
  "TV speaker",
  "Beeper",
  "Unfiltered",
};

static const guint sound_speaker_type_combo_count = 3;

int
option_enumerate_sound_speaker_type( void )
{
  return option_enumerate_combo( sound_speaker_type_combo,
                                 settings_current.speaker_type,
                                 sound_speaker_type_combo_count,
                                 0 );
}

static void menu_options_sound_done( GtkWidget *widget,
					  gpointer user_data );

void
menu_options_sound( GtkWidget *widget GCC_UNUSED,
			 gpointer data GCC_UNUSED )
{
  GtkWidget *content_area;
  menu_options_sound_t dialog;

  /* Firstly, stop emulation */
  fuse_emulation_pause();

  /* Create the necessary widgets */
  dialog.dialog = gtkstock_dialog_new( "Fuse - Sound Options", NULL );
  content_area = gtk_dialog_get_content_area( GTK_DIALOG( dialog.dialog ) );

  /* Create the various widgets */
  dialog.sound =
    gtk_check_button_new_with_label( "Sound enabled" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.sound ),
                                settings_current.sound );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.sound );

  dialog.sound_load =
    gtk_check_button_new_with_label( "Loading sound" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.sound_load ),
                                settings_current.sound_load );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.sound_load );

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "AY stereo separation" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < sound_stereo_ay_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), sound_stereo_ay_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );
    if( settings_current.stereo_ay != NULL ) {
      for( i = 0; i < sound_stereo_ay_combo_count; i++ ) {
        if( !strcmp( settings_current.stereo_ay, sound_stereo_ay_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.stereo_ay = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.stereo_ay, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  dialog.sound_force_8bit =
    gtk_check_button_new_with_label( "Force 8-bit" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.sound_force_8bit ),
                                settings_current.sound_force_8bit );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.sound_force_8bit );

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Speaker type" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < sound_speaker_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), sound_speaker_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );
    if( settings_current.speaker_type != NULL ) {
      for( i = 0; i < sound_speaker_type_combo_count; i++ ) {
        if( !strcmp( settings_current.speaker_type, sound_speaker_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.speaker_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.speaker_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *frame = gtk_frame_new( "AY volume" );
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *text = gtk_label_new( "%" );
    gchar buffer[80];

    gtk_box_pack_start( GTK_BOX( content_area ), frame, TRUE, TRUE, 0 );

    gtk_container_set_border_width( GTK_CONTAINER( hbox ), 4 );
    gtk_container_add( GTK_CONTAINER( frame ), hbox );

    dialog.volume_ay = gtk_entry_new();
    gtk_entry_set_max_length( GTK_ENTRY( dialog.volume_ay ),
                              3 );
    snprintf( buffer, 80, "%d", settings_current.volume_ay );
    gtk_entry_set_text( GTK_ENTRY( dialog.volume_ay ), buffer );

    gtk_box_pack_start( GTK_BOX( hbox ), dialog.volume_ay, TRUE, TRUE, 0 );

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
  }

  {
    GtkWidget *frame = gtk_frame_new( "Beeper volume" );
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *text = gtk_label_new( "%" );
    gchar buffer[80];

    gtk_box_pack_start( GTK_BOX( content_area ), frame, TRUE, TRUE, 0 );

    gtk_container_set_border_width( GTK_CONTAINER( hbox ), 4 );
    gtk_container_add( GTK_CONTAINER( frame ), hbox );

    dialog.volume_beeper = gtk_entry_new();
    gtk_entry_set_max_length( GTK_ENTRY( dialog.volume_beeper ),
                              3 );
    snprintf( buffer, 80, "%d", settings_current.volume_beeper );
    gtk_entry_set_text( GTK_ENTRY( dialog.volume_beeper ), buffer );

    gtk_box_pack_start( GTK_BOX( hbox ), dialog.volume_beeper, TRUE, TRUE, 0 );

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
  }

  {
    GtkWidget *frame = gtk_frame_new( "SpecDrum volume" );
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *text = gtk_label_new( "%" );
    gchar buffer[80];

    gtk_box_pack_start( GTK_BOX( content_area ), frame, TRUE, TRUE, 0 );

    gtk_container_set_border_width( GTK_CONTAINER( hbox ), 4 );
    gtk_container_add( GTK_CONTAINER( frame ), hbox );

    dialog.volume_specdrum = gtk_entry_new();
    gtk_entry_set_max_length( GTK_ENTRY( dialog.volume_specdrum ),
                              3 );
    snprintf( buffer, 80, "%d", settings_current.volume_specdrum );
    gtk_entry_set_text( GTK_ENTRY( dialog.volume_specdrum ), buffer );

    gtk_box_pack_start( GTK_BOX( hbox ), dialog.volume_specdrum, TRUE, TRUE, 0 );

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
  }

  {
    GtkWidget *frame = gtk_frame_new( "Covox volume" );
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *text = gtk_label_new( "%" );
    gchar buffer[80];

    gtk_box_pack_start( GTK_BOX( content_area ), frame, TRUE, TRUE, 0 );

    gtk_container_set_border_width( GTK_CONTAINER( hbox ), 4 );
    gtk_container_add( GTK_CONTAINER( frame ), hbox );

    dialog.volume_covox = gtk_entry_new();
    gtk_entry_set_max_length( GTK_ENTRY( dialog.volume_covox ),
                              3 );
    snprintf( buffer, 80, "%d", settings_current.volume_covox );
    gtk_entry_set_text( GTK_ENTRY( dialog.volume_covox ), buffer );

    gtk_box_pack_start( GTK_BOX( hbox ), dialog.volume_covox, TRUE, TRUE, 0 );

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
  }

  /* Create the OK and Cancel buttons */
  gtkstock_create_ok_cancel( dialog.dialog, NULL,
                             G_CALLBACK( menu_options_sound_done ),
                             (gpointer) &dialog, NULL, DEFAULT_DESTROY );

  /* Display the window */
  gtk_widget_show_all( dialog.dialog );

  /* Process events until the window is done with */
  gtk_main();

  /* And then carry on with emulation again */
  fuse_emulation_unpause();
}

static void
menu_options_sound_done( GtkWidget *widget GCC_UNUSED,
			      gpointer user_data )
{
  menu_options_sound_t *ptr = user_data;

  settings_current.sound =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->sound ) );

  settings_current.sound_load =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->sound_load ) );

  libspectrum_free( settings_current.stereo_ay );
  settings_current.stereo_ay = utils_safe_strdup( sound_stereo_ay_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->stereo_ay ) ) ] );

  settings_current.sound_force_8bit =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->sound_force_8bit ) );

  libspectrum_free( settings_current.speaker_type );
  settings_current.speaker_type = utils_safe_strdup( sound_speaker_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->speaker_type ) ) ] );

  settings_current.volume_ay =
    atoi( gtk_entry_get_text( GTK_ENTRY( ptr->volume_ay ) ) );

  settings_current.volume_beeper =
    atoi( gtk_entry_get_text( GTK_ENTRY( ptr->volume_beeper ) ) );

  settings_current.volume_specdrum =
    atoi( gtk_entry_get_text( GTK_ENTRY( ptr->volume_specdrum ) ) );

  settings_current.volume_covox =
    atoi( gtk_entry_get_text( GTK_ENTRY( ptr->volume_covox ) ) );

  gtk_widget_destroy( ptr->dialog );

  gtkstatusbar_set_visibility( settings_current.statusbar );
  display_refresh_all();

  gtk_main_quit();
}


static const char * const diskoptions_drive_plus3a_type_combo[] = {
  "Single-sided 40 track",
  "Double-sided 40 track",
  "Single-sided 80 track",
  "Double-sided 80 track",
};

static const guint diskoptions_drive_plus3a_type_combo_count = 4;

int
option_enumerate_diskoptions_drive_plus3a_type( void )
{
  return option_enumerate_combo( diskoptions_drive_plus3a_type_combo,
                                 settings_current.drive_plus3a_type,
                                 diskoptions_drive_plus3a_type_combo_count,
                                 0 );
}


static const char * const diskoptions_drive_plus3b_type_combo[] = {
  "Disabled",
  "Single-sided 40 track",
  "Double-sided 40 track",
  "Single-sided 80 track",
  "Double-sided 80 track",
};

static const guint diskoptions_drive_plus3b_type_combo_count = 5;

int
option_enumerate_diskoptions_drive_plus3b_type( void )
{
  return option_enumerate_combo( diskoptions_drive_plus3b_type_combo,
                                 settings_current.drive_plus3b_type,
                                 diskoptions_drive_plus3b_type_combo_count,
                                 4 );
}

#define diskoptions_drive_beta128a_type_combo diskoptions_drive_plus3a_type_combo
#define diskoptions_drive_beta128a_type_combo_count diskoptions_drive_plus3a_type_combo_count

int
option_enumerate_diskoptions_drive_beta128a_type( void )
{
  return option_enumerate_combo( diskoptions_drive_beta128a_type_combo,
                                 settings_current.drive_beta128a_type,
                                 diskoptions_drive_beta128a_type_combo_count,
                                 3 );
}

#define diskoptions_drive_beta128b_type_combo diskoptions_drive_plus3b_type_combo
#define diskoptions_drive_beta128b_type_combo_count diskoptions_drive_plus3b_type_combo_count

int
option_enumerate_diskoptions_drive_beta128b_type( void )
{
  return option_enumerate_combo( diskoptions_drive_beta128b_type_combo,
                                 settings_current.drive_beta128b_type,
                                 diskoptions_drive_beta128b_type_combo_count,
                                 4 );
}

#define diskoptions_drive_beta128c_type_combo diskoptions_drive_plus3b_type_combo
#define diskoptions_drive_beta128c_type_combo_count diskoptions_drive_plus3b_type_combo_count

int
option_enumerate_diskoptions_drive_beta128c_type( void )
{
  return option_enumerate_combo( diskoptions_drive_beta128c_type_combo,
                                 settings_current.drive_beta128c_type,
                                 diskoptions_drive_beta128c_type_combo_count,
                                 4 );
}

#define diskoptions_drive_beta128d_type_combo diskoptions_drive_plus3b_type_combo
#define diskoptions_drive_beta128d_type_combo_count diskoptions_drive_plus3b_type_combo_count

int
option_enumerate_diskoptions_drive_beta128d_type( void )
{
  return option_enumerate_combo( diskoptions_drive_beta128d_type_combo,
                                 settings_current.drive_beta128d_type,
                                 diskoptions_drive_beta128d_type_combo_count,
                                 4 );
}

#define diskoptions_drive_plusd1_type_combo diskoptions_drive_plus3a_type_combo
#define diskoptions_drive_plusd1_type_combo_count diskoptions_drive_plus3a_type_combo_count

int
option_enumerate_diskoptions_drive_plusd1_type( void )
{
  return option_enumerate_combo( diskoptions_drive_plusd1_type_combo,
                                 settings_current.drive_plusd1_type,
                                 diskoptions_drive_plusd1_type_combo_count,
                                 3 );
}

#define diskoptions_drive_plusd2_type_combo diskoptions_drive_plus3b_type_combo
#define diskoptions_drive_plusd2_type_combo_count diskoptions_drive_plus3b_type_combo_count

int
option_enumerate_diskoptions_drive_plusd2_type( void )
{
  return option_enumerate_combo( diskoptions_drive_plusd2_type_combo,
                                 settings_current.drive_plusd2_type,
                                 diskoptions_drive_plusd2_type_combo_count,
                                 4 );
}

#define diskoptions_drive_didaktik80a_type_combo diskoptions_drive_plus3a_type_combo
#define diskoptions_drive_didaktik80a_type_combo_count diskoptions_drive_plus3a_type_combo_count

int
option_enumerate_diskoptions_drive_didaktik80a_type( void )
{
  return option_enumerate_combo( diskoptions_drive_didaktik80a_type_combo,
                                 settings_current.drive_didaktik80a_type,
                                 diskoptions_drive_didaktik80a_type_combo_count,
                                 3 );
}

#define diskoptions_drive_didaktik80b_type_combo diskoptions_drive_plus3b_type_combo
#define diskoptions_drive_didaktik80b_type_combo_count diskoptions_drive_plus3b_type_combo_count

int
option_enumerate_diskoptions_drive_didaktik80b_type( void )
{
  return option_enumerate_combo( diskoptions_drive_didaktik80b_type_combo,
                                 settings_current.drive_didaktik80b_type,
                                 diskoptions_drive_didaktik80b_type_combo_count,
                                 4 );
}

#define diskoptions_drive_disciple1_type_combo diskoptions_drive_plus3a_type_combo
#define diskoptions_drive_disciple1_type_combo_count diskoptions_drive_plus3a_type_combo_count

int
option_enumerate_diskoptions_drive_disciple1_type( void )
{
  return option_enumerate_combo( diskoptions_drive_disciple1_type_combo,
                                 settings_current.drive_disciple1_type,
                                 diskoptions_drive_disciple1_type_combo_count,
                                 3 );
}

#define diskoptions_drive_disciple2_type_combo diskoptions_drive_plus3b_type_combo
#define diskoptions_drive_disciple2_type_combo_count diskoptions_drive_plus3b_type_combo_count

int
option_enumerate_diskoptions_drive_disciple2_type( void )
{
  return option_enumerate_combo( diskoptions_drive_disciple2_type_combo,
                                 settings_current.drive_disciple2_type,
                                 diskoptions_drive_disciple2_type_combo_count,
                                 4 );
}

#define diskoptions_drive_opus1_type_combo diskoptions_drive_plus3a_type_combo
#define diskoptions_drive_opus1_type_combo_count diskoptions_drive_plus3a_type_combo_count

int
option_enumerate_diskoptions_drive_opus1_type( void )
{
  return option_enumerate_combo( diskoptions_drive_opus1_type_combo,
                                 settings_current.drive_opus1_type,
                                 diskoptions_drive_opus1_type_combo_count,
                                 0 );
}

#define diskoptions_drive_opus2_type_combo diskoptions_drive_plus3b_type_combo
#define diskoptions_drive_opus2_type_combo_count diskoptions_drive_plus3b_type_combo_count

int
option_enumerate_diskoptions_drive_opus2_type( void )
{
  return option_enumerate_combo( diskoptions_drive_opus2_type_combo,
                                 settings_current.drive_opus2_type,
                                 diskoptions_drive_opus2_type_combo_count,
                                 1 );
}


static const char * const diskoptions_disk_try_merge_combo[] = {
  "Never",
  "With single-sided drives",
  "Always",
};

static const guint diskoptions_disk_try_merge_combo_count = 3;

int
option_enumerate_diskoptions_disk_try_merge( void )
{
  return option_enumerate_combo( diskoptions_disk_try_merge_combo,
                                 settings_current.disk_try_merge,
                                 diskoptions_disk_try_merge_combo_count,
                                 1 );
}

static void menu_options_diskoptions_done( GtkWidget *widget,
					  gpointer user_data );

void
menu_options_diskoptions( GtkWidget *widget GCC_UNUSED,
			 gpointer data GCC_UNUSED )
{
  GtkWidget *content_area;
  menu_options_diskoptions_t dialog;

  /* Firstly, stop emulation */
  fuse_emulation_pause();

  /* Create the necessary widgets */
  dialog.dialog = gtkstock_dialog_new( "Fuse - Drives Setup", NULL );
  content_area = gtk_dialog_get_content_area( GTK_DIALOG( dialog.dialog ) );

  /* Create the various widgets */
  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "+3 Drive A" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_plus3a_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_plus3a_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );
    if( settings_current.drive_plus3a_type != NULL ) {
      for( i = 0; i < diskoptions_drive_plus3a_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_plus3a_type, diskoptions_drive_plus3a_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_plus3a_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_plus3a_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "+3 Drive B" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_plus3b_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_plus3b_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 4 );
    if( settings_current.drive_plus3b_type != NULL ) {
      for( i = 0; i < diskoptions_drive_plus3b_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_plus3b_type, diskoptions_drive_plus3b_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_plus3b_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_plus3b_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  dialog.plus3_detect_speedlock =
    gtk_check_button_new_with_label( "+3 Detect Speedlock" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.plus3_detect_speedlock ),
                                settings_current.plus3_detect_speedlock );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.plus3_detect_speedlock );

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Beta 128 Drive A" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_beta128a_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_beta128a_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 3 );
    if( settings_current.drive_beta128a_type != NULL ) {
      for( i = 0; i < diskoptions_drive_beta128a_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_beta128a_type, diskoptions_drive_beta128a_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_beta128a_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_beta128a_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Beta 128 Drive B" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_beta128b_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_beta128b_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 4 );
    if( settings_current.drive_beta128b_type != NULL ) {
      for( i = 0; i < diskoptions_drive_beta128b_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_beta128b_type, diskoptions_drive_beta128b_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_beta128b_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_beta128b_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Beta 128 Drive C" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_beta128c_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_beta128c_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 4 );
    if( settings_current.drive_beta128c_type != NULL ) {
      for( i = 0; i < diskoptions_drive_beta128c_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_beta128c_type, diskoptions_drive_beta128c_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_beta128c_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_beta128c_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Beta 128 Drive D" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_beta128d_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_beta128d_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 4 );
    if( settings_current.drive_beta128d_type != NULL ) {
      for( i = 0; i < diskoptions_drive_beta128d_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_beta128d_type, diskoptions_drive_beta128d_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_beta128d_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_beta128d_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "+D Drive 1" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_plusd1_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_plusd1_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 3 );
    if( settings_current.drive_plusd1_type != NULL ) {
      for( i = 0; i < diskoptions_drive_plusd1_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_plusd1_type, diskoptions_drive_plusd1_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_plusd1_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_plusd1_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "+D Drive 2" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_plusd2_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_plusd2_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 4 );
    if( settings_current.drive_plusd2_type != NULL ) {
      for( i = 0; i < diskoptions_drive_plusd2_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_plusd2_type, diskoptions_drive_plusd2_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_plusd2_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_plusd2_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Didaktik 80 Drive A" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_didaktik80a_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_didaktik80a_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 3 );
    if( settings_current.drive_didaktik80a_type != NULL ) {
      for( i = 0; i < diskoptions_drive_didaktik80a_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_didaktik80a_type, diskoptions_drive_didaktik80a_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_didaktik80a_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_didaktik80a_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Didaktik 80 Drive B" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_didaktik80b_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_didaktik80b_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 4 );
    if( settings_current.drive_didaktik80b_type != NULL ) {
      for( i = 0; i < diskoptions_drive_didaktik80b_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_didaktik80b_type, diskoptions_drive_didaktik80b_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_didaktik80b_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_didaktik80b_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "DISCiPLE Drive 1" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_disciple1_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_disciple1_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 3 );
    if( settings_current.drive_disciple1_type != NULL ) {
      for( i = 0; i < diskoptions_drive_disciple1_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_disciple1_type, diskoptions_drive_disciple1_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_disciple1_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_disciple1_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "DISCiPLE Drive 2" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_disciple2_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_disciple2_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 4 );
    if( settings_current.drive_disciple2_type != NULL ) {
      for( i = 0; i < diskoptions_drive_disciple2_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_disciple2_type, diskoptions_drive_disciple2_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_disciple2_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_disciple2_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Opus Drive 1" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_opus1_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_opus1_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );
    if( settings_current.drive_opus1_type != NULL ) {
      for( i = 0; i < diskoptions_drive_opus1_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_opus1_type, diskoptions_drive_opus1_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_opus1_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_opus1_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Opus Drive 2" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_drive_opus2_type_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_drive_opus2_type_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 1 );
    if( settings_current.drive_opus2_type != NULL ) {
      for( i = 0; i < diskoptions_drive_opus2_type_combo_count; i++ ) {
        if( !strcmp( settings_current.drive_opus2_type, diskoptions_drive_opus2_type_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.drive_opus2_type = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.drive_opus2_type, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Try merge 'B' side of disks" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < diskoptions_disk_try_merge_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), diskoptions_disk_try_merge_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 1 );
    if( settings_current.disk_try_merge != NULL ) {
      for( i = 0; i < diskoptions_disk_try_merge_combo_count; i++ ) {
        if( !strcmp( settings_current.disk_try_merge, diskoptions_disk_try_merge_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.disk_try_merge = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.disk_try_merge, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  dialog.disk_ask_merge =
    gtk_check_button_new_with_label( "Confirm merge disk sides" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.disk_ask_merge ),
                                settings_current.disk_ask_merge );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.disk_ask_merge );

  /* Create the OK and Cancel buttons */
  gtkstock_create_ok_cancel( dialog.dialog, NULL,
                             G_CALLBACK( menu_options_diskoptions_done ),
                             (gpointer) &dialog, NULL, DEFAULT_DESTROY );

  /* Display the window */
  gtk_widget_show_all( dialog.dialog );

  /* Process events until the window is done with */
  gtk_main();

  /* And then carry on with emulation again */
  fuse_emulation_unpause();
}

static void
menu_options_diskoptions_done( GtkWidget *widget GCC_UNUSED,
			      gpointer user_data )
{
  menu_options_diskoptions_t *ptr = user_data;

  libspectrum_free( settings_current.drive_plus3a_type );
  settings_current.drive_plus3a_type = utils_safe_strdup( diskoptions_drive_plus3a_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_plus3a_type ) ) ] );

  libspectrum_free( settings_current.drive_plus3b_type );
  settings_current.drive_plus3b_type = utils_safe_strdup( diskoptions_drive_plus3b_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_plus3b_type ) ) ] );

  settings_current.plus3_detect_speedlock =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->plus3_detect_speedlock ) );

  libspectrum_free( settings_current.drive_beta128a_type );
  settings_current.drive_beta128a_type = utils_safe_strdup( diskoptions_drive_beta128a_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_beta128a_type ) ) ] );

  libspectrum_free( settings_current.drive_beta128b_type );
  settings_current.drive_beta128b_type = utils_safe_strdup( diskoptions_drive_beta128b_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_beta128b_type ) ) ] );

  libspectrum_free( settings_current.drive_beta128c_type );
  settings_current.drive_beta128c_type = utils_safe_strdup( diskoptions_drive_beta128c_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_beta128c_type ) ) ] );

  libspectrum_free( settings_current.drive_beta128d_type );
  settings_current.drive_beta128d_type = utils_safe_strdup( diskoptions_drive_beta128d_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_beta128d_type ) ) ] );

  libspectrum_free( settings_current.drive_plusd1_type );
  settings_current.drive_plusd1_type = utils_safe_strdup( diskoptions_drive_plusd1_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_plusd1_type ) ) ] );

  libspectrum_free( settings_current.drive_plusd2_type );
  settings_current.drive_plusd2_type = utils_safe_strdup( diskoptions_drive_plusd2_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_plusd2_type ) ) ] );

  libspectrum_free( settings_current.drive_didaktik80a_type );
  settings_current.drive_didaktik80a_type = utils_safe_strdup( diskoptions_drive_didaktik80a_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_didaktik80a_type ) ) ] );

  libspectrum_free( settings_current.drive_didaktik80b_type );
  settings_current.drive_didaktik80b_type = utils_safe_strdup( diskoptions_drive_didaktik80b_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_didaktik80b_type ) ) ] );

  libspectrum_free( settings_current.drive_disciple1_type );
  settings_current.drive_disciple1_type = utils_safe_strdup( diskoptions_drive_disciple1_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_disciple1_type ) ) ] );

  libspectrum_free( settings_current.drive_disciple2_type );
  settings_current.drive_disciple2_type = utils_safe_strdup( diskoptions_drive_disciple2_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_disciple2_type ) ) ] );

  libspectrum_free( settings_current.drive_opus1_type );
  settings_current.drive_opus1_type = utils_safe_strdup( diskoptions_drive_opus1_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_opus1_type ) ) ] );

  libspectrum_free( settings_current.drive_opus2_type );
  settings_current.drive_opus2_type = utils_safe_strdup( diskoptions_drive_opus2_type_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->drive_opus2_type ) ) ] );

  libspectrum_free( settings_current.disk_try_merge );
  settings_current.disk_try_merge = utils_safe_strdup( diskoptions_disk_try_merge_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->disk_try_merge ) ) ] );

  settings_current.disk_ask_merge =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->disk_ask_merge ) );

  gtk_widget_destroy( ptr->dialog );

  gtkstatusbar_set_visibility( settings_current.statusbar );
  display_refresh_all();

  gtk_main_quit();
}


static const char * const movie_movie_compr_combo[] = {
  "None",
  "Lossless",
  "High",
};

static const guint movie_movie_compr_combo_count = 3;

int
option_enumerate_movie_movie_compr( void )
{
  return option_enumerate_combo( movie_movie_compr_combo,
                                 settings_current.movie_compr,
                                 movie_movie_compr_combo_count,
                                 1 );
}

static void menu_options_movie_done( GtkWidget *widget,
					  gpointer user_data );

void
menu_options_movie( GtkWidget *widget GCC_UNUSED,
			 gpointer data GCC_UNUSED )
{
  GtkWidget *content_area;
  menu_options_movie_t dialog;

  /* Firstly, stop emulation */
  fuse_emulation_pause();

  /* Create the necessary widgets */
  dialog.dialog = gtkstock_dialog_new( "Fuse - Movie Options", NULL );
  content_area = gtk_dialog_get_content_area( GTK_DIALOG( dialog.dialog ) );

  /* Create the various widgets */
  {
    GtkWidget *hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 0 );
    GtkWidget *combo = gtk_combo_box_text_new();
    GtkWidget *text = gtk_label_new( "Movie compression" );
    guint i;

    gtk_box_pack_start( GTK_BOX( hbox ), text, FALSE, FALSE, 5 );
    text = gtk_label_new( " " );
    gtk_box_pack_start( GTK_BOX( hbox ), text, TRUE, FALSE, 5 );

    for( i = 0; i < movie_movie_compr_combo_count; i++ ) {
      gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT( combo ), movie_movie_compr_combo[i] );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 1 );
    if( settings_current.movie_compr != NULL ) {
      for( i = 0; i < movie_movie_compr_combo_count; i++ ) {
        if( !strcmp( settings_current.movie_compr, movie_movie_compr_combo[i] ) ) {
          gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), i );
        }
      }
    }

    dialog.movie_compr = combo;
    gtk_box_pack_start( GTK_BOX( hbox ), dialog.movie_compr, FALSE, FALSE, 5 );

    gtk_box_pack_start( GTK_BOX( content_area ), hbox, TRUE, TRUE, 0 );
  }

  dialog.movie_stop_after_rzx =
    gtk_check_button_new_with_label( "Stop recording after RZX ends" );
  gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dialog.movie_stop_after_rzx ),
                                settings_current.movie_stop_after_rzx );
  gtk_container_add( GTK_CONTAINER( content_area ), dialog.movie_stop_after_rzx );

  /* Create the OK and Cancel buttons */
  gtkstock_create_ok_cancel( dialog.dialog, NULL,
                             G_CALLBACK( menu_options_movie_done ),
                             (gpointer) &dialog, NULL, DEFAULT_DESTROY );

  /* Display the window */
  gtk_widget_show_all( dialog.dialog );

  /* Process events until the window is done with */
  gtk_main();

  /* And then carry on with emulation again */
  fuse_emulation_unpause();
}

static void
menu_options_movie_done( GtkWidget *widget GCC_UNUSED,
			      gpointer user_data )
{
  menu_options_movie_t *ptr = user_data;

  libspectrum_free( settings_current.movie_compr );
  settings_current.movie_compr = utils_safe_strdup( movie_movie_compr_combo[
    gtk_combo_box_get_active( GTK_COMBO_BOX( ptr->movie_compr ) ) ] );

  settings_current.movie_stop_after_rzx =
    gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ptr->movie_stop_after_rzx ) );

  gtk_widget_destroy( ptr->dialog );

  gtkstatusbar_set_visibility( settings_current.statusbar );
  display_refresh_all();

  gtk_main_quit();
}


#endif			/* #ifdef UI_GTK */
