#!/bin/bash
#\
exec wish -f "$0" ${1+"$@"}
#
# wacomcpl-exec -- Wacom Control Panel Utility to Change Configuration Setting.
#
# Author	: Ping Cheng
# Creation date	: 04/05/2003
#
# Based on calibrate 1998-99 Patrick Lecoanet --
#
# 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 "540x300"

set device ""
set deviceIndex 0
set showHelp 0
set modeToggleB 33
set ignoreButton 34
set doubleClickB 35
set displayToggleB 36
set keystrokeB 37


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 ] } {
	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 calibrationSequence {which xDev yDev} {
    global device calibResults screenY_org screenX_org
    global workingTags screenTags size numScreens
    global swapThresh screenWidth screenHeight
    global getDeviceModel screenXBottom screenYBottom

    set calibResults(xDev,$which) $xDev
    set calibResults(yDev,$which) $yDev
    if { $which == 0 } {
	.topleft.m configure -background "#505075"
	wacomxi::bindevent .topleft.m $device <ButtonRelease> ""
	.bottomright.m configure -background "#df94df"
	wacomxi::bindevent .bottomright.m $device <ButtonRelease> \
		{calibrationSequence 1 %0 %1}
    } elseif { $which == 1 } {
	.bottomright.m configure -background "#505075"
	wacomxi::bindevent .bottomright.m $device <ButtonRelease> ""	
	set borderOffset [expr ($size / 2 )]
	set widthDev [expr $calibResults(xDev,1) - $calibResults(xDev,0)]
 	set heightDev [expr $calibResults(yDev,1) - $calibResults(yDev,0)]
 	set widthX [expr $screenWidth-$size]
 	set heightX [expr $screenHeight-$size]

	#
	# A rough verification of the click
	set clickCheck 0
	set xDevMin $calibResults(xDev,0)
	set xDevMax $calibResults(xDev,1)
	set yDevMin $calibResults(yDev,0)
	set yDevMax $calibResults(yDev,1)
	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 { $clickCheck == 1 } {
	    messageWindow "Warning !!!" \
		"\n\nThere was something unusual in your calibration step.\n\
		If you are pretty sure that you have clicked on the center\n\
		of the pink crosshair, you are fine. Otherwise, try it again."
	}
	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
	set eraser $getDeviceModel($device,eraser)
	if { [ string compare $eraser $device ] } {
	    updateXinitrc $eraser topx $xDevMin
	    updateXinitrc $eraser topy $yDevMin
	    updateXinitrc $eraser bottomx $xDevMax
	    updateXinitrc $eraser bottomy $yDevMax
	}

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

proc Calibration {} {
    global numScreens device screenTags getOption Option

    set Option(1) "Mode"
    getDeviceOptionProc $device 1
    set mode $getOption($device,Mode)
    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
	set screenTags [ bindtags .screen.list.list]
	.screen.list.title configure -text "Select $device associated Screen:"
	wm state .screen normal
    } else {
	updateCurrentScreenInfo
	startCalibration
    }
    disableButtons
}

proc startCalibration {} {
    global device calibResults
    global screenX_org screenY_org size numScreens
    global screenWidth screenHeight screenXBottom screenYBottom
    
    if { $numScreens($device) > 1 } {
	bindtags .screen.list.list .
    }

    set y_coor [ expr $screenYBottom-$size*(abs($screenYBottom)/$screenYBottom) ]
    set x_coor [ expr $screenXBottom-$size*(abs($screenXBottom)/$screenXBottom) ]
    pad .topleft +$screenX_org+$screenY_org
    pad .bottomright +$x_coor+$y_coor
    update
    #
    # Start calib sequence
    catch {unset calibResults}
    exec xsetwacom set $device xydefault
    .topleft.m configure -background "#df94df"
    wacomxi::bindevent .topleft.m $device <ButtonRelease> \
		{calibrationSequence 0 %0 %1}
    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

    if { $numScreens($device) > 1 } {
	set cScreen [ .screen.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
    .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
    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 spName numButton modeToggleB
    global displayToggleB ignoreButton doubleClickB keystrokeB numStrips

    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 <= [ expr ($numButton+$numStrips) ] } { 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 { ($value > $doubleClickB) || ($value == 0) } {
		    if { ![string compare -nocase -length 8 DBLCLICK $value ] } {
			set getOption($dev,$Option($j)) $doubleClickB
		    }
		    if { ![string compare -nocase -length 4 CORE $value ] } {
			set getOption($dev,$Option($j)) $keystrokeB
			set oldKeys($Option($j)) $value
		    }
		    if { ![string compare -nocase -length 10 MODETOGGLE $value ] } {
			set getOption($dev,$Option($j)) $modeToggleB
		    }
		    if { ![string compare -nocase -length 13 DISPLAYTOGGLE $value ] } {
			set getOption($dev,$Option($j)) $displayToggleB
		    }
		    if { $value == 0 } {
			set getOption($dev,$Option($j)) $ignoreButton
		    }
		}
		if { $value == 0 } {
		    set getOptionDefault($dev,$Option($j)) $ignoreButton
		}
	    }
	}
    }
}

proc updateDevice {} {
    global device deviceIndex hasPad isLCD
    global numScreens getDeviceModel 

    set olddev $device
    set device [ .workingDev.list get anchor ]
    set deviceIndex [ .workingDev.list index anchor ]
    if { $device != $olddev && $olddev != ""} {
	#
	# Clear old state related to preceding device
	#
	wacomxi::bindevent . $device <ButtonPress> ""
	wacomxi::bindevent . $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
	if { ![ string compare $type "pad" ] } {
	    if { $hasPad($model) } {
		createPanel 0 1 0 0
	    }
	} else {
	   if { $isLCD($model) } { 
	    	if { ![ string compare $type "stylus" ] } {
		    createPanel 1 1 0 1
		} else {
		    if { [ string compare $type "cursor" ] } {
			createPanel 1 1 0 0
		    } else {
			createPanel 0 0 0 0
		    }
		}
	    } else {
		if { [ string compare $type "cursor" ] } {
		    createPanel 1 1 1 0
		} else {
		    createPanel 0 1 1 0
		}
	    }
	}
    } else {
	#
	# Update the entry indicator
	#
	.workingDev.label configure -text $device
    }
}

proc createDeviceList {} {
    global getDeviceModel

    set infoString [exec xsetwacom list]
    set index 0
    set devices ""
    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} {
	    set getDeviceModel($dev,type) $type
	    set getDeviceModel($dev,model) $model
	    set devices "$devices $dev"
	    set index [ expr $index+1 ]
	}
        set dev [ lindex $infoString $index ]
    }

    frame .workingDev
    label .workingDev.title -text "Select the Device:"
    label .workingDev.label -background gray
    listbox .workingDev.list -width 16 -height 12 \
	    -yscrollcommand ".workingDev.sb set"
    scrollbar .workingDev.sb -width 10 \
	    -command ".workingDev.list yview"
    grid .workingDev.title -row 0 -column 0 -columnspan 3 -sticky we
    grid .workingDev.label -row 1 -column 0 -columnspan 3 -sticky we
    grid .workingDev.list -row 2 -column 0 
    grid .workingDev.sb -row 2 -sticky nse
    set flag 0
    foreach dev $devices {
	.workingDev.list insert end $dev
	createScreenList $dev
	set type $getDeviceModel($dev,type)
	if { ![string compare $type "eraser"] } {
	    set model $getDeviceModel($dev,model)
	    foreach dev1 $devices {
		set type1 $getDeviceModel($dev1,type)
		set model1 $getDeviceModel($dev1,model)
		if { ( $model == $model1 ) 
			&& ![string compare $type1 "stylus"] } {
		    set getDeviceModel($dev1,eraser) $dev
		}
	    }
	}
    }
    bind .workingDev.list <ButtonRelease-1> updateDevice
}

