#!/bin/bash
#\
exec wish -f "$0" ${1+"$@"}
#
# wacomcpl-exec -- Wacom Control Panel Utility to Change Configuration Setting.
#
# Author	: Ping Cheng <pinglinux@gmail.com>
# Creation date	: 04/05/2003
# Updated       : 2003 - 2010
#
# Based on calibrate 1998-99 Patrick Lecoanet --
#
# There are two ways to run this program:
#  wacomcpl:  full control panel features with pressure and button configuration, 
#		tablet and screen mapping, as well as calibration. 
#
#  wacomcpl calibrate dev: fesatures calibration for a LCD device (identified as dev)
#
#  wacomcpl calibrate dev on: fesatures calibration for a LCD device (identified as dev)
#			      and display warnings when abnormal coordinates are detected
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This code 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this code; if not, write to the Free
# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#

package require LIBWACOMXI

set currentScreen 0
set desktopWidth [ winfo screenwidth . ]
set desktopHeight [ winfo screenheight . ]
set screenWidth [ winfo screenwidth . ]
set screenHeight [ winfo screenheight . ]
set screenXBottom [ winfo screenwidth . ]
set screenYBottom [ winfo screenheight . ]

set screenX_org 0
set screenY_org 0
set swapThresh 100
set size 200
set circle_size 10
set line_size 30

set origin_x [ expr ($desktopWidth/2) - ($desktopWidth/4) ]
set origin_y [ expr ($desktopHeight/2) - ($desktopHeight/4) ]
set windowSize "700x300"

set device ""
set showHelp 0
set doubleClickB 33
set ignoreButton 34
set modeToggleB 35
set displayToggleB 36
set screenToggleB 37
set keystrokeB 38
# application defined button number
set originalButton 39
set maxNumTablets 227
set numControls 0
set maxNumButtons 18
set maxNumStripEvents 4
set calibration_sequence_only 0
set calibration_with_warning 0
set xDefinedButtons 7

proc updateCurrentScreenInfo {} {
    global device numScreens currentScreen 
    global screenXBottom screenYBottom screenX_org screenY_org 
    global getScreenInfo screenWidth screenHeight

    if { $numScreens($device) != 1 } {
        set screenInfo $getScreenInfo($device,Screen$currentScreen)
	set screenXBottom [ lindex $screenInfo 0 ]
	set screenYBottom [ lindex $screenInfo 1 ]
	set screenX_org [ lindex $screenInfo 2 ]
	set screenY_org [ lindex $screenInfo 3 ]
	set screenWidth abs([ expr $screenXBottom-$screenX_org ])
	set screenHeight abs([ expr $screenYBottom-$screenY_org ])
   }
}

proc pad {name geometry} {
    global size circle_size line_size

    set circleox [ expr $size/2-$circle_size/2 ]
    set circleoy $circleox
    set circlecx [ expr $circleox+$circle_size ]
    set circlecy $circlecx
    set vertx [ expr $size/2 ]
    set vertoy [ expr ($size-$line_size)/2 ]
    set vertcy [ expr $vertoy+$line_size ]
    set horizox [ expr ($size-$line_size)/2 ]
    set horizcx [ expr $horizox+$line_size ]
    set horizy [ expr $size/2 ]

    toplevel $name
    wm geometry $name $geometry
    wm overrideredirect $name true
    canvas $name.m -height $size -width $size -bg "#505075"
    $name.m create oval $circleox $circleoy $circlecx $circlecy -outline white
    $name.m create line $vertx $vertoy $vertx $vertcy -fill white
    $name.m create line $horizox $horizy $horizcx $horizy -fill white
    pack $name.m
}

proc updateXinitrc {device option value} {
    if { ![ file exists ~/.xinitrc ] } {
	if { [ file exists ~/.xsession ] } {
	    file copy -force ~/.xsession ~/.xsession.bak
	    file copy -force ~/.xsession /tmp/xsession1
	    exec sed -e "/xsetwacom set \"$device\" $option /d" /tmp/xsession1 > /tmp/wacom
	    exec echo "xsetwacom set \"$device\" $option \"$value\"" > ~/.xsession
	    exec cat /tmp/wacom >> ~/.xsession
	    file delete -force /tmp/wacom /tmp/xsession1
	} else {
	    exec echo "xsetwacom set \"$device\" $option \"$value\"" > ~/.xinitrc
	    exec echo "# run the primary system script" >> ~/.xinitrc
	    exec echo ". /etc/X11/xinit/xinitrc" >> ~/.xinitrc
	}
    } else {
	file copy -force ~/.xinitrc ~/.xinitrc.bak
	file copy -force ~/.xinitrc /tmp/xinitrc1
	exec sed -e "/xsetwacom set \"$device\" $option /d" /tmp/xinitrc1 > /tmp/wacom
	exec echo "xsetwacom set \"$device\" $option \"$value\"" > ~/.xinitrc
	exec cat /tmp/wacom >> ~/.xinitrc
	file delete -force /tmp/wacom /tmp/xinitrc1
    }
    if { $option == "PressCurve" } {
	set index 0
	set v1 [ lindex $value $index ]
    	for { set i 2 } { $i < 5 } { incr i 1 } {
	    set index [ expr $index+1 ]
	    set v$i [ lindex $value $index ]
	}
	exec xsetwacom set "$device" $option $v1 $v2 $v3 $v4
    } else {
	exec xsetwacom set "$device" $option $value
    }
}

proc verifycalibResultsTopLeft { } {
    global device getOptionDefault xDevMin yDevMin
    global screenWidth screenHeight size end

    set tol_w [expr ($getOptionDefault($device,BottomY) - \
		$getOptionDefault($device,TopY)) * $size / $screenHeight]
    set tol_h [expr ($getOptionDefault($device,BottomX) - \
		$getOptionDefault($device,TopX)) * $size / $screenWidth]

    set tol_top [expr $getOptionDefault($device,TopY)]
    set tol_bottom [expr $tol_top + $tol_h]
    set tol_left [expr $getOptionDefault($device,TopX)]
    set tol_right [expr $tol_left + $tol_w]

    if { ($xDevMin < $tol_left) || ($xDevMin > $tol_right) || \
    	($yDevMin < $tol_top) || ($yDevMin > $tol_bottom) } {
    	.topleft.m configure -background "#ff0000"
    	set end 0
    	after 100 set end 1
    	vwait end	

    	.topleft.m configure -background "#505075"
    	set end 0
    	after 70 set end 1
    	vwait end	

    	.topleft.m configure -background "#ff0000"
    	set end 0
    	after 100 set end 1
    	vwait end

    	set xDevMin [expr ($getOptionDefault($device,TopX) + ($tol_w / 2))]
    	set yDevMin [expr ($getOptionDefault($device,TopY) + ($tol_h / 2))]
    }
}

proc verifycalibResultsBottomRight { } {
    global device getOptionDefault xDevMax yDevMax
    global screenWidth screenHeight size end

    set tol_w [expr ($getOptionDefault($device,BottomY) - \
		$getOptionDefault($device,TopY)) * $size / $screenHeight]
    set tol_h [expr ($getOptionDefault($device,BottomX) - \
		$getOptionDefault($device,TopX)) * $size / $screenWidth]

    set tol_bottom [expr $getOptionDefault($device,BottomY)]
    set tol_top [expr $tol_bottom - $tol_h]
    set tol_right [expr $getOptionDefault($device,BottomX)]
    set tol_left [expr $tol_right - $tol_w]

    if { ($xDevMax < $tol_left) || ($xDevMax > $tol_right) || \
    	($yDevMax < $tol_top) || ($yDevMax > $tol_bottom) } {
    
    	.bottomright.m configure -background "#ff0000"
    	set end 0
    	after 100 set end 1
    	vwait end	

    	.bottomright.m configure -background "#505075"
    	set end 0
    	after 70 set end 1
    	vwait end	

    	.bottomright.m configure -background "#ff0000"
    	set end 0
    	after 100 set end 1
    	vwait end
    
    	set xDevMax [expr ($getOptionDefault($device,BottomX) - ($tol_w / 2))]
    	set yDevMax [expr ($getOptionDefault($device,BottomY) - ($tol_h / 2))]
    }
}

