// options.cxx
// This file is part of galvani.
// Copyright (C) 2020-2024 Burkard Lutz <b.lutz@online.de>
//
// 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, see <http://www.gnu.org/licenses/>.

#include <gtkmm.h>
#include <iostream>
#include <fstream>
#include "options.h"
#include <libserial/SerialPortConstants.h>
#include <glibmm/i18n.h>
#include <experimental/filesystem>

namespace fs = std::experimental::filesystem;

//DMM-Functions: Transform to Strings
std::string Multimeter::get_baud()
{
	std::string baudrate;
	
	switch (dmm_baud)
	{
		case LibSerial::BaudRate::BAUD_600: baudrate = "600"; break;
		case LibSerial::BaudRate::BAUD_1200: baudrate = "1200"; break;
		case LibSerial::BaudRate::BAUD_1800: baudrate = "1800"; break;
		case LibSerial::BaudRate::BAUD_2400: baudrate = "2400"; break;
		case LibSerial::BaudRate::BAUD_4800: baudrate = "4800"; break;
		case LibSerial::BaudRate::BAUD_9600: baudrate = "9600"; break;
		case LibSerial::BaudRate::BAUD_19200: baudrate = "19200"; break;
		case LibSerial::BaudRate::BAUD_38400: baudrate = "38400"; break;
		case LibSerial::BaudRate::BAUD_57600: baudrate = "57600"; break;
		case LibSerial::BaudRate::BAUD_115200: baudrate = "115200"; break;
		default: baudrate = "9600";
	}		
	return baudrate;
}

void Multimeter::set_baud(std::string baudrate)
{
	if (baudrate == "600") dmm_baud = LibSerial::BaudRate::BAUD_600;
	else if (baudrate == "1200") dmm_baud = LibSerial::BaudRate::BAUD_1200;
	else if (baudrate == "1800") dmm_baud = LibSerial::BaudRate::BAUD_1800;
	else if (baudrate == "2400") dmm_baud = LibSerial::BaudRate::BAUD_2400;
	else if (baudrate == "4800") dmm_baud = LibSerial::BaudRate::BAUD_4800;
	else if (baudrate == "9600") dmm_baud = LibSerial::BaudRate::BAUD_9600;
	else if (baudrate == "19200") dmm_baud = LibSerial::BaudRate::BAUD_19200;
	else if (baudrate == "38400") dmm_baud = LibSerial::BaudRate::BAUD_38400;
	else if (baudrate == "57600") dmm_baud = LibSerial::BaudRate::BAUD_57600;
	else if (baudrate == "115200") dmm_baud = LibSerial::BaudRate::BAUD_115200;
	else dmm_baud = LibSerial::BaudRate::BAUD_9600;

	return;
}

std::string Multimeter::get_charsize()
{
	std::string charactersize;
	
	switch (dmm_charsize)
	{
		case LibSerial::CharacterSize::CHAR_SIZE_7: charactersize = "7"; break;
		case LibSerial::CharacterSize::CHAR_SIZE_8: charactersize = "8"; break;
		default: charactersize = "7";
	}		
	return charactersize;
}

void Multimeter::set_charsize(std::string charactersize)
{
	if (charactersize == "7") dmm_charsize =LibSerial::CharacterSize::CHAR_SIZE_7;
	else if (charactersize == "8") dmm_charsize =LibSerial::CharacterSize::CHAR_SIZE_8;
	else dmm_charsize =LibSerial::CharacterSize::CHAR_SIZE_7;
	return;
}


std::string Multimeter::get_flowcontrol()
{
	std::string flowcontrol;
	
	switch (dmm_flowcontrol)
	{
		case LibSerial::FlowControl::FLOW_CONTROL_HARDWARE: flowcontrol = "hardware"; break;
		case LibSerial::FlowControl::FLOW_CONTROL_SOFTWARE: flowcontrol = "software"; break;
		case LibSerial::FlowControl::FLOW_CONTROL_NONE: flowcontrol = "none"; break;
		default: flowcontrol = "none";
	}		
	return flowcontrol;
}


void Multimeter::set_flowcontrol(std::string flowcontrol)
{
	if (flowcontrol == "hardware") dmm_flowcontrol = LibSerial::FlowControl::FLOW_CONTROL_HARDWARE;
	else if (flowcontrol == "software") dmm_flowcontrol = LibSerial::FlowControl::FLOW_CONTROL_SOFTWARE;
	else dmm_flowcontrol = LibSerial::FlowControl::FLOW_CONTROL_NONE;
	return;
}


std::string Multimeter::get_stopbits()
{
	std::string stopbits;
	
	switch (dmm_stopbits)
	{
		case LibSerial::StopBits::STOP_BITS_1: stopbits = "1"; break;
		case LibSerial::StopBits::STOP_BITS_2: stopbits = "2"; break;
		default: stopbits = "2";
	}		
	return stopbits;
}

void Multimeter::set_stopbits(std::string stopbits)
{
	if (stopbits == "1") dmm_stopbits = LibSerial::StopBits::STOP_BITS_1;
	else dmm_stopbits = LibSerial::StopBits::STOP_BITS_2;
	return;
}


std::string Multimeter::get_parity()
{
	std::string parity;
	
	switch (dmm_parity)
	{
		case LibSerial::Parity::PARITY_EVEN: parity = "even"; break;
		case LibSerial::Parity::PARITY_ODD: parity = "odd"; break;
		case LibSerial::Parity::PARITY_NONE: parity = "none"; break;
		default: parity = "none"; 
	}		
	return parity;
}


void Multimeter::set_parity(std::string parity)
{
	if (parity == "even") dmm_parity = LibSerial::Parity::PARITY_EVEN;
	else if (parity == "odd") dmm_parity = LibSerial::Parity::PARITY_ODD;
	else dmm_parity = LibSerial::Parity::PARITY_NONE;
	return;
}



