#!/usr/bin/perl -T
# $Id: rig_setup.cgi,v 1.138 2020/11/23 07:40:38 sqko Exp $
############################################################
############################################################
###                                                      ###
###   Originally designed by Soeren Koch                 ###
###                                                      ###
###   Impelemented by Soeren Koch                        ###
###                                                      ###
###   Copyright by Soeren Koch January 2011              ###
###                                                      ###
############################################################
############################################################


use strict;
use warnings;
use CGI qw(:standard :netscape);
use RFC::Main;
use RFC::Rig;
use RFC::RFCCGI qw(:cgi :html);
use RFC::Header;
use RFC::Device;

#### List of device types with non-default setup ###
my %setup = ();
$setup{'MFC'} = \&MFC;
$setup{'tempcontrol'} = \&tempcontrol;
$setup{'templog'} = \&templog;
$setup{'multiplex'} = \&multiplexer;
$setup{'water'} = \&water;
$setup{'gas'} = \&gas;
$setup{'filter'} = \&filter;
$setup{'math'} = \&math;

my $acmode = get_cv('global','access_mode');
$acmode = 'celltest' unless ($acmode);
my $r = param('rig');
unless ($r)
{
    print header();
    print "No rig specified!\n";
    exit;
}
my $rig = RFC::Rig->new($r);
my $legacy = 0;
$legacy = 1 if ($rig->get_cv('main','legacy_mode') && $rig->get_cv('main','legacy_mode') =~ /yes/i);
my $usermode = user_auth($acmode,'c');
$usermode = 1 if (RFC::RFCCGI::rig_mode());
my $modifymode = user_auth($acmode,'m'); 
$modifymode = rig_cert() if (RFC::RFCCGI::rig_mode());
if (RFC::RFCCGI::rig_mode())
{
    ####  Read and use mode deprecated after initialisation of rig authentification ####
    $usermode = 1;
}
####
unless (RFC::RFCCGI::rig_auth())
{
    $usermode = 0;
    $modifymode = 0;
}
unless ($modifymode)
{
    $modifymode = RFC::Main::passwd_client('isadmin',get_id());
}

my @devicelist = $rig->list_types();

if (!defined(param))
{
    &print_header("Please log in to the $name");
    print '<center>';
    RFC::RFCCGI::login();
    print '</center>';
    &print_end;
}
else
{
    #### husk at aendre accessparameter til det relevante for scriptet!! ####
    if (login_ok() && ($usermode || $modifymode))
    { 
        &print_header("Configuration of rig $rig");
        top_nav_bar_start;
	top_no_button;	
	top_no_button;
        if ($modifymode)
        {
            top_nav_bar_button('','calibration','','Setup thermocouple calibration','s1','rig,'.$rig->name.',1');
        }
        else
        {
            top_no_button;
        }
	tab_newrow;
	&js_back();
	top_js_return('#006600','white');
        if ($modifymode)
        {
            top_nav_bar_button('rig_conf.cgi','','','Manual configuration','s1','rig,'.$rig->name.',1');
        }
        else
        {
            top_no_button;
        }
	if ($rig->list_devices_control('PSU') || $rig->list_devices_control('analog'))
	{
	    top_nav_bar_button('iv_setup.cgi','','','Setup i-V curve parameters','s3','rig,'.$rig->name.',1');
	}
	else
	{
	    top_no_button;
	}
	top_nav_bar_button('rig_main.cgi','','','To rig'.$rig->name.' main page','s3','rig,'.$rig->name.',1');
	top_nav_bar_button('main.cgi','','','To menu','s4');
	end_top_bar;
        param(-name=>'action',-value=>'')  unless (defined(param('action')));
	$_ = param('action');
      CASE:
	{
	    ### Insert case statements ###
	    ### Default response ####
    	    &insert_data_form;
	}	
	print_end;
    }
    else 
    {
	&not_auth;
    }
}
    
$rig = undef;
exit;



