<commit_before>#!/bin/sh
# the next line restarts using emcsh \
exec ${EMC2_EMCSH-emcsh} "$0" "$@"

###############################################################
# Description:  tkemc
#               A Tcl/Tk GUI script that defines default  
#               emc interface functionality. 
#
#  Derived from a work by <NAME> & <NAME>
#  Author: 
#  License: GPL Version 2
#
#  Copyright (c) 2006-2009 All rights reserved.
###############################################################
# Uses the emcsh library of tcl/tk functions.
# Provides default display or operators for each NML message
###############################################################

# Load the emc.tcl file, which defines variables for various useful paths
source [file join [file dirname [info script]] emc.tcl]

# Tk GUI for the Enhanced Machine Controller

# Notes

# 1. Widget focus. Keyboard traversal with TAB sets the focus to some of the
# widgets. When they're focused, arrow keys and numbers don't work. To fix
# this, most widgets that would get focus have the focus disabled with
# -takefocus 0. A few remain; these are added to the widgets that bindtags
# applies to when switching between ManualBindings, AutoBindings

# 2. Adds tkbackplot and scripts to menu.
# 3. Adds info to help menu that calls tcl.sysinfo.tcl and uses emc/emcversion

# Set global that signifies we're the tkemc, so that other sourced scripts
# can know how to pack themselves. This lets these scripts pack into the
# main window "." if "tkemc" is not defined, or in their own top-level window
# if "tkemc" is defined. emclog.tcl looks at this.
set tkemc 1

# Internationalisation (i18n)
# in order to use i18n, all the strings will be called [msgcat::mc "string-foo"]
# instead of "string-foo".
# Thus msgcat searches for a translation of the string, and in case one isn't 
# found, the original string is used.
# In order to properly use locale's the env variable LANG is queried.
# If LANG is defined, then the folder src/po is searched for files
# called *.msg, (e.g. en_US.msg).
package require msgcat
if ([info exists env(LANG)]) {
    msgcat::mclocale $env(LANG)
    msgcat::mcload $emc::LANG_DIR
}

# read the application defaults
set TKEMCCONF $emc::TCL_DIR/TkEmc
if {[file exists $TKEMCCONF]} {
    option readfile $TKEMCCONF startupFile
}
foreach f {TkEmc /usr/X11R6/lib/X11/app-defaults/TkEmc /etc/X11/app-defaults/TkEmc} {
    if {[file exists $f]} {
	option readfile $f
	break
    }
}

# test for windows flag
set windows 0

foreach arg $argv {
    if { $arg == "-win" } {
	set windows 1
    }
}

# Read the ini file to determine what the axes and coordinates are.

set worldlabellist ""
set axiscoordmap ""
set numaxes [emc_ini "AXES" "TRAJ"]
set coordnames [ emc_ini "COORDINATES" "TRAJ"]

set numcoords 0

if { [ string first "X" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist X]
    set axiscoordmap [ concat $axiscoordmap 0  ]
}

if { [ string first "Y" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist Y]
    set axiscoordmap [ concat $axiscoordmap  1 ]
}

if { [ string first "Z" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist Z]
    set axiscoordmap [ concat $axiscoordmap  2 ]
}


if { [ string first "A" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist A]
    set axiscoordmap [ concat $axiscoordmap  3 ]
}

if { [ string first "B" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist B]
    set axiscoordmap [ concat $axiscoordmap  4 ]
}

if { [ string first "C" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist C]
    set axiscoordmap [ concat $axiscoordmap  5 ]
}

if { [ string first "U" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist U]
    set axiscoordmap [ concat $axiscoordmap  6 ]
}

if { [ string first "V" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist V]
    set axiscoordmap [ concat $axiscoordmap  7 ]
}

if { [ string first "W" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist W]
    set axiscoordmap [ concat $axiscoordmap  8 ]
}

set worldlabellist [ concat $worldlabellist "-" "-" "-" "-" "-" "-" "-" "-" "-" ]
set axiscoordmap [ concat $axiscoordmap 0 0 0 0 0 0 0 0 0]
set worldlabel0 [lindex  $worldlabellist 0 ]
set worldlabel1 [lindex  $worldlabellist 1 ]
set worldlabel2 [lindex  $worldlabellist 2 ]
set worldlabel3 [lindex  $worldlabellist 3 ]
set worldlabel4 [lindex  $worldlabellist 4 ]
set worldlabel5 [lindex  $worldlabellist 5 ]
set worldlabel6 [lindex  $worldlabellist 6 ]
set worldlabel7 [lindex  $worldlabellist 7 ]
set worldlabel8 [lindex  $worldlabellist 8 ]

set jointlabel0 "0"
set jointlabel1 "1"
set jointlabel2 "2"
set jointlabel3 "3"
set jointlabel4 "4"
set jointlabel5 "5"
set jointlabel6 "6"
set jointlabel7 "7"
set jointlabel8 "8"

# set the cycle time for display updating
set temp [emc_ini "CYCLE_TIME" "DISPLAY"]
if {[string length $temp] == 0} {
    set temp 0.200
}
set displayCycleTime [expr {int($temp * 1000 + 0.5)}]
set syncDelayTime    $displayCycleTime ;#increasing improves slider behavior

# set the debounce time for key repeats
set debounceTime 150

if { $windows == 0 } {
    # load the generic editor "startEditor <name>"
    source $emc::TCL_BIN_DIR/genedit.tcl

    # load the EMC calibrator
#    source $emc::TCL_BIN_DIR/emccalib.tcl

    # load the EMC data logger
#    source $emc::TCL_BIN_DIR/emclog.tcl

    # load the EMC performance tester
    source $emc::TCL_BIN_DIR/emctesting.tcl

    # load the EMC debug level setter
    source $emc::TCL_BIN_DIR/emcdebug.tcl

    # load the backplotter
    source $emc::TCL_BIN_DIR/tkbackplot.tcl

    # load balloon help
    source $emc::TCL_SCRIPT_DIR/balloon.tcl
    source $emc::TCL_SCRIPT_DIR/emchelp.tcl
    set do_balloons [emc_ini "BALLOON_HELP" "DISPLAY"]
    if {$do_balloons == ""} {
        set do_balloons 0
    }
}

# the line from which to run the program; 0 or 1 means from start
set runMark 0
proc popupRunMark {mark} {
    global runMark
    catch {destroy .runmark}
    toplevel .runmark
    wm title .runmark [msgcat::mc "Set Run Mark"]
    label .runmark.msg -font {Helvetica 12 bold} -wraplength 4i -justify left \
        -text [msgcat::mc "Set run mark at line %s?" $mark]
    pack .runmark.msg -side top
    frame .runmark.buttons
    pack .runmark.buttons -side bottom -fill x -pady 2m
    button .runmark.buttons.ok -text [msgcat::mc "OK"] -default active \
        -command "set runMark $mark; destroy .runmark"
    button .runmark.buttons.cancel -text [msgcat::mc "Cancel"] \
        -command "destroy .runmark"
    pack .runmark.buttons.ok .runmark.buttons.cancel -side left -expand 1
    bind .runmark <Return> "set runMark $mark; destroy .runmark"
}

# pop up the program editor
proc popupProgramEditor {} {
    global programnamestring

    # create an editor as top-level ".programEditor"
    if {[file isfile $programnamestring]} {
        geneditStart programEditor $programnamestring
    } else {
        geneditStart programEditor [msgcat::mc "untitled"].ngc
    }

    frame .programEditor.buttons
    pack .programEditor.buttons -side bottom -fill x -pady 2m
    button .programEditor.buttons.mark -text [msgcat::mc "Set Run Mark"] -command \
        {popupRunMark [int [.programEditor.textframe.textwin index insert]]}
    pack .programEditor.buttons.mark -side left -expand 1
}

set toolfilename [emc_ini "TOOL_TABLE" "EMCIO"]
if {[string length $toolfilename] == 0} {
    set toolfilename "emc.tbl"
}

# pop up the tool table editor
proc popupToolEditor {} {
    global toolfilename

    # create an editor as top-level ".toolEditor"
    if {[file isfile $toolfilename]} {
        geneditStart toolEditor $toolfilename
    } else {
        geneditStart toolEditor [msgcat::mc "untitled"].tbl
    }

    frame .toolEditor.buttons
    pack .toolEditor.buttons -side bottom -fill x -pady 2m
    button .toolEditor.buttons.load -text [msgcat::mc "Load Tool Table"] -command {geneditSaveFile toolEditor; emc_load_tool_table $toolfilename}
    button .toolEditor.buttons.cancel -text [msgcat::mc "Cancel"] -default active -command {destroy .toolEditor}
    pack .toolEditor.buttons.load .toolEditor.buttons.cancel -side left -expand 1
}

set paramfilename [emc_ini "PARAMETER_FILE" "RS274NGC"]
if {[string length $paramfilename] == 0} {
    set paramfilename "emc.var"
}

# pop up the parameter file editor
proc popupParamEditor {} {
    global paramfilename

    # create an editor as top-level ".paramEditor"
    if {[file isfile $paramfilename]} {
        geneditStart paramEditor $paramfilename
    } else {
        geneditStart paramEditor [msgcat::mc "untitled"].var
    }

    # disable "Save As..." menu, since we don't support changing it
    .paramEditor.menubar.file entryconfigure 3 -state disabled

    frame .paramEditor.buttons
    pack .paramEditor.buttons -side bottom -fill x -pady 2m
    button .paramEditor.buttons.load -text [msgcat::mc "Load Parameter File"] -command {geneditSaveFile paramEditor; emc_task_plan_init}
    button .paramEditor.buttons.cancel -text [msgcat::mc "Cancel"] -default active -command {destroy .paramEditor}
    pack .paramEditor.buttons.load .paramEditor.buttons.cancel -side left -expand 1
}

set helpfilename [emc_ini "HELP_FILE" "DISPLAY"]
if {[string length $helpfilename] == 0} {
    set helpfilename "tkemc.txt"
}

