summaryrefslogtreecommitdiff
path: root/lib/editor/eventhandlers.tcl
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/editor/eventhandlers.tcl
Import Upstream version 1.3.7
Diffstat (limited to 'lib/editor/eventhandlers.tcl')
-rwxr-xr-xlib/editor/eventhandlers.tcl781
1 files changed, 781 insertions, 0 deletions
diff --git a/lib/editor/eventhandlers.tcl b/lib/editor/eventhandlers.tcl
new file mode 100755
index 0000000..c6d1083
--- /dev/null
+++ b/lib/editor/eventhandlers.tcl
@@ -0,0 +1,781 @@
+#!/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 event handlers
+# This file should be loaded into class Editor in file "editor.tcl"
+# --------------------------------------------------------------------------
+
+
+## Binding for event <Configure>
+ # Commit new width of the editor widget -- for correct line wrapping
+ # @return void
+public method Configure {} {
+ if {$editor_to_use} {return}
+
+ # Check if program is loaded
+ if {!${::APPLICATION_LOADED}} {return}
+
+ # Adjust editor height
+ set eh_org $editor_height
+ adjust_editor_height
+
+ # Determinate width and height of the active area
+ set width [winfo width $editor]
+ incr width -6
+ incr width [expr {-($width % $defaultCharWidth)}]
+
+ # If width changed then adjust line wrapping
+ if {$editor_width != $width} {
+ set editor_width $width
+ set highlighted_lines [string repeat 0 [string bytelength $highlighted_lines]]
+ highlight_visible_area
+ } elseif {$eh_org != $editor_height} {
+ highlight_visible_area
+ }
+}
+
+## This function handles mouse click in frame which wraps the editor text widget
+ # This should happen much often, so this function ensures that everything
+ # is still ok.
+ # @parm Int x - X coordinate
+ # @parm Int y - Y coordinate
+ # @return void
+public method click_under_editor {x y} {
+ Configure
+
+ catch {
+ $editor tag remove sel 0.0 end
+ }
+
+ # Move insertion cursor
+ $editor mark set insert [$editor index @$x,$y+1l]
+
+ # Adjust meters
+ rightPanel_adjust [expr {int([$editor index insert])}]
+ recalc_status_counter {} 1
+ $editor see insert
+
+}
+
+## Handle click on "Line numbers"
+ # Add/Remove breakpoint
+ # @parm Int x - realative X coordinate
+ # @parm Int y - realative Y coordinate
+ # @return void
+public method lineNumbers_click {x y} {
+ Breakpoint [wrap_aux_line2idx [expr {int([$lineNumbers index @$x,$y])}]]
+}
+
+## Handle click on "Icon border"
+ # Add/Remove bookmarks
+ # @parm Int x - realative X coordinate
+ # @parm Int y - realative Y coordinate
+ # @return void
+public method iconBorder_click {x y} {
+ Bookmark [wrap_aux_line2idx [expr {int([$iconBorder index @$x,$y])}]]
+}
+
+## Do the same as scroll + set up the scollbar
+ # @parm Float fraction0 - Freaction where to move
+ # @parm Float fraction1 - Freaction where to setup end of visible area for the scrollbar
+ # @return void
+public method scrollSet {fraction0 fraction1} {
+ if {$editor_to_use} {return}
+
+ $scrollbar set $fraction0 $fraction1
+ scroll moveto $fraction0
+}
+
+public method scroll_0 args {
+ if {$editor_to_use} {return}
+
+ if {[lindex $args 0] != {moveto}} {
+ eval "$this scroll $args"
+ return
+ }
+
+ scroll [expr {int([lindex $args 1] * [$editor index end] + 1)}]
+}
+
+## Scroll simultaneously Icon border, Lines count and editor widget
+ # @parm String - Scroll command (eg. 'moveto')
+ # @parm Float - Scroll fraction
+ # @parm String = {} - Units
+ # @return void
+public method scroll args {
+ if {$editor_to_use} {return}
+
+ # This function cannot be caled recursively
+ if {$scroll_in_progress} {return}
+ set scroll_in_progress 1
+
+ set line 0
+ if {[lindex $args 0] == {scroll}} {
+ set line [expr {int([$editor index @5,5])}]
+ set unit [string index [lindex $args end] 0]
+
+ if {$unit != {p}} {
+ incr line [lindex $args 1]
+ } {
+ incr line [expr {30 * [lindex $args 1]}]
+ }
+ incr line -1
+
+ $editor yview $line
+ set row $line
+ incr row
+ set col 0
+
+ } else {
+ eval "$editor yview $args"
+
+ set idx [$editor index @5,5]
+ scan $idx "%d.%d" row col
+ $editor see $idx
+ }
+
+ highlight_visible_area ;# Highlight lines which hasn't been highlighted yet
+ update idle
+
+ set tmp_row $row
+ if {$number_of_wraps} {
+ set remaining $number_of_wraps
+ for {set i 1} {$i < $row} {incr i} {
+ set wrap [lindex $map_of_wraped_lines $i]
+ if {$wrap < 0} {
+ set wrap 0
+ }
+ incr tmp_row $wrap
+ incr remaining -$wrap
+ if {!$remaining} {break}
+ }
+ }
+ if {$col != 0} {
+ incr tmp_row [get_count_of_lines "$idx linestart" "$idx"]
+ }
+ incr tmp_row -1
+
+ $iconBorder yview $tmp_row
+ $lineNumbers yview $tmp_row
+
+ if {$number_of_wraps} {
+ if {$tmp_row != $line} {
+ highlight_visible_area ;# Highlight lines which hasn't been highlighted yet
+ }
+ }
+
+ # Done ...
+ update idle
+ set scroll_in_progress 0
+}
+
+## Invoke editor 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 popupMenu {X Y x y} {
+ if {![winfo exists $menu]} {return}
+
+ if {$frozen} {
+ set address [$parentObject simulator_line2address \
+ [expr {int([$editor index @$x,$y])}] \
+ [$parentObject simulator_get_filenumber $fullFileName] \
+ ]
+ if {$address == {}} {
+ set state {disabled}
+ } {
+ set state {normal}
+ }
+ $menu entryconfigure [::mc "LJMP this line"] -state $state
+ $menu entryconfigure [::mc "LCALL this line"] -state $state
+ } {
+ $menu entryconfigure [::mc "LJMP this line"] -state disabled
+ $menu entryconfigure [::mc "LCALL this line"] -state disabled
+ }
+
+ tk_popup $menu $X $Y
+ $editor mark set insert "@$x,$y"
+ recalc_status_counter {} 0
+}
+
+## Invoke Icon Border 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 iconBorder_popup_menu {X Y x y} {
+ if {![winfo exists $IB_menu]} {return}
+ set line [expr {int([$iconBorder index @$x,$y])}]
+ set line [wrap_aux_line2idx $line]
+ set pmenu_cline $line
+ set bookmark [lindex $bookmarks $line]
+ tk_popup $IB_menu $X $Y
+}
+
+## Invoke Line Numbers 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 lineNumbers_popup_menu {X Y x y} {
+ if {![winfo exists $LN_menu]} {return}
+ set line [expr {int([$lineNumbers index @$x,$y])}]
+ set line [wrap_aux_line2idx $line]
+ set pmenu_cline $line
+ set breakpoint [lindex $breakpoints $line]
+ tk_popup $LN_menu $X $Y
+}
+
+## Invoke statusbar popup menu
+ # @parm Widget editor - Editor widget
+ # @parm Int X - absolute X coordinate
+ # @parm Int Y - absolute Y coordinate
+ # @return void
+public method statusbar_popup_menu {editor X Y} {
+ if {![winfo exists $stat_menu]} {return}
+
+ if {[lindex $statusbar_menu_config 0] != 0} {
+ set state normal
+ } {
+ set state disabled
+ }
+ $stat_menu entryconfigure [::mc "Split vertical"] -state $state
+ $stat_menu entryconfigure [::mc "Split horizontal"] -state $state
+
+ if {[lindex $statusbar_menu_config 1] != 0} {
+ set state normal
+ } {
+ set state disabled
+ }
+ $stat_menu entryconfigure [::mc "Close current view"] -state $state
+
+ if {[lindex $statusbar_menu_config 2] != 0} {
+ set state normal
+ } {
+ set state disabled
+ }
+ $stat_menu entryconfigure [::mc "Back"] -state $state
+
+ if {[lindex $statusbar_menu_config 3] != 0} {
+ set state normal
+ } {
+ set state disabled
+ }
+ $stat_menu entryconfigure [::mc "Forward"] -state $state
+ set ::X::selectedView $this
+ focus $editor
+ tk_popup $stat_menu $X $Y
+}
+
+## Handles pseudo-event: "Selection"
+ # @return void
+public method editor_selection {} {
+ if {$selection_in_progress} {return}
+ set selection_in_progress 1
+
+ switch -- $selection_mode {
+ 0 { ;# Normal selection mode
+ }
+ 1 { ;# Block selection mode
+ adjust_selection_to_block
+ }
+ }
+
+ set selection_in_progress 0
+}
+
+## Handles event: "Control-Key-Up"
+ # @return void
+public method control_down {} {
+ $editor yview scroll 1 units
+}
+
+## Handles event: "Control-Key-Up"
+ # @return void
+public method control_up {} {
+ $editor yview scroll -1 units
+}
+
+## Handles event: "Shift-Key-Down"
+ # @return void
+public method shift_down {} {
+ tk::TextKeySelect $editor [get_up_down_idx 0]
+
+ # Adjust selection in list of bookmarks and list of breakpoints
+ rightPanel_adjust [expr {int([$editor index insert])}]
+
+ # Adjust status bar counters
+ recalc_status_counter {}
+ $editor see insert
+}
+
+## Handles event: "Shift-Key-Up"
+ # @return void
+public method shift_up {} {
+ tk::TextKeySelect $editor [get_up_down_idx 1]
+
+ # Adjust selection in list of bookmarks and list of breakpoints
+ rightPanel_adjust [expr {int([$editor index insert])}]
+
+ # Adjust status bar counters
+ recalc_status_counter {}
+ $editor see insert
+}
+
+## Handles event: "Key-Up"
+ # @return void
+public method up {} {
+ # Move insertion cursor
+ $editor mark set insert [get_up_down_idx 1]
+
+ # Remove selection
+ catch {
+ $editor tag remove sel 1.0 end
+ }
+
+ # Adjust selection in list of bookmarks and list of breakpoints
+ rightPanel_adjust [expr {int([$editor index insert])}]
+
+ # Adjust status bar counters
+ recalc_status_counter {} 1
+ $editor see insert
+}
+
+## Handles event: "Key-Down"
+ # @return void
+public method down {} {
+ # Focus completion popup window
+ if {$completion_win_opened} {
+ catch {
+ focus -force $completion_listbox
+ $completion_listbox selection set [$completion_listbox items 0]
+ }
+ return
+ }
+
+ # Move insertion cursor
+ $editor mark set insert [get_up_down_idx 0]
+
+ # Remove selection
+ catch {
+ $editor tag remove sel 1.0 end
+ }
+
+ # Adjust selection in list of bookmarks and list of breakpoints
+ rightPanel_adjust [expr {int([$editor index insert])}]
+
+ # Adjust status bar counters
+ recalc_status_counter {}
+ $editor see insert
+}
+
+## Handles event: "Key-Escape"
+ # @return void
+public method key_escape {} {
+ if {$completion_win_opened} {
+ catch {
+ detete_text_in_editor sel.first sel.last
+ }
+ }
+ catch {
+ $editor tag remove sel 1.0 end
+ }
+}
+
+## Handles event: "Shift-Key-Home"
+ # @return void
+public method shift_home {} {
+ # Selection tag defined
+ if {[llength [$editor tag nextrange sel 1.0]]} {
+ set sel_f [$editor index sel.first]
+ set sel_l [$editor index sel.last]
+ set idx0 [$editor index insert]
+ $editor tag remove sel 1.0 end
+ home_press
+ set idx1 [$editor index insert]
+
+ if {[$editor compare $idx0 == $sel_f]} {
+ $editor tag add sel $idx1 $sel_l
+ } elseif {[$editor compare $idx0 == $sel_l]} {
+ $editor tag add sel $sel_f $idx1
+ }
+
+ # Nothing selected
+ } {
+ set idx [$editor index insert]
+ home_press
+ catch {
+ $editor tag remove sel 1.0 end
+ }
+
+ if {[$editor compare $idx < insert]} {
+ $editor tag add sel $idx insert
+ } {
+ $editor tag add sel insert $idx
+ }
+ }
+}
+
+## Handles event: "Key-Home"
+ # @return void
+public method home_press {} {
+ # Local variables
+ set idx [$editor index insert] ;# Insert index
+ set row [expr {int($idx)}] ;# Current row
+ regexp {\d+$} $idx col_original ;# Current column
+
+ # Determinate start line index (true line start)
+ if {[regexp {^\s+} [$editor get $row.0 "$row.0 lineend"] space]} {
+ set col [string length $space]
+ if {$col_original == $col} {
+ $editor mark set insert $row.0
+ } {
+ $editor mark set insert $row.$col
+ }
+ } {
+ $editor mark set insert $row.0
+ }
+
+ # Unset selection
+ catch {
+ $editor tag remove sel 1.0 end
+ }
+
+ # Adjust status bar counters
+ recalc_status_counter {} 0
+ $editor see insert
+}
+
+## Handles event: "Key-Tab"
+ # @return void
+public method tab_press {} {
+ if {$spaces_no_tabs} {
+ set indent_char [string repeat { } $number_of_spaces]
+ } {
+ set indent_char "\t"
+ }
+
+ # Nothing selected or popup completion window is opened -> insert tab character
+ if {$completion_win_opened || [$editor tag ranges sel] == {}} {
+ Key $indent_char
+
+ # Something selected -> indent
+ } {
+ # convert selection indexes to line numbers
+ set start [expr {int([$editor index sel.first])}]
+ set end_o [$editor index sel.last]
+ set end [expr {int($end_o)}]
+ if {$end == $end_o} {incr end -1}
+ # perform indent on each line in the block
+ for {set line $start} {$line <= $end} {incr line} {
+ $editor insert $line.0 $indent_char
+ rightPanel_changeLineContent $line
+ restore_line_markers $line
+ }
+ $editor tag add sel $start.0 [expr {$end + 1}].0
+
+ # Recalculate status bar
+ recalc_status_counter {} 0
+
+ $editor see insert
+ }
+}
+
+## Handles event: "Shift-Key-Return", "Shift-Key-KP_Enter"
+ # Smart new line
+ # @return void
+public method shift_enter {} {
+ if {$critical_edit_proc} {return}
+ set critical_edit_proc 1
+
+ deleteselection
+ $editor insert insert "\n"
+
+ set line [$editor get [list insert-1l linestart] [list insert-1l lineend]]
+ if {![regexp {^\s*[^\w]+} $line line]} {
+ set critical_edit_proc 0
+ return
+ }
+ $editor insert insert $line
+
+ # Recalcutlate Left frame, status bar and right panel
+ $editor see insert
+ update
+ recalc_left_frame
+ recalc_status_counter {}
+ rightPanel_adjust [expr {int([$editor index insert])}]
+ set critical_edit_proc 0
+
+ # Reevaluate highlight on the next line if C language is used
+ if {$prog_language == 1} {
+ c_syntax_highlight [expr {int([$editor index insert])+1}]
+ }
+}
+
+## Handles event: "Key-Return", "Key-KP_Enter"
+ # @return void
+public method enter {} {
+ if {$critical_edit_proc} {return}
+ set critical_edit_proc 1
+
+ $editor configure -autoseparators 0
+
+ set idx [$editor index insert] ;# Determinate insert index
+ $editor insert $idx "\n" ;# Insert EOL
+ resetUpDownIndex ;# Column changed
+
+ set idx [expr {int($idx)}]
+ incr idx
+
+ # Keep indention of the previous line
+ if {$intentation_mode == {normal}} {
+
+ # Determinate indetication charactes
+ set prev_line [$editor get \
+ [$editor index {insert-1l linestart}] \
+ [$editor index {insert-1l lineend}] \
+ ]
+ if {[string length $prev_line]} {
+ set indent_chars {}
+ regexp {^\s+} $prev_line indent_chars
+
+ # Insert indentication characers from the previous line
+ if {$indent_chars != {}} {
+ $editor insert $idx.0 $indent_chars
+ }
+
+ if {$prev_line == $indent_chars} {
+ $editor delete {insert-1l linestart} {insert-1l lineend}
+ }
+ }
+ }
+
+ # Remove selected text
+ deleteselection
+
+ # Recalcutlate Left frame, status bar and right panel
+ $editor see $idx.0
+ update
+ recalc_left_frame
+ recalc_status_counter {}
+ rightPanel_adjust $idx
+ set critical_edit_proc 0
+
+ # Reevaluate highlight on the next line if C language is used
+ if {$prog_language == 1} {
+ incr idx
+ c_syntax_highlight $idx
+ }
+
+ $editor edit separator
+ $editor configure -autoseparators 1
+}
+
+## Handles event: 'Menu'
+ # @return void
+public method Key_Menu {} {
+ # Close autocompletion popup window
+ if {$completion_win_opened} {
+ close_completion_popup_window
+ }
+
+ # Invoke popup menu
+ $editor see insert
+ set bbox [$editor bbox [$editor index insert]]
+ tk_popup $menu \
+ [expr {[winfo rootx $editor] + [lindex $bbox 0] + 10}] \
+ [expr {[winfo rooty $editor] + [lindex $bbox 1] + 10}]
+}
+
+## Handles event: 'KeyRelease'
+ # @parm String key - Key name
+ # @return void
+public method KeyRelease {key} {
+ if {[lsearch {ISO_Next_Group ISO_Prev_Group Alt_R Alt_L Control Meta Shift_L Shift_R} $key] == -1} {
+ if {$do_not_hide_comp_win} {
+ set do_not_hide_comp_win 0
+ } {
+ close_completion_popup_window
+ }
+ }
+}
+
+## Handles event: 'Key'
+ # @return void
+public method Key {key} {
+ # Skip values with no meaning
+ if {![string is print -strict $key] && $key != "\t"} {
+ return
+ }
+
+ if {$key_handler_in_progress} {
+ if {[llength $key_handler_buffer] < 4} {
+ lappend key_handler_buffer $key
+ }
+ return
+ }
+ set key_handler_in_progress 1
+ set scroll_in_progress 1 ;# Block scrolling
+
+ autocompletion_maybe_important_change insert insert
+ $editor configure -autoseparators 0
+
+ if {
+ $auto_brackets &&
+ ($key == {'} || $key == "\"" || $key == {(} || $key == "\[" || $key == "\{")
+ } then {
+ # Enclose selected text by the selected charactere
+ if {[llength [$editor tag nextrange sel 1.0]]} {
+ $editor insert sel.first $key
+ switch -- $key {
+ {(} {$editor insert sel.last {)}}
+ {[} {$editor insert sel.last {]}}
+ "\{" {$editor insert sel.last "\}"}
+ default {
+ $editor insert sel.last $key
+ }
+ }
+ $editor mark set insert sel.last
+ $editor tag remove sel 1.0 end
+
+ # Insert the selected character twice
+ } {
+ set next_char [$editor get insert insert+1c]
+ $editor insert insert $key
+ switch -- $key {
+ {(} {$editor insert insert {)}}
+ {[} {$editor insert insert {]}}
+ "\{" {$editor insert insert "\}"}
+ {'} {
+ if {$next_char != {'}} {
+ $editor insert insert {'}
+ }
+ }
+ "\"" {
+ if {$next_char != "\""} {
+ $editor insert insert "\""
+ }
+ }
+ default {
+ $editor insert insert $key
+ }
+ }
+ $editor mark set insert {insert - 1c}
+ }
+
+ } else {
+ # Delete selected text
+ deleteselection
+
+ # Mode overwrite
+ if {!$ins_ovr_mode} {
+ if {[$editor compare insert != {insert lineend}]} {
+ detete_text_in_editor insert insert+1c
+ }
+ }
+
+ # Insert the given character
+ $editor insert insert $key
+ }
+ # Restore highlight on the current line
+ parse [expr {int([$editor index insert])}]
+ set scroll_in_progress 1 ;# Block scrolling
+ recalc_left_frame
+ set scroll_in_progress 1 ;# Block scrolling
+
+ # Invoke popup completion menu
+ if {$auto_completion} {
+ aux_Key_autocompletion_0 \
+ [$editor index {insert-1c wordstart}] \
+ [$editor index {insert-1c wordend}]
+ }
+
+ $editor edit separator
+ $editor configure -autoseparators 1
+
+ if {[llength $key_handler_buffer]} {
+ set key [lindex $key_handler_buffer 0]
+ set key_handler_buffer [lreplace $key_handler_buffer 0 0]
+ update
+ set scroll_in_progress 0 ;# Unblock scrolling
+ set key_handler_in_progress 0
+ Key $key
+ }
+ set key_handler_in_progress 0
+ update
+ set scroll_in_progress 0 ;# Unblock scrolling
+}
+
+## Handles event: 'Key-Delete'
+ # @return void
+public method key_delete {} {
+ if {![$this deleteselection 1]} {
+ if {[$editor compare {insert linestart} != {insert+1c linestart}]} {
+ set remove_trailing_space 1
+ } {
+ set remove_trailing_space 0
+ }
+
+ $this detete_text_in_editor insert insert+1c
+
+ if {$remove_trailing_space && [regexp {\s+$} [$editor get {insert linestart} {insert lineend}] space]} {
+ set line_end [$editor index {insert lineend}]
+ $editor delete $line_end-[string length $space]c {insert lineend}
+ }
+ }
+
+ $this resetUpDownIndex
+ $this recalc_left_frame
+ update
+}
+
+## Handles event: 'Key-Backspace'
+ # @return void
+public method key_backspace {} {
+ if {$auto_brackets} {
+ set char0 [$editor get insert-1c insert]
+ set char1 [$editor get insert insert+1c]
+ if {
+ ($char0 == "\{" && $char1 == "\}") ||
+ ($char0 == {(} && $char1 == {)}) ||
+ ($char0 == {[} && $char1 == {]})
+ } then {
+ $this detete_text_in_editor insert insert+1c
+ } elseif {$char0 == $char1 && ($char0 == "\"" || $char1 == {'})} {
+ $this detete_text_in_editor insert insert+1c
+ }
+ }
+ if {![$this deleteselection]} {
+ $this detete_text_in_editor insert-1c insert
+ }
+ $this resetUpDownIndex
+ $this recalc_left_frame
+ $this parse [expr {int([$editor index insert])}]
+ update
+}