summaryrefslogtreecommitdiff
path: root/lib/rightpanel
diff options
context:
space:
mode:
authorAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
committerAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
commit5b8466f7fae0e071c0f4eda13051c93313910028 (patch)
tree7061957f770e5e245ba00666dad912a2d44e7fdc /lib/rightpanel
Import Upstream version 1.3.7
Diffstat (limited to 'lib/rightpanel')
-rwxr-xr-xlib/rightpanel/hwmanager.tcl419
-rwxr-xr-xlib/rightpanel/instructiondetails.tcl1755
-rwxr-xr-xlib/rightpanel/regwatches.tcl2120
-rwxr-xr-xlib/rightpanel/rightpanel.tcl2273
-rwxr-xr-xlib/rightpanel/subprograms.tcl704
5 files changed, 7271 insertions, 0 deletions
diff --git a/lib/rightpanel/hwmanager.tcl b/lib/rightpanel/hwmanager.tcl
new file mode 100755
index 0000000..0e27941
--- /dev/null
+++ b/lib/rightpanel/hwmanager.tcl
@@ -0,0 +1,419 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Provides panel for managing hardware plugins (e.g. Programmer, ICD, etc.)
+# --------------------------------------------------------------------------
+
+class HwManager {
+ ## COMMON
+ common PLUGIN_SEARCH_PATHS {
+ ../hwplugins
+ /usr/share/mcu8051ide/hwplugins
+ /usr/local/share/mcu8051ide/hwplugins
+ }
+ common inst_plg_count 0 ;# Int: Number of installed plugins
+
+ ## PRIVATE
+ private variable parent ;# Widget: parent widget
+ private variable gui_initialized 0 ;# Bool: GUI initialized
+
+ private variable main_frame ;# Widget: Main frame
+ private variable pagesmanager ;# Widget: Pages manager for plugins GUI
+ private variable plg_combobox ;# Widget: Plugin selection combobox
+ private variable plg_refresh_but ;# Widget: Button "Refresh avaliable plugins"
+ private variable ins_plugin_namespaces {} ;# List of Strings: Namespaces of installed (initialized) plugins
+ private variable ins_plugin_names {} ;# List of Strings: Names of installed (initialized) plugins
+ private variable avl_plugin_files {} ;# List of Strings: Full filenames of avaliable plugins
+ private variable avl_plugin_names {} ;# List of Strings: Names of avaliable plugins
+
+ # List: Configuraion list of this panel (for session management)
+ private variable local_config [lindex $::CONFIG(HW_MANAGER_CONFIG) 0]
+ # List: Names of plugins with saved configuration (for session management)
+ private variable plugin_config_0 [lindex $::CONFIG(HW_MANAGER_CONFIG) 1]
+ # List: Configuration lists for plugins with saved configuration (for session management)
+ private variable plugin_config_1 [lindex $::CONFIG(HW_MANAGER_CONFIG) 2]
+
+
+ constructor {} {
+ }
+
+ destructor {
+ # Order all plugins to free their resources
+ hw_man_kill_childern
+ }
+
+ ## Kill all child processes
+ # @return void
+ public method hw_man_kill_childern {} {
+ foreach ns $ins_plugin_namespaces name $ins_plugin_names {
+
+ if {[catch {
+ ${ns}::dispose
+ }]} {
+ plugin_error $name $ns
+ }
+ }
+ }
+
+ ## Prepare this panel for initialization of its GUI
+ # MUST BE called before "CreateHwManagerGUI"
+ # @parm Widget _parent - Frame where this panel would be created
+ # @return void
+ public method PrepareHwManager {_parent} {
+ set parent $_parent
+ set gui_initialized 0
+ }
+
+ ## Finalize initialization of this panel
+ # @return void
+ public method CreateHwManagerGUI {} {
+ if {$gui_initialized} {return}
+ set gui_initialized 1
+
+ # Create main GUI parts
+ set main_frame [frame $parent.main_frame]
+ set top_frame [frame $main_frame.top]
+ set pagesmanager [PagesManager $main_frame.pagesmanager -background {#eeeeee}]
+
+ ## Create parts of top panel
+ # Label "HW"
+ pack [label $top_frame.plg_label \
+ -text [mc "HW:"] \
+ ] -side left
+ # Combobox of avaliable/installed plugins
+ set plg_combobox [ttk::combobox $top_frame.plg_cbbox \
+ -exportselection 1 \
+ -width 0 \
+ -state readonly \
+ ]
+ DynamicHelp::add $plg_combobox -text [mc "List avaliable or installed HW plugins"]
+ bind $plg_combobox <<ComboboxSelected>> "$this hw_manager_plg_cbs"
+ pack $plg_combobox -fill x -expand 1 -side left
+ setStatusTip -widget $plg_combobox -text [mc "Avaliable/installed plugins"]
+ # Button "Refresh"
+ set plg_refresh_but [ttk::button $top_frame.plg_refresh_but \
+ -image ::ICONS::16::reload \
+ -command "$this hw_manager_refresh_plugins" \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $top_frame.plg_refresh_but \
+ -text [mc "Refresh list avaliable or installed HW plugins"]
+ pack $plg_refresh_but -side left
+ setStatusTip -widget $plg_refresh_but -text [mc "Refresh"]
+ # Fill in the combobox
+ hw_manager_refresh_plugins
+
+ # Show GUI of the plugin from the last session
+ set idx [lsearch -ascii -exact [$plg_combobox cget -values] [lindex $local_config 0]]
+ if {$idx != -1} {
+ $plg_combobox current $idx
+ hw_manager_plg_cbs
+ }
+
+ # Pack top frame, create separator and pack the pages manager
+ pack $top_frame -fill x
+ pack [ttk::separator $main_frame.sep \
+ -orient horizontal \
+ ] -fill x -pady 5
+ pack $pagesmanager -fill both -expand 1
+ pack $main_frame -fill both -expand 1
+ }
+
+ ## Refresh list avaliable or installed HW plugins
+ # @return void
+ public method hw_manager_refresh_plugins {} {
+ if {!$gui_initialized} {CreateHwManagerGUI}
+ if {${::CLI_OPTION(no-plugins)}} {return}
+
+ set avl_plugin_files [list]
+ set avl_plugin_names [list]
+
+ # Search for avaliable plugins
+ foreach dir $PLUGIN_SEARCH_PATHS {
+ set dir [file join ${::LIB_DIRNAME} $dir]
+ catch { ;# For Microsoft Windows it has to be enclosed by catch
+ foreach file [glob -directory $dir -nocomplain -types f *.tcl] {
+ if {[lsearch -ascii -exact $avl_plugin_names [file tail [file rootname $file]]] != -1} {
+ continue
+ }
+ lappend avl_plugin_files $file
+ lappend avl_plugin_names [regsub -all {_} [file tail [file rootname $file]] { }]
+ }
+ }
+ }
+
+ # Adjust the combobox
+ $plg_combobox configure -values $avl_plugin_names
+ }
+
+ ## Switch plugin
+ # @parm String plugin_name - Plugin to switch to
+ # @return void
+ public method hw_manager_switch_plugin {plugin_name} {
+ if {!$gui_initialized} {CreateHwManagerGUI}
+ if {${::CLI_OPTION(no-plugins)}} {return}
+
+ # Install the plugin if it wasn't installed yet
+ if {[lsearch -ascii -exact $ins_plugin_names $plugin_name] == -1} {
+ # Check if the selected plugin is really avaliable
+ if {[lsearch -ascii -exact $avl_plugin_names $plugin_name] == -1} {
+ return
+ }
+
+ # Install the plugin (means initialize)
+ lappend ins_plugin_names $plugin_name
+ lappend ins_plugin_namespaces [ \
+ hw_manager_install_plugin $plugin_name [lindex \
+ $avl_plugin_files \
+ [lsearch -ascii -exact $avl_plugin_names $plugin_name] \
+ ]
+ ]
+ }
+
+ # Adjust the combobox of avaliable/installed plugins
+ $pagesmanager raise [regsub -all {\s} $plugin_name {_}]
+ }
+
+ ## "Change command" for the combobox of avaliable/installed plugins
+ # Switches the selected plugin
+ # @return void
+ public method hw_manager_plg_cbs {} {
+ if {!$gui_initialized} {CreateHwManagerGUI}
+ hw_manager_switch_plugin [$plg_combobox get]
+ }
+
+ ## Install plugin (means initialize)
+ # @parm String plugin_name - Plugin name
+ # @parm String file_path - Full path to the plugin main file
+ # @return String - Plugin namespace
+ public method hw_manager_install_plugin {plugin_name file_path} {
+ if {!$gui_initialized} {CreateHwManagerGUI}
+ if {${::CLI_OPTION(no-plugins)}} {return}
+ set plg_ns {}
+
+ if {[catch {
+ set frame [$pagesmanager add [regsub -all {\s} $plugin_name {_}]]
+ set plg_ns "::HwManager::plugin_ns::$inst_plg_count"
+ incr inst_plg_count
+
+ namespace eval $plg_ns "source {$file_path}"
+
+ set min_ide_ver [subst "\$${plg_ns}::MIN_IDE_VER"]
+ if {[package vcompare $min_ide_ver $::VERSION] == 1} {
+ tk_messageBox \
+ -title [mc "Too old version"] \
+ -type ok -icon warning \
+ -message [mc "Plugin %s requires MCU 8051 IDE version %s and above, please upgrade your MCU 8051 IDE" $plugin_name $min_ide_ver]
+ }
+
+ ${plg_ns}::init $frame $this $plg_ns [file dirname $file_path]
+
+ set idx [lsearch $plugin_config_0 $plugin_name]
+ if {$idx != -1} {
+ ${plg_ns}::restore_session [lindex $plugin_config_1 $idx]
+ }
+ }]} {
+ plugin_error $plugin_name $plg_ns
+ }
+
+ return $plg_ns
+ }
+
+ ## Handle plugin error and display error message
+ # @parm String plugin_name - Name of the plugin
+ # @parm String plugin_ns - Namespace of the plugin
+ # @return void
+ private method plugin_error {plugin_name plugin_ns} {
+
+ # Try to gain some informations about the crashed plugin
+ set plugin_ver {not defined}
+ set plugin_author {not defined}
+ set authors_email {not defined}
+ set err_info $::errorInfo
+ catch {set plugin_ver [subst "\$${plugin_ns}::P_VERSION"]}
+ catch {set plugin_author [subst "\$${plugin_ns}::AUTHOR"]}
+ catch {set authors_email [subst "\$${plugin_ns}::EMAIL"]}
+
+ # Print error message to stadrad error output
+ puts stderr "\n\n"
+ puts stderr [string repeat {=} 64]
+ puts stderr "PLUGIN ERROR:"
+ puts stderr [string repeat {-} 64]
+ puts stderr "Plugin name:\t$plugin_name"
+ puts stderr "Plugin version:\t$plugin_ver"
+ puts stderr "Author:\t\t$plugin_author <$authors_email>"
+ puts stderr [string repeat {-} 64]
+ puts stderr $err_info
+ puts stderr [string repeat {=} 64]
+ puts stderr "\n\n"
+
+ # Save log file
+ if {![catch {set log_file [open [file join ${::X::defaultDirectory} mcu8051ide_plugin_errors.log] a]}]} {
+ puts $log_file "\n\n"
+ puts $log_file [string repeat {=} 64]
+ puts $log_file "PLUGIN ERROR:"
+ puts $log_file [string repeat {-} 64]
+ puts $log_file "Plugin name:\t$plugin_name"
+ puts $log_file "Plugin version:\t$plugin_ver"
+ puts $log_file "Author:\t\t$plugin_author <$authors_email>"
+ puts $log_file [string repeat {-} 64]
+ puts $log_file $err_info
+ puts $log_file [string repeat {=} 64]
+ puts $log_file "\n\n"
+ close $log_file
+ }
+
+ # Display GUI error message
+ set dialog [toplevel .plugin_error -bg {#EEEEEE}]
+
+ # Create window frames
+ set main_dlg_frame [frame $dialog.main_frame]
+ set top_frame [frame $main_dlg_frame.top_frame -bg {#EE0000}]
+ set middle_frame [frame $main_dlg_frame.middle_frame]
+ set bottom_frame [frame $main_dlg_frame.bottom_frame]
+
+ # Create window header
+ pack [label $top_frame.header_lbl \
+ -text [mc "PLUGIN ERROR"] \
+ -bg {#EE0000} -fg {#FFFFFF} \
+ -font [font create \
+ -family helvetica \
+ -size -24 \
+ -weight bold \
+ ] \
+ ] -side left -fill x -expand 1
+
+ # Create error message text and scrollbar
+ pack [text $middle_frame.text \
+ -bg {white} -bd 0 \
+ -yscrollcommand "$middle_frame.scrollbar set" \
+ -width 0 -height 0 -relief flat -wrap word \
+ ] -side left -fill both -expand 1 -padx 5 -pady 5
+ bind $middle_frame.text <Button-1> {focus %W}
+ pack [ttk::scrollbar $middle_frame.scrollbar \
+ -orient vertical \
+ -command "$middle_frame.text yview" \
+ ] -fill y -side right
+
+ # Create button "Close"
+ pack [ttk::button $bottom_frame.ok \
+ -text [mc "Close"] \
+ -style GreenBg.TButton \
+ -command "
+ grab release $dialog
+ destroy $dialog
+ " \
+ ] -side right
+ focus -force $bottom_frame.ok
+
+ # Display error message
+ $middle_frame.text insert insert [mc "Plugin name:\t%s\n" $plugin_name]
+ $middle_frame.text insert insert [mc "Plugin version:\t%s\n" $plugin_ver]
+ $middle_frame.text insert insert [mc "Author:\t\t%s <%s>\n" $plugin_author $authors_email]
+ $middle_frame.text insert insert "\n"
+ $middle_frame.text insert insert $err_info
+ $middle_frame.text insert insert "\n"
+ $middle_frame.text configure -state disabled
+
+ # Pack window frames
+ pack $top_frame -fill x -anchor n
+ pack $middle_frame -fill both -expand 1
+ pack $bottom_frame -fill x
+ pack $main_dlg_frame -fill both -expand 1 -padx 5 -pady 5
+
+ # Configure dialog window
+ set x [expr {[winfo screenwidth $dialog] / 2 - 225}]
+ set y [expr {[winfo screenheight $dialog] / 2 - 125}]
+ wm iconphoto $dialog ::ICONS::16::bug
+ wm title $dialog [mc "PLUGIN ERROR - MCU 8051 IDE"]
+ wm minsize $dialog 450 250
+ wm geometry $dialog =550x250+$x+$y
+ wm protocol $dialog WM_DELETE_WINDOW "
+ grab release $dialog
+ destroy $dialog"
+ update
+ raise $dialog
+ grab $dialog
+ wm transient $dialog .
+ tkwait window $dialog
+ }
+
+ ## Ask all plugins wheather they are ready for exit
+ # @return Bool - 1 == Exit allowed; 0 == Exit DENIED
+ public method hw_manager_comfirm_exit {} {
+ if {!$gui_initialized} {return 1}
+
+ foreach plg_name $ins_plugin_names plg_ns $ins_plugin_namespaces {
+ set busy_flag 0
+ catch {
+ set busy_flag [${plg_ns}::is_busy]
+ }
+ if {$busy_flag} {
+ if {[tk_messageBox \
+ -parent . \
+ -type yesno \
+ -icon question \
+ -title [mc "Hardware is busy"] \
+ -message [mc "Plugin \"%s\" is busy.\nDo you really want to close the program ?" $plg_name]
+ ] != {yes}} {
+ return 0
+ }
+ }
+ }
+
+ return 1
+ }
+
+ ## Get configuration list for this panel (intented for sessions management)
+ # @return void
+ public method hw_manager_get_cfg {} {
+ if {!$gui_initialized} {
+ return [list $local_config $plugin_config_0 $plugin_config_1]
+ }
+
+ set local_config {}
+ set plugin_config_0 {}
+ set plugin_config_1 {}
+
+ # Get panel configuration
+ lappend local_config [$plg_combobox get]
+
+ # Get plugins configuration
+ foreach plg_name $ins_plugin_names plg_ns $ins_plugin_namespaces {
+ set idx [lsearch -ascii -exact $plugin_config_0 $plg_name]
+
+ set config [${plg_ns}::save_session]
+
+ if {$idx == -1} {
+ lappend plugin_config_0 $plg_name
+ lappend plugin_config_1 $config
+ } {
+ lset plugin_config_1 $idx $config
+ }
+ }
+
+ return [list $local_config $plugin_config_0 $plugin_config_1]
+ }
+}
diff --git a/lib/rightpanel/instructiondetails.tcl b/lib/rightpanel/instructiondetails.tcl
new file mode 100755
index 0000000..0c7efaf
--- /dev/null
+++ b/lib/rightpanel/instructiondetails.tcl
@@ -0,0 +1,1755 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Implements tab "Instruction details" on the Right Panel
+# --------------------------------------------------------------------------
+
+class InstructionDetails {
+
+ ## COMMON
+ # Conter of instances
+ common count 0
+ # Font for instruction details
+ common instruction_font [font create -size -12 -family $::DEFAULT_FIXED_FONT]
+ ## Highlighting tags for instruction details
+ # {
+ # {tag_name foreground_color ?bold_or_italic?}
+ # ...
+ # }
+ common instruction_tags {
+ {tag_code8 #00AA00 0}
+ {tag_code11 #00AA33 0}
+ {tag_code16 #00AA55 0}
+ {tag_imm8 #FF0000 0}
+ {tag_imm16 #FF0055 0}
+ {tag_data #88DD00 0}
+ {tag_bit #555588 0}
+ {tag_DPTR #0000FF 1}
+ {tag_A #3300DD 1}
+ {tag_AB #8800FF 1}
+ {tag_SFR #0000FF 1}
+ {tag_indr #FF0000 1}
+ {tag_1 #00DD00}
+ {tag_2 #AAAA00}
+ {tag_3 #FF0000}
+ {tag_4 #8800FF}
+ {tag_5 #0000FF}
+ }
+
+ ## Detail description of each directive
+ # Format: {
+ # {directive} {description}
+ # {directive} {description}
+ # {directive} {description}
+ # . .
+ # . .
+ # . .
+ # }
+ common HELP_FOR_DIRECTIVES {}
+ common HELP_FOR_DIRECTIVES_RAW {
+ elseif {Conditional assembly\n\nSyntax:\n ELSEIF <expr>\n\nExample:\n IF(2 * 4 - CND)\n MOV A, #20h\n ELSEIF SOMETHING_ELSE\n MOV A, #40h\n ENDIF\n\nNote:\n Supported by ASEM-51 only}
+ ifn {IF Not, conditional assembly\n\nSyntax:\n IFN <expr>\n\nExample:\n IF(2 * 4 - CND)\n MOV A, #20h\n ELSE\n MOV A, #40h\n ENDIF\n\n}
+ elseifn {ELSE IF Not\n\nSyntax:\n ELSEIFN <expr>\n\nExample:\n IF(2 * 4 - CND)\n MOV A, #20h\n ELSEIFN SOMETHING_ELSE\n MOV A, #40h\n ENDIF\n\nNote:\n Supported by ASEM-51 only}
+ ifdef {IF DEFined\n\nSyntax:\n IFDEF <symbol>\n\nExample:\n IFDEF CND\n MOV A, #20h\n ELSE\n MOV A, #40h\n ENDIF\n\n}
+ elseifdef {ELSE IF DEFined\n\nSyntax:\n ELSEIFDEF <symbol>\n\nExample:\n IFDEF(2 * 4 - CND)\n MOV A, #20h\n ELSEIFDEF SOMETHING_ELSE\n MOV A, #40h\n ENDIF\n\nNote:\n Supported by ASEM-51 only}
+ ifndef {IF Not DEFined\n\nSyntax:\n IFNDEF <symbol>\n\nExample:\n IFNDEF CND\n MOV A, #20h\n ELSE\n MOV A, #40h\n ENDIF\n\n}
+ elseifndef {ELSE IF Not DEFined\n\nSyntax:\n ELSEIFNDEF <symbol>\n\nExample:\n IFDEF CND\n MOV A, #20h\n ELSEIFNDEF SOMETHING_ELSE\n MOV A, #40h\n ENDIF\n\nNote:\n Supported by ASEM-51 only}
+ ifb {IF Black\n\nSyntax:\n IFB <literal>\n\nExample:\n IFB <CND>\n MOV A, #20h\n ELSE\n MOV A, #40h\n ENDIF\n\nNote:\n Supported by ASEM-51 only}
+ elseifb {ELSE IF Black\n\nSyntax:\n ELSEIFB <literal>\n\nExample:\n IFB <CND>\n MOV A, #20h\n ELSEIFB <SOMETHING_ELSE>\n MOV A, #40h\n ENDIF\n\literal:\n Supported by ASEM-51 only}
+ ifnb {IF Not Black\n\nSyntax:\n IFNB <literal>\n\nExample:\n IFNB <CND>\n MOV A, #20h\n ELSE\n MOV A, #40h\n ENDIF\n\nNote:\n Supported by ASEM-51 only}
+ elseifnb {ELSE IF Not Black\n\nSyntax:\n ELSEIFNB <literal>\n\nExample:\n IFB <CND>\n MOV A, #20h\n ELSEIFNB <SOMETHING_ELSE>\n MOV A, #40h\n ENDIF\n\nNote:\n Supported by ASEM-51 only}
+ rept {REPeaT Macro\n\nSyntax:\n REPT <expr>\n\nExample:\n REPT 5\n NOP\n ENDM\n\n}
+ times {REPeaT Macro\n\nSyntax:\n TIMES <expr>\n\nExample:\n TIMES 5\n NOP\n ENDM\n\nNote:\n Supported by native assembler only}
+ name {define module NAME\n\nSyntax:\n NAME <name>\n\nExample:\n NAME my_2nd_program\n\nNote:\n Supported by ASEM-51 only}
+ if {Conditional assembly\n\nSyntax:\n IF <expr>\n\nExample:\n IF(2 * 4 - CND)\n MOV A, #20h\n ELSE\n MOV A, #40h\n ENDIF\n\n}
+ else {Conditional assembly\n\nSyntax:\n ELSE\n\nExample:\n IF(2 * 4 - CND)\n MOV A, #20h\n ELSE\n MOV A, #40h\n ENDIF\n\n}
+ endif {Conditional assembly\n\nSyntax:\n ENDIF\n\nExample:\n IF(2 * 4 - CND)\n MOV A, #20h\n ELSE\n MOV A, #40h\n ENDIF\n\n}
+ endm {END of Macro definition\n\nSyntax:\n ENDM\n\nExample:\n ABC MACRO\n MOV B, #12d\n ENDM\n\n}
+ end {END of the program\n\nSyntax:\n END\n\nExample:\n END\n\n}
+ exitm {premature end of macro expansion\n\nSyntax:\n EXITM\n\nExample:\n ABC MACRO\n MOV B, #12d\n EXITM\n NOP\n ENDM\n\n}
+ list {enable code LISTing\n\nSyntax:\n LIST\n\nExample:\n NOP\n NOLIST\n NOP\n NOP\n LIST\n NOP\n\n}
+ nolist {disabled code listing\n\nSyntax:\n NOLIST\n\nExample:\n NOP\n NOLIST\n NOP\n NOP\n LIST\n NOP\n\n}
+ dseg {switch to DATA segment \[at address\]\n\nSyntax:\n DSEG \[AT <expr>\]\n\nExample:\n DSEG at 20d\n\n}
+ iseg {switch to IDATA segment \[at address\]\n\nSyntax:\n ISEG \[AT <expr>\]\n\nExample:\n ISEG at 10d\n\n}
+ bseg {switch to BIT segment \[at address\]\n\nSyntax:\n BSEG \[AT <expr>\]\n\nExample:\n BSEG at 5d\n\n}
+ xseg {switch to XDATA segment \[at address\]\n\nSyntax:\n XSEG \[AT <expr>\]\n\nExample:\n XSEG at 30d\n\n}
+ cseg {switch to CODE segment \[at address\]\n\nSyntax:\n CSEG \[AT <expr>\]\n\nExample:\n CSEG at 40d\n\n}
+ flag {define a FLAG bit\n\nSyntax:\n <symbol> FLAG <expr>\n\nExample:\n F4 FLAG 16h\n\nNote:\n Deprecated directive. Consider directive BIT instead.}
+ skip {SKIP bytes in the code memory\n\nSyntax:\n SKIP <expr>\n\nExample:\n SKIP 5\n\n}
+ equ {EQUivalent\n\nSyntax:\n <symbol> EQU <expr>\n\nExample:\n ABC EQU R0\n XYZ EQU 4Eh+12\n\n}
+ bit {define BIT address\n\nSyntax:\n <symbol> BIT <expr>\n\nExample:\n ABC BIT P4.5\n\n}
+ set {SET numeric variable or variable register\n\nSyntax:\n <symbol> SET <expr>\n <symbol> SET <register>\n\nExample:\n ALPHA SET R0\N ALPHA SET 42*BETA\n\n}
+ code {define address in the CODE memory\n\nSyntax:\n <symbol> CODE <expr>\n\nExample:\n TBL CODE 600h\n\n}
+ data {define address in the DATA memory\n\nSyntax:\n <symbol> DATA <expr>\n\nExample:\n UIV DATA 20h\n\n}
+ idata {define address in the Internal DATA memory\n\nSyntax:\n <symbol> IDATA <expr>\n\nExample:\n UIV IDATA 20h\n\n}
+ xdata {define address in the External DATA memory\n\nSyntax:\n <symbol> XDATA <expr>\n\nExample:\n UIV XDATA 400h\n\n}
+ macro {MACRO definition\n\nSyntax:\n <macro> MACRO \[<arg0> \[,<arg1> ... \]\n\n\nExample:\n ABC MACRO X\n MOV X, #12d\n ENDM\n\n}
+ ds {Define Space\n\nSyntax:\n DS <expr>\n\nExample:\n DS 2+4\n\n}
+ dw {Define Words\n\nSyntax:\n DW <expr1> \[,<expr2> ... \]\n\nExample:\n DW 0,02009H,2009,4171\n\n}
+ db {Define Bytes\n\nSyntax:\n DB <expr1> \[,<expr2> ... \]\n\nExample:\n DB 24,'August',09,(2*8+24)/8\n\n}
+ dbit {Define BITs\n\nSyntax:\n DBIT <expr>\n\nExample:\n DBIT 4+2\n\n}
+ include {INCLUDE an external source code\n\nSyntax:\n INCLUDE <filename>\n\nExample:\n INCLUDE 'my file.asm'\n\n}
+ org {ORiGin of segment location\n\nSyntax:\n ORG <expr>\n\nExample:\n ORG 0Bh\n\n}
+ using {USING register banks\n\nSyntax:\n USING <expr>\n\nExample:\n USING 2\n\n}
+ byte {define BYTE address in the data memory\n\nSyntax:\n <symbol> BYTE <expr>\n\nExample:\n UIV BYTE 20h\n\nNote:\n Deprecated directive. Consider directive DATA instead.}
+
+ {$cond} {List full IFxx .. ENDIF\n\nSyntax:\n \$COND\n\nExample:\n \$COND\n\nNote:\n Supported by ASEM-51 only}
+ {$nocond} {Don't list lines in false branches\n\nSyntax:\n \$NOCOND\n\nExample:\n \$NOCOND\n\nNote:\n Supported by ASEM-51 only}
+ {$condonly} {List assembled lines only\n\nSyntax:\n \$CONDONLY\n\nExample:\n \$CONDONLY\n\nNote:\n Supported by ASEM-51 only}
+ {$date} {Inserts date string into page header\n\nSyntax:\n \$DATE(string)\n\nExample:\n \$DATE(1965-12-31)\n\n}
+ {$da} {Inserts date string into page header\n\nSyntax:\n \$DATE(string)\n\nExample:\n \$DATE(1965-12-31)\n\n}
+ {$debug} {Include debug information\n\nSyntax:\n \$DEBUG\n\nExample:\n \$DEBUG\n\nNote:\n Supported by ASEM-51 only}
+ {$db} {Include debug information\n\nSyntax:\n \$DB\n\nExample:\n \$DB\n\nNote:\n Supported by ASEM-51 only}
+ {$nodebug} {Don't include debug information\n\nSyntax:\n \$NODEBUG\n\nExample:\n \$NODEBUG\n\nNote:\n Supported by ASEM-51 only}
+ {$nodb} {Don't include debug information\n\nSyntax:\n \$NODB\n\nExample:\n \$NODB\n\nNote:\n Supported by ASEM-51 only}
+ {$eject} {Start a new page in list file\n\nSyntax:\n \$EJECT\n\nExample:\n \$EJECT\n\n}
+ {$ej} {Start a new page in list file\n\nSyntax:\n \$EJ\n\nExample:\n \$EJ\n\n}
+ {$error} {Force a user-defined error\n\nSyntax:\n \$ERROR(string)\n\nExample:\n \$ERROR(Impossible combination ...)\n\nNote:\n Supported by ASEM-51 only}
+ {$warning} {Force a user-defined warning\n\nSyntax:\n \$WARNING(string)\n\nExample:\n \$WARNING(Testing only !)\n\nNote:\n Supported by ASEM-51 only}
+ {$ge} {List macro calls and expansion lines\n\nSyntax:\n \$GE\n\nExample:\n \$GE\n\nNote:\n Supported by ASEM-51 only}
+ {$gen} {List macro calls and expansion lines\n\nSyntax:\n \$GEN\n\nExample:\n \$GEN\n\nNote:\n Supported by ASEM-51 only}
+ {$noge} {List macro calls only\n\nSyntax:\n \$NOGE\n\nExample:\n \$NOGE\n\nNote:\n Supported by ASEM-51 only}
+ {$nogen} {List macro calls only\n\nSyntax:\n \$NOGEN\n\nExample:\n \$NOGEN\n\nNote:\n Supported by ASEM-51 only}
+ {$go} {List expansion lines only\n\nSyntax:\n \$GO\n\nExample:\n \$GO\n\nNote:\n Supported by ASEM-51 only}
+ {$genonly} {List expansion lines only\n\nSyntax:\n \$GENONLY\n\nExample:\n \$GENONLY\n\nNote:\n Supported by ASEM-51 only}
+ {$include} {Include a source file\n\nSyntax:\n \$INCLUDE(string)\n\nExample:\n \$INCLUDE(somefile.asm)\n\n}
+ {$inc} {Include a source file\n\nSyntax:\n \$INC(string)\n\nExample:\n \$INC(somefile.asm)\n\n}
+ {$list} {List subsequent source lines\n\nSyntax:\n \$LIST\n\nExample:\n \$LIST\n\n}
+ {$li} {List subsequent source lines\n\nSyntax:\n \$LI\n\nExample:\n \$LI\n\n}
+ {$noli} {Don't list subsequent source lines\n\nSyntax:\n \$NOLI\n\nExample:\n \$NOLI\n\n}
+ {$nolist} {Don't list subsequent source lines\n\nSyntax:\n \$NOLIST\n\nExample:\n \$NOLIST\n\n}
+ {$macro} {Reserve n % of free memory for macros\n\nSyntax:\n \$MACRO(int)\n\nExample:\n \$MACRO(50)\n\nNote:\n Supported by ASEM-51 only}
+ {$mr} {Reserve n % of free memory for macros\n\nSyntax:\n \$MR(int)\n\nExample:\n \$MR(50)\n\nNote:\n Supported by ASEM-51 only}
+ {$nomr} {Reserve all for the symbol table\n\nSyntax:\n \$NOMR\n\nExample:\n \$NOMR\n\nNote:\n Supported by ASEM-51 only}
+ {$nomacro} {Reserve all for the symbol table\n\nSyntax:\n \$NOMACRO\n\nExample:\n \$NOMACRO\n\nNote:\n Supported by ASEM-51 only}
+ {$mod51} {Enable predefined SFR symbols\n\nSyntax:\n \$MOD51\n\nExample:\n \$MOD51\n\nNote:\n Supported by ASEM-51 only}
+ {$mo} {Enable predefined SFR symbols\n\nSyntax:\n \$MO\n\nExample:\n \$MO\n\nNote:\n Supported by ASEM-51 only}
+ {$nomod} {Disable predefined SFR symbols\n\nSyntax:\n \$NOMOD\n\nExample:\n \$NOMOD\n\n}
+ {$nomo} {Disable predefined SFR symbols\n\nSyntax:\n \$NOMO\n\nExample:\n \$NOMO\n\n}
+ {$nomod51} {Disable predefined SFR symbols\n\nSyntax:\n \$NOMOD51\n\nExample:\n \$NOMOD51\n\n}
+ {$nobuiltin} {Don't list predefined symbols\n\nSyntax:\n \$NOBUILTIN\n\nExample:\n \$NOBUILTIN\n\nNote:\n Supported by ASEM-51 only}
+ {$notabs} {Don't use tabs in list file\n\nSyntax:\n \$NOTABS\n\nExample:\n \$NOTABS\n\nNote:\n Supported by ASEM-51 only}
+ {$paging} {Enable listing page formatting\n\nSyntax:\n \$LIST\n\nExample:\n \$PAGING\n\n}
+ {$pi} {Enable listing page formatting\n\nSyntax:\n \$PI\n\nExample:\n \$PI\n\n}
+ {$nopi} {Disable listing page formatting\n\nSyntax:\n \$NOPI\n\nExample:\n \$NOPI\n\n}
+ {$nopaging} {Disable listing page formatting\n\nSyntax:\n \$NOPAGING\n\nExample:\n \$NOPAGING\n\n}
+ {$pagelength} {Set lines per page for listing\n\nSyntax:\n \$PAGELENGTH(int)\n\nExample:\n \$PAGELENGTH(64)\n\n}
+ {$pl} {Set lines per page for listing\n\nSyntax:\n \$PL(int)\n\nExample:\n \$PL(64)\n\n}
+ {$pagewidth} {Set columns per line for listing\n\nSyntax:\n \$PAGEWIDTH(int)\n\nExample:\n \$PAGEWIDTH(132)\n\n}
+ {$pw} {Set columns per line for listing\n\nSyntax:\n \$PW(int)\n\nExample:\n \$PW(132)\n\n}
+ {$philips} {Switch on 83C75x family support\n\nSyntax:\n \$PHILIPS\n\nExample:\n \$PHILIPS\n\nNote:\n Supported by ASEM-51 only}
+ {$save} {Save current \$LIST/\$GEN/\$COND\n\nSyntax:\n \$SAVE\n\nExample:\n \$SAVE\n\nNote:\n Supported by ASEM-51 only}
+ {$sa} {Save current \$LIST/\$GEN/\$COND\n\nSyntax:\n \$SA\n\nExample:\n \$SA\n\nNote:\n Supported by ASEM-51 only}
+ {$restore} {Restore old \$LIST/\$GEN/\$COND\n\nSyntax:\n \$RESTORE\n\nExample:\n \$RESTORE\n\nNote:\n Supported by ASEM-51 only}
+ {$rs} {Restore old \$LIST/\$GEN/\$COND\n\nSyntax:\n \$RS\n\nExample:\n \$RS\n\nNote:\n Supported by ASEM-51 only}
+ {$symbols} {Create symbol table\n\nSyntax:\n \$SYMBOLS\n\nExample:\n \$SYMBOLS\n\n}
+ {$sb} {Create symbol table\n\nSyntax:\n \$SB\n\nExample:\n \$SB\n\n}
+ {$nosymbols} {Don't create symbol table\n\nSyntax:\n \$NOSYMBOLS\n\nExample:\n \$NOSYMBOLS\n\n}
+ {$nosb} {Don't create symbol table\n\nSyntax:\n \$NOSB\n\nExample:\n \$NOSB\n\n}
+ {$title} {Inserts title string into page header\n\nSyntax:\n \$TITLE(string)\n\nExample:\n \$TITLE(My firts code)\n\n}
+ {$tt} {Inserts title string into page header\n\nSyntax:\n \$TT(string)\n\nExample:\n \$TT(My firts code)\n\n}
+ {$xref} {Create cross reference\n\nSyntax:\n \$XREF\n\nExample:\n \$XREF\n\nNote:\n Supported by ASEM-51 only}
+ {$xr} {Create cross reference\n\nSyntax:\n \$XR\n\nExample:\n \$XR\n\nNote:\n Supported by ASEM-51 only}
+ {$noxref} {Don't create cross reference\n\nSyntax:\n \$NOXREF\n\nExample:\n \$NOXREF\n\nNote:\n Supported by ASEM-51 only}
+ {$noxr} {Don't create cross reference\n\nSyntax:\n \$NOXR\n\nExample:\n \$NOXR\n\nNote:\n Supported by ASEM-51 only}
+ {$noobject} {Do not create Intel HEX file\n\nSyntax:\n \$NOOBJECT\n\nExample:\n \$NOOBJECT\n\nNote:\n Supported by native assembler only}
+ {$object} {Specify file name for Intel HEX\n\nSyntax:\n \$OBJECT(string)\n\nExample:\n \$OBJECT(my_hex.hex)\n\nNote:\n Supported by native assembler only}
+ {$print} {Specify file name for list file\n\nSyntax:\n \$PRINT(string)\n\nExample:\n \$PRINT(my_list.lst)\n\nNote:\n Supported by native assembler only}
+ {$noprint} {Do not create list file at all\n\nSyntax:\n \$NOPRINT\n\nExample:\n \$NOPRINT\n\nNote:\n Supported by native assembler only}
+ {$nomacrosfirst} {Define and expand macro instruction after! conditional assembly and definitions of constants\n\nSyntax:\n \$NOMACROSFIRTS\n\nExample:\n \$NOMACROSFIRTS\n\nNote:\n Supported by native assembler only}
+ }
+
+ ## Detail description of each instruction
+ # Format: {
+ # {INSTRUCTION OPR0, OPR1 ...} {
+ # {description}
+ # {class}
+ # {note}
+ # {affected flags in order: C OV AC, for instance "{0 X 1}"}
+ # }
+ # }
+ common INSTRUCTION_DESCRIPTION {
+ {ADD A, Rn} {
+ {Add register to Accumulator}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {ADD A, direct} {
+ {Add direct byte to Accumulator}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {ADD A, @Ri} {
+ {Add indirect RAM to Accumulator}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {ADD A, #data} {
+ {Add immediate data to Accumulator}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {ADDC A, Rn} {
+ {Add register to Accumulator with Carry}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {ADDC A, direct} {
+ {Add direct byte to Accumulator with Carry}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {ADDC A, @Ri} {
+ {Add indirect RAM to Accumulator with Carry}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {ADDC A, #data} {
+ {Add immediate data to Acc with Carry}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {SUBB A, Rn} {
+ {Subtract Register from Acc with borrow}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {SUBB A, direct} {
+ {Subtract direct byte from Acc with borrow}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {SUBB A, @Ri} {
+ {Subtract indirect RAM from ACC with borrow}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {SUBB A, #data} {
+ {Subtract immediate data from Acc with borrow}
+ {Arithmetic Operations}
+ {}
+ {X X X}
+ }
+ {INC A} {
+ {Increment Accumulator}
+ {Arithmetic Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {INC Rn} {
+ {Increment register}
+ {Arithmetic Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {INC direct} {
+ {Increment direct byte}
+ {Arithmetic Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {INC @Ri} {
+ {Increment direct RAM}
+ {Arithmetic Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {DEC A} {
+ {Decrement Accumulator}
+ {Arithmetic Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {DEC Rn} {
+ {Decrement Register}
+ {Arithmetic Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {DEC direct} {
+ {Decrement direct byte}
+ {Arithmetic Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {DEC @Ri} {
+ {Decrement indirect RAM}
+ {Arithmetic Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {INC DPTR} {
+ {Increment Data Pointer}
+ {Arithmetic Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {MUL AB} {
+ {Multiply A & B}
+ {Arithmetic Operations}
+ {}
+ {0 X {}}
+ }
+ {DIV AB} {
+ {Divide A by B}
+ {Arithmetic Operations}
+ {}
+ {0 X {}}
+ }
+ {DA A} {
+ {Decimal Adjust Accumulator}
+ {Arithmetic Operations}
+ {}
+ {X {} {}}
+ }
+
+
+ {ANL A, Rn} {
+ {AND Register to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ANL A, direct} {
+ {AND direct byte to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ANL A, @Ri} {
+ {AND indirect RAM to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ANL A, #data} {
+ {AND immediate data to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ANL direct, A} {
+ {AND Accumulator to direct byte}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ANL direct, #data} {
+ {AND immediate data to direct byte}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ORL A, Rn} {
+ {OR register to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ORL A, direct} {
+ {OR direct byte to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ORL A, @Ri} {
+ {OR indirect RAM to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ORL A, #data} {
+ {OR immediate data to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ORL direct, A} {
+ {OR Accumulator to direct byte}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {ORL direct, #data} {
+ {OR immediate data to direct byte}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {XRL A, Rn} {
+ {Exclusive-OR register to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {XRL A, direct} {
+ {Exclusive-OR direct byte to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {XRL A, @Ri} {
+ {Exclusive-OR indirect RAM to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {XRL A, #data} {
+ {Exclusive-OR immediate data to Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {XRL direct, A} {
+ {Exclusive-OR Accumulator to direct byte}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {XRL direct, #data} {
+ {Exclusive-OR immediate data to direct byte}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {CLR A} {
+ {Clear Accumulator}
+ {Logical Operations}
+ {}
+ {}
+ }
+ {CPL A} {
+ {Complement Accumulator}
+ {Logical Operations}
+ {Read-Modify-Write}
+ {}
+ }
+ {RL A} {
+ {Rotate Accumulator Left}
+ {Logical Operations}
+ {}
+ {}
+ }
+ {RLC A} {
+ {Rotate Accumulator Left through the Carry}
+ {Logical Operations}
+ {}
+ {X {} {}}
+ }
+ {RR A} {
+ {Rotate Accumulator Right}
+ {Logical Operations}
+ {}
+ {}
+ }
+ {RRC A} {
+ {Rotate Accumulator Right through the Carry}
+ {Logical Operations}
+ {}
+ {X {} {}}
+ }
+ {SWAP A} {
+ {Swap nibbles within the Accumulator}
+ {Logical Operations}
+ {}
+ {}
+ }
+
+
+
+ {MOV A, Rn} {
+ {Move register to Accumulator}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV A, direct} {
+ {Move direct byte to Accumulator}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV A, @Ri} {
+ {Move indirect RAM to Accumulator}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV A, #data} {
+ {Move immediate data to Accumulator}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV Rn, A} {
+ {Move Accumulator to register}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV Rn, direct} {
+ {Move direct byte to register}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV Rn, #data} {
+ {Move immediate data to register}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV direct, A} {
+ {Move Accumulator to direct byte}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV direct, Rn} {
+ {Move register to direct byte}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV direct, direct} {
+ {Move direct byte to direct}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV direct, @Ri} {
+ {Move indirect RAM to direct byte}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV direct, #data} {
+ {Move immediate data to direct byte}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV @Ri, A} {
+ {Move Accumulator to indirect RAM}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV @Ri, direct} {
+ {Move direct byte to indirect RAM}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV @Ri, #data} {
+ {Move immediate data to indirect RAM}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOV DPTR, #data16} {
+ {Load Data Pointer with a 16-bit constant}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOVC A, @A+DPTR} {
+ {Move Code byte relative to DPTR to Acc}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOVC A, @A+PC} {
+ {Move Code byte relative to PC to Acc}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOVX A, @Ri} {
+ {Move External RAM (8-bit addr) to Acc}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOVX A, @DPTR} {
+ {Move Exernal RAM (16-bit addr) to Acc}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOVX @Ri, A} {
+ {Move Acc to External RAM (8-bit addr)}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {MOVX @DPTR, A} {
+ {Move Acc to External RAM (16-bit addr)}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {PUSH direct} {
+ {Push direct byte onto stack}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {POP direct} {
+ {Pop direct byte from stack}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {XCH A, Rn} {
+ {Exchange register with Accumulator}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {XCH A, direct} {
+ {Exchange direct byte with Accumulator}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {XCH A, @Ri} {
+ {Exchange indirect RAM with Accumulator}
+ {Data Transfer}
+ {}
+ {}
+ }
+ {XCHD A, @Ri} {
+ {Exchange low-order Digit indirect RAM with Acc}
+ {Data Transfer}
+ {}
+ {}
+ }
+
+
+ {CLR C} {
+ {Clear Carry}
+ {Boolean Variable Manipulation}
+ {}
+ {0 {} {}}
+ }
+ {CLR bit} {
+ {Clear direct bit}
+ {Boolean Variable Manipulation}
+ {Read-Modify-Write}
+ {}
+ }
+ {SETB C} {
+ {Set Carry}
+ {Boolean Variable Manipulation}
+ {}
+ {1 {} {}}
+ }
+ {SETB bit} {
+ {Set direct bit}
+ {Boolean Variable Manipulation}
+ {Read-Modify-Write}
+ {}
+ }
+ {CPL C} {
+ {Complement Carry}
+ {Boolean Variable Manipulation}
+ {Read-Modify-Write}
+ {X {} {}}
+ }
+ {CPL bit} {
+ {Complement direct bit}
+ {Boolean Variable Manipulation}
+ {Read-Modify-Write}
+ {}
+ }
+ {ANL C, bit} {
+ {AND direct bit to CARRY}
+ {Boolean Variable Manipulation}
+ {Read-Modify-Write}
+ {X {} {}}
+ }
+ {ANL C, /bit} {
+ {AND complement of direct bit to Carry}
+ {Boolean Variable Manipulation}
+ {Read-Modify-Write}
+ {X {} {}}
+ }
+ {ORL C, bit} {
+ {OR direct bit to Carry}
+ {Boolean Variable Manipulation}
+ {}
+ {X {} {}}
+ }
+ {ORL C, /bit} {
+ {OR complement of direct bit to Carry}
+ {Boolean Variable Manipulation}
+ {}
+ {X {} {}}
+ }
+ {MOV C, bit} {
+ {Move direct bit to Carry}
+ {Boolean Variable Manipulation}
+ {}
+ {X {} {}}
+ }
+ {MOV bit, C} {
+ {Move Carry to direct bit}
+ {Boolean Variable Manipulation}
+ {Read-Modify-Write}
+ {}
+ }
+ {JC rel} {
+ {Jump if Carry is set}
+ {Boolean Variable Manipulation}
+ {}
+ {}
+ }
+ {JNC rel} {
+ {Jump if Carry not set}
+ {Boolean Variable Manipulation}
+ {}
+ {}
+ }
+ {JB bit, rel} {
+ {Jump if direct Bit is set}
+ {Boolean Variable Manipulation}
+ {}
+ {}
+ }
+ {JNB bit, rel} {
+ {Jump if direct Bit is Not set}
+ {Boolean Variable Manipulation}
+ {}
+ {}
+ }
+ {JBC bit, rel} {
+ {Jump if direct Bit is set & clear bit}
+ {Boolean Variable Manipulation}
+ {Read-Modify-Write}
+ {}
+ }
+
+
+ {ACALL addr11} {
+ {Absolute Subroutine Call}
+ {Program Branching}
+ {}
+ {}
+ }
+ {LCALL addr16} {
+ {Long Subroutine Call}
+ {Program Branching}
+ {}
+ {}
+ }
+ {RET } {
+ {Return from Subroutine}
+ {Program Branching}
+ {}
+ {}
+ }
+ {RETI } {
+ {Return from interrupt}
+ {Program Branching}
+ {}
+ {}
+ }
+ {AJMP addr11} {
+ {Absolute Jump}
+ {Program Branching}
+ {}
+ {}
+ }
+ {LJMP addr16} {
+ {Long Jump}
+ {Program Branching}
+ {}
+ {}
+ }
+ {SJMP rel} {
+ {Short Jump (relative addr)}
+ {Program Branching}
+ {}
+ {}
+ }
+ {JMP @A+DPTR} {
+ {Jump indirect relative to the DPTR}
+ {Program Branching}
+ {}
+ {}
+ }
+ {JZ rel} {
+ {Jump if Accumulator is Zero}
+ {Program Branching}
+ {}
+ {}
+ }
+ {JNZ rel} {
+ {Jump if Accumulator is Not Zero}
+ {Program Branching}
+ {}
+ {}
+ }
+ {CJNE A, direct, rel} {
+ {Compare direct byte to Acc and Jump if Not Equal}
+ {Program Branching}
+ {}
+ {X {} {}}
+ }
+ {CJNE A, #data, rel} {
+ {Compare immediate to Acc and Jump if Not Equal}
+ {Program Branching}
+ {}
+ {X {} {}}
+ }
+ {CJNE Rn, #data, rel} {
+ {Compare immediate to register and Jump if Not Equal}
+ {Program Branching}
+ {}
+ {X {} {}}
+ }
+ {CJNE @Ri, #data, rel} {
+ {Compare immediate to indirect and Jump if Not Equal}
+ {Program Branching}
+ {}
+ {X {} {}}
+ }
+ {DJNZ Rn, rel} {
+ {Decrement register and Jump if Not Zero}
+ {Program Branching}
+ {Read-Modify-Write}
+ {}
+ }
+ {DJNZ direct, rel} {
+ {Decrement direct byte and Jump if Not Zero}
+ {Program Branching}
+ {Read-Modify-Write}
+ {}
+ }
+ {NOP } {
+ {No Operation}
+ {Program Branching}
+ {}
+ {}
+ }
+ }
+
+ ## PRIVATE
+ private variable instruction_text {} ;# Widget: ID of text widget of tab "Instruction details"
+ private variable instruction_menu ;# Widget: Popup menu for the text widget
+ private variable instruction_label ;# Widget: ID of label above instruction details
+ private variable header_text ;# Widget: Text header
+ private variable instruction_last {} ;# String: Last instruction shown in details window
+ private variable parent {} ;# Widget: GUI parent
+ private variable gui_initialized 0 ;# Bool: GUI initialized
+ private variable gui_preparing 0 ;# Bool: Prearing panel GUI
+ private variable enabled 0 ;# Bool: enable procedures which are needless while loading project
+
+ private variable help_win_index 0 ;# Int: Index of help window object (just some number)
+ private variable ins_help_win_enabled 1 ;# Bool: Enable instruction help window
+ private variable ins_help_win_created 0 ;# Bool: Help window widgets are ready to be mapped by geometry manager
+ private variable ins_help_win_visible 0 ;# Bool: Flag help window visible
+ private variable ins_help_window {} ;# Widget: Help window itself
+ private variable help_win_title ;# Widget: Title label (should contain instruction name and operands)
+ ## Array of Widgets: Labels containing certain information
+ # Avaliable keys are: description, length, execution_time, opcode, note and class
+ private variable help_win_labels
+
+ constructor {} {
+ incr count
+ }
+
+ destructor {
+ }
+
+ ## Prepare object for creating its GUI
+ # @parm Widget _parent - GUI parent widget
+ # @return void
+ public method PrepareInstructionDetails {_parent} {
+ set parent $_parent
+ set gui_initialized 0
+ }
+
+ ## Create GUI of tab "Instruction details"
+ # @return void
+ public method CreateInstructionDetailsGUI {} {
+ if {$gui_initialized || $gui_preparing || ${::Editor::editor_to_use}} {return}
+ set gui_preparing 1
+
+ # Create frames
+ set body_frame [frame $parent.frm_rightPanel_instruction_body]
+ set text_frame [frame $body_frame.frm_rightPanel_instruction_txt -bd 1 -relief sunken]
+ set header_frame [frame $parent.frm_rightPanel_instruction_header]
+
+ # Button "Show legend"
+ set button [ttk::button \
+ $header_frame.but_rightPanel_instruction_legend \
+ -image ::ICONS::16::help \
+ -style Flat.TButton \
+ -command "$this rightPanel_ins_legend" \
+ ]
+ DynamicHelp::add $header_frame.but_rightPanel_instruction_legend \
+ -text [mc "Show legend"]
+ pack $button -side right -fill none -expand 0
+ setStatusTip -widget $button -text [mc "Show legend"]
+
+ # Tab header (instruction name)
+ set instruction_label [label $header_frame.lbl_rightPanel_instruction_header \
+ -fg {#0000FF} \
+ -anchor w \
+ -padx {20px} \
+ -font [font create -weight {bold} -size -17 -family $::DEFAULT_FIXED_FONT] \
+ ]
+ pack $instruction_label -side left -fill x -expand 1
+ setStatusTip -widget $instruction_label -text [mc "Instruction name"]
+
+ # Create popup menu for instruction text and its header
+ set instruction_menu [menu $text_frame.popup_menu -tearoff 0]
+ $instruction_menu add command -label "Configure" -compound left \
+ -command {::configDialogs::rightPanel::mkDialog 1} \
+ -underline 0 -image ::ICONS::16::configure
+
+ # Text header
+ set header_text [text $text_frame.txt_rightPanel_instruction_hdr \
+ -cursor left_ptr \
+ -font $instruction_font \
+ -bg {#DDDDDD} \
+ -height 1 \
+ -bd 0 \
+ -exportselection 0 \
+ ]
+ bind $header_text <ButtonRelease-3> "tk_popup $instruction_menu %X %Y; break"
+ bind $header_text <Key-Menu> "tk_popup $instruction_menu %X %Y; break"
+ bindtags $header_text $header_text
+
+ # Instruction details text
+ set instruction_text [text $text_frame.txt_rightPanel_instruction \
+ -yscrollcommand "$body_frame.src_rightPanel_instruction set" \
+ -cursor left_ptr -state disabled -wrap word \
+ -font $instruction_font -bd 0 -exportselection 0 \
+ ]
+ # Create scrollbar
+ pack [ttk::scrollbar $body_frame.src_rightPanel_instruction \
+ -orient vertical -command "$instruction_text yview" \
+ ] -side right -fill y
+
+ setStatusTip -widget $instruction_text -text [mc "Instruction operands"]
+ bind $instruction_text <ButtonRelease-3> "tk_popup $instruction_menu %X %Y; break"
+ bind $instruction_text <Key-Menu> "tk_popup $instruction_menu %X %Y; break"
+ bind $instruction_text <<Selection>> {false_selection %W}
+ bind $instruction_text <Motion> "$this rightPanel_ins_text_motion %x %y %X %Y"
+ bind $instruction_text <Leave> "+$this rightPanel_ins_hide_ins_help_window"
+
+ $instruction_text delete 1.0 end
+ $instruction_text tag configure tag_sel -background #CCCCFF
+ $instruction_text tag configure tag_sel0 -background #E0FFE0
+ rightPanel_refresh_instruction_highlighting
+ $instruction_text tag configure tag_bold -font [font create \
+ -size -12 -family $::DEFAULT_FIXED_FONT -weight {bold}]
+
+ # Pack parts of text frame (Instruction details text, Text header)
+ pack $header_text -side top -fill x
+ pack $instruction_text -side bottom -fill both -expand 1
+ pack $text_frame -side left -fill both -expand 1
+
+ # Pack all remaining frames
+ pack $header_frame -side top -fill x
+ pack $body_frame -side bottom -fill both -expand 1
+
+ set gui_initialized 1
+ }
+
+ ## Invoke legend window for "Instruction details"
+ # @return void
+ public method rightPanel_ins_legend {} {
+ # Destroy legend window
+ if {[winfo exists .rightPanel_legend]} {
+ grab release .rightPanel_legend
+ destroy .rightPanel_legend
+ return
+ }
+ set x [expr {[winfo pointerx .] - 380}]
+ set y [winfo pointery .]
+
+ # Create legend window
+ set win [toplevel .rightPanel_legend -class {Help} -bg {#EEEEEE}]
+ set frame [frame $win.f -bg {#555555} -bd 0 -padx 1 -pady 1]
+ wm overrideredirect $win 1
+
+ # Click to close
+ bind $win <Button-1> "grab release $win; destroy $win"
+
+ # Create header "-- click to close --"
+ pack [label $frame.lbl_header \
+ -text [mc "-- click to close --"] \
+ -bg {#FFFF55} -font $::smallfont\
+ -fg {#000000} -anchor c \
+ ] -side top -anchor c -fill x
+
+ # Create text widget
+ set text [text $frame.text \
+ -bg {#FFFFCC} \
+ -exportselection 0 \
+ -takefocus 0 \
+ -cursor left_ptr \
+ -bd 0 -relief flat \
+ ]
+
+ pack $frame -fill both -expand 1
+
+ # Create text tags
+ $this right_panel_create_highlighting_tags $text $instruction_tags 0
+ $text tag configure tag_sel \
+ -relief raised \
+ -borderwidth 1 \
+ -background #F8F8F8
+ $text tag configure tag_desc
+
+ ## Fill text widget
+ # "code8"
+ set idx [$text index insert]
+ $text insert end [mc "code8"]
+ $text tag add tag_code8 $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\t8 bit offset for relative jump\n"]
+ $text tag add tag_desc $idx insert
+ # "code11"
+ set idx [$text index insert]
+ $text insert end [mc "code11"]
+ $text tag add tag_code11 $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\t11 bit program memory address\n"]
+ $text tag add tag_desc $idx insert
+ # "code16"
+ set idx [$text index insert]
+ $text insert end [mc "code16"]
+ $text tag add tag_code16 $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\t16 bit program memory address\n"]
+ $text tag add tag_desc $idx insert
+ # "imm8"
+ set idx [$text index insert]
+ $text insert end [mc "imm8"]
+ $text tag add tag_imm8 $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\t8 bit constant data\n"]
+ $text tag add tag_desc $idx insert
+ # "imm16"
+ set idx [$text index insert]
+ $text insert end [mc "imm16"]
+ $text tag add tag_imm16 $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\t16 bit constant data\n"]
+ $text tag add tag_desc $idx insert
+ # "data"
+ set idx [$text index insert]
+ $text insert end [mc "data"]
+ $text tag add tag_data $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\tinternal data memory or SFR direct address\n"]
+ $text tag add tag_desc $idx insert
+ # "bit"
+ set idx [$text index insert]
+ $text insert end [mc "bit"]
+ $text tag add tag_bit $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\tbit memory direct address\n"]
+ $text tag add tag_desc $idx insert
+
+ $text insert end "\n"
+ # "DPTR"
+ set idx [$text index insert]
+ $text insert end "DPTR"
+ $text tag add tag_DPTR $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\tData PoinTeR register (16 bit)\n"]
+ $text tag add tag_desc $idx insert
+ # "A"
+ set idx [$text index insert]
+ $text insert end "A"
+ $text tag add tag_A $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\tPrimary work register\n"]
+ $text tag add tag_desc $idx insert
+ # "AB"
+ set idx [$text index insert]
+ $text insert end "AB"
+ $text tag add tag_AB $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\tAccumulator\n"]
+ $text tag add tag_desc $idx insert
+
+ $text insert end "\n"
+ # "R0..R7"
+ set idx [$text index insert]
+ $text insert end "R0..R7"
+ $text tag add tag_SFR $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\tRegisters of active bank\n"]
+ $text tag add tag_desc $idx insert
+ # "C"
+ set idx [$text index insert]
+ $text insert end "C"
+ $text tag add tag_SFR $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\tCarry flag\n"]
+ $text tag add tag_desc $idx insert
+ # "@R0 ..."
+ set idx [$text index insert]
+ $text insert end "@R0 ..."
+ $text tag add tag_indr $idx insert
+ set idx [$text index insert]
+ $text insert end [mc "\tIndirect address"]
+ $text tag add tag_desc $idx insert
+
+ # Show the text
+ $text configure -state disabled
+ pack $text -side bottom -fill both -expand 1
+
+ # Show the window
+ wm geometry $win "=380x280+$x+$y"
+ update
+ catch {
+ grab -global $win
+ }
+ }
+
+ ## Clear instruction details window
+ # @return void
+ public method rightPanel_ins_clear {} {
+ if {!$enabled || ${::Editor::editor_to_use}} {return}
+ if {!$gui_initialized} {CreateInstructionDetailsGUI}
+ $instruction_text configure -state normal
+ $instruction_text delete 1.0 end
+ $instruction_text configure -state disabled
+ $instruction_label configure -text {}
+
+ set instruction_last {}
+ rightPanel_ins_hide_ins_help_window
+ set help_win_index 0
+ }
+
+ ## Refresh highlighting tags in "Instruction details"
+ # @return void
+ public method rightPanel_refresh_instruction_highlighting {} {
+ if {${::Editor::editor_to_use}} {return}
+ if {!$gui_initialized && !$gui_preparing} {return}
+ $this right_panel_create_highlighting_tags \
+ $instruction_text $instruction_tags 0
+ }
+
+ ## Unset current selection in "Instruction details" window
+ # @return void
+ public method rightPanel_ins_unselect {} {
+ if {!$enabled || ${::Editor::editor_to_use}} {return}
+ if {!$gui_initialized} {return}
+
+ $instruction_text tag remove tag_sel 1.0 end
+ if {$::CONFIG(VALIDATION_LEVEL) == 2} {
+ $instruction_label configure -fg {#FF0000}
+ } {
+ $instruction_label configure -fg {#0000FF}
+ }
+ }
+
+ ## Change current selection in "Instruction details" window
+ # @parm Bool perfect_match - Operand matches exactly
+ # @parm List list_of_indexes - Lines to select (benining from zero) (eg. '0 4 9')
+ # @return void
+ public method rightPanel_ins_select {perfect_match list_of_indexes} {
+ if {!$enabled || ${::Editor::editor_to_use}} {return}
+ if {!$gui_initialized} {return}
+ if {[$instruction_label cget -text] == {}} {return}
+ $instruction_label configure -fg {#0000FF}
+ if {$perfect_match} {
+ set tag tag_sel
+ } {
+ set tag tag_sel0
+ }
+ foreach line $list_of_indexes {
+ incr line
+ $instruction_text tag add $tag $line.0 "$line.0+1l"
+ }
+ $instruction_text see $line.0
+ }
+
+ ## Change current directive in "Instruction details" window
+ # @parm Char type - 'C' == Control; 'D' == Directive
+ # @parm String directive - directive name
+ # @return void
+ public method rightPanel_dir_change {type directive} {
+ if {!$enabled || ${::Editor::editor_to_use}} {return}
+ if {!$gui_initialized} {return}
+
+ regsub {^\.} $directive {} directive
+ set directive [string tolower $directive]
+ if {$instruction_last == $directive} {return}
+ set instruction_last $directive
+
+ set ins_help_win_enabled 0
+
+ # Change content of tab header
+ if {$type == {D}} {
+ set clr {#00AADD}
+ } {
+ set clr {#00AADD}
+ }
+ set dir_up [string toupper $directive]
+ $instruction_label configure -text $dir_up -fg $clr
+ $header_text delete 1.0 end
+
+ # Enable and clear the text widget
+ $instruction_text configure -state normal
+ $instruction_text delete 1.0 end
+
+ set idx [lsearch -ascii -exact $HELP_FOR_DIRECTIVES $directive]
+ if {$idx == -1} {
+ $instruction_text insert end [mc "no help available for this directive"]
+ } {
+ incr idx
+ $instruction_text insert end [lindex $HELP_FOR_DIRECTIVES $idx]
+ }
+
+ # Create highlight tags
+ $instruction_text tag add tag_DPTR 1.0 {1.0 lineend}
+ $instruction_text tag add tag_AB 3.0 {3.0 lineend}
+ $instruction_text tag add tag_AB 6.0 {6.0 lineend}
+ $instruction_text tag add tag_indr {end-2l linestart} {end-2l lineend}
+
+ # Disable the widget
+ $instruction_text configure -state disabled
+ }
+
+ ## Change current instruction in "Instruction details" window
+ # @parm String instruction - instruction name
+ # @return void
+ public method rightPanel_ins_change {instruction} {
+ if {!$enabled || ${::Editor::editor_to_use}} {return}
+ if {!$gui_initialized} {return}
+
+ set instruction [string tolower $instruction]
+ if {$instruction_last == $instruction} {return}
+ set instruction_last $instruction
+
+ set ins_help_win_enabled 0
+
+ # Change content of tab header
+ $instruction_label configure -text [string toupper $instruction] -fg {#0000FF}
+ $header_text delete 1.0 end
+ $header_text insert 1.0 "Opr 0\tOpr 1\tOpr 2\tLen Code Time"
+
+ # Find given instruction in compilers instruction set definition
+ if {[lsearch -ascii -exact ${::CompilerConsts::AllInstructions} $instruction] == -1} {return}
+
+ # Enable and clear the text widget
+ $instruction_text configure -state normal
+ $instruction_text delete 1.0 end
+
+ # Display instruction details
+ set data {}
+ foreach line [lindex $::CompilerConsts::InstructionDefinition($instruction) 1] {
+ # Write operands
+ for {set i 0} {$i < 3} {incr i} {
+ set startIndex [$instruction_text index insert]
+ set opr [lindex $line [list 0 $i]]
+
+ # Adjust operand
+ if {[lsearch -ascii -exact {code8 code11 code16 imm8 imm16 data bit} $opr] == -1} {
+ set opr [string toupper $opr]
+ }
+
+ # Insert operand
+ $instruction_text insert insert $opr
+ $instruction_text insert insert "\t"
+
+ # Highlight operand
+ switch -- $opr {
+ {code8} { ;# 8 bit offset for relative jump
+ $instruction_text tag add tag_code8 $startIndex insert-1c
+ }
+ {code11} { ;# 11 bit program memory address
+ $instruction_text tag add tag_code11 $startIndex insert-1c
+ }
+ {code16} { ;# 16 bit program memory address
+ $instruction_text tag add tag_code16 $startIndex insert-1c
+ }
+ {imm8} { ;# 8 bit constant data
+ $instruction_text tag add tag_imm8 $startIndex insert-1c
+ }
+ {imm16} { ;# 16 bit constant data
+ $instruction_text tag add tag_imm16 $startIndex insert-1c
+ }
+ {data} { ;# internal data memory or SFR direct address
+ $instruction_text tag add tag_data $startIndex insert-1c
+ }
+ {bit} { ;# bit memory direct address
+ $instruction_text tag add tag_bit $startIndex insert-1c
+ }
+ {DPTR} { ;# Data PoinTeR register (16 bit)
+ $instruction_text tag add tag_DPTR $startIndex insert-1c
+ }
+ {A} { ;# Primary work register (Accumulator)
+ $instruction_text tag add tag_A $startIndex insert-1c
+ }
+ {AB} { ;# Accumulator
+ $instruction_text tag add tag_AB $startIndex insert-1c
+ }
+ default { ;# SFR or indirect address
+ # Indirect address
+ if {[string index $opr 0] == {@}} {
+ $instruction_text tag add tag_indr $startIndex insert-1c
+ # SFR
+ } {
+ $instruction_text tag add tag_SFR $startIndex insert-1c
+ }
+ }
+ }
+ }
+
+ # Write length
+ $instruction_text insert insert " "
+ set startIndex [$instruction_text index insert]
+ set num [lindex $line 1]
+ $instruction_text insert insert $num
+ if {$num > 0 && $num < 6} {
+ $instruction_text tag add "tag_$num" $startIndex insert
+ }
+
+ # Write OP code
+ $instruction_text insert insert " "
+ $instruction_text insert insert [string toupper [lindex $line 2]]
+
+ # Write time
+ $instruction_text insert insert " "
+ set startIndex [$instruction_text index insert]
+ set num [lindex $line 4]
+ $instruction_text insert insert $num
+ if {$num > 0 && $num < 6} {
+ $instruction_text tag add "tag_$num" $startIndex insert
+ }
+
+ # Set last 9 characters to bold font
+ $instruction_text tag add tag_bold {insert-9c} insert
+ $instruction_text insert insert "\n"
+ }
+
+ # Disable the widget
+ $instruction_text configure -state disabled
+
+ # Update help window
+ if {$ins_help_win_visible} {
+ set idx $help_win_index
+ set help_win_index 0
+ show_ins_help_window $idx
+ }
+
+ set ins_help_win_enabled 1
+ }
+
+ ## Set flag enabled
+ # @parm Bool bool - New value
+ # @return void
+ public method right_panel_instruction_details_set_enabled {bool} {
+ set enabled $bool
+ }
+
+ ## Handles Motion event on the text widget
+ # @param Int x - Relative mouse pointer position
+ # @param Int y - Relative mouse pointer position
+ # @param Int X - Absolute mouse pointer position
+ # @param Int Y - Absolute mouse pointer position
+ # @return void
+ public method rightPanel_ins_text_motion {x y X Y} {
+ if {!$ins_help_win_enabled} {return}
+ set index [$instruction_text index @$x,$y]
+ set index [expr {int($index)}]
+ if {$help_win_index == $index} {
+ move_ins_help_window $X $Y
+ return
+ }
+ set help_win_index $index
+
+ show_ins_help_window $index
+ }
+
+ ## Move instruction help window
+ # @param Int X - Absolute mouse pointer position
+ # @param Int Y - Absolute mouse pointer position
+ # @return void
+ private method move_ins_help_window {X Y} {
+ if {!$ins_help_win_visible} {
+ return
+ }
+
+ # Determinate main window geometry
+ set geometry [split [wm geometry .] {+}]
+ set limits [split [lindex $geometry 0] {x}]
+
+ # Adjust X and Y
+ set x_coord [expr {$X - 5 - [lindex $geometry 1]}]
+ set y_coord [expr {$Y - 20 - [lindex $geometry 2]}]
+
+ if {$y_coord > ([lindex $limits 1] - 220)} {incr y_coord -240}
+
+ # Show the window
+ catch {
+ place $ins_help_window -anchor ne -x $x_coord -y $y_coord -width 300
+ raise $ins_help_window
+ }
+ }
+
+ ## Show instruction help window
+ # @param Int index - Line number
+ # @return void
+ private method show_ins_help_window {index} {
+ # Create help window widget
+ if {!$ins_help_win_created} {
+ create_ins_help_window
+ }
+ # Hide window if there is nothing to show
+ if {[$instruction_text compare $index.0 == end]} {
+ rightPanel_ins_hide_ins_help_window
+ return
+ }
+
+ # Set help window visibility flag
+ set ins_help_win_visible 1
+
+ # Determinate instruction name (and possibly abort the process)
+ incr index -1
+ set instruction [string tolower [$instruction_label cget -text]]
+ if {![string length $instruction]} {
+ rightPanel_ins_hide_ins_help_window
+ return
+ }
+ # Check if the instruction is really an instruction
+ if {[lsearch -ascii -exact ${::CompilerConsts::AllInstructions} $instruction] == -1} {return}
+
+ # Modify instruction name if nessesary
+ switch -- $instruction {
+ {jmp} {
+ switch -- $index {
+ 1 {set instruction {ljmp}}
+ 2 {set instruction {ajmp}}
+ 3 {set instruction {sjmp}}
+ }
+ set index 0
+ }
+ }
+
+ # Obtain detailed informations about the instruction
+ set operands_tmp [list]
+ set instruction_def [lindex $::CompilerConsts::InstructionDefinition($instruction) [list 1 $index]]
+ set operands [lindex $instruction_def 0]
+ foreach operand $operands {
+ switch -glob -- $operand {
+ a -
+ c -
+ ab -
+ @dptr -
+ @a+dptr -
+ @a+pc -
+ dptr {
+ set operand [string toupper $operand]
+ }
+ r? {
+ set operand {Rn}
+ }
+ @r? {
+ set operand {@Ri}
+ }
+ imm8 {
+ set operand {#data}
+ }
+ imm16 {
+ set operand {#data16}
+ }
+ code8 {
+ set operand {rel}
+ }
+ code11 {
+ set operand {addr11}
+ }
+ code16 {
+ set operand {addr16}
+ }
+ bit {
+ set operand {bit}
+ }
+ /bit {
+ set operand {/bit}
+ }
+ data {
+ set operand {direct}
+ }
+ }
+ lappend operands_tmp $operand
+ }
+ set operands [join $operands_tmp {, }]
+ set instruction [string toupper $instruction]
+
+ # Modify detailed informations
+ set title "$instruction\t$operands"
+
+ set ins_length [lindex $instruction_def 1]
+ set opcode [string toupper [lindex $instruction_def 2]]
+ if {[string length $ins_length]} {
+ append opcode [string repeat {-} [expr {($ins_length - 1) * 2}]]
+ }
+
+ set ins_description [lsearch -ascii -exact $INSTRUCTION_DESCRIPTION $title]
+ if {$ins_description == -1} {
+ rightPanel_ins_hide_ins_help_window
+ return
+ }
+ incr ins_description
+ set ins_description [lindex $INSTRUCTION_DESCRIPTION $ins_description]
+
+ # Fill in the help window
+ $help_win_title configure -text $title
+ $help_win_labels(description) configure -text [mc [lindex $ins_description 0]]
+ $help_win_labels(length) configure -text $ins_length
+ $help_win_labels(execution_time) configure -text [lindex $instruction_def 4]
+ $help_win_labels(opcode) configure -text "0x$opcode"
+ $help_win_labels(note) configure -text [mc [lindex $ins_description 2]]
+ $help_win_labels(class) configure -text [mc [lindex $ins_description 1]]
+ foreach i_0 {0 1 2 } \
+ i_1 {C OV AC } \
+ i_2 {C_l OV_l AC_l } \
+ {
+ set txt [lindex $ins_description [list 3 $i_0]]
+ switch -- $txt {
+ X {set clr {#00AAFF}}
+ 0 {set clr {#DD0000}}
+ 1 {set clr {#00CC00}}
+ default {set clr {#888888}}
+ }
+ $help_win_labels($i_1) configure -text $txt -fg $clr
+ $help_win_labels($i_2) configure -fg $clr
+ }
+ }
+
+ ## Hide instruction help window
+ # @return void
+ public method rightPanel_ins_hide_ins_help_window {} {
+ if {!$ins_help_win_visible} {
+ return
+ }
+
+ set help_win_index 0
+ set ins_help_win_visible 0
+ catch {
+ place forget $ins_help_window
+ }
+ }
+
+ ## Create instruciton help window
+ # @return void
+ private method create_ins_help_window {} {
+ set ins_help_win_created 1
+
+ # Create main parts of the window
+ set ins_help_window [frame .ins_help_window${count} -bd 0 -bg {#BBBBFF} -padx 2 -pady 2]
+ pack [frame $ins_help_window.top -bg {#BBBBFF}] -fill x -expand 1
+ pack [label $ins_help_window.top.img -bg {#BBBBFF} -image ::ICONS::16::info] -side left
+ pack [label $ins_help_window.top.tit -bg {#BBBBFF} -justify left -anchor w] -side left -fill x -expand 1
+ pack [frame $ins_help_window.msg -bg {#FFFFFF} -padx 10 -pady 5] -fill both -expand 1
+ set help_win_title "$ins_help_window.top.tit"
+
+ ## Create other parts of the window
+ # Descripton
+ set i 0
+ set help_win_labels(description) [ \
+ label $ins_help_window.msg.r_$i \
+ -pady 0 -bg {#FFFFFF} \
+ -highlightthickness 0 \
+ -wraplength 260 -justify left \
+ ]
+ grid $help_win_labels(description) -row $i -column 0 -columnspan 2 -sticky w
+ incr i
+ # - (separator)
+ grid [ttk::separator $ins_help_window.msg.sep \
+ -orient horizontal \
+ ] -row $i -column 0 -columnspan 2 -sticky we
+ # Class
+ incr i
+ grid [label $ins_help_window.msg.l_$i \
+ -pady 0 -fg {#0000AA} \
+ -bg {#FFFFFF} \
+ -highlightthickness 0 \
+ -text [mc "Class:"] \
+ ] -row $i -column 0 -sticky w
+ set help_win_labels(class) [ \
+ label $ins_help_window.msg.r_$i \
+ -pady 0 -bg {#FFFFFF} \
+ -highlightthickness 0 \
+ ]
+ grid $help_win_labels(class) -row $i -column 1 -sticky w
+ incr i
+ # Flags
+ grid [label $ins_help_window.msg.l_$i \
+ -pady 0 -fg {#0000AA} \
+ -highlightthickness 0 \
+ -text [mc "Flags:"] \
+ -bg {#FFFFFF} \
+ ] -row $i -column 0 -sticky nw
+
+ set flags_frm [frame $ins_help_window.msg.flags_frm \
+ -bg {#888888} \
+ ]
+ grid $flags_frm -row $i -column 1 -sticky w
+ incr i
+ # Length
+ grid [label $ins_help_window.msg.l_$i \
+ -pady 0 -fg {#0000AA} \
+ -highlightthickness 0 \
+ -text [mc "Length:"] \
+ -bg {#FFFFFF} \
+ ] -row $i -column 0 -sticky w
+ set help_win_labels(length) [ \
+ label $ins_help_window.msg.r_$i \
+ -pady 0 -bg {#FFFFFF} \
+ -highlightthickness 0 \
+ ]
+ grid $help_win_labels(length) -row $i -column 1 -sticky w
+ incr i
+ # Time
+ grid [label $ins_help_window.msg.l_$i \
+ -pady 0 -fg {#0000AA} \
+ -highlightthickness 0 \
+ -text [mc "Time:"] \
+ -bg {#FFFFFF} \
+ ] -row $i -column 0 -sticky w
+ set help_win_labels(execution_time) [ \
+ label $ins_help_window.msg.r_$i \
+ -pady 0 -bg {#FFFFFF} \
+ -highlightthickness 0 \
+ ]
+ grid $help_win_labels(execution_time) -row $i -column 1 -sticky w
+ incr i
+ # OPCODE
+ grid [label $ins_help_window.msg.l_$i \
+ -pady 0 -fg {#0000AA} \
+ -highlightthickness 0 \
+ -text [mc "OPCODE:"] \
+ -bg {#FFFFFF} \
+ ] -row $i -column 0 -sticky w
+ set help_win_labels(opcode) [ \
+ label $ins_help_window.msg.r_$i \
+ -pady 0 -bg {#FFFFFF} \
+ -highlightthickness 0 \
+ ]
+ grid $help_win_labels(opcode) -row $i -column 1 -sticky w
+ incr i
+ # Note
+ grid [label $ins_help_window.msg.l_$i \
+ -pady 0 -fg {#0000AA} \
+ -highlightthickness 0 \
+ -text [mc "Note:"] \
+ -bg {#FFFFFF} \
+ ] -row $i -column 0 -sticky w
+ set help_win_labels(note) [ \
+ label $ins_help_window.msg.r_$i \
+ -pady 0 -bg {#FFFFFF} \
+ -highlightthickness 0 \
+ ]
+ grid $help_win_labels(note) -row $i -column 1 -sticky w
+ ## Table of flags
+ # Flag C
+ set help_win_labels(C_l) [ \
+ label $flags_frm.ll_C \
+ -bg {#FFFFFF} \
+ -pady 0 \
+ -highlightthickness 0 \
+ -text "C" \
+ ]
+ grid $help_win_labels(C_l) -row 0 -column 0 -sticky nswe -padx 1 -pady 1
+ set help_win_labels(C) [ \
+ label $flags_frm.lr_C \
+ -bg {#FFFFFF} \
+ -pady 0 \
+ -highlightthickness 0 \
+ ]
+ grid $help_win_labels(C) -row 1 -column 0 -sticky nswe -padx 1 -pady 1
+ # Flag OV
+ set help_win_labels(OV_l) [ \
+ label $flags_frm.ll_OV \
+ -bg {#FFFFFF} \
+ -pady 0 \
+ -highlightthickness 0 \
+ -text "OV" \
+ ]
+ grid $help_win_labels(OV_l) -row 0 -column 1 -sticky nswe -padx 1 -pady 1
+ set help_win_labels(OV) [ \
+ label $flags_frm.lr_OV \
+ -bg {#FFFFFF} \
+ -pady 0 \
+ -highlightthickness 0 \
+ ]
+ grid $help_win_labels(OV) -row 1 -column 1 -sticky nswe -padx 1 -pady 1
+ # Flag AC
+ set help_win_labels(AC_l) [ \
+ label $flags_frm.ll_AC \
+ -bg {#FFFFFF} \
+ -pady 0 \
+ -highlightthickness 0 \
+ -text "AC" \
+ ]
+ grid $help_win_labels(AC_l) -row 0 -column 2 -sticky nswe -padx 1 -pady 1
+ set help_win_labels(AC) [ \
+ label $flags_frm.lr_AC \
+ -bg {#FFFFFF} -bd 1 \
+ -pady 0 \
+ -highlightthickness 0 \
+ ]
+ grid $help_win_labels(AC) -row 1 -column 2 -sticky nswe -padx 1 -pady 1
+ # (finalize creation of table of flags)
+ grid columnconfigure $ins_help_window.msg 0 -minsize 80
+ grid columnconfigure $ins_help_window.msg 1 -weight 1
+ }
+
+ proc initialize {} {
+ set l [llength $HELP_FOR_DIRECTIVES_RAW]
+ for {set i 0; set j 1} {$i < $l} {incr i 2; incr j 2} {
+ lappend HELP_FOR_DIRECTIVES [lindex $HELP_FOR_DIRECTIVES_RAW $i]
+ lappend HELP_FOR_DIRECTIVES [mc [subst [lindex $HELP_FOR_DIRECTIVES_RAW $j]]]
+ }
+ }
+}
+
+# Initialize
+::InstructionDetails::initialize
diff --git a/lib/rightpanel/regwatches.tcl b/lib/rightpanel/regwatches.tcl
new file mode 100755
index 0000000..ad5e433
--- /dev/null
+++ b/lib/rightpanel/regwatches.tcl
@@ -0,0 +1,2120 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Implements register watches (part of Right Panel)
+# --------------------------------------------------------------------------
+
+class RegWatches {
+
+ ## COMMON
+ common watches_set_shortcuts {} ;# Currently set shortcuts for register watches
+ common watches_shortcuts_cat {watches} ;# Key shortcut categories related to register watches
+ # Counter of embedded entry widgets in register watches
+ common watch_entry_count 0
+ # Conter of instances
+ common count 0
+ ## Highlighting tags for register watches
+ # {
+ # {tag_name foreground_color ?bold_or_italic?}
+ # ...
+ # }
+ common watch_text_tags {
+ {tag_Baddr #DD0000 1}
+ {tag_Xaddr #AA00FF 1}
+ {tag_Eaddr #00AAFF 1}
+ {tag_addr #0000DD 1}
+ {tag_name #8888DD {}}
+ }
+ common regfont [font create -family $::DEFAULT_FIXED_FONT -size -14]
+ # Popup menu for register watches
+ common WATCHMENU {
+ {command {Move top} {$watches:top} 0 "rightPanel_watch_move_top"
+ {top} "Move this register watch to the top of list"}
+ {command {Move up} {$watches:up} 0 "rightPanel_watch_move_up"
+ {1uparrow} "Move this register watch up"}
+ {command {Move down} {$watches:down} 1 "rightPanel_watch_move_down"
+ {1downarrow} "Move this register watch down"}
+ {command {Move bottom} {$watches:bottom} 2 "rightPanel_watch_move_bottom"
+ {bottom} "Move this register watch to the bottom of list"}
+ {separator}
+ {command {Remove} {$watches:remove} 2 "rightPanel_watch_remove"
+ {button_cancel} "Remove this register watch from the list"}
+ {separator}
+ {command {Remove all} {$watches:remove_all} 0 "rightPanel_watch_clear"
+ {editdelete} "Clear the list of register watches"}
+ {separator}
+ {command {Save} {} 0 "rightPanel_watch_save {} 1" {filesave}
+ "Save this list to a file"}
+ {command {Configure} {} 0 "rightPanel_configure 0" {configure}
+ "Configure this panel"}
+ }
+ # Configuration menu
+ common CONFMENU {
+ {cascade {Sort by} 0 "" .sort false 1 {
+ {command {Name} {} 0 "rightPanel_watch_sort_by N" {}
+ ""}
+ {command {Address} {} 0 "rightPanel_watch_sort_by A" {}
+ ""}
+ {command {Type} {} 0 "rightPanel_watch_sort_by T" {}
+ ""}
+ {separator}
+ {radiobutton "Incremental" {} ::RegWatches::sorting_order 1
+ {} 0 ""}
+ {radiobutton "Decremental" {} ::RegWatches::sorting_order 0
+ {} 0 ""}
+ }}
+ {command {Remove all} {} 0 "rightPanel_watch_clear" {editdelete}
+ ""}
+ {separator}
+ {checkbutton {Autoload from code listing} {} {::RegWatches::menu_autoload} 1 0 0
+ {rightPanel_watch_toggle_autoload_flag}}
+ }
+
+ ## PRIVATE
+ private variable enabled 0 ;# Bool: enable procedures which are needless while loading project
+ private variable obj_idx ;# Number of this object
+ private variable parent ;# Widget: parent widget
+ private variable gui_initialized 0 ;# Bool: GUI initialized
+
+ private variable conf_button ;# Widget: Configuration button
+ private variable conf_menu {} ;# Configuration menu
+ private variable watch_menu ;# ID of popup menu for "Register watches"
+ private variable watch_text ;# ID of text widget representing list of register watches
+ private variable watch_remove_button ;# ID of button "Remove watch" - Register watches
+ private variable watch_new_button ;# ID of button "New watch" - Register watches
+ private variable watch_add_button ;# ID of button "Add watch" - Register watches
+ private variable watch_addr_entry ;# ID of entry "Address" - Register watches
+ private variable watch_search_entry ;# ID of entry "Search" - Register watches
+ private variable watch_search_clear ;# ID of button "Clear search entry" - Register watches
+
+ # Bool: Autoload from LST file
+ private variable autoload_flag [lindex $::CONFIG(REGWATCHES_CONFIG) 0]
+ private variable watches_modified 0 ;# Bool: Register watches definition modified
+ private variable search_val_in_progress 0 ;# Bool: Search entry validation in porgress
+ private variable watch_file_name {} ;# Name of file currently loaded in register watches
+ private variable watch_curLine 0 ;# Current line in list of register watches
+ private variable watch_AN_valid_ena 1 ;# Bool: Enable validation of address entry in register watches
+ private variable validator_engaged 0 ;# Bool: Address entry validation in progress
+ private variable watches_enabled 0 ;# Bool: Entry widgets in register watches enabled
+
+ private variable watch_addrs {} ;# List - {hex_addr hex_addr ...}
+ ## Array of Lists - info about particular watch
+ # format: $watch_data($hex_addr) -> {regName textVariable}
+ # note: embedded entry path == $watch_text.$textVariable
+ private variable watch_data
+
+
+ ## Object constructor
+ constructor {} {
+ incr count
+ set obj_idx $count
+ }
+
+ ## Object destructor
+ destructor {
+ if {$gui_initialized} {
+ # Remove status bar tips for popup menus
+ menu_Sbar_remove $watch_menu
+
+ # Unallocate GUI related variables
+ unset RightPanel::watch_addr$obj_idx
+ unset RightPanel::watch_name$obj_idx
+ }
+ }
+
+ ## Prepare object for creating its GUI
+ # @parm Widget _parent - GUI parent widget
+ # @parm String watches_file - Definition file for register watches
+ # @return void
+ public method PrepareRegWatches {_parent filename} {
+ set parent $_parent
+ set watch_file_name $filename
+ set gui_initialized 0
+ }
+
+ ## Create GUI of register watches
+ # @return void
+ public method CreateRegWatchesGUI {} {
+ if {$gui_initialized} {return}
+ set gui_initialized 1
+
+ # Top frame
+ set icon_bar [frame $parent.frm_rightPanel_watch_iconBar]
+ # Bottom frame
+ set text_frame [frame $parent.frm_rightPanel_watch_txt]
+ # Toolbar
+ set tool_bar [frame $parent.frm_rightPanel_watch_toolBar]
+
+ # Button "Configure"
+ set button [ttk::button $icon_bar.conf_but \
+ -image ::ICONS::16::configure \
+ -command "$this rightPanel_watch_cfg_menu" \
+ -style Flat.TButton \
+ ]
+ set conf_button $button
+ pack $button -side left -padx 3
+ # Separator
+ pack [ttk::separator $icon_bar.sep_rightPanel_watch_ib_sepm0 \
+ -orient vertical \
+ ] -side left -fill y -padx 3
+ # Button "Save"
+ set button [ttk::button $icon_bar.but_rightPanel_watch_save \
+ -image ::ICONS::16::filesave \
+ -command "$this rightPanel_watch_save {} 1" \
+ -style Flat.TButton \
+ ]
+ pack $button -side left -padx 3
+ DynamicHelp::add $button -text [mc "Save"]
+ setStatusTip -widget $button \
+ -text [mc "Save"]
+ # Button "Save as"
+ set button [ttk::button $icon_bar.but_rightPanel_watch_saveas \
+ -image ::ICONS::16::filesaveas \
+ -command "$this rightPanel_watch_saveas" \
+ -style Flat.TButton \
+ ]
+ pack $button -side left -padx 3
+ DynamicHelp::add $button -text [mc "Save under a different filename"]
+ setStatusTip -widget $button \
+ -text [mc "Save under a different filename"]
+ # Separator
+ pack [ttk::separator $icon_bar.sep_rightPanel_watch_ib_sep0 \
+ -orient vertical \
+ ] -side left -fill y -padx 3
+ # Button "Open"
+ set button [ttk::button $icon_bar.but_rightPanel_watch_open \
+ -image ::ICONS::16::fileopen \
+ -command "$this rightPanel_watch_open" \
+ -style Flat.TButton \
+ ]
+ pack $button -side left -padx 3
+ DynamicHelp::add $button -text [mc "Open *.wtc file"]
+ setStatusTip -widget $button \
+ -text [mc "Open *.wtc file"]
+ # Button "Import"
+ set button [ttk::button $icon_bar.but_rightPanel_watch_imp \
+ -image ::ICONS::16::fileimport \
+ -style Flat.TButton \
+ -command "$this rightPanel_watch_import" \
+ ]
+ pack $button -side left -padx 3
+ DynamicHelp::add $button -text [mc "Import list of registers from code listing or WTC file"]
+ setStatusTip -widget $button \
+ -text [mc "Import list of registers from *.lst or *.wtc file"]
+ # Entry "Search"
+ set watch_search_entry [ttk::entry $icon_bar.search_entry \
+ -validate key \
+ -width 0 \
+ -validatecommand "$this rightPanel_watch_search_validate %P" \
+ ]
+ DynamicHelp::add $watch_search_entry \
+ -text [mc "Enter your search string here"]
+ pack $watch_search_entry -side left -fill x -expand 1
+ setStatusTip -widget $watch_search_entry \
+ -text [mc "Search for a name"]
+ # Button "Clear search string"
+ set watch_search_clear [ttk::button $icon_bar.clear_search \
+ -image ::ICONS::16::clear_left \
+ -command "$watch_search_entry delete 0 end" \
+ -state disabled \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $icon_bar.clear_search -text [mc "Clear search string"]
+ pack $watch_search_clear -side right -after $watch_search_entry
+ setStatusTip -widget $icon_bar.clear_search \
+ -text [mc "Clear search string"]
+
+ # Entry "Address"
+ set entry [ttk::entry $tool_bar.ent_rightPanel_watch_addr \
+ -textvariable RightPanel::watch_addr$count \
+ -validatecommand "$this rightPanel_watch_addr_validate %P" \
+ -validate key \
+ -width 4 \
+ ]
+ DynamicHelp::add $entry \
+ -text [mc "Register address:\n 1 or 2 digits\tinternal RAM (not SFR)\n 3 digits\t\texpanded RAM\n 4 digits\t\texternal RAM\n dot and 2 digits\tBit"]
+ setStatusTip -widget $entry \
+ -text [mc "Register address or bit address"]
+ grid $entry -sticky w -row 2 -column 1
+ bind $entry <Return> "$this rightPanel_watch_add"
+ bind $entry <KP_Enter> "$this rightPanel_watch_add"
+
+ # Entry "Name"
+ set entry [ttk::entry $tool_bar.ent_rightPanel_watch_name \
+ -textvariable RightPanel::watch_name$count \
+ -validatecommand "$this rightPanel_watch_name_validate %P" \
+ -validate key \
+ -width 20 \
+ ]
+ setStatusTip -widget $entry \
+ -text [mc "Name of the watch. Any string."]
+ grid $entry -sticky w -row 2 -column 2 -padx 3
+ bind $entry <Return> "$this rightPanel_watch_add"
+ bind $entry <KP_Enter> "$this rightPanel_watch_add"
+ # Button "Add"
+ set watch_add_button [ttk::button $tool_bar.but_rightPanel_watch_add \
+ -image ::ICONS::16::add \
+ -command "$this rightPanel_watch_add" \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $watch_add_button -text [mc "Add this entry to register watches"]
+ setStatusTip -widget $watch_add_button \
+ -text [mc "Add this entry to register watches"]
+ grid $watch_add_button -sticky w -row 2 -column 3
+ # Button "New"
+ set watch_new_button [ttk::button $tool_bar.but_rightPanel_watch_new \
+ -image ::ICONS::16::filenew \
+ -command "$this rightPanel_watch_new" \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $watch_new_button -text [mc "New register watches entry"]
+ setStatusTip -widget $watch_new_button \
+ -text [mc "Create new register watch"]
+ grid $watch_new_button -sticky w -row 2 -column 4
+ # Button "Remove"
+ set watch_remove_button [ttk::button $tool_bar.but_rightPanel_watch_remove \
+ -image ::ICONS::16::button_cancel \
+ -command "$this rightPanel_watch_remove" \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $watch_remove_button -text [mc "Remove this entry"]
+ setStatusTip -widget $watch_remove_button \
+ -text [mc "Remove this entry"]
+ grid $watch_remove_button -sticky w -row 2 -column 5
+ # Label "Addr"
+ set watch_addr_entry [label $tool_bar.lbl_rightPanel_watch_addr \
+ -text [mc "Addr"] \
+ -font ${Simulator_GUI::smallfont} \
+ -fg ${Simulator_GUI::small_color} \
+ ]
+ grid $watch_addr_entry -row 1 -column 1
+ # Label "Register name"
+ grid [label $tool_bar.lbl_rightPanel_watch_name \
+ -text [mc "Register name"] \
+ -font ${Simulator_GUI::smallfont} \
+ -fg ${Simulator_GUI::small_color} \
+ ] -row 1 -column 2
+
+ # Create text widget representing list of register watches
+ set watch_text [text $text_frame.txt_rightPanel_watch \
+ -yscrollcommand "$text_frame.src_rightPanel_watch set" \
+ -bg {#FFFFFF} -font $regfont \
+ -cursor left_ptr \
+ -state disabled -exportselection 0 \
+ ]
+ # Create text tags
+ $this right_panel_create_highlighting_tags $watch_text $watch_text_tags -1
+ $watch_text tag configure tag_curLine -background ${::RightPanel::selection_color_dark}
+
+ # Create scrollbar
+ pack [ttk::scrollbar $text_frame.src_rightPanel_watch \
+ -orient vertical \
+ -command "$watch_text yview" \
+ ] -side right -fill y
+ pack $watch_text -side left -fill both -expand 1
+ # Create event bindings
+ bind $watch_text <ButtonRelease-3> "$this rightPanel_watch_popupmenu %X %Y %x %y; break"
+ bind $watch_text <Button-1> "$this rightPanel_watch_click %x %y; break"
+ bind $watch_text <<Selection>> "false_selection $watch_text; break"
+ bind $watch_text <Key-Menu> {break}
+
+ # Pack frames
+ pack $tool_bar -side bottom -anchor w
+ pack $icon_bar -side top -fill x
+ pack $text_frame -side top -fill both -expand 1
+ rightPanel_watch_switch_line 1
+
+ # Create popup menu
+ set watch_menu $parent.menu_rightPanel_watch
+ regwatches_makePopupMenu
+
+ # Refresh highlighting tags
+ rightPanel_refresh_regwatches_highlighting
+
+ # Open definition file
+ if {$watch_file_name != {}} {
+ rightPanel_watch_openfile $watch_file_name . 0
+ }
+ }
+
+ ## Sort register watches
+ # @parm Char sorting_key
+ # N - Sort by name
+ # A - Sort by address
+ # T - Sort by type
+ # @return void
+ public method rightPanel_watch_sort_by {sorting_key} {
+ # Pack all watches into one sigle list
+ set list_to_sort [list]
+ set type {}
+ foreach addr [array names watch_data] {
+
+ switch -- [string length $addr] {
+ 4 {
+ set type {X}
+ }
+ 3 {
+ if {[string index $addr 0] == {.}} {
+ set type {B}
+ } {
+ set type {E}
+ }
+ }
+ default {
+ set type {D}
+ }
+ }
+
+ lappend list_to_sort [list $addr [lindex $watch_data($addr) 0] $type]
+ }
+
+ # Incremental sorting order
+ if {$::RegWatches::sorting_order} {
+ set order {-increasing}
+ # Decremental sorting order
+ } {
+ set order {-decreasing}
+ }
+
+ switch -- $sorting_key {
+ N { ;# Name
+ set index 1
+ }
+ A { ;# Address
+ set index 0
+ }
+ T { ;# Type
+ set index 2
+ }
+ }
+
+ # Sort the list
+ set list_to_sort [lsort -dictionary $order -index $index $list_to_sort]
+
+ # Refill the panel
+ rightPanel_watch_clear 1
+ foreach entry $list_to_sort {
+ set addr [lindex $entry 0]
+ set name [lindex $entry 1]
+
+ rightPanel_watch_add $addr $name
+ }
+ }
+
+ ## Perform autoload on simulator start
+ # @parm String filename - Code listinf file
+ # @return void
+ public method rightPanel_watch_autoload {filename} {
+ if {!$autoload_flag} {return}
+ if {![file exists $filename]} {return}
+
+ rightPanel_watch_import_file $filename .
+ }
+
+ ## Autoload flag toggled (this function should be invoked from configuration menu)
+ # @return void
+ public method rightPanel_watch_toggle_autoload_flag {} {
+ set autoload_flag $::RegWatches::menu_autoload
+ }
+
+ ## Get configuration list
+ # @return void
+ public method rightPanel_watch_get_config {} {
+ return [list $::RegWatches::menu_autoload $::RegWatches::sorting_order]
+ }
+
+ ## Create configuration menu
+ # @return void
+ private method create_conf_menu {} {
+ if {$conf_menu != {}} {
+ return
+ }
+ set conf_menu $parent.conf_menu
+ menuFactory $CONFMENU $conf_menu 0 "$this " 0 {}
+
+ watch_disEna_buttons
+ }
+
+ ## Invoke configuration menu
+ # @return void
+ public method rightPanel_watch_cfg_menu {} {
+ create_conf_menu
+
+ set x [winfo rootx $conf_button]
+ set y [winfo rooty $conf_button]
+ incr y [winfo height $conf_button]
+
+ set ::RegWatches::menu_autoload $autoload_flag
+ tk_popup $conf_menu $x $y
+ }
+
+ ## Refresh highlighting tags
+ # @return void
+ public method rightPanel_refresh_regwatches_highlighting {} {
+ if {!$gui_initialized} {return}
+ $this right_panel_create_highlighting_tags $watch_text $watch_text_tags -1
+ }
+
+ ## Recreate popup menu
+ # @return void
+ public method regwatches_makePopupMenu {} {
+ if {!$gui_initialized} {return}
+ if {[winfo exists $watch_menu]} {destroy $watch_menu}
+ menuFactory $WATCHMENU $watch_menu 0 "$this " 0 {}
+ }
+
+
+ ## Retrun name of file currently loaded in register watches
+ # @return String - filename
+ public method getWatchesFileName {} {
+ # Determinate project root path
+ set prj_path [$this cget -projectPath]
+ append prj_path {/}
+
+ # Return relative directory location
+ if {![string first $prj_path $watch_file_name]} {
+ return [string range $watch_file_name [string length $prj_path] end]
+ # Return absolute directory location
+ } {
+ return $watch_file_name
+ }
+ }
+
+ ## (Re)set dynamic shortcuts for the given entry widget
+ # @parm Widget entry - Target entry widget
+ # @return void
+ private method watch_entry_shortcuts_reset {entry} {
+ if {!$gui_initialized} {return}
+
+ # Unset previous configuration
+ foreach key $watches_set_shortcuts {
+ bind $entry <$key> {}
+ }
+ set set_shortcuts {}
+
+ # Iterate over shortcuts definition
+ foreach block ${::SHORTCUTS_LIST} {
+ # Determinate category
+ set category [lindex $block 0]
+ if {[lsearch $watches_shortcuts_cat $category] == -1} {continue}
+
+ # Determinate definition list and its length
+ set block [lreplace $block 0 2]
+ set len [llength $block]
+
+ # Iterate over definition list and create bindings
+ for {set i 0; set j 1} {$i < $len} {incr i 2; incr j 2} {
+ # Determinate key sequence
+ set key [lindex $block $i]
+ if {[catch {
+ set key $::SHORTCUTS_DB($category:$key)
+ }]} then {
+ continue
+ }
+ if {$key == {}} {continue}
+
+ # Create and register new binding
+ lappend watches_set_shortcuts $key
+ set cmd [subst [lindex $block [list $j 1]]]
+ append cmd {;break}
+ bind $entry <$key> $cmd
+ }
+ }
+ }
+
+ ## Get adjusted value of address entry (register watches)
+ # @parm String string - input data ("\n" == get value from entry widget)
+ # @return String - result address
+ private method get_watchAddr {string} {
+
+ # Evaluate input string
+ if {$string == {} || $string == {.}} {
+ return { .00}
+ }
+ if {$string == "\n"} {
+ set string [subst "\$::RightPanel::watch_addr${obj_idx}"]
+ regsub {^\s+} $string {} string
+ }
+ if {[string index $string 0] == {.}} {
+ set string [string replace $string 0 0]
+ set bit_addr 1
+ } {
+ set bit_addr 0
+ }
+
+ # Adjust address
+ set len [string length $string]
+ if {$len > 2} {
+ if {$len != 4} {
+ set string " $string"
+ }
+ } {
+ if {$len == 1} {
+ set string "0$string"
+ }
+ set string " $string"
+ }
+
+ # Resturn result
+ if {$bit_addr} {
+ return [string replace $string 1 1 {.}]
+ } {
+ return [string toupper $string]
+ }
+ }
+
+ ## Get adjusted value of register name (Register watches)
+ # @parm String string - input data ("\n" == get value from entry widget)
+ # @return String - resulting register name
+ private method get_watchName {string} {
+ # Conditionaly get value from entry widget
+ if {$string == "\n"} {
+ set string [subst "\$::RightPanel::watch_name${obj_idx}"]
+ regsub {\t+$} $string {} string
+ }
+
+ # Adjust resulting string
+ set len [string length $string]
+ append string [string repeat { } [expr {23 - $len}]]
+
+ # Return result
+ return $string
+ }
+
+ ## Validate content of address entry - Register watches
+ # @parm String value - input value
+ # @return Bool - result
+ public method rightPanel_watch_addr_validate {value} {
+
+ # Check if validation is enabled
+ if {!$watch_AN_valid_ena} {return 1}
+
+ # Check for allowed length
+ if {[string length $value] > 4} {
+ return 0
+ }
+
+ # Check for allowed characters
+ if {!([regexp {^[A-Fa-f0-9]*$} $value] || [regexp {^\.[A-Fa-f0-9]{0,2}$} $value])} {
+ return 0
+ }
+
+ # Change content of address field in register watches text widget
+ if {$watch_curLine != 0 && $value != {}} {
+
+ # Get address
+ set value [get_watchAddr $value]
+ regsub {^\s+} $value {} real_value
+
+ # Check it the desired address is unique
+ if {[lsearch -ascii -exact $watch_addrs $real_value] != -1} {
+ Sbar [mc "Unable to assign, address is already in use"]
+ return 1
+ }
+
+ # Modify variables related to the current entry
+ set idx [expr {$watch_curLine - 1}]
+ set addr [lindex $watch_addrs $idx]
+ set var [lindex $watch_data($addr) 1]
+ set watch_data($real_value) $watch_data($addr)
+ unset watch_data($addr)
+ lset watch_addrs $idx $real_value
+
+ # Synchronize
+ $watch_text.$var configure -state normal
+ rightPanel_watch_sync $real_value
+ $watch_text.$var configure -fg ${Simulator::normal_color}
+ if {!$watches_enabled || [read_from_simulator $real_value] == {--}} {
+ $watch_text.$var configure -state disabled
+ }
+
+ # Enable entry watches text widget
+ $watch_text configure -state normal
+
+ # Change content of address field
+ $watch_text delete $watch_curLine.0 $watch_curLine.4
+ $watch_text insert $watch_curLine.0 $value
+
+ # Bit -> Byte
+ if {[string index $addr 0] == {.} && [string index $real_value 0] != {.}} {
+ $watch_text.$var configure -width 2
+ help_window_hide
+
+ # Byte -> Bit
+ } elseif {[string index $addr 0] != {.} && [string index $real_value 0] == {.}} {
+ $watch_text.$var configure -width 1
+ help_window_hide
+ }
+
+ # Highlight address field
+ set len [string length $real_value]
+ if {$len == 4} {
+ set addr_tag {tag_Xaddr}
+ } elseif {$len == 3 && ([string index $real_value 0] == {.})} {
+ set addr_tag {tag_Baddr}
+ } elseif {$len == 3} {
+ set addr_tag {tag_Eaddr}
+ } else {
+ set addr_tag {tag_addr}
+ }
+ $watch_text tag add $addr_tag $watch_curLine.0 $watch_curLine.4
+
+ # Change selection
+ $watch_text tag remove tag_curLine 1.0 end
+ $watch_text tag add tag_curLine $watch_curLine.0 "$watch_curLine.0 + 1 line"
+
+ $watch_text configure -state disabled
+
+ # Adjust help window
+ help_window_update_addr $addr $real_value
+ bind $watch_text.[lindex $watch_data($real_value) 1] <Enter> \
+ "$this create_help_window_ram ${real_value}h; help_window_variable_addr"
+
+ # Adjust flag: modified
+ set watches_modified 1
+ }
+
+ # Success
+ return 1
+ }
+
+ ## Validate content of register name entry - Register watches
+ # @parm String value - input value
+ # @return Bool - result
+ public method rightPanel_watch_name_validate {value} {
+ # Check if validation is enabled
+ if {!$watch_AN_valid_ena} {return 1}
+
+ # Check for allowed length
+ if {[string length $value] > 23} {
+ return 0
+ }
+
+ # Change content of register name field in register watches text widget
+ if {$watch_curLine != 0} {
+ # Local variables
+ set name [get_watchName $value] ;# Register name
+
+ # Change reg. name in object variable watch_data
+ lset watch_data([lindex $watch_addrs [expr {$watch_curLine - 1}]]) 0 [string trimright $value]
+
+ # Enable list of watches widget
+ $watch_text configure -state normal
+
+ # Change current register name
+ $watch_text delete $watch_curLine.5 "$watch_curLine.0 lineend - 1 char"
+ $watch_text insert $watch_curLine.5 $name
+
+ # Restore reg. name text tag
+ $watch_text tag add tag_name $watch_curLine.5 $watch_curLine.28
+
+ # Adjust selection
+ $watch_text tag remove tag_curLine 1.0 end
+ $watch_text tag add tag_curLine $watch_curLine.0 "$watch_curLine.0 + 1 line"
+
+ # Disable list of watches widget
+ $watch_text configure -state disabled
+
+ # Adjust status modified
+ set watches_modified 1
+ }
+
+ # Success
+ $watch_search_entry delete 0 end
+ return 1
+ }
+
+ ## Validate content of embedded entries in list of register watches
+ # @parm String addr - hexadecimal representation of register addres
+ # @parm String value - string to validate
+ # @return Bool - result
+ public method rightPanel_watch_value_validate {addr value} {
+ if {$validator_engaged} {return 1}
+ set validator_engaged 1
+
+ # Check for allowed length
+ if {[string length $value] > 2} {
+ set validator_engaged 0
+ return 0
+ }
+
+ # Check for allowed characters
+ if {![regexp {^[A-Fa-f0-9]*$} $value]} {
+ set validator_engaged 0
+ return 0
+ }
+
+ ## Synchronize new content with simulator engine
+ if {[string index $addr 0] == {.}} {
+ set addr [string replace $addr 0 0]
+ set bit_addr 1
+ } {
+ set bit_addr 0
+ }
+ set dec_addr [expr "0x$addr"]
+ # Bit
+ if {$bit_addr} {
+ if {$value == {}} {
+ set value 0
+ }
+ if {![regexp {^[01]?$} $value]} {
+ set validator_engaged 0
+ return 0
+ }
+ $this setBit $dec_addr $value
+
+ # External RAM
+ } elseif {[string length $addr] == 4} {
+ $this setXdata $dec_addr $value
+ $this Simulator_XDATA_sync $addr
+
+ # Expanded RAM
+ } elseif {[string length $addr] == 3} {
+ $this setEram $dec_addr $value
+ $this Simulator_XDATA_sync $addr
+
+ # Internal RAM
+ } else {
+ $this setData $dec_addr $value
+ $this SimGUI_disable_sync
+ $this Simulator_GUI_sync I $dec_addr
+ $this SimGUI_enable_sync
+ }
+
+ if {$bit_addr} {
+ set addr .$addr
+ }
+ $watch_text.[lindex $watch_data($addr) 1] configure -fg ${Simulator::normal_color}
+
+ # Synchronize with help window
+ help_window_update $addr $value
+
+ # Done ...
+ set validator_engaged 0
+ return 1
+ }
+
+ ## Enable entry widgets in register watches
+ # AFFECT ALL ENTRIES (not only valid ones) !!!
+ # @return void
+ public method rightPanel_watch_force_enable {} {
+ if {!$gui_initialized} {CreateRegWatchesGUI}
+
+ set watches_enabled 1
+ foreach addr $watch_addrs {
+ $watch_text.[lindex $watch_data($addr) 1] configure -state normal
+ }
+ }
+
+ ## Enable entry widgets in register watches
+ # Affect only entries with valid address (implemented on current MCU)
+ # @return void
+ public method rightPanel_watch_enable {} {
+ if {!$gui_initialized} {CreateRegWatchesGUI}
+
+ set watches_enabled 1
+ foreach addr $watch_addrs {
+ if {[string index $addr 0] == {.}} {
+ set addr [string replace $addr 0 0]
+ set bit_addr 1
+ } {
+ set bit_addr 0
+ }
+ set dec_addr [expr "0x$addr"]
+ set len [string length $addr]
+
+ # Bit
+ if {$bit_addr} {
+ if {$dec_addr > 0x7F} {
+ if {![$this simulator_is_sfr_avaliable [$this getRegOfBit $dec_addr]]} {
+ continue
+ }
+ }
+ set addr ".$addr"
+
+ # Internal RAM
+ } elseif {$len < 3} {
+ if {$dec_addr >= [lindex [$this cget -procData] 3]} {
+ continue
+ }
+
+ # Expanded RAM
+ } elseif {$len == 3} {
+ if {$dec_addr >= [lindex [$this cget -procData] 8]} {
+ continue
+ }
+
+ # External RAM
+ } else {
+ if {$dec_addr >= [$this cget -P_option_mcu_xdata]} {
+ continue
+ }
+ }
+
+ $watch_text.[lindex $watch_data($addr) 1] configure -state normal
+ }
+ }
+
+ ## Disable all entry widgets in register watches
+ # @return void
+ public method rightPanel_watch_disable {} {
+ if {!$gui_initialized} {return}
+
+ set watches_enabled 0
+ foreach addr $watch_addrs {
+ $watch_text.[lindex $watch_data($addr) 1] configure -state disabled
+ }
+ }
+ ## Select line in list of register watches
+ # @parm Int x - relative X coordinate
+ # @parm Int y - relative Y coordinate
+ # @return void
+ public method rightPanel_watch_click {x y} {
+ rightPanel_watch_switch_line [expr {int([$watch_text index @$x,$y])}]
+ $watch_search_entry delete 0 end
+ }
+
+ ## Change current line in register watches
+ # @parm Int row - target line
+ # @return void
+ public method rightPanel_watch_switch_line {row} {
+ if {!$gui_initialized} {return}
+ set watch_AN_valid_ena 0
+
+ # Determinate number of the last row
+ set end [$watch_text index end]
+ set end [expr {int($end) - 1}]
+
+ # Restore previous state of the last selected entry box
+ if {$watch_curLine} {
+ set addr [lindex $watch_addrs [expr {$watch_curLine - 1}]]
+ set var [lindex $watch_data($addr) 1]
+ $watch_text.$var selection clear
+ $watch_text.$var configure \
+ -disabledbackground {#FFFFFF} \
+ -bg {#FFFFFF}
+ }
+
+ # Enable/Disable buttons and Clear/Keep entry widgets at the bottom
+ if {$row == $end} {
+ $watch_remove_button configure -state disabled
+ $watch_new_button configure -state disabled
+ $watch_add_button configure -state normal
+ set watch_curLine 0
+ $watch_text tag remove tag_curLine 1.0 end
+ set ::RightPanel::watch_name${obj_idx} {}
+ set ::RightPanel::watch_addr${obj_idx} {}
+ set watch_AN_valid_ena 1
+ return 0
+ } {
+ set watch_curLine $row
+ $watch_remove_button configure -state normal
+ $watch_new_button configure -state normal
+ $watch_add_button configure -state disabled
+ }
+
+ # Determinate text indexes
+ set idx0 "$row.0"
+ set idx1 [expr {$row + 1}]
+ append idx1 {.0}
+
+ # Set selection tag
+ $watch_text tag remove tag_curLine 1.0 end
+ $watch_text tag add tag_curLine $idx0 $idx1
+
+ # Adjust content of entry widgets at the bottom
+ set addr [lindex $watch_addrs [expr {$watch_curLine - 1}]]
+ set name [lindex $watch_data($addr) 0]
+ set var [lindex $watch_data($addr) 1]
+
+ set ::RightPanel::watch_name${obj_idx} [string trimright $name]
+ set ::RightPanel::watch_addr${obj_idx} [string trimright $addr]
+
+ # Change foreground color of current value entry
+ $watch_text.$var configure \
+ -fg ${Simulator::normal_color} \
+ -bg ${::RightPanel::selection_color_dark} \
+ -disabledbackground ${::RightPanel::selection_color_dark}
+
+ # Focus on value entry
+ focus $watch_text.$var
+ $watch_text.$var selection range 0 end
+ $watch_text see $row.0
+
+ set watch_AN_valid_ena 1
+ }
+
+ ## Create a new register watch
+ # @parm String - Hex address, {} == Content of address entry
+ # @parm String - Register name, {} == Content of name entry
+ # @return void
+ public method rightPanel_watch_add args {
+ # Local variables
+ set row [$watch_text index end] ;# Last row in the list
+ set row [expr {int($row) - 1}]
+ set addr [lindex $args 0] ;# Register address (Hex String)
+ set name [lindex $args 1] ;# Watch name
+ set shortAddr {} ;# Register address (Hex Number)
+
+ if {$addr == {} || $name == {}} {
+ set addr [get_watchAddr "\n"]
+ set name [get_watchName "\n"]
+ set no_sbar 0
+ } {
+ set addr [get_watchAddr $addr]
+ set name [get_watchName $name]
+ set no_sbar 1
+ }
+ set shortAddr [regsub {^\s*} $addr {}]
+
+ # Check address validity
+ if {$shortAddr == {}} {
+ if {!$no_sbar} {
+ Sbar [mc "You must specify the register address."]
+ }
+ return 0
+ }
+ if {[lsearch -ascii -exact $watch_addrs $shortAddr] != -1} {
+ if {!$no_sbar} {
+ Sbar [mc "Specified address is already used."]
+ }
+ return 0
+ }
+
+ # Enable text widget
+ $watch_text configure -state normal
+ # Insert address and watch name
+ $watch_text insert end "$addr $name"
+ # Insert text tags
+ regsub {^ +} $addr {} addr
+ set entry [watch_create_entry $addr $row $watch_entry_count]
+ $watch_text window create end -window $entry -pady 0
+ $watch_text insert end "\n"
+ set len [string length $addr]
+ if {$len == 4} {
+ set addr_tag {tag_Xaddr}
+ } elseif {$len == 3 && ([string index $addr 0] == {.})} {
+ set addr_tag {tag_Baddr}
+ } elseif {$len == 3} {
+ set addr_tag {tag_Eaddr}
+ } else {
+ set addr_tag {tag_addr}
+ }
+ $watch_text tag add $addr_tag $row.0 $row.4
+ $watch_text tag add tag_name $row.5 $row.28
+ # Disable text widget
+ $watch_text configure -state disabled
+
+ # Register new watch
+ regsub {\t+$} $name {} name
+ lappend watch_addrs $addr
+ set watch_data($addr) [list $name $watch_entry_count]
+
+ # Synchronize
+ rightPanel_watch_sync $addr
+ $entry configure -fg ${Simulator::normal_color}
+
+ # Enable/Disable the entry widget
+ if {!$watches_enabled} {
+ $entry configure -state disabled
+ }
+
+ incr watch_entry_count
+
+ # Reevaluate button states
+ watch_disEna_buttons
+
+ # Clear search entry
+ $watch_search_entry delete 0 end
+
+ # Adjust status modified
+ set watches_modified 1
+ }
+
+ ## Create entry widget for embedding in list of watches
+ # @parm String addr - hexadecimal register address
+ # @parm Int row - target row in text widget
+ # @parm Variable var - entry text variable
+ # @return Widget - resulting entry widget
+ private method watch_create_entry {addr row var} {
+ if {[string index $addr 0] == {.}} {
+ set width 1
+ } {
+ set width 2
+ }
+
+ # Create entry widget
+ set entry [entry $watch_text.$var \
+ -width $width \
+ -font ${::Simulator_GUI::entry_font} \
+ -bg {#FFFFFF} -validate key \
+ -takefocus 0 -highlightthickness 0 \
+ -disabledbackground {#FFFFFF} \
+ -vcmd "$this rightPanel_watch_value_validate $addr %P" \
+ -bd 0 -justify right \
+ ]
+
+ # Set event bindings
+ bind $entry <Button-1> "$this rightPanel_watch_switch_line $row"
+ bind $entry <Key-Up> "$this rightPanel_watch_up 1"
+ bind $entry <Key-Down> "$this rightPanel_watch_down 1"
+ bind $entry <Key-Next> "$this rightPanel_watch_down 4"
+ bind $entry <Key-Prior> "$this rightPanel_watch_up 4"
+ bind $entry <Motion> {help_window_show %X %Y}
+ bind $entry <Leave> {help_window_hide}
+ bind $entry <Enter> "$this create_help_window_ram ${addr}h; help_window_variable_addr"
+ bind $entry <Button-4> "$watch_text yview scroll -5 units"
+ bind $entry <Button-5> "$watch_text yview scroll +5 units"
+ watch_entry_shortcuts_reset $entry
+
+ # Return entry reference
+ return $entry
+ }
+
+ ## Clear highlight for all registers
+ # @return void
+ public method rightPanel_watch_clear_highlight {} {
+ if {!$gui_initialized} {return}
+
+ foreach addr $watch_addrs {
+ $watch_text.[lindex $watch_data($addr) 1] configure -fg ${Simulator::normal_color}
+ }
+ }
+
+ ## Clear highlight for the given register
+ # @return void
+ public method rightPanel_watch_unhighlight {addr} {
+ if {!$gui_initialized} {return}
+
+ if {[lsearch $watch_addrs $addr] == -1} {
+ return
+ }
+ $watch_text.[lindex $watch_data($addr) 1] configure -fg ${Simulator::normal_color}
+ }
+
+ ## Move current watch to the top
+ # @return void
+ public method rightPanel_watch_move_top {} {
+ rightPanel_watch_move 1
+ }
+
+ ## Move current watch to up
+ # @return void
+ public method rightPanel_watch_move_up {} {
+ # Determinate target line
+ set target_line [expr {$watch_curLine - 1}]
+ if {$target_line == 0} {return 0}
+ # Move watch
+ rightPanel_watch_move $target_line
+ }
+
+ ## Move current watch to down
+ # @return void
+ public method rightPanel_watch_move_down {} {
+ # Determinate target line
+ set target_line [expr {$watch_curLine + 1}]
+ set end [$watch_text index end]
+ set end [expr {int($end) - 1}]
+ if {$target_line == $end} {return 0}
+ # Move watch
+ rightPanel_watch_move $target_line
+ }
+
+ ## Move current watch to the bottom
+ # @return void
+ public method rightPanel_watch_move_bottom {} {
+ # Determinate target line
+ set target_line [$watch_text index end]
+ set target_line [expr {int($target_line) - 2}]
+ # Move watch
+ rightPanel_watch_move $target_line
+ }
+
+ ## Move current watch to the given line
+ # @parm Int target_line - target line
+ # @return void
+ private method rightPanel_watch_move {target_line} {
+ # Validate current line value
+ if {$watch_curLine == 0} {return}
+
+ # Local variables
+ set cur_idx [expr {$watch_curLine - 1}] ;# index in $watch_addrs -- current line
+ set trg_idx [expr {$target_line - 1}] ;# index in $watch_addrs -- target line
+ set addr [lindex $watch_addrs $cur_idx] ;# register address
+ set name [lindex $watch_data($addr) 0] ;# watch name
+ set var [lindex $watch_data($addr) 1] ;# textvariable of the value entry
+
+ # Modify variables related to the watch
+ set watch_addrs [lreplace $watch_addrs $cur_idx $cur_idx]
+ set watch_addrs [linsert $watch_addrs $trg_idx $addr]
+
+ # Enable the widget
+ $watch_text configure -state normal
+ # Change textual content
+ $watch_text delete $watch_curLine.0 "$watch_curLine.0 + 1 line linestart"
+ $watch_text insert $target_line.0 "[get_watchAddr $addr] [get_watchName $name]\n"
+ # Destroy the current entry widget
+ destroy $watch_text.$var
+ # Change embedded entry
+ set entry [watch_create_entry $addr $target_line $var]
+ $watch_text window create [list $target_line.0 lineend] -window $entry -pady 0
+ set len [string length $addr]
+ if {$len == 4} {
+ set addr_tag {tag_Xaddr}
+ } elseif {$len == 3 && ([string index [string trim $addr] 0] == {.})} {
+ set addr_tag {tag_Baddr}
+ } elseif {$len == 3} {
+ set addr_tag {tag_Eaddr}
+ } {
+ set addr_tag {tag_addr}
+ }
+ # Restore text tags
+ $watch_text tag add $addr_tag $target_line.0 $target_line.4
+ $watch_text tag add tag_name $target_line.5 $target_line.28
+ # Disable the widget
+ $watch_text configure -state disabled
+
+ # Synchronize entry widget content
+ rightPanel_watch_sync $addr
+
+ # Enable/Disable the entry widget
+ if {!$watches_enabled} {
+ $entry configure -state disabled
+ }
+
+ # Set current line
+ set watch_curLine $target_line
+ rightPanel_watch_switch_line $target_line
+
+ # Clear search entry
+ $watch_search_entry delete 0 end
+
+ # Adjust status modified
+ set watches_modified 1
+ }
+
+ ## Change current line in list of register watches to the line above the current one
+ # @parm Int lines - number of lines to skip - 1
+ # @return void
+ public method rightPanel_watch_up {lines} {
+ # Determinate number of last row in the widget
+ set end [$watch_text index end]
+ set end [expr {int($end) - 2}]
+
+ # Change current line (logicaly)
+ set line $watch_curLine
+ incr line -$lines
+ if {$line < 1} {
+ set line 1
+ }
+
+ # Change current line (physicaly)
+ $watch_text see $watch_curLine.0
+ rightPanel_watch_switch_line $line
+
+ # Clear search entry
+ $watch_search_entry delete 0 end
+ }
+
+ ## Change current line in list of register watches to the line below the current one
+ # @parm Int lines - number of lines to skip - 1
+ # @return void
+ public method rightPanel_watch_down {lines} {
+ # Determinate number of last row in the widget
+ set end [$watch_text index end]
+ set end [expr {int($end) - 2}]
+
+ # Change current line (logicaly)
+ set line $watch_curLine
+ incr line $lines
+ if {$line > $end} {
+ set line $end
+ }
+
+ # Change current line (physicaly)
+ $watch_text see $watch_curLine.0
+ rightPanel_watch_switch_line $line
+
+ # Clear search entry
+ $watch_search_entry delete 0 end
+ }
+
+ ## Binding for button "New" (Clears entry widgets at the bottom and unselect current watch)
+ # @return void
+ public method rightPanel_watch_new {} {
+ set end [$watch_text index end]
+ set end [expr {int($end) - 1}]
+ rightPanel_watch_switch_line $end
+
+ # Clear search entry
+ $watch_search_entry delete 0 end
+ }
+
+ ## Remove the current register watch
+ # @return void
+ public method rightPanel_watch_remove {} {
+ # Determinate register address
+ set addr [lindex $watch_addrs [expr {$watch_curLine - 1}]]
+ # Destroy value entry
+ set var [lindex $watch_data($addr) 1]
+ destroy $watch_text.$var
+ # Unregister watch
+ unset watch_data($addr)
+ set idx [lsearch $watch_addrs $addr]
+ set watch_addrs [lreplace $watch_addrs $idx $idx]
+
+ # Remove watch from the text widget
+ $watch_text configure -state normal
+ $watch_text delete $watch_curLine.0 "$watch_curLine.0 + 1 line"
+ $watch_text configure -state disabled
+
+ # Change current line
+ if {$watch_curLine > [llength $watch_addrs]} {
+ set watch_curLine [llength $watch_addrs]
+ }
+ if {$watch_curLine} {
+ rightPanel_watch_switch_line $watch_curLine
+ }
+
+ # Reevaluate button states
+ watch_disEna_buttons
+ # Clear search entry
+ $watch_search_entry delete 0 end
+ # Adjust status modified
+ set watches_modified 1
+ }
+
+ ## Save watches definition to a file
+ # @parm String filename - Target filename or an empty string
+ # @parm Bool force = 0 - Do not ask for overwrite
+ # @return void
+ public method rightPanel_watch_save args {
+ if {!$gui_initialized} {CreateRegWatchesGUI}
+
+ set filename [lindex $args 0]
+ set force [lindex $args 1]
+ if {$filename != {}} {
+ set watch_file_name $filename
+ }
+ if {$force != {1}} {
+ set force 0
+ }
+
+ # If no filename specified -> invoke dislog "Save as"
+ if {$watch_file_name == {}} {
+ rightPanel_watch_saveas
+
+ # Save file
+ } {
+ # Set new filename
+ if {!$::MICROSOFT_WINDOWS} { ;# POSIX way
+ if {![regexp "^(~|/)" $watch_file_name]} {
+ set filename "[$this cget -ProjectDir]/$watch_file_name"
+ }
+ } { ;# Microsoft windows way
+ if {![regexp "^\w:" $watch_file_name]} {
+ set filename [file join [$this cget -ProjectDir] $watch_file_name]
+ }
+ }
+
+ set watch_file_name [file normalize $watch_file_name]
+ # Adjust file extension
+ if {![regexp {\.wtc$} $watch_file_name]} {
+ append watch_file_name {.wtc}
+ }
+
+ if {[file exists $watch_file_name] && [file isfile $watch_file_name]} {
+ # Ask user for overwrite existing file
+ if {!$force && [tk_messageBox \
+ -type yesno \
+ -icon question \
+ -parent . \
+ -title [mc "Overwrite file"] \
+ -message [mc "A file name '%s' already exists. Are you sure you want to overwrite it ?" [file tail $watch_file_name]]
+ ] != {yes}
+ } {
+ return
+ }
+ # Create a backup file
+ catch {
+ file rename -force $watch_file_name "$watch_file_name~"
+ }
+ }
+ if {[catch {
+ set file [open $watch_file_name w 420]
+ }]} {
+ if {[winfo exists .fsd]} {
+ set parent .fsd
+ } {
+ set parent .
+ }
+ tk_messageBox -type ok \
+ -parent $parent -icon warning \
+ -title [mc "Error - MCU 8051 IDE"] \
+ -message [mc "Unable to access file \"%s\", check your permissions." $watch_file_name]
+ return
+ }
+
+ # Write file header
+ puts $file "# Watches definition file -- ${::APPNAME}"
+ puts $file "# Date: [clock format [clock seconds] -format {%D}]"
+
+ # Write watches definition
+ puts -nonewline $file [regsub -all -line {\s+$} [$watch_text get 1.0 end] {}]
+
+ # Finish
+ close $file
+ Sbar [mc "Definitions saved to \"%s\"" $watch_file_name]
+
+ # Adjust status modified
+ set watches_modified 0
+ }
+ }
+
+ ## Invoke dialog "Save as" - Register watches
+ # @return void
+ public method rightPanel_watch_saveas {} {
+
+ # Abort if there is already opened some file selection dialog
+ if {[winfo exists .fsd]} {return}
+
+ # Invoke the dialog
+ KIFSD::FSD ::fsd \
+ -title [mc "Save watches - MCU 8051 IDE"] \
+ -directory [$this cget -ProjectDir] \
+ -defaultmask 0 -multiple 0 -filetypes {
+ {{MCU 8051 IDE watch definition} {*.wtc} }
+ {{All files} {*} }
+ }
+ # Save file after press of OK button
+ ::fsd setokcmd {
+ set ::filename [::fsd get]
+ if {$::filename != {} && ![file isdirectory $::filename]} {
+ ${::X::actualProject} rightPanel_watch_save $::filename
+ }
+ }
+ # Activate the dialog
+ ::fsd activate
+ }
+
+ ## Open and process watches definition file
+ # @parm String filename - name of source file
+ # @parm Widget parent - GUI parent (for error dialogs)
+ # @parm Bool clear - Clear watches before loading
+ # @return Bool - result
+ public method rightPanel_watch_openfile {filename parent clear} {
+ if {!$gui_initialized} {CreateRegWatchesGUI}
+
+ # Normalize filename
+ if {!$::MICROSOFT_WINDOWS} { ;# POSIX way
+ if {![regexp "^(~|/)" $filename]} {
+ set filename "[$this cget -projectPath]/$filename"
+ }
+ } { ;# Microsoft windows way
+ if {![regexp "^\w:" $filename]} {
+ set filename [file join [$this cget -projectPath] $filename]
+ }
+ }
+ set filename [file normalize $filename]
+
+ # Set new watches filename
+ set watch_file_name $filename
+
+ # Open file
+ if {[catch {
+ set file [open $filename r]
+ }]} then {
+ tk_messageBox -parent $parent -icon warning -type ok \
+ -title [mc "File access error"] \
+ -message [mc "Unable to read file '%s'" $filename]
+ set watch_file_name {}
+ return 0
+ }
+
+ # Verify input data validity
+ while {![eof $file]} {
+ set line [gets $file]
+
+ # Skip comments and empty lines
+ if {[regexp {^\s*#} $line]} {continue}
+ if {[regexp {^\s*$} $line]} {continue}
+
+ # Local variables
+ regexp {^\s*\.?\w+} $line addr ;# Register address
+ regsub {^\s*\.?\w+\s*} $line {} name ;# Watch name
+ regsub {\s+$} $name {} name
+
+ # Check for address and name validity
+ if {
+ ![regexp {^\s*\.?[A-Fa-f0-9]+$} $addr] ||
+ [string length $addr] > 4 ||
+ [string length $name] > 23
+ } {
+ tk_messageBox \
+ -title [mc "Corrupted file"] \
+ -icon error -type ok -parent $parent \
+ -message [mc "file: %s is eighter corrupted or it is not a file in expected format." $filename]
+ return 0
+ }
+ }
+
+ # Clear watches
+ if {$clear} {
+ rightPanel_watch_clear 1
+ }
+
+ # Parse input data
+ seek $file 0
+ while {![eof $file]} {
+ set line [gets $file]
+
+ # Skip comments and empty lines
+ if {[regexp {^\s*#} $line]} {continue}
+ if {[regexp {^\s*$} $line]} {continue}
+
+ regexp {^\s*\.?\w+} $line addr ;# Register address
+ regsub {^\s*\.?\w+\s*} $line {} name ;# Watch name
+ set addr [string trimleft $addr]
+ set name [string trimright $name]
+
+ # Create new register watch
+ rightPanel_watch_add $addr $name
+ }
+
+ # Deselect all
+ rightPanel_watch_new
+
+ # Reevaluate button states (icon bar)
+ watch_disEna_buttons
+
+ # Adjust status modified
+ set watches_modified 0
+
+ # Success
+ close $file
+ return 1
+ }
+
+ ## Invoke dialog "Open file"
+ # @return void
+ public method rightPanel_watch_open {} {
+ # Invoke the dialog
+ KIFSD::FSD ::fsd \
+ -title [mc "Load watches from file - MCU 8051 IDE"] \
+ -directory [$this cget -ProjectDir] -autoclose 0 \
+ -defaultmask 0 -multiple 0 -filetypes {
+ {{MCU 8051 IDE watches definition} {*.wtc} }
+ {{All files} {*} }
+ }
+
+ # Open file after press of OK button
+ fsd setokcmd {
+ # Get chosen file name
+ set filename [::fsd get]
+ if {[${X::actualProject} rightPanel_watch_openfile $filename [::fsd get_window_name] 1]} {
+ ::fsd deactivate
+ delete object fsd
+ }
+ }
+
+ # Activate the dialog
+ fsd activate
+ }
+
+ ## Invoke dialog "Import file"
+ # @return void
+ public method rightPanel_watch_import {} {
+ # Invoke the dialog
+ KIFSD::FSD ::fsd \
+ -title [mc "Import file - MCU 8051 IDE"] \
+ -directory [$this cget -ProjectDir] -autoclose 0 \
+ -defaultmask 0 -multiple 0 -filetypes {
+ {{Code listing} {*.lst} }
+ {{MCU 8051 IDE watches definition} {*.wtc} }
+ {{All files} {*} }
+ }
+
+ # Open file after press of OK button
+ fsd setokcmd {
+ # Get chosen file name
+ set filename [::fsd get]
+ if {[${X::actualProject} rightPanel_watch_import_file $filename [::fsd get_window_name]]} {
+ ::fsd deactivate
+ delete object fsd
+ }
+ }
+
+ # Activate the dialog
+ fsd activate
+ }
+
+ ## Import file
+ # @parm String filename - Name of source file (*.lst or *.wtc)
+ # @parm Widget parent - GUI parent (for error dialogs)
+ # @return Bool - result
+ public method rightPanel_watch_import_file {filename parent} {
+ if {!$gui_initialized} {CreateRegWatchesGUI}
+
+ # Determinate file type
+ set filename [file normalize [file join [$this cget -ProjectDir] $filename]]
+ set file_type 0
+ switch -- [file extension $filename] {
+ {.wtc} { ;# Watches definition file
+ set file_type 1
+ }
+ {.lst} { ;# Code listing
+ set file_type 2
+ }
+ default { ;# Try to detect file type by file header
+ catch {
+ set file [open $filename r]
+ if {[string first {# Watches definition file} [gets $file]] == 0} {
+ set file_type 1
+ }
+ close $file
+ }
+ }
+ }
+
+ # Unknown file type
+ if {!$file_type} {
+ tk_messageBox \
+ -parent . \
+ -type ok \
+ -icon warning \
+ -title [mc "Unknown file"] \
+ -message [mc "Unable to recognize file format"]
+ return 0
+ }
+
+ # -----------------------------------------------------------------------
+ ## WTC file - load and exit procedure
+ # -----------------------------------------------------------------------
+ if {$file_type == 1} {
+ return [rightPanel_watch_openfile $filename $parent 0]
+ }
+
+
+ # -----------------------------------------------------------------------
+ # LST file
+ # -----------------------------------------------------------------------
+
+ # Try to open file
+ if {[catch {
+ set file [open $filename r]
+ }]} {
+ tk_messageBox \
+ -parent . \
+ -type ok \
+ -icon warning \
+ -title [mc "File access error"] \
+ -message [mc "Unable to open file:\n'%s'" $filename]
+ return 0
+ }
+
+ # Parse file
+ set read_line 0
+ set line {}
+ set name {}
+ set addr {}
+ set type {}
+ set bita 0
+ while {![eof $file]} {
+ set bita 0
+ set line [gets $file]
+
+ # Empty line - stop reading
+ if {![string length [string trimright $line "  \f"]]} {
+ set read_line 0
+ continue
+
+ # MCU 8051 IDE Assembler symbol table
+ } elseif {![string first {SYMBOL TABLE:} $line]} {
+ set read_line 1
+ continue
+
+ # ASEM-51 Assembler symbol table
+ } elseif {![string first {------------------------------------------------------------} $line]} {
+ set read_line 2
+ continue
+ }
+
+
+ # MCU 8051 IDE Assembler symbol
+ if {$read_line == 1} {
+ if {![regexp {^\w+} $line name]} {
+ continue
+ }
+ if {![regexp {[\w\s]+$} $line line]} {
+ continue
+ }
+ set type [lindex $line 0]
+
+ # Ignore all types except address
+ if {[lindex $line 1] != {ADDR}} {
+ continue
+ }
+
+ # Internal data memory
+ if {$type == {D} || $type == {I}} {
+ set addr [string range [lindex $line 2] 2 3]
+ # External data memory (inluding ERAM, EEPROM, etc.)
+ } elseif {$type == {X}} {
+ set addr [string range [lindex $line 2] 0 3]
+ # Bit addressable area
+ } elseif {$type == {B}} {
+ set bita 1
+ set addr [string range [lindex $line 2] 2 3]
+ # Another type of memory -> IGNORE
+ } else {
+ continue
+ }
+
+ # Ignore unused symbols
+ if {[lindex $line end-1] == {NOT} || [lindex $line end-2] == {NOT}} {
+ continue
+ }
+
+ # ASEM-51 Assembler symbol
+ } elseif {$read_line == 2} {
+ # Remove dangerous characters
+ regsub -all {\{\}\"\"} $line {} line
+
+ # Ignore unused symbols
+ if {[llength $line] < 4} {
+ continue
+ }
+
+ # Determinate address and symbol name
+ set type [lindex $line 1]
+ set addr [lindex $line 2]
+ set name [lindex $line 0]
+
+ # Accept only internal and external data memory
+ if {$type != {IDATA} && $type != {DATA} && $type != {XDATA} && $type != {BIT}} {
+ continue
+ }
+ if {$type == {BIT}} {
+ set bita 1
+ }
+
+ # This line is not a part of symbol table
+ } else {
+ continue
+ }
+
+ # Address must be a valid hexadecimal value
+ if {![string is xdigit -strict $addr]} {
+ continue
+ }
+
+ # Exclude SFR's
+ if {[lsearch -ascii -exact ${::ASMsyntaxHighlight::spec_registers} $name] != -1} {
+ continue
+ }
+
+ # Create new register watch
+ if {[string length $name] > 23} {
+ set name [string range $name 0 16]
+ append name {..}
+ }
+
+ if {$bita} {
+ set addr .$addr
+ }
+
+ rightPanel_watch_add $addr $name
+ set watches_modified 1
+ }
+
+ # Finalize
+ rightPanel_watch_new
+ watch_disEna_buttons
+ close $file
+ return 1
+ }
+
+ ## Remove all register watches
+ # Bool force = 0 - Don't ask user for comfirmation
+ # @return void
+ public method rightPanel_watch_clear args {
+ if {!$gui_initialized} {CreateRegWatchesGUI}
+
+ # Parse arguments
+ set force [lindex $args 0]
+ if {$force == {}} {
+ set force 0
+ }
+
+ # Ask user for comfirmation
+ if {!$force} {
+ if {[tk_messageBox \
+ -parent . \
+ -type yesno \
+ -icon question \
+ -title [mc "Are you sure ?"] \
+ -message [mc "Do you really want to clear the panel ?"]
+ ] != {yes}} {
+ return
+ }
+ }
+
+ # Clear text widget
+ $watch_text configure -state normal
+ $watch_text delete 1.0 end
+ $watch_text configure -state disabled
+
+ # Destroy all embedded entry widgets
+ foreach addr $watch_addrs {
+ destroy $watch_text.[lindex $watch_data($addr) 1]
+ }
+
+ # Clear entries on the bottom bar
+ set watch_curLine 0
+ set ::RightPanel::watch_name${obj_idx} {}
+ set ::RightPanel::watch_addr${obj_idx} {}
+
+ # Unregister all watches
+ set watch_addrs {}
+ catch {
+ array unset watch_data
+ }
+
+ # Reevaluate button states (icon bar)
+ watch_disEna_buttons
+
+ # Adjust status modified
+ set watches_modified 1
+ }
+
+ ## Search for the given string in the list of register watches -- search entry validator
+ # @parm String content - String to find/validate
+ # @return Bool - result
+ public method rightPanel_watch_search_validate {content} {
+ if {$search_val_in_progress} {return 0}
+ set search_val_in_progress 1
+
+ # Enable/Disable button "Clear search entry"
+ if {$content == {}} {
+ $watch_search_clear configure -state disabled
+ } {
+ $watch_search_clear configure -state normal
+ }
+
+ # Validate search string
+ if {[regexp {^\s*$} $content]} {
+ $watch_search_entry configure -style TEntry
+ set search_val_in_progress 0
+ return 1
+ }
+ if {[string length $content] > 23} {
+ set search_val_in_progress 0
+ return 0
+ }
+
+ # Search for the given string
+ set i 1
+ set content [string trimright $content]
+ set content [string tolower $content]
+ foreach addr $watch_addrs {
+ if {![string first $content [string tolower [lindex $watch_data($addr) 0]]]} {
+ $watch_search_entry configure -style StringFound.TEntry
+ rightPanel_watch_switch_line $i
+ focus $watch_search_entry
+ set search_val_in_progress 0
+ return 1
+ }
+ incr i
+ }
+
+ # String not found
+ $watch_search_entry configure -style StringNotFound.TEntry
+ set search_val_in_progress 0
+ return 1
+ }
+
+ ## Syncronize all register watches
+ # @return void
+ public method rightPanel_watch_sync_all {} {
+ if {!$gui_initialized} {CreateRegWatchesGUI}
+
+ # Iterate over addresses
+ foreach addr $watch_addrs {
+ # Synchronize
+ rightPanel_watch_sync $addr
+ # Clear highligh
+ set var [lindex $watch_data($addr) 1]
+ $watch_text.$var configure -fg ${Simulator::normal_color}
+ }
+ }
+
+ ## Read value from simulator engine
+ # @parm String addr - hexadecimal register address
+ # @return String - hexadecimal value or {--}
+ private method read_from_simulator {addr} {
+ ## Determinate address type (Bit / Internal / Enternal / Expanded)
+ if {[string index $addr 0] == {.}} {
+ set addr [string replace $addr 0 0]
+ if {![string length $addr]} {
+ return {--}
+ }
+ set bit_addr 1
+ } {
+ set bit_addr 0
+ }
+ set len [string length $addr]
+ set val {--}
+ set addr_dec [expr "0x$addr"]
+
+ # Bit
+ if {$bit_addr} {
+ if {$addr_dec > 0x7F} {
+ if {[$this simulator_is_sfr_avaliable [$this getRegOfBit $addr_dec]]} {
+ set val [$this getBit $addr_dec]
+ }
+ } {
+ set val [$this getBit $addr_dec]
+ }
+
+ # Internal RAM
+ } elseif {$len < 3} {
+ # Normalize address
+ if {$len == 1} {
+ set addr "0$addr"
+ }
+ # Get register value
+ if {$addr_dec < [lindex [$this cget -procData] 3]} {
+ set val [$this getData $addr_dec]
+ }
+
+ # Expanded RAM
+ } elseif {$len == 3} {
+ if {$addr_dec < [lindex [$this cget -procData] 8]} {
+ set val [$this getEram $addr_dec]
+ }
+
+ # External RAM
+ } elseif {$len == 4} {
+ if {$addr_dec < [$this cget -P_option_mcu_xdata]} {
+ set val [$this getXdata $addr_dec]
+ }
+ }
+
+ return $val
+ }
+
+ ## Synchronize all bits in the specified SFR
+ # @parm Int dec_addr - SFR register address
+ # @return void
+ public method rightPanel_watch_sync_sfr {dec_addr} {
+ if {$validator_engaged} {
+ return
+ }
+ if {$dec_addr % 8} {
+ return
+ }
+
+ for {set i 0} {$i < 8} {incr i} {
+ rightPanel_watch_sync .[format %X $dec_addr]
+ incr dec_addr
+ }
+ }
+
+ ## Synchronize one register watch
+ # @parm String addr - hexadecimal register address
+ # @return Bool - result
+ public method rightPanel_watch_sync {addr} {
+ if {$validator_engaged} {return 1}
+ if {!$gui_initialized} {CreateRegWatchesGUI}
+
+ # Detect bit address
+ if {[string index $addr 0] == {.}} {
+ set bit_addr 1
+ } {
+ set bit_addr 0
+ }
+
+ # Get register value
+ set val [read_from_simulator $addr]
+
+ # Synchronize bits in the given register
+ if {!$validator_engaged && [string length $addr] == 2} {
+ set dec_addr [expr "0x$addr"]
+
+ if {$dec_addr >= 0x20 && $dec_addr <= 0x2F} {
+ set dec_addr [expr {($dec_addr - 0x20) * 8}]
+ for {set i 0} {$i < 8} {incr i} {
+
+ set hex_addr [format %X $dec_addr]
+ if {[string length $hex_addr] == 1} {
+ set hex_addr "0$hex_addr"
+ }
+ rightPanel_watch_sync .$hex_addr
+ incr dec_addr
+ }
+ }
+ }
+
+ # Check for watch presence
+ if {[lsearch -ascii -exact $watch_addrs $addr] == -1} {
+ return 0
+ }
+
+ # Normalize register value
+ if {!$bit_addr && [string length $val] == 1} {
+ set val "0$val"
+ }
+
+ set var [lindex $watch_data($addr) 1]
+ set path $watch_text.$var ;# Path to watch entry widget
+
+ # Determinate original value
+ set original_val [$watch_text.$var get]
+
+ # Highlight value entry
+ if { "0x$original_val" != "0x$val"} {
+ $path configure -fg ${Simulator::highlight_color}
+ }
+
+ # Set new entry value
+ set validator_engaged 1
+ $watch_text.$var delete 0 end
+ $watch_text.$var insert 0 $val
+ set validator_engaged 0
+
+ # Synchronize with help window
+ help_window_update $addr $val
+
+ # Done ...
+ return 1
+ }
+
+ ## Enable/Disable buttons on watches icon bar
+ # @return void
+ private method watch_disEna_buttons {} {
+ if {!$gui_initialized} {return}
+
+ if {[$watch_text index end] == {2.0}} {
+ set state {disabled}
+ } {
+ set state {normal}
+ }
+
+ if {$conf_menu != {}} {
+ $conf_menu entryconfigure [::mc "Sort by"] -state $state
+ $conf_menu entryconfigure [::mc "Remove all"] -state $state
+ }
+ }
+
+ ## Get status modified for register watches
+ # @return Bool - true if register watches were modified
+ public method rightPanel_watch_modified {} {
+ return $watches_modified
+ }
+
+ ## Invoke register watches popup menu
+ # @parm Int X - absolute X coordinate
+ # @parm Int Y - absolute Y coordinate
+ # @parm Int x - relative X coordinate
+ # @parm Int y - relative Y coordinate
+ # @return void
+ public method rightPanel_watch_popupmenu {X Y x y} {
+ # Change current line
+ rightPanel_watch_click $x $y
+
+ ## Enable/Disable menu items
+
+ # If address entry is not empty -> disable all
+ set addr [subst "\$::RightPanel::watch_addr${obj_idx}"]
+ if {$addr != {}} {
+ set end [$watch_text index end]
+ } {
+ set end {2.0}
+ }
+ # Empty list
+ if {$end == {2.0}} {
+ $watch_menu entryconfigure [::mc "Move top"] -state disabled
+ $watch_menu entryconfigure [::mc "Move up"] -state disabled
+ $watch_menu entryconfigure [::mc "Move down"] -state disabled
+ $watch_menu entryconfigure [::mc "Move bottom"] -state disabled
+ $watch_menu entryconfigure [::mc "Remove"] -state disabled
+ $watch_menu entryconfigure [::mc "Remove all"] -state disabled
+ # One item
+ } elseif {$end == {3.0}} {
+ $watch_menu entryconfigure [::mc "Move top"] -state disabled
+ $watch_menu entryconfigure [::mc "Move up"] -state disabled
+ $watch_menu entryconfigure [::mc "Move down"] -state disabled
+ $watch_menu entryconfigure [::mc "Move bottom"] -state disabled
+ $watch_menu entryconfigure [::mc "Remove"] -state normal
+ $watch_menu entryconfigure [::mc "Remove all"] -state normal
+ # More items
+ } else {
+ # First item
+ if {$watch_curLine == 1} {
+ $watch_menu entryconfigure [::mc "Move top"] -state disabled
+ $watch_menu entryconfigure [::mc "Move up"] -state disabled
+ $watch_menu entryconfigure [::mc "Move down"] -state normal
+ $watch_menu entryconfigure [::mc "Move bottom"] -state normal
+ # Last item
+ } elseif {$watch_curLine == ($end - 2)} {
+ $watch_menu entryconfigure [::mc "Move top"] -state normal
+ $watch_menu entryconfigure [::mc "Move up"] -state normal
+ $watch_menu entryconfigure [::mc "Move down"] -state disabled
+ $watch_menu entryconfigure [::mc "Move bottom"] -state disabled
+ # Any other item
+ } else {
+ $watch_menu entryconfigure [::mc "Move top"] -state normal
+ $watch_menu entryconfigure [::mc "Move up"] -state normal
+ $watch_menu entryconfigure [::mc "Move down"] -state normal
+ $watch_menu entryconfigure [::mc "Move bottom"] -state normal
+ }
+ $watch_menu entryconfigure [::mc "Remove"] -state normal
+ $watch_menu entryconfigure [::mc "Remove all"] -state normal
+ }
+
+ # Invoke popup menu
+ tk_popup $watch_menu $X $Y
+ }
+
+
+ ## Create bindings for defined key shortcuts -- register watches
+ # @return void
+ public method rightPanel_watch_shortcuts_reevaluate {} {
+ if {!$gui_initialized} {return}
+ foreach addr $watch_addrs {
+ watch_entry_shortcuts_reset watch_text.[lindex $watch_data($addr) 1]
+ }
+ }
+
+ ## Set flag enabled
+ # @parm Bool bool - New value
+ # @return void
+ public method right_panel_watches_set_enabled {bool} {
+ set enabled $bool
+ }
+}
+
+set ::RegWatches::menu_autoload [lindex $::CONFIG(REGWATCHES_CONFIG) 0]
+set ::RegWatches::sorting_order [lindex $::CONFIG(REGWATCHES_CONFIG) 1]
diff --git a/lib/rightpanel/rightpanel.tcl b/lib/rightpanel/rightpanel.tcl
new file mode 100755
index 0000000..061f1f5
--- /dev/null
+++ b/lib/rightpanel/rightpanel.tcl
@@ -0,0 +1,2273 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Implements Right Panel
+# Right Panel Notebook consist of:
+# - List of bookmarks
+# - List of breakpoints
+# - List of register watches
+# - Instruction details
+# - List of active subprograms
+# --------------------------------------------------------------------------
+
+# Import nesesary sources
+source "${::LIB_DIRNAME}/rightpanel/regwatches.tcl" ;# Register watches
+source "${::LIB_DIRNAME}/rightpanel/instructiondetails.tcl" ;# Instruction details
+source "${::LIB_DIRNAME}/rightpanel/subprograms.tcl" ;# List of active subprograms
+source "${::LIB_DIRNAME}/rightpanel/hwmanager.tcl" ;# Hardware tools manager
+
+class RightPanel {
+ inherit RegWatches InstructionDetails SubPrograms HwManager
+
+ ## COMMON
+ # Conter of instances
+ common count 0
+ # Background color for selected rows -- light
+ common selection_color {#EEFFDD}
+ # Background color for selected rows -- dark
+ common selection_color_dark {#DDDDFF}
+ # Default font size for text widgets
+ common fontSize ${Editor::fontSize}
+ # Default font family for text widgets
+ common fontFamily ${Editor::fontFamily}
+ # Font used in Editor
+ common editor_font [font create -size -$fontSize -family $fontFamily]
+ # Definition of popup menu for bookmark list
+ common BOOKMARKMENU {
+ {command {Remove} {$edit:bookmark} 0 "editor_procedure {} Bookmark {}"
+ {button_cancel} "Add/Remove editor bookmark to/from current line"}
+ {separator}
+ {command {Previous} {} 0 "rightPanel_bm_up" {1uparrow}
+ "Goto previous bookmark"}
+ {command {Next} {} 0 "rightPanel_bm_up" {1downarrow}
+ "Goto next bookmark"}
+ {separator}
+ {command {Remove all} {} 0 "editor_procedure {} clear_all_bookmarks {}"
+ {editdelete} "Remove all bookmarks from the editor"}
+ }
+ # Definition of popup menu for breakpoint list
+ common BREAKPOINTMENU {
+ {command {Remove} {$edit:breakpoint} 0 "editor_procedure {} Breakpoint {}"
+ {button_cancel} "Add/Remove editor breakpoint to/from current line"}
+ {separator}
+ {command {Previous} {} 0 "rightPanel_bp_up" {1uparrow}
+ "Goto previous breakpoint"}
+ {command {Next} {} 0 "rightPanel_bp_up" {1downarrow}
+ "Goto next breakpoint"}
+ {separator}
+ {command {Remove all} {} 0 "editor_procedure {} clear_all_breakpoints {}"
+ {editdelete} "Remove all breakpoints from the editor"}
+ }
+ # Definition of popup menu for symbols list
+ common SYMBOLSKMENU {}
+
+ ## PRIVATE
+ private variable notebook_frame ;# ID of panel main frame
+ private variable notebook ;# ID of panel NoteBook
+ private variable bookmarks ;# ID of tab "Bookmarks"
+ private variable breakpoints ;# ID of tab "Breakpoints"
+ private variable watches ;# ID of tab "Register watches"
+ private variable instruction ;# ID of tab "Instruction details"
+ private variable subprograms ;# ID of tab "Active subprograms"
+ private variable hwmanager ;# ID of tab "Hardware manager"
+ private variable table_of_symbols ;# ID of tab "Table of symbols"
+ private variable obj_idx ;# Number of this object
+
+ private variable bookmarks_menu ;# ID of popup menu for "Bookmarks"
+ private variable breakpoints_menu ;# ID of popup menu for "Breakpoints"
+ private variable symbols_menu ;# ID of popup menu for "Symbol list"
+
+ private variable bm_pagesManager ;# ID of pages manager for tab "Bookmarks"
+ private variable bp_pagesManager ;# ID of pages manager for tab "Breakpoints"
+ private variable sm_pagesManager ;# ID of pages manager for tab "Symbol list"
+
+ private variable bookmarks_lineNumbers ;# ID of text widget showing line numbers - tab "Bookmarks"
+ private variable breakpoints_lineNumbers ;# ID of text widget showing line numbers - tab "Breakpoints"
+ private variable bookmarks_text ;# ID of list of bookmarks (text widget) - tab "Bookmarks"
+ private variable breakpoints_text ;# ID of list of breakpoints (text widget) - tab "Breakpoints"
+ private variable bm_up_button ;# ID of button "Up" - tab "Bookmarks"
+ private variable bm_down_button ;# ID of button "Down" - tab "Bookmarks"
+ private variable bm_clear_button ;# ID of button "Clear all" - tab "Bookmarks"
+ private variable bp_up_button ;# ID of button "Up" - tab "Breakpoints"
+ private variable bp_down_button ;# ID of button "Down" - tab "Breakpoints"
+ private variable bp_clear_button ;# ID of button "Clear all" - tab "Breakpoints"
+ private variable sm_text ;# ID of symbol list text widget - tab "Symbols"
+ private variable sm_lineNumbers ;# ID of text widget showing line numbers - tab "Symbols"
+
+ private variable LIST_bookmarks_lineNumbers {} ;# List of $bookmarks_lineNumbers (for each editor)
+ private variable LIST_breakpoints_lineNumbers {} ;# List of $breakpoints_lineNumbers (for each editor)
+ private variable LIST_bookmarks_text {} ;# List of $bookmarks_text (for each editor)
+ private variable LIST_breakpoints_text {} ;# List of $breakpoints_text (for each editor)
+ private variable LIST_bm_up_button {} ;# List of $bm_up_button (for each editor)
+ private variable LIST_bm_down_button {} ;# List of $bm_down_button (for each editor)
+ private variable LIST_bm_clear_button {} ;# List of $bm_clear_button (for each editor)
+ private variable LIST_bp_up_button {} ;# List of $bp_up_button (for each editor)
+ private variable LIST_bp_down_button {} ;# List of $bp_down_button (for each editor)
+ private variable LIST_bp_clear_button {} ;# List of $bp_clear_button (for each editor)
+ private variable LIST_sm_text {} ;# List of $sm_text (for each editor)
+ private variable LIST_sm_lineNumbers {} ;# List of $sm_lineNumbers (for each editor)
+
+ private variable bm_bp_pages_list {} ;# List of editor numbers present in the panel
+ private variable editors_count 0 ;# Counter of added editors
+ private variable current_editor_idx 0 ;# Int: Index of currently active editor
+
+ private variable block_select 0 ;# Bool: Block selection of an item for certain procedures
+ private variable search_val_in_progress 0 ;# Bool: Search procedure is in progress
+
+ private variable button_bar ;# ID of button bar which replaces notebook on hide
+ private variable redraw_pane_in_progress 0 ;# (see procedure right_panel_redraw_pane)
+ private variable parentPane ;# ID of parent container (some frame)
+ private variable last_PanelSize ;# Last panel widgth
+ private variable PanelSize $::CONFIG(RIGHT_PANEL_SIZE) ;# Current panel width
+ private variable active_page $::CONFIG(RIGHT_PANEL_ACTIVE_PAGE) ;# ID of the active page
+ private variable PanelVisible $::CONFIG(RIGHT_PANEL) ;# Bool: is panel visible
+
+ private variable enabled 0 ;# Bool: enable procedures which are needless while loading project
+
+ ## Object constructor
+ constructor {} {
+ incr count
+ set obj_idx $count
+ }
+
+ ## Object destructor
+ destructor {
+ # Clean up GUI
+ destroy $notebook_frame
+
+ # Remove status bar tips for popup menus
+ menu_Sbar_remove $bookmarks_menu
+ menu_Sbar_remove $breakpoints_menu
+ }
+
+ ## Create right panel
+ # @parm Widget notebookframe - frame where to pack NoteBook
+ # @parm Widget ParentPane - parent paned window
+ # @parm String watches_file - definition file for register watches
+ # @return void
+ public method Initialize_rightPanel {notebookframe ParentPane watches_file} {
+
+ # Object variables
+ set parentPane $ParentPane ;# Parent container (some frame)
+ # Main frame of this panel
+ set notebook_frame $notebookframe
+
+ ## Create NoteBook
+ set notebook [NoteBook $notebook_frame.ntb_rightPanel \
+ -side top -bg {#EEEEEE} \
+ -arcradius 4 \
+ ]
+
+ # Register notebook status bar tips
+ notebook_Sbar_set {rightpanel} [list \
+ Bookmarks [mc "List of bookmarks in the current editor"] \
+ Breakpoints [mc "List of breakpoints in the current editor"] \
+ Instruction [mc "Details for instruction on the current line"] \
+ Watches [mc "Register watches (for internal data memory, external data memory, expanded data memory and bits)"] \
+ Subprograms [mc "List of active subprograms"] \
+ Symbols [mc "Symbol list"] \
+ Hardware [mc "Hardware manager"] \
+ Hide [mc "Hide the panel"] \
+ ]
+ $notebook bindtabs <Enter> "notebook_Sbar rightpanel"
+ $notebook bindtabs <Leave> "Sbar {} ;#"
+
+ #
+ # Create tabs
+ #
+
+ if {!${::Editor::editor_to_use}} {
+ # Tab "Bookmarks"
+ set bookmarks [$notebook insert end [mc "Bookmarks"] \
+ -image ::ICONS::16::bookmark_toolbar \
+ -raisecmd "$this rightPanel_set_active_page Bookmarks" \
+ -helptext [mc "List of bookmarks in editor (Ctrl+6)"] \
+ ]
+ # Tab "Breakpoints"
+ set breakpoints [$notebook insert end [mc "Breakpoints"] \
+ -image ::ICONS::16::flag \
+ -raisecmd "$this rightPanel_set_active_page Breakpoints" \
+ -helptext [mc "List of breakpoints in editor (Ctrl+7)"] \
+ ]
+ # Tab "Symbols"
+ set table_of_symbols [$notebook insert end [mc "Symbols"] \
+ -image ::ICONS::16::_blockdevice \
+ -raisecmd "$this rightPanel_set_active_page Symbols" \
+ -helptext [mc "Symbol List"] \
+ ]
+ # Tab "Instruction"
+ set instruction [$notebook insert end [mc "Instruction"] \
+ -image ::ICONS::16::info \
+ -raisecmd "$this rightPanel_set_active_page Instruction" \
+ -helptext [mc "Instruction details (Ctrl+8)"] \
+ -createcmd [list $this CreateInstructionDetailsGUI] \
+ ]
+ }
+ # Tab "Watches"
+ set watches [$notebook insert end [mc "Watches"] \
+ -image ::ICONS::16::player_playlist \
+ -raisecmd "$this rightPanel_set_active_page Watches" \
+ -helptext [mc "Register watches (Ctrl+9)"] \
+ -createcmd [list $this CreateRegWatchesGUI] \
+ ]
+ # Tab "Subprograms"
+ set subprograms [$notebook insert end [mc "Subprograms"] \
+ -image ::ICONS::16::queue \
+ -raisecmd "$this rightPanel_set_active_page Subprograms"\
+ -helptext [mc "Active subprograms (Ctrl+0)"] \
+ -createcmd [list $this CreateSubProgramsGUI] \
+ ]
+ # Tab "Hardware manager"
+ set hwmanager [$notebook insert end [mc "Hardware"] \
+ -image ::ICONS::16::kcmpci \
+ -raisecmd "$this rightPanel_set_active_page Hardware" \
+ -helptext [mc "Hardware manager"] \
+ -createcmd [list $this CreateHwManagerGUI] \
+ ]
+
+ # Tab "Hide"
+ $notebook insert end [mc "Hide"] \
+ -image ::ICONS::16::2rightarrow \
+ -raisecmd "$this right_panel_show_hide" \
+ -helptext [mc "Hide the panel"]
+
+ # Prepare panel componenets but do not create GUI elements
+ PrepareRegWatches $watches $watches_file
+ PrepareSubPrograms $subprograms
+ PrepareHwManager $hwmanager
+
+ if {!${::Editor::editor_to_use}} {
+ PrepareInstructionDetails $instruction
+ }
+
+
+ ## Create Button bar
+ # Button "Show"
+ set button_bar [frame $notebook_frame.button_bar]
+ pack [ttk::button $button_bar.but_show \
+ -image ::ICONS::16::2leftarrow \
+ -style ToolButton.TButton \
+ -command "$this right_panel_show_hide" \
+ ]
+ DynamicHelp::add $button_bar.but_show -text [mc "Show the panel"]
+ setStatusTip -widget $button_bar.but_show -text [mc "Show the panel"]
+ # Separator
+ pack [ttk::separator $button_bar.sep -orient horizontal] -fill x -pady 2
+ # Button "Hardware manager"
+ pack [ttk::button $button_bar.but_hwman \
+ -image ::ICONS::16::kcmpci \
+ -style ToolButton.TButton \
+ -command "$this rightPanel_show_up Hardware" \
+ ]
+ DynamicHelp::add $button_bar.but_hwman -text [mc "Hardware tools"]
+ setStatusTip -widget $button_bar.but_hwman \
+ -text [mc "Hardware tools manager"]
+ # Button "Active Subprograms"
+ pack [ttk::button $button_bar.but_subprog \
+ -image ::ICONS::16::queue \
+ -style ToolButton.TButton \
+ -command "$this rightPanel_show_up Subprograms" \
+ ]
+ DynamicHelp::add $button_bar.but_subprog -text [mc "Active subprograms (Ctrl+0)"]
+ setStatusTip -widget $button_bar.but_subprog \
+ -text [mc "List of active subprograms"]
+ # Button "Register watches"
+ pack [ttk::button $button_bar.but_reg_watch \
+ -image ::ICONS::16::player_playlist \
+ -style ToolButton.TButton \
+ -command "$this rightPanel_show_up Watches" \
+ ]
+ DynamicHelp::add $button_bar.but_reg_watch -text [mc "MCU register watches (Ctrl+9)"]
+ setStatusTip -widget $button_bar.but_reg_watch \
+ -text [mc "Register watches for internal data memory, external data memory and expanded data memory"]
+ if {!${::Editor::editor_to_use}} {
+ # Button "Instruction details"
+ pack [ttk::button $button_bar.but_ins_det \
+ -image ::ICONS::16::info \
+ -style ToolButton.TButton \
+ -command "$this rightPanel_show_up Instruction" \
+ -state [expr {${::Editor::editor_to_use} ? {disabled} : {!disabled}}] \
+ ]
+ DynamicHelp::add $button_bar.but_ins_det -text [mc "Instruction details (Ctrl+8)"]
+ setStatusTip -widget $button_bar.but_ins_det \
+ -text [mc "Details for instruction on the current line"]
+ # Button "Symbol List"
+ pack [ttk::button $button_bar.but_symbols \
+ -image ::ICONS::16::_blockdevice \
+ -style ToolButton.TButton \
+ -command "$this rightPanel_show_up Symbols" \
+ -state [expr {${::Editor::editor_to_use} ? {disabled} : {!disabled}}] \
+ ]
+ DynamicHelp::add $button_bar.but_symbols -text [mc "Symbol List"]
+ setStatusTip -widget $button_bar.but_symbols \
+ -text [mc "Symbol List"]
+ # Button "Breakpoints"
+ pack [ttk::button $button_bar.but_breakpoints \
+ -image ::ICONS::16::flag \
+ -style ToolButton.TButton \
+ -command "$this rightPanel_show_up Breakpoints" \
+ -state [expr {${::Editor::editor_to_use} ? {disabled} : {!disabled}}] \
+ ]
+ DynamicHelp::add $button_bar.but_breakpoints -text [mc "List of breakpoints in editor (Ctrl+7)"]
+ setStatusTip -widget $button_bar.but_breakpoints \
+ -text [mc "List of breakpoints in the current editor"]
+ # Button "Bookmarks"
+ pack [ttk::button $button_bar.but_bookmarks \
+ -image ::ICONS::16::bookmark_toolbar \
+ -style ToolButton.TButton \
+ -command "$this rightPanel_show_up Bookmarks" \
+ -state [expr {${::Editor::editor_to_use} ? {disabled} : {!disabled}}] \
+ ]
+ DynamicHelp::add $button_bar.but_bookmarks -text [mc "List of bookmarks in editor (Ctrl+6)"]
+ setStatusTip -widget $button_bar.but_bookmarks \
+ -text [mc "List of bookmarks in the current editor"]
+ }
+
+ if {!${::Editor::editor_to_use}} {
+ # Pack pages managers
+ set bm_pagesManager [PagesManager $bookmarks.pgm_rightPanel_bm -background {#eeeeee}]
+ pack $bm_pagesManager -expand 1 -fill both
+ $bm_pagesManager compute_size
+
+ set bp_pagesManager [PagesManager $breakpoints.pgm_rightPanel_pm -background {#eeeeee}]
+ pack $bp_pagesManager -expand 1 -fill both
+ $bp_pagesManager compute_size
+
+ set sm_pagesManager [PagesManager $table_of_symbols.sm_pagesManager -background {#eeeeee}]
+ pack $sm_pagesManager -expand 1 -fill both
+ $sm_pagesManager compute_size
+
+ # Create popup menus
+ set bookmarks_menu $notebook_frame.menu_rightPanel_bookmarks
+ set breakpoints_menu $notebook_frame.menu_rightPanel_breakpoints
+ set symbols_menu $notebook_frame.menu_rightPanel_symbols
+ menuFactory $BREAKPOINTMENU $breakpoints_menu 0 "$this " 0 {}
+ menuFactory $BOOKMARKMENU $bookmarks_menu 0 "$this " 0 {}
+ menuFactory $SYMBOLSKMENU $symbols_menu 0 "$this " 0 {}
+ }
+
+
+ #
+ # Post-initialization
+ #
+
+ bind $parentPane <ButtonRelease-1> "$this right_panel_set_size"
+
+ # Show panel GUI components
+ if {$PanelVisible} {
+ # Show NoteBook
+ $parentPane paneconfigure $notebook_frame -minsize 295
+ pack $notebook -expand 1 -fill both
+ $parentPane configure -sashwidth 2
+
+ if {[catch {
+ $notebook raise $active_page
+ if {
+ ${::Editor::editor_to_use} &&
+ ([lsearch {Bookmarks Breakpoints Instruction Symbols} $active_page] != -1)
+ } {
+ set active_page {Watches}
+ $notebook raise {Watches}
+ }
+ }]} {
+ set active_page {Watches}
+ $notebook raise {Watches}
+ }
+ } {
+ # Show button bar
+ $parentPane paneconfigure $notebook_frame -minsize 0
+ pack $button_bar -anchor nw
+ $parentPane configure -sashwidth 0
+ bind $parentPane <Button> {break}
+ set last_PanelSize $PanelSize
+ set PanelSize 60
+ }
+ }
+
+ ## Synchronously scroll list of bookmarks and its line numbers
+ # @parm Char - what (m == Bookmarks; p == Breakpoints; s == Symbols)
+ # @parm String - string "moveto"
+ # @parm Float - number between 0.0 and 1.0 (0.0 == 'start', 1.0 == 'end')
+ # @return void
+ public method rightPanel_scroll args {
+ # Local variables
+ set what [lindex $args 0]
+ set cmd [lindex $args 1] ;# Scroll command (moveto, scroll and such)
+ set frac [lindex $args 2] ;# Fraction where to move
+ set units [lindex $args 3] ;# Units (optonal)
+
+ switch -- $what {
+ {m} { ;# Bookmarks
+ set lnb $bookmarks_lineNumbers
+ set txt $bookmarks_text
+ }
+ {p} { ;# Breakpoints
+ set lnb $breakpoints_lineNumbers
+ set txt $breakpoints_text
+ }
+ {s} { ;# Symbols
+ set lnb $sm_lineNumbers
+ set txt $sm_text
+ }
+ }
+
+ if {$units == {}} {
+ $lnb yview $cmd $frac
+ $txt yview $cmd $frac
+ } {
+ $lnb yview $cmd $frac $units
+ $txt yview $cmd $frac $units
+ }
+ }
+
+ ## Set position for scrollbar and line numbers in bookmark list
+ # @parm Char what - (m == Bookmarks; p == Breakpoints; s == Symbols)
+ # @parm Widget scrollbar - ID of scrollbar widget to adjust
+ # @parm Float fraction0 - y position
+ # @parm Float fraction1 - x position
+ # @return Bool - result
+ public method rightPanel_scrollSet {what scrollbar fraction0 fraction1} {
+ switch -- $what {
+ {m} { ;# Bookmarks
+ set txt $bookmarks_text
+ }
+ {p} { ;# Breakpoints
+ set txt $breakpoints_text
+ }
+ {s} { ;# Symbols
+ set txt $sm_text
+ }
+ }
+
+ if {![winfo exists $txt]} {
+ return 0
+ }
+
+ catch {
+ if {$fraction0 == {0.0} && $fraction1 == {1.0}} {
+ if {[winfo ismapped $scrollbar]} {
+ pack forget $scrollbar
+ }
+ } {
+ if {![winfo ismapped $scrollbar]} {
+ pack $scrollbar -side right -fill y -after $txt
+ }
+ }
+ }
+
+
+ $scrollbar set $fraction0 $fraction1
+ rightPanel_scroll $what moveto $fraction0
+
+ return 1
+ }
+
+ ## Refresh font settings for all text widgets in the panel
+ # @parm Bool for_all - 0 == only for the current editor; 1 == for all editors
+ # @return void
+ public method rightPanel_refresh_font_settings {for_all} {
+ if {${::Editor::editor_to_use}} {return}
+ if {$for_all} {
+ foreach widget $LIST_bookmarks_lineNumbers {
+ $widget configure -font ${Editor::defaultFont_bold}
+ }
+
+ foreach widget $LIST_breakpoints_lineNumbers {
+ $widget configure -font ${Editor::defaultFont_bold}
+ }
+
+ set i 0
+ foreach widget $LIST_bookmarks_text {
+ $widget configure -font ${Editor::defaultFont_bold}
+ ASMsyntaxHighlight::create_tags $widget ${Editor::fontSize} ${Editor::fontFamily}
+ set language [$this editor_procedure $i get_language {}]
+ if {$language == 1} {
+ CsyntaxHighlight::create_tags \
+ $widget ${Editor::fontSize} ${Editor::fontFamily}
+ } elseif {$language == 2} {
+ LSTsyntaxHighlight::create_tags \
+ $widget ${Editor::fontSize} ${Editor::fontFamily}
+ }
+ incr i
+ }
+
+ set i 0
+ foreach widget $LIST_breakpoints_text {
+ $widget configure -font ${Editor::defaultFont_bold}
+ ASMsyntaxHighlight::create_tags $widget ${Editor::fontSize} ${Editor::fontFamily}
+ set language [$this editor_procedure $i get_language {}]
+ if {$language == 1} {
+ CsyntaxHighlight::create_tags \
+ $widget ${Editor::fontSize} ${Editor::fontFamily}
+ } elseif {$language == 2} {
+ LSTsyntaxHighlight::create_tags \
+ $widget ${Editor::fontSize} ${Editor::fontFamily}
+ }
+ incr i
+ }
+ } {
+ $bookmarks_lineNumbers configure -font ${Editor::defaultFont_bold}
+ $bookmarks_text configure -font ${Editor::defaultFont_bold}
+ $breakpoints_lineNumbers configure -font ${Editor::defaultFont_bold}
+ $breakpoints_text configure -font ${Editor::defaultFont_bold}
+ $sm_lineNumbers configure -font ${Editor::defaultFont_bold}
+ $sm_text configure -font ${Editor::defaultFont_bold}
+
+ ASMsyntaxHighlight::create_tags $bookmarks_text ${Editor::fontSize} ${Editor::fontFamily}
+ ASMsyntaxHighlight::create_tags $breakpoints_text ${Editor::fontSize} ${Editor::fontFamily}
+ set language [$this editor_procedure {end} get_language {}]
+ if {$language == 1} {
+ CsyntaxHighlight::create_tags \
+ $bookmarks_text ${Editor::fontSize} ${Editor::fontFamily}
+ CsyntaxHighlight::create_tags \
+ $breakpoints_text ${Editor::fontSize} ${Editor::fontFamily}
+ } elseif {$language == 2} {
+ CsyntaxHighlight::create_tags \
+ $bookmarks_text ${Editor::fontSize} ${Editor::fontFamily}
+ CsyntaxHighlight::create_tags \
+ $breakpoints_text ${Editor::fontSize} ${Editor::fontFamily}
+ }
+
+ create_tags_in_symbol_list
+ }
+ }
+
+ ## Create highlight tag for list of bookmarks and breakpoints for the current editor
+ # @return void
+ public method rightPanel_add_Editor__create_menu_and_tags {} {
+ if {${::Editor::editor_to_use}} {return}
+ ASMsyntaxHighlight::create_tags $breakpoints_text $fontSize $fontFamily
+ ASMsyntaxHighlight::create_tags $bookmarks_text $fontSize $fontFamily
+ set language [$this editor_procedure {end} get_language {}]
+ if {$language == 1} {
+ rightPanel_bm_bp_create_c_hg_tags
+ } elseif {$language == 2} {
+ rightPanel_bm_bp_create_lst_hg_tags
+ }
+
+ create_tags_in_symbol_list
+ }
+
+ ## Create highlighting tags in the text widget in the "List of Symbols"
+ # @return void
+ private method create_tags_in_symbol_list {} {
+ set tags_to_define [list tag_label tag_constant tag_normal tag_macro]
+ foreach tag_def [concat ${::ASMsyntaxHighlight::hightlight_tags} ${::CsyntaxHighlight::hightlight_tags}] {
+ if {[lsearch -ascii -exact $tags_to_define [lindex $tag_def 0]] == -1} {
+ continue
+ }
+
+ # Create array of tag attributes
+ for {set i 0} {$i < 5} {incr i} {
+ set tag_def_item($i) [lindex $tag_def $i]
+ }
+
+ # Foreground color
+ if {$tag_def_item(1) == {}} {
+ set tag_def_item(1) black
+ }
+ # Fonr slant
+ if {$tag_def_item(3) == 1} {
+ set tag_def_item(3) italic
+ } {
+ set tag_def_item(3) roman
+ }
+ # Font weight
+ if {$tag_def_item(4) == 1} {
+ set tag_def_item(4) bold
+ } {
+ set tag_def_item(4) normal
+ }
+
+ # Create the tag in the target text widget
+ $sm_text tag configure $tag_def_item(0) \
+ -foreground $tag_def_item(1) \
+ -font [font create \
+ -overstrike $tag_def_item(2) \
+ -slant $tag_def_item(3) \
+ -weight $tag_def_item(4) \
+ -size -$::Editor::fontSize \
+ -family $::Editor::fontFamily \
+ ]
+ }
+
+ # Create tag for C function
+ $sm_text tag configure tag_c_func \
+ -foreground {#0000DD} \
+ -font ${::Editor::defaultFont}
+ }
+
+ ## Create highlighting tags for Codelisting for the current editor
+ # @return void
+ public method rightPanel_bm_bp_create_lst_hg_tags {} {
+ LSTsyntaxHighlight::create_tags $breakpoints_text $fontSize $fontFamily
+ LSTsyntaxHighlight::create_tags $bookmarks_text $fontSize $fontFamily
+ }
+ ## Create highlighting tags for C language for the current editor
+ # @return void
+ public method rightPanel_bm_bp_create_c_hg_tags {} {
+ CsyntaxHighlight::create_tags $breakpoints_text $fontSize $fontFamily
+ CsyntaxHighlight::create_tags $bookmarks_text $fontSize $fontFamily
+ }
+
+ ## Add new list of bookmarks and list of breakpoints for new editor
+ # @parm Bool create_menu_and_tags - Create popup menus and highlighting tags
+ # @return void
+ public method rightPanel_add_Editor {create_menu_and_tags} {
+ if {${::Editor::editor_to_use}} {return}
+
+ # Local variables
+ set bm_page [$bm_pagesManager add $editors_count] ;# ID of current bookmarks page
+ set bp_page [$bp_pagesManager add $editors_count] ;# ID of current breakpoints page
+ set sm_page [$sm_pagesManager add $editors_count] ;# ID of current page in symbol list
+
+ # Register new editor
+ set current_editor_idx $editors_count
+ lappend bm_bp_pages_list $editors_count
+ incr editors_count ;# increment counter of editors
+
+
+ #
+ # Create tab "Bookmarks"
+ #
+
+ ## Create icon bar (up, down, bookmark, clear all)
+ # Create button frame
+ set button_frame [frame $bm_page.frm_rightPanel_bm_button_frame]
+ pack $button_frame -side top -fill x
+ # Button "Up"
+ set bm_up_button [ttk::button $button_frame.but_rightPanel_bm_up \
+ -image ::ICONS::16::1uparrow \
+ -state disabled \
+ -command "$this rightPanel_bm_up" \
+ -style ToolButton.TButton \
+ ]
+ pack $bm_up_button -side left
+ DynamicHelp::add $bm_up_button -text [mc "Move to previous bookmark"]
+ setStatusTip -widget $bm_up_button \
+ -text [mc "Goto to line of previous bookmark"]
+ # Button "Down"
+ set bm_down_button [ttk::button $button_frame.but_rightPanel_bm_down \
+ -image ::ICONS::16::1downarrow \
+ -state disabled \
+ -command "$this rightPanel_bm_down" \
+ -style ToolButton.TButton \
+ ]
+ pack $bm_down_button -side left
+ DynamicHelp::add $bm_down_button -text [mc "Move to the next bookmark"]
+ setStatusTip -widget $bm_down_button \
+ -text [mc "Goto to line of next bookmark"]
+ # Separator
+ pack [ttk::separator $button_frame.but_rightPanel_bm_sep \
+ -orient vertical \
+ ] -side left -fill y -padx 2
+ # Button "Bookmark"
+ set button [ttk::button $button_frame.but_rightPanel_bm_bookmark \
+ -image ::ICONS::16::bookmark_add \
+ -command "$this editor_procedure {} Bookmark {}" \
+ -style ToolButton.TButton \
+ ]
+ pack $button -side left
+ DynamicHelp::add $button -text [mc "Add/Remove bookmark on the current line"]
+ setStatusTip -widget $button \
+ -text [mc "Add/Remove bookmark on the current line in editor"]
+ # Button "Clear all"
+ set bm_clear_button [ttk::button $button_frame.but_rightPanel_bm_clear \
+ -image ::ICONS::16::editdelete \
+ -state disabled \
+ -command "$this editor_procedure {} clear_all_bookmarks {}" \
+ -style ToolButton.TButton \
+ ]
+ pack $bm_clear_button -side right
+ DynamicHelp::add $bm_clear_button -text [mc "Clear all bookmarks"]
+ setStatusTip -widget $bm_clear_button \
+ -text [mc "Clear all bookmarks from editor"]
+
+ # Create text frame (Contains: text widget, scrollbar, LineNumbers)
+ set text_frame [frame $bm_page.frm_rightPanel_bm_text_frame -bd 1 -relief sunken]
+ pack $text_frame -fill both -expand 1 -side bottom
+
+ # Create scrollbar
+ set scrollbar [ttk::scrollbar \
+ $text_frame.scr_rightPanel_bookmars \
+ -orient vertical \
+ -command "$this rightPanel_scroll m" \
+ ]
+ # Create line numbers
+ set bookmarks_lineNumbers [text $text_frame.txt_rightPanel_bm_lineNumbers \
+ -yscrollcommand "$this rightPanel_scrollSet m $scrollbar" \
+ -cursor left_ptr \
+ -width 1 -height 1 \
+ -bg gray \
+ -fg white \
+ -relief flat \
+ -bd 1 \
+ -state disabled \
+ -exportselection 0 \
+ -takefocus 0 \
+ -font ${Editor::defaultFont_bold} \
+ ]
+ $bookmarks_lineNumbers tag configure right -justify right
+ # Create list of bookmarks
+ set bookmarks_text [text $text_frame.txt_rightPanel_bookmars \
+ -cursor left_ptr -state disabled -width 1 -height 1 \
+ -wrap none -exportselection 0 -bd 1 -relief flat \
+ -yscrollcommand "$this rightPanel_scrollSet m $scrollbar" \
+ -font ${Editor::defaultFont_bold} \
+ ]
+ $bookmarks_text tag configure curLine \
+ -borderwidth 1 \
+ -relief raised \
+ -background ${::RightPanel::selection_color}
+
+ # Set bindings
+ bind $bookmarks_text <<Selection>> "false_selection $bookmarks_text; break"
+ bind $bookmarks_text <Button-1> "$this rightPanel_xx_txt_click m %x %y; break"
+ bind $bookmarks_text <ButtonRelease-3> "$this rightPanel_bm_popupmenu %X %Y %x %y; break; break"
+ bind $bookmarks_lineNumbers <ButtonRelease-3> "$this rightPanel_bm_popupmenu %X %Y %x %y; break; break"
+ bind $bookmarks_text <Key-Menu> {break}
+ bind $bookmarks_lineNumbers <<Selection>> "false_selection $bookmarks_lineNumbers; break"
+
+ # Pack components of "Text frame"
+ pack $bookmarks_lineNumbers -side left -fill y
+ pack $bookmarks_text -side left -expand 1 -fill both
+
+
+ #
+ # Breakpoints tab
+ #
+
+ ## Create icon bar (up, down, breakpoint, clear all)
+ # Create button frame
+ set button_frame [frame $bp_page.frm_rightPanel_bp_button_frame]
+ pack $button_frame -side top -fill x
+ # Button "Up"
+ set bp_up_button [ttk::button $button_frame.but_rightPanel_bp_up \
+ -image ::ICONS::16::1uparrow \
+ -state disabled \
+ -command "$this rightPanel_bp_up" \
+ -style ToolButton.TButton \
+ ]
+ pack $bp_up_button -side left
+ DynamicHelp::add $bp_up_button -text [mc "Move to previous breakpoint"]
+ setStatusTip -widget $bp_up_button \
+ -text [mc "Goto to line of previous breakpoint"]
+ # Button "Down"
+ set bp_down_button [ttk::button $button_frame.but_rightPanel_bp_down \
+ -image ::ICONS::16::1downarrow \
+ -state disabled \
+ -command "$this rightPanel_bp_down" \
+ -style ToolButton.TButton \
+ ]
+ pack $bp_down_button -side left
+ DynamicHelp::add $bp_down_button -text [mc "Move to next breakpoint"]
+ setStatusTip -widget $bp_down_button \
+ -text [mc "Goto to line of next breakpoint"]
+ # Separator
+ pack [ttk::separator $button_frame.but_rightPanel_bp_sep \
+ -orient vertical \
+ ] -side left -fill y -padx 2
+ # Button "Breakpoint"
+ set button [ttk::button $button_frame.but_rightPanel_bp_breakpoint \
+ -image ::ICONS::16::flag \
+ -command "$this editor_procedure {} Breakpoint {}" \
+ -style ToolButton.TButton \
+ ]
+ pack $button -side left
+ DynamicHelp::add $button -text [mc "Add/Remove breakpoint on the current line"]
+ setStatusTip -widget $button \
+ -text [mc "Add/Remove breakpoint on the current line in editor"]
+ # Buttton "Clear all"
+ set bp_clear_button [ttk::button $button_frame.but_rightPanel_bp_clear \
+ -image ::ICONS::16::editdelete \
+ -state disabled \
+ -command "$this editor_procedure {} clear_all_breakpoints {}" \
+ -style ToolButton.TButton \
+ ]
+ pack $bp_clear_button -side right
+ DynamicHelp::add $bp_clear_button -text [mc "Clear all breakpoints"]
+ setStatusTip -widget $bp_clear_button \
+ -text [mc "Clear all breakpoints from editor"]
+
+ # Create text frame (Contains: text widget, scrollbar, LineNumbers)
+ set text_frame [frame $bp_page.frm_rightPanel_bp_text_frame -bd 1 -relief sunken]
+ pack $text_frame -fill both -expand 1 -side bottom
+
+ # Create scrollbar
+ set scrollbar [ttk::scrollbar \
+ $text_frame.scr_rightPanel_breakpoints \
+ -orient vertical \
+ -command "$this rightPanel_scroll p" \
+ ]
+ # Create line numbers
+ set breakpoints_lineNumbers [text $text_frame.txt_rightPanel_bp_lineNumbers \
+ -yscrollcommand "$this rightPanel_scrollSet p $scrollbar" \
+ -cursor left_ptr \
+ -width 1 -height 1 \
+ -exportselection 0 \
+ -bg gray \
+ -fg white \
+ -relief flat \
+ -bd 1 \
+ -state disabled \
+ -takefocus 0 \
+ -font ${Editor::defaultFont_bold} \
+ ]
+ $breakpoints_lineNumbers tag configure right -justify right
+ # Create list of breakpoints
+ set breakpoints_text [text $text_frame.txt_rightPanel_breakpoints \
+ -cursor left_ptr -state disabled \
+ -wrap none -exportselection 0 -bd 1 -relief flat \
+ -font ${Editor::defaultFont_bold} -width 1 -height 1 \
+ -yscrollcommand "$this rightPanel_scrollSet p $scrollbar" \
+ ]
+ $breakpoints_text tag configure curLine \
+ -borderwidth 1 \
+ -relief raised \
+ -background ${::RightPanel::selection_color}
+
+ # Pack widgets of the text frame
+ pack $breakpoints_lineNumbers -side left -fill y
+ pack $breakpoints_text -side left -expand 1 -fill both
+
+ # Set bindings
+ bind $breakpoints_text <<Selection>> "false_selection $breakpoints_text; break"
+ bind $breakpoints_text <Button-1> "$this rightPanel_xx_txt_click p %x %y; break"
+ bind $breakpoints_text <ButtonRelease-3> "$this rightPanel_bp_popupmenu %X %Y %x %y; break; break"
+ bind $breakpoints_lineNumbers <ButtonRelease-3> "$this rightPanel_bp_popupmenu %X %Y %x %y; break; break"
+ bind $breakpoints_text <Key-Menu> {break}
+ bind $breakpoints_lineNumbers <<Selection>> "false_selection $breakpoints_lineNumbers; break"
+
+
+ #
+ # Symbol list
+ #
+
+ ## Create icon bar (up, down, breakpoint, clear all)
+ # Create button frame
+ set button_frame [frame $sm_page.button_frame]
+ pack $button_frame -side top -fill x
+ # Button "Refresh"
+ set refresh_but [ttk::button $button_frame.refresh_but \
+ -image ::ICONS::16::reload \
+ -command "$this rightPanel_refresh_symbols" \
+ -style ToolButton.TButton \
+ ]
+ pack $refresh_but -side left
+ DynamicHelp::add $refresh_but -text [mc "Reevaluate"]
+ setStatusTip -widget $refresh_but \
+ -text [mc "Reevaluate ..."]
+
+ # Button "Clear search string"
+ set sm_search_clear [ttk::button $button_frame.clear_search \
+ -image ::ICONS::16::clear_left \
+ -style Flat.TButton \
+ -command "$button_frame.search_entry delete 0 end" \
+ -state disabled \
+ ]
+ DynamicHelp::add $button_frame.clear_search -text [mc "Clear search string"]
+ pack $sm_search_clear -side right
+ setStatusTip -widget $sm_search_clear \
+ -text [mc "Clear search string"]
+ # Entry "Search"
+ set sm_search_entry [ttk::entry $button_frame.search_entry \
+ -validate key \
+ -width 0 \
+ -validatecommand "$this rightPanel_sm_search_validate %P %W $sm_search_clear" \
+ ]
+ DynamicHelp::add $sm_search_entry -text [mc "Search for a constant, variable, function or macro"]
+ pack $sm_search_entry -side right -fill x -expand 1
+ setStatusTip -widget $sm_search_entry \
+ -text [mc "Search for a constant, variable, function or macro"]
+ # Label "Search:"
+ pack [label $button_frame.search_lbl -text [mc " Search:"]] -side right
+
+ # Create text frame (Contains: text widget, scrollbar, LineNumbers)
+ set text_frame [frame $sm_page.text_frame -bd 1 -relief sunken]
+ pack $text_frame -fill both -expand 1 -side bottom
+
+ # Create scrollbar
+ set scrollbar [ttk::scrollbar $text_frame.scr \
+ -orient vertical \
+ -command "$this rightPanel_scroll s" \
+ ]
+ set sm_lineNumbers [text $text_frame.ln \
+ -yscrollcommand "$this rightPanel_scrollSet s $scrollbar" \
+ -cursor left_ptr -width 1 \
+ -exportselection 0 -bg gray \
+ -height 1 -fg white \
+ -relief flat -bd 1 \
+ -state disabled -takefocus 0 \
+ -font ${Editor::defaultFont_bold} \
+ ]
+ $sm_lineNumbers tag configure right -justify right
+ set sm_text [text $text_frame.txt \
+ -cursor left_ptr -state disabled \
+ -wrap none -exportselection 0 -bd 1 -relief flat \
+ -font ${Editor::defaultFont_bold} -width 1 -height 1 \
+ -yscrollcommand "$this rightPanel_scrollSet s $scrollbar" \
+ ]
+ $sm_text tag configure curLine \
+ -borderwidth 1 \
+ -relief raised \
+ -background ${::RightPanel::selection_color}
+
+ # Pack widgets of the text frame
+ pack $scrollbar -side right -fill y
+ pack $sm_lineNumbers -side left -fill y
+ pack $sm_text -side left -expand 1 -fill both
+
+ # Set bindings
+ bind $sm_text <<Selection>> "false_selection $sm_text; break"
+ bind $sm_text <Button-1> "$this rightPanel_xx_txt_click s %x %y; break"
+ bind $sm_text <Key-Menu> {break}
+ bind $sm_text <ButtonRelease-3> {break}
+ bind $sm_lineNumbers <<Selection>> "false_selection $sm_lineNumbers; break"
+ bind $sm_lineNumbers <Key-Menu> {break}
+ bind $sm_lineNumbers <ButtonRelease-3> {break}
+
+ ## FINISH
+
+ # Append create d widgets to lists
+ lappend LIST_bookmarks_lineNumbers $bookmarks_lineNumbers
+ lappend LIST_breakpoints_lineNumbers $breakpoints_lineNumbers
+ lappend LIST_bookmarks_text $bookmarks_text
+ lappend LIST_breakpoints_text $breakpoints_text
+ lappend LIST_bm_up_button $bm_up_button
+ lappend LIST_bm_down_button $bm_down_button
+ lappend LIST_bm_clear_button $bm_clear_button
+ lappend LIST_bp_up_button $bp_up_button
+ lappend LIST_bp_down_button $bp_down_button
+ lappend LIST_bp_clear_button $bp_clear_button
+ lappend LIST_sm_text $sm_text
+ lappend LIST_sm_lineNumbers $sm_lineNumbers
+
+ if {$create_menu_and_tags} {
+ rightPanel_add_Editor__create_menu_and_tags
+ }
+ }
+
+ ## Enable/Disable buttons on Bookmarks+Breakpoints icon bar
+ # @return void
+ private method bm_bp_disEna_buttons {} {
+
+ # Bookmarks
+ set end [$bookmarks_text index end]
+ switch -- $end {
+ {2.0} { ;# Empty list
+ $bm_up_button configure -state disabled
+ $bm_down_button configure -state disabled
+ $bm_clear_button configure -state disabled
+ }
+ {3.0} { ;# One item
+ $bm_up_button configure -state disabled
+ $bm_down_button configure -state disabled
+ $bm_clear_button configure -state normal
+ }
+ default { ;# More items
+ $bm_up_button configure -state normal
+ $bm_down_button configure -state normal
+ $bm_clear_button configure -state normal
+ }
+ }
+
+ # Breakpoints
+ set end [$breakpoints_text index end]
+ switch -- $end {
+ {2.0} { ;# Empty list
+ $bp_up_button configure -state disabled
+ $bp_down_button configure -state disabled
+ $bp_clear_button configure -state disabled
+ }
+ {3.0} { ;# One item
+ $bp_up_button configure -state disabled
+ $bp_down_button configure -state disabled
+ $bp_clear_button configure -state normal
+ }
+ default { ;# More items
+ $bp_up_button configure -state normal
+ $bp_down_button configure -state normal
+ $bp_clear_button configure -state normal
+ }
+ }
+ }
+
+ ## Recreate popup menus
+ # @return void
+ public method rightPanel_makePopupMenu {} {
+ regwatches_makePopupMenu
+
+ if {[winfo exists $breakpoints_menu]} {destroy $breakpoints_menu}
+ if {[winfo exists $bookmarks_menu]} {destroy $bookmarks_menu}
+ menuFactory $BREAKPOINTMENU $breakpoints_menu 0 "$this " 0 {}
+ menuFactory $BOOKMARKMENU $bookmarks_menu 0 "$this " 0 {}
+ }
+
+ ## Invoke bookmarks popup menu
+ # @parm Int X - Absolute X coordinate
+ # @parm Int Y - Absolute Y coordinate
+ # @parm Int x - Relative X coordinate
+ # @parm Int y - Relative Y coordinate
+ # @return void
+ public method rightPanel_bm_popupmenu {X Y x y} {
+
+ # Change position in the list
+ rightPanel_xx_txt_click m $x $y
+
+ # Enable/Disable menu items
+ set end [$bookmarks_text index end]
+ switch -- $end {
+ {2.0} { ;# Empty list
+ $bookmarks_menu entryconfigure [::mc "Remove"] -state disabled
+ $bookmarks_menu entryconfigure [::mc "Next"] -state disabled
+ $bookmarks_menu entryconfigure [::mc "Previous"] -state disabled
+ $bookmarks_menu entryconfigure [::mc "Remove all"] -state disabled
+ }
+ {3.0} { ;# One item
+ $bookmarks_menu entryconfigure [::mc "Remove"] -state normal
+ $bookmarks_menu entryconfigure [::mc "Next"] -state disabled
+ $bookmarks_menu entryconfigure [::mc "Previous"] -state disabled
+ $bookmarks_menu entryconfigure [::mc "Remove all"] -state normal
+ }
+ default { ;# More items
+ $bookmarks_menu entryconfigure [::mc "Remove"] -state normal
+ $bookmarks_menu entryconfigure [::mc "Next"] -state normal
+ $bookmarks_menu entryconfigure [::mc "Previous"] -state normal
+ $bookmarks_menu entryconfigure [::mc "Remove all"] -state normal
+ }
+ }
+
+ # Invoke the menu
+ tk_popup $bookmarks_menu $X $Y
+ }
+
+ ## Invoke breakpoints popup menu
+ # @parm Int X - Absolute X coordinate
+ # @parm Int Y - Absolute Y coordinate
+ # @parm Int x - Relative X coordinate
+ # @parm Int y - Relative Y coordinate
+ # @return void
+ public method rightPanel_bp_popupmenu {X Y x y} {
+
+ # Change position in the list
+ rightPanel_xx_txt_click p $x $y
+
+ # Enable/Disable menu items
+ set end [$breakpoints_text index end]
+ switch -- $end {
+ {2.0} { ;# Empty list
+ $breakpoints_menu entryconfigure [::mc "Remove"] -state disabled
+ $breakpoints_menu entryconfigure [::mc "Next"] -state disabled
+ $breakpoints_menu entryconfigure [::mc "Previous"] -state disabled
+ $breakpoints_menu entryconfigure [::mc "Remove all"] -state disabled
+ }
+ {3.0} { ;# One item
+ $breakpoints_menu entryconfigure [::mc "Remove"] -state normal
+ $breakpoints_menu entryconfigure [::mc "Next"] -state disabled
+ $breakpoints_menu entryconfigure [::mc "Previous"] -state disabled
+ $breakpoints_menu entryconfigure [::mc "Remove all"] -state normal
+ } default { ;# More items
+ $breakpoints_menu entryconfigure [::mc "Remove"] -state normal
+ $breakpoints_menu entryconfigure [::mc "Next"] -state normal
+ $breakpoints_menu entryconfigure [::mc "Previous"] -state normal
+ $breakpoints_menu entryconfigure [::mc "Remove all"] -state normal
+ }
+ }
+
+ # Invoke the menu
+ tk_popup $breakpoints_menu $X $Y
+ }
+
+ ## Remove editor from the list
+ # @parm Int idx - editor index
+ # @return void
+ public method rightPanel_remove_Editor {idx} {
+ if {${::Editor::editor_to_use}} {return}
+
+ # Remove pages from pages managers
+ $bm_pagesManager delete [lindex $bm_bp_pages_list $idx]
+ $bp_pagesManager delete [lindex $bm_bp_pages_list $idx]
+ $sm_pagesManager delete [lindex $bm_bp_pages_list $idx]
+ set bm_bp_pages_list [lreplace $bm_bp_pages_list $idx $idx]
+
+ # Remove widget references from its lists
+ set LIST_bookmarks_lineNumbers [lreplace $LIST_bookmarks_lineNumbers $idx $idx]
+ set LIST_breakpoints_lineNumbers [lreplace $LIST_breakpoints_lineNumbers $idx $idx]
+ set LIST_bookmarks_text [lreplace $LIST_bookmarks_text $idx $idx]
+ set LIST_breakpoints_text [lreplace $LIST_breakpoints_text $idx $idx]
+ set LIST_bm_up_button [lreplace $LIST_bm_up_button $idx $idx]
+ set LIST_bm_down_button [lreplace $LIST_bm_down_button $idx $idx]
+ set LIST_bm_clear_button [lreplace $LIST_bm_clear_button $idx $idx]
+ set LIST_bp_up_button [lreplace $LIST_bp_up_button $idx $idx]
+ set LIST_bp_down_button [lreplace $LIST_bp_down_button $idx $idx]
+ set LIST_bp_clear_button [lreplace $LIST_bp_clear_button $idx $idx]
+ set LIST_sm_text [lreplace $LIST_sm_text $idx $idx]
+ set LIST_sm_lineNumbers [lreplace $LIST_sm_lineNumbers $idx $idx]
+ }
+
+ ## Change the current editor
+ # @parm Int idx - editor index
+ # @return void
+ public method rightPanel_switch_editor {idx} {
+ if {${::Editor::editor_to_use}} {return}
+
+ set current_editor_idx $idx
+ rightPanel_switch_page $idx
+ rightPanel_switch_editor_vars $idx
+ }
+
+ ## Change the current page in pages managers
+ # @parm Int idx - editor index
+ # @return void
+ public method rightPanel_switch_page {idx} {
+ if {${::Editor::editor_to_use}} {return}
+
+ set current_editor_idx $idx
+ $bm_pagesManager raise [lindex $bm_bp_pages_list $idx]
+ $bp_pagesManager raise [lindex $bm_bp_pages_list $idx]
+ $sm_pagesManager raise [lindex $bm_bp_pages_list $idx]
+
+ if {$active_page == {Symbols}} {
+ catch {$this editor_procedure {} comp_win_highlight_all_in_background {}}
+ }
+ }
+
+ ## Change current editor but don not affect GUI
+ # @parm Int idx - editor index
+ # @return void
+ public method rightPanel_switch_editor_vars {idx} {
+ if {${::Editor::editor_to_use}} {return}
+
+ # Set active widgets
+ set current_editor_idx $idx
+ set bookmarks_lineNumbers [lindex $LIST_bookmarks_lineNumbers $idx]
+ set breakpoints_lineNumbers [lindex $LIST_breakpoints_lineNumbers $idx]
+ set bookmarks_text [lindex $LIST_bookmarks_text $idx]
+ set breakpoints_text [lindex $LIST_breakpoints_text $idx]
+ set bm_up_button [lindex $LIST_bm_up_button $idx]
+ set bm_down_button [lindex $LIST_bm_down_button $idx]
+ set bm_clear_button [lindex $LIST_bm_clear_button $idx]
+ set bp_up_button [lindex $LIST_bp_up_button $idx]
+ set bp_down_button [lindex $LIST_bp_down_button $idx]
+ set bp_clear_button [lindex $LIST_bp_clear_button $idx]
+ set sm_text [lindex $LIST_sm_text $idx]
+ set sm_lineNumbers [lindex $LIST_sm_lineNumbers $idx]
+ }
+
+
+ ## Binding for event <Button-1> for list of ...
+ # Change selection in the widget and change current line in the editor
+ # @parm Char - what (m == Bookmarks; p == Breakpoints; s == Symbols)
+ # @parm Int x - relative X coordinate
+ # @parm Int y - relative Y coordinate
+ # @return Bool - result
+ public method rightPanel_xx_txt_click {what x y} {
+ if {$block_select} {return}
+
+ switch -- $what {
+ {m} { ;# Bookmarks
+ set lnb $bookmarks_lineNumbers
+ set txt $bookmarks_text
+ }
+ {p} { ;# Breakpoints
+ set lnb $breakpoints_lineNumbers
+ set txt $breakpoints_text
+ }
+ {s} { ;# Symbols
+ set lnb $sm_lineNumbers
+ set txt $sm_text
+ }
+ }
+
+ # Determinate line number
+ set lineNum [rightPanel_txt_click $txt $lnb $x $y]
+ if {$lineNum == {}} {return 0}
+
+ # Change current line in the editor
+ set block_select 1
+ $this editor_procedure {} goto $lineNum
+ update idle
+ set block_select 0
+
+ return 1
+ }
+
+ ## Determinate line number and select the line
+ # @parm Widget txt_widget - ID of the text widget
+ # @parm Widget ln_widget - ID of line numbers widget
+ # @parm Int x - relative X coordinate
+ # @parm Int y - relative X coordinate
+ # @return Int - line number (from line numbers panel)
+ private method rightPanel_txt_click {txt_widget ln_widget x y} {
+ set idx [$txt_widget index @$x,$y]
+
+ # Determinate traslated line number
+ set lineNum [$ln_widget get [list $idx linestart] [list $idx lineend]]
+
+ # Select the line
+ if {$lineNum != {}} {
+ $txt_widget tag remove curLine 1.0 end
+ $txt_widget tag add curLine [list $idx linestart] [list $idx+1l linestart]
+ }
+
+ # Retrun result
+ return $lineNum
+ }
+
+ ## If the given line contain bookmark then select it in the list
+ # This function should be called after change line in the editor
+ # @parm Int lineNum - line number
+ # @return Bool - result
+ public method rightPanel_bm_select {lineNum} {
+ if {!$enabled || $block_select} {return}
+ if {![info exists bookmarks_text]} {return}
+
+ # Check for bookmark presence
+ set idx0 [lsearch -ascii -exact [$bookmarks_lineNumbers get 1.0 end] $lineNum]
+ if {$idx0 == -1} {return 0}
+
+ # Select the line
+ incr idx0
+ set idx1 $idx0
+ incr idx1
+ $bookmarks_text tag remove curLine 1.0 end
+ $bookmarks_text tag add curLine $idx0.0 $idx1.0
+ $bookmarks_text see $idx0.0
+ return 1
+ }
+
+ ## If the given line contain bookmark then select it in the list
+ # This function should be called after change line in the editor
+ # @parm Int lineNum - line number
+ # @return Bool - result
+ public method rightPanel_bp_select {lineNum} {
+ if {!$enabled || $block_select} {return}
+ if {![info exists breakpoints_text]} {return}
+
+ # Check for bookmark presence
+ set idx0 [lsearch [$breakpoints_lineNumbers get 1.0 end] $lineNum]
+ if {$idx0 == -1} {return 0}
+
+ # Select the line
+ incr idx0
+ set idx1 $idx0
+ incr idx1
+ $breakpoints_text tag remove curLine 1.0 end
+ $breakpoints_text tag add curLine $idx0.0 $idx1.0
+ $breakpoints_text see $idx0.0
+ return 1
+ }
+
+ ## Unset selection in list of bookmarks
+ # @return void
+ public method rightPanel_bm_unselect {} {
+ if {!$enabled || $block_select} {return}
+ if {![info exists bookmarks_text]} {return}
+ $bookmarks_text tag remove curLine 1.0 end
+ }
+
+ ## Unset selection in list of breakpoints
+ # @return void
+ public method rightPanel_bp_unselect {} {
+ if {!$enabled || $block_select} {return}
+ if {![info exists breakpoints_text]} {return}
+ $breakpoints_text tag remove curLine 1.0 end
+ }
+
+ ## Copy line from the editor to target widget and preserve highlight
+ # @parm Widget target_widget - target widget, where to copy the line
+ # @parm TextIndex idx - target text index
+ # @parm Int lineNum - source line number
+ # @parm Int editor_idx - editor index
+ # @return void
+ private method insert_text {target_widget idx lineNum editor_idx} {
+
+ # Copy text
+ set line [$this editor_procedure $editor_idx getLineContent $lineNum]
+ regsub -all {\t} $line { } line
+ append line "\n"
+ $target_widget insert $idx $line
+
+ # Gain list of text tags in source widget
+ set ranges [$this editor_procedure $editor_idx getTagsRanges $lineNum]
+ # Determinate row in the target widget
+ if {$idx == {end}} {
+ set row [$target_widget index end]
+ set row [expr {int($row) - 2}]
+ } {
+ set row [expr {int($idx)}]
+ }
+ # Iterate over source text tags and add them to target widget
+ foreach range $ranges {
+ # Local variables
+ set tag [lindex $range 0] ;# Text tag
+ set range [lindex $range 1] ;# Tag range
+ set range_len [llength $range] ;# Number of indexes in tag range
+
+ # Iterate over ranges
+ for {set i 0} {$i < $range_len} {incr i} {
+
+ # Translate indexes
+ set idx0 [lindex $range $i]
+ regsub {^\d+} $idx0 $row idx0
+ incr i
+ set idx1 [lindex $range $i]
+ regsub {^\d+} $idx1 $row idx1
+
+ # Set tag
+ $target_widget tag add $tag $idx0 $idx1
+ }
+ }
+ }
+
+ ## Add bookmark to the list
+ # @parm Int lineNum - line number in the editor
+ # @return void
+ public method rightPanel_add_bookmark {lineNum} {
+ if {$block_select} {return}
+
+ ## Determinate target text index
+ set indexes [$bookmarks_lineNumbers get 1.0 end]
+
+ set idx -1
+ set i 0
+ foreach line $indexes {
+ incr i
+ if {$line > $lineNum} {
+ set idx $i
+ break
+ }
+ }
+
+ if {$idx == -1} {
+ set idx {end}
+ } {
+ append idx {.0}
+ }
+
+ # Enable widgets
+ $bookmarks_lineNumbers configure -state normal
+ $bookmarks_text configure -state normal
+
+ # Insert new line to line numbers
+ $bookmarks_lineNumbers insert $idx "$lineNum\n"
+ adjust_width $bookmarks_lineNumbers
+
+ # Insert text to the list
+ insert_text $bookmarks_text $idx $lineNum {}
+
+ # Disable widgets
+ $bookmarks_lineNumbers configure -state disabled
+ $bookmarks_text configure -state disabled
+
+ # Reevaluate icon bar button states
+ bm_bp_disEna_buttons
+ }
+
+ ## Remove bookmark from the list
+ # @parm Int lineNum - line number (in Editor)
+ # @return void
+ public method rightPanel_remove_bookmark {lineNum} {
+ if {$block_select} {return}
+
+ # Determinate start and end index
+ set idx [lsearch [$bookmarks_lineNumbers get 1.0 end] $lineNum]
+ if {$idx == -1} {return}
+
+ set idx0 [expr {int($idx) + 1}]
+ set idx1 [expr {int($idx) + 2}]
+
+ # Enable widgets
+ $bookmarks_lineNumbers configure -state normal
+ $bookmarks_text configure -state normal
+
+ # Remove line from line numbers
+ $bookmarks_lineNumbers delete $idx0.0 $idx1.0
+ adjust_width $bookmarks_lineNumbers
+
+ # Remove line from the list
+ $bookmarks_text delete $idx0.0 $idx1.0
+
+ # Disable widgets
+ $bookmarks_lineNumbers configure -state disabled
+ $bookmarks_text configure -state disabled
+
+ # Reevaluate icon bar button states
+ bm_bp_disEna_buttons
+ }
+
+ ## Add breakpoint to the list
+ # @parm Int lineNum - line number in the editor
+ # @return void
+ public method rightPanel_add_breakpoint {lineNum} {
+ if {$block_select} {return}
+
+ ## Determinate target text index
+ set indexes [$breakpoints_lineNumbers get 1.0 end]
+
+ set idx -1
+ set i 0
+ foreach line $indexes {
+ incr i
+ if {$line > $lineNum} {
+ set idx $i
+ break
+ }
+ }
+
+ if {$idx == -1} {
+ set idx {end}
+ } {
+ append idx {.0}
+ }
+
+ # Enable widgets
+ $breakpoints_lineNumbers configure -state normal
+ $breakpoints_text configure -state normal
+
+ # Insert new line to line numbers
+ $breakpoints_lineNumbers insert $idx "$lineNum\n"
+ adjust_width $breakpoints_lineNumbers
+
+ # Insert text to the list
+ insert_text $breakpoints_text $idx $lineNum {}
+
+ # Disable widgets
+ $breakpoints_lineNumbers configure -state disabled
+ $breakpoints_text configure -state disabled
+
+ # Reevaluate icon bar button states
+ bm_bp_disEna_buttons
+ }
+
+ ## Remove breakpoint from the list
+ # @parm Int lineNum - line number (in Editor)
+ # @return void
+ public method rightPanel_remove_breakpoint {lineNum} {
+ if {$block_select} {return}
+
+ # Determinate start and end index
+ set idx [lsearch [$breakpoints_lineNumbers get 1.0 end] $lineNum]
+ if {$idx == -1} {return}
+
+ set idx0 [expr {int($idx) + 1}]
+ set idx1 [expr {int($idx) + 2}]
+
+ # Enable widgets
+ $breakpoints_lineNumbers configure -state normal
+ $breakpoints_text configure -state normal
+
+ # Remove line from line numbers
+ $breakpoints_lineNumbers delete $idx0.0 $idx1.0
+ adjust_width $breakpoints_lineNumbers
+
+ # Remove line from the list
+ $breakpoints_text delete $idx0.0 $idx1.0
+
+ # Disable widgets
+ $breakpoints_lineNumbers configure -state disabled
+ $breakpoints_text configure -state disabled
+
+ # Reevaluate icon bar button states
+ bm_bp_disEna_buttons
+ }
+
+ ## Adjust width of given text widget to fit lenght of the last line
+ # @parm Widget widget - target text widget
+ # @return void
+ private method adjust_width {widget} {
+ $widget configure -width [string length [lindex [$widget get end-2l end] end]]
+
+ catch {
+ $widget tag add right 0.0 end
+ }
+ }
+
+ ## Binding for button "Up" (Bookmarks icon bar) - select bookmark above the current line
+ # @return void
+ public method rightPanel_bm_up {} {
+
+ # Gain list of bookmarks (line numbers)
+ set lineNumbers [$bookmarks_lineNumbers get 1.0 end]
+ if {[llength $lineNumbers] == 0} {return}
+
+ # Get current line in the editor
+ set curLineNum [$this editor_procedure {} get_current_line_number {}]
+
+ # Find nearest bookmark
+ set lineNum [lindex $lineNumbers end]
+ set idx -2
+ foreach line $lineNumbers {
+ incr idx
+ if {$line >= $curLineNum} {
+ if {$idx >= 0} {
+ set lineNum [lindex $lineNumbers $idx]
+ }
+ break
+ }
+ }
+
+ # Select designated bookmark and jump to its line
+ rightPanel_bm_select $lineNum
+ $this editor_procedure {} goto $lineNum
+ }
+
+ ## Binding for button "Up" (Breakpoints icon bar) - select breakpoint above the current line
+ # @return void
+ public method rightPanel_bp_up {} {
+
+ # Gain list of breakpoints (line numbers)
+ set lineNumbers [$breakpoints_lineNumbers get 1.0 end]
+ if {[llength $lineNumbers] == 0} {return}
+
+ # Get current line in the editor
+ set curLineNum [$this editor_procedure {} get_current_line_number {}]
+
+ # Find nearest breakpoint
+ set lineNum [lindex $lineNumbers end]
+ set idx -2
+ foreach line $lineNumbers {
+ incr idx
+ if {$line >= $curLineNum} {
+ if {$idx >= 0} {
+ set lineNum [lindex $lineNumbers $idx]
+ }
+ break
+ }
+ }
+
+ # Select designated breakpoint and jump to its line
+ rightPanel_bp_select $lineNum
+ $this editor_procedure {} goto $lineNum
+ }
+
+ ## Binding for button "Down" (Bookmarks icon bar) - select bookmark below the current line
+ # @return void
+ public method rightPanel_bm_down {} {
+ # Gain list of bookmarks (line numbers)
+ set lineNumbers [$bookmarks_lineNumbers get 1.0 end]
+ if {[llength $lineNumbers] == 0} {return}
+
+ # Get current line in the editor
+ set curLineNum [$this editor_procedure {} get_current_line_number {}]
+
+ # Find nearest bookmark
+ set lineNum [lindex $lineNumbers 0]
+ set idx -1
+ foreach line $lineNumbers {
+ incr idx
+ if {$line > $curLineNum} {
+ set lineNum [lindex $lineNumbers $idx]
+ break
+ }
+ }
+
+ # Select designated bookmark and jump to its line
+ rightPanel_bm_select $lineNum
+ $this editor_procedure {} goto $lineNum
+ }
+
+ ## Binding for button "Down" (Breakpoints icon bar) - select breakpoint below the current line
+ # @return void
+ public method rightPanel_bp_down {} {
+ # Gain list of breakpoints (line numbers)
+ set lineNumbers [$breakpoints_lineNumbers get 1.0 end]
+ if {[llength $lineNumbers] == 0} {return}
+
+ # Get current line in the editor
+ set curLineNum [$this editor_procedure {} get_current_line_number {}]
+
+ # Find nearest breakpoint
+ set lineNum [lindex $lineNumbers 0]
+ set idx -1
+ foreach line $lineNumbers {
+ incr idx
+ if {$line > $curLineNum} {
+ set lineNum [lindex $lineNumbers $idx]
+ break
+ }
+ }
+
+ # Select designated breakpoint and jump to its line
+ rightPanel_bp_select $lineNum
+ $this editor_procedure {} goto $lineNum
+ }
+
+ ## Remove all bookmarks from the list
+ # @return void
+ public method rightPanel_clear_all_bookmarks {} {
+ # Enable widgets
+ $bookmarks_lineNumbers configure -state normal
+ $bookmarks_text configure -state normal
+ # Clear text widgets
+ $bookmarks_lineNumbers delete 1.0 end
+ adjust_width $bookmarks_lineNumbers
+ $bookmarks_text delete 1.0 end
+ # Disable widgets
+ $bookmarks_lineNumbers configure -state disabled
+ $bookmarks_text configure -state disabled
+
+ # Reevaluate button states (icon bar)
+ bm_bp_disEna_buttons
+ }
+
+ ## Remove all breapoints editor
+ # @return void
+ public method rightPanel_clear_all_breakpoints {} {
+ # Enable widgets
+ $breakpoints_lineNumbers configure -state normal
+ $breakpoints_text configure -state normal
+ # Clear text widgets
+ $breakpoints_lineNumbers delete 1.0 end
+ adjust_width $breakpoints_lineNumbers
+ $breakpoints_text delete 1.0 end
+ # Disable widgets
+ $breakpoints_lineNumbers configure -state disabled
+ $breakpoints_text configure -state disabled
+
+ # Reevaluate button states (icon bar)
+ bm_bp_disEna_buttons
+ }
+
+ ## Manage list of bookmarks - some lines have been removed from editor widget
+ # @parm Int start_line - start of deleted area
+ # @parm Int end_line - end of deleted area
+ # @return void
+ public method rightPanel_remove_bookmarks {start_line end_line} {
+
+ # Gain list of bookmarks
+ set lineNumbers [$bookmarks_lineNumbers get 1.0 end]
+
+ ## Determinate start and end text indexes (list of bookmarks)
+
+ # Start index
+ set start_idx {}
+ set idx 0
+ foreach line $lineNumbers {
+ incr idx
+ if {$line >= $start_line} {
+ set start_idx $idx.0
+ break
+ }
+ }
+
+ # End index
+ set end_idx {end}
+ set idx 0
+ foreach line $lineNumbers {
+ incr idx
+ if {$line > $end_line} {
+ if {$idx != 0} {
+ set end_idx $idx.0
+ }
+ break
+ }
+ }
+
+ # Default start index
+ if {$start_idx == {}} {
+ if {[lindex $lineNumbers end] != $end_line} {
+ return
+ } {
+ set start_idx 1.0
+ }
+ }
+
+ # Determinate number of lines to remove
+ set diff [expr {$end_line - $start_line + 1}]
+
+ # Enable line numbers
+ $bookmarks_lineNumbers configure -state normal
+ # Gain list of lines to recomputation
+ set lineNumbers [$bookmarks_lineNumbers get $end_idx end]
+ # Remove lines from line numbers
+ $bookmarks_lineNumbers delete $start_idx end
+ if {[llength [$bookmarks_lineNumbers get 1.0 end]] != 0} {
+ $bookmarks_lineNumbers insert end "\n"
+ }
+ # Compute missing lines in line numbers
+ foreach line $lineNumbers {
+ $bookmarks_lineNumbers insert end [expr {$line - $diff}]
+ $bookmarks_lineNumbers insert end "\n"
+ }
+ # Finish adjustemnt of line numbers
+ adjust_width $bookmarks_lineNumbers
+ $bookmarks_lineNumbers configure -state disabled
+
+ # Remove lines from list of bookmarks
+ $bookmarks_text configure -state normal
+ $bookmarks_text delete $start_idx $end_idx
+ $bookmarks_text configure -state disabled
+
+ # Reevaluate button states (icon bar)
+ bm_bp_disEna_buttons
+ }
+
+ ## Manage list of breakpoints - some lines have been removed from editor widget
+ # @parm Int start_line - start of deleted area
+ # @parm Int end_line - end of deleted area
+ # @return void
+ public method rightPanel_remove_breakpoints {start_line end_line} {
+
+ # Gain list of breakpoints
+ set lineNumbers [$breakpoints_lineNumbers get 1.0 end]
+
+ ## Determinate start and end text indexes (list of breakpoints)
+
+ # Start index
+ set start_idx {}
+ set idx 0
+ foreach line $lineNumbers {
+ incr idx
+ if {$line >= $start_line} {
+ set start_idx $idx.0
+ break
+ }
+ }
+
+ # End index
+ set end_idx {end}
+ set idx 0
+ foreach line $lineNumbers {
+ incr idx
+ if {$line > $end_line} {
+ if {$idx != 0} {
+ set end_idx $idx.0
+ }
+ break
+ }
+ }
+
+ # Default start index
+ if {$start_idx == {}} {
+ if {[lindex $lineNumbers end] != $end_line} {
+ return
+ } {
+ set start_idx 1.0
+ }
+ }
+
+ # Determinate number of lines to remove
+ set diff [expr {$end_line - $start_line + 1}]
+
+ # Enable line numbers
+ $breakpoints_lineNumbers configure -state normal
+ # Gain list of lines to recomputation
+ set lineNumbers [$breakpoints_lineNumbers get $end_idx end]
+ # Remove lines from line numbers
+ $breakpoints_lineNumbers delete $start_idx end
+ if {[llength [$breakpoints_lineNumbers get 1.0 end]] != 0} {
+ $breakpoints_lineNumbers insert end "\n"
+ }
+ # Compute missing lines in line numbers
+ foreach line $lineNumbers {
+ $breakpoints_lineNumbers insert end [expr {$line - $diff}]
+ $breakpoints_lineNumbers insert end "\n"
+ }
+ # Finish adjustemnt of line numbers
+ adjust_width $breakpoints_lineNumbers
+ $breakpoints_lineNumbers configure -state disabled
+
+ # Remove lines from list of breakpoints
+ $breakpoints_text configure -state normal
+ $breakpoints_text delete $start_idx $end_idx
+ $breakpoints_text configure -state disabled
+
+ # Reevaluate button states (icon bar)
+ bm_bp_disEna_buttons
+ }
+
+ ## Clear the list of symbols
+ # @return void
+ public method rightPanel_clear_symbol_list {} {
+ $sm_lineNumbers configure -state normal
+ $sm_text configure -state normal
+
+ $sm_lineNumbers delete 0.0 end
+ $sm_text delete 0.0 end
+ adjust_width $sm_lineNumbers
+
+ $sm_lineNumbers configure -state disabled
+ $sm_text configure -state disabled
+ }
+
+ ## Refresh the list of symbols
+ # @return void
+ public method rightPanel_refresh_symbols {} {
+ rightPanel_clear_symbol_list
+
+ $this editor_procedure {} autocompletion_turned_on {}
+ $this editor_procedure {} clear_autocompletion_list {}
+ $this editor_procedure {} comp_win_highlight_all_in_background {}
+ }
+
+ ## Validator for search entrybox in the list of symbols
+ # @parm String content - A string to search for
+ # @parm Widget widget - Search entrybox widget
+ # @parm Widget clr_b - Clear button
+ # @return Bool - Success
+ public method rightPanel_sm_search_validate {content widget clr_b} {
+ # No recursion ...
+ if {$search_val_in_progress} {return 0}
+ set search_val_in_progress 1
+
+ # Empty string
+ if {![string length $content]} {
+ $widget configure -style TEntry
+ $clr_b configure -state disabled
+
+ set search_val_in_progress 0
+ return 1
+
+ # Not empty string
+ } {
+ $clr_b configure -state normal
+ }
+
+ # Perform the search
+ set content [string toupper $content]
+ set e [expr {int([$sm_text index insert])}]
+ for {set i 1} {$i < $e} {incr i} {
+ if {![string first $content [string toupper [$sm_text get $i.0 [list $i.0 lineend]]]]} {
+ $widget configure -style StringFound.TEntry
+
+ $sm_text tag remove curLine 1.0 end
+ $sm_text tag add curLine [list $i.0 linestart] [list $i.0+1l linestart]
+
+ set block_select 1
+ $this editor_procedure {} goto $i
+ update idle
+ set block_select 0
+ set search_val_in_progress 0
+ return 1
+ }
+ }
+
+ $widget configure -style StringNotFound.TEntry
+ set search_val_in_progress 0
+ return 1
+ }
+
+ ## Adjust list of symbols
+ # @parm Int lineNum - Line number
+ # @parm String symbol_name - Symbol name
+ # @parm Int symbol_type -
+ # 0 - Label
+ # 1 - Constant
+ # 2 - Something else
+ # 3 - Macro
+ # @parm Bool add__remove - 1 == Add; 0 == Remove
+ # @return void
+ public method rightPanel_adjust_symbol_list {lineNum symbol_name symbol_type add__remove} {
+ $sm_lineNumbers configure -state normal
+ $sm_text configure -state normal
+
+ # Add symbol
+ if {$add__remove} {
+ set indexes [$sm_lineNumbers get 1.0 end]
+
+ set idx -1
+ set i 0
+ foreach line $indexes {
+ incr i
+ if {$line > $lineNum} {
+ set idx $i
+ break
+ }
+ }
+
+ if {$idx == -1} {
+ set idx [$sm_text index {end-1l}]
+ } {
+ append idx {.0}
+ }
+
+ $sm_lineNumbers insert $idx "$lineNum\n"
+ $sm_text insert $idx "$symbol_name\n"
+
+ switch -- $symbol_type {
+ 0 { ;# Label
+ set tag {tag_label}
+ }
+ 1 { ;# Constant
+ set tag {tag_constant}
+ }
+ 2 { ;# C variable
+ set tag {tag_normal}
+ }
+ 3 { ;# Macro
+ set tag {tag_macro}
+ }
+ 7 { ;# C function
+ set tag {tag_c_func}
+ }
+ default {
+ set tag {}
+ }
+ }
+
+ if {$tag != {}} {
+ $sm_text tag add $tag $idx [list $idx lineend]
+ }
+
+ # Remove symbol
+ } {
+ if {$lineNum == {all}} {
+ set idx [list]
+ set e [expr {int([$sm_lineNumbers index end]) - 1}]
+ for {set i 0} {$i < $e} {incr i} {
+ lappend idx $i
+ }
+ } {
+ set idx [lsearch -all [$sm_lineNumbers get 1.0 end] $lineNum]
+ }
+
+ if {$idx == {}} {
+ return
+ }
+ foreach i $idx {
+ incr i
+ if {[string equal [$sm_text get $i.0 [list $i.0 lineend]] $symbol_name]} {
+ $sm_text delete $i.0 $i.0+1l
+ $sm_lineNumbers delete $i.0 $i.0+1l
+ break
+ }
+ }
+ }
+
+ adjust_width $sm_lineNumbers
+ $sm_lineNumbers configure -state disabled
+ $sm_text configure -state disabled
+ }
+
+ ## Shift list of symbols by certain number of lines
+ # @parm Int lineNum - Starting line
+ # @parm Int length - Number of lines to shift by
+ # @return void
+ public method rightPanel_shift_symbols {lineNum length} {
+ if {![info exists sm_lineNumbers]} {return}
+
+ # Get list of bookmarks
+ set lineNumbers [$sm_lineNumbers get 1.0 end]
+
+ # Deterinate start index
+ set start_idx {}
+ set idx 0
+ foreach line $lineNumbers {
+ incr idx
+ if {$line >= $lineNum} {
+ set start_idx $idx.0
+ break
+ }
+ }
+
+ if {$start_idx == {}} {return}
+
+ # Adjust line numbers
+ $sm_lineNumbers configure -state normal
+ set lineNumbers [$sm_lineNumbers get $start_idx end]
+ $sm_lineNumbers delete $start_idx end
+ if {[llength [$sm_lineNumbers get 1.0 end]] != 0} {
+ $sm_lineNumbers insert end "\n"
+ }
+ foreach line $lineNumbers {
+ $sm_lineNumbers insert end [expr {$line + $length}]
+ $sm_lineNumbers insert end "\n"
+ }
+ adjust_width $sm_lineNumbers
+ $sm_lineNumbers configure -state disabled
+ }
+
+ ## Manage list of bookmarks - some lines have been added to editor widget
+ # @parm Int lineNum - line number
+ # @parm Int length - number of lines
+ # @return void
+ public method rightPanel_shift_bookmarks {lineNum length} {
+ if {![info exists bookmarks_lineNumbers]} {return}
+
+ # Get list of bookmarks
+ set lineNumbers [$bookmarks_lineNumbers get 1.0 end]
+
+ # Deterinate start index
+ set start_idx {}
+ set idx 0
+ foreach line $lineNumbers {
+ incr idx
+ if {$line >= $lineNum} {
+ set start_idx $idx.0
+ break
+ }
+ }
+
+ if {$start_idx == {}} {return}
+
+ # Adjust line numbers
+ $bookmarks_lineNumbers configure -state normal
+ set lineNumbers [$bookmarks_lineNumbers get $start_idx end]
+ $bookmarks_lineNumbers delete $start_idx end
+ if {[llength [$bookmarks_lineNumbers get 1.0 end]] != 0} {
+ $bookmarks_lineNumbers insert end "\n"
+ }
+ foreach line $lineNumbers {
+ $bookmarks_lineNumbers insert end [expr {$line + $length}]
+ $bookmarks_lineNumbers insert end "\n"
+ }
+ adjust_width $bookmarks_lineNumbers
+ $bookmarks_lineNumbers configure -state disabled
+ }
+
+ ## Manage list of breakpoints - some lines have been added to editor widget
+ # @parm Int lineNum - line number
+ # @parm Int length - number of lines
+ # @return void
+ public method rightPanel_shift_breakpoints {lineNum length} {
+ if {![info exists bookmarks_lineNumbers]} {return}
+
+ # Get list of bookmarks
+ set lineNumbers [$breakpoints_lineNumbers get 1.0 end]
+
+ # Deterinate start index
+ set start_idx {}
+ set idx 0
+ foreach line $lineNumbers {
+ incr idx
+ if {$line >= $lineNum} {
+ set start_idx $idx.0
+ break
+ }
+ }
+
+ if {$start_idx == {}} {return}
+
+ # Adjust line numbers
+ $breakpoints_lineNumbers configure -state normal
+ set lineNumbers [$breakpoints_lineNumbers get $start_idx end]
+ $breakpoints_lineNumbers delete $start_idx end
+ if {[llength [$breakpoints_lineNumbers get 1.0 end]] != 0} {
+ $breakpoints_lineNumbers insert end "\n"
+ }
+ foreach line $lineNumbers {
+ $breakpoints_lineNumbers insert end [expr {$line + $length}]
+ $breakpoints_lineNumbers insert end "\n"
+ }
+ adjust_width $breakpoints_lineNumbers
+ $breakpoints_lineNumbers configure -state disabled
+ }
+
+ ## Invoke right panel configuration dialog
+ # This function takes any list of arguments
+ # @return void
+ public method rightPanel_configure args {
+ ::configDialogs::rightPanel::mkDialog $args
+ }
+
+ ## Return true if this panel is in visible state
+ # @return Bool - result
+ public method isRightPanelVisible {} {return $PanelVisible}
+
+ ## Get width of the panel
+ # @return Int - width in pixels
+ public method getRightPanelSize {} {
+ if {$PanelVisible} {
+ return $PanelSize
+ } {
+ return $last_PanelSize
+ }
+ }
+
+ ## Get ID of currently active page
+ # @return String - the ID
+ public method getRightPanelActivePage {} {return $active_page}
+
+ ## Show/Hide this panel
+ # @return void
+ public method right_panel_show_hide {} {
+ # Hide the panel
+ if {$PanelVisible} {
+ $parentPane paneconfigure $notebook_frame -minsize 0
+
+ pack forget $notebook ;# Hide notebook
+ set last_PanelSize $PanelSize ;# Save current panel width
+ set PanelSize 60 ;# Change panel width
+ right_panel_redraw_pane ;# Redraw panel
+
+ # Show button bar
+ pack $button_bar -anchor nw
+ # Hide pane sash
+ $parentPane configure -sashwidth 0
+ bind $parentPane <Button> {break}
+ # Set panel visibility flag
+ set PanelVisible 0
+
+ # Show the panel
+ } {
+ $parentPane paneconfigure $notebook_frame -minsize 295
+
+ # Hide button bar
+ pack forget $button_bar
+ # Show panel notebook
+ set PanelSize $last_PanelSize
+ right_panel_redraw_pane
+ $notebook raise $active_page
+ pack $notebook -expand 1 -fill both
+ # Show pane sash
+ $parentPane configure -sashwidth 2
+ bind $parentPane <Button> {}
+ # Set panel visibility flag
+ set PanelVisible 1
+ }
+ }
+
+ ## Change panel active page
+ # @parm String page - ID of the page to show
+ # @return void
+ public method rightPanel_show_up {page} {
+ if {!$PanelVisible} right_panel_show_hide
+ $notebook raise $page
+ }
+
+ ## Set active page but do not show it
+ # @parm String pageName - ID of the page
+ # @return void
+ public method rightPanel_set_active_page {pageName} {
+ switch -- $active_page {
+ {Symbols} {
+ catch {
+ $this editor_procedure {} comp_win_highlight_all_in_background {}
+ }
+ }
+ {Instruction} {
+ right_panel_instruction_details_set_enabled 0
+ }
+ }
+
+ set active_page $pageName
+
+ switch -- $active_page {
+ {Symbols} {
+ catch {
+ $this editor_procedure {} comp_win_highlight_all_in_background {}
+ }
+ }
+ {Instruction} {
+ right_panel_instruction_details_set_enabled $enabled
+ catch {
+ $this editor_procedure {} adjust_instruction_details {}
+ }
+ }
+ }
+ }
+
+ ## Set panel width acording to current sash position
+ # @return void
+ public method right_panel_set_size {} {
+ set PanelSize [lindex [$parentPane sash coord 0] 0]
+ set PanelSize [expr {${::WIN_GEOMETRY_width} - $PanelSize}]
+ }
+
+ ## Redraw panel (move pane sash) acorning to current value of $PanelSize
+ # @return void
+ public method right_panel_redraw_pane {} {
+ if {$redraw_pane_in_progress} {
+ after 50 "$this right_panel_redraw_pane"
+ return
+ }
+ set redraw_pane_in_progress 1
+
+ update
+ $parentPane sash place 0 [expr {${::WIN_GEOMETRY_width} - $PanelSize}] 0
+ update
+
+ set redraw_pane_in_progress 0
+ }
+
+ ## Create text tags inteded for "Instruction details"
+ # @parm Widget widget - tagret text widget
+ # @parm List definition_list - List of tags to create ({tag_name fg_color ?bold_or_italic?} ...)
+ # @parm Bool use_editor_font - Use font family and size from code editor
+ # @return void
+ public method right_panel_create_highlighting_tags {widget definition_list use_editor_font} {
+ if {$use_editor_font == 1} {
+ set font $fontFamily
+ set size $fontSize
+ } elseif {$use_editor_font == -1} {
+ set font $::DEFAULT_FIXED_FONT
+ set size -14
+ } {
+ set font $::DEFAULT_FIXED_FONT
+ set size -12
+ }
+
+ # Iterate over tags definition
+ foreach tag $definition_list {
+
+ # Explicit flag "Bold or Italic"
+ if {[lindex $tag 2] != {}} {
+ # Bold font
+ if {[lindex $tag 2]} {
+ $widget tag configure [lindex $tag 0] \
+ -foreground [lindex $tag 1] \
+ -font [font create -size $size \
+ -family $font \
+ -weight {bold} \
+ -slant {roman}]
+ # Italic font
+ } {
+ $widget tag configure [lindex $tag 0] \
+ -foreground [lindex $tag 1] \
+ -font [font create -size $size \
+ -family $font \
+ -weight {normal} \
+ -slant {italic}]
+ }
+
+ # No bold, no italic
+ } {
+ $widget tag configure [lindex $tag 0] \
+ -foreground [lindex $tag 1] \
+ -font [font create -size $size \
+ -family $font \
+ -weight {normal} \
+ -slant {roman}]
+ }
+ }
+ }
+
+ ## Enable selections in list of bookmarks and breakpoints and enbale instruction details
+ # @return void
+ public method rightPanel_enable {} {
+ set enabled 1
+ $this right_panel_watches_set_enabled $enabled
+ $this right_panel_instruction_details_set_enabled $enabled
+ }
+
+ ## Disable selections in list of bookmarks and breakpoints and enbale instruction details
+ # @return void
+ public method rightPanel_disable {} {
+ set enabled 0
+ $this right_panel_watches_set_enabled $enabled
+ $this right_panel_instruction_details_set_enabled $enabled
+ }
+}
diff --git a/lib/rightpanel/subprograms.tcl b/lib/rightpanel/subprograms.tcl
new file mode 100755
index 0000000..6385266
--- /dev/null
+++ b/lib/rightpanel/subprograms.tcl
@@ -0,0 +1,704 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Provides panel for watching subprogram calls
+# --------------------------------------------------------------------------
+
+class SubPrograms {
+ ## COMMON
+ common fsd_filename {} ;# Filename choosen by FSD
+ # Main font for the text widget
+ common main_font [font create \
+ -family {helvetica} \
+ -size -14 \
+ ]
+ # Bold font for the text widget
+ common bold_font [font create \
+ -family {helvetica} \
+ -size -14 -weight {bold} \
+ ]
+ # Font for status bar below the text box
+ common large_font [font create \
+ -family {helvetica} \
+ -size -14 \
+ ]
+ # Bold font for status bar below the text box
+ common large_bold_font [font create \
+ -family {helvetica} \
+ -size -14 -weight {bold} \
+ ]
+
+ ## PRIVATE
+ private variable parent ;# Widget: parent widget
+ private variable gui_initialized 0 ;# Bool: GUI initialized
+
+ private variable text_widget ;# Widget: Text widget containg almost all the information
+ private variable scrollbar ;# Widget: Scrollbar for the text widget
+ private variable enable_chbut ;# Widget: Check button "Enable"
+ private variable intr_chbut ;# Widget: Check button "Include interrupts"
+ private variable total_val_lbl ;# Widget: Label containg the count of subprograms recorded
+ private variable menu {} ;# Widget: Popup menu for the text widget
+ private variable enabled 1 ;# Bool: Panel active
+ private variable ena_intr 1 ;# Bool: Taking interrupts enabled
+ private variable return_but ;# Widget: Button "RETURN"
+ private variable save_but ;# Widget: Button "Save"
+ private variable clear_but ;# Widget: Button "Clear"
+ private variable count 0 ;# Int: Number of subprograms mentioned in the text widget
+ private variable menu_source {} ;# String: Auxiliary variable for the popup menu -- Source address
+ private variable menu_target {} ;# String: Auxiliary variable for the popup menu -- Target address
+
+ constructor {} {
+ }
+
+ destructor {
+ if {$gui_initialized} {
+ menu_Sbar_remove $menu
+ }
+ }
+
+ ## Prepare this panel for initialization of its GUI
+ # MUST BE called before "CreateSubProgramsGUI"
+ # @parm Widget _parent - Frame where this panel would be created
+ # @return void
+ public method PrepareSubPrograms {_parent} {
+ set parent $_parent
+ set gui_initialized 0
+ load_config $::CONFIG(SUBP_MON_CONFIG)
+ }
+
+ ## Finalize initialization of this panel
+ # @return void
+ public method CreateSubProgramsGUI {} {
+ create_gui
+ subprograms_create_tags
+ create_menus
+ set_bindings
+ }
+
+ ## Get configuration list for this panel
+ # @return void
+ public method subprograms_get_config {} {
+ return [list $enabled $ena_intr]
+ }
+
+ ## Load configuration list for this panel
+ # @parm List conf - Configuration list
+ # @return void
+ private method load_config {conf} {
+ if {![regexp {^[01] [01]$} $conf]} {
+ return
+ }
+ set enabled [lindex $conf 0]
+ set ena_intr [lindex $conf 1]
+ }
+
+ ## Create all widgets which this panel consist of
+ # @return void
+ private method create_gui {} {
+ if {$gui_initialized} {return}
+ set gui_initialized 1
+
+ # Create top frame (checkbuttons)
+ set top_frame [frame $parent.top]
+ set enable_chbut [checkbutton $top_frame.enable_chbut \
+ -text [mc "Enable"] \
+ -command "$this subprograms_dis_ena" \
+ ]
+ set intr_chbut [checkbutton $top_frame.intr_chbut \
+ -text [mc "Include interrupts"] \
+ -command "$this subprograms_intr_yesno" \
+ ]
+ pack $enable_chbut -side left -padx 10
+ pack $intr_chbut -side left -padx 10
+
+ # Adjust check buttons
+ if {$enabled} {
+ $enable_chbut select
+ } {
+ $enable_chbut deselect
+ }
+ if {$ena_intr} {
+ $intr_chbut select
+ } {
+ $intr_chbut deselect
+ }
+
+ # Create button frame (Buttons: Save, Clear and Return)
+ set button_frame [frame $parent.button_frame]
+ set return_but [ttk::button $button_frame.return_but \
+ -text [mc "RETURN"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -command "$this subprograms_force_return" \
+ -state disabled \
+ -width 6 \
+ ]
+ set clear_but [ttk::button $button_frame.clear_but \
+ -text [mc "Clear"] \
+ -style Flat.TButton \
+ -compound left \
+ -state disabled \
+ -image ::ICONS::16::editdelete \
+ -command "$this subprograms_clear" \
+ -width 5 \
+ ]
+ set save_but [ttk::button $button_frame.filesaveas \
+ -text [mc "Save"] \
+ -style Flat.TButton \
+ -compound left \
+ -state disabled \
+ -image ::ICONS::16::filesaveas \
+ -command "$this subprograms_save" \
+ -width 5 \
+ ]
+ pack $save_but -pady 0 -side left
+ pack $clear_but -pady 0 -side left -padx 5
+ pack $return_but -pady 0 -side right
+
+ # Create middle frame (text widget and its scrollbar)
+ set middle_frame [frame $parent.middle]
+ set text_widget [text $middle_frame.text \
+ -yscrollcommand "$middle_frame.scrollbar set" \
+ -bg {#FFFFFF} -width 0 -height 0 \
+ -font $main_font -insertontime 0 -wrap none \
+ -cursor left_ptr -takefocus 0 \
+ -tabstyle wordprocessor \
+ ]
+ set scrollbar [ttk::scrollbar $middle_frame.scrollbar \
+ -orient vertical \
+ -command "$text_widget yview" \
+ ]
+ pack $text_widget -side left -fill both -expand 1
+ pack $scrollbar -side right -fill y -after $text_widget
+
+ # Create bottom frame
+ set bottom_frame [frame $parent.bottom]
+ pack [label $bottom_frame.total_lbl \
+ -text [mc "TOTAL: "] -font $large_font \
+ -fg {#555555} \
+ ] -side left
+ set total_val_lbl [label $bottom_frame.total_val_lbl \
+ -font $large_bold_font -text {0} \
+ ]
+ pack $total_val_lbl -side left
+
+ # Pack all main frames
+ pack $top_frame -fill x
+ pack $button_frame -fill x
+ pack $middle_frame -fill both -expand 1
+ pack $bottom_frame -fill x -side bottom
+ }
+
+ ## Set event bindings for the text widget
+ # @return void
+ private method set_bindings {} {
+ foreach event {
+ <B1-Enter> <B1-Leave>
+ <B2-Motion> <Button-5> <Button-4>
+ <MouseWheel>
+ } {
+ bind $text_widget $event [bind Text $event]
+ }
+ bind $text_widget <Button-1> "$this subprograms_click %x %y"
+ bind $text_widget <ButtonRelease-3> "$this subprograms_popup %x %y %X %Y"
+ bindtags $text_widget $text_widget
+ }
+
+ ## Create popup menu for the text widget
+ # @return void
+ private method create_menus {} {
+ set menu "$text_widget.popup_menu"
+ if {[winfo exists $menu]} {destroy $menu}
+ menuFactory {
+ {command {Go to source line} {} 0 "subprograms_menu_action 0"
+ {goto} "Navigate code editor to the line from which this subprogram was invoked"}
+ {command {Go to target line} {} 0 "subprograms_menu_action 1"
+ {goto} "Navigate code editor to the line from where this subprogram resides"}
+ {separator}
+ {command {Copy source address to clipboard} {} 0 "subprograms_menu_action 2"
+ {editcopy} "Copy return address to clipboard (hexadecimal representation)"}
+ {command {Copy target address to clipboard} {} 0 "subprograms_menu_action 3"
+ {editcopy} "Copy address where this subprogram begins to the clipboard"}
+ {separator}
+ {command {Remove this} {} 0 "subprograms_menu_action 4"
+ {editdelete} "Remove this entry"}
+ } $menu 0 "$this " 0 {}
+ }
+
+ ## Create highlighting tags for the text widget
+ # @return void
+ private method subprograms_create_tags {} {
+ $text_widget tag configure tag_sel -borderwidth 1 -relief raised
+ $text_widget tag configure tag_from -foreground {#00AA00}
+ $text_widget tag configure tag_to -foreground {#0000AA}
+ $text_widget tag configure tag_ins -font $bold_font
+ $text_widget tag configure tag_first -background {#DDDDDD}
+ }
+
+ ## Toggle state enabled for whole panel
+ # @return void
+ public method subprograms_dis_ena {} {
+ set enabled [expr {!$enabled}]
+ if {$enabled} subprograms_clear
+ }
+
+ ## Toggle flag "Enable interrupts"
+ # @return void
+ public method subprograms_intr_yesno {} {
+ set ena_intr [expr {!$ena_intr}]
+ }
+
+ ## Event handler for the text widget: <Button-1>
+ # @parm Int x - Relative pointer position
+ # @parm Int y - Relative pointer position
+ # @return void
+ public method subprograms_click {x y} {
+ set menu_source {}
+ set menu_target {}
+ $text_widget configure -state normal
+
+ # Remove selection and determinate line number
+ $text_widget tag remove tag_sel 1.0 end
+ set line [expr {int([$text_widget index @$x,$y])}]
+
+ # Adjust selection
+ if {$line % 3} {
+ set line [expr {($line / 3) * 3}]
+ if {($line / 3) < $count} {
+ # Set selection
+ incr line
+ $text_widget tag add tag_sel $line.0 [expr {$line+2}].0
+
+ # Determinate source address of the selected subprogram
+ regexp {\w+\s*$} [$text_widget get \
+ $line.0 [list $line.0 lineend] \
+ ] menu_target
+ set menu_target [string trimright $menu_target { h}]
+ if {![string is xdigit $menu_target]} {
+ set menu_target {}
+ }
+
+ # Determinate target address of the selected subprogram
+ regexp {\w+\s*$} [$text_widget get \
+ [expr {$line + 1}].0 \
+ [list [expr {$line + 1}].0 lineend] \
+ ] menu_source
+ set menu_source [string trimright $menu_source { h}]
+ if {![string is xdigit $menu_source]} {
+ set menu_source {}
+ }
+ }
+ }
+
+ # Disable the text widget again
+ $text_widget configure -state disabled
+ }
+
+ ## Perform certain menu action (popup menu for the text widget)
+ # @parm Int action - ID of action to execute
+ # @return void
+ public method subprograms_menu_action {action} {
+ switch -- $action {
+ 0 { ;# Action: "Go to source line"
+ if {$menu_source != {}} {
+ goto_line [expr {"0x$menu_source" - 1}]
+ }
+ }
+ 1 { ;# Action: "Go to target line"
+ if {$menu_target != {}} {
+ goto_line [expr "0x$menu_target"]
+ }
+ }
+ 2 { ;# Action: "Copy source address to clipboard"
+ clipboard clear
+ clipboard append $menu_source
+ }
+ 3 { ;# Action: "Copy target address to clipboard"
+ clipboard clear
+ clipboard append $menu_target
+ }
+ 4 { ;# Remove this entry
+ if {[llength [$text_widget tag nextrange tag_sel 1.0]]} {
+ $text_widget configure -state normal
+ $text_widget delete tag_sel.first tag_sel.last+1l
+ $text_widget configure -state disabled
+ }
+ }
+ }
+ }
+
+ ## Action: "Go to source line" / "Go to target line"
+ # @parm Int address - Address in code memory
+ # @return void
+ private method goto_line {address} {
+ # Resolve line number and source address
+ set line [$this simulator_address2line $address]
+ set address [$this simulator_line2address [lindex $line 0] [lindex $line 1]]
+
+ # Line resolved
+ if {$line != {}} {
+ # Simulator is running
+ if {[$this is_frozen]} {
+ $this setPC $address
+ $this Simulator_sync_PC_etc
+ $this move_simulator_line $line
+ # Simulator is not running
+ } {
+ set filename [$this simulator_get_filename [lindex $line 1]]
+ set filename [file tail $filename]
+ if {[$this fucus_specific_editor $filename 0]} {
+ $this editor_procedure {} goto [lindex $line 0]
+ }
+ }
+ # Line unresolved
+ } {
+ tk_messageBox \
+ -parent . \
+ -title [mc "Line not found"] \
+ -message [mc "There is no matching line in the source code"]
+ }
+ }
+
+ ## Invoke popup menu for the text widget
+ # @parm Int x - Relative position of mouse pointer
+ # @parm Int y - Relative position of mouse pointer
+ # @parm Int X - Absolute position of mouse pointer
+ # @parm Int Y - Absolute position of mouse pointer
+ # @return void
+ public method subprograms_popup {x y X Y} {
+ # Adjust selection
+ subprograms_click $x $y
+
+ # Determinate line and what to do with the menu
+ set line [expr {int([$text_widget index @$x,$y])}]
+ if {$line % 3} {
+ set line [expr {$line / 3}]
+ if {$line >= $count} {
+ set state {disabled}
+ } {
+ set state {normal}
+ }
+ } {
+ set state {disabled}
+ }
+
+ # Adjust states of certain items in the menu
+ foreach entry {
+ {Go to source line}
+ {Go to target line}
+ {Copy source address to clipboard}
+ {Copy target address to clipboard}
+ {Remove this}
+ } {
+ $menu entryconfigure [::mc $entry] -state $state
+ }
+
+ # Invoke the menu
+ tk_popup $menu $X $Y
+ }
+
+ ## Register subprogram call
+ # @parm Int type - Invoked by: 0 == LCALL; 1 == ACALL; 2 == Interrupt; 3 == LCALL or ACALL
+ # @parm Int from - Source address (return address)
+ # @parm Int to - Target address
+ # @return void
+ public method subprograms_call {type from to} {
+ if {!$enabled} {return}
+ if {!$gui_initialized} CreateSubProgramsGUI
+
+ # Determinate string to print as an instruction
+ switch -- $type {
+ 0 {set ins " LCALL\t"}
+ 1 {set ins " ACALL\t"}
+ 2 {
+ set ins " Interrupt\t"
+ if {!$ena_intr} {
+ return
+ }
+ }
+ 3 {set ins " CALL\t"}
+ }
+
+ # Convert value of source address to hexadecimal representation
+ if {$from < 0} {
+ set from {-----}
+ } {
+ set from [format %X $from]
+ set len [string length $from]
+ if {$len < 4} {
+ set from "[string repeat {0} [expr {4 - $len}]]$from"
+ }
+ append from {h}
+ }
+
+ # Convert value of target address to hexadecimal representation
+ if {$to < 0} {
+ set to {-----}
+ } {
+ set to [format %X $to]
+ set len [string length $to]
+ if {$len < 4} {
+ set to "[string repeat {0} [expr {4 - $len}]]$to"
+ }
+ append to {h}
+ }
+
+ # Enable the text widget
+ $text_widget configure -state normal
+
+ # Insert separator
+ if {$count} {
+ $text_widget insert 1.0 "\n"
+ }
+
+ # Print return address
+ $text_widget insert 1.0 "\n"
+ $text_widget insert 1.0 [mc " Return address:\t"]
+ set idx [$text_widget index {1.0 lineend}]
+ $text_widget insert {1.0 lineend} $from
+ $text_widget tag add tag_from $idx {1.0 lineend}
+
+ # Print type and target address
+ $text_widget insert 1.0 "\n"
+ $text_widget insert 1.0 "$ins\t"
+ $text_widget tag add tag_ins 1.0 {1.0 lineend}
+ set idx [$text_widget index {1.0 lineend}]
+ $text_widget insert {1.0 lineend} $to
+ $text_widget tag add tag_to $idx {1.0 lineend}
+
+ $text_widget tag remove tag_first 1.0 end
+ $text_widget tag add tag_first 1.0 3.0
+
+ # Disable the text widget, adjust button bar, labels on the bottom
+ $text_widget configure -state disabled
+ incr count
+ $total_val_lbl configure -text $count
+ disena_buttonbar $count
+ }
+
+ ## Disable or enable buttons on the button bar
+ # @parm Bool bool - 1 == enable; 0 == diable
+ # @return void
+ private method disena_buttonbar {bool} {
+ if {$bool} {
+ set state {normal}
+ } {
+ set state {disabled}
+ }
+ $return_but configure -state $state
+ $clear_but configure -state $state
+ $save_but configure -state $state
+ }
+
+ ## Register return for subprogram
+ # @parm Bool intr__sub - 0 == Common subprogram; 1== Interrupt
+ # @return void
+ public method subprograms_return {intr__sub} {
+ if {!$enabled} {return}
+ if {!$count} {return}
+ if {$intr__sub && !$ena_intr} {return}
+ if {!$gui_initialized} CreateSubProgramsGUI
+
+ $text_widget configure -state normal
+ $text_widget delete 1.0 4.0
+ $text_widget configure -state disabled
+ incr count -1
+ if {$count} {
+ $text_widget tag remove tag_first 1.0 end
+ $text_widget tag add tag_first 1.0 3.0
+ }
+ $total_val_lbl configure -text $count
+ disena_buttonbar $count
+ }
+
+ ## Clear the text widget
+ # @return void
+ public method subprograms_clear {} {
+ if {!$gui_initialized} {return}
+ set count 0
+ $total_val_lbl configure -text 0
+ $text_widget configure -state normal
+ $text_widget delete 1.0 end
+ $text_widget configure -state disabled
+ disena_buttonbar 0
+ }
+
+ ## Enable or disable this panel
+ # @parm Bool bool - 1 == Enable; 0 == Disbale
+ # @return void
+ public method subprograms_setEnabled {bool} {
+ if {!$gui_initialized} {return}
+ if {!$bool} {
+ $return_but configure -state disabled
+ }
+ }
+
+ ## Force return from active subprogram (the topmost entry)
+ # Binding for button "RETURN" on the button bar
+ # @return void
+ public method subprograms_force_return {} {
+ if {![regexp {^\s*\w+} [$text_widget get 1.0 3.0] word]} {
+ return
+ }
+ set word [string trim $word]
+ if {$word == {Interrupt}} {
+ set word 1
+ } {
+ set word 0
+ }
+ $this simulator_return_from_SP $word
+ }
+
+ ## Invoke file selection dialog to save file
+ # Binding for button "Save" on the button bar
+ # @return void
+ public method subprograms_save {} {
+
+ # Invoke the dialog
+ catch {delete object fsd}
+ KIFSD::FSD fsd \
+ -title [mc "Save file - MCU 8051 IDE"] \
+ -directory [$this cget -projectPath] \
+ -defaultmask 0 -multiple 0 -filetypes {
+ {{Plain text} {*.txt} }
+ {{All files} {*} }
+ }
+
+ # Ok button
+ fsd setokcmd {
+ set fsd_filename [::SubPrograms::fsd get]
+ if {!$::MICROSOFT_WINDOWS} { ;# POSIX way
+ if {![regexp "^(~|/)" $fsd_filename]} {
+ set filename "[${::X::actualProject} cget -ProjectDir]/$fsd_filename"
+ }
+ } { ;# Microsoft windows way
+ if {![regexp "^\w:" $fsd_filename]} {
+ set filename [file join [${::X::actualProject} cget -ProjectDir] $fsd_filename]
+ }
+ }
+
+ set ::SubPrograms::fsd_filename [file normalize $fsd_filename]
+ }
+
+ # Activate the dialog
+ fsd activate
+ if {$fsd_filename != {}} {
+ subprograms_save_proc $fsd_filename
+ }
+ }
+
+ ## Save content of the text widget under certain filename
+ # @parm String filename - Target filename
+ # @return void
+ public method subprograms_save_proc {filename} {
+ # Adjust file extension
+ if {[file extension [file tail $filename]] != {.txt}} {
+ append filename {.txt}
+ }
+ # Make backup copy of the file
+ if {[file exists $filename] && [file isfile $filename]} {
+ # Ask user for overwrite existing file
+ if {[tk_messageBox \
+ -type yesno \
+ -icon question \
+ -parent . \
+ -title [mc "Overwrite file"] \
+ -message [mc "A file name '%s' already exists. Are you sure you want to overwrite it ?" [file tail $filename]]
+ ] != {yes}
+ } {
+ return
+ }
+ # Create a backup file
+ catch {
+ file rename -force $filename "$filename~"
+ }
+ }
+ # Try to open the file
+ if {[catch {
+ set file [open $filename w 420]
+ }]} {
+ tk_messageBox \
+ -parent . \
+ -icon warning \
+ -type ok \
+ -title [mc "Permission denied"] \
+ -message [mc "Unable to write to file:\n\"%s\"" $filename]
+ return
+ }
+ # Write content of the text widget into the file and close the file
+ puts -nonewline $file [$text_widget get 1.0 end]
+ close $file
+ }
+
+ ## Get number of recorder active subprograms
+ # @return Int - Count
+ public method subprograms_get_count {} {
+ if {!$gui_initialized} {return 0}
+ return $count
+ }
+
+ ## Get content for purpose of program hibernation
+ # @return String - Text
+ public method subprograms_get_formated_content {} {
+ if {!$gui_initialized} {return {}}
+ set result {}
+ set source {}
+ set target {}
+ set type {}
+ set line_num 0
+
+ foreach line [split [$text_widget get 1.0 end] "\n"] {
+ if {$line == {}} {
+ if {$source != {} && $target != {} && $type != {}} {
+ lappend result [list $source $target $type]
+ }
+ set line 0
+ set source {}
+ set target {}
+ set type {}
+ continue
+ }
+ if {$line_num} {
+ regexp {\w+\s*$} $line source
+ set source [string range $source 0 3]
+ set source [expr "0x$source"]
+ } {
+ regexp {\w+\s*$} $line target
+ set target [string range $target 0 3]
+ set target [expr "0x$target"]
+
+ regexp {^\s*\w+} $line type
+ switch -- [string trim $type] {
+ {LCALL} {set type 0}
+ {ACALL} {set type 1}
+ {Interrupt} {set type 2}
+ {CALL} {set type 3}
+ }
+ }
+ incr line_num
+ }
+ return $result
+ }
+}