sub insert_data_form
{
    print <<END;


<script language="javascript">

function new_device()
{
    var text = prompt("New device name:",'');
    if (text == null)
    {
        return false;
    }
    var reg = /^\\w+\$/;
    if (!reg.test(text))
    {
	alert("Device names must be a single string containing only alpahnumeric characters and no spaces!");
	return false;
    }
    var type = document.device_select.type.value;
    run_ajax('new_device.cgi','&action=new_device&type='+type+'&value='+text,set_new_device);
}


function set_new_device(res)
{
    var name = '';
    var arr = res.split("\\n");
    if (arr[0] == "OK" || arr[0] == "WARN")
    {
        if (arr[0] == "WARN")
        {
            alert(arr[3]);
        }
        name = arr[2];
    }
    else
    {
        alert(arr[0]);
	return false;
    }
    var opt = document.createElement("option");
    opt.text = name;
    opt.value = name;
    document.device_select.device.options.add(opt);
    var idx = document.device_select.device.length - 1;
    document.device_select.device.selectedIndex = idx;
    document.device_select.submit();
}

</script>



END


    print '<center>';
    print '<table border=0 cellspacing=5 cellpadding=0 style="width:100%"><tr height=20>';
    print '<td width="5%"></td>';
    print '<td width="14%"></td>';
    print '<td width="2%"></td>';
    print '<td width="14%"></td>';
    print '<td width="14%"></td>';
    print '<td width="2%"></td>';
    print '<td width="14%"></td>';
    print '<td width="14%"></td>';
    print '<td width="2%"></td>';
    print '<td width="14%"></td>';
    print '<td width="5%"></td>';
    print '</tr>';
    print '<tr><td colspan=11 class="heading">';
    print "Setup for rig ".$rig->name;
    print '</td></tr>';
    my %h = ();
    foreach (@devicelist)
    {
	$h{$_} = ucfirst($rig->get_uiname($_));
    }
    unshift @devicelist,'';
    my $type = get_CGI_value_clean('type');
    print '<tr><td></td><th colspan=2> Select device type </th><td>';
    print start_form(-name=>'type');
    print_hidden_rig();
    print popup_menu(-name=>'type',-values=>[(@devicelist)],-labels=>\%h,-class=>'textfield',-default=>$type,-force=>1,-onchange=>'document.type.submit()');
    print end_form();
    unless ($type)
    {
	print '</td></tr>';
	print '</table>';
	return;
    }
    ### Default setup ###
    my @list = sort {lc($a) cmp lc($b)} $rig->avaliable_devices_nofilter($type);
    unshift @list,'';
    my $device = get_CGI_value_clean('device');
    print '<th colspan=2> Select device: </th><td>';
    print start_form(-name=>'device_select');
    print_hidden_rig();
    print hidden(-name=>'type',-value=>$type,-force=>1);
    print popup_menu(-name=>'device',-values=>[(@list)],-class=>'textfield',-default=>$device,-force=>1,-onchange=>'document.device_select.submit()',-id=>'device_list');
    print hidden(-name=>'dname',-value=>'',-force=>1);
    print hidden(-name=>'action',-value=>'',-force=>1);
    print end_form();
    print '</td><td>';
    print button(-name=>$type,-value=>'New '.$rig->get_uiname($type),-class=>'s2',-Onclick=>'new_device()');
    print '</td></tr>';
    unless ($device)
    {
	print '</table>';
	return;	
    }
    print "\n\n";
    print start_form(-name=>'device');
    print_hidden_rig();
    print hidden(-name=>'type',-value=>$type,-force=>1);
    print hidden(-name=>'typename',-value=>$type,-force=>1);
    print hidden(-name=>'device',-value=>$device,-force=>1);
    my $dev = undef;
    foreach my $name ($rig->avaliable_devices('filter'))
    {
	next unless $name eq $device;
	$dev = $rig->init_device('filter',$device);
	$type = 'filter';
	last;
    }
    $dev = $rig->init_device($type,$device) unless ($dev);
    print hidden(-name=>'section',-value=>$dev->sectionname,-force=>1); 
    print end_form();
    param(-name=>'section',-value=>$dev->sectionname)  unless (defined(param('section')));
    my @devtypes = RFC::Device::list_device_types($type);
    unless ($dev)
    {
	print center(h1({-class=>'Alert'},"Error: No device id returned for device $type $device"));
	return;
    }
    my @arr = ();
    if (exists($setup{$type}))
    {
	@arr = $setup{$type}->($device,$dev,\@devtypes);
    }
    else
    {
	@arr = print_default($device,$dev,\@devtypes);
    }
    my $checked = 0;
    foreach ($rig->list_names($type))
    {
	$checked = 1 if ($_ eq $device);
    }
    &print_ui_fn($dev,@arr);
    print '<tr><th colspan=11 class="Alert">';
    print checkbox(-name=>'include',-value=>'1',-label=>'Include '.$rig->get_uiname($type)." '$device' in data logging and/or automated control system",-class=>'Alert',-checked=>$checked,-force=>1,-onchange=>'change_include(this)',-id=>'include');
    print '<tr><td colspan=2></td><td colspan=3>';
    print button(-name=>'test_device',-value=>"Test $device",-onclick=>'run_test()',-class=>'s3');
    print '</td><td colspan=3>';
    print button(-name=>'moditor_device',-value=>"Monitor $device",-onclick=>'run_monitor()',-class=>'s4');
    print "</td></tr>";


    print '</table></center>';
    print <<END;

<script language="javascript">


function change_include(element)
{
    var n = element.name;
    var val = 0;
    if (element.checked == true)
    {
	val = 1;
    }
    if (val == 0)
    {
	if (!confirm('Exclude $device from data logging'))
	{
	    element.checked = true;
	    return false;
	}
    }
    var typename = document.device.typename.value;
    var dev = document.device.device.value;
    element.disabled = true;
    run_ajax('change_config.cgi','&action=include_device&type='+typename+'&device='+dev+'&value='+val+'&key='+n,set_checkbox);
}

function run_monitor()
{
    var typename = document.device.typename.value;
    var dev = document.device.device.value;
    var rig = document.login_info.rig.value;
    var user = document.login_info.name.value;
    var pass = document.login_info.pass.value;
    var time = document.login_info.time.value;
    var js = document.login_info.jscheck.value;
    var hidden = "?rig="+rig+"&type="+typename+"&device="+dev+"&name="+user+"&pass="+pass+"&time="+time+"&jscheck="+js;
    var myWin=window.open('monitor.cgi'+hidden,'windowRef','width=400,height=350,left=100,top=100');
    myWin.location.href = 'monitor.cgi'+hidden;
    if (!myWin.opener)
        myWin.opener = self;
    myWin.focus();
}

function plot_data(data)
{
    data = data.replace(/\\n/g,",");
    var url = 'plot.cgi?data=' + data +'&size=0.6,0.6';
    var myWin=window.open(url,'windowRef','width=600,height=500,left=100,top=100');
    myWin.location.href = url;
    if (!myWin.opener)
        myWin.opener = self;
    myWin.focus();
}


function run_test()
{
    var typename = document.device.typename.value;
    var dev = document.device.device.value;
    run_ajax('change_config.cgi','&action=test_device&type='+typename+'&device='+dev,alert);
}

function set_checkbox(res)
{
    var arr = res.split("\\n");
    if (arr[0] == "OK" || arr[0] == "WARN")
    {
        if (arr[0] == "WARN")
        {
            alert(arr[3]);
        }
        var obj = document.getElementById(arr[1]);
        obj.disabled = false;
	var val = arr[2];
        obj.checked = false;
	if (val == 1)
	{
	    obj.checked = true;
	}
    }
    else
    {
        alert(arr[0]);
        var obj = document.getElementById(arr[1]);
        obj.disabled = false;
        obj.checked = false;
	var val = arr[2];
	if (val == 1)
	{
	    obj.checked = true;
	}
    }
}


function set_val(res)
{
    var arr = res.split("\\n");
    if (arr[0] == "OK" || arr[0] == "WARN")
    {
        if (arr[0] == "WARN")
        {
            alert(arr[3]);
        }
        var obj = document.getElementById(arr[1]);
        obj.disabled = false;
        obj.value = arr[2];
    }
    else
    {
        alert(arr[0]);
        var obj = document.getElementById(arr[1]);
        obj.disabled = false;
        obj.value = arr[2];
    }
}

function set_type(res)
{
    var arr = res.split("\\n");
    if (arr[0] == "OK" || arr[0] == "WARN")
    {
        if (arr[0] == "WARN")
        {
            alert(arr[3]);
        }
        var obj = document.getElementById(arr[1]);
        obj.disabled = false;
        obj.value = arr[2];
    }
    else
    {
        alert(arr[0]);
        var obj = document.getElementById(arr[1]);
        obj.disabled = false;
        obj.value = arr[2];
    }
    document.device_select.submit();
}


function change_val(element)
{
    var n = element.name;
    var val = element.value;
    var sec = document.device.section.value;
    element.disabled = true;
    run_ajax('change_config.cgi','&action=change_config_value&section='+sec+'&key='+n+'&value='+val,set_val);
}

function change_type(element)
{
    var n = element.name;
    var val = element.value;
    var sec = document.device.section.value;
    element.disabled = true;
    run_ajax('change_config.cgi','&action=change_config_value&section='+sec+'&key='+n+'&value='+val,set_type);
}

function set_spline(res)
{
    var arr = res.split("\\n");
    if (arr[0] == "OK" || arr[0] == "WARN")
    {
        if (arr[0] == "WARN")
        {
            alert(arr[3]);
        }
        var obj = document.getElementById(arr[1]);
        obj.disabled = false;
	obj.value = arr[2].replace(/,/g,"\\n");
    }
    else
    {
        alert(arr[0]);
        var obj = document.getElementById(arr[1]);
        obj.disabled = false;
	obj.value = arr[2].replace(/,/g,"\\n");
    }
}


function change_spline(element)
{
    var n = element.name;
    var val = element.value;
    val = val.replace(/\\n/g,",");
    var sec = document.device.section.value;
    element.disabled = true;
    run_ajax('change_config.cgi','&action=change_config_value&section='+sec+'&key='+n+'&value='+val,set_spline);
}

function show_help(key)
{
    var typename = document.device.typename.value;
    var dev = document.device.device.value;
    var query = '&action=help_tag&type='+typename+'&device='+dev+"&key="+key;
    run_ajax('change_config.cgi',query,alert);
}

function find_tty()
{
    var query = '&action=list_ttys';
    run_ajax('ajax.cgi',query,alert);
}

</script>

END

}    