void set_options ()
{
	Gdk::RGBA color;
	std::string option, funkt_x_saved;
	typ dmm1_typ_saved, dmm2_typ_saved;
	int i, opt_page;
	
	
	//set standard values (for reset)
	std_axcol.set_rgba(0.0,0.0,0.0);
	std_gridcol.set_rgba(0.5,0.5,0.5);
	std_bkcol.set_rgba(0.95,0.95,0.94);
	std_xycol.set_rgba(1.0,0.0,0.0);

	//////////////// Show Diagram Settings //////////////////////
	//Colours
	color.set_rgba(diag->bkcol_r, diag->bkcol_g, diag->bkcol_b);
	diag_bkcolor->set_rgba(color);
	color.set_rgba(diag->gridcol_r, diag->gridcol_g, diag->gridcol_b);
	diag_gridcolor->set_rgba(color);
	color.set_rgba(diag->axcol_r, diag->axcol_g, diag->axcol_b);
	diag_axcolor->set_rgba(color);
	color.set_rgba(diag->xycol_r, diag->xycol_g, diag->xycol_b);
	diag_xycolor->set_rgba(color);
	//Switches
	diag_gridsw->set_state(diag->grid);
	diag_autoscalesw->set_state(diag->autoscale);
	diag_zerosw->set_state(diag->showzero);
	diag_titlesw->set_state(diag->showtitle);
	//Symbols
	if (diag->mw_symbol == cross) diag_symbol->set_active_text(_("cross"));
	else if (diag->mw_symbol == square) diag_symbol->set_active_text(_("square"));
	else if (diag->mw_symbol == circle) diag_symbol->set_active_text(_("circle"));
	else if (diag->mw_symbol == diamond) diag_symbol->set_active_text(_("diamond"));
	else diag_symbol->set_active_text(_("no symbol"));
	diag_symw->set_value(diag->symw);
	//Symbol style
	if (diag->symbol_filled) diag_symbolstyle->set_active_text(_("filled"));
	else diag_symbolstyle->set_active_text(_("outline"));
	//Line style	
	if (diag->mw_linestyle == dashed) diag_linestyle->set_active_text(_("dashed"));
	else if (diag->mw_linestyle == pointed) diag_linestyle->set_active_text(_("dotted"));
	else diag_linestyle->set_active_text(_("solid"));
	//Connection between points
	if (diag->mw_line) diag_graph->set_active_text(_("line"));
	else if (diag->mw_curve) diag_graph->set_active_text(_("curve"));
	else diag_graph->set_active_text(_("no connection"));
	//manual scaling
	diag_xmin->set_value(diag->xmin);
	diag_xmax->set_value(diag->xmax);
	diag_ymin->set_value(diag->ymin);
	diag_ymax->set_value(diag->ymax);
	show_diag_manual_limits (diag_autoscalesw->get_state ());
	
	//////////////////////// Show Device Settings /////////////////////
	// save starting values 
	dmm1_typ_saved = dmm[0].dmm_typ;
	dmm2_typ_saved = dmm[1].dmm_typ;
	funkt_x_saved = project->funktion_x;

	// Set minimum values for Measurement intervall
	if ((dmm[1].dmm_typ == DMM) || (dmm[1].dmm_typ == DEVICE)) min_timeout = dmm[1].ms_timeout;
	else min_timeout = 0.01;
	if ((dmm[0].dmm_typ == DMM) && (dmm[0].ms_timeout > dmm[1].ms_timeout)) min_timeout = dmm[0].ms_timeout;
	dmm_mtime->set_range (0.001 * min_timeout, 3600); 
	show_options_Kanal_XY ();
	///////////////////////////////////////////////////////////////////////
		
	options_dialog-> show ();
		
	//////////////////////	Accept Settings  ///////////////////////
	int result = options_dialog->run();
	switch(result)
  	{
    	case(Gtk::RESPONSE_ACCEPT):
    	{
			///////////////////// Diagram Settings ///////////////////
			//Colours
			color = diag_bkcolor->get_rgba();
			diag->bkcol_r = color.get_red();
			diag->bkcol_g = color.get_green();
			diag->bkcol_b = color.get_blue();
			color = diag_axcolor->get_rgba();
			diag->axcol_r = color.get_red();
			diag->axcol_g = color.get_green();
			diag->axcol_b = color.get_blue();
			color = diag_gridcolor->get_rgba();
			diag->gridcol_r = color.get_red();
			diag->gridcol_g = color.get_green();
			diag->gridcol_b = color.get_blue();
			color = diag_xycolor->get_rgba();
			diag->xycol_r = color.get_red();
			diag->xycol_g = color.get_green();
			diag->xycol_b = color.get_blue();
			//Switches
			diag->grid = diag_gridsw->get_state();
			diag->autoscale = diag_autoscalesw->get_state();
			diag->showzero = diag_zerosw->get_state();
			diag->showtitle = diag_titlesw->get_state();
			//Symbols
			option = diag_symbol->get_active_text();
			if (option == _("cross")) 
			{
				diag->mw_symbol = cross;
				diag_symbolstyle->set_active_text(_("outline"));
			}
			else if (option == _("square")) diag->mw_symbol = square;
			else if (option == _("circle")) diag->mw_symbol = circle;
			else if (option == _("diamond")) diag->mw_symbol = diamond;
			else diag->mw_symbol = none;
			diag->symw = diag_symw->get_value();
			//Symbol style
			option = diag_symbolstyle->get_active_text();
			if (option == _("filled")) diag->symbol_filled = true;
			else diag->symbol_filled = false;
			//Line style
			option = diag_linestyle->get_active_text();
			if (option == _("dashed")) diag->mw_linestyle = dashed;
			else if (option == _("dotted")) diag->mw_linestyle = pointed;
			else diag->mw_linestyle = solid;
			//Connection between points
			option = diag_graph->get_active_text();
			if (option == _("line"))
			{
				diag->mw_line = true;
				diag->mw_curve = false;
			}
			else if (option == _("curve"))
			{
				diag->mw_line = false;
				diag->mw_curve = true;
			}
			else
			{
				diag->mw_line = false;
				diag->mw_curve = false;
			}
			//manual scaling
			diag->xmin = diag_xmin->get_value();
			if (diag->xmin < 0) diag->xmin = 0;
			if (diag_xmax->get_value() > diag->xmin) diag->xmax = diag_xmax->get_value();
			diag->xscale = diag->xmax - diag->xmin;
			diag->ymin = diag_ymin->get_value();
			if ((diag->showzero) && (diag->ymin > 0)) diag->ymin = 0;
			if (diag_ymax->get_value() > diag->ymin) diag->ymax = diag_ymax->get_value();
			if ((diag->showzero) && (diag->ymax < 0)) diag->ymax = 0;
			diag->yscale = diag->ymax - diag->ymin;
			
			////////////////////////// DMM Settings ///////////////////
			diag->mtime = trunc (1000 * dmm_mtime->get_value());
			if (diag->mtime < min_timeout) diag->mtime = min_timeout;

			for (int k=0; k<=1; k++)
			{
				option = dmm_typ[k]->get_active_text();
				if (option == _("Time")) 
				{
					dmm[k].dmm_typ = TIME;
					dmm[k].dmm_name = "";
					project->funktion_x = _("Time");
				}
				else if (option == _("Simulation"))
				{
					if (k == 0)
					{
						dmm[k].dmm_typ = LINEAR;
						dmm[k].dmm_name = "";
					}
					else
					{
						option = dmm_simtyp[k]->get_active_text();
						if (option == _("Exponential")) dmm[k].dmm_typ = EXP;
						else if (option == _("Chromatogramm")) dmm[k].dmm_typ = PEAK;
						else if (option == _("Spektrum")) 
						{
							dmm[k].dmm_typ = SPEKTRUM;
							set_messfunkt (0, _("Wavelength"));
							set_messfunkt (1, _("Absorption"));
						}
						else if (option == "pH") 
						{
							dmm[k].dmm_typ = PH;
							set_messfunkt (1, "pH");
							eval_titvolumen = true;
						}
						else dmm[k].dmm_typ = LINEAR;
						dmm[k].dmm_name = "";
						dmm[k].remote_cfg = false;
					}
				}
				else if (option == _("Device"))
				{
					dmm[k].dmm_typ = DEVICE;
					dmm[k].dmm_name = device_name->get_active_text();
					dmm[k].int_face = device_interface->get_active_text();
					if (dmm[k].dmm_name == "Lutron PH-207") set_device_options_lutron_ph207 ();
					// other Devices following
				
				}
				else 
				{
					dmm[k].dmm_typ = DMM;
					dmm[k].dmm_name = dmm_name[k]->get_active_text();
					dmm[k].int_face = dmm_interface[k]->get_active_text();
					dmm[k].set_baud (dmm_baud[k]->get_active_text());
					dmm[k].set_charsize (dmm_bits[k]->get_active_text());
					dmm[k].set_flowcontrol (dmm_flowcontrol[k]->get_active_text());
					dmm[k].set_stopbits (dmm_stopbits[k]->get_active_text());
					dmm[k].set_parity (dmm_parity[k]->get_active_text());
					dmm[k].dmm_polling = dmm_polling[k]->get_state();
					dmm[k].scpi = dmm_scpi[k]->get_state();
					dmm[k].num_bytes = dmm_num_bytes[k]->get_value();
					dmm[k].num_val = dmm_num_val[k]->get_value();
					dmm[k].ms_timeout = dmm_timeout[k]->get_value();
					dmm[k].remote_cfg = dmm_remote_control[k]->get_state();
					if (dmm_remote_control[k]->get_state())
					{
						set_messfunkt (k, dmm_funktion[k]->get_active_text());
						dmm[k].m_range = dmm_range[k]->get_active_text();
						dmm[k].set_ctrlstr (DCV, dmm_DCV[k]->get_active_text ());
						dmm[k].set_ctrlstr (ACV, dmm_ACV[k]->get_active_text ());
						dmm[k].set_ctrlstr (DCmA, dmm_DCmA[k]->get_active_text ());
						dmm[k].set_ctrlstr (ACmA, dmm_ACmA[k]->get_active_text ());
						dmm[k].set_ctrlstr (DCA, dmm_DCA[k]->get_active_text ());
						dmm[k].set_ctrlstr (ACA, dmm_ACA[k]->get_active_text ());
						dmm[k].set_ctrlstr (Res, dmm_Res[k]->get_active_text ());
						dmm[k].set_ctrlstr (Cond, dmm_Cond[k]->get_active_text ());
						dmm[k].set_ctrlstr (pH, dmm_pH[k]->get_active_text ());
						dmm[k].set_ctrlstr (Temp, dmm_Temp[k]->get_active_text ());
					}

					//edit existing dmm or install new one
					if (dmm_exist (dmm_name[k]->get_active_text())) i = id; else i = ++mid;
					idmm[i].dmm_name = dmm_name[k]->get_active_text();
					idmm[i].set_baud (dmm_baud[k]->get_active_text());
					idmm[i].set_charsize (dmm_bits[k]->get_active_text());
					idmm[i].set_flowcontrol (dmm_flowcontrol[k]->get_active_text());
					idmm[i].set_stopbits (dmm_stopbits[k]->get_active_text());
					idmm[i].set_parity (dmm_parity[k]->get_active_text());
					idmm[i].dmm_polling = dmm_polling[k]->get_state();
					idmm[i].scpi = dmm_scpi[k]->get_state();
					idmm[i].num_bytes = dmm_num_bytes[k]->get_value();
					idmm[i].num_val = dmm_num_val[k]->get_value();
					idmm[i].ms_timeout = dmm_timeout[k]->get_value();
					idmm[i].remote_cfg = dmm_remote_control[k]->get_state();
					if (dmm_remote_control[k]->get_state())
					{
						idmm[i].set_ctrlstr (DCV, dmm_DCV[k]->get_active_text ());
						idmm[i].set_ctrlstr (ACV, dmm_ACV[k]->get_active_text ());
						idmm[i].set_ctrlstr (DCmA, dmm_DCmA[k]->get_active_text ());
						idmm[i].set_ctrlstr (ACmA, dmm_ACmA[k]->get_active_text ());
						idmm[i].set_ctrlstr (DCA, dmm_DCA[k]->get_active_text ());
						idmm[i].set_ctrlstr (ACA, dmm_ACA[k]->get_active_text ());
						idmm[i].set_ctrlstr (Res, dmm_Res[k]->get_active_text ());
						idmm[i].set_ctrlstr (Cond, dmm_Cond[k]->get_active_text ());
						idmm[i].set_ctrlstr (pH, dmm_pH[k]->get_active_text ());
						idmm[i].set_ctrlstr (Temp, dmm_Temp[k]->get_active_text ());
					}
				}
			}
			
			break;
    	}
    	case(Gtk::RESPONSE_CANCEL):
    	{
			// reset dmm_typ
			dmm[0].dmm_typ = dmm1_typ_saved;
			dmm[1].dmm_typ = dmm2_typ_saved;
			project->funktion_x = funkt_x_saved;
			break;
    	}
		case(Gtk::RESPONSE_DELETE_EVENT):	//Reset
    	{
			if (!dialog_ok (_("Reset options of current page?"))) break;
			opt_page = edit_options->get_current_page ();
			switch (opt_page)
			{
				case 0:		// Reset Diagram Settings
				{
					//Colours
					diag->bkcol_r = std_bkcol.get_red();
					diag->bkcol_g = std_bkcol.get_green();
					diag->bkcol_b = std_bkcol.get_blue();
					diag->axcol_r = std_axcol.get_red();
					diag->axcol_g = std_axcol.get_green();
					diag->axcol_b = std_axcol.get_blue();
					diag->gridcol_r = std_gridcol.get_red();
					diag->gridcol_g = std_gridcol.get_green();
					diag->gridcol_b = std_gridcol.get_blue();
					diag->xycol_r = std_xycol.get_red();
					diag->xycol_g = std_xycol.get_green();
					diag->xycol_b = std_xycol.get_blue();
					//Switches
					diag->grid = true;
					diag->autoscale = true;
					diag->showzero = false;
					diag->showtitle = true;
					//Symbols
					diag->mw_symbol = none;
					diag->symbol_filled = false;
					//Line style
					diag->mw_linestyle = solid;
					//Connection between points
					diag->mw_line = true;
										
					break;
				}
				case 1:		// Reset DMM-Settings Channel X
				{
					project->funktion_x = _("Time");
					dmm[0].dmm_name = "";
					dmm[0].int_face = "";
					dmm[0].dmm_typ = TIME;
					break;
				}
				case 2:		// Reset DMM-Settings Channel Y
				{
					dmm[1].dmm_name = "";
					dmm[1].int_face = "";
					dmm[1].dmm_typ = DMM;
					dmm[1].dmm_baud = LibSerial::BaudRate::BAUD_9600;
					dmm[1].dmm_charsize = LibSerial::CharacterSize::CHAR_SIZE_7;
					dmm[1].dmm_flowcontrol = LibSerial::FlowControl::FLOW_CONTROL_NONE;
					dmm[1].dmm_stopbits = LibSerial::StopBits::STOP_BITS_2;
					dmm[1].dmm_parity = LibSerial::Parity::PARITY_NONE;
					dmm[1].dmm_polling = true;
					dmm[1].scpi = false;
					dmm[1].num_bytes = 0;
					dmm[1].num_val = 1;
					dmm[1].ms_timeout = 100;
					dmm[1].m_funkt = _("DC Voltage");
					dmm[1].m_range = "2 V";
					diag->mtime = 1000;
					break;
				}				
			}
			
			break;
    	}
  	}
		
	
	options_dialog->hide();
	return;
}