proc verifycalibResults { } {
    global device getOptionDefault xDevMin xDevMax yDevMin yDevMax
    global screenWidth screenHeight size clickCheck tvID

    # Verifying the end results
    if { $tvID == 1 } { # a Nvidia Xinerama setup
	set tol_offset [expr ($getOptionDefault($device,BottomY) / 4)]
	set tol_left [expr ($getOptionDefault($device,BottomY) - $tol_offset) / 2]
	set tol_right [expr ($getOptionDefault($device,BottomY) + $tol_offset) / 2]
	set tol_bottom [expr ($getOptionDefault($device,BottomY) - $tol_offset)]

	# set tablet Y values to normal when offset is by whole of the tablet size.
	# Whole has to be first and we do it two times to make sure.
	if { $yDevMin > $tol_bottom } {
	    set yDevMin [expr ($yDevMin - $getOptionDefault($device,BottomY))]
	    set yDevMax [expr ($yDevMax - $getOptionDefault($device,BottomY))]
	} 
	if { $yDevMin > $tol_bottom } {
	    set yDevMin [expr ($yDevMin - $getOptionDefault($device,BottomY))]
	    set yDevMax [expr ($yDevMax - $getOptionDefault($device,BottomY))]
	} elseif { ($yDevMin > $tol_left) && ($yDevMin < $tol_right) } {
	    # set tablet Y values to normal when offset is by half tablet size
	    set yDevMin [expr ($yDevMin - ($getOptionDefault($device,BottomY) / 2))]
	    set yDevMax [expr ($yDevMax - ($getOptionDefault($device,BottomY) / 2))]
	}

	set tol_offset [expr ($getOptionDefault($device,BottomX) / 4)]
	set tol_left [expr ($getOptionDefault($device,BottomX) - $tol_offset) / 2]
	set tol_right [expr ($getOptionDefault($device,BottomX) + $tol_offset) / 2]
	set tol_bottom [expr ($getOptionDefault($device,BottomX) - $tol_offset)]

	# set tablet X values to normal when offset is by whole of the tablet size. 
	# Whole has to be first and we do it two times to make sure.
	if { $xDevMin > $tol_bottom } {
	    set xDevMin [expr ($xDevMin - $getOptionDefault($device,BottomX))]
	    set xDevMax [expr ($xDevMax - $getOptionDefault($device,BottomX))]
	} 
	if { $xDevMin > $tol_bottom } {
	    set xDevMin [expr ($xDevMin - $getOptionDefault($device,BottomX))]
	    set xDevMax [expr ($xDevMax - $getOptionDefault($device,BottomX))]
	} elseif { ($xDevMin > $tol_left) && ($xDevMin < $tol_right) } {
	    # set tablet X values to normal when offset is by half tablet size
	    set xDevMin [expr ($xDevMin - ($getOptionDefault($device,BottomX) / 2))]
	    set xDevMax [expr ($xDevMax - ($getOptionDefault($device,BottomX) / 2))]
	}
    } else {
	set tol_w [expr ($getOptionDefault($device,BottomY) - \
		$getOptionDefault($device,TopY)) * $size / $screenHeight]
	set tol_h [expr ($getOptionDefault($device,BottomX) - \
		$getOptionDefault($device,TopX)) * $size / $screenWidth]

	set tol_top [expr $getOptionDefault($device,TopY)]
	set tol_bottom [expr $tol_top + $tol_h]
	set tol_left [expr $getOptionDefault($device,TopX)]
	set tol_right [expr $tol_left + $tol_w]

	if { ($xDevMin < $tol_left) || ($xDevMin > $tol_right) || \
		($yDevMin < $tol_top) || ($yDevMin > $tol_bottom) } {
	    set clickCheck 1
	}

	set tol_w [expr ($getOptionDefault($device,BottomY) - \
		$getOptionDefault($device,TopY)) * $size / $screenHeight]
	set tol_h [expr ($getOptionDefault($device,BottomX) - \
		$getOptionDefault($device,TopX)) * $size / $screenWidth]

	set tol_bottom [expr $getOptionDefault($device,BottomY)]
	set tol_top [expr $tol_bottom - $tol_h]
	set tol_right [expr $getOptionDefault($device,BottomX)]
	set tol_left [expr $tol_right - $tol_w]

	if { ($xDevMax < $tol_left) || ($xDevMax > $tol_right) || \
		($yDevMax < $tol_top) || ($yDevMax > $tol_bottom) } {
	    set clickCheck 1
	}
    }
}

proc calibrationSequence {which xDev yDev} {
    global device calibResults screenY_org screenX_org orig_device
    global workingTags screenTags size numScreens
    global swapThresh screenWidth screenHeight getOptionDefault
    global getDeviceModel screenXBottom screenYBottom
    global calibX_org calibY_org calibX_botm calibY_botm
    global xDevMin xDevMax yDevMin yDevMax
    global calibration_sequence_only clickCheck 
    global calibration_with_warning

    set scaling [exec xsetwacom get "$device" xscaling]
    if { $scaling == 1 } {
	set xNewDev [expr (($xDev - $calibX_org) * $getOptionDefault($device,BottomX))]
	set xDev [expr ($xNewDev / ($calibX_botm - $calibX_org))]
	set yNewDev [expr (($yDev - $calibY_org) * $getOptionDefault($device,BottomY))]
	set yDev [expr ($yNewDev / ($calibY_botm - $calibY_org))]
    }

    set calibResults(xDev,$which) $xDev
    set calibResults(yDev,$which) $yDev

    if { $which == 0 } {
	wacomxi::bindevent .topleft.m "$orig_device" <ButtonRelease> ""

	set xDevMin $calibResults(xDev,0)
	set yDevMin $calibResults(yDev,0)

	if { $calibration_with_warning != 0 } {
		verifycalibResultsTopLeft
	}

	.topleft.m configure -background "#505075"
	.topleft.m configure -cursor "watch #505075 #505075"
	.bottomright.m configure -background "#df94df"
	#hide the cursor
	.bottomright.m configure -cursor "center_ptr #df94df #df94df"
	wacomxi::bindevent .bottomright.m "$orig_device" <ButtonRelease> \
		{calibrationSequence 1 %0 %1}
    } elseif { $which == 1 } {
	wacomxi::bindevent .bottomright.m "$orig_device" <ButtonRelease> ""	
	set borderOffset [expr ($size / 2 )]

	set xDevMax $calibResults(xDev,1)
	set yDevMax $calibResults(yDev,1)
	.bottomright.m configure -background "#505075"
	.bottomright.m configure -cursor "watch #505075 #505075"

	# A direction verification of the click
	set clickCheck 0
	if { $calibResults(xDev,1) < $calibResults(xDev,0) } {
	    set clickCheck 1
	    set xDevMin $calibResults(xDev,1)
	    set xDevMax $calibResults(xDev,0)
	}
	if { $calibResults(yDev,1) < $calibResults(yDev,0) } {
	    set clickCheck 1
	    set yDevMin $calibResults(yDev,1)
	    set yDevMax $calibResults(yDev,0)
	}

	if { $calibration_with_warning != 0 } {
	    verifycalibResultsBottomRight
	    .bottomright.m configure -background "#505075"
	} else {
	    verifycalibResults
	}

	set widthDev [expr $xDevMax - $xDevMin]
	set heightDev [expr $yDevMax - $yDevMin]
 	set widthX [expr $screenWidth - $size]
 	set heightX [expr $screenHeight - $size]

	set xDevMin [expr $xDevMin - ($borderOffset * $widthDev / $widthX)]
	set xDevMax [expr $xDevMax + ($borderOffset * $widthDev / $widthX)]
	set yDevMin [expr $yDevMin - ($borderOffset * $heightDev / $heightX)]
	set yDevMax [expr $yDevMax + ($borderOffset * $heightDev / $heightX)]

	updateXinitrc $device topx $xDevMin
	updateXinitrc $device topy $yDevMin
	updateXinitrc $device bottomx $xDevMax
	updateXinitrc $device bottomy $yDevMax

	# send the same data to the associated eraser if it is a stylus
	set type $getDeviceModel($device,type)
	if { ![ string compare $type "stylus" ] } {
	    set eraser $getDeviceModel($device,eraser)
	    if { [ string compare $eraser $device ] && $eraser != "" } {
		updateXinitrc $eraser topx $xDevMin
		updateXinitrc $eraser topy $yDevMin
		updateXinitrc $eraser bottomx $xDevMax
		updateXinitrc $eraser bottomy $yDevMax
	    }
	}

	if { $clickCheck == 1 } {
	    messageWindow "Warning !!!" \
		"\n\nIf the cursor follows the tip of your\n\
		tool better than before, you are fine.\n\
		Otherwise, please rerun the calibration\n\
		steps and make sure you are clicking\n\
		on the center of the pink crosshairs."
	}

	destroy .topleft .bottomright
	if { $numScreens($device) > 1 } {
            if { $calibration_sequence_only == 0 } {
		.screen.list.label configure -text ""
 		bindtags .screen.list.list $screenTags
	    } else {
		.list.label configure -text ""
 		bindtags .list.list $screenTags
	    }
	} else {
            if { $calibration_sequence_only == 1 } {
                exit 0
	    } else {
		closeTabWindow
	    }
	}
    }
}

proc Calibration {} {
    global numScreens device screenTags getOption Option 
    global tvID calibration_sequence_only

    # mainly to get the defaults
    set Option(1) "TopX"
    set Option(2) "TopY"
    set Option(3) "BottomX"
    set Option(4) "BottomY"
    set Option(5) "Mode"
    set Option(6) "TwinView"

    getDeviceOptionProc $device 6
    set mode $getOption($device,Mode)
    set tvID $getOption($device,TwinView)

    if { $calibration_sequence_only == 0 } {
	if { $mode != 1 } {
	    disableButtons
	    messageWindow "Warning " "\n\nDevice $device is in relative mode. \n\
		You can calibrate $device only when it is in absolute mode. \n\
		Please swith $device's mode and try again. "
	    closeTabWindow
	    return
	}
    }

#    bindtags .workingDev.list .
    if { $numScreens($device) > 1 } {
	displayScreenList $device
	if { $calibration_sequence_only == 0 } {
		set screenTags [ bindtags .screen.list.list]
		.screen.list.title configure -text "Select $device associated Screen:"
		wm state .screen normal
	} else {
		set screenTags [ bindtags .list.list]
		.list.title configure -text "Select $device associated Screen:"
		wm state . normal
	}
    } else {
	updateCurrentScreenInfo
	startCalibration
    }

    if { $calibration_sequence_only == 0 } {
	disableButtons
    }
}

proc startCalibration {} {
    global device size numScreens tvID orig_device
    global calibResults calibX_org calibY_org calibX_botm calibY_botm
    global screenX_org screenY_org screenXBottom screenYBottom
    global screenWidth screenHeight calibration_sequence_only
    
    if { $numScreens($device) > 1 } {
	if { $calibration_sequence_only == 0 } {
	     bindtags .screen.list.list .
	} else {
	     bindtags .list.list .
	}
    }

    # convert underscores back to spaces for wacomxi.c
    regsub -all {_} $device " " orig_device

    if { $tvID == 1 } { # Nvidia Xinerama setup starts at (0,0) even when it is not in xorg.conf
	set calibX_org 0
	set calibY_org 0
	set calibX_botm $screenWidth
	set calibY_botm $screenHeight
    } else {
	set calibX_org $screenX_org
	set calibY_org $screenY_org
	set calibX_botm $screenXBottom
	set calibY_botm $screenYBottom
    }
    set y_coor [ expr $calibY_botm-$size*(abs($calibY_botm)/$calibY_botm) ]
    set x_coor [ expr $calibX_botm-$size*(abs($calibX_botm)/$calibX_botm) ]
    pad .topleft +$calibX_org+$calibY_org
    pad .bottomright +$x_coor+$y_coor
    update
    #
    # Start calib sequence
    catch {unset calibResults}
    exec xsetwacom set "$device" xydefault
    .topleft.m configure -background "#df94df"
    # hide the cursor
    .topleft.m configure -cursor "center_ptr #df94df #df94df"
    wacomxi::bindevent .topleft.m "$orig_device" <ButtonRelease> \
		{calibrationSequence 0 %0 %1}
    .bottomright.m configure -background "#505075"
    #hide the cursor
    .bottomright.m configure -cursor "watch #505075 #505075"
    helpWindow "Help Window " \
		"\n\nPlease click on the center of \n\
		the pink crosshair using $device \n\
		Please don't click on anything else \n\
		by $device before you finish"
}