sub print_ui_fn($)
{
    my $dev = shift;
    my @count_list = @_;
    my $count = 0;
#    unless ($dev && $modifymode) ### Normal users also need access to function buttons #
    unless ($dev)
    {
	print '<tr valign=top><td></td>';
	while ($count_list[$count])
	{
	    if ($count++ > 1)
	    {
		$count = 0;
		print '</tr>',"\n";
		print '<tr valign=top><td></td>';
		foreach (@count_list)
		{
		    $_-- if ($_);
		}
	    }
	}
	print '</tr>';
	print '<tr valign=top><td></td></tr>';
	return;   
    }
    my @names = $dev->ui_fn_names();
    unless (@names)
    {
	print '<tr valign=top><td></td>';
	while ($count_list[$count])
	{
	    if ($count++ > 1)
	    {
		$count = 0;
		print '</tr>',"\n";
		print '<tr valign=top><td></td>';
		foreach (@count_list)
		{
		    $_-- if ($_);
		}
	    }
	}
	print '</tr>';
	print '<tr valign=top><td></td></tr>';
	return;   
    }
    my $type = get_CGI_value_clean('type');
    my $device = get_CGI_value_clean('device');
    foreach my $key (@names)
    {
	print '<tr valign=top><td></td>' unless ($count);
	while ($count_list[$count])
	{
	    print '<td colspan=2></td>';
	    if ($count++ > 1)
	    {
		$count = 0;
		print '</tr>',"\n";
		print '<tr valign=top><td></td>';
		foreach (@count_list)
		{
		    $_-- if ($_);
		}
	    }
	}
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_fn_help('$key')");
	print '</td><td>';
	my $args = $dev->ui_fn_args($key);
	my $function = "run_no_args('$type','$device','$key')";
	$function = "run_args('$type','$device','$key',$args)" if ($args);
	print button(-name=>'activate',-value=>'Run function',-class=>'run_function',-onclick=>$function);
	print '</td>';
        if ($count++ > 1)
        {
            $count = 0;
            print '</tr>',"\n";
            foreach (@count_list)
            {
                $_-- if ($_);
            }
        }
    }
    print '<tr valign=top><td></td>';
    while ($count_list[$count])
    {
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	    print '<tr valign=top><td></td>';
	    foreach (@count_list)
	    {
		$_-- if ($_);
	    }
	}
    }
    print '</tr>';
    my $user = &get_user();
    print <<END;

<script>

function show_fn_help(key)
{
    var typename = document.device.typename.value;
    var dev = document.device.device.value;
    var query = '&action=help_func&type='+typename+'&device='+dev+"&func_name="+key;
    run_ajax('change_config.cgi',query,alert);
}

function process_result(res)
{
    var arr = res.split("\\n");
    if (arr[0] == "OK")
    {
	arr.shift();
	var reload = false;
	if (arr[arr.length - 1] == 'RELOAD')
	{
	    reload = true;
	    arr.pop();
	}
	alert(arr.join("\\n"));
	if (reload)
	{	
	    document.device_select.submit();
	}
    }
    else
    {
        alert(res);
    }
}

function run_args(type,dev,fname,a)
{
    var args = '$user';
    if (a == 1)
    {
	arg1 = prompt("Input argument to "+fname,'');
	if (arg1 == null)
	{
	    return false;
	}
	args = arg1+','+args;
	run_ajax('rig_ajax_run.cgi','&action=run_device_function&type='+type+'&dname='+dev+'&function='+fname+'&arguments='+args,process_result);
    }
}

function run_no_args(type,dev,fname)
{
    var args = '$user';
    if (confirm('Run function '+fname))
    {
	run_ajax('rig_ajax_run.cgi','&action=run_device_function&type='+type+'&dname='+dev+'&function='+fname+'&arguments='+args,process_result);
    }
}

</script>

END

}

sub print_default($$$)
{
    my $device = get_CGI_value_clean('device');
    my $type = get_CGI_value_clean('type');
    my $section = get_CGI_value_clean('section');
    my $str = shift;
    my $dev = shift;
    my $typeref = shift;
    my @devtypes = @{$typeref};
    unshift @devtypes,'' unless ($devtypes[0] eq '');
    print '<tr><td colspan=11 class="heading">';
    print xss("Configuring $type $str"); 
    print "</td></tr>";
    my $info = $dev->info_string();
    if ($info)
    {
	print '<tr><td colspan=11 class="heading">';
	print xss("Notice: $info"); 
	print "</td></tr>";	
    }
    my @tags = $dev->setup_tags();
    @tags = $dev->setup_tags_legacy() if ($legacy);
    unshift @tags,'type' unless ($dev->type eq 'Multiline' || $dev->type eq 'PSUMulti' || $dev->type =~ /logic\sdevice|Adapter|Alert|^Trigger|Modulus/i);
    my %setup = ();
    foreach my $tag (@tags)
    {
	my $val = $rig->get_cv($section,$tag);
	if ($tag eq 'mode')
	{
	    $val = 'Automatic' if (defined($val) && $val =~ /auto/i);
	}
	$val = $dev->get_default($tag) unless (defined($val));
	$val = '' unless defined($val);
	$setup{$tag} = $val;
    }
    my $count = 0;
    my @count_list = (0,0,0);
    foreach my $key (@tags)
    {
	my %labels = ();
	print '<tr valign=top><td></td>' unless ($count);
	while ($count_list[$count])
	{
	    print '<td colspan=3></td>';
	    if ($count++ > 1)
	    {
		$count = 0;
		print '</tr>',"\n";
		print '<tr valign=top><td></td>';
		foreach (@count_list)
		{
		    $_-- if ($_);
		}
	    }
	}
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_help('$key')");
	print '</td>';
	my @l = $dev->get_tag_values($key);
	@l = @devtypes if ($key eq 'type');
	if ($key =~ /name/ && $key !~ /RSD_/ && $dev->type !~ /Multiline/)
	{
	    @l = $rig->avaliable_devices('simplechannel');
	    unshift @l,'';
	}
	@l = sort {lc($a) cmp lc($b)} @l;
	my $change = 'change_val(this)';
	$change = 'change_type(this)' if ($dev->change_reload($key));

	my $class = 'textfield';
	$class = 'hidden' if ($dev->hide_tag($key));

	$class = 'hidden' if (exists($setup{'external_RSD'}) && (!$setup{'external_RSD'} || $setup{'external_RSD'} !~ /yes/i) && $key ne 'external_RSD' && $key =~ /RSD/);
	$class = 'hidden' if (exists($setup{'RSD_name'}) && $setup{'RSD_name'} && $key ne 'RSD_name' && $key ne 'external_RSD' && $key =~ /RSD/);
	if ($dev->tag_type($key) =~ /readonly/i)
	{
	    print '<th>',xss($dev->readonly_value($key)),'</th>';
	}
	else
	{
	    if ($key =~ /spline|comments|command_list/ && $key !~ /gpib/)
	    {
		my $rows = 5;
		print '<td rowspan=3>';
		my $val = $setup{$key};
		$val =~ s/\s*\,\s*/\n/g if ($val);
		if ($key =~ /comments|command/)
		{
		    $rows = 3;
		    $count_list[$count] = 2;
		}
		else
		{
		    $count_list[$count] = 3;
		}
		print textarea(-name=>$key,-rows=>$rows,-value=>$val,-class=>$class,-default=>$val,-force=>1,-onchange=>'change_spline(this)',-id=>$key,-ondblclick=>'plot_data(this.value)');
	    }
	    elsif (@l || $key eq 'mode' || $key =~ 'type' || $key eq 'device')
	    {
		print '<td>';
		print popup_menu(-name=>$key,-values=>[(@l)],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>$change,-id=>$key,-labels=>\%labels);
	    }
	    elsif ($key eq 'tty')
	    {
		print '<td>';
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key,-style=>'width:80%;');
		print button(-name=>'dummy',-value=>'?',-onclick=>'find_tty()',-style=>'width:20%;');
	    }
	    else
	    {
		print '<td>';
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key);
	    }
	    print '</td>';
	}
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	    foreach (@count_list)
	    {
		$_-- if ($_);
	    }
	}
    }
    if ($type eq 'analog')
    {
	print '<tr><td></td>' unless ($count);
	print '<th> Setup </th><th></th><th>';
	eval {
	    print $dev->setup_mode;
	};
	if ($@)
	{
	    print $@;
	}
	print '</th>';
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	}
	if ($count)
	{
	    print '</tr>';
	    $count = 0;
	}
	
    }
    return @count_list;
}