# pop up the help window
proc popupHelp {} {
    global helpfilename
    global HELPDIR

    # create an editor as top-level ".help"
    if {[file isfile $emc::HELP_DIR/$helpfilename]} {
        geneditStart help $emc::HELP_DIR/$helpfilename
    } else {
        geneditStart help $emc::HELP_DIR/tkemc.txt
    }

    # disable menu entries that don't apply to read-only text
    .help.menubar.file entryconfigure 0 -state disabled
    .help.menubar.file entryconfigure 1 -state disabled
    .help.menubar.file entryconfigure 2 -state disabled
    .help.menubar.file entryconfigure 3 -state disabled
    .help.menubar.edit entryconfigure 0 -state disabled
    .help.menubar.edit entryconfigure 2 -state disabled
    .help.textframe.textwin configure -state disabled

    frame .help.buttons
    pack .help.buttons -side bottom -fill x -pady 2m
    button .help.buttons.ok -text [msgcat::mc "OK"] -default active -command {destroy .help}
    pack .help.buttons.ok -side left -expand 1
    bind .help <Return> {destroy .help}
}

# pop up the diagnostics window
proc popupDiagnostics {} {
    set d .diagnostics

    if {[winfo exists $d]} {
        wm deiconify $d
        raise $d
        focus $d
        return
    }
    toplevel $d
    wm title $d [msgcat::mc "EMC Diagnostics"]

    label $d.task -text [msgcat::mc "Task"] -width 30 -anchor center
    frame $d.taskhb
    label $d.taskhb.lab -text [msgcat::mc "Heartbeat:"] -anchor w
    label $d.taskhb.val -textvariable taskhb -anchor e
    frame $d.taskcmd
    label $d.taskcmd.lab -text [msgcat::mc "Command:"] -anchor w
    label $d.taskcmd.val -textvariable taskcmd -anchor e
    frame $d.tasknum
    label $d.tasknum.lab -text [msgcat::mc "Command #:"] -anchor w
    label $d.tasknum.val -textvariable tasknum -anchor e
    frame $d.taskstatus
    label $d.taskstatus.lab -text [msgcat::mc "Status:"] -anchor w
    label $d.taskstatus.val -textvariable taskstatus -anchor e
    pack $d.task $d.taskhb $d.taskcmd $d.tasknum $d.taskstatus -side top -fill x
    pack $d.taskhb.lab -side left
    pack $d.taskhb.val -side right
    pack $d.taskcmd.lab -side left
    pack $d.taskcmd.val -side right
    pack $d.tasknum.lab -side left
    pack $d.tasknum.val -side right
    pack $d.taskstatus.lab -side left
    pack $d.taskstatus.val -side right

    label $d.io -text [msgcat::mc "Io"] -width 30 -anchor center
    frame $d.iohb
    label $d.iohb.lab -text [msgcat::mc "Heartbeat:"] -anchor w
    label $d.iohb.val -textvariable iohb -anchor e
    frame $d.iocmd
    label $d.iocmd.lab -text [msgcat::mc "Command:"] -anchor w
    label $d.iocmd.val -textvariable iocmd -anchor e
    frame $d.ionum
    label $d.ionum.lab -text [msgcat::mc "Command #:"] -anchor w
    label $d.ionum.val -textvariable ionum -anchor e
    frame $d.iostatus
    label $d.iostatus.lab -text [msgcat::mc "Status:"] -anchor w
    label $d.iostatus.val -textvariable iostatus -anchor e
    pack $d.io $d.iohb $d.iocmd $d.ionum $d.iostatus -side top -fill x
    pack $d.iohb.lab -side left
    pack $d.iohb.val -side right
    pack $d.iocmd.lab -side left
    pack $d.iocmd.val -side right
    pack $d.ionum.lab -side left
    pack $d.ionum.val -side right
    pack $d.iostatus.lab -side left
    pack $d.iostatus.val -side right

    label $d.motion -text [msgcat::mc "Motion"] -width 30 -anchor center
    frame $d.motionhb
    label $d.motionhb.lab -text [msgcat::mc "Heartbeat:"] -anchor w
    label $d.motionhb.val -textvariable motionhb -anchor e
    frame $d.motioncmd
    label $d.motioncmd.lab -text [msgcat::mc "Command:"] -anchor w
    label $d.motioncmd.val -textvariable motioncmd -anchor e
    frame $d.motionnum
    label $d.motionnum.lab -text [msgcat::mc "Command #:"] -anchor w
    label $d.motionnum.val -textvariable motionnum -anchor e
    frame $d.motionstatus
    label $d.motionstatus.lab -text [msgcat::mc "Status:"] -anchor w
    label $d.motionstatus.val -textvariable motionstatus -anchor e
    pack $d.motion $d.motionhb $d.motioncmd $d.motionnum $d.motionstatus -side top -fill x
    pack $d.motionhb.lab -side left
    pack $d.motionhb.val -side right
    pack $d.motioncmd.lab -side left
    pack $d.motioncmd.val -side right
    pack $d.motionnum.lab -side left
    pack $d.motionnum.val -side right
    pack $d.motionstatus.lab -side left
    pack $d.motionstatus.val -side right

    frame $d.buttons
    button $d.buttons.ok -text OK -default active -command "destroy $d"

    pack $d.buttons -side bottom -fill x -pady 2m
    pack $d.buttons.ok -side left -expand 1
    bind $d <Return> "destroy $d"
}

# pop up the about box
proc popupAbout {} {
    global env
    if {[winfo exists .about]} {
        wm deiconify .about
        raise .about
        focus .about
        return
    }
    toplevel .about
    wm title .about [msgcat::mc "About TkEmc"]
    message .about.msg -aspect 1000 -justify center -font {Helvetica 12 bold} -text [ format "%s\n(EMC2 %s)" [msgcat::mc "TkEmc\n\nTcl/Tk GUI for Enhanced Machine Controller version 2 (EMC2)\n\nGPL Version 2 (2006)"] $env(EMC2VERSION) ]
    frame .about.buttons
    button .about.buttons.ok -default active -text OK -command "destroy .about"
    pack .about.msg -side top
    pack .about.buttons -side bottom -fill x -pady 2m
    pack .about.buttons.ok -side left -expand 1
    bind .about <Return> "destroy .about"
}

proc popupToolOffset {} {
    global toolsetting tooloffsetsetting
    global toolentry toollengthentry tooldiameterentry

    if {[winfo exists .tooloffset]} {
        wm deiconify .tooloffset
        raise .tooloffset
        focus .tooloffset
        return
    }
    toplevel .tooloffset
    wm title .tooloffset [msgcat::mc "Set Tool Offset"]

    # pre-load the entries with values
    set toolentry $toolsetting
    set toollengthentry $tooloffsetsetting
    set tooldiameterentry 0.0 ; # no value provided by controller

    frame .tooloffset.tool
    label .tooloffset.tool.label -text [msgcat::mc "Tool:"] -anchor w -width 15
    entry .tooloffset.tool.entry -textvariable toolentry -width 20

    frame .tooloffset.length
    label .tooloffset.length.label -text [msgcat::mc "Length:"] -anchor w -width 15
    entry .tooloffset.length.entry -textvariable toollengthentry -width 20

    frame .tooloffset.diameter
    label .tooloffset.diameter.label -text [msgcat::mc "Diameter:"] -anchor w -width 15
    entry .tooloffset.diameter.entry -textvariable tooldiameterentry -width 20

    frame .tooloffset.buttons
    button .tooloffset.buttons.ok -text [msgcat::mc "OK"] -default active -command {emc_set_tool_offset $toolentry $toollengthentry $tooldiameterentry; destroy .tooloffset}
    button .tooloffset.buttons.cancel -text [msgcat::mc "Cancel"] -command {destroy .tooloffset}

    pack .tooloffset.tool -side top
    pack .tooloffset.tool.label .tooloffset.tool.entry -side left
    pack .tooloffset.length -side top
    pack .tooloffset.length.label .tooloffset.length.entry -side left
    pack .tooloffset.diameter -side top
    pack .tooloffset.diameter.label .tooloffset.diameter.entry -side left

    pack .tooloffset.buttons -side bottom -fill x -pady 2m
    pack .tooloffset.buttons.ok .tooloffset.buttons.cancel -side left -expand 1
    bind .tooloffset <Return> {emc_set_tool_offset $toolentry $toollengthentry $tooldiameterentry; destroy .tooloffset}

    focus .tooloffset.length.entry
    .tooloffset.length.entry select range 0 end
}

# set waiting on EMC to wait until command is received, not finished, with
# timeout of 10 seconds
emc_set_timeout 1.0
emc_set_wait received

# force an update
emc_update

set modifier Alt
set modifierstring "Alt"

set programDirectory [emc_ini "PROGRAM_PREFIX" "DISPLAY"]

# process to load the program text display widget
proc loadProgramText {} {
    global programnamestring programfiletext
    # clear out program text
    $programfiletext config -state normal
    $programfiletext delete 1.0 end
    # close the current program
    catch {close $programin}
    # open the new program, if it's not "none"
    if {[catch {open $programnamestring} programin]} {
        puts stdout [msgcat::mc "can't open %s" $programnamestring]
    } else {
        $programfiletext insert end [read $programin]
        $programfiletext config -state disabled
        catch {close $programin}
    }
}

# set initial value for program status comparison
set oldstatusstring "idle"

proc fileDialog {} {
    global programDirectory
    global programnamestring
    set allfilestring [msgcat::mc "All files"]
    set textfilestring [msgcat::mc "Text files"]
    set ncfilestring [msgcat::mc "NC files"]

    set all [list ]
    lappend all $allfilestring
    lappend all *
    set text [list ]
    lappend text $textfilestring
    lappend text ".txt"
    set nc [list ]
    lappend nc $ncfilestring
    lappend nc ".nc .ngc"
    
    set types [list ]
    lappend types $all
    lappend types $text 
    lappend types $nc
    
    set f [tk_getOpenFile -filetypes $types -initialdir $programDirectory]
    if {[string len $f] > 0} {
        set programDirectory [file dirname $f]
        set programnamestring $f
        emc_mode auto
        emc_abort
        emc_open $programnamestring
        loadProgramText
    }
}

proc toggleEstop {} {
    if {[emc_estop] == "on"} {
        emc_estop off
    } else {
        emc_estop on
    }
}

proc toggleMachine {} {
    if {[emc_machine] == "off"} {
        emc_machine on
    } else {
        emc_machine off
    }
}

proc toggleMist {} {
    if {[emc_mist] == "off"} {
        emc_mist on
    } else {
        emc_mist off
    }
}

proc toggleFlood {} {
    if {[emc_flood] == "off"} {
        emc_flood on
    } else {
        emc_flood off
    }
}

proc toggleSpindleForward {} {
    if {[emc_spindle] == "off"} {
        emc_spindle forward
    } else {
        emc_spindle off
    }
}