proc helpWindow { tString mString } {
    global showHelp

    if { $showHelp }  {
	messageWindow $tString $mString
    }
}

proc messageWindow { tString mString } {
    toplevel .mWindow
    wm title .mWindow $tString
    wm transient .mWindow .
    text .mWindow.text -background gray -width 40 -height 10
    button .mWindow.dismiss -text "Dismiss" \
		-command "destroy .mWindow; set ok 1"
    .mWindow.text insert end $mString
    pack .mWindow.text .mWindow.dismiss
    #
    # Do some spiffy animation to draw attention !
    for { set i 0 } { $i < 10 } { incr i } {
	after 100
	.mWindow.text configure -background white
	update
	after 100
	.mWindow.text configure -background gray
	update
    }
    tkwait variable ok 
}

proc updateScreenList {} {
    global currentScreen numScreens screenWidth screenHeight
    global device screenX_org screenY_org origin_x origin_y
    global calibration_sequence_only

    if { $numScreens($device) > 1 } {
	if { $calibration_sequence_only == 0 } {
	    set cScreen [ .screen.list.list get anchor ]
	} else {
	    set cScreen [ .list.list get anchor ]
	}

	for { set i 0 } { $i < $numScreens($device) } { incr i 1 } {
	    if { $cScreen == "Screen$i" } {
		set currentScreen $i
		set i $numScreens($device)
	    }
	}
    }
    updateCurrentScreenInfo
    set origin_x [ expr $screenX_org+$screenWidth/2-$screenWidth/4 ]
    set origin_y [ expr $screenY_org+$screenHeight/2-$screenHeight/4 ]
    wm geometry . =+$origin_x+$origin_y

    if { $calibration_sequence_only == 0 } {
	.screen.list.label configure -text $cScreen
	set o_x [ expr $origin_x+100 ]
	set o_y [ expr $origin_y+20 ]
	wm geometry .screen =+$o_x+$o_y
    } else {
	.list.label configure -text $cScreen
    }

    startCalibration
}

proc disableButtons {} {
    global bName numButton numStrips currentW currentb

    if { $currentb } {
	for { set i 1 } { $i <= [ expr ($numButton+$numStrips) ] } { incr i 1 } {
	    .allothers.f.$i configure -state disabled
	}
	.allothers.f.ok configure -state disable
	.allothers.f.default configure -state disable
	.allothers.f.cancel configure -state disable
    } else {
	if { $bName(pressure) } {
	    .panel.pressure configure -state disabled
	}
	if { $bName(calibrate) } {
	    .panel.calibrate configure -state disabled
	}
	if { $bName(button) } {
	    .panel.button configure -state disabled
	}
	if { $bName(mapping) } {
	    .panel.mapping configure -state disabled
	}
	if { $bName(advanced) } {
	    .panel.advanced configure -state disabled
	}
    }
}

proc getDeviceOptionProc { dev i } {
    global getOption getOptionDefault Option oldKeys modeToggleB
    global displayToggleB ignoreButton screenToggleB doubleClickB keystrokeB 
    global numStrips numControls numButton spName originalButton
    global xDefinedButtons

    for { set j 1 } { $j < [ expr $i+1 ] } { incr j 1 } {
	set value [ exec xsetwacom get "$dev" $Option($j) ] 
	set value1 [ exec xsetwacom getdefault "$dev" $Option($j) ] 
	if { ![ string compare -nocase -length 10 $Option($j) "PressCurve" ] } {
	    set getOption($dev,PressCurve) 4
	    set getOptionDefault($dev,PressCurve) 4

	    set p0 [ expr ( $value >> 24) & 0xFF ]
	    set p1 [ expr ( $value >> 16) & 0xFF ]
	    if { ($p1 > 5) && ($p1 < 35) } {
		set getOption($dev,PressCurve) 3
	    }
	    if { ($p1 >= 35) && ($p1 < 65) } {
		set getOption($dev,PressCurve) 2
	    }
	    if { ($p1 >= 65) && ($p1 < 95) } {
		set getOption($dev,PressCurve) 1
	    }
	    if { ($p0 > 5) && ($p0 < 35) } {
		set getOption($dev,PressCurve) 5
	    }
	    if { ($p0 >= 35) && ($p0 < 65) } {
		set getOption($dev,PressCurve) 6
	    }
	    if { ($p0 >= 65) && ($p0 < 95) } {
		set getOption($dev,PressCurve) 7
	    }
	} else {
	    set match 0
	    # are they button/wheel/ring/strip?
	    for { set k 1 } { $k <= $numControls } { incr k 1 } {
		if { ![string compare -nocase $Option($j) $spName($k)] } {
		    set match 1
		    break
		}
	    }
	    set getOption($dev,$Option($j)) $value
	    set getOptionDefault($dev,$Option($j)) $value1

	    if { $match } {
		if { $value1 == 0 } {
		    set getOptionDefault($dev,$Option($j)) $ignoreButton
		} elseif { ($value1 > $xDefinedButtons) && ($value1 < $doubleClickB) } {
 		    set getOptionDefault($dev,$Option($j)) $originalButton
		}

		if { ![string compare -nocase -length 8 DBLCLICK $value ] } {
		    set getOption($dev,$Option($j)) $doubleClickB
		} elseif { ![string compare -nocase -length 4 CORE $value ] } {
		    set getOption($dev,$Option($j)) $keystrokeB
		    set oldKeys($Option($j)) $value
		} elseif { ![string compare -nocase -length 10 MODETOGGLE $value ] } {
		    set getOption($dev,$Option($j)) $modeToggleB
		} elseif { ![string compare -nocase -length 13 DISPLAYTOGGLE $value ] } {
		    set getOption($dev,$Option($j)) $displayToggleB
		} elseif { ![string compare -nocase -length 12 SCREENTOGGLE $value ] } {
		    set getOption($dev,$Option($j)) $screenToggleB
		} elseif { $value == 0 } {
		    set getOption($dev,$Option($j)) $ignoreButton
		} elseif { ($value > $xDefinedButtons) && ($value < $doubleClickB) } {
		    set getOption($dev,$Option($j)) $originalButton
		}
	    }
	}
    }
}

proc CreateDevicePanel { type model } {
    global isLCD hasGesture

    if { ![ string compare $type "pad" ] } {
	createPanel 0 1 0 0
    } elseif { ![ string compare $type "touch" ] } {
	if { $hasGesture($model) != 0 } {
	    createPanel 1 1 0 1
	} else {
	    createPanel 1 0 0 1
	}
    } elseif { $isLCD($model) } { 
	if { ![ string compare $type "stylus" ] } {
	    createPanel 1 1 0 1
	} elseif { [ string compare $type "cursor" ] } {
	    createPanel 1 1 0 0
	}
    } elseif { [ string compare $type "cursor" ] } {
	createPanel 1 1 1 0
    } else {
	createPanel 0 1 1 0
    }
}

proc updateDevice {} {
    global device orig_device getDeviceModel

    set olddev $device
    set device [ .workingDev.list get anchor ]
    if { $device != $olddev && $olddev != ""} {
	# convert underscores back to spaces for wacomxi.c
   	regsub -all {_} $olddev " " orig_device

 	# Clear old state related to preceding device
	wacomxi::bindevent . $orig_device <ButtonPress> ""
	wacomxi::bindevent . $orig_device <ButtonRelease> ""
    }

    if { $device != ""} {
	#
	# Update the entry indicator
	#
	.workingDev.label configure -text $device
	set model $getDeviceModel($device,model)
	set type $getDeviceModel($device,type)
	destroy .panel
	CreateDevicePanel $type $model
    } else {
	#
	# Update the entry indicator
	#
	.workingDev.label configure -text $device
    }
}

proc createDeviceList {} {
    global getDeviceModel deviceList hasPad hasTouch isLCD

    set infoString [exec xsetwacom list]
    set index 0
    set deviceList ""
    set dev [ lindex $infoString $index ]

    while { $dev != "" } {
 	set index [ expr $index+1 ]
	set type [ lindex $infoString $index ]

	if { [catch { exec xsetwacom get "$dev" TabletID } model] == 0 } {
	    if { (![ string compare $type "cursor" ] && !$isLCD($model)) ||
		(![ string compare $type "touch" ] && $hasTouch($model)) ||
		(![ string compare $type "pad" ] && $hasPad($model)) ||
		![ string compare $type "stylus" ] || 
		![ string compare $type "eraser" ] } {
		    set getDeviceModel($dev,type) $type
		    set getDeviceModel($dev,model) $model
		    set deviceList "$deviceList \"$dev\""
	    }
	    set index [ expr $index+1 ]
	}
	set dev [ lindex $infoString $index ]
    }

    foreach dev $deviceList {
	# initial related erasers for styli
	set getDeviceModel($dev,eraser) ""
    }

    foreach dev $deviceList {
	set type $getDeviceModel($dev,type)
	if { ![string compare $type "eraser"] } {
	    set model $getDeviceModel($dev,model)
	    foreach dev1 $deviceList {
		set type1 $getDeviceModel($dev1,type)
		set model1 $getDeviceModel($dev1,model)
		if { ( $model == $model1 ) &&
			 ![string compare $type1 "stylus"] } {
		    set getDeviceModel($dev1,eraser) $dev
		}
	    }
	}
    }
}