sub filter($$$)
{
    my $device = get_CGI_value_clean('device');
    my $type = get_CGI_value_clean('type');
    my $section = get_CGI_value_clean('section');
    my $str = shift;
    my $dev = shift;
    my $typeref = shift;
    my @devtypes = @{$typeref};
    print '<tr><td colspan=11 class="heading">';
    print xss("Configuring filter device $str"); 
    print "</td></tr>";
    my $info = $dev->info_string();
    if ($info)
    {
	print '<tr><td colspan=11 class="heading">';
	print xss("Notice: $info"); 
	print "</td></tr>";	
    }
    my @tags = $dev->setup_tags();
    @tags = $dev->setup_tags_legacy() if ($legacy);
    my %setup = ();
    foreach my $tag (@tags)
    {
	my $val = $rig->get_cv($section,$tag);
	$val = $dev->get_default($tag) unless (defined($val));
	$val = '' unless defined($val);
	$setup{$tag} = $val;
    }
    my $count = 0;
    my @count_list = (0,0,0);
    foreach my $key (@tags)
    {
	my %labels = ();
	print '<tr valign=top><td></td>' unless ($count);
	while ($count_list[$count])
	{
	    print '<td colspan=3></td>';
	    if ($count++ > 1)
	    {
		$count = 0;
		print '</tr>',"\n";
		print '<tr valign=top><td></td>';
		foreach (@count_list)
		{
		    $_-- if ($_);
		}
	    }
	}
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_help('$key')");
	print '</td>';
	my @l = $dev->get_tag_values($key);
	@l = sort {lc($a) cmp lc($b)} @l if (@l);
	my $change = 'change_val(this)';
	$change = 'change_type(this)' if ($dev->change_reload($key));
	my $class = 'textfield';
	$class = 'hidden' if ($dev->hide_tag($key));
	if ($dev->tag_type($key) =~ /readonly/i)
	{
	    print '<th>',xss($dev->readonly_value($key)),'</th>';
	}
	else
	{
	    if ($key =~ /spline|comments/)
	    {
		my $rows = 5;
		print '<td rowspan=3>';
		my $val = $setup{$key};
		$val =~ s/\s*\,\s*/\n/g if ($val);
		if ($key =~ /comments/)
		{
		    $rows = 3;
		    $count_list[$count] = 2;
		}
		else
		{
		    $count_list[$count] = 3;
		}
		print textarea(-name=>$key,-rows=>$rows,-value=>$val,-class=>$class,-default=>$val,-force=>1,-onchange=>'change_spline(this)',-id=>$key,-ondblclick=>'plot_data(this.value)');
	    }
	    elsif (@l || $key eq 'read_function' || $key eq 'notify_function' || ($key =~ /device|class/ && $key != /factor/))
	    {
		print '<td>';
		print popup_menu(-name=>$key,-values=>[(@l)],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>$change,-id=>$key,-labels=>\%labels);
	    }
	    else
	    {
		print '<td>';
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key);
	    }
	    print '</td>';
	}
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	    foreach (@count_list)
	    {
		$_-- if ($_);
	    }
	}
    }
    return @count_list;
}

sub math($$$)
{
    my $device = get_CGI_value_clean('device');
    my $type = get_CGI_value_clean('type');
    my $section = get_CGI_value_clean('section');
    my $str = shift;
    my $dev = shift;
    my $typeref = shift;
    my @devtypes = @{$typeref};
    print '<tr><td colspan=11 class="heading">';
    print xss("Configuring Arithmetic device $str"); 
    print "</td></tr>";
    $dev->init();
    my $info = $dev->info_string();
    if ($info)
    {
	print '<tr><td colspan=11 class="heading">';
	print xss("Notice: $info"); 
	print "</td></tr>";	
    }
    my @tags = $dev->setup_tags();
    @tags = $dev->setup_tags_legacy() if ($legacy);
    my %setup = ();
    foreach my $tag (@tags)
    {
	my $val = $rig->get_cv($section,$tag);
	$val = $dev->get_default($tag) unless (defined($val));
	$val = '' unless defined($val);
	$setup{$tag} = $val;
    }
    my $count = 0;
    my @count_list = (0,0,0);
    foreach my $key (@tags)
    {
	my %labels = ();
	print '<tr valign=top><td></td>' unless ($count);
	while ($count_list[$count])
	{
	    print '<td colspan=3></td>';
	    if ($count++ > 1)
	    {
		$count = 0;
		print '</tr>',"\n";
		print '<tr valign=top><td></td>';
		foreach (@count_list)
		{
		    $_-- if ($_);
		}
	    }
	}
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_help('$key')");
	print '</td>';
	my @l = $dev->get_tag_values($key);
	@l = sort {lc($a) cmp lc($b)} @l if (@l);
	my $change = 'change_val(this)';
	$change = 'change_type(this)' if ($dev->change_reload($key));
	$change = 'change_type(this)' if ($key =~ /device/);
	my $class = 'textfield';
	$class = 'hidden' if ($dev->hide_tag($key));
	if ($dev->tag_type($key) =~ /readonly/i)
	{
	    print '<th>',xss($dev->readonly_value($key)),'</th>';
	}
	else
	{
	    if ($key =~ /comments/)
	    {
		my $rows = 5;
		print '<td rowspan=3>';
		my $val = $setup{$key};
		$val =~ s/\s*\,\s*/\n/g if ($val);
		if ($key =~ /comments/)
		{
		    $rows = 3;
		    $count_list[$count] = 2;
		}
		else
		{
		    $count_list[$count] = 3;
		}
		print textarea(-name=>$key,-rows=>$rows,-value=>$val,-class=>$class,-default=>$val,-force=>1,-onchange=>'change_spline(this)',-id=>$key,-ondblclick=>'plot_data(this.value)');
	    }
	    elsif (@l || ($key =~ /device|class|function/i && $key !~ /factor/))
	    {
		print '<td>';
		print popup_menu(-name=>$key,-values=>[(@l)],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>$change,-id=>$key,-labels=>\%labels);
	    }
	    else
	    {
		print '<td>';
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key);
	    }
	    print '</td>';
	}
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	    foreach (@count_list)
	    {
		$_-- if ($_);
	    }
	}
    }
    return @count_list;
}