proc createScreenList { dev } {
    global numScreens currentScreen
    global desktopHeight desktopWidth 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 screenTags

    closeTabWindow
    destroy .topleft .bottomright .screen
}

proc displayScreenList { dev } {
    global numScreens currentScreen 

    if {  $numScreens($dev) <= 1  } {
	return
    }
    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

    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
    grid .screen.cancel -row 10
    pack .screen.list .screen.cancel
}

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

    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) ]
	}
	switch [ $currentW.f.$i cget -text ] {
	    "Left"
		{ set j 1 
		  set v "Button 1" }
	    "Middle"
		{ set j 2 
		 set v "Button 2" }
	    "Right"
		{ set j 3 
		 set v "Button 3" }
	    "Fourth"
		{ set j 4 
		 set v "Button 4" }
	    "Fifth"
		{ set j 5 
		 set v "Button 5" }
	    "Left Double"
		{ set j $doubleClickB
		 set v "DBLCLICK 1" }
	    "Mode Toggle"
		{ set j $modeToggleB
		 set v "ModeToggle 1" }
	    "Display Toggle"
		{ set j $displayToggleB
		 set v "DisplayToggle 1" }
	    "KeyStroke"
		{ set j $keystrokeB 
		 set v $cKeys($spName($k)) 
		 set oldKeys($spName($k)) $cKeys($spName($k)) }
	    "Ignore"
		{ set j $ignoreButton
		 set v "Button 0" }
	}
	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 db1 db2 db3 db4 db5 db6 db7 db8 db9 db10
    global db11 db12 db13 db14 isLCD spName
    global dm sm dmv smv numButton startS numStrips
    global device getOptionDefault getDeviceModel

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

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

    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 numStrips startS device Option cKeys oldKeys
    global numPadRelW numPadStrips numPadRings getDeviceModel

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

    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"

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

    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]

    # initial keys
    for { set i 1 } { $i <= [ expr ($numButton + 8) ] } { incr i 1 } {
	set oldKeys($spName($i)) ""
	set cKeys($spName($i)) ""
    }
}

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
    }

    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

    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
    if { $deF != 0 } {
	button $currentW.f.default -text "Default" -command $deF
	grid $currentW.f.default -row 8 -column 0 -columnspan 3 -padx 10 -pady 10
	#
	# Suppress tags on listboxes to prevent changing the
	# device and disable other controls
	bindtags .workingDev.list .
	set columnN 4
    }

    disableButtons
    $initial

    grid $currentW.f -row 0 -column 0 -sticky nw
    grid $currentW.f.ok -row 8 -column [expr ($columnN + 4)] -columnspan 3 -padx 10 -pady 10
    grid $currentW.f.cancel -row 8 -column $columnN -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 db1 db2 db3 db4 db5 db6 db7 db8 db9 db10
    global db11 db12 db13 db14 startS
    global currentW device numButton spName numStrips
    global Option getOption getDeviceModel cKeys oldKeys 
    global displayToggleB ignoreButton keystrokeB
    global numPadRings numPadStrips numPadAbsW numPadRelW

    set name(1) "Wheel Up"
    set name(2) "Wheel Down"
    set name(3) "Ring Clockwise"
    set name(4) "Ring Anticlockwise"
    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 cur [ expr ($numButton + $i - $startS + 1) ]
	set opt $getOption($device,$Option($i))
	if { $opt == "" } { set opt $ignoreButton }

	set curOption [ expr ($numButton + $i) ]
	set db$cur $db($opt) 
	#reset keys
	if { $opt != $keystrokeB } {
	    set cKeys($Option($i)) ""
	    set oldKeys($Option($i)) ""
	}
	set bmenu [ tk_optionMenu $currentW.f.$cur db$cur $db(1) $db(2) \
	    $db(3) $db(4) $db(5) $db($displayToggleB) $db($ignoreButton) ]
	$bmenu insert 8 radiobutton -label "$db($keystrokeB)" \
	    -variable menvar -command "displaySubWindow \
	    updateKeys 0 initialKeys 5 $cur $curOption"

	label $currentW.f.name$cur -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.$cur -row $t2 -column [expr $t1+1] 
	grid $currentW.f.name$cur -row $t2 -column $t1
    }
}