void show_diag_manual_limits (bool manual)
{
	bool auto_scale;
		
	auto_scale = diag_autoscalesw->get_state();
	if (auto_scale)	
	{
		diag_xmin-> set_sensitive (false);
		diag_xmax-> set_sensitive (false);
		diag_ymin-> set_sensitive (false);
		diag_ymax-> set_sensitive (false);
	}
	else 
	{
		diag_xmin-> set_sensitive (true);
		diag_xmax-> set_sensitive (true);
		diag_ymin-> set_sensitive (true);
		diag_ymax-> set_sensitive (true);
	}
	
	return;
}


void show_options_Kanal_XY ()
{
	int i;
	bool dmm_remote;

	messintervall = 0.001 * diag->mtime;		//Measurement Intervall in Seconds
	dmm_mtime->set_value(messintervall);
	for (int k=0; k<=1; k++)
	{
		if ((k==0) && ((project->funktion_x == _("Time")) || (project->funktion_x == _("Wavelength")))) 
		{
			dmm_typ[0]->set_active_text(_("Time"));
			dmm_dmm_options[0]->hide();
			dmm_serial_options[0]->hide();
			dmm_simtyp[0]->hide();
			dmm_control_options[k]->hide();
			dmm_function_control[k]->hide();
		}
		else if (dmm[k].dmm_typ == DMM)
		{
			dmm_dmm_options[k]->show();
			if (k == 1) dmm_device_options->hide();
			dmm_typ[k]->set_active_text(_("Digitalmultimeter"));
			dmm_simtyp[k]->hide();
			dmm_interface[k]->remove_all();
			ports = dmm[k].dmm_port.GetAvailableSerialPorts(); 
			for (i=0; i<ports.size(); i++) dmm_interface[k]->append (ports.at(i));
			ports = get_usb_ports(); 
			for (i=0; i<ports.size(); i++) dmm_interface[k]->append (ports.at(i));
			dmm_interface[k]->show();
			//  renew list of all installed dmm 
			dmm_name[k]->remove_all ();
			for (i=1; i<=mid; i++) dmm_name[k]->append (idmm[i].dmm_name);
			dmm[k].m_range = set_std_range (dmm[k].m_funkt);
			dmm_name[k]->set_active_text(dmm[k].dmm_name);
			dmm_interface[k]->set_active_text(dmm[k].int_face);
			dmm_baud[k]->set_active_text(dmm[k].get_baud());
			dmm_bits[k]->set_active_text(dmm[k].get_charsize());
			dmm_flowcontrol[k]->set_active_text(dmm[1].get_flowcontrol());
			dmm_stopbits[k]->set_active_text(dmm[k].get_stopbits());
			dmm_parity[k]->set_active_text(dmm[k].get_parity());
			dmm_polling[k]->set_state(dmm[k].dmm_polling);
			dmm_scpi[k]->set_state(dmm[k].scpi);
			dmm_num_bytes[k]->set_value(dmm[k].num_bytes);
			dmm_num_val[k]->set_value(dmm[k].num_val);
			dmm_timeout[k]->set_value(dmm[k].ms_timeout);
			show_dmm_interface_options (k);
			dmm_remote_control[k]->set_state(dmm[k].remote_cfg);
			dmm_remote = dmm_remote_control[k]->get_state ();
			if (dmm_remote)
			{
				show_dmm_function_control(true, k);
				dmm_funktion[k]->set_active_text(dmm[k].m_funkt);		
				dmm_range[k]->set_active_text(dmm[k].m_range);
				dmm_DCV[k]->set_active_text (dmm[k].get_ctrlstr (DCV));
				dmm_ACV[k]->set_active_text (dmm[k].get_ctrlstr (ACV));
				dmm_DCmA[k]->set_active_text (dmm[k].get_ctrlstr (DCmA));
				dmm_ACmA[k]->set_active_text (dmm[k].get_ctrlstr (ACmA));
				dmm_DCA[k]->set_active_text (dmm[k].get_ctrlstr (DCA));
				dmm_ACA[k]->set_active_text (dmm[k].get_ctrlstr (ACA));
				dmm_Res[k]->set_active_text (dmm[k].get_ctrlstr (Res));
				dmm_Cond[k]->set_active_text (dmm[k].get_ctrlstr (Cond));
				dmm_pH[k]->set_active_text (dmm[k].get_ctrlstr (pH));
				dmm_Temp[k]->set_active_text (dmm[k].get_ctrlstr (Temp));
				dmm_control_options[k]-> show();
			}
			else dmm_control_options[k]-> hide();
		}
		else if (dmm[k].dmm_typ == DEVICE)
		{
			dmm_dmm_options[k]->hide();
			dmm_serial_options[k]->hide();
			dmm_control_options[k]->hide();
			dmm_function_control[k]->hide();
			dmm_simtyp[k]->hide();
			if (k == 1) dmm_device_options->show();
			dmm_typ[k]->set_active_text(_("Device"));
			device_interface->remove_all();
			ports = dmm[k].dmm_port.GetAvailableSerialPorts(); 
			for (i=0; i<ports.size(); i++) device_interface->append (ports.at(i));
			ports = get_usb_ports(); 
			for (i=0; i<ports.size(); i++) device_interface->append (ports.at(i));
			device_interface->set_active_text(dmm[k].int_face);
			device_interface->show();
		}
		else	// simulation
		{
			dmm_dmm_options[k]->hide();
			dmm_device_options->hide();
			dmm_serial_options[k]->hide();
			dmm_control_options[k]->hide();
			dmm_function_control[k]->hide();
			dmm_typ[k]->set_active_text(_("Simulation"));
			switch (dmm[k].dmm_typ)
			{
				case LINEAR: dmm_simtyp[k]->set_active_text(_("Linear")); break;
				case EXP: dmm_simtyp[k]->set_active_text(_("Exponential")); break;
				case PEAK: dmm_simtyp[k]->set_active_text(_("Chromatogramm")); break;
				case SPEKTRUM: dmm_simtyp[k]->set_active_text(_("Spektrum")); break;
				case PH: dmm_simtyp[k]->set_active_text("pH"); break;
			}
			dmm_simtyp[k]->show();
		}
	}
	return;
}