proc toggleSpindleReverse {} {
    if {[emc_spindle] == "off"} {
        emc_spindle reverse
    } else {
        emc_spindle off
    }
}

# coords can be relative or machine
set temp [emc_ini "POSITION_OFFSET" "DISPLAY"]
if {$temp == "RELATIVE"} {
    set coords relative
} elseif {$temp == "MACHINE"} {
    set coords machine
} else {
    # not found, or invalid, so set to relative
    set coords relative
}

# actcmd can be actual or commanded
set temp [emc_ini "POSITION_FEEDBACK" "DISPLAY"]
if {$temp == "ACTUAL"} {
    set actcmd actual
} elseif {$temp == "COMMANDED"} {
    set actcmd commanded
} else {
    # not found, or invalid, so set to actual
    set actcmd actual
}

proc toggleRelAbs {} {
    global coords
    if {$coords == "relative"} {
        set coords machine
    } else {
        set coords relative
    }
}

proc toggleCmdAct {} {
    global actcmd
    if {$actcmd == "actual"} {
        set actcmd commanded
    } else {
        set actcmd actual
    }
}

set jointworld "joint"

proc toggleJointWorld {} {
    global jointworld
    if {$jointworld == "joint"} {
        set jointworld world
    } else {
        set jointworld joint
    }
}

proc toggleJogType {} {
    global jogLabel jogType jogIncrement

    if {$jogType == "continuous"} {
        set jogType $jogIncrement
	set jogLabel $jogIncrement
    } else {
        set jogType continuous
	set jogLabel [msgcat::mc "continuous"]
    }
}

proc toggleJogIncrement {} {
    global jogLabel jogType jogIncrement

    if {$jogType == "continuous"} {
        set jogType $jogIncrement
	set jogLabel $jogIncrement
    } else {
        if {$jogIncrement == "0.0001"} {
            set jogIncrement 0.0010
        } elseif {$jogIncrement == "0.0010"} {
            set jogIncrement 0.0100
        } elseif {$jogIncrement == "0.0100"} {
            set jogIncrement 0.1000
        } elseif {$jogIncrement == "0.1000"} {
            set jogIncrement 1.0000
        } elseif {$jogIncrement == "1.0000"} {
            set jogIncrement 0.0001
        }
        set jogType $jogIncrement
	set jogLabel $jogIncrement
    }
}

# given axis, determines speed and cont v. incr and jogs it neg
proc jogNeg {axis} {
    global activeAxis jogType jogIncrement axiscoordmap

    set activeAxis $axis

    if { [emc_teleop_enable] == 1 } {
	set axisToJog [ lindex $axiscoordmap $axis ]
    } else {
	set axisToJog $axis
    }
    switch $::jogAxisType($axisToJog) {
      linear  {set speed $::linearJogSpeed}
      angular {set speed $::angularJogSpeed}
    }
    if {$jogType == "continuous"} {
        emc_jog $axisToJog -$speed
    } else {
        emc_jog_incr $axisToJog -$speed $jogIncrement
    }
}

# given axis, determines speed and cont v. incr and jogs it pos
proc jogPos {axis} {
    global activeAxis jogType jogIncrement axiscoordmap

    set activeAxis $axis
    
    if { [emc_teleop_enable] == 1 } {
	set axisToJog [ lindex $axiscoordmap $axis ]
    } else {
	set axisToJog $axis
    }
    switch $::jogAxisType($axisToJog) {
      linear  {set speed $::linearJogSpeed}
      angular {set speed $::angularJogSpeed}
    }

    if {$jogType == "continuous"} {
        emc_jog $axisToJog $speed
    } else {
        emc_jog_incr $axisToJog $speed $jogIncrement
    }
}

# stops the active axis
proc jogStop {axis} {
    global jogType
    #removed globalAxis, as that caused the problems with multiple jogs

    # only stop continuous jogs; let incremental jogs finish
    if {$jogType == "continuous"} {
        emc_jog_stop $axis
    }
}

# toggles the limit override state
proc toggleLimitOverride {} {
    if {[emc_override_limit]} {
        emc_override_limit 0
    } else {
        emc_override_limit 1
    }
}

# toggles the optional stop
proc toggleOptionalStop {} {
    if {[emc_optional_stop]} {
        emc_optional_stop 0
    } else {
        emc_optional_stop 1
    }
}


# use the top-level window as our top-level window, and name it
wm title . "TkEMC"

# create the main window top frame
set top [frame .top]
pack $top -side top -fill both -expand true

# build the top menu bar
set menubar [menu $top.menubar -tearoff 0]

# add the File menu
set filemenu [menu $menubar.file -tearoff 0]
$menubar add cascade -label [msgcat::mc "File"] -menu $filemenu -underline 0
$filemenu add command -label [msgcat::mc "Open..."] -command {fileDialog} -underline 0
bind . <$modifier-o> {fileDialog}
$filemenu add command -label [msgcat::mc "Edit..."] -command {popupProgramEditor} -underline 0
$filemenu add command -label [msgcat::mc "Reset"] -command {emc_task_plan_init} -underline 0
$filemenu add separator
$filemenu add command -label [msgcat::mc "Exit"] -command {after cancel updateStatus ; destroy . ; exit} -accelerator $modifierstring+X -underline 1
bind . <$modifier-x> {after cancel updateStatus ; destroy . ; exit}

# add the View menu
set viewmenu [menu $menubar.view -tearoff 0]
$menubar add cascade -label [msgcat::mc "View"] -menu $viewmenu -underline 0
$viewmenu add command -label [msgcat::mc "Tools..."] -command {popupToolEditor} -underline 0
$viewmenu add command -label [msgcat::mc "Offsets and Variables..."] -command {popupParamEditor} -underline 0
$viewmenu add command -label [msgcat::mc "Diagnostics..."] -command {popupDiagnostics} -underline 0
$viewmenu add command -label [msgcat::mc "Backplot..."] -command {popupPlot} -underline 0

# add the Settings menu
set settingsmenu [menu $menubar.settings -tearoff 0]
$menubar add cascade -label [msgcat::mc "Settings"] -menu $settingsmenu -underline 0
$settingsmenu add command -label [msgcat::mc "Calibration..."] -command "exec $emc::TCL_BIN_DIR/emccalib.tcl -- -ini $EMC_INIFILE &"
$settingsmenu add command -label [msgcat::mc "Testing..."] -command {popupTesting} -underline 0 -state disabled
$settingsmenu add command -label [msgcat::mc "Debug..."] -command {popupDebug} -underline 0
$settingsmenu add command -label [msgcat::mc "Font..."] -command {popupFont} -underline 0

# add the Units menu
set unitsmenu [menu $menubar.units -tearoff 0]
$menubar add cascade -label [msgcat::mc "Units"] -menu $unitsmenu -underline 0
$unitsmenu add command -label [msgcat::mc "auto"] -command {emc_linear_unit_conversion auto} -underline 0
$unitsmenu add command -label [msgcat::mc "inches"] -command {emc_linear_unit_conversion inch} -underline 0
$unitsmenu add command -label [msgcat::mc "mm"] -command {emc_linear_unit_conversion mm} -underline 0
$unitsmenu add command -label [msgcat::mc "cm"] -command {emc_linear_unit_conversion cm} -underline 0

# add the Utilities menu
set utilsmenu [menu $menubar.utils -tearoff 1]
$menubar add cascade -label [msgcat::mc "Utilities"] -menu $utilsmenu -underline 1
$utilsmenu add command -label [msgcat::mc "Hal Scope"] -command {exec halscope -- -ini $EMC_INIFILE &}
$utilsmenu add command -label [msgcat::mc "Hal Meter"] -command {exec halmeter &}

# Add a scripts menu that looks for *.tcl files in tcl/scripts subdirectory
set scriptsmenu [menu $menubar.scripts -tearoff 1]
$menubar add cascade -label [msgcat::mc "Scripts"] -menu $scriptsmenu -underline 1

if { $windows == 0 } {
    set files [exec /bin/ls $emc::TCL_SCRIPT_DIR]
    foreach file $files {
	if {[string match *.tcl $file]} {
	    set fname [file rootname $file]
	    # if it's executable, arrange for direct execution
	    if {[file executable $emc::TCL_SCRIPT_DIR/$file]} {
		$scriptsmenu add command -label $fname -command "exec $emc::TCL_SCRIPT_DIR/$file -- -ini $EMC_INIFILE &"
	    }
	}
    }
}

# add halconfig, to help for HAL setup, it's under Scripts, but it's in the TCL_BIN_DIR
$scriptsmenu add separator
$scriptsmenu add command -label [msgcat::mc "HAL Show"] -command "exec $emc::TCL_BIN_DIR/halshow.tcl -- -ini $EMC_INIFILE &"
$scriptsmenu add command -label [msgcat::mc "HAL Config"] -command "exec $emc::TCL_BIN_DIR/halconfig.tcl -- -ini $EMC_INIFILE &"

# add the help menu
set helpmenu [menu $menubar.help -tearoff 0]
$menubar add cascade -label [msgcat::mc "Help"] -menu $helpmenu -underline 0
$helpmenu add command -label [msgcat::mc "Help..."] -command {popupHelp} -underline 0
$helpmenu add check -label [msgcat::mc "Balloon help"] -variable do_balloons
#$helpmenu add separator
#$helpmenu add command -label [msgcat::mc "Info..."] -command {catch {exec tcl/sysinfo.tcl -- -ini $EMC_INIFILE}} -underline 0
$helpmenu add separator
$helpmenu add command -label [msgcat::mc "About..."] -command {popupAbout} -underline 0

. configure -menu $menubar

set commandbuttons [frame $top.commandbuttons] ; # whole group
set commandbuttonsl1 [frame $commandbuttons.l1] ; # estop/mode
set commandbuttonsl2 [frame $commandbuttons.l2] ; # mist/flood
set commandbuttonsl3 [frame $commandbuttons.l3] ; # </spindle/>//brake
set commandbuttonsl3t1 [frame $commandbuttonsl3.t1] ; # </spindle/>

pack $commandbuttons -side top -fill both -expand true
pack $commandbuttonsl1 -side left -fill both -expand true
pack $commandbuttonsl2 -side left -fill both -expand true
pack $commandbuttonsl3 -side left -fill both -expand true
pack $commandbuttonsl3t1 -side top -fill both -expand true