proc createDeviceListPanel {} {
    global deviceList

    frame .workingDev
    label .workingDev.title -text "Select the Device:"
    label .workingDev.label -background gray
    listbox .workingDev.list -width 40 -height 12 \
	    -yscrollcommand ".workingDev.sb set"
    scrollbar .workingDev.sb -width 10 \
	    -command ".workingDev.list yview"
    grid .workingDev.title -row 0 -column 0 -columnspan 8 -sticky we
    grid .workingDev.label -row 1 -column 0 -columnspan 8 -sticky we
    grid .workingDev.list -row 2 -column 0
    grid .workingDev.sb -row 2 -sticky nse

    createDeviceList
    foreach dev $deviceList {
	.workingDev.list insert end $dev
	createScreenList $dev
    }
    bind .workingDev.list <ButtonRelease-1> updateDevice
}

proc createScreenList { dev } {
    global numScreens currentScreen getScreenInfo

    set numScreens($dev) [ exec xsetwacom get "$dev" NumScreen ]
    for { set i 0 } {$i < $numScreens($dev)} { incr i 1 } {
	set s1 [ exec xsetwacom get "$dev" SBottomX$i ]
	set s2 [ exec xsetwacom get "$dev" SBottomY$i ]
	set s3 [ exec xsetwacom get "$dev" STopX$i ]
	set s4 [ exec xsetwacom get "$dev" STopY$i ]
	set getScreenInfo($dev,Screen$i) "$s1 $s2 $s3 $s4"
    }
}

proc screenCancel {} {
    global calibration_sequence_only

    destroy .topleft .bottomright
    if { $calibration_sequence_only == 0 } {
	closeTabWindow
	destroy .screen
    } else {
	exit 0
    }
}

proc displayScreenList { dev } {
    global numScreens currentScreen calibration_sequence_only

    if {  $numScreens($dev) <= 1  } {
	return
    }

    if { $calibration_sequence_only == 0} {
	toplevel .screen
	wm title .screen "Screen List Window"
	wm transient .screen .
	wm geometry .screen =250x200
	wm state .screen withdraw
	button .screen.cancel -text "Close" -command screenCancel
	grid .screen.cancel -row 10
	frame .screen.list
	label .screen.list.title -text "Select the Screen:"
	label .screen.list.label -background gray
	listbox .screen.list.list -width 12 -height 5 -yscrollcommand ".screen.list.sb set"
	scrollbar .screen.list.sb -width 10 -command ".screen.list yview"
	grid .screen.list.title -row 2 -column 0 -columnspan 3 -sticky we
	grid .screen.list.label -row 3 -column 0 -columnspan 3 -sticky we
	grid .screen.list.list -row 4 -column 0
	grid .screen.list.sb -row 4 -column 1 -sticky nse
	for { set i 0 } { $i < $numScreens($dev) } { incr i } {
	    .screen.list.list insert end "Screen$i"
        }
	bind .screen.list.list <ButtonRelease-1> updateScreenList
	pack .screen.list .screen.cancel
    } else {
	button .cancel -text "Close" -command screenCancel
	grid .cancel -row 10
	frame .list
	label .list.title -text "Select the Screen:"
	label .list.label -background gray
	listbox .list.list -width 12 -height 5 -yscrollcommand ".list.sb set"
	scrollbar .list.sb -width 10 -command ".list yview"
	grid .list.title -row 2 -column 0 -columnspan 3 -sticky we
	grid .list.label -row 3 -column 0 -columnspan 3 -sticky we
	grid .list.list -row 4 -column 0
	grid .list.sb -row 4 -column 1 -sticky nse
	for { set i 0 } { $i < $numScreens($dev) } { incr i } {
	    .list.list insert end "Screen$i"
	}
	bind .list.list <ButtonRelease-1> updateScreenList
	pack .list .cancel
    }
}

proc updateButton {} {
    global device db getDeviceModel sm getOption spName isLCD
    global dm currentW oldKeys numButton cKeys numStrips startS
    global modeToggleB ignoreButton doubleClickB keystrokeB xDefinedButtons
    global displayToggleB screenToggleB originalButton maxNumButtons

    set type $getDeviceModel($device,type)
    set model $getDeviceModel($device,model)

    for { set i 1 } { $i <= [ expr ($numButton + $numStrips)] } { incr i 1 } {
	set k $i
	if { $i > $numButton } {
	    set k [ expr ($startS-1+$i) ]
	}

	set buttonAssigned [ $currentW.f.$i cget -text ]
	set v $buttonAssigned
	for { set l 1} { $l <= $originalButton } { incr l 1 } {
	    if { $db($l) != "" && ![string compare -nocase $buttonAssigned $db($l)] } {
		set j $l
		set v "Button $l"

		if { ![string compare -nocase $buttonAssigned "KeyStroke"] } {
		    set j $keystrokeB
		    if { $cKeys($spName($k)) == "" } {
			set v $oldKeys($spName($k))
		    } else {
			set v $cKeys($spName($k)) 
			set oldKeys($spName($k)) $cKeys($spName($k))
		    }
		} elseif { ![string compare -nocase $buttonAssigned "Application Defined"] } {
		    #don't change application defined button number back to X server defined
		    if { $i > $xDefinedButtons } {
			set j $i
			set v "Button $i"
		    }
		} elseif { ![string compare -nocase $buttonAssigned "Ignore"] } {
		    set j $ignoreButton
		    set v "Button 0"
		} elseif { $l >= $doubleClickB && $l < $screenToggleB } {
		    set j $l
		    set v $db($l)
		}
		set l [ expr ($originalButton+1) ]
	    }
	}

	set getOption($device,$spName($k)) $j
	updateXinitrc $device $spName($k) $v

	# reset key strokes 
	if { $j != $keystrokeB } {
	    set $oldKeys($spName($k)) ""
	    set cKeys($spName($k)) ""
	}
    }

    if { !$isLCD($model) && [string compare $type "pad"] } { 
	set mode [ $currentW.f.mode cget -text ]
	updateXinitrc $device mode $mode
	if { $mode == $dm(1) } {
	    set getOption($device,Mode) 0
	} else {
	    set getOption($device,Mode) 1
	}
    }

    if { ![ string compare $type "stylus" ] } {
	    set smode [ $currentW.f.smode cget -text ]
	    if { $smode == $sm(1) } {
		updateXinitrc $device TPCButton off
		set getOption($device,TPCButton) 0
	    } else {
		updateXinitrc $device TPCButton on
		set getOption($device,TPCButton) 1
	    }
    }
    closeSubWindow
}

proc defaultButton {} {
    global db isLCD
    global dm sm dmv smv numButton startS numStrips spName
    global device getOptionDefault getDeviceModel currentB

    for { set i 1 } { $i <= $numButton } { incr i 1 } {
	set currentB($i) $db($getOptionDefault($device,$spName($i)))
    }

    if { $startS } {
	for { set i $startS } { $i <= [ expr ($startS+$numStrips-1) ] } { incr i 1 } {
	    set k [ expr ($numButton+$i-$startS+1) ]
	    set currentB($k) $db($getOptionDefault($device,$spName($k)))
	}
    }

    set model $getDeviceModel($device,model)
    set type $getDeviceModel($device,type)

    if { !$isLCD($model) && [ string compare $type "pad" ] } { 
	set dmv $dm([ expr $getOptionDefault($device,Mode)+1 ])
    }

    if { ![ string compare $type "stylus" ] } {
	set smv $sm([ expr $getOptionDefault($device,TPCButton)+1 ])
    }
}

proc getNumButton { type } {
    global device Option numButton getDeviceModel numPadButtons
    
    set Option(1) "Button1"
    set t 1
    if { [ string compare $type "eraser" ] } {
	set Option(2) "Button2"
	set Option(3) "Button3"
	set t [ expr ($t+2) ]
	if { [ string compare $type "stylus" ] } {
	    set Option(4) "Button4"
	    set Option(5) "Button5"
	    set t [ expr ($t+2) ]
	}
	if { ![ string compare $type "pad" ] } {
	    set model $getDeviceModel($device,model)
	    set t $numPadButtons($model)
	    for { set i 6 } { $i <= $t } { incr i 1 } {
		set Option($i) "Button$i"
	    }
	}
    }

   set numButton $t
}

proc setspName {} {
    global numButton spName startS device Option cKeys oldKeys
    global numPadRelW numPadStrips numPadRings getDeviceModel
    global numControls numStrips getOption

    for { set i 1 } { $i <= $numButton } { incr i 1 } {
	set spName($i) Button$i
    }

    set spName([expr ($numButton + 1) ]) "RelWUp"
    set spName([expr ($numButton + 2) ]) "RelWDn"
    set spName([expr ($numButton + 3) ]) "AbsWUp"
    set spName([expr ($numButton + 4) ]) "AbsWDn"
    set spName([expr ($numButton + 5) ]) "StripLUp"
    set spName([expr ($numButton + 6) ]) "StripLDn"
    set spName([expr ($numButton + 7) ]) "StripRUp"
    set spName([expr ($numButton + 8) ]) "StripRDn"

    set numControls [expr ($numButton+8)]
    for { set i 1 } { $i <= $numControls } { incr i 1 } {
	set Option($i) $spName($i)
    }

    # initial keys before we call getDeviceOptionProc
    for { set i 1 } { $i <= $numControls } { incr i 1 } {
	set oldKeys($spName($i)) ""
	set cKeys($spName($i)) ""
    }

    getDeviceOptionProc $device $numControls

    set s1 5
    set s2 8
    set model $getDeviceModel($device,model)
    if { $numPadRelW($model) } { # G4
	set s1 1
	set s2 2
    } elseif { $numPadStrips($model) == 1 } { # I3 4x5
	set s1 5
	set s2 6
    } elseif { $numPadRings($model) } { # Bamboo
	set s1 3
	set s2 4
    }
    set startS $s1
    set numStrips [expr ($s2 - $s1) + 1]

}