void show_dmm_control_options (bool state, int kanal)
{
	bool dmm_remote_ctrl;
		
	dmm_remote_ctrl = dmm_remote_control[kanal]->get_state();
	if ((dmm_remote_ctrl) && (dmm[kanal].dmm_typ == DMM))	
	{
		show_dmm_function_control(true, kanal);
		dmm_control_options[kanal]-> show();
	}
	else 
	{
		dmm_function_control[kanal]->hide();
		dmm_control_options[kanal]-> hide();
	}
	
	return;
}



void show_dmm_function_control(bool state, int k)
{
	bool dmm_remote_ctrl;
	
	dmm_remote_ctrl = dmm_remote_control[k]->get_state();
	if ((dmm_remote_ctrl) && (dmm[k].dmm_typ == DMM)) 
	{
		dmm_funktion[k]->remove_all ();
		if (dmm_DCV[k]->get_active_text () != "") dmm_funktion[k]->append(_("DC Voltage"));
		if (dmm_ACV[k]->get_active_text () != "") dmm_funktion[k]->append(_("AC Voltage"));
		if ((dmm_DCmA[k]->get_active_text () != "") || (dmm_DCA[k]->get_active_text () != "")) dmm_funktion[k]->append(_("DC Current"));
		if ((dmm_ACmA[k]->get_active_text () != "") || (dmm_ACA[k]->get_active_text () != "")) dmm_funktion[k]->append(_("AC Current"));
		if (dmm_Res[k]->get_active_text () != "") dmm_funktion[k]->append(_("Resistance"));	
		if (dmm_Cond[k]->get_active_text () != "") dmm_funktion[k]->append(_("Conductivity"));	
		if (dmm_pH[k]->get_active_text () != "") dmm_funktion[k]->append(_("pH"));
		if (dmm_Temp[k]->get_active_text () != "") dmm_funktion[k]->append(_("Temperature"));
		dmm_funktion[k]->set_active_text(dmm[k].m_funkt);
		set_range_options_device (k);
		dmm_range[k]->set_active_text(dmm[k].m_range);
		dmm_function_control[k]-> show();
	}
	return;
}


void set_options_diag ()
{
	edit_options->set_current_page (0);
	set_options();
	return;
}

void set_options_device_x ()
{
	edit_options->set_current_page (1);
	set_options();
	return;
}

void set_options_device_y ()
{
	edit_options->set_current_page (2);
	set_options();
	return;
}

void set_range_options_device (int k)
{
	std::string funkt;

	funkt = dmm_funktion[k]->get_active_text();
	dmm_range[k]->remove_all();
	if ((funkt == _("DC Voltage")) || (funkt == _("AC Voltage")))
	{
		dmm_range[k]->append("200 mV");
		dmm_range[k]->append("2 V");
		dmm_range[k]->append("20 V");
		dmm_range[k]->append("200 V");
		dmm_range[k]->append("1000 V");
		dmm_range[k]->set_active_text("200 mV");
	}
	else if ((funkt == _("DC Current")) || (funkt == _("AC Current")))
	{
		dmm_range[k]->append("200 uA");
		dmm_range[k]->append("200 mA");
		dmm_range[k]->append("20 A");
		dmm_range[k]->set_active_text("200 mA");
	}	
	else if (funkt == _("Resistance"))
	{
		dmm_range[k]->append("200 Ohm");
		dmm_range[k]->append("2 kOhm");
		dmm_range[k]->append("20 kOhm");
		dmm_range[k]->append("200 kOhm");
		dmm_range[k]->append("2 MOhm");
		dmm_range[k]->append("20 MOhm");
		dmm_range[k]->set_active_text("200 Ohm");
	}
	else if (funkt == _("Conductivity"))
	{
		dmm_range[k]->append("200 mS");
		dmm_range[k]->set_active_text("200 mS");
	}
	else if (funkt == _("pH"))
	{
		dmm_range[k]->append("pH");
		dmm_range[k]->set_active_text("pH");
	}
	else if (funkt == _("Temperature"))
	{
		dmm_range[k]->append("°C");
		dmm_range[k]->set_active_text("°C");
	}
	dmm_function_control[k]->queue_draw ();
	return;
}


void show_dmm_interface_options(int kanal)
{
	std::string interface;
	interface = dmm_interface[kanal]->get_active_text();
	if (interface.find ("tty")< interface.size())
		dmm_serial_options[kanal]->show();
	else dmm_serial_options[kanal]->hide();
	return;
}


void preset_mtime ()
{
	std::string dev;
	
	
	dev = dmm_name[1]->get_active_text();
	if (dev == "Lutron PH-207") min_timeout = 2000;
	// other devices following
	
	else min_timeout = 1000;
		
	dmm_mtime->set_range (0.001 * min_timeout, 3600);
	dmm_device_options->queue_draw();
	return;
}

void restart_options_x ()
{
	std::string option;
	typ dmmtyp;
	std::string akt_funktion;

	akt_funktion = project->funktion_x;
	dmmtyp = dmm[0].dmm_typ;
	option = dmm_typ[0]->get_active_text();
	if (option == _("Time")) project->funktion_x = _("Time");
	else 
	{
		if (akt_funktion == _("Time")) project->funktion_x = _("DC Voltage");
		if (option == _("Digitalmultimeter")) dmm[0].dmm_typ = DMM;
		else 
		{
			dmm[0].dmm_typ = LINEAR;
			if ((dmmtyp != DMM) && (dmmtyp != DEVICE))  dmm[0].dmm_typ = dmmtyp;
		}
	}
	show_options_Kanal_XY ();
	return;
}