set estopbutton [menubutton $commandbuttonsl1.estop -textvariable estoplabel -direction below -relief raised -width 15]
set estopmenu [menu $estopbutton.menu -tearoff 0]
$estopbutton configure -menu $estopmenu
$estopmenu add command -label [msgcat::mc "Estop on"] -command {emc_estop on}
$estopmenu add command -label [msgcat::mc "Estop off"] -command {emc_estop off}
$estopmenu add separator
$estopmenu add command -label [msgcat::mc "Machine on"] -command {emc_machine on}
$estopmenu add command -label [msgcat::mc "Machine off"] -command {emc_machine off}

pack $estopbutton -side top -fill both -expand true

set modebutton [menubutton $commandbuttonsl1.mode -textvariable modelabel -direction below -relief raised -width 15]
set modemenu [menu $modebutton.menu -tearoff 0]
$modebutton configure -menu $modemenu
$modemenu add command -label [msgcat::mc "Manual"] -command {emc_mode manual}
$modemenu add command -label [msgcat::mc "Auto"] -command {emc_mode auto}
$modemenu add command -label [msgcat::mc "MDI"] -command {emc_mode mdi}

pack $modebutton -side top -fill both -expand true

set mistbutton [menubutton $commandbuttonsl2.mist -textvariable mistlabel -direction below -relief raised -width 15]
set mistmenu [menu $mistbutton.menu -tearoff 0]
$mistbutton configure -menu $mistmenu
$mistmenu add command -label [msgcat::mc "Mist on"] -command {emc_mist on}
$mistmenu add command -label [msgcat::mc "Mist off"] -command {emc_mist off}

pack $mistbutton -side top -fill both -expand true

set floodbutton [menubutton $commandbuttonsl2.flood -textvariable floodlabel -direction below -relief raised -width 15]
set floodmenu [menu $floodbutton.menu -tearoff 0]
$floodbutton configure -menu $floodmenu
$floodmenu add command -label [msgcat::mc "Flood on"] -command {emc_flood on}
$floodmenu add command -label [msgcat::mc "Flood off"] -command {emc_flood off}

pack $floodbutton -side top -fill both -expand true

set lubebutton [menubutton $commandbuttonsl2.lube -textvariable lubelabel -direction below -relief raised -width 15]
set lubemenu [menu $lubebutton.menu -tearoff 0]
$lubebutton configure -menu $lubemenu
$lubemenu add command -label [msgcat::mc "Lube on"] -command {emc_lube on}
$lubemenu add command -label [msgcat::mc "Lube off"] -command {emc_lube off}

# FIXME-- there's probably a better place to put the lube button
# if {[emc_ini LUBE_WRITE_INDEX EMCIO] != ""} {
#     pack $lubebutton -side top -fill both -expand true
# }

set decrbutton [button $commandbuttonsl3t1.decr -text "<" -takefocus 0]

pack $decrbutton -side left -fill both -expand true

bind $decrbutton <ButtonPress-1> {emc_spindle decrease}
bind $decrbutton <ButtonRelease-1> {emc_spindle constant}

set spindlebutton [menubutton $commandbuttonsl3t1.spindle -textvariable spindlelabel -direction below -relief raised -width 15]
set spindlemenu [menu $spindlebutton.menu -tearoff 0]
$spindlebutton configure -menu $spindlemenu
$spindlemenu add command -label [msgcat::mc "Spindle forward"] -command {emc_spindle forward}
$spindlemenu add command -label [msgcat::mc "Spindle reverse"] -command {emc_spindle reverse}
$spindlemenu add command -label [msgcat::mc "Spindle off"] -command {emc_spindle off}

pack $spindlebutton -side left -fill both -expand true

set incrbutton [button $commandbuttonsl3t1.incr -text ">" -takefocus 0]

pack $incrbutton -side left -fill both -expand true

bind $incrbutton <ButtonPress-1> {emc_spindle increase}
bind $incrbutton <ButtonRelease-1> {emc_spindle constant}

set brakebutton [menubutton $commandbuttonsl3.brake -textvariable brakelabel -direction below -relief raised -width 25]
set brakemenu [menu $brakebutton.menu -tearoff 0]
$brakebutton configure -menu $brakemenu
$brakemenu add command -label [msgcat::mc "Brake on"] -command {emc_brake on}
$brakemenu add command -label [msgcat::mc "Brake off"] -command {emc_brake off}

pack $brakebutton -side top -fill both -expand true

set abortbutton [button $commandbuttons.abort -text [msgcat::mc "ABORT"] -width 15 -height 3 -takefocus 0]

pack $abortbutton -side left -fill both -expand true

bind $abortbutton <ButtonPress-1> {tkemc_abort}
pack $abortbutton -side top -fill both -expand true

set toolsetting 0
set tooloffsetsetting 0.0000
set offsetsetting "X0.0000 Y0.0000 Z0.0000"
set unitsetting "custom"
set oldunitsetting $unitsetting

set settings [frame $top.settings]
pack $settings -side top -anchor w -pady 2m
set toollabel [label $settings.toollabel -text [msgcat::mc "Tool:"] -anchor w]
set toolsetting [label $settings.toolsetting -textvariable toolsetting -width 4 -anchor w]
set tooloffsetlabel [label $settings.tooloffsetlabel -text [msgcat::mc "Offset:"] -anchor w]
set tooloffsetsetting [label $settings.tooloffsetsetting -textvariable tooloffsetsetting -width 10 -anchor e]
set offsetlabel [label $settings.offsetlabel -text [msgcat::mc "Work Offsets:"] -anchor w]
set offsetsetting [label $settings.offsetsetting -textvariable offsetsetting -width 30 -anchor w]
set unitlabel [label $settings.unitlabel -textvariable unitsetting -width 6 -anchor e]

pack $toollabel -side left -padx 1m
pack $toolsetting -side left -padx 1m
pack $tooloffsetlabel -side left -padx 1m
pack $tooloffsetsetting -side left -padx 1m
pack $offsetlabel -side left -padx 1m
pack $offsetsetting -side left -padx 1m
pack $unitlabel -side left -padx 1m

# set up help for these
set_balloon $offsetlabel [offsethelp]
set_balloon $offsetsetting [offsethelp]

bind $tooloffsetlabel <ButtonPress-1> {popupToolOffset}
bind $tooloffsetsetting <ButtonPress-1> {popupToolOffset}
bind $tooloffsetlabel <ButtonPress-3> {popupToolOffset}
bind $tooloffsetsetting <ButtonPress-3> {popupToolOffset}

# jointworld can be joint or world
if {  [emc_kinematics_type] == 1 } {
    set jointworld "world"
    set poslabel0 $worldlabel0
    set poslabel1 $worldlabel1
    set poslabel2 $worldlabel2
    set poslabel3 $worldlabel3
    set poslabel4 $worldlabel4
    set poslabel5 $worldlabel5
    set poslabel6 $worldlabel6
    set poslabel7 $worldlabel7
    set poslabel8 $worldlabel8
} else {
    set jointworld "joint"
    set poslabel0 $jointlabel0
    set poslabel1 $jointlabel1
    set poslabel2 $jointlabel2
    set poslabel3 $jointlabel3
    set poslabel4 $jointlabel4
    set poslabel5 $jointlabel5
    set poslabel6 $jointlabel6
    set poslabel7 $jointlabel7
    set poslabel8 $jointlabel8
}    

# process ini file settings for jog speed -- angular and linear
# use TRAJ settings only
set vitems "DEFAULT_VELOCITY DEFAULT_ANGULAR_VELOCITY DEFAULT_LINEAR_VELOCITY\
                MAX_VELOCITY     MAX_ANGULAR_VELOCITY     MAX_LINEAR_VELOCITY"
foreach item $vitems {
  set temp [emc_ini "$item" "TRAJ"]
  if {"$temp" != ""} {set tempini($item) $temp}
}      
if [info exists tempini(DEFAULT_LINEAR_VELOCITY)] {
  set temp     $tempini(DEFAULT_LINEAR_VELOCITY)
} elseif [info exists tempini(DEFAULT_VELOCITY)] {
  set temp           $tempini(DEFAULT_VELOCITY)
} else {
  set temp 1
}
set ::linearJogSpeed [expr int($temp * 60 + 0.5)] ;# units/minute

if [info exists tempini(MAX_LINEAR_VELOCITY)] {
  set temp     $tempini(MAX_LINEAR_VELOCITY)
} elseif [info exists tempini(MAX_VELOCITY)] {
  set temp           $tempini(MAX_VELOCITY)
} else {
  set temp 1
}
set ::linearJogSpeedMax [expr int($temp * 60 + 0.5)] ;# units/minute

if [info exists tempini(DEFAULT_ANGULAR_VELOCITY)] {
  set temp     $tempini(DEFAULT_ANGULAR_VELOCITY)
  set ::angularJogSpeed [expr {int($temp * 60 + 0.5)}] ;# units/minute
}
# no angular jog slider if no DEFAULT_ANGULAR_VELOCITY
if [info exists ::angularJogSpeed] {
  if [info exists tempini(MAX_ANGULAR_VELOCITY)] {
    set temp     $tempini(MAX_ANGULAR_VELOCITY)
    set ::angularJogSpeedMax [expr {int($temp * 60 + 0.5)}] ;# units/minute
  } else {
    set ::angularJogSpeedMax $::angularJogSpeed
  }
}

foreach axis {0 1 2 3 4 5 6 7 8} {
  set temp [emc_ini "TYPE" "AXIS_$axis"]
  switch $temp {
    LINEAR  {set ::jogAxisType($axis) linear}
    ANGULAR {set ::jogAxisType($axis) angular}
  }
}
unset vitems tempini ;# remove clutter

set jogType continuous
set jogIncrement 0.0010

set move [frame $top.move]
set position [frame $move.position]
set pos0 [frame $position.pos0 -borderwidth 4]
set pos1 [frame $position.pos1 -borderwidth 4]
set pos2 [frame $position.pos2 -borderwidth 4]
set pos3 [frame $position.pos3 -borderwidth 4]
set pos4 [frame $position.pos4 -borderwidth 4]
set pos5 [frame $position.pos5 -borderwidth 4]
set pos6 [frame $position.pos6 -borderwidth 4]
set pos7 [frame $position.pos7 -borderwidth 4]<commit_msg>apply fix from <NAME> - fix angular jogspeed value bug (if no DEFAULT_ANGULAR_VELOCITY was given any angular jogs were dropped)<commit_after>#!/bin/sh
# the next line restarts using emcsh \
exec ${EMC2_EMCSH-emcsh} "$0" "$@"