proc initialButton {} {
    global device Option numButton getDeviceModel 
    global spName numStrips

    set type $getDeviceModel($device,type)
    set t $numButton

    if { [ string compare $type "pad" ] } {
	set t [expr ($t+1)]
	set Option($t) "Mode"
	set t [expr ($t+1)]
	set Option($t) "TPCButton"
    }
    getDeviceOptionProc $device $t

    if { [ string compare $type "pad" ] } {
    	displayMode
    }

    # initial controls
    setspName

    for { set i 1 } { $i <= $numButton } { incr i 1 } {
	addMenu $i
    }

    # then touch strip
    if { ![ string compare $type "pad" ] } {
	expressKeys
    } else {
	set numStrips 0
    }
}

proc displayMode {} {
    global device getDeviceModel sm smv
    global dmv dm getOption currentW isLCD

    set model $getDeviceModel($device,model)
    set type $getDeviceModel($device,type)

    if { !$isLCD($model) && [ string compare $type "pad" ]  } { 
 	set dmv $dm([ expr $getOption($device,Mode)+1 ])
	tk_optionMenu $currentW.f.mode dmv $dm(1) $dm(2)
	label $currentW.f.modeL -text "Positioning Mode: "
	grid $currentW.f.mode -row 4 -column 1
	grid $currentW.f.modeL -row 4 -column 0
    }

    if { ![ string compare $type "stylus" ] } {
	set smv $sm([ expr $getOption($device,TPCButton)+1 ])
	tk_optionMenu $currentW.f.smode smv $sm(1) $sm(2)
	label $currentW.f.smodeL -text "Side Switch Mode: "
	grid $currentW.f.smode -row 4 -column 4 
	grid $currentW.f.smodeL -row 4 -column 3
    }
}

proc displaySubWindow { okF deF initial winID cbutton kcurrent} {
    global currentb currentW wName currentk numPadButtons 
    global device getDeviceModel

    set currentb $cbutton
    set currentk $kcurrent
    if { $cbutton } {
	set currentW .keystrokes
    } else {
	set currentW .allothers
    }

    toplevel $currentW
    wm geometry $currentW =650x425
    wm title $currentW $wName($winID)
    wm transient $currentW .
    wm state $currentW normal
    frame $currentW.f
    button $currentW.f.ok -text "Ok" -command $okF
    button $currentW.f.cancel -text "Cancel" -command closeSubWindow

    set columnN 0
    set rowN 6
    if { $deF != 0 } {
	set columnN 2
	set rowN 8
	set model $getDeviceModel($device,model)

	if { [ expr ($numPadButtons($model)/2) ] > $rowN } {
		set rowN [ expr ($numPadButtons($model)/2 + 4) ]
	}
	button $currentW.f.default -text "Default" -command $deF
	grid $currentW.f.default -row $rowN -column 0 -columnspan 3 -padx 10 -pady 10
	#
	# Suppress tags on listboxes to prevent changing the
	# device and disable other controls
	bindtags .workingDev.list .
    }

    disableButtons
    $initial

    grid $currentW.f -row 0 -column 0 -sticky nw
    grid $currentW.f.ok -row $rowN -column [expr ($columnN + 4)] -columnspan 3 -padx 10 -pady 10
    grid $currentW.f.cancel -row $rowN -column [expr ($columnN + 1)] -columnspan 3 -padx 10 -pady 10
}

proc closeSubWindow {} {
    global currentW
    destroy $currentW
    closeTabWindow
}

proc closeTabWindow {} {
    global bName workingTags currentW numButton 
    global currentb cKeys spName numStrips 

    if { $bName(keystroke) } {
	set bName(keystroke) 0
	set currentW .allothers
	for { set i 1 } { $i <= [ expr ($numButton+$numStrips) ] } { incr i 1 } {
	    $currentW.f.$i configure -state normal
	}
	$currentW.f.default configure -state normal
	$currentW.f.ok configure -state normal
	$currentW.f.cancel configure -state normal
	set currentb 0
    } else {
	if { $bName(pressure) } {
	    .panel.pressure configure -state normal
	}
	if { $bName(calibrate) } {
	    .panel.calibrate configure -state normal
	}
	if { $bName(button) } {
	    .panel.button configure -state normal
	}
	if { $bName(mapping) } {
	    .panel.mapping configure -state normal
	}
	if { $bName(advanced) } {
	    .panel.advanced configure -state normal
	}
	for { set i 1 } { $i <= [ expr ($numButton+$numStrips) ] } { incr i 1 } {
	    set cKeys($spName($i)) ""
	}
	bindtags .workingDev.list $workingTags
    }
}

proc expressKeys { } {
    global db currentW device numButton spName numStrips startS
    global getDeviceModel cKeys oldKeys getOption currentB
    global displayToggleB ignoreButton keystrokeB screenToggleB
    global numPadRings numPadStrips numPadAbsW numPadRelW

    set name(1) "Wheel Up"
    set name(2) "Wheel Down"
    set name(3) "Ring Anticlockwise"
    set name(4) "Ring Clockwise"
    set name(5) "Left Strip Up"
    set name(6) "Left Strip Down"
    set name(7) "Right Strip Up"
    set name(8) "Right Strip Down"

    set s2 [expr ($startS + $numStrips) - 1]
    for { set i $startS } { $i <= $s2 } { incr i 1 } {
	set curb [ expr ($numButton + $i - $startS + 1) ]
	set curOption [ expr ($numButton + $i) ]
	set opt $getOption($device,$spName($curOption))
	if { $opt == "" } { set opt $ignoreButton }

	set currentB($curb) $db($opt) 
	#reset keys
	if { $opt != $keystrokeB } {
	    set cKeys($spName($curOption)) ""
	    set oldKeys($spName($curOption)) ""
	}

	set bmenu [ tk_optionMenu $currentW.f.$curb currentB($curb) $db(1) $db(2) \
	    $db(3) $db(4) $db(5) $db(6) $db(7) $db($ignoreButton) ]
	$bmenu insert 7 radiobutton -label "$db($keystrokeB)" \
	    -variable menvar -command "displaySubWindow \
	    updateKeys 0 initialKeys 5 $curb $curOption"

	label $currentW.f.name$curb -text "$name($i): "
	set t2 [expr ($numButton+1)/2+1]
	set t1 0
	if { [expr ($s2 - $startS) > 1] } {
	    if { $i == [expr ($startS+1)] || \
		    $i == [expr ($startS+3)] } { 
		set t2 [expr ($numButton+1)/2+2]
	    }
	    if { [expr ($i - $startS) > 1] } {
		set t1 2
	    }
	} else {
	    if { [expr ($i - $startS) > 0] } {
		set t1 2
	    }
	}
	grid $currentW.f.$curb -row $t2 -column [expr $t1+1] 
	grid $currentW.f.name$curb -row $t2 -column $t1
    }
}

proc addMenu { curb } {
    global db currentW device spName currentB getOption getDeviceModel
    global cKeys oldKeys keystrokeB doubleClickB screenToggleB
    global displayToggleB ignoreButton modeToggleB originalButton
    global xDefinedButtons

    set model $getDeviceModel($device,model)
    set type $getDeviceModel($device,type)

    set opt $getOption($device,$spName($curb))

    if { $opt == "" } { set opt $curb }
    if { ($opt > $xDefinedButtons) && ($opt < $doubleClickB) } {
	 set currentB($curb) $db($originalButton)
    } else {
	set currentB($curb) $db($opt) 
    }

    #reset keys
    if { $opt != $keystrokeB } {
	set cKeys($spName($curb)) ""
	set oldKeys($spName($curb)) ""
    }

    if { [string compare $type "pad"] } {
	set bmenu [ tk_optionMenu $currentW.f.$curb currentB($curb) \
		$db(1) $db(2) $db(3) $db(4) $db(5) $db(6) $db(7) \
		$db($doubleClickB) $db($modeToggleB) $db($displayToggleB) \
		$db($screenToggleB) $db($ignoreButton) ]
	set i 11
    } else {
	set bmenu [ tk_optionMenu $currentW.f.$curb currentB($curb) \
		$db(1) $db(2) $db(3) $db(4) $db(5) $db(6) $db(7) \
		$db($doubleClickB) $db($displayToggleB) \
		$db($screenToggleB) $db($ignoreButton) ]
	set i 10
    }

    # add keystroke before "Application Defined"
    $bmenu insert $i radiobutton -label "$db($keystrokeB)" \
	-variable menvar -command "displaySubWindow \
	updateKeys 0 initialKeys 5 $curb $curb"

    # add "Application Defined" only when it is necessary
    set i [ expr ($i + 1) ]
    if { ($curb > $xDefinedButtons) || ($opt > $xDefinedButtons) } {
	$bmenu insert $i radiobutton -label "$db($originalButton)" \
	    -variable menvar
    }

    label $currentW.f.name$curb -text "Button $curb: "
    set t2 [expr ($curb-1)/2]
    if { [expr ($curb/2)] == [expr ($curb+1)/2] } {
	set t1 2
    } else {
	set t1 0
    }

    grid $currentW.f.$curb -row $t2 -column [expr ($t1+1)]
    grid $currentW.f.name$curb -row $t2 -column $t1
}