void restart_options_y ()
{
	std::string option;
	typ dmmtyp;

	dmmtyp = dmm[1].dmm_typ;
	option = dmm_typ[1]->get_active_text();
	if (option == _("Digitalmultimeter")) dmm[1].dmm_typ = DMM;
	else if (option == _("Device")) dmm[1].dmm_typ = DEVICE;
	else 
	{
		dmm[1].dmm_typ = LINEAR;
		if ((dmmtyp != DMM) && (dmmtyp != DEVICE))  dmm[1].dmm_typ = dmmtyp;
	}
	
	show_options_Kanal_XY ();
	return;
}


bool dmm_exist (std::string name) //seek for dmm-name in array of installed dmms and set index
{
	int i;
	bool exist;
	
	exist = false;
	for (i=0; i<=mid; i++) if (idmm[i].dmm_name == name) //position 0 not used, name is empty
	{
		exist = true;	// dmm is installed
		id = i;			//set index
		break;
	}
	if (!exist) id = 0;
	return exist;
}

void select_dmm (int k)
{
	int i;
	std::string name;
	bool dmm_remote;
		
	name = dmm_name[k]->get_active_text ();
	if (name == "") return;
	for (i=0; i<=mid; i++)
	{
		if (idmm[i].dmm_name == name) 
		{
			// copy settings to actual dmm
			dmm_baud[k]->set_active_text(idmm[i].get_baud());
			dmm_bits[k]->set_active_text(idmm[i].get_charsize());
			dmm_flowcontrol[k]->set_active_text(idmm[i].get_flowcontrol());
			dmm_stopbits[k]->set_active_text(idmm[i].get_stopbits());
			dmm_parity[k]->set_active_text(idmm[i].get_parity());
			dmm_polling[k]->set_state(idmm[i].dmm_polling);
			dmm_scpi[k]->set_state(idmm[i].scpi);
			dmm_num_bytes[k]->set_value(idmm[i].num_bytes);
			dmm_num_val[k]->set_value(idmm[i].num_val);
			dmm_timeout[k]->set_value(idmm[i].ms_timeout);
			dmm_mtime->set_range (0.001 * idmm[i].ms_timeout, 3600);
			dmm_remote_control[k]->set_state(idmm[i].remote_cfg);
			dmm_remote = dmm_remote_control[k]->get_state ();
			if (dmm_remote)
			{
				dmm_funktion[k]->set_active_text(idmm[i].m_funkt);
				dmm_range[k]->set_active_text(idmm[i].m_range);
				dmm_DCV[k]->set_active_text (idmm[i].get_ctrlstr (DCV));
				dmm_ACV[k]->set_active_text (idmm[i].get_ctrlstr (ACV));
				dmm_DCmA[k]->set_active_text (idmm[i].get_ctrlstr (DCmA));
				dmm_ACmA[k]->set_active_text (idmm[i].get_ctrlstr (ACmA));
				dmm_DCA[k]->set_active_text (idmm[i].get_ctrlstr (DCA));
				dmm_ACA[k]->set_active_text (idmm[i].get_ctrlstr (ACA));
				dmm_Res[k]->set_active_text (idmm[i].get_ctrlstr (Res));
				dmm_Cond[k]->set_active_text (idmm[i].get_ctrlstr (Cond));
				dmm_pH[k]->set_active_text (idmm[i].get_ctrlstr (pH));
				dmm_Temp[k]->set_active_text (idmm[i].get_ctrlstr (Temp));
				dmm_control_options[k]->show();
			}
			else dmm_control_options[k]->hide();
		}
	}
	dmm_serial_options[k]->queue_draw ();	

	return;
}


///////////////// Save DMM Settings ////////////////////////////
void save_dmm_options(int k)	
{
	std::ofstream dmm_save_file;
	std::string filename;

	
	dmmoptions_save_dialog->set_action (Gtk::FILE_CHOOSER_ACTION_SAVE);
	dmmoptions_save_ok->set_label(_("Save"));
	dmmoptions_save_dialog->set_current_folder(workdir);
	dmmoptions_save_dialog->set_current_name(dmm_name[k]->get_active_text () + ".dmm");
	if (!filefilter_dmm)
	{
		filefilter_dmm = Gtk::FileFilter::create();
		filefilter_dmm->add_pattern("*.dmm");
	}
	dmmoptions_save_dialog->set_filter(filefilter_dmm);
	int result = dmmoptions_save_dialog->run();
	if (result == Gtk::RESPONSE_CANCEL)
	{
		dmmoptions_save_dialog->hide(); 
		return;
	}
    filename = dmmoptions_save_dialog->get_filename();
	dmm_save_file.open (filename); 
	if (!dmm_save_file.is_open())
	{
		fehler (_("Error writing File"));
		dmmoptions_save_dialog->hide();
		return;
	}
	
	//Write data
	dmm_save_file <<dmm_file_id<<"\n"; //ID
	try
	{
		dmm_save_file <<"dmm_name: " << dmm_name[k]->get_active_text() <<"\n";
		dmm_save_file <<"dmm_baud: " << dmm_baud[k]->get_active_text() <<"\n";
		dmm_save_file <<"dmm_charsize: " << dmm_bits[k]->get_active_text() <<"\n";
		dmm_save_file <<"dmm_flowcontrol: " << dmm_flowcontrol[k]->get_active_text() <<"\n";
		dmm_save_file <<"dmm_stopbits: " << dmm_stopbits[k]->get_active_text() <<"\n";
		dmm_save_file <<"dmm_parity: " << dmm_parity[k]->get_active_text() <<"\n";
		dmm_save_file <<"dmm_polling: " << dmm_polling[k]->get_state() <<"\n";			
		dmm_save_file <<"dmm_num_bytes: " << dmm_num_bytes[k]->get_value_as_int () <<"\n";
		dmm_save_file <<"dmm_num_val: " << dmm_num_val[k]->get_value_as_int () <<"\n";
		dmm_save_file <<"dmm_timeout: " << dmm_timeout[k]->get_value () <<"\n";
		dmm_save_file <<"dmm_remote_control: " << dmm_remote_control[k]->get_state() <<"\n";
		dmm_save_file <<"dmm_scpi: " << dmm_scpi[k]->get_state() <<"\n";
		if (dmm_remote_control[k]->get_state())
		{
			dmm_save_file << "DCV: " << dmm_DCV[k]->get_active_text () <<"\n";
			dmm_save_file << "ACV: " << dmm_ACV[k]->get_active_text () <<"\n";
			dmm_save_file << "DCmA: " << dmm_DCmA[k]->get_active_text () <<"\n";
			dmm_save_file << "ACmA: " << dmm_ACmA[k]->get_active_text () <<"\n";
			dmm_save_file << "DCA: " << dmm_DCA[k]->get_active_text () <<"\n";
			dmm_save_file << "ACA: " << dmm_ACA[k]->get_active_text () <<"\n";
			dmm_save_file << "Res: " << dmm_Res[k]->get_active_text () <<"\n";
			dmm_save_file << "Cond: " << dmm_Cond[k]->get_active_text () <<"\n";
			dmm_save_file << "pH: " << dmm_pH[k]->get_active_text () <<"\n";
			dmm_save_file << "Temp: " << dmm_Temp[k]->get_active_text () <<"\n";
		}
			
	}
	catch (const Glib::FileError & ex)
	{
		fehlercode = ex.what();
		fehler (fehlercode);
		dmmoptions_save_dialog->hide();
		return;
	}
		
	dmm_save_file.close();
	dmmoptions_save_dialog->hide();
	return;
}

///////////////// Load DMM Settings ////////////////////////////