###############################################################
# Description:  tkemc
#               A Tcl/Tk GUI script that defines default  
#               emc interface functionality. 
#
#  Derived from a work by <NAME> & <NAME>
#  Author: 
#  License: GPL Version 2
#
#  Copyright (c) 2006-2009 All rights reserved.
###############################################################
# Uses the emcsh library of tcl/tk functions.
# Provides default display or operators for each NML message
###############################################################

# Load the emc.tcl file, which defines variables for various useful paths
source [file join [file dirname [info script]] emc.tcl]

# Tk GUI for the Enhanced Machine Controller

# Notes

# 1. Widget focus. Keyboard traversal with TAB sets the focus to some of the
# widgets. When they're focused, arrow keys and numbers don't work. To fix
# this, most widgets that would get focus have the focus disabled with
# -takefocus 0. A few remain; these are added to the widgets that bindtags
# applies to when switching between ManualBindings, AutoBindings

# 2. Adds tkbackplot and scripts to menu.
# 3. Adds info to help menu that calls tcl.sysinfo.tcl and uses emc/emcversion

# Set global that signifies we're the tkemc, so that other sourced scripts
# can know how to pack themselves. This lets these scripts pack into the
# main window "." if "tkemc" is not defined, or in their own top-level window
# if "tkemc" is defined. emclog.tcl looks at this.
set tkemc 1

# Internationalisation (i18n)
# in order to use i18n, all the strings will be called [msgcat::mc "string-foo"]
# instead of "string-foo".
# Thus msgcat searches for a translation of the string, and in case one isn't 
# found, the original string is used.
# In order to properly use locale's the env variable LANG is queried.
# If LANG is defined, then the folder src/po is searched for files
# called *.msg, (e.g. en_US.msg).
package require msgcat
if ([info exists env(LANG)]) {
    msgcat::mclocale $env(LANG)
    msgcat::mcload $emc::LANG_DIR
}

# read the application defaults
set TKEMCCONF $emc::TCL_DIR/TkEmc
if {[file exists $TKEMCCONF]} {
    option readfile $TKEMCCONF startupFile
}
foreach f {TkEmc /usr/X11R6/lib/X11/app-defaults/TkEmc /etc/X11/app-defaults/TkEmc} {
    if {[file exists $f]} {
	option readfile $f
	break
    }
}

# test for windows flag
set windows 0

foreach arg $argv {
    if { $arg == "-win" } {
	set windows 1
    }
}

# Read the ini file to determine what the axes and coordinates are.

set worldlabellist ""
set axiscoordmap ""
set numaxes [emc_ini "AXES" "TRAJ"]
set coordnames [ emc_ini "COORDINATES" "TRAJ"]

set numcoords 0

if { [ string first "X" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist X]
    set axiscoordmap [ concat $axiscoordmap 0  ]
}

if { [ string first "Y" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist Y]
    set axiscoordmap [ concat $axiscoordmap  1 ]
}

if { [ string first "Z" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist Z]
    set axiscoordmap [ concat $axiscoordmap  2 ]
}


if { [ string first "A" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist A]
    set axiscoordmap [ concat $axiscoordmap  3 ]
}

if { [ string first "B" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist B]
    set axiscoordmap [ concat $axiscoordmap  4 ]
}

if { [ string first "C" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist C]
    set axiscoordmap [ concat $axiscoordmap  5 ]
}

if { [ string first "U" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist U]
    set axiscoordmap [ concat $axiscoordmap  6 ]
}

if { [ string first "V" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist V]
    set axiscoordmap [ concat $axiscoordmap  7 ]
}

if { [ string first "W" $coordnames ] >= 0 } {
    set numcoords $numcoords+1
    set worldlabellist [ concat $worldlabellist W]
    set axiscoordmap [ concat $axiscoordmap  8 ]
}

set worldlabellist [ concat $worldlabellist "-" "-" "-" "-" "-" "-" "-" "-" "-" ]
set axiscoordmap [ concat $axiscoordmap 0 0 0 0 0 0 0 0 0]
set worldlabel0 [lindex  $worldlabellist 0 ]
set worldlabel1 [lindex  $worldlabellist 1 ]
set worldlabel2 [lindex  $worldlabellist 2 ]
set worldlabel3 [lindex  $worldlabellist 3 ]
set worldlabel4 [lindex  $worldlabellist 4 ]
set worldlabel5 [lindex  $worldlabellist 5 ]
set worldlabel6 [lindex  $worldlabellist 6 ]
set worldlabel7 [lindex  $worldlabellist 7 ]
set worldlabel8 [lindex  $worldlabellist 8 ]

set jointlabel0 "0"
set jointlabel1 "1"
set jointlabel2 "2"
set jointlabel3 "3"
set jointlabel4 "4"
set jointlabel5 "5"
set jointlabel6 "6"
set jointlabel7 "7"
set jointlabel8 "8"

# set the cycle time for display updating
set temp [emc_ini "CYCLE_TIME" "DISPLAY"]
if {[string length $temp] == 0} {
    set temp 0.200
}
set displayCycleTime [expr {int($temp * 1000 + 0.5)}]
set syncDelayTime    $displayCycleTime ;#increasing improves slider behavior

# set the debounce time for key repeats
set debounceTime 150

if { $windows == 0 } {
    # load the generic editor "startEditor <name>"
    source $emc::TCL_BIN_DIR/genedit.tcl

    # load the EMC calibrator
#    source $emc::TCL_BIN_DIR/emccalib.tcl

    # load the EMC data logger
#    source $emc::TCL_BIN_DIR/emclog.tcl

    # load the EMC performance tester
    source $emc::TCL_BIN_DIR/emctesting.tcl

    # load the EMC debug level setter
    source $emc::TCL_BIN_DIR/emcdebug.tcl

    # load the backplotter
    source $emc::TCL_BIN_DIR/tkbackplot.tcl

    # load balloon help
    source $emc::TCL_SCRIPT_DIR/balloon.tcl
    source $emc::TCL_SCRIPT_DIR/emchelp.tcl
    set do_balloons [emc_ini "BALLOON_HELP" "DISPLAY"]
    if {$do_balloons == ""} {
        set do_balloons 0
    }
}

# the line from which to run the program; 0 or 1 means from start
set runMark 0
proc popupRunMark {mark} {
    global runMark
    catch {destroy .runmark}
    toplevel .runmark
    wm title .runmark [msgcat::mc "Set Run Mark"]
    label .runmark.msg -font {Helvetica 12 bold} -wraplength 4i -justify left \
        -text [msgcat::mc "Set run mark at line %s?" $mark]
    pack .runmark.msg -side top
    frame .runmark.buttons
    pack .runmark.buttons -side bottom -fill x -pady 2m
    button .runmark.buttons.ok -text [msgcat::mc "OK"] -default active \
        -command "set runMark $mark; destroy .runmark"
    button .runmark.buttons.cancel -text [msgcat::mc "Cancel"] \
        -command "destroy .runmark"
    pack .runmark.buttons.ok .runmark.buttons.cancel -side left -expand 1
    bind .runmark <Return> "set runMark $mark; destroy .runmark"
}

# pop up the program editor
proc popupProgramEditor {} {
    global programnamestring

    # create an editor as top-level ".programEditor"
    if {[file isfile $programnamestring]} {
        geneditStart programEditor $programnamestring
    } else {
        geneditStart programEditor [msgcat::mc "untitled"].ngc
    }

    frame .programEditor.buttons
    pack .programEditor.buttons -side bottom -fill x -pady 2m
    button .programEditor.buttons.mark -text [msgcat::mc "Set Run Mark"] -command \
        {popupRunMark [int [.programEditor.textframe.textwin index insert]]}
    pack .programEditor.buttons.mark -side left -expand 1
}

set toolfilename [emc_ini "TOOL_TABLE" "EMCIO"]
if {[string length $toolfilename] == 0} {
    set toolfilename "emc.tbl"
}

# pop up the tool table editor
proc popupToolEditor {} {
    global toolfilename

    # create an editor as top-level ".toolEditor"
    if {[file isfile $toolfilename]} {
        geneditStart toolEditor $toolfilename
    } else {
        geneditStart toolEditor [msgcat::mc "untitled"].tbl
    }

    frame .toolEditor.buttons
    pack .toolEditor.buttons -side bottom -fill x -pady 2m
    button .toolEditor.buttons.load -text [msgcat::mc "Load Tool Table"] -command {geneditSaveFile toolEditor; emc_load_tool_table $toolfilename}
    button .toolEditor.buttons.cancel -text [msgcat::mc "Cancel"] -default active -command {destroy .toolEditor}
    pack .toolEditor.buttons.load .toolEditor.buttons.cancel -side left -expand 1
}

set paramfilename [emc_ini "PARAMETER_FILE" "RS274NGC"]
if {[string length $paramfilename] == 0} {
    set paramfilename "emc.var"
}

# pop up the parameter file editor
proc popupParamEditor {} {
    global paramfilename

    # create an editor as top-level ".paramEditor"
    if {[file isfile $paramfilename]} {
        geneditStart paramEditor $paramfilename
    } else {
        geneditStart paramEditor [msgcat::mc "untitled"].var
    }

    # disable "Save As..." menu, since we don't support changing it
    .paramEditor.menubar.file entryconfigure 3 -state disabled

    frame .paramEditor.buttons
    pack .paramEditor.buttons -side bottom -fill x -pady 2m
    button .paramEditor.buttons.load -text [msgcat::mc "Load Parameter File"] -command {geneditSaveFile paramEditor; emc_task_plan_init}
    button .paramEditor.buttons.cancel -text [msgcat::mc "Cancel"] -default active -command {destroy .paramEditor}
    pack .paramEditor.buttons.load .paramEditor.buttons.cancel -side left -expand 1
}

set helpfilename [emc_ini "HELP_FILE" "DISPLAY"]
if {[string length $helpfilename] == 0} {
    set helpfilename "tkemc.txt"
}

# pop up the help window
proc popupHelp {} {
    global helpfilename
    global HELPDIR

    # create an editor as top-level ".help"
    if {[file isfile $emc::HELP_DIR/$helpfilename]} {
        geneditStart help $emc::HELP_DIR/$helpfilename
    } else {
        geneditStart help $emc::HELP_DIR/tkemc.txt
    }

    # disable menu entries that don't apply to read-only text
    .help.menubar.file entryconfigure 0 -state disabled
    .help.menubar.file entryconfigure 1 -state disabled
    .help.menubar.file entryconfigure 2 -state disabled
    .help.menubar.file entryconfigure 3 -state disabled
    .help.menubar.edit entryconfigure 0 -state disabled
    .help.menubar.edit entryconfigure 2 -state disabled
    .help.textframe.textwin configure -state disabled

    frame .help.buttons
    pack .help.buttons -side bottom -fill x -pady 2m
    button .help.buttons.ok -text [msgcat::mc "OK"] -default active -command {destroy .help}
    pack .help.buttons.ok -side left -expand 1
    bind .help <Return> {destroy .help}
}