sub MFC($$$)
{
    my $device = get_CGI_value_clean('device');
    my $type = get_CGI_value_clean('type');
    my $section = get_CGI_value_clean('section');
    my $str = shift;
    my $dev = shift;
    my $typeref = shift;
    my @devtypes = @{$typeref};
    print '<tr><td colspan=11 class="heading">';
    print xss("Configuring controler $str"); 
    print "</td></tr>";
    my $info = $dev->info_string();
    if ($info)
    {
	print '<tr><td colspan=11 class="heading">';
	print xss("Notice: $info"); 
	print "</td></tr>";	
    }
    my @tags = $dev->setup_tags();
    @tags = $dev->setup_tags_legacy() if ($legacy);
    my %setup = ();
    foreach my $tag (@tags)
    {
	my $val = $rig->get_cv($section,$tag);
	if ($tag eq 'mode')
	{
	    $val = 'Automatic' if (defined($val) && $val =~ /auto/i);
	}
	$val = $dev->get_default($tag) unless (defined($val));
	if ($tag =~ /relay/i)
	{
	    $val = 'YES' if ($val && $val =~ /^yes$/i);
	    $val = 'NO' if ($val && $val =~ /^no$/i);
	    $val = 'NO' if (($tag eq 'relay' || $tag eq 'control_relay') && !$val);
	}
	$val = '' unless defined($val);
	$setup{$tag} = $val;
    }
    unshift @tags,'type';
    $setup{'type'} = $dev->type();
    my $class = ref($dev);
    my $count = 0;
    my @count_list = (0,0,0);
    foreach my $key (@tags)
    {
	my %labels = ();
	print '<tr valign=top><td></td>' unless ($count);
	while ($count_list[$count])
	{
	    print '<td colspan=2></td>';
	    if ($count++ > 1)
	    {
		$count = 0;
		print '</tr>',"\n";
		print '<tr valign=top><td></td>';
		foreach (@count_list)
		{
		    $_-- if ($_);
		}
	    }
	}
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_help('$key')");
	print '</td>';
	my @l = $dev->get_tag_values($key);
	@l = @devtypes if ($key eq 'type');
	@l = sort {lc($a) cmp lc($b)} @l if (@l);
	my $class = 'textfield';
	foreach ('channel_type','relay','output_control_relay')
	{
	    next if defined($setup{$_});
	    $setup{$_} = '';
	}
	$class = 'hidden' if ($dev->hide_tag($key));
	my $change = 'change_val(this)';
	$change = 'change_type(this)' if ($dev->change_reload($key));
	$change = 'change_type(this)' if ($key =~ /type|name|gas/);
	if ($dev->tag_type($key) =~ /readonly/i)
	{
	    print '<th>',xss($dev->readonly_value($key)),'</th>';
	}
	else
	{
	    if ($key =~ /spline|comments/)
	    {
		my $rows = 5;
		print '<td rowspan=3>';
		my $val = $setup{$key};
		$val =~ s/\s*\,\s*/\n/g if ($val);
		if ($key =~ /comments/)
		{
		    $rows = 3;
		    $count_list[$count] = 2;
		}
		else
		{
		    $count_list[$count] = 3;
		}
		print textarea(-name=>$key,-rows=>$rows,-value=>$val,-class=>$class,-default=>$val,-force=>1,-onchange=>'change_spline(this)',-id=>$key,-ondblclick=>'plot_data(this.value)');
	    }
	    elsif (@l || $key eq 'mode' || $key =~ /type/)
	    {
		print '<td>';
		print popup_menu(-name=>$key,-values=>[@l],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>$change,-id=>$key,-labels=>\%labels);
	    }
	    elsif ($key eq 'tty')
	    {
		print '<td>';
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key,-style=>'width:80%;');
		print button(-name=>'dummy',-value=>'?',-onclick=>'find_tty()',-style=>'width:20%;');
	    }
	    else
	    {
		print '<td>';
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key);
	    }
	    print '</td>';
	}
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	    foreach (@count_list)
	    {
		$_-- if ($_);
	    }
	}
    }
    return @count_list;
}

sub templog($$$)
{
    my $device = get_CGI_value_clean('device');
    my $type = get_CGI_value_clean('type');
    my $section = get_CGI_value_clean('section');
    my $str = shift;
    my $dev = shift;
    my $typeref = shift;
    my @devtypes = @{$typeref};
    print '<tr><td colspan=11 class="heading">';
    print xss("Configuring temperature log $str"); 
    print "</td></tr>";
    my $info = $dev->info_string();
    if ($info)
    {
	print '<tr><td colspan=11 class="heading">';
	print xss("Notice: $info"); 
	print "</td></tr>";	
    }
    my @tags = $dev->setup_tags();
    @tags = $dev->setup_tags_legacy() if ($legacy);
    my %setup = ();
    foreach my $tag (@tags)
    {
	my $val = $rig->get_cv($section,$tag);
	if ($tag eq 'mode')
	{
	    $val = 'Automatic' if (defined($val) && $val =~ /auto/i);
	}
	$val = $dev->get_default($tag) unless (defined($val));
	$val = '' unless defined($val);
	$setup{$tag} = $val;
    }
    unshift @tags,'type' if ($type eq 'Analog');
    my $count = 0;
    my $first = 1;
    my @count_list = (0,0,0);
    foreach my $key (@tags)
    {
	my %labels = ();
	print '<tr valign=top><td></td>' unless ($count);
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_help('$key')");
	print '</td>';
	my @l = $dev->get_tag_values($key);
	@l = sort {lc($a) cmp lc($b)} @l if (@l);
	my $change = 'change_val(this)';
	$change = 'change_type(this)' if ($dev->change_reload($key));
	my $class = 'textfield';
	$class = 'hidden' if ($dev->hide_tag($key));
	if ($first)
	{
	    @l = RFC::Device::list_Templog();
	    $first = 0;
	    print '<td>';
	    print popup_menu(-name=>$key,-values=>[(@l)],-class=>'textfield',-default=>$setup{'type'},-force=>1,-onchange=>'change_type(this)',-id=>$key,-labels=>\%labels);
	    print '</td>';
	}
	else
	{
	    if ($key =~ /spline|comments/)
	    {
		my $rows = 5;
		print '<td rowspan=3>';
		my $val = $setup{$key};
		$val =~ s/\s*\,\s*/\n/g if ($val);
		if ($key =~ /comments/)
		{
		    $rows = 3;
		    $count_list[$count] = 2;
		}
		else
		{
		    $count_list[$count] = 3;
		}
		print textarea(-name=>$key,-rows=>$rows,-value=>$val,-class=>$class,-default=>$val,-force=>1,-onchange=>'change_spline(this)',-id=>$key,-ondblclick=>'plot_data(this.value)');
	    }
	    elsif ($dev->tag_type($key) =~ /readonly/i)
	    {
		print '<th>',xss($dev->readonly_value($key)),'</th>';
	    }
	    else
	    {
		print '<td>';
		if (@l || $key eq 'mode' || $key eq 'callibration_file' || $key eq 'controller_mode')
		{
		    $change = 'change_val(this)' if ($key eq 'controller_mode');
		    print popup_menu(-name=>$key,-values=>[(@l)],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>$change,-id=>$key,-labels=>\%labels);
		}
		elsif ($key eq 'tty')
		{
		    print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key,-style=>'width:80%;');
		    print button(-name=>'dummy',-value=>'?',-onclick=>'find_tty()',-style=>'width:20%;');
		}		
		else
		{
		    print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>'change_val(this)',-id=>$key);
		}
	    }
	    print '</td>';
	}
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	}
    }
    return @count_list;
}