void load_dmm_options(int k)	
{
	std::string filename, line, dmm_nm, ctrl_str;
	size_t pos,dotpos;
	int i;
	
  	dmmoptions_save_dialog->set_action (Gtk::FILE_CHOOSER_ACTION_OPEN);
	dmmoptions_save_ok->set_label(_("Open"));
	dmmoptions_save_dialog->set_current_folder(workdir);
	if (!filefilter_dmm)
	{
		filefilter_dmm = Gtk::FileFilter::create();
		filefilter_dmm->add_pattern("*.dmm");
	}
	dmmoptions_save_dialog->set_filter(filefilter_dmm);
	
	int result = dmmoptions_save_dialog->run();
	
	if (result == Gtk::RESPONSE_CANCEL)
	{
		dmmoptions_save_dialog->hide(); 
		return;
	}
    filename = dmmoptions_save_dialog->get_filename();
	
	dmm_open_file.open (filename); 
	
	//Import data
	if (dmm_open_file.is_open())
	{
		getline(dmm_open_file,line);
		if (line != dmm_file_id)
		{
			fehler (_("No Galvani DMM configuration file"));
			dmm_open_file.close();
			dmmoptions_save_dialog->hide();
			return;
		}
		dmm_nm = read_dmmoption("dmm_name: ");

		// append new dmm to list
		dmm_name[0]->append (dmm_nm);
		dmm_name[1]->append (dmm_nm);
		
		// select new dmm 
		dmm_name[k]->set_active_text (dmm_nm);
		dmm_baud[k]->set_active_text (read_dmmoption("dmm_baud: "));
		dmm_bits[k]->set_active_text (read_dmmoption("dmm_charsize: "));
		dmm_flowcontrol[k]->set_active_text (read_dmmoption("dmm_flowcontrol: "));
		dmm_stopbits[k]->set_active_text (read_dmmoption("dmm_stopbits: "));
		dmm_parity[k]->set_active_text (read_dmmoption("dmm_parity: "));
		dmm_polling[k]->set_state(get_boolstr(read_dmmoption("dmm_polling: ")));
		dmm_num_bytes[k]->set_value(get_intstr(read_dmmoption("dmm_num_bytes: ")));
		dmm_num_val[k]->set_value(get_intstr(read_dmmoption("dmm_num_val: ")));
		dmm_timeout[k]->set_value(get_intstr(read_dmmoption("dmm_timeout: ")));
		dmm_remote_control[k]->set_state(get_boolstr(read_dmmoption("dmm_remote_control: ")));
		dmm_scpi[k]->set_state(get_boolstr(read_dmmoption("dmm_scpi: ")));
		if (dmm_remote_control[k]->get_state())
		{
			ctrl_str = read_dmmoption("DCV: ");
			dmm_DCV[k]->append (ctrl_str);
			dmm_DCV[k]->set_active_text (ctrl_str);
			ctrl_str = read_dmmoption("ACV: ");
			dmm_ACV[k]->append (ctrl_str);
			dmm_ACV[k]->set_active_text (ctrl_str);
			ctrl_str = read_dmmoption("DCmA: ");
			dmm_DCmA[k]->append (ctrl_str);
			dmm_DCmA[k]->set_active_text (ctrl_str);
			ctrl_str = read_dmmoption("ACmA: ");
			dmm_ACmA[k]->append (ctrl_str);
			dmm_ACmA[k]->set_active_text (ctrl_str);
			ctrl_str = read_dmmoption("DCA: ");
			dmm_DCA[k]->append (ctrl_str);
			dmm_DCA[k]->set_active_text (ctrl_str);
			ctrl_str = read_dmmoption("ACA: ");
			dmm_ACA[k]->append (ctrl_str);
			dmm_ACA[k]->set_active_text (ctrl_str);				
			ctrl_str = read_dmmoption("Res: ");
			dmm_Res[k]->append (ctrl_str);
			dmm_Res[k]->set_active_text (ctrl_str);
			ctrl_str = read_dmmoption("Cond: ");
			dmm_Cond[k]->append (ctrl_str);
			dmm_Cond[k]->set_active_text (ctrl_str);
			ctrl_str = read_dmmoption("pH: ");
			dmm_pH[k]->append (ctrl_str);
			dmm_pH[k]->set_active_text (ctrl_str);
			ctrl_str = read_dmmoption("Temp: ");
			dmm_Temp[k]->append (ctrl_str);
			dmm_Temp[k]->set_active_text (ctrl_str);
		}			
		dmm_mtime->set_range (0.001 * dmm_timeout[1]->get_value(), 3600);
		dmm_mtime->queue_draw ();
		dmm_serial_options[k]->queue_draw ();
		
		dmm_open_file.close();
	}	
	else fehler (_("Error reading File"));
	dmmoptions_save_dialog->hide();
	
	return;
}


std::string read_dmmoption(std::string opt_item)
{
	std::string opt = "", line;
	int pos;
	
	dmm_open_file.seekg(0,std::ios::beg);
	while (!dmm_open_file.eof())
	{
		getline(dmm_open_file,line);
		pos = line.find (opt_item);
		if (pos <= line.length()) 
		{
			opt = line.substr (pos + opt_item.length ());
			break;
		}
	}
	return opt;
}

void save_all_options ()
{
	std::ofstream conf_save_file;
	std::string filename;

	filename = confdir + "/galvani.conf";
	conf_save_file.open (filename); 
	if (!conf_save_file.is_open())
	{
		fehler (_("Error writing File"));
		return;
	}
	conf_save_file <<conf_file_id<<"\n"; //ID
	
	//////// Graphics Settings //////////
	try
	{
		// Colours
		conf_save_file <<"axcol_r: " << diag->axcol_r<<"\n";
		conf_save_file <<"axcol_g: " << diag->axcol_g<<"\n";
		conf_save_file <<"axcol_b: " << diag->axcol_b<<"\n";
		conf_save_file <<"bkcol_r: " << diag->bkcol_r<<"\n";
		conf_save_file <<"bkcol_g: " << diag->bkcol_g<<"\n";
		conf_save_file <<"bkcol_b: " << diag->bkcol_b<<"\n";
		conf_save_file <<"gridcol_r: " << diag->gridcol_r<<"\n";
		conf_save_file <<"gridcol_g: " << diag->gridcol_g<<"\n";
		conf_save_file <<"gridcol_b: " << diag->gridcol_b<<"\n";
		conf_save_file <<"xycol_r: " << diag->xycol_r<<"\n";
		conf_save_file <<"xycol_g: " << diag->xycol_g<<"\n";
		conf_save_file <<"xycol_b: " << diag->xycol_b<<"\n";
		//Switches
		conf_save_file <<"grid: " << diag->grid<<"\n";
		conf_save_file <<"autoscale: " << diag->autoscale<<"\n";
		conf_save_file <<"showzero: " << diag->showzero<<"\n";
		conf_save_file <<"showtitle: " << diag->showtitle<<"\n";
		//Symbols
		conf_save_file <<"mw_symbol: " << diag->mw_symbol<<"\n";
		conf_save_file <<"symbol_filled: " << diag->symbol_filled<<"\n";
		conf_save_file <<"symw: " << diag->symw<<"\n";
		//Line style
		conf_save_file <<"mw_linestyle: " << diag->mw_linestyle<<"\n";
		//Connection between points
		conf_save_file <<"mw_line: " << diag->mw_line<<"\n";
		conf_save_file <<"mw_curve: " << diag->mw_curve<<"\n";
		
	}
	catch (const Glib::FileError & ex)
	{
		fehlercode = ex.what();
		fehler (fehlercode);
		return;
	}

	//////// DMM Settings ////////////
	try
	{
		///////////// Kanal X /////////////////////
		conf_save_file <<"Kanal X: " << project->funktion_x<<"\n";
		conf_save_file <<"dmm1_typ: " << dmm[0].dmm_typ <<"\n";
		conf_save_file <<"dmm1_name: " << dmm[0].dmm_name <<"\n";
		conf_save_file <<"dmm1_interface: " << dmm[0].int_face <<"\n";
		conf_save_file <<"dmm1_baud: " << dmm[0].get_baud() <<"\n";
		conf_save_file <<"dmm1_charsize: " << dmm[0].get_charsize() <<"\n";
		conf_save_file <<"dmm1_flowcontrol: " << dmm[0].get_flowcontrol () <<"\n";
		conf_save_file <<"dmm1_stopbits: " << dmm[0].get_stopbits () <<"\n";
		conf_save_file <<"dmm1_parity: " << dmm[0].get_parity() <<"\n";
		conf_save_file <<"dmm1_polling: " << dmm[0].dmm_polling <<"\n";
		conf_save_file <<"dmm1_num_bytes: " << dmm[0].num_bytes <<"\n";
		conf_save_file <<"dmm1_num_val: " << dmm[0].num_val <<"\n";
		conf_save_file <<"dmm1_timeout: " << dmm[0].ms_timeout <<"\n";
		conf_save_file <<"dmm1_mfunkt: " << dmm[0].m_funkt <<"\n";
		conf_save_file <<"dmm1_mrange: " << dmm[0].m_range <<"\n";
		conf_save_file <<"dmm1_remote_control: " << dmm[0].remote_cfg <<"\n";
		conf_save_file <<"dmm1_scpi: " << dmm[0].scpi <<"\n";
		conf_save_file << "dmm1_DCV: " << dmm[0].get_ctrlstr (DCV) <<"\n";
		conf_save_file << "dmm1_ACV: " << dmm[0].get_ctrlstr (ACV) <<"\n";
		conf_save_file << "dmm1_DCmA: " << dmm[0].get_ctrlstr (DCmA) <<"\n";
		conf_save_file << "dmm1_ACmA: " << dmm[0].get_ctrlstr (ACmA) <<"\n";
		conf_save_file << "dmm1_DCA: " << dmm[0].get_ctrlstr (DCA) <<"\n";
		conf_save_file << "dmm1_ACA: " << dmm[0].get_ctrlstr (ACA) <<"\n";
		conf_save_file << "dmm1_Res: " << dmm[0].get_ctrlstr (Res) <<"\n";
		conf_save_file << "dmm1_Cond: " << dmm[0].get_ctrlstr (Cond) <<"\n";
		conf_save_file << "dmm1_pH: " << dmm[0].get_ctrlstr (pH) <<"\n";
		conf_save_file << "dmm1_Temp: " << dmm[0].get_ctrlstr (Temp) <<"\n";
		
		///////////// Kanal Y /////////////////////
		conf_save_file <<"Kanal Y: " << project->funktion_y<<"\n";
		conf_save_file <<"dmm2_typ: " << dmm[1].dmm_typ <<"\n";
		conf_save_file <<"dmm2_name: " << dmm[1].dmm_name <<"\n";
		conf_save_file <<"dmm2_interface: " << dmm[1].int_face <<"\n";
		conf_save_file <<"dmm2_baud: " << dmm[1].get_baud() <<"\n";
		conf_save_file <<"dmm2_charsize: " << dmm[1].get_charsize() <<"\n";
		conf_save_file <<"dmm2_flowcontrol: " << dmm[1].get_flowcontrol () <<"\n";
		conf_save_file <<"dmm2_stopbits: " << dmm[1].get_stopbits () <<"\n";
		conf_save_file <<"dmm2_parity: " << dmm[1].get_parity() <<"\n";
		conf_save_file <<"dmm2_polling: " << dmm[1].dmm_polling <<"\n";
		conf_save_file <<"dmm2_num_bytes: " << dmm[1].num_bytes <<"\n";
		conf_save_file <<"dmm2_num_val: " << dmm[1].num_val <<"\n";
		conf_save_file <<"dmm2_timeout: " << dmm[1].ms_timeout <<"\n";
		conf_save_file <<"dmm2_mfunkt: " << dmm[1].m_funkt <<"\n";
		conf_save_file <<"dmm2_mrange: " << dmm[1].m_range <<"\n";
		conf_save_file <<"dmm2_remote_control: " << dmm[1].remote_cfg <<"\n";
		conf_save_file <<"dmm2_scpi: " << dmm[1].scpi <<"\n";
		conf_save_file << "dmm2_DCV: " << dmm[1].get_ctrlstr (DCV) <<"\n";
		conf_save_file << "dmm2_ACV: " << dmm[1].get_ctrlstr (ACV) <<"\n";
		conf_save_file << "dmm2_DCmA: " << dmm[1].get_ctrlstr (DCmA) <<"\n";
		conf_save_file << "dmm2_ACmA: " << dmm[1].get_ctrlstr (ACmA) <<"\n";
		conf_save_file << "dmm2_DCA: " << dmm[1].get_ctrlstr (DCA) <<"\n";
		conf_save_file << "dmm2_ACA: " << dmm[1].get_ctrlstr (ACA) <<"\n";
		conf_save_file << "dmm2_Res: " << dmm[1].get_ctrlstr (Res) <<"\n";
		conf_save_file << "dmm2_Cond: " << dmm[1].get_ctrlstr (Cond) <<"\n";
		conf_save_file << "dmm2_pH: " << dmm[1].get_ctrlstr (pH) <<"\n";
		conf_save_file << "dmm2_Temp: " << dmm[1].get_ctrlstr (Temp) <<"\n";
		
		conf_save_file <<"Messintervall: " << diag->mtime <<"\n";		
	}
	catch (const Glib::FileError & ex)
	{
		fehlercode = ex.what();
		fehler (fehlercode);
		return;
	}
	conf_save_file.close();
	return;
}