# pop up the diagnostics window
proc popupDiagnostics {} {
    set d .diagnostics

    if {[winfo exists $d]} {
        wm deiconify $d
        raise $d
        focus $d
        return
    }
    toplevel $d
    wm title $d [msgcat::mc "EMC Diagnostics"]

    label $d.task -text [msgcat::mc "Task"] -width 30 -anchor center
    frame $d.taskhb
    label $d.taskhb.lab -text [msgcat::mc "Heartbeat:"] -anchor w
    label $d.taskhb.val -textvariable taskhb -anchor e
    frame $d.taskcmd
    label $d.taskcmd.lab -text [msgcat::mc "Command:"] -anchor w
    label $d.taskcmd.val -textvariable taskcmd -anchor e
    frame $d.tasknum
    label $d.tasknum.lab -text [msgcat::mc "Command #:"] -anchor w
    label $d.tasknum.val -textvariable tasknum -anchor e
    frame $d.taskstatus
    label $d.taskstatus.lab -text [msgcat::mc "Status:"] -anchor w
    label $d.taskstatus.val -textvariable taskstatus -anchor e
    pack $d.task $d.taskhb $d.taskcmd $d.tasknum $d.taskstatus -side top -fill x
    pack $d.taskhb.lab -side left
    pack $d.taskhb.val -side right
    pack $d.taskcmd.lab -side left
    pack $d.taskcmd.val -side right
    pack $d.tasknum.lab -side left
    pack $d.tasknum.val -side right
    pack $d.taskstatus.lab -side left
    pack $d.taskstatus.val -side right

    label $d.io -text [msgcat::mc "Io"] -width 30 -anchor center
    frame $d.iohb
    label $d.iohb.lab -text [msgcat::mc "Heartbeat:"] -anchor w
    label $d.iohb.val -textvariable iohb -anchor e
    frame $d.iocmd
    label $d.iocmd.lab -text [msgcat::mc "Command:"] -anchor w
    label $d.iocmd.val -textvariable iocmd -anchor e
    frame $d.ionum
    label $d.ionum.lab -text [msgcat::mc "Command #:"] -anchor w
    label $d.ionum.val -textvariable ionum -anchor e
    frame $d.iostatus
    label $d.iostatus.lab -text [msgcat::mc "Status:"] -anchor w
    label $d.iostatus.val -textvariable iostatus -anchor e
    pack $d.io $d.iohb $d.iocmd $d.ionum $d.iostatus -side top -fill x
    pack $d.iohb.lab -side left
    pack $d.iohb.val -side right
    pack $d.iocmd.lab -side left
    pack $d.iocmd.val -side right
    pack $d.ionum.lab -side left
    pack $d.ionum.val -side right
    pack $d.iostatus.lab -side left
    pack $d.iostatus.val -side right

    label $d.motion -text [msgcat::mc "Motion"] -width 30 -anchor center
    frame $d.motionhb
    label $d.motionhb.lab -text [msgcat::mc "Heartbeat:"] -anchor w
    label $d.motionhb.val -textvariable motionhb -anchor e
    frame $d.motioncmd
    label $d.motioncmd.lab -text [msgcat::mc "Command:"] -anchor w
    label $d.motioncmd.val -textvariable motioncmd -anchor e
    frame $d.motionnum
    label $d.motionnum.lab -text [msgcat::mc "Command #:"] -anchor w
    label $d.motionnum.val -textvariable motionnum -anchor e
    frame $d.motionstatus
    label $d.motionstatus.lab -text [msgcat::mc "Status:"] -anchor w
    label $d.motionstatus.val -textvariable motionstatus -anchor e
    pack $d.motion $d.motionhb $d.motioncmd $d.motionnum $d.motionstatus -side top -fill x
    pack $d.motionhb.lab -side left
    pack $d.motionhb.val -side right
    pack $d.motioncmd.lab -side left
    pack $d.motioncmd.val -side right
    pack $d.motionnum.lab -side left
    pack $d.motionnum.val -side right
    pack $d.motionstatus.lab -side left
    pack $d.motionstatus.val -side right

    frame $d.buttons
    button $d.buttons.ok -text OK -default active -command "destroy $d"

    pack $d.buttons -side bottom -fill x -pady 2m
    pack $d.buttons.ok -side left -expand 1
    bind $d <Return> "destroy $d"
}

# pop up the about box
proc popupAbout {} {
    global env
    if {[winfo exists .about]} {
        wm deiconify .about
        raise .about
        focus .about
        return
    }
    toplevel .about
    wm title .about [msgcat::mc "About TkEmc"]
    message .about.msg -aspect 1000 -justify center -font {Helvetica 12 bold} -text [ format "%s\n(EMC2 %s)" [msgcat::mc "TkEmc\n\nTcl/Tk GUI for Enhanced Machine Controller version 2 (EMC2)\n\nGPL Version 2 (2006)"] $env(EMC2VERSION) ]
    frame .about.buttons
    button .about.buttons.ok -default active -text OK -command "destroy .about"
    pack .about.msg -side top
    pack .about.buttons -side bottom -fill x -pady 2m
    pack .about.buttons.ok -side left -expand 1
    bind .about <Return> "destroy .about"
}

proc popupToolOffset {} {
    global toolsetting tooloffsetsetting
    global toolentry toollengthentry tooldiameterentry

    if {[winfo exists .tooloffset]} {
        wm deiconify .tooloffset
        raise .tooloffset
        focus .tooloffset
        return
    }
    toplevel .tooloffset
    wm title .tooloffset [msgcat::mc "Set Tool Offset"]

    # pre-load the entries with values
    set toolentry $toolsetting
    set toollengthentry $tooloffsetsetting
    set tooldiameterentry 0.0 ; # no value provided by controller

    frame .tooloffset.tool
    label .tooloffset.tool.label -text [msgcat::mc "Tool:"] -anchor w -width 15
    entry .tooloffset.tool.entry -textvariable toolentry -width 20

    frame .tooloffset.length
    label .tooloffset.length.label -text [msgcat::mc "Length:"] -anchor w -width 15
    entry .tooloffset.length.entry -textvariable toollengthentry -width 20

    frame .tooloffset.diameter
    label .tooloffset.diameter.label -text [msgcat::mc "Diameter:"] -anchor w -width 15
    entry .tooloffset.diameter.entry -textvariable tooldiameterentry -width 20

    frame .tooloffset.buttons
    button .tooloffset.buttons.ok -text [msgcat::mc "OK"] -default active -command {emc_set_tool_offset $toolentry $toollengthentry $tooldiameterentry; destroy .tooloffset}
    button .tooloffset.buttons.cancel -text [msgcat::mc "Cancel"] -command {destroy .tooloffset}

    pack .tooloffset.tool -side top
    pack .tooloffset.tool.label .tooloffset.tool.entry -side left
    pack .tooloffset.length -side top
    pack .tooloffset.length.label .tooloffset.length.entry -side left
    pack .tooloffset.diameter -side top
    pack .tooloffset.diameter.label .tooloffset.diameter.entry -side left

    pack .tooloffset.buttons -side bottom -fill x -pady 2m
    pack .tooloffset.buttons.ok .tooloffset.buttons.cancel -side left -expand 1
    bind .tooloffset <Return> {emc_set_tool_offset $toolentry $toollengthentry $tooldiameterentry; destroy .tooloffset}

    focus .tooloffset.length.entry
    .tooloffset.length.entry select range 0 end
}

# set waiting on EMC to wait until command is received, not finished, with
# timeout of 10 seconds
emc_set_timeout 1.0
emc_set_wait received

# force an update
emc_update

set modifier Alt
set modifierstring "Alt"

set programDirectory [emc_ini "PROGRAM_PREFIX" "DISPLAY"]

# process to load the program text display widget
proc loadProgramText {} {
    global programnamestring programfiletext
    # clear out program text
    $programfiletext config -state normal
    $programfiletext delete 1.0 end
    # close the current program
    catch {close $programin}
    # open the new program, if it's not "none"
    if {[catch {open $programnamestring} programin]} {
        puts stdout [msgcat::mc "can't open %s" $programnamestring]
    } else {
        $programfiletext insert end [read $programin]
        $programfiletext config -state disabled
        catch {close $programin}
    }
}

# set initial value for program status comparison
set oldstatusstring "idle"

proc fileDialog {} {
    global programDirectory
    global programnamestring
    set allfilestring [msgcat::mc "All files"]
    set textfilestring [msgcat::mc "Text files"]
    set ncfilestring [msgcat::mc "NC files"]

    set all [list ]
    lappend all $allfilestring
    lappend all *
    set text [list ]
    lappend text $textfilestring
    lappend text ".txt"
    set nc [list ]
    lappend nc $ncfilestring
    lappend nc ".nc .ngc"
    
    set types [list ]
    lappend types $all
    lappend types $text 
    lappend types $nc
    
    set f [tk_getOpenFile -filetypes $types -initialdir $programDirectory]
    if {[string len $f] > 0} {
        set programDirectory [file dirname $f]
        set programnamestring $f
        emc_mode auto
        emc_abort
        emc_open $programnamestring
        loadProgramText
    }
}

proc toggleEstop {} {
    if {[emc_estop] == "on"} {
        emc_estop off
    } else {
        emc_estop on
    }
}

proc toggleMachine {} {
    if {[emc_machine] == "off"} {
        emc_machine on
    } else {
        emc_machine off
    }
}

proc toggleMist {} {
    if {[emc_mist] == "off"} {
        emc_mist on
    } else {
        emc_mist off
    }
}

proc toggleFlood {} {
    if {[emc_flood] == "off"} {
        emc_flood on
    } else {
        emc_flood off
    }
}

proc toggleSpindleForward {} {
    if {[emc_spindle] == "off"} {
        emc_spindle forward
    } else {
        emc_spindle off
    }
}

proc toggleSpindleReverse {} {
    if {[emc_spindle] == "off"} {
        emc_spindle reverse
    } else {
        emc_spindle off
    }
}

