diff options
author | Andrej Shadura <andrewsh@debian.org> | 2018-05-08 15:59:29 +0200 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2018-05-08 15:59:29 +0200 |
commit | 5b8466f7fae0e071c0f4eda13051c93313910028 (patch) | |
tree | 7061957f770e5e245ba00666dad912a2d44e7fdc /lib/editor/eventhandlers.tcl |
Import Upstream version 1.3.7
Diffstat (limited to 'lib/editor/eventhandlers.tcl')
-rwxr-xr-x | lib/editor/eventhandlers.tcl | 781 |
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 +} |