void load_all_options ()
{
	std::string filename, line;
	std::string mw_symbol, mw_linestyle, dmm_nm;
	size_t pos,dotpos;

	filename = confdir + "/galvani.conf";
	conf_open_file.open (filename); 
	
	//Read settings
	if (conf_open_file.is_open())
	{
		getline(conf_open_file,line);
		if (line != conf_file_id)
		{
			fehler (_("No Galvani Configuration File"));
			conf_open_file.close();
			return;
		}
		//////// Graphics Settings //////////
		diag->axcol_r = get_dbstr (read_option("axcol_r: "));
		diag->axcol_g = get_dbstr (read_option("axcol_g: "));
		diag->axcol_b = get_dbstr (read_option("axcol_b: "));
		diag->bkcol_r = get_dbstr (read_option("bkcol_r: "));
		diag->bkcol_g = get_dbstr (read_option("bkcol_g: "));
		diag->bkcol_b = get_dbstr (read_option("bkcol_b: "));
		diag->gridcol_r = get_dbstr (read_option("gridcol_r: "));
		diag->gridcol_g = get_dbstr (read_option("gridcol_g: "));
		diag->gridcol_b = get_dbstr (read_option("gridcol_b: "));
		diag->xycol_r = get_dbstr (read_option("xycol_r: "));
		diag->xycol_g = get_dbstr (read_option("xycol_g: "));
		diag->xycol_b = get_dbstr (read_option("xycol_b: "));
		if (read_option("grid: ") == "1") diag->grid = true; else diag->grid = false;
		if (read_option("autoscale: ") == "1") diag->autoscale = true; else diag->autoscale = false;
		if (read_option("showzero: ") == "1") diag->showzero = true; else diag->showzero = false;
		if (read_option("showtitle: ") == "1") diag->showtitle = true; else diag->showtitle = false;
		mw_symbol = read_option("mw_symbol: ");
		if (mw_symbol == "1") diag->mw_symbol = cross;
		else if (mw_symbol == "2") diag->mw_symbol = square;
		else if (mw_symbol == "3") diag->mw_symbol = diamond;
		else if (mw_symbol == "4")diag->mw_symbol = circle;
		else diag->mw_symbol = none;
		if (read_option("symbol_filled: ") == "1") diag->symbol_filled = true; else diag->symbol_filled = false;
		diag->symw = get_intstr (read_option("symw: "));
		mw_linestyle = read_option ("mw_linestyle: ");
		if (mw_linestyle == "1") diag->mw_linestyle = pointed;
		else if (mw_linestyle == "2") diag->mw_linestyle = dashed;
		else diag->mw_linestyle = solid;
		if (read_option("mw_line: ") == "1") diag->mw_line = true; else diag->mw_line = false;
		if (read_option("mw_curve: ") == "1") diag->mw_curve = true; else diag->mw_curve = false;
		
		
		//////// DMM Settings ////////////
		project->funktion_x = read_option("Kanal X: ");
		dmm[0].dmm_typ = get_dmmtyp (read_option("dmm1_typ: "));
		dmm_nm = read_option("dmm1_name: ");
		dmm[0].dmm_name = dmm_nm;
		dmm_name[0]->prepend (dmm_nm);
		dmm_name[0]->set_active_text (dmm_nm);
		dmm[0].int_face = read_option("dmm1_interface: ");
		dmm[0].set_baud(read_option("dmm1_baud: "));
		dmm[0].set_charsize(read_option("dmm1_charsize: "));
		dmm[0].set_flowcontrol (read_option("dmm1_flowcontrol: "));
		dmm[0].set_stopbits (read_option("dmm1_stopbits: "));
		dmm[0].set_parity (read_option("dmm1_parity: "));
		dmm[0].dmm_polling = get_boolstr (read_option ("dmm1_polling: " ));
		dmm[0].num_bytes = get_intstr(read_option("dmm1_num_bytes: "));
		dmm[0].num_val = get_intstr(read_option("dmm1_num_val: "));
		dmm[0].ms_timeout = get_intstr(read_option("dmm1_timeout: "));
		dmm[0].m_funkt = read_option("dmm1_mfunkt: ");
		dmm[0].m_range = read_option("dmm1_mrange: ");
		dmm[0].remote_cfg = get_boolstr (read_option ("dmm1_remote_control: " ));
		dmm[0].scpi = get_boolstr (read_option ("dmm1_scpi: " ));
		dmm[0].set_ctrlstr (DCV, read_option("dmm1_DCV: "));
		dmm_DCV[0]->append (read_option("dmm1_DCV: "));
		dmm[0].set_ctrlstr (ACV, read_option("dmm1_ACV: "));
		dmm_ACV[0]->append (read_option("dmm1_ACV: "));
		dmm[0].set_ctrlstr (DCmA, read_option("dmm1_DCmA: "));
		dmm_DCmA[0]->append (read_option("dmm1_DCmA: "));
		dmm[0].set_ctrlstr (ACmA, read_option("dmm1_ACmA: "));
		dmm_ACmA[0]->append (read_option("dmm1_ACmA: "));
		dmm[0].set_ctrlstr (DCA, read_option("dmm1_DCA: "));
		dmm_DCA[0]->append (read_option("dmm1_DCA: "));
		dmm[0].set_ctrlstr (ACA, read_option("dmm1_ACA: "));
		dmm_ACA[0]->append (read_option("dmm1_ACA: "));
		dmm[0].set_ctrlstr (Res, read_option("dmm1_Res: "));
		dmm_Res[0]->append (read_option("dmm1_Res: "));
		dmm[0].set_ctrlstr (Cond, read_option("dmm1_Cond: "));
		dmm_Cond[0]->append (read_option("dmm1_Cond: "));
		dmm[0].set_ctrlstr (pH, read_option("dmm1_pH: "));
		dmm_pH[0]->append (read_option("dmm1_pH: "));
		dmm[0].set_ctrlstr (Temp, read_option("dmm1_Temp: "));
		dmm_Temp[0]->append (read_option("dmm1_Temp: "));
		project->funktion_y = read_option("Kanal Y: ");
		dmm[1].dmm_typ = get_dmmtyp (read_option("dmm2_typ: "));
		dmm_nm= read_option("dmm2_name: ");
		dmm[1].dmm_name = dmm_nm;
		dmm_name[1]->prepend (dmm_nm);
		dmm_name[1]->set_active_text (dmm_nm);
		dmm[1].int_face = read_option("dmm2_interface: ");
		dmm[1].set_baud(read_option("dmm2_baud: "));
		dmm[1].set_charsize(read_option("dmm2_charsize: "));
		dmm[1].set_flowcontrol (read_option("dmm2_flowcontrol: "));
		dmm[1].set_stopbits (read_option("dmm2_stopbits: "));
		dmm[1].set_parity (read_option("dmm2_parity: "));
		dmm[1].dmm_polling = get_boolstr (read_option ("dmm2_polling: " ));
		dmm[1].num_bytes = get_intstr(read_option("dmm2_num_bytes: "));
		dmm[1].num_val = get_intstr(read_option("dmm2_num_val: "));
		dmm[1].ms_timeout = get_intstr(read_option("dmm2_timeout: "));
		dmm[1].m_funkt = read_option("dmm2_mfunkt: ");
		dmm[1].m_range = read_option("dmm2_mrange: ");
		dmm[1].remote_cfg = get_boolstr (read_option ("dmm2_remote_control: " ));
		dmm[1].scpi = get_boolstr (read_option ("dmm2_scpi: " ));
		dmm[1].set_ctrlstr (DCV, read_option("dmm2_DCV: "));
		dmm_DCV[1]->append (read_option("dmm2_DCV: "));
		dmm[1].set_ctrlstr (ACV, read_option("dmm2_ACV: "));
		dmm_ACV[1]->append (read_option("dmm2_ACV: "));
		dmm[1].set_ctrlstr (DCmA, read_option("dmm2_DCmA: "));
		dmm_DCmA[1]->append (read_option("dmm2_DCmA: "));
		dmm[1].set_ctrlstr (ACmA, read_option("dmm2_ACmA: "));
		dmm_ACmA[1]->append (read_option("dmm2_ACmA: "));
		dmm[1].set_ctrlstr (DCA, read_option("dmm2_DCA: "));
		dmm_DCA[1]->append (read_option("dmm2_DCA: "));
		dmm[1].set_ctrlstr (ACA, read_option("dmm2_ACA: "));
		dmm_ACA[1]->append (read_option("dmm2_ACA: "));
		dmm[1].set_ctrlstr (Res, read_option("dmm2_Res: "));
		dmm_Res[1]->append (read_option("dmm2_Res: "));
		dmm[1].set_ctrlstr (Cond, read_option("dmm2_Cond: "));
		dmm_Cond[1]->append (read_option("dmm2_Cond: "));
		dmm[1].set_ctrlstr (pH, read_option("dmm2_pH: "));
		dmm_pH[1]->append (read_option("dmm2_pH: "));
		dmm[1].set_ctrlstr (Temp, read_option("dmm2_Temp: "));
		dmm_Temp[1]->append (read_option("dmm2_Temp: "));

		diag->mtime = get_intstr (read_option("Messintervall: "));
		
		conf_open_file.close();
	}
	else fehler (_("Error Reading Configuration File"));
	return;
}