proc initialT {} {
    global device getDeviceModel currentW
    global getOption getOptionDefault Option

    set Option(1) "TopX"
    set Option(2) "TopY"
    set Option(3) "BottomX"
    set Option(4) "BottomY"
    set Option(5) "SpeedLevel"
    set Option(6) "Accel"
    set Option(7) "Mode"

    getDeviceOptionProc $device 7

    set mode $getOption($device,Mode)
    frame $currentW.f.group -bd 10 -bg beige -width 150 -height 150

    if { $mode == 1 } {
	label $currentW.f.groupL -text "Mapping: "
	for { set i 1 } { $i < 5 } { incr i 1 } {
	    addMapScale $i
	}
    } else {
	label $currentW.f.groupL -text "Movement: "
	label $currentW.f.group.l1 -text "SpeedLevel: "
	grid $currentW.f.group.l1 -row 0 -column 6
	scale $currentW.f.group.scale1 -orient horizontal -length 100 \
		-from 1 -to 11
	grid $currentW.f.group.scale1 -row 0 -column 8
	$currentW.f.group.scale1 set $getOption($device,SpeedLevel)
	label $currentW.f.group.l2 -text "Slow"
	grid $currentW.f.group.l2 -row 1 -column 7
	label $currentW.f.group.l3 -text "Fast"
	grid $currentW.f.group.l3 -row 1 -column 9
	label $currentW.f.group.l4 -text "Acceleration: "
	grid $currentW.f.group.l4 -row 2 -column 6
	scale $currentW.f.group.scale2 -orient horizontal -length 100 \
		-from 1 -to 7
	grid $currentW.f.group.scale2 -row 2 -column 8
	$currentW.f.group.scale2 set $getOption($device,Accel)
	label $currentW.f.group.l5 -text "Linear"
	grid $currentW.f.group.l5 -row 3 -column 7
	label $currentW.f.group.l6 -text "High"
	grid $currentW.f.group.l6 -row 3 -column 9
    }

    grid $currentW.f.group -row 0 -column 5 
    grid $currentW.f.groupL -row 0 -column 2
}

proc addMapScale { t } {
    global getOption Option getOptionDefault device currentW

    label $currentW.f.group.l$t -text "$Option($t): "
    grid $currentW.f.group.l$t -row [ expr $t-1 ] -column 6
    set j $t
    if { $j < 3 } { set j [expr $j+2] }
    scale $currentW.f.group.scale$t -orient horizontal -length 200 \
		-from -200 -to [expr $getOptionDefault($device,$Option($j))+200]
    grid $currentW.f.group.scale$t -row [ expr $t-1 ] -column 8
    $currentW.f.group.scale$t set $getOption($device,$Option($t))
}

proc updateT {} {
    global getOption getOptionDefault Option device currentW

    set mode $getOption($device,Mode)
    if { $mode == 1 } {
	for { set i 1 } { $i < 5 } { incr i 1 } {
	    set value [ $currentW.f.group.scale$i get ]
	    updateXinitrc $device $Option($i) $value
	    set getOption($device,$Option($i)) $value
	}
    } else {
	set value [ $currentW.f.group.scale1 get ]
	updateXinitrc $device SpeedLevel $value
	set value [ $currentW.f.group.scale2 get ]
	updateXinitrc $device Accel $value
	set getOption($device,Accel) $value
    }
    closeSubWindow
}

proc defaultT {} {
    global getOption getOptionDefault Option device currentW

    set mode $getOption($device,Mode)
    if { $mode == 1 } {
	for { set i 1 } { $i < 5 } { incr i 1 } {
	    $currentW.f.group.scale$i set $getOptionDefault($device,$Option($i))
	}
    } else {
	$currentW.f.group.scale1 set $getOptionDefault($device,SpeedLevel)
	$currentW.f.group.scale2 set $getOptionDefault($device,Accel)
    }
}

proc initialTip {} {
    global device getDeviceModel getOption Option currentW

    set Option(1) "PressCurve"
    set Option(2) "ClickForce"
    set Option(3) "RawSample"
    set Option(4) "Suppress"
    getDeviceOptionProc $device 4

    frame $currentW.f.group -bd 10 -bg beige -width 150 -height 150
    label $currentW.f.group.groupl1 -text "Tip Sensitivity: "
    grid $currentW.f.group.groupl1 -row 0 -column 0
    scale $currentW.f.group.scale1 -orient horizontal -length 100 \
		-from 1 -to 7
    grid $currentW.f.group.scale1 -row 0 -column 8
    set curve $getOption($device,PressCurve)

    $currentW.f.group.scale1 set $curve
    label $currentW.f.group.l2 -text "Soft"
    grid $currentW.f.group.l2 -row 1 -column 7
    label $currentW.f.group.l3 -text "Firm"
    grid $currentW.f.group.l3 -row 1 -column 9

    label $currentW.f.group.groupl2 -text "Click Force: "
    grid $currentW.f.group.groupl2 -row 3 -column 0
    label $currentW.f.group.l4 -text "Low"
    grid $currentW.f.group.l4 -row 4 -column 7
    label $currentW.f.group.l5 -text "High"
    grid $currentW.f.group.l5 -row 4 -column 9
    scale $currentW.f.group.scale2 -orient horizontal -length 100 \
		-from 1 -to 21
    grid $currentW.f.group.scale2 -row 3 -column 8
    $currentW.f.group.scale2 set $getOption($device,ClickForce)

    label $currentW.f.group.groupl3 -text "Smoothness: "
    grid $currentW.f.group.groupl3 -row 5 -column 0
    label $currentW.f.group.l6 -text "Low"
    grid $currentW.f.group.l6 -row 6 -column 7
    label $currentW.f.group.l7 -text "High"
    grid $currentW.f.group.l7 -row 6 -column 9
    scale $currentW.f.group.scale3 -orient horizontal -length 100 \
               -from 1 -to 20
    grid $currentW.f.group.scale3 -row 5 -column 8
    $currentW.f.group.scale3 set $getOption($device,RawSample)

    label $currentW.f.group.groupl4 -text "Suppress Points: "
    grid $currentW.f.group.groupl4 -row 7 -column 0
    label $currentW.f.group.l8 -text "Low"
    grid $currentW.f.group.l8 -row 8 -column 7
    label $currentW.f.group.l9 -text "High"
    grid $currentW.f.group.l9 -row 8 -column 9
    scale $currentW.f.group.scale4 -orient horizontal -length 100 \
               -from 1 -to 20
    grid $currentW.f.group.scale4 -row 7 -column 8
    $currentW.f.group.scale4 set $getOption($device,Suppress)

    grid $currentW.f.group -row 0 -column 5 
}

proc updateTip {} {
    global device currentW

    switch [ $currentW.f.group.scale1 get ] {
	1 
	    { set curve "0 75 25 100" }
	2  
	    { set curve "0 50 50 100" }
	3  
	    { set curve "0 25 75 100" }
	4  
	    { set curve "0 0 100 100" }
	5  
	    { set curve "25 0 100 75" }
	6  
	    { set curve "50 0 100 50" }
	7  
	    { set curve "75 0 100 25" }
    }
    updateXinitrc $device PressCurve $curve
    set getOption($device,PressCurve) $curve
    updateXinitrc $device ClickForce [ $currentW.f.group.scale2 get ]
    set getOption($device,ClickForce) [ $currentW.f.group.scale2 get ]
    updateXinitrc $device RawSample [ $currentW.f.group.scale3 get ]
    set getOption($device,RawSample) [ $currentW.f.group.scale3 get ]
    updateXinitrc $device Suppress [ $currentW.f.group.scale4 get ]
    set getOption($device,Suppress) [ $currentW.f.group.scale4 get ]

    closeSubWindow
}

proc defaultTip {} {
    global currentW

    $currentW.f.group.scale1 set 4
    $currentW.f.group.scale2 set 6
}

proc initialSet {} {
    global device getDeviceModel getOption Option
    global tvCurrent tvID snd currentW tvDefined

    # used by both TwinView and non TwinView multimonitor setup
    label $currentW.f.sns -text "Display Mapping: "

    set Option(1) "NumScreen"
    set Option(2) "TwinView"
    set Option(3) "Screen_no"
    getDeviceOptionProc $device 3

    set numS  $getOption($device,NumScreen)
    set tvID $getOption($device,TwinView)
    set snd $getOption($device,Screen_no)

    if { $snd == -1 } {
	set snd "Desktop" 
    } else {
	set snd "Screen$snd"
    }

    if { $numS == 1 } {
	set sn0 "Desktop" 
	set sn1 "Screen0"
	set sn2 "Screen1"
	tk_optionMenu $currentW.f.snsmenu snd $sn0 $sn1 $sn2
    } else {
	set smenu [ tk_optionMenu $currentW.f.snsmenu snd "Desktop" ]
	pack $currentW.f.snsmenu -side left
	for { set i 0 } { $i < $numS } { incr i } {
	    $smenu insert $i radiobutton -label "Screen$i" \
		-variable smenvar -command \
		{ global smenvar; set snd $smenvar }
	}
    }

    grid $currentW.f.sns -row 5 -column 0 
    grid $currentW.f.snsmenu -row 5 -column 1
    if { $numS > 1 } {
	$currentW.f.snsmenu configure -state normal
    } else {
	$currentW.f.snsmenu configure -state disable 
    }

    label $currentW.f.tv -text "TwinView Setup: "
    set tvDefined(0) "None"
    set tvDefined(1) "Xinerama"
    set tvDefined(2) "Vertical"
    set tvDefined(3) "Horizontal"
    set tvDefined(4) "AboveOf"
    set tvDefined(5) "LeftOf"

    for { set i 0 } { $i < 6 } { incr i 1 } {
	if { $tvID == $i } {
	    set tvCurrent $tvDefined($i)
	}
    }

    tk_optionMenu $currentW.f.tvmenu tvCurrent $tvDefined(0) $tvDefined(1) \
	$tvDefined(2) $tvDefined(3) $tvDefined(4) $tvDefined(5)
    grid $currentW.f.tv -row 4 -column 0 
    grid $currentW.f.tvmenu -row 4 -column 1

    $currentW.f.tvmenu configure -state normal
    label $currentW.f.message1 -text "\nThe \"TwinView Setup\" option "
    label $currentW.f.message2 -text "is only for Nvidia graphic card."
    label $currentW.f.message3 -text "If your graphic card is not from Nvidia, "
    label $currentW.f.message4 -text "please leave the option as \"None\".\n"
 
    grid $currentW.f.message1 -row 0 -column 1
    grid $currentW.f.message2 -row 1 -column 1
    grid $currentW.f.message3 -row 2 -column 1
    grid $currentW.f.message4 -row 3 -column 1
}