# coords can be relative or machine
set temp [emc_ini "POSITION_OFFSET" "DISPLAY"]
if {$temp == "RELATIVE"} {
    set coords relative
} elseif {$temp == "MACHINE"} {
    set coords machine
} else {
    # not found, or invalid, so set to relative
    set coords relative
}

# actcmd can be actual or commanded
set temp [emc_ini "POSITION_FEEDBACK" "DISPLAY"]
if {$temp == "ACTUAL"} {
    set actcmd actual
} elseif {$temp == "COMMANDED"} {
    set actcmd commanded
} else {
    # not found, or invalid, so set to actual
    set actcmd actual
}

proc toggleRelAbs {} {
    global coords
    if {$coords == "relative"} {
        set coords machine
    } else {
        set coords relative
    }
}

proc toggleCmdAct {} {
    global actcmd
    if {$actcmd == "actual"} {
        set actcmd commanded
    } else {
        set actcmd actual
    }
}

set jointworld "joint"

proc toggleJointWorld {} {
    global jointworld
    if {$jointworld == "joint"} {
        set jointworld world
    } else {
        set jointworld joint
    }
}

proc toggleJogType {} {
    global jogLabel jogType jogIncrement

    if {$jogType == "continuous"} {
        set jogType $jogIncrement
	set jogLabel $jogIncrement
    } else {
        set jogType continuous
	set jogLabel [msgcat::mc "continuous"]
    }
}

proc toggleJogIncrement {} {
    global jogLabel jogType jogIncrement

    if {$jogType == "continuous"} {
        set jogType $jogIncrement
	set jogLabel $jogIncrement
    } else {
        if {$jogIncrement == "0.0001"} {
            set jogIncrement 0.0010
        } elseif {$jogIncrement == "0.0010"} {
            set jogIncrement 0.0100
        } elseif {$jogIncrement == "0.0100"} {
            set jogIncrement 0.1000
        } elseif {$jogIncrement == "0.1000"} {
            set jogIncrement 1.0000
        } elseif {$jogIncrement == "1.0000"} {
            set jogIncrement 0.0001
        }
        set jogType $jogIncrement
	set jogLabel $jogIncrement
    }
}

# given axis, determines speed and cont v. incr and jogs it neg
proc jogNeg {axis} {
    global activeAxis jogType jogIncrement axiscoordmap

    set activeAxis $axis

    if { [emc_teleop_enable] == 1 } {
	set axisToJog [ lindex $axiscoordmap $axis ]
    } else {
	set axisToJog $axis
    }
    switch $::jogAxisType($axisToJog) {
      linear  {set speed $::linearJogSpeed}
      angular {set speed $::angularJogSpeed}
      undefined {return}
    }
    if {$jogType == "continuous"} {
        emc_jog $axisToJog -$speed
    } else {
        emc_jog_incr $axisToJog -$speed $jogIncrement
    }
}

# given axis, determines speed and cont v. incr and jogs it pos
proc jogPos {axis} {
    global activeAxis jogType jogIncrement axiscoordmap

    set activeAxis $axis
    
    if { [emc_teleop_enable] == 1 } {
	set axisToJog [ lindex $axiscoordmap $axis ]
    } else {
	set axisToJog $axis
    }
    switch $::jogAxisType($axisToJog) {
      linear  {set speed $::linearJogSpeed}
      angular {set speed $::angularJogSpeed}
      undefined {return}
    }

    if {$jogType == "continuous"} {
        emc_jog $axisToJog $speed
    } else {
        emc_jog_incr $axisToJog $speed $jogIncrement
    }
}

# stops the active axis
proc jogStop {axis} {
    global jogType
    #removed globalAxis, as that caused the problems with multiple jogs

    # only stop continuous jogs; let incremental jogs finish
    if {$jogType == "continuous"} {
        emc_jog_stop $axis
    }
}

# toggles the limit override state
proc toggleLimitOverride {} {
    if {[emc_override_limit]} {
        emc_override_limit 0
    } else {
        emc_override_limit 1
    }
}

# toggles the optional stop
proc toggleOptionalStop {} {
    if {[emc_optional_stop]} {
        emc_optional_stop 0
    } else {
        emc_optional_stop 1
    }
}


# use the top-level window as our top-level window, and name it
wm title . "TkEMC"

# create the main window top frame
set top [frame .top]
pack $top -side top -fill both -expand true

# build the top menu bar
set menubar [menu $top.menubar -tearoff 0]

# add the File menu
set filemenu [menu $menubar.file -tearoff 0]
$menubar add cascade -label [msgcat::mc "File"] -menu $filemenu -underline 0
$filemenu add command -label [msgcat::mc "Open..."] -command {fileDialog} -underline 0
bind . <$modifier-o> {fileDialog}
$filemenu add command -label [msgcat::mc "Edit..."] -command {popupProgramEditor} -underline 0
$filemenu add command -label [msgcat::mc "Reset"] -command {emc_task_plan_init} -underline 0
$filemenu add separator
$filemenu add command -label [msgcat::mc "Exit"] -command {after cancel updateStatus ; destroy . ; exit} -accelerator $modifierstring+X -underline 1
bind . <$modifier-x> {after cancel updateStatus ; destroy . ; exit}

# add the View menu
set viewmenu [menu $menubar.view -tearoff 0]
$menubar add cascade -label [msgcat::mc "View"] -menu $viewmenu -underline 0
$viewmenu add command -label [msgcat::mc "Tools..."] -command {popupToolEditor} -underline 0
$viewmenu add command -label [msgcat::mc "Offsets and Variables..."] -command {popupParamEditor} -underline 0
$viewmenu add command -label [msgcat::mc "Diagnostics..."] -command {popupDiagnostics} -underline 0
$viewmenu add command -label [msgcat::mc "Backplot..."] -command {popupPlot} -underline 0

# add the Settings menu
set settingsmenu [menu $menubar.settings -tearoff 0]
$menubar add cascade -label [msgcat::mc "Settings"] -menu $settingsmenu -underline 0
$settingsmenu add command -label [msgcat::mc "Calibration..."] -command "exec $emc::TCL_BIN_DIR/emccalib.tcl -- -ini $EMC_INIFILE &"
$settingsmenu add command -label [msgcat::mc "Testing..."] -command {popupTesting} -underline 0 -state disabled
$settingsmenu add command -label [msgcat::mc "Debug..."] -command {popupDebug} -underline 0
$settingsmenu add command -label [msgcat::mc "Font..."] -command {popupFont} -underline 0

# add the Units menu
set unitsmenu [menu $menubar.units -tearoff 0]
$menubar add cascade -label [msgcat::mc "Units"] -menu $unitsmenu -underline 0
$unitsmenu add command -label [msgcat::mc "auto"] -command {emc_linear_unit_conversion auto} -underline 0
$unitsmenu add command -label [msgcat::mc "inches"] -command {emc_linear_unit_conversion inch} -underline 0
$unitsmenu add command -label [msgcat::mc "mm"] -command {emc_linear_unit_conversion mm} -underline 0
$unitsmenu add command -label [msgcat::mc "cm"] -command {emc_linear_unit_conversion cm} -underline 0

# add the Utilities menu
set utilsmenu [menu $menubar.utils -tearoff 1]
$menubar add cascade -label [msgcat::mc "Utilities"] -menu $utilsmenu -underline 1
$utilsmenu add command -label [msgcat::mc "Hal Scope"] -command {exec halscope -- -ini $EMC_INIFILE &}
$utilsmenu add command -label [msgcat::mc "Hal Meter"] -command {exec halmeter &}

# Add a scripts menu that looks for *.tcl files in tcl/scripts subdirectory
set scriptsmenu [menu $menubar.scripts -tearoff 1]
$menubar add cascade -label [msgcat::mc "Scripts"] -menu $scriptsmenu -underline 1

if { $windows == 0 } {
    set files [exec /bin/ls $emc::TCL_SCRIPT_DIR]
    foreach file $files {
	if {[string match *.tcl $file]} {
	    set fname [file rootname $file]
	    # if it's executable, arrange for direct execution
	    if {[file executable $emc::TCL_SCRIPT_DIR/$file]} {
		$scriptsmenu add command -label $fname -command "exec $emc::TCL_SCRIPT_DIR/$file -- -ini $EMC_INIFILE &"
	    }
	}
    }
}

# add halconfig, to help for HAL setup, it's under Scripts, but it's in the TCL_BIN_DIR
$scriptsmenu add separator
$scriptsmenu add command -label [msgcat::mc "HAL Show"] -command "exec $emc::TCL_BIN_DIR/halshow.tcl -- -ini $EMC_INIFILE &"
$scriptsmenu add command -label [msgcat::mc "HAL Config"] -command "exec $emc::TCL_BIN_DIR/halconfig.tcl -- -ini $EMC_INIFILE &"

# add the help menu
set helpmenu [menu $menubar.help -tearoff 0]
$menubar add cascade -label [msgcat::mc "Help"] -menu $helpmenu -underline 0
$helpmenu add command -label [msgcat::mc "Help..."] -command {popupHelp} -underline 0
$helpmenu add check -label [msgcat::mc "Balloon help"] -variable do_balloons
#$helpmenu add separator
#$helpmenu add command -label [msgcat::mc "Info..."] -command {catch {exec tcl/sysinfo.tcl -- -ini $EMC_INIFILE}} -underline 0
$helpmenu add separator
$helpmenu add command -label [msgcat::mc "About..."] -command {popupAbout} -underline 0

. configure -menu $menubar

set commandbuttons [frame $top.commandbuttons] ; # whole group
set commandbuttonsl1 [frame $commandbuttons.l1] ; # estop/mode
set commandbuttonsl2 [frame $commandbuttons.l2] ; # mist/flood
set commandbuttonsl3 [frame $commandbuttons.l3] ; # </spindle/>//brake
set commandbuttonsl3t1 [frame $commandbuttonsl3.t1] ; # </spindle/>

pack $commandbuttons -side top -fill both -expand true
pack $commandbuttonsl1 -side left -fill both -expand true
pack $commandbuttonsl2 -side left -fill both -expand true
pack $commandbuttonsl3 -side left -fill both -expand true
pack $commandbuttonsl3t1 -side top -fill both -expand true