std::string read_option(std::string opt_item)
{
	std::string opt = "", line;
	int pos;
	
	conf_open_file.seekg(0,std::ios::beg);
	while (conf_open_file.peek() != EOF)
	{
		getline(conf_open_file,line);
		pos = line.find (opt_item);
		if (pos <= line.length()) 
		{
			opt = line.substr (pos + opt_item.length ());
			break;
		}
	}
	
	return opt;
}

double get_dbstr(std::string num_str)
{
	double result;
	std::string dezimal, error_str;
	size_t dotpos;
	struct lconv *lc  = localeconv();

	lc=localeconv();
	dezimal = lc->decimal_point;
	if (dezimal == ",")
	{
		dotpos = num_str.find (".");
		if (dotpos <= num_str.length()) num_str.replace (dotpos,1,",");
	}
	try
	{
		result = stod(num_str);
	}
	catch (const std::invalid_argument& ia) 
	{
		error_str = _("Conversion to double: ");
		error_str += num_str;
		fehler(error_str);
    	result = 0.0;
	}
	catch (const std::out_of_range& oor) 
	{
		error_str = _("Conversion to double: ");
		error_str += num_str;
		fehler(error_str);
    	result = 0.0;
	}
	return result;
}

int get_intstr(std::string num_str)
{
	int result;
	std::string error_str;
	

	try
	{
		result = stoi(num_str);
	}
	catch (const std::invalid_argument& ia) 
	{
		error_str = _("Conversion to integer: ");
		error_str += num_str;
		fehler(error_str);
    	result = 0;
	}
	catch (const std::out_of_range& oor) 
	{
		error_str = _("Conversion to integer: ");
		error_str += num_str;
		fehler(error_str);
    	result = 0;
	}
	return result;
}

bool get_boolstr(std::string num_str)
{
	bool result;
	std::string error_str;
	

	if (num_str == "1") result = true;
	else if (num_str == "0") result = false;
	else
	{
		error_str = _("Conversion to bool: ");
		error_str += num_str;
		fehler(error_str);
    	result = false;
	}
	return result;
}

std::vector<std::string> get_usb_ports ()
{
	std::vector<std::string> ports;
	std::string found;
	const fs::path usbdev{"/dev"};
	const fs::path usb{"/dev/usb"};
	int usb_pos;
	
	for (auto const& dir_entry : fs::directory_iterator{usbdev}) 
    {
		try
		{
			found = dir_entry.path();
		}
		catch (const std::exception & ex)
		{
			
		}
		usb_pos = found.find ("usb");
		
		if ((usb_pos < found.size()) && (!fs::is_directory(dir_entry)))
		    ports.push_back (dir_entry.path());
    }

	try
	{
		if (fs::exists(usb))
		{
			for (auto const& dir_entry : fs::directory_iterator{usb}) 
    		{
       			ports.push_back (dir_entry.path());
    		}
		}
		
	}
	catch (fs::filesystem_error const& ex) { }
	
	return ports;
}


////////////// Set Device Options //////////////////
void set_device_options_lutron_ph207 ()
{
	dmm[1].set_baud ("9600");
	dmm[1].set_charsize ("7");
	dmm[1].set_stopbits ("2");
	dmm[1].dmm_polling = false;
	dmm[1].num_bytes = 16;
	// min m_time: 2 Sec
	dmm[1].ms_timeout = 2000;
	project->funktion_y = "pH";
	return;
}