proc addMenu { curb } {
    global db db1 db2 db3 db4 db5 db6 db7 db8 db9 db10 
    global db11 db12 db13 db14 currentW 
    global getOption getDeviceModel cKeys oldKeys device spName
    global doubleClickB displayToggleB ignoreButton modeToggleB keystrokeB

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

    set opt $getOption($device,$spName($curb))
    if { $opt == "" } { set opt $curb }
    if { ![string compare $type "pad"] } { 
	# values 30 or larger are special functions
	if { ($opt > 8 && $opt < 30) } {
	    set opt [ expr ($opt-8) ] 
	}
    }
    set db$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 db$curb $db(1) $db(2) \
		$db(3) $db(4) $db(5) $db($doubleClickB) $db($modeToggleB) \
		$db($displayToggleB) $db($ignoreButton) ]
	set i 9
    } else {
	set bmenu [ tk_optionMenu $currentW.f.$curb db$curb $db(1) $db(2) \
		$db(3) $db(4) $db(5) $db($displayToggleB) $db($ignoreButton) ]
	set i 7
    }

    set i [expr ($i+1)]
    $bmenu insert $i radiobutton -label "$db($keystrokeB)" \
	-variable menvar -command "displaySubWindow \
	updateKeys 0 initialKeys 5 $curb $curb"

    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 tvd snd currentW

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

    set numS [ exec xsetwacom get $device NumScreen ]
    set tvID [ exec xsetwacom get $device TwinView ]
    set snd [ exec xsetwacom get $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 3 -column 0 
    grid $currentW.f.snsmenu -row 3 -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 tv(0) "None"
    set tv(1) "Vertical"
    set tv(2) "Horizontal"
    for { set i 0 } { $i < 3 } { incr i 1 } {
	if { $tvID == $i } {
	    set tvd $tv($i)
	}
    }

    tk_optionMenu $currentW.f.tvmenu tvd $tv(0) $tv(1) $tv(2) 
    grid $currentW.f.tv -row 2 -column 0 
    grid $currentW.f.tvmenu -row 2 -column 1

    $currentW.f.tvmenu configure -state normal
    if { $numS == 1 } {
	label $currentW.f.message1 -text "Please click on \"Cancel\" "
	label $currentW.f.message2 -text "if your X server isn't in TwinView setup." 
	grid $currentW.f.message1 -row 0 -column 0
	grid $currentW.f.message2 -row 0 -column 1
    } elseif { !$tvID } {
	$currentW.f.tvmenu configure -state disable
    }
}