set estopbutton [menubutton $commandbuttonsl1.estop -textvariable estoplabel -direction below -relief raised -width 15]
set estopmenu [menu $estopbutton.menu -tearoff 0]
$estopbutton configure -menu $estopmenu
$estopmenu add command -label [msgcat::mc "Estop on"] -command {emc_estop on}
$estopmenu add command -label [msgcat::mc "Estop off"] -command {emc_estop off}
$estopmenu add separator
$estopmenu add command -label [msgcat::mc "Machine on"] -command {emc_machine on}
$estopmenu add command -label [msgcat::mc "Machine off"] -command {emc_machine off}

pack $estopbutton -side top -fill both -expand true

set modebutton [menubutton $commandbuttonsl1.mode -textvariable modelabel -direction below -relief raised -width 15]
set modemenu [menu $modebutton.menu -tearoff 0]
$modebutton configure -menu $modemenu
$modemenu add command -label [msgcat::mc "Manual"] -command {emc_mode manual}
$modemenu add command -label [msgcat::mc "Auto"] -command {emc_mode auto}
$modemenu add command -label [msgcat::mc "MDI"] -command {emc_mode mdi}

pack $modebutton -side top -fill both -expand true

set mistbutton [menubutton $commandbuttonsl2.mist -textvariable mistlabel -direction below -relief raised -width 15]
set mistmenu [menu $mistbutton.menu -tearoff 0]
$mistbutton configure -menu $mistmenu
$mistmenu add command -label [msgcat::mc "Mist on"] -command {emc_mist on}
$mistmenu add command -label [msgcat::mc "Mist off"] -command {emc_mist off}

pack $mistbutton -side top -fill both -expand true

set floodbutton [menubutton $commandbuttonsl2.flood -textvariable floodlabel -direction below -relief raised -width 15]
set floodmenu [menu $floodbutton.menu -tearoff 0]
$floodbutton configure -menu $floodmenu
$floodmenu add command -label [msgcat::mc "Flood on"] -command {emc_flood on}
$floodmenu add command -label [msgcat::mc "Flood off"] -command {emc_flood off}

pack $floodbutton -side top -fill both -expand true

set lubebutton [menubutton $commandbuttonsl2.lube -textvariable lubelabel -direction below -relief raised -width 15]
set lubemenu [menu $lubebutton.menu -tearoff 0]
$lubebutton configure -menu $lubemenu
$lubemenu add command -label [msgcat::mc "Lube on"] -command {emc_lube on}
$lubemenu add command -label [msgcat::mc "Lube off"] -command {emc_lube off}

# FIXME-- there's probably a better place to put the lube button
# if {[emc_ini LUBE_WRITE_INDEX EMCIO] != ""} {
#     pack $lubebutton -side top -fill both -expand true
# }

set decrbutton [button $commandbuttonsl3t1.decr -text "<" -takefocus 0]

pack $decrbutton -side left -fill both -expand true

bind $decrbutton <ButtonPress-1> {emc_spindle decrease}
bind $decrbutton <ButtonRelease-1> {emc_spindle constant}

set spindlebutton [menubutton $commandbuttonsl3t1.spindle -textvariable spindlelabel -direction below -relief raised -width 15]
set spindlemenu [menu $spindlebutton.menu -tearoff 0]
$spindlebutton configure -menu $spindlemenu
$spindlemenu add command -label [msgcat::mc "Spindle forward"] -command {emc_spindle forward}
$spindlemenu add command -label [msgcat::mc "Spindle reverse"] -command {emc_spindle reverse}
$spindlemenu add command -label [msgcat::mc "Spindle off"] -command {emc_spindle off}

pack $spindlebutton -side left -fill both -expand true

set incrbutton [button $commandbuttonsl3t1.incr -text ">" -takefocus 0]

pack $incrbutton -side left -fill both -expand true

bind $incrbutton <ButtonPress-1> {emc_spindle increase}
bind $incrbutton <ButtonRelease-1> {emc_spindle constant}

set brakebutton [menubutton $commandbuttonsl3.brake -textvariable brakelabel -direction below -relief raised -width 25]
set brakemenu [menu $brakebutton.menu -tearoff 0]
$brakebutton configure -menu $brakemenu
$brakemenu add command -label [msgcat::mc "Brake on"] -command {emc_brake on}
$brakemenu add command -label [msgcat::mc "Brake off"] -command {emc_brake off}

pack $brakebutton -side top -fill both -expand true

set abortbutton [button $commandbuttons.abort -text [msgcat::mc "ABORT"] -width 15 -height 3 -takefocus 0]

pack $abortbutton -side left -fill both -expand true

bind $abortbutton <ButtonPress-1> {tkemc_abort}
pack $abortbutton -side top -fill both -expand true

set toolsetting 0
set tooloffsetsetting 0.0000
set offsetsetting "X0.0000 Y0.0000 Z0.0000"
set unitsetting "custom"
set oldunitsetting $unitsetting

set settings [frame $top.settings]
pack $settings -side top -anchor w -pady 2m
set toollabel [label $settings.toollabel -text [msgcat::mc "Tool:"] -anchor w]
set toolsetting [label $settings.toolsetting -textvariable toolsetting -width 4 -anchor w]
set tooloffsetlabel [label $settings.tooloffsetlabel -text [msgcat::mc "Offset:"] -anchor w]
set tooloffsetsetting [label $settings.tooloffsetsetting -textvariable tooloffsetsetting -width 10 -anchor e]
set offsetlabel [label $settings.offsetlabel -text [msgcat::mc "Work Offsets:"] -anchor w]
set offsetsetting [label $settings.offsetsetting -textvariable offsetsetting -width 30 -anchor w]
set unitlabel [label $settings.unitlabel -textvariable unitsetting -width 6 -anchor e]

pack $toollabel -side left -padx 1m
pack $toolsetting -side left -padx 1m
pack $tooloffsetlabel -side left -padx 1m
pack $tooloffsetsetting -side left -padx 1m
pack $offsetlabel -side left -padx 1m
pack $offsetsetting -side left -padx 1m
pack $unitlabel -side left -padx 1m

# set up help for these
set_balloon $offsetlabel [offsethelp]
set_balloon $offsetsetting [offsethelp]

bind $tooloffsetlabel <ButtonPress-1> {popupToolOffset}
bind $tooloffsetsetting <ButtonPress-1> {popupToolOffset}
bind $tooloffsetlabel <ButtonPress-3> {popupToolOffset}
bind $tooloffsetsetting <ButtonPress-3> {popupToolOffset}

# jointworld can be joint or world
if {  [emc_kinematics_type] == 1 } {
    set jointworld "world"
    set poslabel0 $worldlabel0
    set poslabel1 $worldlabel1
    set poslabel2 $worldlabel2
    set poslabel3 $worldlabel3
    set poslabel4 $worldlabel4
    set poslabel5 $worldlabel5
    set poslabel6 $worldlabel6
    set poslabel7 $worldlabel7
    set poslabel8 $worldlabel8
} else {
    set jointworld "joint"
    set poslabel0 $jointlabel0
    set poslabel1 $jointlabel1
    set poslabel2 $jointlabel2
    set poslabel3 $jointlabel3
    set poslabel4 $jointlabel4
    set poslabel5 $jointlabel5
    set poslabel6 $jointlabel6
    set poslabel7 $jointlabel7
    set poslabel8 $jointlabel8
}    

# process ini file settings for jog speed -- angular and linear
# use TRAJ settings only
set vitems "DEFAULT_VELOCITY DEFAULT_ANGULAR_VELOCITY DEFAULT_LINEAR_VELOCITY\
                MAX_VELOCITY     MAX_ANGULAR_VELOCITY     MAX_LINEAR_VELOCITY"
foreach item $vitems {
  set temp [emc_ini "$item" "TRAJ"]
  if {"$temp" != ""} {set tempini($item) $temp}
}      
if [info exists tempini(DEFAULT_LINEAR_VELOCITY)] {
  set temp     $tempini(DEFAULT_LINEAR_VELOCITY)
} elseif [info exists tempini(DEFAULT_VELOCITY)] {
  set temp           $tempini(DEFAULT_VELOCITY)
} else {
  set temp 1
}
set ::linearJogSpeed [expr int($temp * 60 + 0.5)] ;# units/minute

if [info exists tempini(MAX_LINEAR_VELOCITY)] {
  set temp     $tempini(MAX_LINEAR_VELOCITY)
} elseif [info exists tempini(MAX_VELOCITY)] {
  set temp           $tempini(MAX_VELOCITY)
} else {
  set temp 1
}
set ::linearJogSpeedMax [expr int($temp * 60 + 0.5)] ;# units/minute

if [info exists tempini(DEFAULT_ANGULAR_VELOCITY)] {
  set temp     $tempini(DEFAULT_ANGULAR_VELOCITY)
  set ::angularJogSpeed [expr {int($temp * 60 + 0.5)}] ;# units/minute
}
# no angular jog slider if no DEFAULT_ANGULAR_VELOCITY
if [info exists ::angularJogSpeed] {
  if [info exists tempini(MAX_ANGULAR_VELOCITY)] {
    set temp     $tempini(MAX_ANGULAR_VELOCITY)
    set ::angularJogSpeedMax [expr {int($temp * 60 + 0.5)}] ;# units/minute
  } else {
    set ::angularJogSpeedMax $::angularJogSpeed
  }
}

foreach axis {0 1 2 3 4 5 6 7 8} {
  set temp [emc_ini "TYPE" "AXIS_$axis"]
  switch $temp {
    LINEAR  {set ::jogAxisType($axis) linear}
    ANGULAR {
      if [info exists ::angularJogSpeed] {
        set ::jogAxisType($axis) angular
      } else {
        # insufficient information to jog:
        set ::jogAxisType($axis) undefined
      }
    }
  }
}
unset vitems tempini ;# remove clutter

set jogType continuous
set jogIncrement 0.0010

set move [frame $top.move]
set position [frame $move.position]
set pos0 [frame $position.pos0 -borderwidth 4]
set pos1 [frame $position.pos1 -borderwidth 4]
set pos2 [frame $position.pos2 -borderwidth 4]
set pos3 [frame $position.pos3 -borderwidth 4]
set pos4 [frame $position.pos4 -borderwidth 4]
set pos5 [frame $position.pos5 -borderwidth 4]
set pos6 [frame $position.pos6 -borderwidth 4]
set pos7 [frame $position.pos7 -borderwidth 4]
{'fraction_non_alphanumeric': 0.10895526393473419, 'fraction_numerical': 0.012800901698736012, 'mean_word_length': 3.477171692899195, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 68, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7608102', 'n_tokens_mistral': 25540, 'n_tokens_neox': 24516, 'n_words': 8039}