/*
 *  Copyright (C) 2006-2016  Ronald Blankendaal
 *
 *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
package org.dbgl.gui;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.dbgl.db.Database;
import org.dbgl.interfaces.Configurable;
import org.dbgl.model.DosboxVersion;
import org.dbgl.model.ExpTemplate;
import org.dbgl.model.Mount;
import org.dbgl.model.NativeCommand;
import org.dbgl.model.Template;
import org.dbgl.model.conf.Autoexec;
import org.dbgl.model.conf.Conf;
import org.dbgl.model.conf.SectionsWrapper;
import org.dbgl.model.conf.Settings;
import org.dbgl.util.FileUtils;
import org.dbgl.util.PlatformUtils;
import org.dbgl.util.StringRelatedUtils;
import swing2swt.layout.BorderLayout;


public class EditTemplateDialog extends Dialog {

	protected Text title;
	protected Button defaultButton;
	protected Combo dbversion;
	protected Button setButton, switchButton, reloadButton;
	protected Combo priority_active, priority_inactive;
	protected Button waitonerror, exit;
	protected Text language, captures, config_file;
	protected Combo output, frameskip;
	protected Combo scaler, pixelshader;
	protected Button fulldouble, fullscreen;
	protected Combo fullresolution, windowresolution;
	protected Button aspect;
	protected Combo overscan;
	protected Combo videoram;
	protected Combo vsyncmode;
	protected Text vsyncrate, forcerate;
	protected Button scaler_forced, linewise, char9, multiscan, autofit, cgasnow, splash3dfx;
	protected Text glideport, memsizeKB;
	protected Combo glide, lfbGlide;
	protected Combo voodoo, voodooMem;
	protected Spinner surfaceNpSharpness;
	protected Button surfaceCollapseDbl;
	protected Combo dacMT32, analogMT32, reverbmodeMT32, reverbtimeMT32, reverblevelMT32;
	protected Combo driverFluid, samplerateFluid;
	protected Text romDirMT32, soundfontFluid, gainFluid;
	protected Combo machine, cpu_type, core;
	protected Combo cycles, cycles_up, cycles_down;
	protected Combo memsize;
	protected Button xms;
	protected Combo ems, umb, memalias;
	protected Button nosound;
	protected Combo rate, blocksize, prebuffer, mpu401, midi_device;
	protected Text midi_config;
	protected Text mixer_config;
	protected Combo sbtype, oplrate, oplmode, oplemu, sbbase, irq, dma, hdma, hardwareaddresssbbase;
	protected Button sbmixer, goldplay;
	protected Button gus, ps1, innova;
	protected Combo gusrate, gusbase, gusdma1, gusdma2, gusirq1, gusirq2;
	protected Combo ps1rate, innovarate, innovabase, innovaquality;
	protected Text ultradir;
	protected Button pcspeaker;
	protected Combo pcrate;
	protected Combo tandy, tandyrate;
	protected Button disney, swapstereo, swapstereoMT32, loggingMT32, multithreadMT32;
	protected Button int33, biosps2, aux, isapnpbios, ide1, ide2, ide3, ide4, automount;
	protected Spinner chunkMT32, prebufferMT32, partialsMT32, files, printerdpi, printerwidth, printerheight, printertimeout;
	protected Button usescancodes, dongle, ne2000;
	protected Text mapperfile;
	protected Combo keyboard_layout, auxdevice, printeroutput;
	protected Text keyb, printerdocpath, ne2000base, ne2000irq, ne2000macaddress, ne2000realnic;
	protected Button autolock;
	protected Combo sensitivity;
	protected Combo joysticktype;
	protected Button timed, autofire, swap34, buttonwrap;
	protected Text serial1, serial2, serial3, serial4, parallel1, parallel2, parallel3;
	protected Button ipx, printer, printermultipage;
	protected Text ipxnet;
	protected Text[] customCommands;
	protected List mountingpoints;
	protected ExpandItem booterExpandItem, dosExpandItem;
	protected Group memoryGroup, associationGroup, miscGroup, executeGroup;
	protected TabItem infoTabItem, generalTabItem, mountingTabItem;
	protected Button okButton, cancelButton;

	protected int dbversionIndex = -1;

	protected Shell shell;
	protected java.util.List<DosboxVersion> dbversionsList;
	protected Database dbase;
	protected java.util.List<Configurable> multiProfileList = new ArrayList<Configurable>();
	protected List nativeCommands;
	protected Settings settings;
	protected Object result;

	protected enum DosboxConfAction {
		SET, SWITCH, RELOAD, RELOAD_TEMPLATE
	};

	public EditTemplateDialog(final Shell parent) {
		super(parent, SWT.NONE);
	}

	public void setTemplate(final Template template) {
		this.result = template;
	}

	public Object open() {
		settings = Settings.getInstance();
		dbase = Database.getInstance();
		if (init()) {
			createContents();
			shell.open();
			shell.layout();
			Display display = getParent().getDisplay();
			while (!shell.isDisposed()) {
				if (!display.readAndDispatch()) {
					display.sleep();
				}
			}
		}
		return result;
	}

	protected boolean init() {
		try {
			dbversionsList = dbase.readDosboxVersionsList();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			PrintStream ps = new PrintStream(bos);
			if (result == null) {
				dbversionIndex = DosboxVersion.indexOfDefault(dbversionsList);
				java.util.List<NativeCommand> nativeCommands = dbase.readNativeCommandsList(-1, -1);
				multiProfileList.add(new ExpTemplate(new Conf((Template)null, dbversionsList.get(dbversionIndex), ps), nativeCommands));
			} else {
				dbversionIndex = DosboxVersion.findIndexById(dbversionsList, ((Template)result).getDbversionId());
				java.util.List<NativeCommand> nativeCommands = dbase.readNativeCommandsList(-1, ((Template)result).getId());
				multiProfileList.add(new ExpTemplate(new Conf((Template)result, dbversionsList.get(dbversionIndex), ps), nativeCommands));
			}
			if (bos.size() > 0) {
				GeneralPurposeDialogs.warningMessage(getParent(), bos.toString());
				bos.reset();
			}
			return true;
		} catch (Exception e) {
			GeneralPurposeDialogs.warningMessage(getParent(), e);
			return false;
		}
	}

	protected void createContents() {
		shell = new Shell(getParent(), SWT.TITLE | SWT.CLOSE | SWT.BORDER | SWT.RESIZE | SWT.APPLICATION_MODAL);
		shell.setLayout(new BorderLayout(0, 0));
		shell.addControlListener(new SizeControlAdapter(shell, "templatedialog"));
		if (result == null) {
			shell.setText(settings.msg("dialog.template.title.add"));
		} else {
			// meaning we are essentially editing an existing template
			shell.setText(settings.msg("dialog.template.title.edit", new Object[] {((Template)result).getTitle(), ((Template)result).getId()}));
		}

		final TabFolder tabFolder = new TabFolder(shell, SWT.NONE);
		createInfoTab(tabFolder);
		createGeneralTab(tabFolder);
		createDisplayTab(tabFolder);
		createMachineTab(tabFolder);
		createAudioTab(tabFolder);
		createIOTab(tabFolder);
		createCustomCommandsTab(tabFolder);
		createMountingTab(tabFolder);

		createOkCancelButtons();
		okButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				if (!isValid()) {
					return;
				}
				try {
					Conf conf = multiProfileList.get(0).getConf();
					result = dbase.addOrEditTemplate(title.getText(), conf.getDbversion().getId(), defaultButton.getSelection(), result == null ? -1: ((Template)result).getId());
					dbase.saveNativeCommands(multiProfileList.get(0).getNativeCommandsList(), -1, ((Template)result).getId());
					updateConfigurationBySettings(conf);
					conf.injectOrUpdateTemplate((Template)result);
					conf.save();
				} catch (Exception e) {
					GeneralPurposeDialogs.warningMessage(shell, e);
				}
				shell.close();
			}
		});

		// init values
		for (DosboxVersion dbv: dbversionsList) {
			dbversion.add(dbv.getTitle());
		}
		dbversion.select(dbversionIndex);

		if (result == null) {
			title.setFocus();
		} else {
			// meaning we are essentially editing an existing template
			// so we need to set previous values
			title.setText(((Template)result).getTitle());
			defaultButton.setSelection(((Template)result).isDefault());
		}

		enableSettingsByConfiguration(multiProfileList.get(0).getConf().getDosboxSettings());
		selectSettingsByConfiguration(multiProfileList.get(0).getConf());
	}

	protected void createOkCancelButtons() {
		final Composite composite_7 = new Composite(shell, SWT.NONE);
		composite_7.setLayout(new GridLayout(2, true));
		composite_7.setLayoutData(BorderLayout.SOUTH);

		okButton = new Button(composite_7, SWT.NONE);
		shell.setDefaultButton(okButton);
		okButton.setText(settings.msg("button.ok"));

		cancelButton = new Button(composite_7, SWT.NONE);
		cancelButton.setText(settings.msg("button.cancel"));
		cancelButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				if (cancelButton.getText().equals(settings.msg("button.cancel"))) {
					result = null;
				}
				shell.close();
			}
		});

		final GridData gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.widthHint = GeneralPurposeGUI.getWidth(okButton, cancelButton);
		okButton.setLayoutData(gridData);
		cancelButton.setLayoutData(gridData);
	}

	protected void createMountingTab(final TabFolder tabFolder) {
		mountingTabItem = new TabItem(tabFolder, SWT.NONE);
		mountingTabItem.setText(settings.msg("dialog.template.tab.mounting"));

		final Composite composite = new Composite(tabFolder, SWT.NONE);
		composite.setLayout(new GridLayout());
		mountingTabItem.setControl(composite);

		createMountingGroup(composite);
		createExecuteGroup(composite);
	}

	protected void createExecuteGroup(final Composite composite) {
		executeGroup = new Group(composite, SWT.NONE);
		executeGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		executeGroup.setText(settings.msg("dialog.template.execute"));
		executeGroup.setLayout(new FillLayout());

		final ExpandBar bar = new ExpandBar(executeGroup, SWT.V_SCROLL);

		Composite booterComposite = new Composite(bar, SWT.NONE);
		Composite dosComposite = new Composite(bar, SWT.NONE);

		createBooterComposite(booterComposite);
		createDosComposite(dosComposite);

		booterExpandItem = new ExpandItem(bar, SWT.NONE, 0);
		booterExpandItem.setText(settings.msg("dialog.template.booter"));
		booterExpandItem.setHeight(booterComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
		booterExpandItem.setControl(booterComposite);

		dosExpandItem = new ExpandItem(bar, SWT.NONE, 1);
		dosExpandItem.setText(settings.msg("dialog.template.dos"));
		dosExpandItem.setHeight(dosComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
		dosExpandItem.setControl(dosComposite);

		bar.addExpandListener(new ExpandAdapter() {
			public void itemCollapsed(final ExpandEvent e) {
				bar.getItem((((ExpandItem)e.item).getText().equals(settings.msg("dialog.template.dos"))) ? 0: 1).setExpanded(true);
				Display.getCurrent().asyncExec(new Runnable() {
					public void run() {
						composite.layout();
					}
				});
			}

			public void itemExpanded(final ExpandEvent e) {
				bar.getItem((((ExpandItem)e.item).getText().equals(settings.msg("dialog.template.dos"))) ? 0: 1).setExpanded(false);
				Display.getCurrent().asyncExec(new Runnable() {
					public void run() {
						composite.layout();
					}
				});
			}
		});

		if (isMultiEdit()) {
			bar.setEnabled(false);
		}
	}

	protected void createBooterComposite(Composite booterComposite) {
		booterComposite.setLayout(new GridLayout());
		final Label image1Label = new Label(booterComposite, SWT.NONE);
		image1Label.setText(settings.msg("dialog.profile.booterimage1"));
	}

	protected void createDosComposite(Composite dosComposite) {
		dosComposite.setLayout(new GridLayout());
		final Label mainExeLabel = new Label(dosComposite, SWT.NONE);
		mainExeLabel.setText(settings.msg("dialog.profile.mainexe"));
	}

	protected void createMountingGroup(final Composite composite) {
		final Group mountGroup = new Group(composite, SWT.NONE);
		mountGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		mountGroup.setText(settings.msg("dialog.template.mountingoverview"));
		mountGroup.setLayout(new GridLayout(2, false));

		mountingpoints = new List(mountGroup, SWT.V_SCROLL | SWT.BORDER);
		mountingpoints.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 3));
		mountingpoints.addMouseListener(new MouseAdapter() {
			public void mouseDoubleClick(final MouseEvent event) {
				if (mountingpoints.getSelectionIndex() == -1) {
					doAddMount();
				} else {
					doEditMount();
				}
			}
		});

		final Button addButton = new Button(mountGroup, SWT.NONE);
		addButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		addButton.setText(settings.msg("dialog.template.mount.add"));
		addButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				doAddMount();
			}
		});

		final Button editButton = new Button(mountGroup, SWT.NONE);
		editButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		editButton.setText(settings.msg("dialog.template.mount.edit"));
		editButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				doEditMount();
			}
		});

		final Button removeButton = new Button(mountGroup, SWT.NONE);
		removeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		removeButton.setText(settings.msg("dialog.template.mount.remove"));
		removeButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				doRemoveMount();
			}
		});

		if (isMultiEdit()) {
			mountingpoints.setEnabled(false);
			addButton.setEnabled(false);
			editButton.setEnabled(false);
			removeButton.setEnabled(false);
		}
	}

	protected void createCustomCommandsTab(final TabFolder tabFolder) {
		final TabItem customCommandsTabItem = new TabItem(tabFolder, SWT.NONE);
		customCommandsTabItem.setText(settings.msg("dialog.template.tab.customcommands"));

		Composite compositeHoldingSubTabs = new Composite(tabFolder, SWT.NONE);
		compositeHoldingSubTabs.setLayout(new FillLayout());
		customCommandsTabItem.setControl(compositeHoldingSubTabs);
		final TabFolder subTabFolder = new TabFolder(compositeHoldingSubTabs, SWT.NONE);

		final TabItem dosboxTabItem = new TabItem(subTabFolder, SWT.NONE);
		dosboxTabItem.setText(settings.msg("dialog.template.tab.dosboxautoexec"));

		final Composite dosboxComposite = new Composite(subTabFolder, SWT.NONE);
		dosboxComposite.setLayout(new GridLayout(2, false));
		dosboxTabItem.setControl(dosboxComposite);

		customCommands = new Text[Autoexec.SECTIONS];
		for (int i = 0; i < Autoexec.SECTIONS; i++) {
			Label filterLabel = new Label(dosboxComposite, SWT.NONE);
			filterLabel.setText(settings.msg("dialog.template.customcommand" + (i + 1)));
			customCommands[i] = new Text(dosboxComposite, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.H_SCROLL);
			customCommands[i].setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		}

		final TabItem nativeTabItem = new TabItem(subTabFolder, SWT.NONE);
		nativeTabItem.setText(settings.msg("dialog.template.tab.native"));

		final Composite nativeComposite = new Composite(subTabFolder, SWT.NONE);
		nativeComposite.setLayout(new GridLayout(2, false));
		nativeTabItem.setControl(nativeComposite);

		nativeCommands = new List(nativeComposite, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
		nativeCommands.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 6));
		nativeCommands.addMouseListener(new MouseAdapter() {
			public void mouseDoubleClick(final MouseEvent event) {
				if (nativeCommands.getSelectionIndex() == -1) {
					doAddNativeCommand();
				} else {
					doEditNativeCommand();
				}
			}
		});

		final Button addButton = new Button(nativeComposite, SWT.NONE);
		addButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		addButton.setText(settings.msg("dialog.template.mount.add"));
		addButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				doAddNativeCommand();
			}
		});

		final Button editButton = new Button(nativeComposite, SWT.NONE);
		editButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		editButton.setText(settings.msg("dialog.template.mount.edit"));
		editButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				doEditNativeCommand();
			}
		});

		final Button removeButton = new Button(nativeComposite, SWT.NONE);
		removeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		removeButton.setText(settings.msg("dialog.template.mount.remove"));
		removeButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				doRemoveNativeCommand();
			}
		});

		Button arrowUpButton = new Button(nativeComposite, SWT.ARROW | SWT.UP);
		arrowUpButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		arrowUpButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				int sel = nativeCommands.getSelectionIndex();
				if (sel > 0) {
					Collections.swap(multiProfileList.get(0).getNativeCommandsList(), sel, sel - 1);
					updateNativeCommands(sel - 1);
				}
			}
		});

		Button arrowDownButton = new Button(nativeComposite, SWT.ARROW | SWT.DOWN);
		arrowDownButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		arrowDownButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				int sel = nativeCommands.getSelectionIndex();
				if (sel >= 0 && sel < nativeCommands.getItemCount() - 1) {
					Collections.swap(multiProfileList.get(0).getNativeCommandsList(), sel, sel + 1);
					updateNativeCommands(sel + 1);
				}
			}
		});

		new Label(nativeComposite, SWT.NONE);

		if (isMultiEdit()) {
			nativeCommands.setEnabled(false);
			addButton.setEnabled(false);
			editButton.setEnabled(false);
			removeButton.setEnabled(false);
			arrowUpButton.setEnabled(false);
			arrowDownButton.setEnabled(false);
		} else {
			updateNativeCommands(-1);
		}
	}

	protected void updateNativeCommands(int sel) {
		nativeCommands.removeAll();
		for (NativeCommand cmd: multiProfileList.get(0).getNativeCommandsList())
			nativeCommands.add(cmd.toString());
		nativeCommands.select(sel);
	}

	protected void createIOTab(final TabFolder tabFolder) {
		final TabFolder subTabFolder = createRelExpTabs(tabFolder, "dialog.template.tab.io", 3, 3);
		final Composite composite_ro = (Composite)subTabFolder.getChildren()[0];
		final Composite composite_xo = (Composite)subTabFolder.getChildren()[1];

		final Group mouseGroup = new Group(composite_ro, SWT.NONE);
		mouseGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		mouseGroup.setText(settings.msg("dialog.template.mouse"));
		mouseGroup.setLayout(new GridLayout(2, false));

		final Label autolockLabel = new Label(mouseGroup, SWT.NONE);
		autolockLabel.setText(settings.msg("dialog.template.autolock"));
		autolock = new Button(mouseGroup, SWT.CHECK);
		autolock.setToolTipText(settings.msg("dialog.template.autolock.tooltip"));

		final Label sensitivityLabel = new Label(mouseGroup, SWT.NONE);
		sensitivityLabel.setText(settings.msg("dialog.template.sensitivity"));
		sensitivity = new Combo(mouseGroup, SWT.READ_ONLY);
		sensitivity.setItems(settings.getSettings().getValues("profile", "sensitivity"));
		sensitivity.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
		sensitivity.setVisibleItemCount(20);
		sensitivity.setToolTipText(settings.msg("dialog.template.sensitivity.tooltip"));

		final Group keyboardGroup = new Group(composite_ro, SWT.NONE);
		keyboardGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		keyboardGroup.setText(settings.msg("dialog.template.keyboard"));
		keyboardGroup.setLayout(new GridLayout(2, false));

		final Label useScancodesLabel = new Label(keyboardGroup, SWT.NONE);
		useScancodesLabel.setText(settings.msg("dialog.template.usescancodes"));
		usescancodes = new Button(keyboardGroup, SWT.CHECK);
		usescancodes.setToolTipText(settings.msg("dialog.template.usescancodes.tooltip"));

		final Label mapperFileLabel = new Label(keyboardGroup, SWT.NONE);
		mapperFileLabel.setText(settings.msg("dialog.template.mapperfile"));

		final Composite mapperfileSettings = new Composite(keyboardGroup, SWT.NONE);
		mapperfileSettings.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		GridLayout filler = new GridLayout();
		filler.numColumns = 2;
		filler.horizontalSpacing = 2;
		filler.marginWidth = 0;
		mapperfileSettings.setLayout(filler);
		
		mapperfile = new Text(mapperfileSettings, SWT.BORDER);
		mapperfile.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		mapperfile.setToolTipText(settings.msg("dialog.template.mapperfile.tooltip"));

		Button mapperfileUnique = new Button(mapperfileSettings, SWT.NONE);
		mapperfileUnique.setText("*");
		mapperfileUnique.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				mapperfile.setText(settings.getSettings().getValue("profile", "uniquemapperfile"));
			}
		});
		final Label layoutLabel = new Label(keyboardGroup, SWT.NONE);
		layoutLabel.setText(settings.msg("dialog.template.keyboardlayout"));
		keyboard_layout = new Combo(keyboardGroup, SWT.NONE);
		keyboard_layout.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		keyboard_layout.setVisibleItemCount(15);
		keyboard_layout.setItems(settings.getSettings().getValues("profile", "keyboardlayout"));
		keyboard_layout.setToolTipText(settings.msg("dialog.template.keyboardlayout.tooltip"));

		final Label keybLabel = new Label(keyboardGroup, SWT.NONE);
		keybLabel.setText(settings.msg("dialog.template.keybcommand"));
		keyb = new Text(keyboardGroup, SWT.BORDER);
		keyb.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Group joystickGroup = new Group(composite_ro, SWT.NONE);
		joystickGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		joystickGroup.setText(settings.msg("dialog.template.joystick"));
		joystickGroup.setLayout(new GridLayout(2, false));

		final Label typeLabel_1 = new Label(joystickGroup, SWT.NONE);
		typeLabel_1.setText(settings.msg("dialog.template.joysticktype"));
		joysticktype = new Combo(joystickGroup, SWT.READ_ONLY);
		joysticktype.setItems(settings.getSettings().getValues("profile", "joysticktype"));
		joysticktype.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		joysticktype.setToolTipText(settings.msg("dialog.template.joysticktype.tooltip"));

		final Label timedLabel = new Label(joystickGroup, SWT.NONE);
		timedLabel.setText(settings.msg("dialog.template.timedemulation"));
		timed = new Button(joystickGroup, SWT.CHECK);
		timed.setToolTipText(settings.msg("dialog.template.timedemulation.tooltip"));

		final Label autofireLabel = new Label(joystickGroup, SWT.NONE);
		autofireLabel.setText(settings.msg("dialog.template.autofire"));
		autofire = new Button(joystickGroup, SWT.CHECK);
		autofire.setToolTipText(settings.msg("dialog.template.autofire.tooltip"));

		final Label swapAxes3Label = new Label(joystickGroup, SWT.NONE);
		swapAxes3Label.setText(settings.msg("dialog.template.swap34"));
		swap34 = new Button(joystickGroup, SWT.CHECK);
		swap34.setToolTipText(settings.msg("dialog.template.swap34.tooltip"));

		final Label buttonWrapLabel = new Label(joystickGroup, SWT.NONE);
		buttonWrapLabel.setText(settings.msg("dialog.template.buttonwrapping"));
		buttonwrap = new Button(joystickGroup, SWT.CHECK);
		buttonwrap.setToolTipText(settings.msg("dialog.template.buttonwrapping.tooltip"));

		final Group modemGroup = new Group(composite_ro, SWT.NONE);
		modemGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
		modemGroup.setText(settings.msg("dialog.template.modem"));
		modemGroup.setLayout(new GridLayout(2, false));

		final Label serial1Label = new Label(modemGroup, SWT.NONE);
		serial1Label.setText(settings.msg("dialog.template.serial1"));
		serial1 = new Text(modemGroup, SWT.BORDER);
		serial1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		serial1.setToolTipText(settings.msg("dialog.template.serial.tooltip"));

		final Label serial2Label = new Label(modemGroup, SWT.NONE);
		serial2Label.setText(settings.msg("dialog.template.serial2"));
		serial2 = new Text(modemGroup, SWT.BORDER);
		serial2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		serial2.setToolTipText(settings.msg("dialog.template.serial.tooltip"));

		final Label serial3Label = new Label(modemGroup, SWT.NONE);
		serial3Label.setText(settings.msg("dialog.template.serial3"));
		serial3 = new Text(modemGroup, SWT.BORDER);
		serial3.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		serial3.setToolTipText(settings.msg("dialog.template.serial.tooltip"));

		final Label serial4Label = new Label(modemGroup, SWT.NONE);
		serial4Label.setText(settings.msg("dialog.template.serial4"));
		serial4 = new Text(modemGroup, SWT.BORDER);
		serial4.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		serial4.setToolTipText(settings.msg("dialog.template.serial.tooltip"));

		final Group networkGroup = new Group(composite_ro, SWT.NONE);
		networkGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		networkGroup.setText(settings.msg("dialog.template.network"));
		networkGroup.setLayout(new GridLayout(2, false));

		final Label ipxLabel = new Label(networkGroup, SWT.NONE);
		ipxLabel.setText(settings.msg("dialog.template.enableipx"));
		ipx = new Button(networkGroup, SWT.CHECK);
		ipx.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				ipxnet.setEnabled(ipx.getSelection());
			}
		});
		ipx.setToolTipText(settings.msg("dialog.template.enableipx.tooltip"));

		final Label ipxnetCommandLabel = new Label(networkGroup, SWT.NONE);
		ipxnetCommandLabel.setText(settings.msg("dialog.template.ipxnetcommand"));
		ipxnetCommandLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 2, 1));

		ipxnet = new Text(networkGroup, SWT.BORDER);
		ipxnet.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

		final Group mouseExpGroup = new Group(composite_xo, SWT.NONE);
		mouseExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		mouseExpGroup.setText(settings.msg("dialog.template.mouse"));
		mouseExpGroup.setLayout(new GridLayout(2, false));

		final Label int33Label = new Label(mouseExpGroup, SWT.NONE);
		int33Label.setText(settings.msg("dialog.template.int33"));
		int33 = new Button(mouseExpGroup, SWT.CHECK);

		final Label biosps2Label = new Label(mouseExpGroup, SWT.NONE);
		biosps2Label.setText(settings.msg("dialog.template.biosps2"));
		biosps2 = new Button(mouseExpGroup, SWT.CHECK);

		final Label auxLabel = new Label(mouseExpGroup, SWT.NONE);
		auxLabel.setText(settings.msg("dialog.template.aux"));
		aux = new Button(mouseExpGroup, SWT.CHECK);

		final Label auxdeviceLabel = new Label(mouseExpGroup, SWT.NONE);
		auxdeviceLabel.setText(settings.msg("dialog.template.auxdevice"));
		auxdevice = new Combo(mouseExpGroup, SWT.READ_ONLY);
		auxdevice.setItems(settings.getSettings().getValues("profile", "auxdevice"));

		final Group miscExpGroup = new Group(composite_xo, SWT.NONE);
		miscExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		miscExpGroup.setText(settings.msg("dialog.template.miscellaneous"));
		miscExpGroup.setLayout(new GridLayout(2, false));

		final Label filesLabel = new Label(miscExpGroup, SWT.NONE);
		filesLabel.setText(settings.msg("dialog.template.files"));
		files = new Spinner(miscExpGroup, SWT.BORDER);
		files.setMinimum(8);
		files.setMaximum(255);

		final Label isapnpbiosLabel = new Label(miscExpGroup, SWT.NONE);
		isapnpbiosLabel.setText(settings.msg("dialog.template.isapnpbios"));
		isapnpbios = new Button(miscExpGroup, SWT.CHECK);

		final Label ide1Label = new Label(miscExpGroup, SWT.NONE);
		ide1Label.setText(settings.msg("dialog.template.ide1"));
		ide1 = new Button(miscExpGroup, SWT.CHECK);

		final Label ide2Label = new Label(miscExpGroup, SWT.NONE);
		ide2Label.setText(settings.msg("dialog.template.ide2"));
		ide2 = new Button(miscExpGroup, SWT.CHECK);

		final Label ide3Label = new Label(miscExpGroup, SWT.NONE);
		ide3Label.setText(settings.msg("dialog.template.ide3"));
		ide3 = new Button(miscExpGroup, SWT.CHECK);

		final Label ide4Label = new Label(miscExpGroup, SWT.NONE);
		ide4Label.setText(settings.msg("dialog.template.ide4"));
		ide4 = new Button(miscExpGroup, SWT.CHECK);

		final Label automountLabel = new Label(miscExpGroup, SWT.NONE);
		automountLabel.setText(settings.msg("dialog.template.automount"));
		automount = new Button(miscExpGroup, SWT.CHECK);

		final Group printerExpGroup = new Group(composite_xo, SWT.NONE);
		printerExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		printerExpGroup.setText(settings.msg("dialog.template.printer"));
		printerExpGroup.setLayout(new GridLayout(2, false));

		final Label printerLabel = new Label(printerExpGroup, SWT.NONE);
		printerLabel.setText(settings.msg("dialog.template.printerenable"));
		printer = new Button(printerExpGroup, SWT.CHECK);

		final Label printerdpiLabel = new Label(printerExpGroup, SWT.NONE);
		printerdpiLabel.setText(settings.msg("dialog.template.printerdpi"));
		printerdpi = new Spinner(printerExpGroup, SWT.BORDER);
		printerdpi.setMinimum(0);
		printerdpi.setMaximum(Short.MAX_VALUE);

		final Label printerwidthLabel = new Label(printerExpGroup, SWT.NONE);
		printerwidthLabel.setText(settings.msg("dialog.template.printerwidth"));
		printerwidth = new Spinner(printerExpGroup, SWT.BORDER);
		printerwidth.setMinimum(0);
		printerwidth.setMaximum(Short.MAX_VALUE);

		final Label printerheightLabel = new Label(printerExpGroup, SWT.NONE);
		printerheightLabel.setText(settings.msg("dialog.template.printerheight"));
		printerheight = new Spinner(printerExpGroup, SWT.BORDER);
		printerheight.setMinimum(0);
		printerheight.setMaximum(Short.MAX_VALUE);

		final Label printeroutputLabel = new Label(printerExpGroup, SWT.NONE);
		printeroutputLabel.setText(settings.msg("dialog.template.printeroutput"));
		printeroutput = new Combo(printerExpGroup, SWT.READ_ONLY);
		printeroutput.setItems(settings.getSettings().getValues("profile", "printeroutput"));

		final Label printermultipageLabel = new Label(printerExpGroup, SWT.NONE);
		printermultipageLabel.setText(settings.msg("dialog.template.printermultipage"));
		printermultipage = new Button(printerExpGroup, SWT.CHECK);

		final Label printerdocpathLabel = new Label(printerExpGroup, SWT.NONE);
		printerdocpathLabel.setText(settings.msg("dialog.template.printerdocpath"));
		printerdocpath = new Text(printerExpGroup, SWT.BORDER);
		printerdocpath.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label printertimeoutLabel = new Label(printerExpGroup, SWT.NONE);
		printertimeoutLabel.setText(settings.msg("dialog.template.printertimeout"));
		printertimeout = new Spinner(printerExpGroup, SWT.BORDER);
		printertimeout.setMinimum(0);
		printertimeout.setMaximum(Short.MAX_VALUE);

		final Group parallelExpGroup = new Group(composite_xo, SWT.NONE);
		parallelExpGroup.setText(settings.msg("dialog.template.parallel"));
		parallelExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
		parallelExpGroup.setLayout(new GridLayout(2, false));

		final Label parallel1Label = new Label(parallelExpGroup, SWT.NONE);
		parallel1Label.setText(settings.msg("dialog.template.parallel1"));
		parallel1 = new Text(parallelExpGroup, SWT.BORDER);
		parallel1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label parallel2Label = new Label(parallelExpGroup, SWT.NONE);
		parallel2Label.setText(settings.msg("dialog.template.parallel2"));
		parallel2 = new Text(parallelExpGroup, SWT.BORDER);
		parallel2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label parallel3Label = new Label(parallelExpGroup, SWT.NONE);
		parallel3Label.setText(settings.msg("dialog.template.parallel3"));
		parallel3 = new Text(parallelExpGroup, SWT.BORDER);
		parallel3.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label dongleLabel = new Label(parallelExpGroup, SWT.NONE);
		dongleLabel.setText(settings.msg("dialog.template.dongle"));
		dongle = new Button(parallelExpGroup, SWT.CHECK);

		final Group ne2000ExpGroup = new Group(composite_xo, SWT.NONE);
		ne2000ExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		ne2000ExpGroup.setText(settings.msg("dialog.template.ne2000"));
		ne2000ExpGroup.setLayout(new GridLayout(2, false));

		final Label ne2000Label = new Label(ne2000ExpGroup, SWT.NONE);
		ne2000Label.setText(settings.msg("dialog.template.ne2000enable"));
		ne2000 = new Button(ne2000ExpGroup, SWT.CHECK);

		final Label ne2000baseLabel = new Label(ne2000ExpGroup, SWT.NONE);
		ne2000baseLabel.setText(settings.msg("dialog.template.ne2000base"));
		ne2000base = new Text(ne2000ExpGroup, SWT.BORDER);
		ne2000base.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label ne2000irqLabel = new Label(ne2000ExpGroup, SWT.NONE);
		ne2000irqLabel.setText(settings.msg("dialog.template.ne2000irq"));
		ne2000irq = new Text(ne2000ExpGroup, SWT.BORDER);
		ne2000irq.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label ne2000macaddressLabel = new Label(ne2000ExpGroup, SWT.NONE);
		ne2000macaddressLabel.setText(settings.msg("dialog.template.ne2000macaddress"));
		ne2000macaddress = new Text(ne2000ExpGroup, SWT.BORDER);
		ne2000macaddress.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label ne2000realnicLabel = new Label(ne2000ExpGroup, SWT.NONE);
		ne2000realnicLabel.setText(settings.msg("dialog.template.ne2000realnic"));
		ne2000realnic = new Text(ne2000ExpGroup, SWT.BORDER);
		ne2000realnic.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
	}

	protected void createAudioTab(final TabFolder tabFolder) {
		final TabFolder subTabFolder = createRelExpTabs(tabFolder, "dialog.template.tab.audio", 3, 3);
		final Composite composite_ro = (Composite)subTabFolder.getChildren()[0];
		final Composite composite_xo = (Composite)subTabFolder.getChildren()[1];

		final Group generalGroup = new Group(composite_ro, SWT.NONE);
		generalGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		generalGroup.setLayout(new GridLayout(2, false));
		generalGroup.setText(settings.msg("dialog.template.general"));

		final Label silentModeLabel = new Label(generalGroup, SWT.NONE);
		silentModeLabel.setText(settings.msg("dialog.template.silentmode"));
		nosound = new Button(generalGroup, SWT.CHECK);
		nosound.setToolTipText(settings.msg("dialog.template.silentmode.tooltip"));

		final Label sampleRateLabel = new Label(generalGroup, SWT.NONE);
		sampleRateLabel.setText(settings.msg("dialog.template.samplerate"));
		rate = new Combo(generalGroup, SWT.READ_ONLY);
		rate.setVisibleItemCount(10);
		rate.setItems(settings.getSettings().getValues("profile", "rate"));
		rate.setLayoutData(new GridData());
		rate.setToolTipText(settings.msg("dialog.template.samplerate.tooltip"));

		final Label blockSizeLabel = new Label(generalGroup, SWT.NONE);
		blockSizeLabel.setText(settings.msg("dialog.template.blocksize"));
		blocksize = new Combo(generalGroup, SWT.READ_ONLY);
		blocksize.setItems(settings.getSettings().getValues("profile", "blocksize"));
		blocksize.setLayoutData(new GridData());
		blocksize.setToolTipText(settings.msg("dialog.template.blocksize.tooltip"));

		final Label prebufferLabel = new Label(generalGroup, SWT.NONE);
		prebufferLabel.setText(settings.msg("dialog.template.prebuffer"));
		prebuffer = new Combo(generalGroup, SWT.NONE);
		prebuffer.setItems(settings.getSettings().getValues("profile", "prebuffer"));
		prebuffer.setLayoutData(new GridData(70, SWT.DEFAULT));
		prebuffer.setToolTipText(settings.msg("dialog.template.prebuffer.tooltip"));

		final Label mpu401Label = new Label(generalGroup, SWT.NONE);
		mpu401Label.setText(settings.msg("dialog.template.mpu401"));
		mpu401 = new Combo(generalGroup, SWT.READ_ONLY);
		mpu401.setItems(settings.getSettings().getValues("profile", "mpu401"));
		mpu401.setLayoutData(new GridData());
		mpu401.setToolTipText(settings.msg("dialog.template.mpu401.tooltip"));

		final Label midiDeviceLabel = new Label(generalGroup, SWT.NONE);
		midiDeviceLabel.setText(settings.msg("dialog.template.mididevice"));
		midi_device = new Combo(generalGroup, SWT.READ_ONLY);
		midi_device.setVisibleItemCount(10);
		midi_device.setItems(settings.getSettings().getValues("profile", "device"));
		midi_device.setLayoutData(new GridData());
		midi_device.setToolTipText(settings.msg("dialog.template.mididevice.tooltip"));

		final Label configLabel = new Label(generalGroup, SWT.NONE);
		configLabel.setText(settings.msg("dialog.template.midiconfig"));
		midi_config = new Text(generalGroup, SWT.BORDER);
		midi_config.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		midi_config.setToolTipText(settings.msg("dialog.template.midiconfig.tooltip"));

		final Label mixerConfigLabel = new Label(generalGroup, SWT.NONE);
		mixerConfigLabel.setText(settings.msg("dialog.template.mixercommand"));

		final Composite mixerSettings = new Composite(generalGroup, SWT.NONE);
		mixerSettings.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		GridLayout filler = new GridLayout();
		filler.numColumns = 2;
		filler.horizontalSpacing = 2;
		filler.marginWidth = 0;
		mixerSettings.setLayout(filler);

		mixer_config = new Text(mixerSettings, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
		GridData mixerConfigGridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
		mixerConfigGridData.widthHint = 66;
		mixer_config.setLayoutData(mixerConfigGridData);
		Button mixerConfig = new Button(mixerSettings, SWT.NONE);
		mixerConfig.setText("...");
		mixerConfig.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				EditMixerDialog dialog = new EditMixerDialog(shell);
				dialog.setMixerCommand(mixer_config.getText());
				String command = (String)dialog.open();
				if (command != null) {
					mixer_config.setText(command);
				}
			}
		});

		final Group soundblasterGroup = new Group(composite_ro, SWT.NONE);
		soundblasterGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		soundblasterGroup.setText(settings.msg("dialog.template.soundblaster"));
		soundblasterGroup.setLayout(new GridLayout(2, false));

		final Label typeLabel = new Label(soundblasterGroup, SWT.NONE);
		typeLabel.setText(settings.msg("dialog.template.sbtype"));
		sbtype = new Combo(soundblasterGroup, SWT.READ_ONLY);
		sbtype.setVisibleItemCount(10);
		sbtype.setItems(settings.getSettings().getValues("profile", "sbtype"));
		sbtype.setLayoutData(new GridData());
		sbtype.setToolTipText(settings.msg("dialog.template.sbtype.tooltip"));

		final Label oplRateLabel = new Label(soundblasterGroup, SWT.NONE);
		oplRateLabel.setText(settings.msg("dialog.template.sboplrate"));
		oplrate = new Combo(soundblasterGroup, SWT.READ_ONLY);
		oplrate.setVisibleItemCount(10);
		oplrate.setItems(settings.getSettings().getValues("profile", "oplrate"));
		oplrate.setLayoutData(new GridData());
		oplrate.setToolTipText(settings.msg("dialog.template.sboplrate.tooltip"));

		final Label oplModeLabel = new Label(soundblasterGroup, SWT.NONE);
		oplModeLabel.setLayoutData(new GridData());
		oplModeLabel.setText(settings.msg("dialog.template.sboplmode"));
		oplmode = new Combo(soundblasterGroup, SWT.READ_ONLY);
		oplmode.setItems(settings.getSettings().getValues("profile", "oplmode"));
		oplmode.setLayoutData(new GridData());
		oplmode.setToolTipText(settings.msg("dialog.template.sboplmode.tooltip"));

		final Label oplEmuLabel = new Label(soundblasterGroup, SWT.NONE);
		oplEmuLabel.setLayoutData(new GridData());
		oplEmuLabel.setText(settings.msg("dialog.template.sboplemu"));
		oplemu = new Combo(soundblasterGroup, SWT.READ_ONLY);
		oplemu.setItems(settings.getSettings().getValues("profile", "oplemu"));
		oplemu.setLayoutData(new GridData());
		oplemu.setToolTipText(settings.msg("dialog.template.sboplemu.tooltip"));

		final Label addressLabel = new Label(soundblasterGroup, SWT.NONE);
		addressLabel.setText(settings.msg("dialog.template.sbaddress"));
		sbbase = new Combo(soundblasterGroup, SWT.READ_ONLY);
		sbbase.setItems(settings.getSettings().getValues("profile", "sbbase"));
		sbbase.setLayoutData(new GridData());
		sbbase.setToolTipText(settings.msg("dialog.template.sbaddress.tooltip"));

		final Label irqLabel = new Label(soundblasterGroup, SWT.NONE);
		irqLabel.setText(settings.msg("dialog.template.sbirq"));
		irq = new Combo(soundblasterGroup, SWT.READ_ONLY);
		irq.setItems(settings.getSettings().getValues("profile", "irq"));
		irq.setLayoutData(new GridData());
		irq.setToolTipText(settings.msg("dialog.template.sbirq.tooltip"));

		final Label dmaLabel = new Label(soundblasterGroup, SWT.NONE);
		dmaLabel.setText(settings.msg("dialog.template.sbdma"));
		dma = new Combo(soundblasterGroup, SWT.READ_ONLY);
		dma.setItems(settings.getSettings().getValues("profile", "dma"));
		dma.setLayoutData(new GridData());
		dma.setToolTipText(settings.msg("dialog.template.sbdma.tooltip"));

		final Label hdmaLabel = new Label(soundblasterGroup, SWT.NONE);
		hdmaLabel.setLayoutData(new GridData());
		hdmaLabel.setText(settings.msg("dialog.template.sbhdma"));
		hdma = new Combo(soundblasterGroup, SWT.READ_ONLY);
		hdma.setItems(settings.getSettings().getValues("profile", "hdma"));
		hdma.setLayoutData(new GridData());
		hdma.setToolTipText(settings.msg("dialog.template.sbhdma.tooltip"));

		final Label mixerLabel = new Label(soundblasterGroup, SWT.NONE);
		mixerLabel.setText(settings.msg("dialog.template.mixer"));
		sbmixer = new Button(soundblasterGroup, SWT.CHECK);
		sbmixer.setToolTipText(settings.msg("dialog.template.mixer.tooltip"));

		final Group gusGroup = new Group(composite_ro, SWT.NONE);
		gusGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		gusGroup.setText(settings.msg("dialog.template.gravisultrasound"));
		gusGroup.setLayout(new GridLayout(2, false));

		final Label enableLabel_1 = new Label(gusGroup, SWT.NONE);
		enableLabel_1.setLayoutData(new GridData());
		enableLabel_1.setText(settings.msg("dialog.template.enablegus"));
		gus = new Button(gusGroup, SWT.CHECK);
		gus.setLayoutData(new GridData());
		gus.setToolTipText(settings.msg("dialog.template.enablegus.tooltip"));

		final Label sampleRateLabel_2 = new Label(gusGroup, SWT.NONE);
		sampleRateLabel_2.setText(settings.msg("dialog.template.gusrate"));
		gusrate = new Combo(gusGroup, SWT.READ_ONLY);
		gusrate.setVisibleItemCount(10);
		gusrate.setItems(settings.getSettings().getValues("profile", "gusrate"));
		gusrate.setLayoutData(new GridData());
		gusrate.setToolTipText(settings.msg("dialog.template.gusrate.tooltip"));

		final Label addressLabel_1 = new Label(gusGroup, SWT.NONE);
		addressLabel_1.setText(settings.msg("dialog.template.gusaddress"));
		gusbase = new Combo(gusGroup, SWT.READ_ONLY);
		gusbase.setItems(settings.getSettings().getValues("profile", "gusbase"));
		gusbase.setLayoutData(new GridData());
		gusbase.setToolTipText(settings.msg("dialog.template.gusaddress.tooltip"));

		final Label irqLabel_1 = new Label(gusGroup, SWT.NONE);
		irqLabel_1.setText(settings.msg("dialog.template.gusirq1"));
		gusirq1 = new Combo(gusGroup, SWT.READ_ONLY);
		gusirq1.setItems(settings.getSettings().getValues("profile", "irq1"));
		gusirq1.setLayoutData(new GridData());
		gusirq1.setToolTipText(settings.msg("dialog.template.gusirq1.tooltip"));

		final Label irq2Label = new Label(gusGroup, SWT.NONE);
		irq2Label.setText(settings.msg("dialog.template.gusirq2"));
		gusirq2 = new Combo(gusGroup, SWT.READ_ONLY);
		gusirq2.setItems(settings.getSettings().getValues("profile", "irq2"));
		gusirq2.setLayoutData(new GridData());

		final Label dmaLabel_1 = new Label(gusGroup, SWT.NONE);
		dmaLabel_1.setText(settings.msg("dialog.template.gusdma1"));
		gusdma1 = new Combo(gusGroup, SWT.READ_ONLY);
		gusdma1.setItems(settings.getSettings().getValues("profile", "dma1"));
		gusdma1.setLayoutData(new GridData());
		gusdma1.setToolTipText(settings.msg("dialog.template.gusdma1.tooltip"));

		final Label hdmaLabel_1 = new Label(gusGroup, SWT.NONE);
		hdmaLabel_1.setLayoutData(new GridData());
		hdmaLabel_1.setText(settings.msg("dialog.template.gusdma2"));
		gusdma2 = new Combo(gusGroup, SWT.READ_ONLY);
		gusdma2.setItems(settings.getSettings().getValues("profile", "dma2"));
		gusdma2.setLayoutData(new GridData());

		final Label ultradirLabel = new Label(gusGroup, SWT.NONE);
		ultradirLabel.setText(settings.msg("dialog.template.ultradir"));
		ultradir = new Text(gusGroup, SWT.BORDER);
		ultradir.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		ultradir.setToolTipText(settings.msg("dialog.template.ultradir.tooltip"));

		final Group speakerGroup = new Group(composite_ro, SWT.NONE);
		speakerGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		speakerGroup.setText(settings.msg("dialog.template.pcspeaker"));
		speakerGroup.setLayout(new GridLayout(2, false));

		final Label enableLabel = new Label(speakerGroup, SWT.NONE);
		enableLabel.setText(settings.msg("dialog.template.enablepcspeaker"));
		pcspeaker = new Button(speakerGroup, SWT.CHECK);
		pcspeaker.setToolTipText(settings.msg("dialog.template.enablepcspeaker.tooltip"));

		final Label sampleRateLabel_1 = new Label(speakerGroup, SWT.NONE);
		sampleRateLabel_1.setText(settings.msg("dialog.template.pcrate"));
		pcrate = new Combo(speakerGroup, SWT.READ_ONLY);
		pcrate.setVisibleItemCount(10);
		pcrate.setItems(settings.getSettings().getValues("profile", "pcrate"));
		pcrate.setLayoutData(new GridData());
		pcrate.setToolTipText(settings.msg("dialog.template.pcrate.tooltip"));

		final Group tandyGroup = new Group(composite_ro, SWT.NONE);
		tandyGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		tandyGroup.setText(settings.msg("dialog.template.tandy"));
		tandyGroup.setLayout(new GridLayout(2, false));

		final Label enableLabel_2 = new Label(tandyGroup, SWT.NONE);
		enableLabel_2.setText(settings.msg("dialog.template.enabletandy"));
		tandy = new Combo(tandyGroup, SWT.READ_ONLY);
		tandy.setItems(settings.getSettings().getValues("profile", "tandy"));
		tandy.setLayoutData(new GridData());
		tandy.setToolTipText(settings.msg("dialog.template.enabletandy.tooltip"));

		final Label sampleLabel2 = new Label(tandyGroup, SWT.NONE);
		sampleLabel2.setText(settings.msg("dialog.template.tandyrate"));
		tandyrate = new Combo(tandyGroup, SWT.READ_ONLY);
		tandyrate.setVisibleItemCount(10);
		tandyrate.setItems(settings.getSettings().getValues("profile", "tandyrate"));
		tandyrate.setLayoutData(new GridData());
		tandyrate.setToolTipText(settings.msg("dialog.template.tandyrate.tooltip"));

		final Group disneyGroup = new Group(composite_ro, SWT.NONE);
		disneyGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		disneyGroup.setText(settings.msg("dialog.template.miscellaneous"));
		disneyGroup.setLayout(new GridLayout(2, false));

		final Label enableLabel_3 = new Label(disneyGroup, SWT.NONE);
		enableLabel_3.setText(settings.msg("dialog.template.enablesoundsource"));
		disney = new Button(disneyGroup, SWT.CHECK);
		disney.setToolTipText(settings.msg("dialog.template.enablesoundsource.tooltip"));

		final Group fluidExpGroup = new Group(composite_xo, SWT.NONE);
		fluidExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		fluidExpGroup.setText(settings.msg("dialog.template.fluidsynth"));
		fluidExpGroup.setLayout(new GridLayout(2, false));

		final Label driverFluidLabel = new Label(fluidExpGroup, SWT.NONE);
		driverFluidLabel.setText(settings.msg("dialog.template.fluidsynth.driver"));
		driverFluid = new Combo(fluidExpGroup, SWT.NONE);
		driverFluid.setItems(settings.getSettings().getValues("profile", "fluidsynthdriver"));

		final Label soundfontFluidLabel = new Label(fluidExpGroup, SWT.NONE);
		soundfontFluidLabel.setText(settings.msg("dialog.template.fluidsynth.soundfont"));
		soundfontFluid = new Text(fluidExpGroup, SWT.BORDER);
		soundfontFluid.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		
		final Label sampleFluidLabel = new Label(fluidExpGroup, SWT.NONE);
		sampleFluidLabel.setText(settings.msg("dialog.template.fluidsynth.samplerate"));
		samplerateFluid = new Combo(fluidExpGroup, SWT.READ_ONLY);
		samplerateFluid.setVisibleItemCount(10);
		samplerateFluid.setItems(settings.getSettings().getValues("profile", "fluidsynthsamplerate"));
		
		final Label gainFluidLabel = new Label(fluidExpGroup, SWT.NONE);
		gainFluidLabel.setText(settings.msg("dialog.template.fluidsynth.gain"));
		gainFluid = new Text(fluidExpGroup, SWT.BORDER);
		gainFluid.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		
		final Group soundblasterExpGroup = new Group(composite_xo, SWT.NONE);
		soundblasterExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		soundblasterExpGroup.setText(settings.msg("dialog.template.soundblaster"));
		soundblasterExpGroup.setLayout(new GridLayout(2, false));

		final Label hardwareaddressLabel = new Label(soundblasterExpGroup, SWT.NONE);
		hardwareaddressLabel.setText(settings.msg("dialog.template.hardwaresbaddress"));
		hardwareaddresssbbase = new Combo(soundblasterExpGroup, SWT.READ_ONLY);
		hardwareaddresssbbase.setItems(settings.getSettings().getValues("profile", "hardwaresbbase"));

		final Label goldplayLabel = new Label(soundblasterExpGroup, SWT.NONE);
		goldplayLabel.setText(settings.msg("dialog.template.goldplay"));
		goldplay = new Button(soundblasterExpGroup, SWT.CHECK);

		final Group mt32ExpGroup = new Group(composite_xo, SWT.NONE);
		mt32ExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		mt32ExpGroup.setText(settings.msg("dialog.template.mt32"));
		mt32ExpGroup.setLayout(new GridLayout(2, false));

		final Label romDirMT32Label = new Label(mt32ExpGroup, SWT.NONE);
		romDirMT32Label.setText(settings.msg("dialog.template.mt32.romdir"));
		romDirMT32 = new Text(mt32ExpGroup, SWT.BORDER);
		romDirMT32.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label swapstereoMT32Label = new Label(mt32ExpGroup, SWT.NONE);
		swapstereoMT32Label.setText(settings.msg("dialog.template.swapstereo"));
		swapstereoMT32 = new Button(mt32ExpGroup, SWT.CHECK);

		final Label loggingMT32Label = new Label(mt32ExpGroup, SWT.NONE);
		loggingMT32Label.setText(settings.msg("dialog.template.mt32.verboselogging"));
		loggingMT32 = new Button(mt32ExpGroup, SWT.CHECK);

		final Label multithreadMT32Label = new Label(mt32ExpGroup, SWT.NONE);
		multithreadMT32Label.setText(settings.msg("dialog.template.mt32.multithread"));
		multithreadMT32 = new Button(mt32ExpGroup, SWT.CHECK);

		final Label chunkLabel = new Label(mt32ExpGroup, SWT.NONE);
		chunkLabel.setText(settings.msg("dialog.template.mt32.chunk"));
		chunkMT32 = new Spinner(mt32ExpGroup, SWT.BORDER);
		chunkMT32.setMinimum(2);
		chunkMT32.setMaximum(100);
		
		final Label prebufferMT32Label = new Label(mt32ExpGroup, SWT.NONE);
		prebufferMT32Label.setText(settings.msg("dialog.template.mt32.prebuffer"));
		prebufferMT32 = new Spinner(mt32ExpGroup, SWT.BORDER);
		prebufferMT32.setMinimum(3);
		prebufferMT32.setMaximum(200);
		
		final Label partialsLabel = new Label(mt32ExpGroup, SWT.NONE);
		partialsLabel.setText(settings.msg("dialog.template.mt32.partials"));
		partialsMT32 = new Spinner(mt32ExpGroup, SWT.BORDER);
		partialsMT32.setMinimum(0);
		partialsMT32.setMaximum(256);

		final Label dacLabel = new Label(mt32ExpGroup, SWT.NONE);
		dacLabel.setText(settings.msg("dialog.template.mt32.dac"));
		dacMT32 = new Combo(mt32ExpGroup, SWT.READ_ONLY);
		dacMT32.setItems(settings.getSettings().getValues("profile", "mt32dac"));

		final Label analogLabel = new Label(mt32ExpGroup, SWT.NONE);
		analogLabel.setText(settings.msg("dialog.template.mt32.analog"));
		analogMT32 = new Combo(mt32ExpGroup, SWT.READ_ONLY);
		analogMT32.setItems(settings.getSettings().getValues("profile", "mt32analog"));

		final Label reverbmodeLabel = new Label(mt32ExpGroup, SWT.NONE);
		reverbmodeLabel.setText(settings.msg("dialog.template.mt32.reverbmode"));
		reverbmodeMT32 = new Combo(mt32ExpGroup, SWT.READ_ONLY);
		reverbmodeMT32.setItems(settings.getSettings().getValues("profile", "mt32reverbmode"));

		final Label reverbtimeLabel = new Label(mt32ExpGroup, SWT.NONE);
		reverbtimeLabel.setText(settings.msg("dialog.template.mt32.reverbtime"));
		reverbtimeMT32 = new Combo(mt32ExpGroup, SWT.READ_ONLY);
		reverbtimeMT32.setItems(settings.getSettings().getValues("profile", "mt32reverbtime"));

		final Label reverblevelLabel = new Label(mt32ExpGroup, SWT.NONE);
		reverblevelLabel.setText(settings.msg("dialog.template.mt32.reverblevel"));
		reverblevelMT32 = new Combo(mt32ExpGroup, SWT.READ_ONLY);
		reverblevelMT32.setItems(settings.getSettings().getValues("profile", "mt32reverblevel"));

		final Group generalExpGroup = new Group(composite_xo, SWT.NONE);
		generalExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		generalExpGroup.setLayout(new GridLayout(2, false));
		generalExpGroup.setText(settings.msg("dialog.template.general"));

		final Label swapstereoLabel = new Label(generalExpGroup, SWT.NONE);
		swapstereoLabel.setText(settings.msg("dialog.template.swapstereo"));
		swapstereo = new Button(generalExpGroup, SWT.CHECK);

		final Group ps1ExpGroup = new Group(composite_xo, SWT.NONE);
		ps1ExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		ps1ExpGroup.setText(settings.msg("dialog.template.ps1"));
		ps1ExpGroup.setLayout(new GridLayout(2, false));

		final Label enablePS1Label = new Label(ps1ExpGroup, SWT.NONE);
		enablePS1Label.setText(settings.msg("dialog.template.ps1enable"));
		ps1 = new Button(ps1ExpGroup, SWT.CHECK);

		final Label sampleRatePS1Label = new Label(ps1ExpGroup, SWT.NONE);
		sampleRatePS1Label.setText(settings.msg("dialog.template.ps1rate"));
		ps1rate = new Combo(ps1ExpGroup, SWT.READ_ONLY);
		ps1rate.setItems(settings.getSettings().getValues("profile", "ps1rate"));

		final Group innovaExpGroup = new Group(composite_xo, SWT.NONE);
		innovaExpGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		innovaExpGroup.setText(settings.msg("dialog.template.innova"));
		innovaExpGroup.setLayout(new GridLayout(2, false));

		final Label enableInnovaLabel = new Label(innovaExpGroup, SWT.NONE);
		enableInnovaLabel.setText(settings.msg("dialog.template.innovaenable"));
		innova = new Button(innovaExpGroup, SWT.CHECK);

		final Label sampleRateInnovaLabel = new Label(innovaExpGroup, SWT.NONE);
		sampleRateInnovaLabel.setText(settings.msg("dialog.template.innovarate"));
		innovarate = new Combo(innovaExpGroup, SWT.READ_ONLY);
		innovarate.setItems(settings.getSettings().getValues("profile", "innovarate"));

		final Label sidbaseLabel = new Label(innovaExpGroup, SWT.NONE);
		sidbaseLabel.setText(settings.msg("dialog.template.innovaaddress"));
		innovabase = new Combo(innovaExpGroup, SWT.READ_ONLY);
		innovabase.setItems(settings.getSettings().getValues("profile", "innovabase"));

		final Label sidqualityLabel = new Label(innovaExpGroup, SWT.NONE);
		sidqualityLabel.setText(settings.msg("dialog.template.innovaquality"));
		innovaquality = new Combo(innovaExpGroup, SWT.READ_ONLY);
		innovaquality.setItems(settings.getSettings().getValues("profile", "innovaquality"));
	}

	protected void createMachineTab(final TabFolder tabFolder) {
		final TabFolder subTabFolder = createRelExpTabs(tabFolder, "dialog.template.tab.machine", 1, 1);
		final Composite composite_ro = (Composite)subTabFolder.getChildren()[0];
		final Composite composite_xo = (Composite)subTabFolder.getChildren()[1];

		final Group cpuGroup = new Group(composite_ro, SWT.NONE);
		cpuGroup.setText(settings.msg("dialog.template.cpu"));
		cpuGroup.setLayout(new GridLayout(6, false));

		final Label machineLabel = new Label(cpuGroup, SWT.NONE);
		machineLabel.setText(settings.msg("dialog.template.machine"));
		machine = new Combo(cpuGroup, SWT.READ_ONLY);
		machine.setLayoutData(new GridData());
		machine.setVisibleItemCount(20);
		machine.setToolTipText(settings.msg("dialog.template.machine.tooltip"));

		final Label cputypeLabel = new Label(cpuGroup, SWT.NONE);
		cputypeLabel.setText(settings.msg("dialog.template.cputype"));
		cpu_type = new Combo(cpuGroup, SWT.READ_ONLY);
		cpu_type.setItems(settings.getSettings().getValues("profile", "cputype"));
		cpu_type.setLayoutData(new GridData());
		cpu_type.setVisibleItemCount(10);
		cpu_type.setToolTipText(settings.msg("dialog.template.cputype.tooltip"));
		new Label(cpuGroup, SWT.NONE);
		new Label(cpuGroup, SWT.NONE);

		final Label coreLabel = new Label(cpuGroup, SWT.NONE);
		coreLabel.setText(settings.msg("dialog.template.core"));
		core = new Combo(cpuGroup, SWT.READ_ONLY);
		core.setItems(settings.getSettings().getValues("profile", "core"));
		core.setLayoutData(new GridData());
		core.setToolTipText(settings.msg("dialog.template.core.tooltip"));
		new Label(cpuGroup, SWT.NONE);
		new Label(cpuGroup, SWT.NONE);
		new Label(cpuGroup, SWT.NONE);
		new Label(cpuGroup, SWT.NONE);

		final Label cyclesLabel = new Label(cpuGroup, SWT.NONE);
		cyclesLabel.setText(settings.msg("dialog.template.cycles"));
		cycles = new Combo(cpuGroup, SWT.NONE);
		cycles.setItems(settings.getSettings().getValues("profile", "cycles"));
		cycles.setLayoutData(new GridData(100, SWT.DEFAULT));
		cycles.setVisibleItemCount(15);
		cycles.setToolTipText(settings.msg("dialog.template.cycles.tooltip"));

		final Label upLabel = new Label(cpuGroup, SWT.NONE);
		upLabel.setLayoutData(new GridData());
		upLabel.setText(settings.msg("dialog.template.up"));
		cycles_up = new Combo(cpuGroup, SWT.NONE);
		cycles_up.setItems(settings.getSettings().getValues("profile", "cycles_up"));
		cycles_up.setLayoutData(new GridData(75, SWT.DEFAULT));
		cycles_up.setToolTipText(settings.msg("dialog.template.up.tooltip"));

		final Label downLabel = new Label(cpuGroup, SWT.NONE);
		downLabel.setLayoutData(new GridData());
		downLabel.setText(settings.msg("dialog.template.down"));
		cycles_down = new Combo(cpuGroup, SWT.NONE);
		cycles_down.setItems(settings.getSettings().getValues("profile", "cycles_down"));
		cycles_down.setLayoutData(new GridData(75, SWT.DEFAULT));
		cycles_down.setToolTipText(settings.msg("dialog.template.down.tooltip"));

		memoryGroup = new Group(composite_ro, SWT.NONE);
		memoryGroup.setText(settings.msg("dialog.template.memory"));
		memoryGroup.setLayout(new GridLayout(4, false));

		final Label sizeLabel = new Label(memoryGroup, SWT.NONE);
		sizeLabel.setText(settings.msg("dialog.template.memorysize"));
		memsize = new Combo(memoryGroup, SWT.READ_ONLY);
		memsize.setItems(settings.getSettings().getValues("profile", "memsize"));
		memsize.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		memsize.setToolTipText(settings.msg("dialog.template.memorysize.tooltip"));
		new Label(memoryGroup, SWT.NONE);
		new Label(memoryGroup, SWT.NONE);

		final Label xmsLabel = new Label(memoryGroup, SWT.NONE);
		xmsLabel.setText(settings.msg("dialog.template.xms"));
		xms = new Button(memoryGroup, SWT.CHECK);
		xms.setToolTipText(settings.msg("dialog.template.xms.tooltip"));
		new Label(memoryGroup, SWT.NONE);
		new Label(memoryGroup, SWT.NONE);

		final Label emsLabel = new Label(memoryGroup, SWT.NONE);
		emsLabel.setText(settings.msg("dialog.template.ems"));
		ems = new Combo(memoryGroup, SWT.READ_ONLY);
		ems.setItems(settings.getSettings().getValues("profile", "ems"));
		ems.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		ems.setToolTipText(settings.msg("dialog.template.ems.tooltip"));
		new Label(memoryGroup, SWT.NONE);
		new Label(memoryGroup, SWT.NONE);

		final Label umbLabel = new Label(memoryGroup, SWT.NONE);
		umbLabel.setText(settings.msg("dialog.template.umb"));
		umb = new Combo(memoryGroup, SWT.READ_ONLY);
		umb.setItems(settings.getSettings().getValues("profile", "umb"));
		umb.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		umb.setToolTipText(settings.msg("dialog.template.umb.tooltip"));
		new Label(memoryGroup, SWT.NONE);
		new Label(memoryGroup, SWT.NONE);

		final Group expMemoryGroup = new Group(composite_xo, SWT.NONE);
		expMemoryGroup.setText(settings.msg("dialog.template.memory"));
		expMemoryGroup.setLayout(new GridLayout(2, false));

		final Label sizeKBLabel = new Label(expMemoryGroup, SWT.NONE);
		sizeKBLabel.setText(settings.msg("dialog.template.memorysizekb"));
		memsizeKB = new Text(expMemoryGroup, SWT.BORDER);
		memsizeKB.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label aliasLabel = new Label(expMemoryGroup, SWT.NONE);
		aliasLabel.setText(settings.msg("dialog.template.memalias"));
		memalias = new Combo(expMemoryGroup, SWT.NONE);
		memalias.setItems(settings.getSettings().getValues("profile", "memalias"));
		memalias.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
	}

	protected TabFolder createRelExpTabs(final TabFolder tabFolder, final String titleKey, int col1, int col2) {
		final TabItem displayTabItem = new TabItem(tabFolder, SWT.NONE);
		displayTabItem.setText(settings.msg(titleKey));

		final Composite compositeHoldingSubTabs = new Composite(tabFolder, SWT.NONE);
		compositeHoldingSubTabs.setLayout(new FillLayout());
		displayTabItem.setControl(compositeHoldingSubTabs);
		final TabFolder subTabFolder = new TabFolder(compositeHoldingSubTabs, SWT.NONE);

		final TabItem releaseOptionsTabItem = new TabItem(subTabFolder, SWT.NONE);
		releaseOptionsTabItem.setText(settings.msg("dialog.template.tab.releaseoptions"));
		final TabItem experimentalOptionsTabItem = new TabItem(subTabFolder, SWT.NONE);
		experimentalOptionsTabItem.setText(settings.msg("dialog.template.tab.experimentaloptions"));

		final Composite relComp = new Composite(subTabFolder, SWT.NONE);
		relComp.setLayout(new GridLayout(col1, false));
		releaseOptionsTabItem.setControl(relComp);
		final Composite expComp = new Composite(subTabFolder, SWT.NONE);
		expComp.setLayout(new GridLayout(col2, false));
		experimentalOptionsTabItem.setControl(expComp);

		return subTabFolder;
	}

	protected void createDisplayTab(final TabFolder tabFolder) {
		final TabFolder subTabFolder = createRelExpTabs(tabFolder, "dialog.template.tab.display", 1, 2);
		final Composite composite_ro = (Composite)subTabFolder.getChildren()[0];
		final Composite composite_xo = (Composite)subTabFolder.getChildren()[1];

		final Group groupRelease = new Group(composite_ro, SWT.NONE);
		groupRelease.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
		groupRelease.setLayout(new GridLayout(4, false));
		groupRelease.setText(settings.msg("dialog.template.general"));

		final Label outputLabel = new Label(groupRelease, SWT.NONE);
		outputLabel.setText(settings.msg("dialog.template.output"));
		output = new Combo(groupRelease, SWT.READ_ONLY);
		output.setItems(settings.getSettings().getValues("profile", "output"));
		output.setVisibleItemCount(10);
		output.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		output.setToolTipText(settings.msg("dialog.template.output.tooltip"));
		new Label(groupRelease, SWT.NONE);
		new Label(groupRelease, SWT.NONE);

		final Label frameskipLabel = new Label(groupRelease, SWT.NONE);
		frameskipLabel.setText(settings.msg("dialog.template.frameskip"));
		frameskip = new Combo(groupRelease, SWT.READ_ONLY);
		frameskip.setItems(settings.getSettings().getValues("profile", "frameskip"));
		frameskip.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		frameskip.setToolTipText(settings.msg("dialog.template.frameskip.tooltip"));
		new Label(groupRelease, SWT.NONE);
		new Label(groupRelease, SWT.NONE);

		final Label scalerLabel = new Label(groupRelease, SWT.NONE);
		scalerLabel.setText(settings.msg("dialog.template.scaler"));
		scaler = new Combo(groupRelease, SWT.READ_ONLY);
		scaler.setItems(settings.getSettings().getValues("profile", "scaler"));
		scaler.setVisibleItemCount(15);
		scaler.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		scaler.setToolTipText(settings.msg("dialog.template.scaler.tooltip"));

		final Label forcedLabel = new Label(groupRelease, SWT.NONE);
		forcedLabel.setText(settings.msg("dialog.template.scalerforced"));
		scaler_forced = new Button(groupRelease, SWT.CHECK);
		scaler_forced.setToolTipText(settings.msg("dialog.template.scalerforced.tooltip"));

		final Label resolutionLabel = new Label(groupRelease, SWT.NONE);
		resolutionLabel.setText(settings.msg("dialog.template.fullscreenresolution"));
		fullresolution = new Combo(groupRelease, SWT.READ_ONLY);
		fullresolution.setItems(settings.getSettings().getValues("profile", "fullresolution"));
		fullresolution.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		fullresolution.setVisibleItemCount(10);
		fullresolution.setToolTipText(settings.msg("dialog.template.fullscreenresolution.tooltip"));
		new Label(groupRelease, SWT.NONE);
		new Label(groupRelease, SWT.NONE);

		final Label windowResLabel = new Label(groupRelease, SWT.NONE);
		windowResLabel.setText(settings.msg("dialog.template.windowresolution"));
		windowresolution = new Combo(groupRelease, SWT.READ_ONLY);
		windowresolution.setItems(settings.getSettings().getValues("profile", "windowresolution"));
		windowresolution.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		windowresolution.setVisibleItemCount(10);
		windowresolution.setToolTipText(settings.msg("dialog.template.windowresolution.tooltip"));
		new Label(groupRelease, SWT.NONE);
		new Label(groupRelease, SWT.NONE);

		final Label fullscreenLabel = new Label(groupRelease, SWT.NONE);
		fullscreenLabel.setText(settings.msg("dialog.template.fullscreen"));
		fullscreen = new Button(groupRelease, SWT.CHECK);
		fullscreen.setToolTipText(settings.msg("dialog.template.fullscreen.tooltip"));
		new Label(groupRelease, SWT.NONE);
		new Label(groupRelease, SWT.NONE);

		final Label doubleBuffLabel = new Label(groupRelease, SWT.NONE);
		doubleBuffLabel.setText(settings.msg("dialog.template.doublebuffering"));
		fulldouble = new Button(groupRelease, SWT.CHECK);
		fulldouble.setToolTipText(settings.msg("dialog.template.doublebuffering.tooltip"));
		new Label(groupRelease, SWT.NONE);
		new Label(groupRelease, SWT.NONE);

		final Label aspectLabel = new Label(groupRelease, SWT.NONE);
		aspectLabel.setText(settings.msg("dialog.template.aspectcorrection"));
		aspect = new Button(groupRelease, SWT.CHECK);
		aspect.setToolTipText(settings.msg("dialog.template.aspectcorrection.tooltip"));
		new Label(groupRelease, SWT.NONE);
		new Label(groupRelease, SWT.NONE);

		final Group groupExpGeneral = new Group(composite_xo, SWT.NONE);
		groupExpGeneral.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false, 1, 3));
		groupExpGeneral.setLayout(new GridLayout(2, false));
		groupExpGeneral.setText(settings.msg("dialog.template.general"));

		final Label autofitLabel = new Label(groupExpGeneral, SWT.NONE);
		autofitLabel.setText(settings.msg("dialog.template.autofit"));
		autofit = new Button(groupExpGeneral, SWT.CHECK);

		final Label pixelshaderLabel = new Label(groupExpGeneral, SWT.NONE);
		pixelshaderLabel.setLayoutData(new GridData());
		pixelshaderLabel.setText(settings.msg("dialog.template.pixelshader"));
		pixelshader = new Combo(groupExpGeneral, SWT.NONE);
		pixelshader.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		pixelshader.setVisibleItemCount(20);

		String[] shaders = FileUtils.getShaders();
		if (shaders != null && shaders.length > 0) {
			pixelshader.setItems(shaders);
			pixelshader.add("none", 0);
		} else {
			pixelshader.setItems(settings.getSettings().getValues("profile", "pixelshader"));
		}

		final Label linewiseLabel = new Label(groupExpGeneral, SWT.NONE);
		linewiseLabel.setText(settings.msg("dialog.template.linewise"));
		linewise = new Button(groupExpGeneral, SWT.CHECK);

		final Label char9Label = new Label(groupExpGeneral, SWT.NONE);
		char9Label.setText(settings.msg("dialog.template.char9"));
		char9 = new Button(groupExpGeneral, SWT.CHECK);

		final Label multiscanLabel = new Label(groupExpGeneral, SWT.NONE);
		multiscanLabel.setText(settings.msg("dialog.template.multiscan"));
		multiscan = new Button(groupExpGeneral, SWT.CHECK);

		final Label cgasnowLabel = new Label(groupExpGeneral, SWT.NONE);
		cgasnowLabel.setText(settings.msg("dialog.template.cgasnow"));
		cgasnow = new Button(groupExpGeneral, SWT.CHECK);

		final Label overscanLabel = new Label(groupExpGeneral, SWT.NONE);
		overscanLabel.setText(settings.msg("dialog.template.overscan"));
		overscan = new Combo(groupExpGeneral, SWT.NONE);
		overscan.setItems(settings.getSettings().getValues("profile", "overscan"));
		overscan.setLayoutData(new GridData(25, SWT.DEFAULT));

		final Label vsyncModeLabel = new Label(groupExpGeneral, SWT.NONE);
		vsyncModeLabel.setText(settings.msg("dialog.template.vsyncmode"));
		vsyncmode = new Combo(groupExpGeneral, SWT.READ_ONLY);
		vsyncmode.setItems(settings.getSettings().getValues("profile", "vsyncmode"));

		final Label vsyncRateLabel = new Label(groupExpGeneral, SWT.NONE);
		vsyncRateLabel.setLayoutData(new GridData());
		vsyncRateLabel.setText(settings.msg("dialog.template.vsyncrate"));
		vsyncrate = new Text(groupExpGeneral, SWT.BORDER);
		vsyncrate.setLayoutData(new GridData(25, SWT.DEFAULT));

		final Label forceRateLabel = new Label(groupExpGeneral, SWT.NONE);
		forceRateLabel.setLayoutData(new GridData());
		forceRateLabel.setText(settings.msg("dialog.template.forcerate"));
		forcerate = new Text(groupExpGeneral, SWT.BORDER);
		forcerate.setLayoutData(new GridData(25, SWT.DEFAULT));

		final Label videoRamLabel = new Label(groupExpGeneral, SWT.NONE);
		videoRamLabel.setText(settings.msg("dialog.template.videoram"));
		videoram = new Combo(groupExpGeneral, SWT.READ_ONLY);
		videoram.setItems(settings.getSettings().getValues("profile", "vmemsize"));
		videoram.setLayoutData(new GridData(25, SWT.DEFAULT));

		final Group groupExpGlide = new Group(composite_xo, SWT.NONE);
		groupExpGlide.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
		groupExpGlide.setLayout(new GridLayout(2, false));
		groupExpGlide.setText(settings.msg("dialog.template.glide"));

		final Label glideLabel = new Label(groupExpGlide, SWT.NONE);
		glideLabel.setText(settings.msg("dialog.template.glide"));
		glide = new Combo(groupExpGlide, SWT.READ_ONLY);
		glide.setItems(settings.getSettings().getValues("profile", "glide"));
		glide.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false));

		final Label glidePortLabel = new Label(groupExpGlide, SWT.NONE);
		glidePortLabel.setText(settings.msg("dialog.template.glideport"));
		glideport = new Text(groupExpGlide, SWT.BORDER);
		glideport.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label lfbGlideLabel = new Label(groupExpGlide, SWT.NONE);
		lfbGlideLabel.setText(settings.msg("dialog.template.lfbglide"));
		lfbGlide = new Combo(groupExpGlide, SWT.READ_ONLY);
		lfbGlide.setItems(settings.getSettings().getValues("profile", "lfbglide"));
		lfbGlide.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label splashLabel = new Label(groupExpGlide, SWT.NONE);
		splashLabel.setText(settings.msg("dialog.template.splash3dfx"));
		splash3dfx = new Button(groupExpGlide, SWT.CHECK);
		
		final Group groupExpVoodoo = new Group(composite_xo, SWT.NONE);
		groupExpVoodoo.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
		groupExpVoodoo.setLayout(new GridLayout(2, false));
		groupExpVoodoo.setText(settings.msg("dialog.template.voodoo"));

		final Label voodooLabel = new Label(groupExpVoodoo, SWT.NONE);
		voodooLabel.setText(settings.msg("dialog.template.voodoo"));
		voodoo = new Combo(groupExpVoodoo, SWT.READ_ONLY);
		voodoo.setItems(settings.getSettings().getValues("profile", "voodoo"));
		voodoo.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false));
		
		final Label voodooMemLabel = new Label(groupExpVoodoo, SWT.NONE);
		voodooMemLabel.setText(settings.msg("dialog.template.voodoomem"));
		voodooMem = new Combo(groupExpVoodoo, SWT.READ_ONLY);
		voodooMem.setItems(settings.getSettings().getValues("profile", "voodoomem"));
		voodooMem.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false));
		
		final Group groupExpPPScaling = new Group(composite_xo, SWT.NONE);
		groupExpPPScaling.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
		groupExpPPScaling.setLayout(new GridLayout(2, false));
		groupExpPPScaling.setText(settings.msg("dialog.template.pixelperfectscaling"));

		final Label sharpnessLabel = new Label(groupExpPPScaling, SWT.NONE);
		sharpnessLabel.setText(settings.msg("dialog.template.surfacenpsharpness"));
		surfaceNpSharpness = new Spinner(groupExpPPScaling, SWT.BORDER);
		surfaceNpSharpness.setMinimum(0);
		surfaceNpSharpness.setMaximum(100);
		surfaceNpSharpness.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false));
		
		final Label collapseLabel = new Label(groupExpPPScaling, SWT.NONE);
		collapseLabel.setText(settings.msg("dialog.template.collapsemode"));
		surfaceCollapseDbl = new Button(groupExpPPScaling, SWT.CHECK);
		surfaceCollapseDbl.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false));
	}

	protected void createGeneralTab(final TabFolder tabFolder) {
		generalTabItem = new TabItem(tabFolder, SWT.NONE);
		generalTabItem.setText(settings.msg("dialog.template.tab.general"));

		final Composite composite_1 = new Composite(tabFolder, SWT.NONE);
		composite_1.setLayout(new GridLayout());
		generalTabItem.setControl(composite_1);

		associationGroup = new Group(composite_1, SWT.NONE);
		associationGroup.setText(settings.msg("dialog.template.association"));
		associationGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		associationGroup.setLayout(new GridLayout(5, false));

		final Label dbversionLabel = new Label(associationGroup, SWT.NONE);
		dbversionLabel.setText(settings.msg("dialog.template.dosboxversion"));
		dbversion = new Combo(associationGroup, SWT.READ_ONLY);
		dbversion.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		dbversion.setVisibleItemCount(20);

		setButton = new Button(associationGroup, SWT.NONE);
		setButton.setText(settings.msg("dialog.template.set"));
		setButton.setToolTipText(settings.msg("dialog.template.set.tooltip"));
		setButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				doPerformDosboxConfAction(DosboxConfAction.SET);
			}
		});

		switchButton = new Button(associationGroup, SWT.NONE);
		switchButton.setText(settings.msg("dialog.template.switch"));
		switchButton.setToolTipText(settings.msg("dialog.template.switch.tooltip"));
		switchButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				doPerformDosboxConfAction(DosboxConfAction.SWITCH);
			}
		});

		dbversion.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				setButton.setEnabled(true);
				switchButton.setEnabled(true);
			}
		});

		reloadButton = new Button(associationGroup, SWT.NONE);
		reloadButton.setText(settings.msg("dialog.template.reloadsettings"));
		reloadButton.setToolTipText(settings.msg("dialog.template.reloadsettings.tooltip"));
		reloadButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent event) {
				doPerformDosboxConfAction(DosboxConfAction.RELOAD);
			}
		});

		miscGroup = new Group(composite_1, SWT.NONE);
		miscGroup.setText(settings.msg("dialog.template.miscellaneous"));
		miscGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		miscGroup.setLayout(new GridLayout(3, false));

		new Label(miscGroup, SWT.NONE);
		final Label activeLabel = new Label(miscGroup, SWT.NONE);
		activeLabel.setText(settings.msg("dialog.template.active"));
		final Label inactiveLabel = new Label(miscGroup, SWT.NONE);
		inactiveLabel.setText(settings.msg("dialog.template.inactive"));

		final Label priorityLabel = new Label(miscGroup, SWT.NONE);
		priorityLabel.setText(settings.msg("dialog.template.priority"));
		priority_active = new Combo(miscGroup, SWT.READ_ONLY);
		priority_active.setItems(settings.getSettings().getValues("profile", "priority_active"));
		priority_active.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
		priority_active.setToolTipText(settings.msg("dialog.template.priority.tooltip"));
		priority_inactive = new Combo(miscGroup, SWT.READ_ONLY);
		priority_inactive.setItems(settings.getSettings().getValues("profile", "priority_inactive"));
		priority_inactive.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
		priority_inactive.setToolTipText(settings.msg("dialog.template.priority.tooltip"));

		final Label waitOnErrorLabel = new Label(miscGroup, SWT.NONE);
		waitOnErrorLabel.setText(settings.msg("dialog.template.waitonerror"));
		waitonerror = new Button(miscGroup, SWT.CHECK);
		waitonerror.setToolTipText(settings.msg("dialog.template.waitonerror.tooltip"));
		new Label(miscGroup, SWT.NONE);

		final Label exitLabel = new Label(miscGroup, SWT.NONE);
		exitLabel.setText(settings.msg("dialog.template.exitafterwards"));
		exit = new Button(miscGroup, SWT.CHECK);
		new Label(miscGroup, SWT.NONE);

		final Label languageFileLabel = new Label(miscGroup, SWT.NONE);
		languageFileLabel.setLayoutData(new GridData());
		languageFileLabel.setText(settings.msg("dialog.template.languagefile"));
		language = new Text(miscGroup, SWT.BORDER);
		language.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
		language.setToolTipText(settings.msg("dialog.template.languagefile.tooltip"));

		final Label capturesLabel = new Label(miscGroup, SWT.NONE);
		capturesLabel.setLayoutData(new GridData());
		capturesLabel.setText(settings.msg("dialog.template.captures"));
		captures = new Text(miscGroup, SWT.BORDER);
		captures.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
		captures.setEditable(false);
		captures.setToolTipText(settings.msg("dialog.template.captures.tooltip"));

		final Label configFileLabel = new Label(miscGroup, SWT.NONE);
		configFileLabel.setText(settings.msg("dialog.profile.configfile"));
		config_file = new Text(miscGroup, SWT.BORDER);
		config_file.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
		config_file.setEditable(false);
		config_file.setText(result instanceof Template ? FileUtils.constructCanonicalTemplateFileLocation(((Template)result).getId()).getPath(): SettingsDialog.confFilenames[0]);
	}

	protected void createInfoTab(final TabFolder tabFolder) {
		infoTabItem = new TabItem(tabFolder, SWT.NONE);
		infoTabItem.setText(settings.msg("dialog.template.tab.info"));

		final Composite composite = new Composite(tabFolder, SWT.NONE);
		composite.setLayout(new GridLayout(2, false));
		infoTabItem.setControl(composite);

		final Label titleLabel = new Label(composite, SWT.NONE);
		titleLabel.setText(settings.msg("dialog.template.title"));
		title = new Text(composite, SWT.BORDER);
		title.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		final Label defaultLabel = new Label(composite, SWT.NONE);
		defaultLabel.setText(settings.msg("dialog.template.default"));
		defaultButton = new Button(composite, SWT.CHECK);
	}

	protected void selectSettingsByConfiguration(Conf conf) {
		SectionsWrapper sections = conf.getSettings();
		setFieldIfEnabled(sections, "sdl", "priority", priority_active, priority_inactive);
		setFieldIfEnabled(sections, "sdl", "waitonerror", waitonerror);
		setFieldIfEnabled(sections, "dosbox", "language", language);
		setFieldIfEnabled(settings.msg("dialog.profile.automatic"), false, captures);
		setFieldIfEnabled(sections, "sdl", "output", output);
		setFieldIfEnabled(sections, "render", "frameskip", frameskip);
		if (sections.isConflictingValue("render", "scaler")) {
			setFieldIfEnabled(sections, "render", "scaler", scaler);
			setFieldIfEnabled(null, true, scaler_forced);
		} else {
			String value = sections.getValue("render", "scaler");
			if (value.endsWith(" forced")) {
				setFieldIfEnabled(value.substring(0, value.length() - 7), false, scaler);
				setFieldIfEnabled(String.valueOf(true), false, scaler_forced);
			} else {
				setFieldIfEnabled(value, false, scaler);
				setFieldIfEnabled(String.valueOf(false), false, scaler_forced);
			}
		}
		setFieldIfEnabled(sections, "sdl", "fullscreen", fullscreen);
		setFieldIfEnabled(sections, "sdl", "fulldouble", fulldouble);
		setFieldIfEnabled(sections, "sdl", "fullresolution", fullresolution);
		setFieldIfEnabled(sections, "sdl", "windowresolution", windowresolution);
		setFieldIfEnabled(sections, "render", "aspect", aspect);
		setFieldIfEnabled(sections, "dosbox", "machine", machine);
		setFieldIfEnabled(sections, "cpu", "cputype", cpu_type);
		setFieldIfEnabled(sections, "cpu", "core", core);
		setFieldIfEnabled(sections, "cpu", "cycles", cycles);
		setFieldIfEnabled(sections, "cpu", "cycleup", cycles_up);
		setFieldIfEnabled(sections, "cpu", "cycledown", cycles_down);
		setFieldIfEnabled(sections, "dosbox", "memsize", memsize);
		setFieldIfEnabled(sections, "dos", "xms", xms);
		setFieldIfEnabled(sections, "dos", "ems", ems);
		setFieldIfEnabled(sections, "dos", "umb", umb);
		setFieldIfEnabled(sections, "mixer", "nosound", nosound);
		setFieldIfEnabled(sections, "mixer", "rate", rate);
		setFieldIfEnabled(sections, "mixer", "blocksize", blocksize);
		setFieldIfEnabled(sections, "mixer", "prebuffer", prebuffer);
		if (sections.hasValue("midi", "intelligent")) {
			if (sections.isConflictingValue("midi", "mpu401") || sections.isConflictingValue("midi", "intelligent")) {
				setFieldIfEnabled(null, true, mpu401);
			} else {
				setFieldIfEnabled(sections.getBooleanValue("midi", "mpu401") ? (sections.getBooleanValue("midi", "intelligent") ? "intelligent": "uart"): "none", false, mpu401);
			}
		} else {
			setFieldIfEnabled(sections, "midi", "mpu401", mpu401);
		}
		setFieldIfEnabled(sections, "midi", "device", "mididevice", midi_device);
		setFieldIfEnabled(sections, "midi", "config", "midiconfig", midi_config);
		setFieldIfEnabled(sections, "sblaster", "type", "sbtype", sbtype);
		setFieldIfEnabled(sections, "sblaster", "oplmode", oplmode);
		setFieldIfEnabled(sections, "sblaster", "oplrate", oplrate);
		setFieldIfEnabled(sections, "sblaster", "oplemu", oplemu);
		setFieldIfEnabled(sections, "sblaster", "base", "sbbase", sbbase);
		setFieldIfEnabled(sections, "sblaster", "irq", irq);
		setFieldIfEnabled(sections, "sblaster", "dma", dma);
		setFieldIfEnabled(sections, "sblaster", "hdma", hdma);
		setFieldIfEnabled(sections, "sblaster", "mixer", "sbmixer", sbmixer);
		setFieldIfEnabled(sections, "gus", "gus", gus);
		setFieldIfEnabled(sections, "gus", "rate", "gusrate", gusrate);
		setFieldIfEnabled(sections, "gus", "base", "gusbase", gusbase);
		setFieldIfEnabled(sections, "gus", "irq1", "gusirq", gusirq1);
		setFieldIfEnabled(sections, "gus", "irq2", "gusirq", gusirq2);
		setFieldIfEnabled(sections, "gus", "dma1", "gusdma", gusdma1);
		setFieldIfEnabled(sections, "gus", "dma2", "gusdma", gusdma2);
		setFieldIfEnabled(sections, "gus", "ultradir", ultradir);
		setFieldIfEnabled(sections, "speaker", "pcspeaker", pcspeaker);
		setFieldIfEnabled(sections, "speaker", "pcrate", pcrate);
		setFieldIfEnabled(sections, "speaker", "tandy", tandy);
		setFieldIfEnabled(sections, "speaker", "tandyrate", tandyrate);
		setFieldIfEnabled(sections, "speaker", "disney", disney);
		setFieldIfEnabled(sections, "sdl", "autolock", autolock);
		setFieldIfEnabled(sections, "sdl", "sensitivity", sensitivity);
		setFieldIfEnabled(sections, "sdl", "usescancodes", usescancodes);
		setFieldIfEnabled(sections, "sdl", "mapperfile", mapperfile);
		setFieldIfEnabled(sections, "dos", "keyboardlayout", keyboard_layout);
		if (sections.hasValue("joystick", "joysticktype")) {
			setFieldIfEnabled(sections, "joystick", "joysticktype", joysticktype);
			setFieldIfEnabled(sections, "joystick", "timed", timed);
			setFieldIfEnabled(sections, "joystick", "autofire", autofire);
			setFieldIfEnabled(sections, "joystick", "swap34", swap34);
			setFieldIfEnabled(sections, "joystick", "buttonwrap", buttonwrap);
		} else {
			setFieldIfEnabled(sections, "bios", "joysticktype", joysticktype);
		}
		setFieldIfEnabled(sections, "serial", "serial1", serial1);
		setFieldIfEnabled(sections, "serial", "serial2", serial2);
		setFieldIfEnabled(sections, "serial", "serial3", serial3);
		setFieldIfEnabled(sections, "serial", "serial4", serial4);
		setFieldIfEnabled(sections, "ipx", "ipx", ipx);
		ipxnet.setEnabled(ipx.getSelection());

		setFieldIfEnabled(sections, "render", "autofit", autofit);
		setFieldIfEnabled(sections, "sdl", "pixelshader", pixelshader);
		setFieldIfEnabled(sections, "render", "linewise", linewise);
		setFieldIfEnabled(sections, "render", "char9", char9);
		setFieldIfEnabled(sections, "render", "multiscan", multiscan);
		setFieldIfEnabled(sections, "cpu", "cgasnow", cgasnow);
		setFieldIfEnabled(sections, "sdl", "overscan", overscan);
		setFieldIfEnabled(sections, "vsync", "vsyncmode", vsyncmode);
		setFieldIfEnabled(sections, "vsync", "vsyncrate", vsyncrate);
		setFieldIfEnabled(sections, "cpu", "forcerate", forcerate);
		setFieldIfEnabled(sections, "dosbox", "vmemsize", videoram);
		setFieldIfEnabled(sections, "glide", "glide", glide);
		setFieldIfEnabled(sections, "glide", "port", "grport", glideport);
		setFieldIfEnabled(sections, "glide", "lfb", lfbGlide);
		setFieldIfEnabled(sections, "glide", "splash", splash3dfx);
		setFieldIfEnabled(sections, "pci", "voodoo", voodoo);
		setFieldIfEnabled(sections, "pci", "voodoomem", voodooMem);
		setFieldIfEnabled(sections, "sdl", "surfacenp-sharpness", surfaceNpSharpness);
		setFieldIfEnabled(sections, "sdl", "surface-collapse-dbl", surfaceCollapseDbl);
		setFieldIfEnabled(sections, "dosbox", "memsizekb", memsizeKB);
		setFieldIfEnabled(sections, "dosbox", "memalias", memalias);
		setFieldIfEnabled(sections, "mixer", "swapstereo", swapstereo);
		setOnOffFieldIfEnabled(sections, "midi", "fluid.driver", driverFluid);
		setOnOffFieldIfEnabled(sections, "midi", "fluid.soundfont", soundfontFluid);
		setOnOffFieldIfEnabled(sections, "midi", "fluid.samplerate", samplerateFluid);
		setOnOffFieldIfEnabled(sections, "midi", "fluid.gain", gainFluid);
		setFieldIfEnabled(sections, "sblaster", "hardwarebase", hardwareaddresssbbase);
		setFieldIfEnabled(sections, "sblaster", "goldplay", goldplay);
		setOnOffFieldIfEnabled(sections, "midi", "mt32.romdir", romDirMT32);
		setOnOffFieldIfEnabled(sections, "midi", "mt32.chunk", chunkMT32);
		setOnOffFieldIfEnabled(sections, "midi", "mt32.prebuffer", prebufferMT32);
		setOnOffFieldIfEnabled(sections, "midi", "mt32.reverse.stereo", swapstereoMT32);
		setOnOffFieldIfEnabled(sections, "midi", "mt32.verbose", loggingMT32);
		setOnOffFieldIfEnabled(sections, "midi", "mt32.thread", multithreadMT32);
		setFieldIfEnabled(sections, "midi", "mt32.dac", dacMT32);
		setFieldIfEnabled(sections, "midi", "mt32.analog", analogMT32);
		setFieldIfEnabled(sections, "midi", "mt32.reverb.mode", reverbmodeMT32);
		setFieldIfEnabled(sections, "midi", "mt32.reverb.time", reverbtimeMT32);
		setFieldIfEnabled(sections, "midi", "mt32.reverb.level", reverblevelMT32);
		setFieldIfEnabled(sections, "midi", "mt32.partials", partialsMT32);
		setOnOffFieldIfEnabled(sections, "speaker", "ps1audio", ps1);
		setFieldIfEnabled(sections, "speaker", "ps1audiorate", ps1rate);
		setFieldIfEnabled(sections, "innova", "innova", innova);
		setFieldIfEnabled(sections, "innova", "samplerate", innovarate);
		setFieldIfEnabled(sections, "innova", "sidbase", innovabase);
		setFieldIfEnabled(sections, "innova", "quality", innovaquality);
		setFieldIfEnabled(sections, "dos", "int33", int33);
		setFieldIfEnabled(sections, "dos", "biosps2", biosps2);
		setFieldIfEnabled(sections, "keyboard", "aux", aux);
		setFieldIfEnabled(sections, "keyboard", "auxdevice", auxdevice);
		setFieldIfEnabled(sections, "dos", "files", files);
		setFieldIfEnabled(sections, "cpu", "isapnpbios", isapnpbios);
		setFieldIfEnabled(sections, "ide, primary", "enable", ide1);
		setFieldIfEnabled(sections, "ide, secondary", "enable", ide2);
		setFieldIfEnabled(sections, "ide, tertiary", "enable", ide3);
		setFieldIfEnabled(sections, "ide, quaternary", "enable", ide4);
		setFieldIfEnabled(sections, "dos", "automount", automount);
		setFieldIfEnabled(sections, "printer", "printer", printer);
		setFieldIfEnabled(sections, "printer", "dpi", printerdpi);
		setFieldIfEnabled(sections, "printer", "width", printerwidth);
		setFieldIfEnabled(sections, "printer", "height", printerheight);
		setFieldIfEnabled(sections, "printer", "printoutput", printeroutput);
		setFieldIfEnabled(sections, "printer", "multipage", printermultipage);
		setFieldIfEnabled(sections, "printer", "docpath", printerdocpath);
		setFieldIfEnabled(sections, "printer", "timeout", printertimeout);
		setFieldIfEnabled(sections, "parallel", "parallel1", parallel1);
		setFieldIfEnabled(sections, "parallel", "parallel2", parallel2);
		setFieldIfEnabled(sections, "parallel", "parallel3", parallel3);
		setFieldIfEnabled(sections, "parallel", "dongle", dongle);
		setFieldIfEnabled(sections, "ne2000", "ne2000", ne2000);
		setFieldIfEnabled(sections, "ne2000", "nicbase", ne2000base);
		setFieldIfEnabled(sections, "ne2000", "nicirq", ne2000irq);
		setFieldIfEnabled(sections, "ne2000", "macaddr", ne2000macaddress);
		setFieldIfEnabled(sections, "ne2000", "realnic", ne2000realnic);

		// autoexec settings
		setFieldIfEnabled(String.valueOf(conf.getAutoexec().isExit()), Conf.isConflictingValue(conf.getAutoexec().isExit()), exit);
		setFieldIfEnabled(conf.getAutoexec().getMixer(), Conf.isConflictingValue(conf.getAutoexec().getMixer()), mixer_config);
		setFieldIfEnabled(conf.getAutoexec().getKeyb(), Conf.isConflictingValue(conf.getAutoexec().getKeyb()), keyb);
		setFieldIfEnabled(conf.getAutoexec().getIpxnet(), Conf.isConflictingValue(conf.getAutoexec().getIpxnet()), ipxnet);
		for (int i = 0; i < Autoexec.SECTIONS; i++)
			setFieldIfEnabled(StringRelatedUtils.stringToTextArea(conf.getAutoexec().getCustomSection(i), customCommands[i].getLineDelimiter(), PlatformUtils.EOLN),
				Conf.isConflictingValue(conf.getAutoexec().getCustomSection(i)), customCommands[i]);

		if (!isMultiEdit()) {
			mountingpoints.setItems(conf.getAutoexec().getMountingpoints());
			dosExpandItem.setExpanded(!conf.getAutoexec().isBooter());
			booterExpandItem.setExpanded(conf.getAutoexec().isBooter());
		}
	}

	protected void updateConfigurationBySettings(Conf conf) {
		boolean singleEdit = !isMultiEdit();
		conf.updateValue("sdl", "priority", priority_active.getText() + "," + priority_inactive.getText(), singleEdit || ((Boolean)priority_active.getData() || (Boolean)priority_inactive.getData()));
		conf.updateValue("sdl", "waitonerror", String.valueOf(waitonerror.getSelection()), singleEdit || (Boolean)waitonerror.getData());
		conf.updateValue("dosbox", "language", language.getText(), singleEdit || (Boolean)language.getData());
		conf.updateValue("sdl", "output", output.getText(), singleEdit || (Boolean)output.getData());
		conf.updateValue("render", "frameskip", frameskip.getText(), singleEdit || (Boolean)frameskip.getData());
		conf.updateScalerValue(scaler.getText(), scaler_forced.getSelection(), singleEdit || (Boolean)scaler.getData() || (Boolean)scaler_forced.getData());
		conf.updateValue("sdl", "fullscreen", String.valueOf(fullscreen.getSelection()), singleEdit || (Boolean)fullscreen.getData());
		conf.updateValue("sdl", "fulldouble", String.valueOf(fulldouble.getSelection()), singleEdit || (Boolean)fulldouble.getData());
		conf.updateValue("sdl", "fullresolution", fullresolution.getText(), singleEdit || (Boolean)fullresolution.getData());
		conf.updateValue("sdl", "windowresolution", windowresolution.getText(), singleEdit || (Boolean)windowresolution.getData());
		conf.updateValue("render", "aspect", String.valueOf(aspect.getSelection()), singleEdit || (Boolean)aspect.getData());
		conf.updateValue("dosbox", "machine", machine.getText(), singleEdit || (Boolean)machine.getData());
		conf.updateValue("cpu", "cputype", cpu_type.getText(), singleEdit || (Boolean)cpu_type.getData());
		conf.updateValue("cpu", "core", core.getText(), singleEdit || (Boolean)core.getData());
		conf.updateValue("cpu", "cycles", cycles.getText(), singleEdit || (Boolean)cycles.getData());
		conf.updateValue("cpu", "cycleup", cycles_up.getText(), singleEdit || (Boolean)cycles_up.getData());
		conf.updateValue("cpu", "cycledown", cycles_down.getText(), singleEdit || (Boolean)cycles_down.getData());
		conf.updateValue("dosbox", "memsize", memsize.getText(), singleEdit || (Boolean)memsize.getData());
		conf.updateValue("dos", "xms", String.valueOf(xms.getSelection()), singleEdit || (Boolean)xms.getData());
		conf.updateValue("dos", "ems", ems.getText(), singleEdit || (Boolean)ems.getData());
		conf.updateValue("dos", "umb", umb.getText(), singleEdit || (Boolean)umb.getData());
		conf.updateValue("mixer", "nosound", String.valueOf(nosound.getSelection()), singleEdit || (Boolean)nosound.getData());
		conf.updateValue("mixer", "rate", rate.getText(), singleEdit || (Boolean)rate.getData());
		conf.updateValue("mixer", "blocksize", blocksize.getText(), singleEdit || (Boolean)blocksize.getData());
		conf.updateValue("mixer", "prebuffer", prebuffer.getText(), singleEdit || (Boolean)prebuffer.getData());
		conf.updateMidiValue(mpu401.getText(), singleEdit || (Boolean)mpu401.getData());
		conf.updateValue("midi", "device", "mididevice", midi_device.getText(), singleEdit || (Boolean)midi_device.getData());
		conf.updateValue("midi", "config", "midiconfig", midi_config.getText(), singleEdit || (Boolean)midi_config.getData());
		conf.updateValue("sblaster", "type", "sbtype", sbtype.getText(), singleEdit || (Boolean)sbtype.getData());
		conf.updateValue("sblaster", "oplmode", oplmode.getText(), singleEdit || (Boolean)oplmode.getData());
		conf.updateValue("sblaster", "oplrate", oplrate.getText(), singleEdit || (Boolean)oplrate.getData());
		conf.updateValue("sblaster", "oplemu", oplemu.getText(), singleEdit || (Boolean)oplemu.getData());
		conf.updateValue("sblaster", "base", "sbbase", sbbase.getText(), singleEdit || (Boolean)sbbase.getData());
		conf.updateValue("sblaster", "irq", irq.getText(), singleEdit || (Boolean)irq.getData());
		conf.updateValue("sblaster", "dma", dma.getText(), singleEdit || (Boolean)dma.getData());
		conf.updateValue("sblaster", "hdma", hdma.getText(), singleEdit || (Boolean)hdma.getData());
		conf.updateValue("sblaster", "mixer", "sbmixer", String.valueOf(sbmixer.getSelection()), singleEdit || (Boolean)sbmixer.getData());
		conf.updateValue("gus", "gus", String.valueOf(gus.getSelection()), singleEdit || (Boolean)gus.getData());
		conf.updateValue("gus", "rate", "gusrate", gusrate.getText(), singleEdit || (Boolean)gusrate.getData());
		conf.updateValue("gus", "base", "gusbase", gusbase.getText(), singleEdit || (Boolean)gusbase.getData());
		conf.updateValue("gus", "irq1", "gusirq", gusirq1.getText(), singleEdit || (Boolean)gusirq1.getData());
		conf.updateValue("gus", "irq2", gusirq2.getText(), singleEdit || (Boolean)gusirq2.getData());
		conf.updateValue("gus", "dma1", "gusdma", gusdma1.getText(), singleEdit || (Boolean)gusdma1.getData());
		conf.updateValue("gus", "dma2", gusdma2.getText(), singleEdit || (Boolean)gusdma2.getData());
		conf.updateValue("gus", "ultradir", ultradir.getText(), singleEdit || (Boolean)ultradir.getData());
		conf.updateValue("speaker", "pcspeaker", String.valueOf(pcspeaker.getSelection()), singleEdit || (Boolean)pcspeaker.getData());
		conf.updateValue("speaker", "pcrate", pcrate.getText(), singleEdit || (Boolean)pcrate.getData());
		conf.updateValue("speaker", "tandy", tandy.getText(), singleEdit || (Boolean)tandy.getData());
		conf.updateValue("speaker", "tandyrate", tandyrate.getText(), singleEdit || (Boolean)tandyrate.getData());
		conf.updateValue("speaker", "disney", String.valueOf(disney.getSelection()), singleEdit || (Boolean)disney.getData());
		conf.updateValue("sdl", "autolock", String.valueOf(autolock.getSelection()), singleEdit || (Boolean)autolock.getData());
		conf.updateValue("sdl", "sensitivity", sensitivity.getText(), singleEdit || (Boolean)sensitivity.getData());
		conf.updateValue("sdl", "usescancodes", String.valueOf(usescancodes.getSelection()), singleEdit || (Boolean)usescancodes.getData());
		conf.updateValue("sdl", "mapperfile", mapperfile.getText(), singleEdit || (Boolean)mapperfile.getData());
		conf.updateValue("dos", "keyboardlayout", keyboard_layout.getText(), singleEdit || (Boolean)keyboard_layout.getData());
		conf.updateJoystickValue(joysticktype.getText(), timed.getSelection(), autofire.getSelection(), swap34.getSelection(), buttonwrap.getSelection(), singleEdit || (Boolean)joysticktype.getData(),
			singleEdit || (Boolean)timed.getData(), singleEdit || (Boolean)autofire.getData(), singleEdit || (Boolean)swap34.getData(), singleEdit || (Boolean)buttonwrap.getData());
		conf.updateValue("serial", "serial1", serial1.getText(), singleEdit || (Boolean)serial1.getData());
		conf.updateValue("serial", "serial2", serial2.getText(), singleEdit || (Boolean)serial2.getData());
		conf.updateValue("serial", "serial3", serial3.getText(), singleEdit || (Boolean)serial3.getData());
		conf.updateValue("serial", "serial4", serial4.getText(), singleEdit || (Boolean)serial4.getData());
		conf.updateValue("ipx", "ipx", String.valueOf(ipx.getSelection()), singleEdit || (Boolean)ipx.getData());

		conf.updateValue("render", "autofit", String.valueOf(autofit.getSelection()), singleEdit || (Boolean)autofit.getData());
		conf.updateValue("sdl", "pixelshader", pixelshader.getText(), singleEdit || (Boolean)pixelshader.getData());
		conf.updateValue("render", "linewise", String.valueOf(linewise.getSelection()), singleEdit || (Boolean)linewise.getData());
		conf.updateValue("render", "char9", String.valueOf(char9.getSelection()), singleEdit || (Boolean)char9.getData());
		conf.updateValue("render", "multiscan", String.valueOf(multiscan.getSelection()), singleEdit || (Boolean)multiscan.getData());
		conf.updateValue("cpu", "cgasnow", String.valueOf(cgasnow.getSelection()), singleEdit || (Boolean)cgasnow.getData());
		conf.updateValue("sdl", "overscan", overscan.getText(), singleEdit || (Boolean)overscan.getData());
		conf.updateValue("vsync", "vsyncmode", vsyncmode.getText(), singleEdit || (Boolean)vsyncmode.getData());
		conf.updateValue("vsync", "vsyncrate", vsyncrate.getText(), singleEdit || (Boolean)vsyncrate.getData());
		conf.updateValue("cpu", "forcerate", forcerate.getText(), singleEdit || (Boolean)forcerate.getData());
		conf.updateValue("dosbox", "vmemsize", videoram.getText(), singleEdit || (Boolean)videoram.getData());
		conf.updateValue("glide", "glide", glide.getText(), singleEdit || (Boolean)glide.getData());
		conf.updateValue("glide", "port", "grport", glideport.getText(), singleEdit || (Boolean)glideport.getData());
		conf.updateValue("glide", "lfb", lfbGlide.getText(), singleEdit || (Boolean)lfbGlide.getData());
		conf.updateValue("glide", "splash", String.valueOf(splash3dfx.getSelection()), singleEdit || (Boolean)splash3dfx.getData());
		conf.updateValue("pci", "voodoo", voodoo.getText(), singleEdit || (Boolean)voodoo.getData());
		conf.updateValue("pci", "voodoomem", voodooMem.getText(), singleEdit || (Boolean)voodooMem.getData());
		conf.updateValue("sdl", "surfacenp-sharpness", surfaceNpSharpness.getText(), singleEdit || (Boolean)surfaceNpSharpness.getData());
		conf.updateValue("sdl", "surface-collapse-dbl", String.valueOf(surfaceCollapseDbl.getSelection()), singleEdit || (Boolean)surfaceCollapseDbl.getData());
		conf.updateValue("dosbox", "memsizekb", memsizeKB.getText(), singleEdit || (Boolean)memsizeKB.getData());
		conf.updateValue("dosbox", "memalias", memalias.getText(), singleEdit || (Boolean)memalias.getData());
		conf.updateValue("mixer", "swapstereo", String.valueOf(swapstereo.getSelection()), singleEdit || (Boolean)swapstereo.getData());
		conf.updateValue("midi", "fluid.driver", driverFluid.getText(), singleEdit || (Boolean)driverFluid.getData());
		conf.updateValue("midi", "fluid.soundfont", soundfontFluid.getText(), singleEdit || (Boolean)soundfontFluid.getData());
		conf.updateValue("midi", "fluid.samplerate", samplerateFluid.getText(), singleEdit || (Boolean)samplerateFluid.getData());
		conf.updateValue("midi", "fluid.gain", gainFluid.getText(), singleEdit || (Boolean)gainFluid.getData());
		conf.updateValue("sblaster", "hardwarebase", hardwareaddresssbbase.getText(), singleEdit || (Boolean)hardwareaddresssbbase.getData());
		conf.updateValue("sblaster", "goldplay", String.valueOf(goldplay.getSelection()), singleEdit || (Boolean)goldplay.getData());
		conf.updateValue("midi", "mt32.romdir", romDirMT32.getText(), singleEdit || (Boolean)romDirMT32.getData());
		conf.updateValue("midi", "mt32.reverse.stereo", String.valueOf(swapstereoMT32.getSelection()), singleEdit || (Boolean)swapstereoMT32.getData());
		conf.updateValue("midi", "mt32.verbose", String.valueOf(loggingMT32.getSelection()), singleEdit || (Boolean)loggingMT32.getData());
		conf.updateValue("midi", "mt32.thread", String.valueOf(multithreadMT32.getSelection()), singleEdit || (Boolean)multithreadMT32.getData());
		conf.updateValue("midi", "mt32.chunk", chunkMT32.getText(), singleEdit || (Boolean)chunkMT32.getData());
		conf.updateValue("midi", "mt32.prebuffer", prebufferMT32.getText(), singleEdit || (Boolean)prebufferMT32.getData());
		conf.updateValue("midi", "mt32.dac", dacMT32.getText(), singleEdit || (Boolean)dacMT32.getData());
		conf.updateValue("midi", "mt32.analog", analogMT32.getText(), singleEdit || (Boolean)analogMT32.getData());
		conf.updateValue("midi", "mt32.reverb.mode", reverbmodeMT32.getText(), singleEdit || (Boolean)reverbmodeMT32.getData());
		conf.updateValue("midi", "mt32.reverb.time", reverbtimeMT32.getText(), singleEdit || (Boolean)reverbtimeMT32.getData());
		conf.updateValue("midi", "mt32.reverb.level", reverblevelMT32.getText(), singleEdit || (Boolean)reverblevelMT32.getData());
		conf.updateValue("midi", "mt32.partials", partialsMT32.getText(), singleEdit || (Boolean)partialsMT32.getData());
		conf.updateValue("speaker", "ps1audio", StringRelatedUtils.onOffValue(ps1.getSelection()), singleEdit || (Boolean)ps1.getData());
		conf.updateValue("speaker", "ps1audiorate", ps1rate.getText(), singleEdit || (Boolean)ps1rate.getData());
		conf.updateValue("innova", "innova", String.valueOf(innova.getSelection()), singleEdit || (Boolean)innova.getData());
		conf.updateValue("innova", "samplerate", innovarate.getText(), singleEdit || (Boolean)innovarate.getData());
		conf.updateValue("innova", "sidbase", innovabase.getText(), singleEdit || (Boolean)innovabase.getData());
		conf.updateValue("innova", "quality", innovaquality.getText(), singleEdit || (Boolean)innovaquality.getData());
		conf.updateValue("dos", "int33", String.valueOf(int33.getSelection()), singleEdit || (Boolean)int33.getData());
		conf.updateValue("dos", "biosps2", String.valueOf(biosps2.getSelection()), singleEdit || (Boolean)biosps2.getData());
		conf.updateValue("keyboard", "aux", String.valueOf(aux.getSelection()), singleEdit || (Boolean)aux.getData());
		conf.updateValue("keyboard", "auxdevice", auxdevice.getText(), singleEdit || (Boolean)auxdevice.getData());
		conf.updateValue("dos", "files", files.getText(), singleEdit || (Boolean)files.getData());
		conf.updateValue("cpu", "isapnpbios", String.valueOf(isapnpbios.getSelection()), singleEdit || (Boolean)isapnpbios.getData());
		conf.updateValue("ide, primary", "enable", String.valueOf(ide1.getSelection()), singleEdit || (Boolean)ide1.getData());
		conf.updateValue("ide, secondary", "enable", String.valueOf(ide2.getSelection()), singleEdit || (Boolean)ide2.getData());
		conf.updateValue("ide, tertiary", "enable", String.valueOf(ide3.getSelection()), singleEdit || (Boolean)ide3.getData());
		conf.updateValue("ide, quaternary", "enable", String.valueOf(ide4.getSelection()), singleEdit || (Boolean)ide4.getData());
		conf.updateValue("dos", "automount", String.valueOf(automount.getSelection()), singleEdit || (Boolean)automount.getData());
		conf.updateValue("printer", "printer", String.valueOf(printer.getSelection()), singleEdit || (Boolean)printer.getData());
		conf.updateValue("printer", "dpi", printerdpi.getText(), singleEdit || (Boolean)printerdpi.getData());
		conf.updateValue("printer", "width", printerwidth.getText(), singleEdit || (Boolean)printerwidth.getData());
		conf.updateValue("printer", "height", printerheight.getText(), singleEdit || (Boolean)printerheight.getData());
		conf.updateValue("printer", "printoutput", printeroutput.getText(), singleEdit || (Boolean)printeroutput.getData());
		conf.updateValue("printer", "multipage", String.valueOf(printermultipage.getSelection()), singleEdit || (Boolean)printermultipage.getData());
		conf.updateValue("printer", "docpath", printerdocpath.getText(), singleEdit || (Boolean)printerdocpath.getData());
		conf.updateValue("printer", "timeout", printertimeout.getText(), singleEdit || (Boolean)printertimeout.getData());
		conf.updateValue("parallel", "parallel1", parallel1.getText(), singleEdit || (Boolean)parallel1.getData());
		conf.updateValue("parallel", "parallel2", parallel2.getText(), singleEdit || (Boolean)parallel2.getData());
		conf.updateValue("parallel", "parallel3", parallel3.getText(), singleEdit || (Boolean)parallel3.getData());
		conf.updateValue("parallel", "dongle", String.valueOf(dongle.getSelection()), singleEdit || (Boolean)dongle.getData());
		conf.updateValue("ne2000", "ne2000", String.valueOf(ne2000.getSelection()), singleEdit || (Boolean)ne2000.getData());
		conf.updateValue("ne2000", "nicbase", ne2000base.getText(), singleEdit || (Boolean)ne2000base.getData());
		conf.updateValue("ne2000", "nicirq", ne2000irq.getText(), singleEdit || (Boolean)ne2000irq.getData());
		conf.updateValue("ne2000", "macaddr", ne2000macaddress.getText(), singleEdit || (Boolean)ne2000macaddress.getData());
		conf.updateValue("ne2000", "realnic", ne2000realnic.getText(), singleEdit || (Boolean)ne2000realnic.getData());

		// autoexec settings
		if (singleEdit) {
			String[] customSections = new String[customCommands.length];
			for (int i = 0; i < customCommands.length; i++)
				customSections[i] = StringRelatedUtils.textAreaToString(customCommands[i].getText(), customCommands[i].getLineDelimiter(), PlatformUtils.EOLN);
			conf.setAutoexecSettingsForTemplate(exit.getSelection(), mixer_config.getText(), keyb.getText(), ipx.getSelection() ? ipxnet.getText(): "", booterExpandItem.getExpanded(), customSections);
		}
	}

	protected void doAddNativeCommand() {
		final EditNativeCommandDialog cmdDialog = new EditNativeCommandDialog(shell);
		NativeCommand cmd = (NativeCommand)cmdDialog.open();
		if (cmd != null) {
			int nr = nativeCommands.getSelectionIndex() + 1;
			multiProfileList.get(0).getNativeCommandsList().add(nr, cmd);
			updateNativeCommands(nr);
		}
	}

	protected void doEditNativeCommand() {
		int sel = nativeCommands.getSelectionIndex();
		if (sel != -1) {
			NativeCommand cmd = multiProfileList.get(0).getNativeCommandsList().get(sel);
			if (cmd.getCommand() != null) {
				final EditNativeCommandDialog cmdDialog = new EditNativeCommandDialog(shell);
				cmdDialog.setCommand(cmd);
				cmd = (NativeCommand)cmdDialog.open();
				if (cmd != null) {
					multiProfileList.get(0).getNativeCommandsList().set(sel, cmd);
					updateNativeCommands(sel);
				}
			}
		}
	}

	protected void doRemoveNativeCommand() {
		int sel = nativeCommands.getSelectionIndex();
		if (sel != -1) {
			NativeCommand cmd = multiProfileList.get(0).getNativeCommandsList().get(sel);
			if (cmd.getCommand() != null) {
				multiProfileList.get(0).getNativeCommandsList().remove(sel);
				updateNativeCommands(Math.min(sel, nativeCommands.getItemCount() - 1));
			}
		}
	}

	public static Template duplicateTemplate(final Template template, final java.util.List<DosboxVersion> dbversionsList, final Database dbase, final Shell shell) {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		PrintStream ps = new PrintStream(bos);

		try {
			dbase.startTransaction();
			DosboxVersion dbversion = DosboxVersion.findById(dbversionsList, template.getDbversionId());
			Conf newCompositeConf = new Conf(template, dbversion, ps);
			Template newTemplate = dbase.duplicateTemplate(template);
			dbase.saveNativeCommands(dbase.readNativeCommandsList(-1, template.getId()), -1, newTemplate.getId());

			newTemplate = new Template(newTemplate.getId(), newTemplate);

			newCompositeConf.injectOrUpdateTemplate(newTemplate);
			newCompositeConf.save();

			dbase.commitTransaction();
			if (bos.size() > 0) {
				GeneralPurposeDialogs.warningMessage(shell, bos.toString());
				bos.reset();
			}
			return newTemplate;
		} catch (Exception e) {
			GeneralPurposeDialogs.warningMessage(shell, e);
			try {
				dbase.rollbackTransaction();
			} catch (SQLException se) {
				GeneralPurposeDialogs.warningMessage(shell, se);
			}
			return null;
		} finally {
			dbase.finishTransaction();
		}
	}

	protected void doAddMount() {
		final EditMountDialog addMountDialog = new EditMountDialog(shell);
		try {
			addMountDialog.setDefaultDriveletter(Mount.getFreeDriveletter(booterExpandItem.getExpanded(), multiProfileList.get(0).getConf().nettoMountedDriveLetters()));
		} catch (Exception e) {
			// nothing we can do, just take default 'C'
		}
		String mount = (String)addMountDialog.open();
		if (mount != null) {
			mountingpoints.setItems(multiProfileList.get(0).getConf().addMount(mount));
			mountingpoints.select(mountingpoints.getItemCount() - 1);
		}
	}

	protected void doEditMount() {
		int mounts = mountingpoints.getItemCount();
		int sel = mountingpoints.getSelectionIndex();
		if (sel != -1) {
			final EditMountDialog editMountDialog = new EditMountDialog(shell);
			editMountDialog.setMount(mountingpoints.getItem(sel));
			String mount = (String)editMountDialog.open();
			if (mount != null) {
				mountingpoints.setItems(multiProfileList.get(0).getConf().editMount(sel, mount));
				if (mountingpoints.getItemCount() == mounts) {
					mountingpoints.select(sel);
				} else {
					mountingpoints.select(mountingpoints.getItemCount() - 1);
				}
			}
		}
	}

	protected void doRemoveMount() {
		int mounts = mountingpoints.getItemCount();
		int sel = mountingpoints.getSelectionIndex();
		if (sel == -1 && mounts == 1) {
			sel = 0;
			mountingpoints.select(sel);
		}
		if (sel != -1) {
			mountingpoints.setItems(multiProfileList.get(0).getConf().removeMount(sel));
			if (mountingpoints.getItemCount() == mounts) {
				mountingpoints.select(sel);
			} else {
				if (mountingpoints.getItemCount() > 0) {
					mountingpoints.select(mountingpoints.getItemCount() - 1);
				}
			}
		}
	}

	protected void updateItems(String[] items, boolean available, Combo combo) {
		java.util.List<String> l = new ArrayList<String>(Arrays.asList(combo.getItems()));
		boolean changes = false;
		if (available) {
			for (String s: items) {
				if (!l.contains(s)) {
					l.add(s);
					changes = true;
				}
			}
		} else {
			for (String s: items) {
				if (l.contains(s)) {
					l.remove(s);
					changes = true;
				}
			}
		}
		if (changes) {
			combo.setItems(l.toArray(new String[0]));
		}
	}

	protected void enableSettingsByConfiguration(SectionsWrapper conf) {
		setButton.setEnabled(false);
		switchButton.setEnabled(false);

		String[] otherValues = null;
		if (conf != null) {
			otherValues = conf.hasValue("cpu", "cputype") ? settings.getSettings().getValues("profile", "machine073"): settings.getSettings().getValues("profile", "machine");

			updateItems(new String[] {"openglhq", "direct3d"}, conf.hasOutputDirect3DSupport(), output);
			updateItems(new String[] {"cga_mono", "svga_s3_full", "amstrad"}, conf.hasAmstradSupport(), machine);
			updateItems(new String[] {"hardware2x", "hardware3x"}, conf.hasHardwareScalerSupport(), scaler);
			updateItems(new String[] {"mt32", "synth", "timidity"}, conf.hasMT32Support(), midi_device);
			updateItems(new String[] {"sb16vibra"}, conf.hasSoundBlaster16VibraSupport(), sbtype);
			updateItems(new String[] {"hardware", "hardwaregb"}, conf.hasHardwareOPLSupport(), oplmode);
			updateItems(new String[] {"486", "pentium", "pentium_mmx"}, conf.hasAdditionalCPUTypesSupport(), cpu_type);
		} else {
			otherValues = settings.getSettings().getCommonValues("profile", "machine073", "machine");
		}
		if (!Arrays.equals(machine.getItems(), otherValues)) {
			Object obj = machine.getData();
			machine.setItems(otherValues);
			machine.setData(obj);
		}

		enableDisableControl(conf, "cpu", "cputype", cpu_type);
		enableDisableControl(conf, "dos", "umb", umb);
		enableDisableControl(conf, "sdl", "windowresolution", windowresolution);
		enableDisableControl(conf, "sdl", "usescancodes", usescancodes);
		enableDisableControl(conf, "sblaster", "oplemu", oplemu);
		enableDisableControl(conf, "gus", "irq2", gusirq2);
		enableDisableControl(conf, "gus", "dma2", gusdma2);
		enableDisableControl(conf, "speaker", "tandy", tandy);
		enableDisableControl(conf, "bios", "joysticktype", "joystick", "joysticktype", joysticktype);
		enableDisableControl(conf, "joystick", "timed", timed);
		enableDisableControl(conf, "joystick", "autofire", autofire);
		enableDisableControl(conf, "joystick", "swap34", swap34);
		enableDisableControl(conf, "joystick", "buttonwrap", buttonwrap);
		enableDisableControl(conf, "dos", "keyboardlayout", keyboard_layout);
		enableDisableControl(conf, "serial", "serial1", serial1);
		enableDisableControl(conf, "serial", "serial2", serial2);
		enableDisableControl(conf, "serial", "serial3", serial3);
		enableDisableControl(conf, "serial", "serial4", serial4);

		enableDisableControl(conf, "render", "autofit", autofit);
		enableDisableControl(conf, "sdl", "pixelshader", pixelshader);
		enableDisableControl(conf, "render", "linewise", linewise);
		enableDisableControl(conf, "render", "char9", char9);
		enableDisableControl(conf, "render", "multiscan", multiscan);
		enableDisableControl(conf, "cpu", "cgasnow", cgasnow);
		enableDisableControl(conf, "sdl", "overscan", overscan);
		enableDisableControl(conf, "vsync", "vsyncmode", vsyncmode);
		enableDisableControl(conf, "vsync", "vsyncrate", vsyncrate);
		enableDisableControl(conf, "cpu", "forcerate", forcerate);
		enableDisableControl(conf, "dosbox", "vmemsize", videoram);
		enableDisableControl(conf, "glide", "glide", glide);
		enableDisableControl(conf, "glide", "port", "grport", glideport);
		enableDisableControl(conf, "glide", "lfb", lfbGlide);
		enableDisableControl(conf, "glide", "splash", splash3dfx);
		enableDisableControl(conf, "pci", "voodoo", voodoo);
		enableDisableControl(conf, "pci", "voodoomem", voodooMem);
		enableDisableControl(conf, "sdl", "surfacenp-sharpness", surfaceNpSharpness);
		enableDisableControl(conf, "sdl", "surface-collapse-dbl", surfaceCollapseDbl);
		enableDisableControl(conf, "dosbox", "memsizekb", memsizeKB);
		enableDisableControl(conf, "dosbox", "memalias", memalias);
		enableDisableControl(conf, "mixer", "swapstereo", swapstereo);
		enableDisableControl(conf, "midi", "fluid.driver", driverFluid);
		enableDisableControl(conf, "midi", "fluid.soundfont", soundfontFluid);
		enableDisableControl(conf, "midi", "fluid.samplerate", samplerateFluid);
		enableDisableControl(conf, "midi", "fluid.gain", gainFluid);
		enableDisableControl(conf, "sblaster", "hardwarebase", hardwareaddresssbbase);
		enableDisableControl(conf, "sblaster", "goldplay", goldplay);
		enableDisableControl(conf, "midi", "mt32.romdir", romDirMT32);
		enableDisableControl(conf, "midi", "mt32.reverse.stereo", swapstereoMT32);
		enableDisableControl(conf, "midi", "mt32.verbose", loggingMT32);
		enableDisableControl(conf, "midi", "mt32.thread", multithreadMT32);
		enableDisableControl(conf, "midi", "mt32.chunk", chunkMT32);
		enableDisableControl(conf, "midi", "mt32.prebuffer", prebufferMT32);
		enableDisableControl(conf, "midi", "mt32.dac", dacMT32);
		enableDisableControl(conf, "midi", "mt32.analog", analogMT32);
		enableDisableControl(conf, "midi", "mt32.reverb.mode", reverbmodeMT32);
		enableDisableControl(conf, "midi", "mt32.reverb.time", reverbtimeMT32);
		enableDisableControl(conf, "midi", "mt32.reverb.level", reverblevelMT32);
		enableDisableControl(conf, "midi", "mt32.partials", partialsMT32);
		enableDisableControl(conf, "speaker", "ps1audio", ps1);
		enableDisableControl(conf, "speaker", "ps1audiorate", ps1rate);
		enableDisableControl(conf, "innova", "innova", innova);
		enableDisableControl(conf, "innova", "samplerate", innovarate);
		enableDisableControl(conf, "innova", "sidbase", innovabase);
		enableDisableControl(conf, "innova", "quality", innovaquality);
		enableDisableControl(conf, "dos", "int33", int33);
		enableDisableControl(conf, "dos", "biosps2", biosps2);
		enableDisableControl(conf, "keyboard", "aux", aux);
		enableDisableControl(conf, "keyboard", "auxdevice", auxdevice);
		enableDisableControl(conf, "dos", "files", files);
		enableDisableControl(conf, "cpu", "isapnpbios", isapnpbios);
		enableDisableControl(conf, "ide, primary", "enable", ide1);
		enableDisableControl(conf, "ide, secondary", "enable", ide2);
		enableDisableControl(conf, "ide, tertiary", "enable", ide3);
		enableDisableControl(conf, "ide, quaternary", "enable", ide4);
		enableDisableControl(conf, "dos", "automount", automount);
		enableDisableControl(conf, "printer", "printer", printer);
		enableDisableControl(conf, "printer", "dpi", printerdpi);
		enableDisableControl(conf, "printer", "width", printerwidth);
		enableDisableControl(conf, "printer", "height", printerheight);
		enableDisableControl(conf, "printer", "printoutput", printeroutput);
		enableDisableControl(conf, "printer", "multipage", printermultipage);
		enableDisableControl(conf, "printer", "docpath", printerdocpath);
		enableDisableControl(conf, "printer", "timeout", printertimeout);
		enableDisableControl(conf, "parallel", "parallel1", parallel1);
		enableDisableControl(conf, "parallel", "parallel2", parallel2);
		enableDisableControl(conf, "parallel", "parallel3", parallel3);
		enableDisableControl(conf, "parallel", "dongle", dongle);
		enableDisableControl(conf, "ne2000", "ne2000", ne2000);
		enableDisableControl(conf, "ne2000", "nicbase", ne2000base);
		enableDisableControl(conf, "ne2000", "nicirq", ne2000irq);
		enableDisableControl(conf, "ne2000", "macaddr", ne2000macaddress);
		enableDisableControl(conf, "ne2000", "realnic", ne2000realnic);
	}

	protected void doPerformDosboxConfAction(DosboxConfAction action) {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			PrintStream ps = new PrintStream(bos);
			updateConfigurationBySettings(multiProfileList.get(0).getConf());
			Conf newDosboxVersion = new Conf(dbversionsList.get(dbversion.getSelectionIndex()), ps);

			if (action == DosboxConfAction.SET) {
				multiProfileList.get(0).getConf().setToDosboxVersion(newDosboxVersion);
			} else if (action == DosboxConfAction.SWITCH) {
				multiProfileList.get(0).getConf().switchToDosboxVersion(newDosboxVersion);
			} else if (action == DosboxConfAction.RELOAD) {
				multiProfileList.get(0).getConf().reloadDosboxVersion(newDosboxVersion);
			}

			enableSettingsByConfiguration(multiProfileList.get(0).getConf().getDosboxSettings());
			selectSettingsByConfiguration(multiProfileList.get(0).getConf());

			if (bos.size() > 0) {
				GeneralPurposeDialogs.warningMessage(getParent(), bos.toString());
				bos.reset();
			}
		} catch (IOException e) {
			GeneralPurposeDialogs.warningMessage(getParent(), e);
		}
	}

	protected static void enableDisableControl(final SectionsWrapper dbConf, final String oldSection, final String oldItem, final String newSection, final String newItem, final Control control) {
		control.setEnabled((dbConf != null) && (dbConf.hasValue(newSection, newItem) || dbConf.hasValue(oldSection, oldItem)));
	}

	protected static void enableDisableControl(final SectionsWrapper dbConf, final String section, final String oldItem, final String newItem, final Control control) {
		control.setEnabled((dbConf != null) && (dbConf.hasValue(section, newItem) || dbConf.hasValue(section, oldItem)));
	}

	protected static void enableDisableControl(final SectionsWrapper dbConf, final String section, final String item, final Control control) {
		control.setEnabled((dbConf != null) && dbConf.hasValue(section, item));
	}

	protected static void highlight(final Control control, final int foreGroundColor) {
		Control[] children = control.getParent().getChildren();
		for (int i = 0; i < children.length; i++) {
			if (children[i] == control) {
				if (i > 0) {
					Control target = null;
					if (children[i - 1] instanceof Label) {
						target = children[i - 1];
					} else {
						if ((i + 1) == children.length - 1) {
							target = children[i + 1];
						} else if ((i - 1) > 0 && children[i - 2] instanceof Label) {
							target = children[i - 2];
						}
					}
					if (target != null) {
						target.setForeground(control.getDisplay().getSystemColor(foreGroundColor));
					}
				} else {
					highlight(control.getParent(), foreGroundColor);
				}
			}
		}
	}

	protected static void setFieldIfEnabled(final String value, final boolean isConflictingValue, final AutoSelectCombo combo) {
		if (isConflictingValue) {
			highlight(combo.getControl(), SWT.COLOR_DARK_RED);
		} else {
			if (!combo.getText().equals(value))
				combo.setText(value);
		}
	}

	protected static void setFieldIfEnabled(final String value, final boolean isConflictingValue, final Control control) {
		setFieldIfEnabled(value, isConflictingValue, control, false);
	}

	protected static void setFieldIfEnabled(final String value, final boolean isConflictingValue, final Control control, final boolean isOnOff) {
		if (control.isEnabled()) {
			if (control instanceof Text) {
				if (isConflictingValue) {
					highlight(control, SWT.COLOR_DARK_RED);
				} else {
					if (!((Text)control).getText().equals(value))
						((Text)control).setText(value);
				}
			} else if (control instanceof Combo) {
				if (isConflictingValue) {
					highlight(control, SWT.COLOR_DARK_RED);
				} else {
					if (!((Combo)control).getText().equals(value))
						((Combo)control).setText(value);
				}
			} else if (control instanceof Button) {
				if (isConflictingValue) {
					((Button)control).setSelection(true);
					((Button)control).setGrayed(true);
					highlight(control, SWT.COLOR_DARK_RED);
				} else {
					boolean newValue = isOnOff ? "on".equalsIgnoreCase(value): Boolean.valueOf(value);
					if ((((Button)control).getSelection() != newValue) || ((Button)control).getGrayed()) {
						((Button)control).setSelection(newValue);
						((Button)control).notifyListeners(SWT.Selection, new Event());
					}
				}
			} else if (control instanceof Scale) {
				if (isConflictingValue) {
					highlight(control, SWT.COLOR_DARK_RED);
				} else {
					Integer newValue = Integer.valueOf(value);
					if (((Scale)control).getSelection() != newValue) {
						((Scale)control).setSelection(newValue);
					}
				}
			} else if (control instanceof Spinner) {
				if (isConflictingValue) {
					highlight(control, SWT.COLOR_DARK_RED);
				} else {
					Integer newValue = Integer.valueOf(value);
					if (((Spinner)control).getSelection() != newValue) {
						((Spinner)control).setSelection(newValue);
					}
				}
			}
		}
	}

	protected static void setFieldIfEnabled(final SectionsWrapper conf, final String section, final String item, final Control control) {
		setFieldIfEnabled(conf.getValue(section, item), conf.isConflictingValue(section, item), control);
	}

	protected static void setOnOffFieldIfEnabled(final SectionsWrapper conf, final String section, final String item, final Control control) {
		setFieldIfEnabled(conf.getValue(section, item), conf.isConflictingValue(section, item), control, true);
	}

	protected static void setFieldIfEnabled(final SectionsWrapper conf, final String section, final String item, final Control control1, final Control control2) {
		if (conf.isConflictingValue(section, item)) {
			setFieldIfEnabled(conf.getValue(section, item), conf.isConflictingValue(section, item), control1);
			setFieldIfEnabled(conf.getValue(section, item), conf.isConflictingValue(section, item), control2);
		} else {
			String value = conf.getValue(section, item);
			String[] seperatedValues = value.split(",");
			if ((seperatedValues != null) && (seperatedValues.length >= 2)) {
				setFieldIfEnabled(seperatedValues[0], false, control1);
				setFieldIfEnabled(seperatedValues[1], false, control2);
			}
		}
	}

	protected static void setFieldIfEnabled(final SectionsWrapper conf, final String section, final String oldItem, final String newItem, final Control control) {
		if (conf.hasValue(section, newItem)) {
			setFieldIfEnabled(conf, section, newItem, control);
		} else {
			setFieldIfEnabled(conf, section, oldItem, control);
		}
	}

	protected boolean isMultiEdit() {
		return multiProfileList.size() > 1;
	}

	protected String fetch(Text t) {
		return ((Boolean)t.getData()) ? t.getText(): null;
	}

	protected String fetch(Combo t) {
		return ((Boolean)t.getData()) ? t.getText(): null;
	}

	protected String fetch(AutoSelectCombo t) {
		return ((Boolean)t.getData()) ? t.getText(): null;
	}

	protected Boolean fetch(Button t) {
		return ((Boolean)t.getData()) ? t.getSelection(): null;
	}

	protected int fetch(Scale t) {
		return ((Boolean)t.getData()) ? t.getSelection(): -1;
	}

	protected int fetch(Spinner t) {
		return ((Boolean)t.getData()) ? t.getSelection(): -1;
	}

	private boolean isValid() {
		GeneralPurposeDialogs.initErrorDialog();
		if (title.getText().equals("")) {
			GeneralPurposeDialogs.addError(settings.msg("dialog.template.required.title"), title, infoTabItem);
		}
		if (setButton.isEnabled()) {
			GeneralPurposeDialogs.addError(settings.msg("dialog.template.required.dosboxassociation"), setButton, generalTabItem);
		}
		return !GeneralPurposeDialogs.displayErrorDialog(shell);
	}
}