sub tempcontrol($$$)
{
    my $device = get_CGI_value_clean('device');
    my $type = get_CGI_value_clean('type');
    my $section = get_CGI_value_clean('section');
    my $str = shift;
    my $dev = shift;
    my $typeref = shift;
    my @devtypes = @{$typeref};
    print '<tr><td colspan=11 class="heading">';
    print xss("Configuring temperature controler $str"); 
    print "</td></tr>";
    my $info = $dev->info_string();
    if ($info)
    {
	print '<tr><td colspan=11 class="heading">';
	print xss("Notice: $info"); 
	print "</td></tr>";	
    }
    my @tags = $dev->setup_tags();
    @tags = $dev->setup_tags_legacy() if ($legacy);
    my %setup = ();
    my @count_list = (0,0,0);
    foreach my $tag (@tags)
    {
	my $val = $rig->get_cv($section,$tag);
	if ($tag eq 'mode')
	{
	    $val = 'Automatic' if (defined($val) && $val =~ /auto/i);
	}
	$val = $dev->get_default($tag) unless (defined($val));
	$val = '' unless defined($val);
	$setup{$tag} = $val;
    }
    my $count = 0;
    foreach my $key (@tags)
    {
	my %labels = ();
	print '<tr valign=top><td></td>' unless ($count);
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_help('$key')");
	print '</td>';
	my @l = $dev->get_tag_values($key);
	@l = @devtypes if ($key eq 'controler_type');
	@l = sort {lc($a) cmp lc($b)} @l if (@l);
	my $change = 'change_val(this)';
	$change = 'change_type(this)' if ($dev->change_reload($key));
	$change = 'change_type(this)' if ($key eq 'controler_type');
	my $class = 'textfield';
	$class = 'hidden' if ($dev->hide_tag($key));
	if ($key =~ /spline|comments/)
	{
	    my $rows = 5;
	    print '<td rowspan=3>';
	    my $val = $setup{$key};
	    $val =~ s/\s*\,\s*/\n/g if ($val);
	    if ($key =~ /comments/)
	    {
		$rows = 3;
		$count_list[$count] = 2;
	    }
	    else
	    {
		$count_list[$count] = 3;
	    }
	    print textarea(-name=>$key,-rows=>$rows,-value=>$val,-class=>$class,-default=>$val,-force=>1,-onchange=>'change_spline(this)',-id=>$key,-ondblclick=>'plot_data(this.value)');
	}
	elsif ($dev->tag_type($key) =~ /readonly/i)
	{
	    print '<th>',xss($dev->readonly_value($key)),'</th>';
	}
	else
	{
	    print '<td>';
	    if (@l > 1 || $key eq 'type' || $key eq 'controler_mode')
	    {
		print popup_menu(-name=>$key,-values=>[(@l)],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>$change,-id=>$key,-labels=>\%labels);
	    }
	    elsif ($key eq 'tty')
	    {
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key,-style=>'width:80%;');
		print button(-name=>'dummy',-value=>'?',-onclick=>'find_tty()',-style=>'width:20%;');
	    }
	    else
	    {
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>'change_val(this)',-id=>$key);
	    }
	    print '</td>';
	}
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	}
    }
    return @count_list;
}