proc updateSet {} {
    global device currentW tvCurrent snd tvID tvDefined

    set numS [ exec xsetwacom get "$device" NumScreen ]

    if { $numS > 1 } {
	set sn [ $currentW.f.snsmenu cget -text ]
	if { ![ string compare $sn "Desktop" ] } {
	    set sn -1
	} else {
	    for { set i 0 } { $i < $numS } { incr i 1 } {
		if { $sn == "Screen$i" } {
		    set sn $i
		}
	    }
	}
	updateXinitrc $device Screen_No $sn
	set getOption($device,Screen_No) $sn
    }

    set tvString [ $currentW.f.tvmenu cget -text ]
    for { set i 0 } {$i <= 5 } { incr i 1 } {
	if { ![ string compare $tvString $tvDefined($i) ] } {
	    set tv $i
	}
    }

    if { $tv != $tvID } {
	set tvCurrent $tv
	updateXinitrc $device TwinView $tv
	set getOption($device,TwinView) $tv
    }

    closeSubWindow
}

proc defaultSet {} {
    global tvCurrent snd

    set tvCurrent "None"
    set snd "Desktop"
}

proc initialKeys {} {
    global device getDeviceModel getOption cKeys spName 
    global Option oldKeys currentW bName currentb currentk

    frame $currentW.f.panelt
    set bName(keystroke) 1
    text $currentW.f.panelt.input -width 40 -height 10 \
	-yscrollcommand "$currentW.f.panelt.srl_y set" 

    if { $cKeys($spName($currentk)) != "" } {
	$currentW.f.panelt.input insert end $cKeys($spName($currentk))
    } else {
	if { $oldKeys($spName($currentk)) != "" } {
	    $currentW.f.panelt.input insert end $oldKeys($spName($currentk))
	    set cKeys($spName($currentk)) $oldKeys($spName($currentk))
	}
    }
    scrollbar $currentW.f.panelt.srl_y -width 10 -command \
	"$currentW.f.panelt.input yview"
    label $currentW.f.panelt.title1 -text "Entered keystrokes (type the keys if they are not in the lists):"
    grid $currentW.f.panelt.title1 -row 0 -column 0 -sticky we
    grid $currentW.f.panelt.input -row 1 -column 0 -sticky we
    grid $currentW.f.panelt.srl_y -row 1 -sticky nse

    frame $currentW.f.panel
    set mod(1) "SHIFT"
    set mod(2) "CTRL"
    set mod(3) "ALT"
    set mod(4) "META"
    set mod(5) "SUPER"
    set mod(6) "HYPER"
    set mmenu [ tk_optionMenu $currentW.f.panel.modmenu mod0 "Modifiers" ]
    pack $currentW.f.panel.modmenu -side left
    label $currentW.f.panel.title2 -text "Select special keys below:"
    grid $currentW.f.panel.title2 -row 0 -column 2 
    grid $currentW.f.panel.modmenu -row 1 -column 2 
    $mmenu delete 0
    for { set i 1 } { $i <= 6 } { incr i 1 } {
	$mmenu insert $i radiobutton -label $mod($i) \
	-variable menvar -command \
        { $currentW.f.panelt.input insert end " "; \
	global menvar; \
	$currentW.f.panelt.input insert end $menvar; \
	$currentW.f.panelt.input insert end " " }
    }

    set fk(1) "F1"
    set fk(2) "F2"
    set fk(3) "F3"
    set fk(4) "F4"
    set fk(5) "F5"
    set fk(6) "F6"
    set fk(7) "F7"
    set fk(8) "F8"
    set fk(9) "F9"
    set fk(10) "F10"
    set fk(11) "F11"
    set fk(12) "F12"
    set fmenu [ tk_optionMenu $currentW.f.panel.fmenu fk0 "Function Keys" ]
    pack $currentW.f.panel.fmenu -side left
    grid $currentW.f.panel.fmenu -row 2 -column 2
    $fmenu delete 0
    for { set i 1 } { $i <= 12 } { incr i 1 } {
	$fmenu insert $i radiobutton -label $fk($i) \
	-variable fmenvar -command \
        { $currentW.f.panelt.input insert end " "; \
	global fmenvar; \
	$currentW.f.panelt.input insert end $fmenvar; \
	$currentW.f.panelt.input insert end " " }
    }

    set fs(1) "quotedbl"
    set fs(2) "Pause"
    set fs(3) "ScrollLock"
    set fs(4) "SysReq"
    set fs(5) "End"
    set fs(6) "Insert"
    set fs(7) "Delete"
    set fs(8) "Enter"
    set fs(9) "Home"
    set fs(10) "backslash"
    set fs(11) "break"
    set fs(12) "print"
    set fsmenu [ tk_optionMenu $currentW.f.panel.fsmenu fs0 "Special Keys 1" ]
    pack $currentW.f.panel.fsmenu -side left
    grid $currentW.f.panel.fsmenu -row 3 -column 2 
    $fsmenu delete 0
    for { set i 1 } { $i <= 12 } { incr i 1 } {
	$fsmenu insert $i radiobutton -label $fs($i) \
	-variable fsmenvar -command \
        { $currentW.f.panelt.input insert end " "; \
	global fsmenvar; \
	$currentW.f.panelt.input insert end $fsmenvar; \
	$currentW.f.panelt.input insert end " " }
    }

    set sk(1) "Esc"
    set sk(2) "Tab"
    set sk(3) "CapsLock"
    set sk(4) "PageUp"
    set sk(5) "PageDown"
    set sk(6) "Left"
    set sk(7) "Up"
    set sk(8) "Down"
    set sk(9) "Right"
    set sk(10) "space"
    set sk(11) "NumLock"
    set sk(12) "BackSpace"
    set skmenu [ tk_optionMenu $currentW.f.panel.skmenu sk0 "Special Keys 2" ]
    pack $currentW.f.panel.skmenu -side left
    grid $currentW.f.panel.skmenu -row 4 -column 2 
    $skmenu delete 0
    for { set i 1 } { $i <= 12 } { incr i 1 } {
	$skmenu insert $i radiobutton -label $sk($i) \
	-variable skmenvar -command \
        { $currentW.f.panelt.input insert end " "; \
	global skmenvar; \
	$currentW.f.panelt.input insert end $skmenvar; \
	$currentW.f.panelt.input insert end " " }
    }

    set kp(1) "PgUp"
    set kp(2) "PgDn"
    set kp(3) "KPLeft"
    set kp(4) "KPUp"
    set kp(5) "KPDown"
    set kp(6) "KPRight"
    set kp(7) "Plus"
    set kp(8) "Minus"
    set kp(9) "Divide"
    set kp(10) "Multiply"
    set kp(11) "KPEnd"
    set kp(12) "Ins"
    set kp(13) "Del"
    set kp(14) "KPEnter"
    set kp(15) "KPHome"
    set kpmenu [ tk_optionMenu $currentW.f.panel.kpmenu kp0 "KeyPad Keys" ]
    pack $currentW.f.panel.kpmenu -side left
    grid $currentW.f.panel.kpmenu -row 5 -column 2 
    $kpmenu delete 0
    for { set i 1 } { $i <= 15 } { incr i 1 } {
	$kpmenu insert $i radiobutton -label $kp($i) \
	-variable kpmenvar -command \
        { $currentW.f.panelt.input insert end " "; \
	global kpmenvar; \
	$currentW.f.panelt.input insert end $kpmenvar; \
	$currentW.f.panelt.input insert end " " }
    }

    grid $currentW.f.panelt -row 0 -column 0
    grid $currentW.f.panel -row 0 -column 2 
}

proc updateKeys {} {
    global device oldKeys currentb cKeys spName currentW originalButton
    global db currentk ignoreButton keystrokeB currentB

    set keys [ $currentW.f.panelt.input get 1.0 end ]

    # remove newline characters 
    set index [ string last "\n" $keys ]
    while { $index != -1 } {
	set keys [ string replace $keys $index [expr ($index+1) ] ]
	set index [ string last "\n" $keys ]
    }

    if { $oldKeys($spName($currentk)) != $keys } {
	if { [string compare -nocase -length 8 $keys "core key"] } {
	    set cKeys($spName($currentk)) "core key $keys"
	} else {
	    set cKeys($spName($currentk)) $keys
	}
    }

    if { $cKeys($spName($currentk)) != "" } {
	set currentB($currentb) $db($keystrokeB)
    } elseif { [string compare -nocase -length 6 $spName($currentk) "button"] } {
	set currentB($currentb) $db($originalButton)
    } else {
	set currentB($currentb) $db($ignoreButton)
    }

    if { [ string length $cKeys($spName($currentk)) ] > 240 } {
	helpWindow "Help Window " \
		"\n\nYou have entered more 240 keys. \n\
		wacomcpl only accepts 240 keys. \n\
		Please reduce your keys. "
    } else {
	closeSubWindow
    }
}

proc touchState { theCButton } {
    global device touchButton getDeviceModel

    checkbutton $theCButton -text "Disable Touch" -anchor w \
	-variable touchButton -state normal -command switchTouch
}

proc gestureState { theCButton } {
    global device touchButton getDeviceModel gestureButton 

    # gesture supported and touch is on 
    if { [ exec xsetwacom get "$device" touch ] } {
	checkbutton $theCButton -text "Disable Touch Gesture" -anchor w \
	    -variable gestureButton -state normal -command switchGesture
    } else {
	checkbutton $theCButton -text "Disable Touch Gesture" -anchor w \
	    -variable gestureButton -state disable -command switchGesture
    }
}

proc switchTouch { } {
    global device touchButton gestureButton hasGesture getDeviceModel

    set model $getDeviceModel($device,model)
    if { $touchButton } {
	exec xsetwacom set "$device" touch 0
	updateXinitrc $device touch 0
	if { $hasGesture($model) } {
	    .panel.button configure -state disabled
	}
    } else {
	exec xsetwacom set "$device" touch 1
	updateXinitrc $device touch 1
	if { $hasGesture($model) } {
	    .panel.button configure -state normal
	}
   }
}