proc updateSet {} {
    global device currentW tvd snd

    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 tv [ $currentW.f.tvmenu cget -text ]
    if { ![ string compare $tv "None" ] } {
	set tv 0
    }
    if { ![ string compare $tv "Horizontal" ] } {
	set tv 2
    }
    if { ![ string compare $tv "Vertical" ] } {
	set tv 1
    }

    set tvID [ exec xsetwacom get $device TwinView ]
    if { $tv != $tvID } {
	updateXinitrc $device TwinView $tv
	set getOption($device,TwinView) $tv
    }

    closeSubWindow
}

proc defaultSet {} {
    global tvd snd

    set tvd "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))
	}
    }
    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) "PgUp"
    set sk(5) "PgDn"
    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 " " }
    }
    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
    global db db1 db2 db3 db4 db5 db6 db7 db8 db9 db10
    global db11 db12 db13 db14 currentk
    global ignoreButton keystrokeB

    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 { $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
	    }
	    set getOption($device,$spName($currentk)) $keystrokeB
	    set db$currentb $db($keystrokeB)
	}
    } else {  # ignore the button
	set getOption($device,$spName($currentk)) $ignoreButton
	set db$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 createPanel { pressure button mapping calibrate } {
    global bName device getOption getDeviceModel currentb 
    global wName startS Option

    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.sn -text "Serial Number: $hexSN"
	grid .panel.sn -row 0 -column 0 -columnspan 2 -padx 3 -pady 3
    }

    if { $pressure } {
	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) "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
    }
    if { $calibrate } {
	button .panel.calibrate -text "Calibration" \
	    -command Calibration -state normal
	grid .panel.calibrate -row 5 -column 3 -columnspan 2 -sticky news -padx 10
    }

    set bName(advanced) 0
    if { [string compare $getDeviceModel($device,type) "pad"] } { #not a pad
	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
    global numPadStrips numPadAbsW numPadRelW

    for { set i 0 } { $i <= 198 } { 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
    }
    #PL
    for { set i 48} { $i <= 63 } { incr i 1 } {
	set isLCD($i) 1 
    }
    #TabletPC
    for { set i 144 } { $i <= 151 } { incr i 1 } {
	set isLCD($i) 1 
    }
    #Cintiq
    for { set i 192 } { $i <= 198 } { 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
   }
    # 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

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

proc createControls { } {
    global numScreens currentScreen cKeys spName
    global desktopHeight desktopWidth oldKeys numStrips
    global workingTags db dm sm wName bName numButton
    global doubleClickB ignoreButton displayToggleB 
    global modeToggleB keystrokeB

    createDeviceList 
    updateModelInfo

    set db(1) "Left"
    set db(2) "Middle"
    set db(3) "Right"
    set db(4) "Fourth"
    set db(5) "Fifth"
    set db(6) "Ignore"
    set db(7) "Ignore"
    set db(8) "Ignore"
    set db(9) "Ignore"
    set db(10) "Ignore"
    set db($doubleClickB) "Left Double"
    set db($modeToggleB) "Mode Toggle"
    set db($displayToggleB) "Display Toggle"
    set db($ignoreButton) "Ignore"
    set db($keystrokeB) "KeyStroke"
    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"

    # up to the max number of buttons
    set numButton 10
    set numStrips 4
#    setspName

    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
}

createControls

wm title . "Wacom Control Panel"
wm geometry . =$windowSize+$origin_x+$origin_y

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