sub multiplexer($$$)
{
    my $device = get_CGI_value_clean('device');
    my $type = get_CGI_value_clean('type');
    my $section = get_CGI_value_clean('section');
    my $str = shift;
    my $dev = shift;
    my $typeref = shift;
    my @devtypes = @{$typeref};
    print '<tr><td colspan=11 class="heading">';
    print xss("Configuring gas multiplexer $str"); 
    print "</td></tr>";
    my $info = $dev->info_string();
    if ($info)
    {
	print '<tr><td colspan=11 class="heading">';
	print xss("Notice: $info"); 
	print "</td></tr>";	
    }
    my @tags = $dev->setup_tags();
    @tags = $dev->setup_tags_legacy() if ($legacy);
    my %setup = ();
    foreach my $tag (@tags)
    {
	my $val = $rig->get_cv($section,$tag);
	if ($tag eq 'mode')
	{
	    $val = 'Automatic' if (defined($val) && $val =~ /auto/i);
	}
	$val = $dev->get_default($tag) unless (defined($val));
	$val = '' unless defined($val);
	$setup{$tag} = $val;
    }
    my $count = 0;
    my @count_list = (0,0,0);
    foreach my $key (@tags)
    {
	my %labels = ();
	print '<tr valign=top><td></td>' unless ($count);
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_help('$key')");
	print '</td>';
	my @l = $dev->get_tag_values($key);
	@l = @devtypes if ($key eq 'type');
	if ($key =~ /name/)
	{
	    @l = $rig->avaliable_devices('relay');
	    unshift @l,'';
	}
	if ($key =~ /master/)
	{
	    unshift @l,'';
	}
	if ($key eq 'controler')
	{
	    @l = (0);
	    foreach my $mfc ($rig->avaliable_devices('MFC'))
	    {
		if ($mfc =~ /(\d+)/)
		{
		    push @l,$1;   
		}
	    }
	}
	@l = sort {lc($a) cmp lc($b)} @l if (@l);
	@l = (0,1) if ($key eq 'control_value');
	my $change = 'change_val(this)';
	$change = 'change_type(this)' if ($dev->change_reload($key));
	$change = 'change_type(this)' if ($key eq 'type');
	my $class = 'textfield';
	$class = 'hidden' if ($dev->hide_tag($key));
	if ($key =~ /spline|comments/)
	{
	    my $rows = 5;
	    print '<td rowspan=3>';
	    my $val = $setup{$key};
	    $val =~ s/\s*\,\s*/\n/g if ($val);
	    if ($key =~ /comments/)
	    {
		$rows = 3;
		$count_list[$count] = 2;
	    }
	    else
	    {
		$count_list[$count] = 3;
	    }
	    print textarea(-name=>$key,-rows=>$rows,-value=>$val,-class=>$class,-default=>$val,-force=>1,-onchange=>'change_spline(this)',-id=>$key,-ondblclick=>'plot_data(this.value)');
	}
	elsif ($dev->tag_type($key) =~ /readonly/i)
	{
	    print '<th>',xss($dev->readonly_value($key)),'</th>';
	}
	else
	{
	    print '<td>';
	    if (@l || $key eq 'mode' || $key =~ 'type')
	    {
		print popup_menu(-name=>$key,-values=>[(@l)],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>$change,-id=>$key,-labels=>\%labels);
	    }
	    elsif ($key eq 'tty')
	    {
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key,-style=>'width:80%;');
		print button(-name=>'dummy',-value=>'?',-onclick=>'find_tty()',-style=>'width:20%;');
	    }
	    else
	    {
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>'change_val(this)',-id=>$key);
	    }
	    print '</td>';
	}
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	}
    }
    my @gasses = ();
    my $controler = 0;
    foreach my $c ($rig->list_devices('MFC'))
    {
	my $dev = $rig->get_device('MFC',$c);
	next unless ($dev->multiplexer && $dev->multiplexer->name eq $device);
	@gasses = $dev->gasses();
	$controler = $dev->name;
    }
    return unless ($controler);
    print '<tr><td></td>' unless ($count);
    print '<th> Gas controler';
    print '</th><td>';
    print button(-name=>'helpcontroler',-value=>'(i)',-class=>'hlp',-onclick=>"alert('MFC Control device for multiplexer')");
    print '</td><th>';
    print start_form();
    print_hidden_rig();
    print hidden(-name=>'type',-value=>'MFC',-force=>1);
    print submit(-name=>'device',-value=>$controler,-class=>'s3');
    print end_form();
    print '</th>';
    if ($count++ > 1)
    {
	$count = 0;
	print '</tr>',"\n";
    }
    if ($count)
    {
	print '</tr>';
	$count = 0;
    }
    print '<tr valign=top><td></td>';
    while ($count_list[$count])
    {
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	    print '<tr valign=top><td></td>';
	    foreach (@count_list)
	    {
		$_-- if ($_);
	    }
	}
    }
    print '</tr>';
    print '<tr valign=top><td></td></tr>';
    print '<tr><td colspan=11 class="heading">';
    print xss("Gas channel setup for gas multiplexer $device"); 
    print "</td></tr>";
    my @devs = ('',$rig->avaliable_devices('relay'));
    foreach my $gas (@gasses)
    {
	if ($dev->type eq 'VICI')
	{
	    print '<tr><td></td>';
	    print '<th colspan=2>';
	    print $gas;
	    print '</th><th>';
	    print 'Port';
	    print '</th><td colspan=2>';
	    my $maxch = $dev->get_channels();
	    my @list = (1..$maxch);
	    my $port = $dev->get_conf($gas.'_port');
	    print popup_menu(-name=>$gas.'_port',-values=>[(@list)],-class=>'textfield',-default=>$port,-force=>1,-onchange=>'change_type(this)',-id=>$gas.'_port');	
	    print '</tr>',"\n";
	}
	elsif ($dev->type eq 'Slave multiplexer')
	{
	    print '<tr><td></td>';
	    print '<th colspan=2>';
	    print $gas;
	    print '</th><th>';
	    print 'Master gas';
	    print '</th><td colspan=2>';
            my @list = ();
            @list = @{$dev->{'_master_gasses'}} if ($dev->{'_master_gasses'});
	    print popup_menu(-name=>'gas_link_'.$gas,-values=>['',@list],-class=>'textfield',-default=>$dev->{'_gas_link'}{$gas},-force=>1,-onchange=>'change_type(this)',-id=>'gas_link_'.$gas);	
	    print '</td>';
	    print '</tr>',"\n";	    
	}
	else
	{
	    print '<tr><td></td>';
	    print '<th colspan=2>';
	    print $gas;
	    print '</th><th>';
	    print 'Device name';
	    print '</th><td colspan=2>';
	    my $devname = $rig->get_cv('gas_multiplexer_'.$dev->name,$gas.'_device_name');	
	    print popup_menu(-name=>$gas.'_device_name',-values=>[(@devs)],-class=>'textfield',-default=>$devname,-force=>1,-onchange=>'change_type(this)',-id=>$gas.'_device_name');	
	    print '</td><th> Channel';
	    my $channel = $dev->channel($gas);
	    my $class = 'textfield';
	    $class = 'hidden' if ($devname);
	    print '</th><td>';
	    print textfield(-name=>$gas,-value=>$channel,-class=>$class,-force=>1,-onchange=>'change_val(this)',-id=>$gas);
	    print '</td>';
	    print '</tr>',"\n";
	}
    }
    return @count_list;
}

sub water($$$)
{
    my $device = get_CGI_value_clean('device');
    my $type = get_CGI_value_clean('type');
    my $section = get_CGI_value_clean('section');
    my $str = shift;
    my $dev = shift;
    my $typeref = shift;
    my @devtypes = @{$typeref};
    print '<tr><td colspan=11 class="heading">';
    print xss("Configuring water bubler $str"); 
    print "</td></tr>";
    my $info = $dev->info_string();
    if ($info)
    {
	print '<tr><td colspan=11 class="heading">';
	print xss("Notice: $info"); 
	print "</td></tr>";	
    }
    my @tags = $dev->setup_tags();
    @tags = $dev->setup_tags_legacy() if ($legacy);
    my %setup = ();
    foreach my $tag (@tags)
    {
	my $val = $rig->get_cv($section,$tag);
	if ($tag eq 'mode')
	{
	    $val = 'Automatic' if (defined($val) && $val =~ /auto/i);
	}
	$val = $dev->get_default($tag) unless (defined($val));
	$val = '' unless defined($val);
	$setup{$tag} = $val;
    }
    my $count = 0;
    my @count_list = (0,0,0);
    foreach my $key (@tags)
    {
	my %labels = ();
	print '<tr valign=top><td></td>' unless ($count);
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_help('$key')");
	print '</td>';
	my @l = $dev->get_tag_values($key);
	@l = sort {lc($a) cmp lc($b)} @l if (@l);
	my $class = 'textfield';
	$class = 'hidden' if ($dev->hide_tag($key));
	my $change = 'change_val(this)';
	$change = 'change_type(this)' if ($dev->change_reload($key));
	if ($key =~ /spline|comments/)
	{
	    my $rows = 5;
	    print '<td rowspan=3>';
	    my $val = $setup{$key};
	    $val =~ s/\s*\,\s*/\n/g if ($val);
	    if ($key =~ /comments/)
	    {
		$rows = 3;
		$count_list[$count] = 2;
	    }
	    else
	    {
		$count_list[$count] = 3;
	    }
	    print textarea(-name=>$key,-rows=>$rows,-value=>$val,-class=>$class,-default=>$val,-force=>1,-onchange=>'change_spline(this)',-id=>$key,-ondblclick=>'plot_data(this.value)');
	}
	elsif ($dev->tag_type($key) =~ /readonly/i)
	{
	    print '<th>',xss($dev->readonly_value($key)),'</th>';
	}
	else
	{
	    print '<td>';
	    if (@l > 1 || $key eq 'mode' || $key =~ 'type')
	    {
		print popup_menu(-name=>$key,-values=>[(@l)],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>$change,-id=>$key,-labels=>\%labels);
	    }
	    elsif ($key eq 'tty')
	    {
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key,-style=>'width:80%;');
		print button(-name=>'dummy',-value=>'?',-onclick=>'find_tty()',-style=>'width:20%;');
	    }
	    else
	    {
		print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key);
	    }
	    print '</td>';
	}
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	}
    }
    return @count_list;
}