proc switchGesture { } {
    global device touchButton gestureButton

    if { $gestureButton } {
	exec xsetwacom set "$device" gesture 0
	updateXinitrc $device gesture 0
    } else {
	exec xsetwacom set "$device" gesture 1
	updateXinitrc $device gesture 1
   }
}

proc createPanel { pressure button mapping calibrate } {
    global bName device getOption getDeviceModel currentb 
    global wName startS Option touchButton hasGesture gestureButton

    frame .panel
    set bName(pressure) $pressure
    set bName(button) $button
    set bName(mapping) $mapping
    set bName(calibrate) $calibrate
    set currentb 0
    set type $getDeviceModel($device,type)

    # buttons and expresskeys
    getNumButton $type
    setspName
    set SN [ exec xsetwacom get "$device" ToolSerial ]
    if { $SN && [string compare type "pad"] } {
	set hexSN [format %X $SN]
	label .panel.snt -text "Serial Number: "
	label .panel.sn -text "$hexSN"
	grid .panel.snt -row 0 -column 0 -columnspan 2 -padx 3 -pady 3
	grid .panel.sn -row 0 -column 3 -columnspan 2 -padx 3 -pady 3
    }

    if { $calibrate } {
	button .panel.calibrate -text "Calibration" \
	    -command Calibration -state normal
	grid .panel.calibrate -row 5 -column 3 -columnspan 2 -sticky news -padx 10
    }
    if { $pressure } {
	if { ![string compare $getDeviceModel($device,type) "touch"] } {
	    set touchButton 1
	    if { [exec xsetwacom get "$device" touch] } {
		set touchButton 0
	    }
	    touchState .panel.pressure 
	} else {
	    set wName(1) "Feel"
	    button .panel.pressure -text $wName(1) \
		-state normal -command "displaySubWindow \
	    updateTip defaultTip initialTip 1 0 0"
	}
	grid .panel.pressure -row 5 -column 0 -columnspan 2 -sticky news -padx 10
    }
    if { $button } {
	if { ![string compare $getDeviceModel($device,type) "touch"] } {
	    set model $getDeviceModel($device,model)
	    if { $hasGesture($model) } {
		set gestureButton 1
		if { [ exec xsetwacom get "$device" gesture ] } {
		    set gestureButton 0
		}
		gestureState .panel.button 
	    }
	} elseif { ![string compare $getDeviceModel($device,type) "pad"] } {
	    button .panel.button -text $wName(6) \
		-state normal -command "displaySubWindow \
		updateButton defaultButton initialButton 6 0 $startS"
	} else {
	    button .panel.button -text $wName(2) \
		-state normal -command "displaySubWindow \
		updateButton defaultButton initialButton 2 0 0"
	}
	grid .panel.button -row 6 -column 0 -columnspan 2 -sticky news -padx 10
    }
    if { $mapping } {
	button .panel.mapping -text $wName(3) \
	   -state normal -command "displaySubWindow \
	   updateT defaultT initialT 3 0 0"
	grid .panel.mapping -row 6 -column 3 -columnspan 2 -sticky news -padx 10
    }

    set bName(advanced) 0
    if { [string compare $getDeviceModel($device,type) "touch"] &&
	    [string compare $getDeviceModel($device,type) "pad"] } { #not a pad or touch
	set Option(1) "Mode"
	getDeviceOptionProc $device 1
	set mode $getOption($device,Mode)
   	if { ($pressure || $mapping) && $mode } {  #and in absolute mode
	    set bName(advanced) 1
	    button .panel.advanced -text $wName(4) \
		-state normal -command "displaySubWindow \
		updateSet defaultSet initialSet 4 0 0"
	    grid .panel.advanced -row 9 -column 2 -columnspan 2 -sticky news -padx 10
	}
    }

    grid .panel -row 0 -column 1 -columnspan 8 -sticky news -padx 10 -pady 40
}

proc updateModelInfo { } {
    global isLCD numPadButtons numPadRings hasPad hasTouch
    global numPadStrips numPadAbsW numPadRelW 
    global maxNumTablets hasGesture 

    for { set i 0 } { $i <= $maxNumTablets } { incr i 1 } {
	set isLCD($i) 0 
	set numPadButtons($i) 0
	set numPadRings($i) 0
	set numPadStrips($i) 0
	set numPadAbsW($i) 0
	set numPadRelW($i) 0
	set hasPad($i) 0
	set hasTouch($i) 0
	set hasGesture($i) 0
    }
    #PL
    for { set i 48} { $i <= 63 } { incr i 1 } {
	set isLCD($i) 1 
    }
    #TabletPC
    for { set i 144 } { $i <= 159 } { incr i 1 } {
	set isLCD($i) 1 
    }
    #TabletPC with 2FG touch
    set isLCD(226) 1 
    set isLCD(227) 1 

    #Cintiq
    for { set i 197 } { $i <= 206 } { incr i 1 } {
	set isLCD($i) 1 
    }

    # G4
    set numPadButtons(21) 2
    set numPadButtons(22) 2
    set numPadRelW(21) 1
    set numPadRelW(22) 1
    # Bamboo Fun
    set numPadButtons(23) 4 
    set numPadRings(23) 1
    set numPadButtons(24) 4
    set numPadRings(24) 1
    #Cintiq 21UX
    set numPadButtons(63) 8
    set numPadStrips(63) 2
    # Bamboo
    for { set i 101 } { $i <= 105 } { incr i 1 } {
	set numPadButtons($i) 4
	set numPadRings($i) 1
   }

    # Bamboo Pen and Touch
    for { set i 208 } { $i < 212 } { incr i 1 } {
        set hasPad($i) 1
        set numPadButtons($i) 4
	set hasTouch($i) 1
	set hasGesture($i) 1
    }

    # I3
    set numPadButtons(176) 4
    set numPadStrips(176) 1
    for { set i 177 } { $i <= 182 } { incr i 1 } {
	set numPadButtons($i) 8
	set numPadStrips($i) 2
    }
    set numPadButtons(183) 4
    set numPadStrips(183) 1

    # Cintiq 20WSX
    set numPadButtons(197) 10
    set numPadStrips(197) 2

    # Hummingbird (Cintiq 12WX)
    set numPadButtons(198) 10
    set numPadStrips(198) 2

   # Cintiq 21UX2
    set numPadButtons(204) 18
    set numPadStrips(204) 2

    # I4
    set numPadButtons(184) 7
    set numPadRings(184) 1
    for { set i 185 } { $i <= 189 } { incr i 1 } {
	set numPadButtons($i) 9
	set numPadRings($i) 1
    }

    for { set i 0 } { $i <= $maxNumTablets } { incr i 1 } {
	if { $numPadButtons($i) || $numPadRings($i) 
		|| $numPadStrips($i) || $numPadAbsW($i) 
		|| $numPadRelW($i) } {
	    set hasPad($i) 1
	}
    }

    # one finger 
    for { set i 147 } { $i <= 159 } { incr i 1 } {
	set hasTouch($i) 1
    }

    # 2FG
    for { set i 226 } { $i <= 227 } { incr i 1 } {
	set hasTouch($i) 1
	set hasGesture($i) 1
    }
}

proc createControls { } {
    global numScreens currentScreen cKeys spName xDefinedButtons
    global oldKeys numStrips maxNumButtons maxNumStripEvents
    global workingTags db dm sm wName bName numButton
    global doubleClickB ignoreButton displayToggleB 
    global modeToggleB keystrokeB screenToggleB originalButton

    updateModelInfo
    createDeviceListPanel 

    set db(1) "Left"
    set db(2) "Middle"
    set db(3) "Right"
    set db(4) "Fourth"
    set db(5) "Fifth"
    set db(6) "Sixth"
    set db($xDefinedButtons) "Seventh"

    set db($doubleClickB) "LeftDouble"
    set db($modeToggleB) "ModeToggle"
    set db($displayToggleB) "DisplayToggle"
    set db($screenToggleB) "ScreenToggle"
    set db($ignoreButton) "Ignore"
    set db($keystrokeB) "KeyStroke"
    set db($originalButton) "Application Defined"

    for { set i [ expr ($xDefinedButtons + 1) ] } { $i <= $maxNumButtons } { incr i 1 } {
	set db($i) $db($originalButton)
    }

    for { set i [ expr ($maxNumButtons + 1) ] } { $i < $doubleClickB } { incr i 1 } {
	set db($i) $db($ignoreButton)
    }

    set dm(1) "Relative"
    set dm(2) "Absolute"

    set sm(1) "Side Switch Only"
    set sm(2) "Side Switch + Tip"

    set bName(keystroke) 0
    set wName(1) "Feel"
    set wName(2) "Tool Buttons"
    set wName(3) "Tracking"
    set wName(4) "Screen Mapping"
    set wName(5) "Keystrokes"
    set wName(6) "Tablet Controls"

#   Real help will be supported later
#    checkbutton .showHelp -text "Turn Help on" -anchor w \
#	    -variable showHelp -state normal  

    button .exit -text "Exit" -command "exit 0" -padx 40
    
#    grid .showHelp -row 0 -column 2 -sticky nw -padx 30
    grid .exit -row 20 -column 2 -sticky news -padx 20
    grid .workingDev -row 0 -rowspan 25 -column 0 -sticky news -padx 20

    set workingTags [ bindtags .workingDev.list]

    grid columnconfigure . 1 -weight 1
    grid rowconfigure . 7 -weight 5
}

proc CalibrateOnly { numArg argList } {
    global device calibration_sequence_only calibration_with_warning

    set calibration_sequence_only 1
    set device [ lindex $argList 1 ]

    createDeviceList
    createScreenList $device
    if { $numArg == 3 } {
	set calibration_with_warning 1
    }
    Calibration
}

if { $argc > 1 && [lindex $argv 0] == "calibrate" } {
    wm title . "Wacom Control Panel -Calibration"	
    CalibrateOnly $argc $argv
    wm geometry . =350x200+$origin_x+$origin_y
} else {
    wm title . "Wacom Control Panel"
    createControls
    wm geometry . =$windowSize+$origin_x+$origin_y
}

#
# Local Variables:
# mode: tcl
# End:
#