sub gas($$$)
{
    my $device = get_CGI_value_clean('device');
    my $type = get_CGI_value_clean('type');
    my $section = get_CGI_value_clean('section');
    my $class = $rig->get_cv($section,'class');
    my $str = shift;
    my $dev = shift;
    my $typeref = shift;
    return print_default($str,$dev,$typeref) if ($class && $class =~ /multiline/i);    
    my @devtypes = @{$typeref};
    print '<tr><td colspan=11 class="heading">';
    print xss("Configuring gas $str"); 
    print "</td></tr>";
    my $info = $dev->info_string();
    if ($info)
    {
	print '<tr><td colspan=11 class="heading">';
	print xss("Notice: $info"); 
	print "</td></tr>";	
    }
    my @tags = $dev->setup_tags();
    @tags = $dev->setup_tags_legacy() if ($legacy);
    my %setup = ();
    foreach my $tag (@tags)
    {
	my $val = $rig->get_cv($section,$tag);
	if ($tag eq 'mode')
	{
	    $val = 'Automatic' if ($val =~ /auto/i);
	}
	$val = $dev->get_default($tag) unless (defined($val));
	$val = '' unless defined($val);
	$setup{$tag} = $val;
    }
    my $count = 0;
    my @count_list = (0,0,0);
    foreach my $key (@tags)
    {
	my %labels = ();
	print '<tr valign=top><td></td>' unless ($count);
	print '<th>';
	my $tag = $key;
	$tag =~ s/_/ /g;
	print xss(ucfirst($tag));
	print '</th><td>';
	print button(-name=>'help'.$tag,-value=>'(i)',-class=>'hlp',-onclick=>"show_help('$key')");
	print '</td>';
	my @l = $dev->get_tag_values($key);
	@l = @devtypes if ($key eq 'type');
	if ($key =~ /name/)
	{
	    @l = $rig->avaliable_devices('relay');
	    unshift @l,'';
	}
	@l = sort {lc($a) cmp lc($b)} @l if (@l);
	if ($key =~ /spline|comments/)
	{
	    my $rows = 5;
	    print '<td rowspan=3>';
	    my $val = $setup{$key};
	    $val =~ s/\s*\,\s*/\n/g if ($val);
	    if ($key =~ /comments/)
	    {
		$rows = 3;
		$count_list[$count] = 2;
	    }
	    else
	    {
		$count_list[$count] = 3;
	    }
	    print textarea(-name=>$key,-rows=>$rows,-value=>$val,-class=>'textfield',-default=>$val,-force=>1,-onchange=>'change_spline(this)',-id=>$key,-ondblclick=>'plot_data(this.value)');
	}
	elsif ($key eq 'controler')
	{
	    my @controler = ();
	    foreach my $mfc ($rig->avaliable_devices('MFC'))
	    {
		my $mfcdev = $rig->get_device('MFC',$mfc);
		my @glist = ();
		@glist = $mfcdev->gasses() if ($mfcdev);
		my $gstr = join(' ',@glist);
		push @controler,$mfc if ($gstr =~ /\b$device\b/);
	    }
	    if (@controler == 1 && $dev->mode =~ /auto/i)
	    {
		my $ok = 1;
		if ($setup{$key} ne $controler[0])
		{
		    $rig->proglog("Warning MFC setup for gas $device incorrect (was $setup{$key}, should be $controler[0]), correcting...",&get_user());
		    eval {
			$rig->begin;
			$rig->change_config_value('gas_'.$device,'controler',$controler[0]);
			$rig->init();
			$rig->commit();
		    };
		    if ($@)
		    {
			$rig->rollback();
			$rig->proglog("Error: Could not correct MFC setup for gas $device: $@",&get_user());
			print "<th class='Alert'> Error: ".xss($@)." </th>";
			$ok = 0;
		    }
		}
		if ($ok)
		{
		    print '<th>';
		    if ($controler[0])
		    {
			print start_form();
			print_hidden_rig();
			print hidden(-name=>'type',-value=>'MFC',-force=>1);
			print submit(-name=>'device',-value=>$controler[0],-class=>'s3');
			print end_form();
		    }
		    else
		    {
			print "0";
		    }
		    print '</th>';
		}
	    }
	    elsif ($dev->mode =~ /auto/)
	    {
		print "<th class='Alert'> Error: No controler could be found with gas ".xss($device)." although gas is defined as automatic! </th>";
	    }
	    elsif (@controler == 1 && $controler[0])
	    {
		print '<th>',$controler[0],' (Multiplexed, not engaged)</th>';
	    }
	    else
	    {
		print '<th>0</th>';
	    }
	}
	else
	{
	    @l = (0,1) if ($key eq 'control_value');
	    my $change = 'change_val(this)';
	    $change = 'change_type(this)' if ($dev->change_reload($key));
	    my $class = 'textfield';
	    $class = 'hidden' if ($dev->hide_tag($key));
	    if ($dev->tag_type($key) =~ /readonly/i)
	    {
		print '<th>',xss($dev->readonly_value($key)),'</th>';
	    }
	    else
	    {
		print '<td>';
		if ($key eq 'mode')
		{
		    print popup_menu(-name=>$key,-values=>[(@l)],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>'confirm_mode(this)',-id=>$key,-labels=>\%labels);
		}
		elsif (@l || $key =~ 'type')
		{
		    print popup_menu(-name=>$key,-values=>[(@l)],-class=>$class,-default=>$setup{$key},-force=>1,-onchange=>$change,-id=>$key,-labels=>\%labels);
		}
		elsif ($key eq 'tty')
		{
		    print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>$change,-id=>$key,-style=>'width:80%;');
		    print button(-name=>'dummy',-value=>'?',-onclick=>'find_tty()',-style=>'width:20%;');
		}
		else
		{
		    print textfield(-name=>$key,-value=>$setup{$key},-class=>$class,-force=>1,-onchange=>'change_val(this)',-id=>$key);
		}
		print '</td>';
	    }
	}
	if ($count++ > 1)
	{
	    $count = 0;
	    print '</tr>',"\n";
	}
    }

    print <<END;

<script languate="javascript">

function confirm_mode(element)
{
    if (!confirm("Warning: Changing 'automatic'/'manual' status for a gas may result in incorrect gas configuration! Continue?"))
    {
	return false;
    }
    var n = element.name;
    var val = element.value;
    var sec = document.device.section.value
    element.disabled = true;
    run_ajax('change_config.cgi','&action=change_config_value&section='+sec+'&key='+n+'&value='+val,set_type);
}

</script>


END

    return @count_list;
}


