summaryrefslogtreecommitdiff
path: root/lib/editor/generalproc.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/editor/generalproc.tcl')
-rw-r--r--[-rwxr-xr-x]lib/editor/generalproc.tcl539
1 files changed, 412 insertions, 127 deletions
diff --git a/lib/editor/generalproc.tcl b/lib/editor/generalproc.tcl
index f73be85..3bf8767 100755..100644
--- a/lib/editor/generalproc.tcl
+++ b/lib/editor/generalproc.tcl
@@ -2,7 +2,7 @@
# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
############################################################################
-# Copyright (C) 2007-2009 by Martin Ošmera #
+# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera #
# martin.osmera@gmail.com #
# #
# This program is free software; you can redistribute it and#or modify #
@@ -21,6 +21,11 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
############################################################################
+# >>> File inclusion guard
+if { ! [ info exists _GENERALPROC_TCL ] } {
+set _GENERALPROC_TCL _
+# <<< File inclusion guard
+
# --------------------------------------------------------------------------
# DESCRIPTION
# Implements general purpose procedures
@@ -43,7 +48,7 @@ public method switch_sel_mode {} {
if {$selection_mode} {
adjust_selection_to_block
$sel_mode_lbl configure -text [mc "BLK"] -fg #0088CC
- } {
+ } else {
if {[llength [$editor tag nextrange sel 1.0]]} {
$editor tag add sel sel.first sel.last
}
@@ -73,7 +78,7 @@ public method getBreakpoints {} {
# @parm Bool inSelection - Search in the selected block / search globaly
# @parm String Sindex - index in the text where the search should start
# @parm String String - String to search
- # @return List - {indexMatchBegining indexMatchEnd matchesCount}
+ # @return List - {indexMatchBeginning indexMatchEnd matchesCount}
public method find {fromCursor Backwards regExp noCase inSelection Sindex String} {
## adjust search options
@@ -85,10 +90,10 @@ public method find {fromCursor Backwards regExp noCase inSelection Sindex String
if {$inSelection} {
set Sindex sel.first
set Eindex sel.last
- } {
+ } else {
if {$Backwards} {
set Eindex 1.0
- } {
+ } else {
set Eindex {end}
}
}
@@ -97,12 +102,12 @@ public method find {fromCursor Backwards regExp noCase inSelection Sindex String
if {$fromCursor} {
# Sindex
set Sindex {insert}
- } {
+ } else {
# Sindex
if {$Sindex == {}} {
if {$Backwards} {
set Sindex end
- } {
+ } else {
set Sindex 1.0
}
}
@@ -112,7 +117,7 @@ public method find {fromCursor Backwards regExp noCase inSelection Sindex String
if {$Backwards} {
append Sindex -[expr {[string length $String] - 1}]c
set direction {-backwards}
- } {
+ } else {
set direction {-forwards}
}
@@ -125,7 +130,7 @@ public method find {fromCursor Backwards regExp noCase inSelection Sindex String
set index [$editor search $direction $regexp -nocase \
-count {::editor_search_count} -- \
$String $Sindex $Eindex]
- } {
+ } else {
set index [$editor search $direction $regexp \
-count {::editor_search_count} -- \
$String $Sindex $Eindex]
@@ -149,14 +154,14 @@ public method find {fromCursor Backwards regExp noCase inSelection Sindex String
# Goto line with the found match and select that matched string
if {$Backwards} {
goto $lineNumber.$colNumber
- } {
+ } else {
goto $lineNumber.$end_col
}
$editor tag remove sel 1.0 end
$editor tag add sel $index $lineNumber.$end_col
- # set result acording to values determinated above
+ # set result according to values determinated above
set matches "$index $lineNumber.$end_col ${::editor_search_count}"
- } {
+ } else {
# set result to something like 'nothing found'
set matches "$Sindex $Sindex 0"
}
@@ -196,33 +201,58 @@ public method replace {fromCursor Backwards regExp noCase SearchString Replaceme
if {$critical_edit_proc} {return 0}
set critical_edit_proc 1
- ## Derminate indexes of area to be affected
+ ## Derminate indexes of the area to be affected
if {$fromCursor} {
# from actual cursor position
set index {insert}
- } {
+ } else {
if {$Backwards} {
set index {end}
- } {
+ } else {
set index 1.0
}
}
## Perform replacement for each match
- while $remaining {
+ set index_org {}
+ set index_new {}
+ while {1} {
# Initiate search and determinate count of remaining matches
- set result [find $fromCursor $Backwards $regExp $noCase 0 $index $SearchString]
-
- set remaining [lindex $result 2]
- if {$remaining == 0} {break}
-
- # Determinate index where to reinitiate search
- set index [lindex $result [expr {!$Backwards}]]
+ set last_chance 0
+ while {1} {
+ set result [find $fromCursor $Backwards $regExp $noCase 0 $index $SearchString]
+
+ set remaining [lindex $result 2]
+ if {$remaining == 0} {break}
+
+ # Determinate index where to reinitiate search
+ set index_org $index_new
+ set index [lindex $result [expr {!$Backwards}]]
+ set index_new $index
+ if {$index_org == $index} {
+ if {$last_chance} {
+ break
+ } else {
+ if {!$Backwards} {
+ set index [$editor index [list $index {+1c}]]
+ } else {
+ set index [$editor index [list $index {-1c}]]
+ }
+ set last_chance 1
+ }
+ } else {
+ set last_chance 0
+ break
+ }
+ }
+ if {$last_chance || $remaining == 0 || $remaining == {}} {
+ break
+ }
- # "Annoy user" if there is requested confirmation before each replace
+ # Ask user if there is requested confirmation before each replace
if {$confirm} {
# invoke confirmation command and setup new parameters
- switch [$confirmCMD] {
+ switch -- [$confirmCMD] {
0 { ;# Replace
set cnd 1
}
@@ -246,8 +276,8 @@ public method replace {fromCursor Backwards regExp noCase SearchString Replaceme
break
}
}
- } {
- # automaticaly replace all without any prompt
+ } else {
+ # automatically replace all without any prompt
set cnd 1
}
@@ -272,7 +302,7 @@ public method replace {fromCursor Backwards regExp noCase SearchString Replaceme
for {set line $start} {$line <= $end} {incr line} {
parse $line
}
- } {
+ } else {
for {set line $start} {$line <= $end} {incr line} {
restore_line_markers $line
}
@@ -303,9 +333,9 @@ public method replace {fromCursor Backwards regExp noCase SearchString Replaceme
# @return void
public method select_all {} {
catch {
- $editor tag remove sel 1.0 end
+ $editor tag remove sel 1.0 end
}
- $editor tag add sel 1.0 end
+ $editor tag add sel 1.0 end
}
## Comment the selected area or current line
@@ -323,7 +353,7 @@ public method comment {} {
if {[getselection] == {}} {
set restore_sel 0
set end $start
- } {
+ } else {
set restore_sel 1
set start [expr {int([$editor index sel.first])}]
set end_o [$editor index sel.last]
@@ -345,7 +375,7 @@ public method comment {} {
set by_lines 1
set restore_sel 0
set end $start
- } {
+ } else {
set start_o [$editor index sel.first]
set start [expr {int($start_o)}]
set end_o [$editor index sel.last]
@@ -353,7 +383,7 @@ public method comment {} {
if {$end == $end_o && $start == $start_o} {
set restore_sel 1
set by_lines 1
- } {
+ } else {
set restore_sel 0
set by_lines 0
}
@@ -370,7 +400,7 @@ public method comment {} {
restore_line_markers $line
}
# Comment only selected characters
- } {
+ } else {
$editor insert $end_o { */}
$editor insert $start_o {/* }
$editor tag add sel sel.first-3c sel.last+3c
@@ -388,7 +418,7 @@ public method comment {} {
# Restore highlight
if {$prog_language == 1 && ![string index $highlighted_lines $start] == 6} {
parse $start
- } {
+ } else {
for {set i $start} {$i <= $end} {incr i} {
parse $i
}
@@ -417,7 +447,7 @@ public method uncomment {} {
if {[getselection] == {}} {
set restore_sel 0
set end $start
- } {
+ } else {
set restore_sel 1
set start [expr {int([$editor index sel.first])}]
set end_o [$editor index sel.last]
@@ -431,7 +461,7 @@ public method uncomment {} {
set line_data [$editor get $line.0 "$line.0 lineend"]
if {[regexp {^\s*;\s*} $line_data comment]} {
- detete_text_in_editor $line.0 $line.[string length $comment]
+ detete_text_in_editor $line.0 $line.[string length $comment] 0
regsub {;} $comment {} comment
$editor insert $line.0 $comment
restore_line_markers $line
@@ -447,7 +477,7 @@ public method uncomment {} {
set by_lines 1
set restore_sel 0
set end $start
- } {
+ } else {
set start_o [$editor index sel.first]
set start [expr {int($start_o)}]
set end_o [$editor index sel.last]
@@ -455,7 +485,7 @@ public method uncomment {} {
if {$end == $end_o && $start == $start_o} {
set restore_sel 1
set by_lines 1
- } {
+ } else {
set restore_sel 0
set by_lines 0
}
@@ -476,8 +506,8 @@ public method uncomment {} {
set succesful 1
set start_data [string length $start_data]
set end_data [string length $end_data]
- detete_text_in_editor $end_o-${end_data}c $end_o
- detete_text_in_editor $start_o $start_o+${start_data}c
+ detete_text_in_editor $end_o-${end_data}c $end_o 0
+ detete_text_in_editor $start_o $start_o+${start_data}c 0
}
}
@@ -486,13 +516,13 @@ public method uncomment {} {
set line_data [$editor get $line.0 [list $line.0 lineend]]
if {[regexp {^\s*// ?} $line_data line_data]} {
set line_data [string length $line_data]
- detete_text_in_editor $line.0 $line.$line_data
+ detete_text_in_editor $line.0 $line.$line_data 0
manage_autocompletion_list $line
set succesful 1
}
restore_line_markers $line
}
- } {
+ } else {
$editor edit separator
$editor configure -autoseparators 1
return $succesful
@@ -504,7 +534,7 @@ public method uncomment {} {
# Restore highlight
if {$prog_language == 1 && ![string index $highlighted_lines $start] == 6} {
parse $start
- } {
+ } else {
for {set i $start} {$i <= $end} {incr i} {
parse $i
}
@@ -517,6 +547,13 @@ public method uncomment {} {
}
+ # Perform spell checking for all the affected lines
+ if {$spellchecker_enabled} {
+ for {set i $start} {$i <= $end} {incr i} {
+ spellcheck_check_all $i
+ }
+ }
+
# Return result
return $succesful
}
@@ -545,7 +582,7 @@ public method goto {textIndex} {
[$editor index "$textIndex +1 line linestart"]
}
recalc_status_counter {} 0
- update idle
+ update idletasks
$editor see insert
}
@@ -599,7 +636,7 @@ public method indent {} {
set restore_sel 0
set start [expr {int([$editor index insert])}]
set end $start
- } {
+ } else {
set restore_sel 1
set start [expr {int([$editor index sel.first])}]
set end_o [$editor index sel.last]
@@ -610,7 +647,7 @@ public method indent {} {
# indent each line in the block
if {$spaces_no_tabs} {
set indent_char [string repeat { } $number_of_spaces]
- } {
+ } else {
set indent_char "\t"
}
for {set line $start} {$line <= $end} {incr line} {
@@ -635,7 +672,7 @@ public method unindent {} {
set restore_sel 0
set start [expr {int([$editor index insert])}]
set end [expr {int([$editor index insert])}]
- } {
+ } else {
set restore_sel 1
set start [expr {int([$editor index sel.first])}]
set end_o [$editor index sel.last]
@@ -655,7 +692,7 @@ public method unindent {} {
} elseif {[regexp {^\t} $line_data]} {
detete_text_in_editor $line.0 $line.1
}
- } {
+ } else {
if {[regexp {^[\t( )]} $line_data]} {
detete_text_in_editor $line.0 $line.1
}
@@ -717,15 +754,15 @@ public method get_md5 {} {
## Add/Remove bookmark to/from current line
# Directly depends on variable "bookmarks" (managed by proc. recalc_left_frame)
- # @parm Int = NULL - target text index
+ # @parm Int idx=NULL - target text index
# @return bool - 0: bookmark removed; 1: bookmark created
-public method Bookmark args {
+public method Bookmark {{idx {}}} {
if {$editor_to_use} {return}
# Determinate line number
- if {$args != {}} {
- set lineNumber [expr {int($args)}]
- } {
+ if {$idx != {}} {
+ set lineNumber [expr {int($idx)}]
+ } else {
set lineNumber [expr {int([$editor index insert])}]
}
@@ -758,10 +795,10 @@ public method Bookmark args {
$iconBorder image create $lineNumber_i.0 \
-image ::ICONS::16::dot \
-align center
- } {
+ } else {
if {[llength [$editor tag nextrange tag_error $lineNumber.0 [list $lineNumber.0 lineend]]]} {
set image {bm_ex}
- } {
+ } else {
set image {bookmark}
}
$iconBorder image create $lineNumber_i.0 \
@@ -769,7 +806,7 @@ public method Bookmark args {
-align center
}
# Remove icon
- } {
+ } else {
$iconBorder delete $lineNumber_i.0 $lineNumber_i.2
if {
[llength [$editor tag nextrange tag_error $lineNumber.0 [list $lineNumber.0 lineend]]]
@@ -794,14 +831,14 @@ public method Bookmark args {
$parentObject rightPanel_add_bookmark $lineNumber
$parentObject rightPanel_bm_select $lineNumber
# Remove the tag
- } {
+ } else {
$editor tag remove tag_bookmark $lineNumber.0 $tmp.0
$parentObject rightPanel_remove_bookmark $lineNumber
$parentObject rightPanel_bm_unselect
}
# Enable scrolling
- update idle
+ update idletasks
set scroll_in_progress 0
# Done ...
@@ -810,14 +847,14 @@ public method Bookmark args {
## Add/Remove breapoint to/from current line
# Directly depends on variable "breakpoints" (managed by proc. recalc_left_frame)
- # @parm Int = NULL - target text index
+ # @parm Int idx=NULL - target text index
# @return bool - 0: breakpoint removed; 1: breakpoint created; or {}
-public method Breakpoint args {
+public method Breakpoint {{idx {}}} {
# Determinate line number
- if {$args != {}} {
- set lineNumber [expr {int($args)}]
- } {
+ if {$idx != {}} {
+ set lineNumber [expr {int($idx)}]
+ } else {
set lineNumber [expr {int([$editor index insert])}]
}
@@ -844,12 +881,21 @@ public method Breakpoint args {
# Add the tag
if {$make} {
- $lineNumbers tag add tag_breakpoint $lineNumber_i.0 $tmp.0
+ # Detereminate whether the breakpoint will be valid or not
+ if {[is_breakpoint_valid $lineNumber]} {
+ set tag {tag_breakpoint}
+ } else {
+ set tag {tag_breakpoint_INVALID}
+ }
+
+ $lineNumbers tag add $tag $lineNumber_i.0 $tmp.0
$parentObject rightPanel_add_breakpoint $lineNumber
$parentObject rightPanel_bp_select $lineNumber
+
# Remove the tag
- } {
+ } else {
$lineNumbers tag remove tag_breakpoint $lineNumber_i.0 $tmp.0
+ $lineNumbers tag remove tag_breakpoint_INVALID $lineNumber_i.0 $tmp.0
$parentObject rightPanel_remove_breakpoint $lineNumber
$parentObject rightPanel_bp_unselect
}
@@ -863,7 +909,7 @@ public method Breakpoint args {
}
# Enable scrolling
- update idle
+ update idletasks
set scroll_in_progress 0
# done ...
@@ -910,6 +956,7 @@ public method clear_all_breakpoints {} {
# Clear breakpoint tags from line numbers
$lineNumbers tag remove tag_breakpoint 1.0 end
+ $lineNumbers tag remove tag_breakpoint_INVALID 1.0 end
# Clear right panel
$parentObject rightPanel_clear_all_breakpoints
@@ -991,7 +1038,7 @@ public method insertData {data position} {
# Insert data
$editor insert $position [regsub -all {[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F]} $data {}]
# Highlight
- update idle
+ update idletasks
parseAll
}
@@ -1065,7 +1112,7 @@ private method get_count_of_lines {index0 index1} {
# Translate tabulators to spaces
set idx -1
set cor 0
- while 1 {
+ while {1} {
set idx [string first "\t" $lineText [expr {$idx + 1}]]
if {$idx == -1} {break}
@@ -1076,7 +1123,7 @@ private method get_count_of_lines {index0 index1} {
set line_width [font measure $defaultFont_bold -displayof $editor $lineText]
incr line_width [expr {$cor * $defaultCharWidth}]
# Line doesn't contain tabulators
- } {
+ } else {
set line_width [font measure $defaultFont_bold -displayof $editor $lineText]
}
@@ -1090,14 +1137,6 @@ private method get_count_of_lines {index0 index1} {
return $new_wrap
}
-## Get data of bookmarks and breapoints
- # @return List - {bookmarks breakpoints} (eg. {00011 10100})
-public method export_line_markers_data {} {
- set result [join $bookmarks {}]
- lappend result [join $breakpoints {}]
- return $result
-}
-
## Get total number of lines in editor
# @return Int - result
public method getLinesCount {} {
@@ -1107,28 +1146,66 @@ public method getLinesCount {} {
return [expr {int($result) - 1}]
}
+## Get data of bookmarks and breapoints
+ # @return List - {bookmarks breakpoints} (eg. {{1 15 96} {2 45}})
+public method export_line_markers_data {} {
+ set foo [lsearch -ascii -exact -all $bookmarks 1]
+ if {![llength $foo]} {
+ set foo 0
+ }
+ set bar [lsearch -ascii -exact -all $breakpoints 1]
+ if {![llength $bar]} {
+ set bar 0
+ }
+ return [list $foo $bar]
+}
+
## Import list of bookmarks and breapoints
# This function also validates given input data
# This function does not do anything with the right panel
- # @parm String Bookmarks - bookmakrs (eg. 00011010)
- # @parm String Breakpoints - breakpoints (eg. 011010000000)
+ # @parm String Bookmarks - bookmakrs (eg. {1 15 96})
+ # @parm String Breakpoints - breakpoints (eg. {2 45})
# @return void
public method import_line_markers_data {Bookmarks Breakpoints} {
if {$editor_to_use} {return}
+ # Determinate number of the last line in the editor
+ set lastEnd [expr {int([$editor index end])}]
+
# Check validity of the given data
- if {![regexp {^[01]*$} $Bookmarks]} {
- puts stderr [mc "Invalid list of bookmarks -- bookmarks discarded"]
+ if {[string index $Bookmarks 0] == {0}} {
+ if {![regexp {^[01]*$} $Bookmarks]} {
+ puts stderr [mc "Invalid list of bookmarks -- bookmarks discarded"]
+ set Bookmarks {}
+ }
+ } else {
+ set foo $Bookmarks
set Bookmarks {}
+ for {set i 0} {$i <= $lastEnd} {incr i} {
+ if {[lsearch -ascii -exact $foo $i] != -1} {
+ append Bookmarks 1
+ } else {
+ append Bookmarks 0
+ }
+ }
}
- if {![regexp {^[01]*$} $Breakpoints]} {
- puts stderr [mc "Invalid list of breakpoints -- bookmarks discarded"]
+ if {[string index $Breakpoints 0] == {0}} {
+ if {![regexp {^[01]*$} $Breakpoints]} {
+ puts stderr [mc "Invalid list of breakpoints -- bookmarks discarded"]
+ set Breakpoints {}
+ }
+ } else {
+ set foo $Breakpoints
set Breakpoints {}
+ for {set i 0} {$i <= $lastEnd} {incr i} {
+ if {[lsearch -ascii -exact $foo $i] != -1} {
+ append Breakpoints 1
+ } else {
+ append Breakpoints 0
+ }
+ }
}
- # Determinate number of the last line in the editor
- set lastEnd [expr {int([$editor index end])}]
-
# Initialize list of highlighted lines
set highlighted_lines [string repeat 0 $lastEnd]
@@ -1164,7 +1241,7 @@ public method import_line_markers_data {Bookmarks Breakpoints} {
$iconBorder image create $line.0 \
-image ::ICONS::16::dot \
-align center
- } {
+ } else {
$iconBorder image create $line.0 \
-image ::ICONS::16::bookmark \
-align center
@@ -1269,7 +1346,7 @@ public method set_lock {bool} {
DynamicHelp::add $Sbar_lock_file -text [mc "Unlock file switching"]
$Sbar_lock_file configure \
-image ::ICONS::16::lock
- } {
+ } else {
setStatusTip -widget $Sbar_lock_file -text [mc "File switching unlocked"]
Sbar -freeze [mc "File switching unlocked"]
DynamicHelp::add $Sbar_lock_file -text [mc "Lock file switching"]
@@ -1280,12 +1357,18 @@ public method set_lock {bool} {
}
## Invert simulator lock
- # @retunr void
+ # @return void
public method invert_lock {} {
set_lock [expr {!$auto_switching_lock}]
$parentObject set_editor_lock $this $auto_switching_lock
}
+## Get value of internal flag "frozen"
+ # @return Bool - True if the editor is in simulator mode, or disabled mode
+public method get_flag_frozen {} {
+ return $frozen
+}
+
## Switch from editor mode to simulator mode
# This operation will cause error if editor is in mode disabled
# @return void
@@ -1309,7 +1392,7 @@ public method freeze {} {
if {!$frozen} {
pack $Sbar_ssim_mode -side right
pack $Sbar_lock_file -side left
- } {
+ } else {
pack $Sbar_sim_mode -side right
}
# Disable some popup menu items
@@ -1357,7 +1440,6 @@ public method thaw {} {
if {!$ro_mode} {
$editor configure -state normal
}
- focus -force $editor
set idx [$editor index "insert linestart"]
$editor tag add tag_current_line $idx "$idx + 1 line"
pack $Sbar_CRT_frame
@@ -1379,6 +1461,11 @@ public method thaw {} {
}
# Recalculate counters
recalc_status_counter {} 0
+
+ # Check the flag "file_change_notif_flg" and if set, inform the user
+ #+ about modification to the currently opened file done by another
+ #+ program.
+ check_file_change_notif
}
## Move simulator line (line representing current position in simulator engine)
@@ -1442,12 +1529,15 @@ public method highlight_visible_area {} {
# Highlight the current view
for {set line $start} {$line <= $end} {incr line} {
if {[string index $highlighted_lines $line] == 0} {
- if {![parse $line]} {
+ if {![parse $line 1]} {
if {$line != $start} {break}
}
}
}
+ # Ensure that the current line is also checked for correct spelling
+ spellcheck_check_all [expr {int([$editor index insert])}] 1
+
# Restore previous editor state
if {$frozen} {$editor configure -state disabled}
}
@@ -1458,6 +1548,7 @@ public method highlight_visible_area {} {
# if it is not then invoke procedure 'X::__save_as'
# @return Bool - result
public method save {} {
+ if {$ro_mode} {return 1}
if {$editor_to_use} {return 1}
if {$save_in_progress} {return 1}
set save_in_progress 1
@@ -1474,9 +1565,13 @@ public method save {} {
catch {
file rename -force $fullFileName "$fullFileName~"
}
+
+ # Stop watching for modification of this file on disk (we will reenable it later)
+ FSnotifications::forget $fullFileName
}
+
if {[catch {
- set chanel [open $fullFileName w 420]
+ set chanel [open $fullFileName w 0640]
}]} then {
tk_messageBox \
-parent . \
@@ -1485,6 +1580,10 @@ public method save {} {
-title [mc "Permission denied"] \
-message [mc "Unable to open file:\n\"%s\"\nfor writing" $fullFileName]
set save_in_progress 0
+
+ # Again start watching for modification of this file on disk
+ FSnotifications::watch $fullFileName [list ::Editor::file_change_notif $this]
+
return 0
}
fconfigure $chanel -translation $eol -encoding $encoding
@@ -1494,6 +1593,9 @@ public method save {} {
$editor edit modified 0
set modified 0
+ # Again start watching for modification of this file on disk
+ FSnotifications::watch $fullFileName [list ::Editor::file_change_notif $this]
+
# Stop autosave timer
catch {
after cancel $autosave_timer
@@ -1501,17 +1603,174 @@ public method save {} {
}
# Change application status
- Sbar [mc "File %s saved" $fullFileName]
::X::adjust_title
set save_in_progress 0
if {$fullFileName == {}} {
return 0
- } {
+ } else {
+ if {$::MICROSOFT_WINDOWS} { ;# "/" --> "\"
+ regsub -all {/} $fullFileName "\\" fullFileName_win
+ } else {
+ set fullFileName_win $fullFileName
+ }
+ Sbar [mc "File %s saved" $fullFileName_win]
return 1
}
}
+## Set internal flag "file_change_notif_flg" to true
+ #
+ # The flag indicates that the file opened in this editor was modified on disk
+ # by another program. The flag is automatically cleared when the user is
+ # informed about the modification to the file.
+ #
+ # @return void
+public method set_file_change_notif_flg {} {
+ set file_change_notif_flg 1
+}
+
+## Check flag "file_change_notif_flg" and if set, inform the user about this.
+ #
+ # The flag file_change_notif_flg indicates that the file opened in this editor
+ # was modified on disk by another program. The flag is automatically cleared by
+ # this method. The user is informed via a dialog window giving him three
+ # options, reload the file, overwrite it on disk, and ignore it.
+ #
+ # @return void
+public method check_file_change_notif {} {
+ # Check the flag, and clear it if it was set
+ if {!$file_change_notif_flg} {
+ return
+ }
+ set file_change_notif_flg 0
+
+ # Create the dialog window
+ set dialog [toplevel .file_change_notif_dlg]
+
+ # Create top frame (dialog icon and text of the message)
+ set dlg_top_frame [frame $dialog.top_frame]
+ pack [label $dlg_top_frame.image -image ::ICONS::32::messagebox_warning] -side left -padx 5
+ pack [label $dlg_top_frame.label \
+ -justify left \
+ -text [mc "The file '%s' was modified from outside of this program.\n\nWhat do you want to do with the modified file?" [file tail $fullFileName]] \
+ ] -side left -fill x -expand 1 -padx 5
+
+ # Create bottom bar with dialog buttons
+ set button_frame [frame $dialog.button_frame]
+ pack [ttk::button $button_frame.button_reload \
+ -text [mc "Reload in editor"] \
+ -compound left \
+ -image ::ICONS::16::reload \
+ -command "
+ $parentObject filelist_reload_file $this 1
+ grab release $dialog
+ destroy $dialog
+ " \
+ ] -side left -padx 2
+ pack [ttk::button $button_frame.button_overwrt \
+ -text [mc "Overwrite on disk"] \
+ -compound left \
+ -image ::ICONS::16::filesave \
+ -command "
+ $this save
+ grab release $dialog
+ destroy $dialog
+ " \
+ ] -side left -padx 2
+ pack [ttk::button $button_frame.button_cancel \
+ -text [mc "Do nothing"] \
+ -compound left \
+ -image ::ICONS::16::cancel \
+ -command "
+ grab release $dialog
+ destroy $dialog
+ " \
+ ] -side left -padx 2
+
+ # Pack window frames
+ pack $dlg_top_frame -side top -fill x -expand 1 -padx 5 -pady 10
+ pack $button_frame -side bottom -side right -padx 5 -pady 5
+
+ bind $dialog <Escape> "
+ grab release $dialog
+ destroy $dialog
+ "
+
+ # Set dialog attributes (modal window)
+ wm iconphoto $dialog ::ICONS::16::status_unknown
+ wm title $dialog [mc "File changed on disk"]
+ wm state $dialog normal
+ wm minsize $dialog 400 110
+ wm transient $dialog .
+ wm protocol $dialog WM_DELETE_WINDOW "
+ grab release $dialog
+ destroy $dialog
+ "
+ update
+ catch {
+ grab $dialog
+ }
+ raise $dialog
+ focus -force $button_frame.button_cancel
+ tkwait window $dialog
+}
+
+## File change notification callback
+ #
+ # This function is supposed to be called by the FSnotifications component when
+ # a modification to the currently opened file was made by another program.
+ #
+ # @return void
+proc file_change_notif {editor_ref filename} {
+ # This call is invalid if there are no projects opened
+ if {![llength ${::X::openedProjects}]} {
+ return
+ }
+
+ # Attempt to find the corresponding project and editor index number
+ foreach project ${::X::openedProjects} {
+ set list_of_editors [$project cget -editors]
+ set actual_editor [$project cget -actualEditor]
+ set actual_editor2 [$project cget -actualEditor2]
+ set editor_idx [lsearch -ascii -exact $list_of_editors $editor_ref]
+
+ if {$editor_idx == -1} {
+ # Editor editor index number not found, move on to another project
+ continue
+ }
+
+ # Try to get the "frozen" flag from the editor
+ if {[catch {
+ set editor_frozen [$editor_ref get_flag_frozen]
+ }]} then {
+ # Unable to comply, that probably means that the editor
+ # does not exist any more
+ return
+ }
+
+ # Set the "file_change_notif_flg" flag
+ $project editor_procedure $editor_idx set_file_change_notif_flg {}
+
+ # Check the "file_change_notif_flg" flag right away, if the
+ #+ editor is currently visible to the user
+ if {
+ ($project == ${::X::actualProject})
+ &&
+ ($editor_idx == $actual_editor || $editor_idx == $actual_editor2)
+ } then {
+ # If the editor is in frozen state, i.e. the MCU
+ # simulator is engaged, then don't annoy with nonsense
+ # messages, and instead inform the user later.
+ if {!$editor_frozen} {
+ $project editor_procedure $editor_idx check_file_change_notif {}
+ }
+ }
+
+ break
+ }
+}
+
## Set variable 'fullFileName' for later file save (method 'save')
# note: also change editors status bar
# @parm String full_filename - the full filename (including path)
@@ -1520,6 +1779,16 @@ public method save {} {
public method set_FileName {full_filename rootName} {
if {$editor_to_use} {return}
+ # Start watching for changes in the file (on disk)
+ if {$fullFileName != {}} {
+ # Stop watching the old file
+ FSnotifications::watch forget $fullFileName
+ }
+ if {$full_filename != {}} {
+ # Start watching the new file
+ FSnotifications::watch $full_filename [list ::Editor::file_change_notif $this]
+ }
+
# set variables
set fullFileName $full_filename
set filename $rootName
@@ -1535,7 +1804,7 @@ public method getFileName {} {
return [list [file dirname $fullFileName] $filename]
}
-## Change letter case acording to the given options
+## Change letter case according to the given options
# @parm List options - list of 21 values, each must be one of {- L -U}
# '-' - keep case
# 'U' - Uppercase
@@ -1563,13 +1832,13 @@ public method change_letter_case {options} {
tag_imm_dec tag_imm_bin
tag_imm_constant tag_imm_unknown
tag_macro
- } \
+ } \
{
# Evaluate option
if {$option == {-}} {continue}
if {$option == {U}} {
set option {toupper}
- } {
+ } else {
set option {tolower}
}
@@ -1744,7 +2013,7 @@ public method copy {} {
Sbar [mc "Unable to execute: nothing selected"]
return 0
# Adjust clipboard content
- } {
+ } else {
clipboard clear
clipboard append $data
return 1
@@ -1752,11 +2021,11 @@ public method copy {} {
}
## Paste clipboard content to the text at the cursor position
- # @parm Bool = 0 - Use X selection instead of the clipboard
- # @
- # @
+ # @parm Bool use_X_sel=0 - Use X selection instead of the clipboard
+ # @parm Int x - X coordinate
+ # @parm Int y - Y coordinate
# @return bool - 1: successful; 0: failed
-public method paste args {
+public method paste {{use_X_sel 0} {x {}} {y {}}} {
if {$critical_edit_proc} {return}
set critical_edit_proc 1
@@ -1765,9 +2034,9 @@ public method paste args {
set original_cur_pos [$editor index insert]
}
- if {[lindex $args 0] == {1}} {
+ if {$use_X_sel} {
set cmd {selection}
- } {
+ } else {
set cmd {clipboard}
}
@@ -1780,9 +2049,7 @@ public method paste args {
return 0
}
- if {[lindex $args 0] == {1}} {
- set x [lindex $args 1]
- set y [lindex $args 2]
+ if {$use_X_sel} {
$editor mark set insert @$x,$y
catch {
$editor tag remove sel 0.0 end
@@ -1793,15 +2060,16 @@ public method paste args {
$editor configure -autoseparators 0
deleteselection
recalc_left_frame
- # insert data to the text, restore syntax hightlight and return 1
+ # insert data to the text, restore syntax highlight
$editor insert [$editor index insert] $data
recalc_left_frame
recalc_status_counter {}
$editor see [$editor index insert]
- update idle
+ update idletasks
set line [expr {int([$editor index insert])}]
rightPanel_adjust $line
parse $line
+ spellcheck_check_all $line 2 ;# Perform spell check for the current line
highlight_visible_area
$editor edit separator
$editor configure -autoseparators 1
@@ -1895,7 +2163,7 @@ public method cut {} {
set critical_edit_proc 0
return 0
# Cut
- } {
+ } else {
# Adjust clipboard content
deleteselection
clipboard clear
@@ -1957,8 +2225,10 @@ public method kill_childern {} {
if {$editor_to_use} {
bind $top_frame <Destroy> {}
if {!$::MICROSOFT_WINDOWS} { ;# There is no kill command on Microsoft Windows
- catch {
- exec -- kill $pid
+ if {$pid != [pid] && $pid != 0} {
+ catch {
+ exec -- kill $pid
+ }
}
}
catch {
@@ -1967,7 +2237,7 @@ public method kill_childern {} {
}
}
-## Get ID of file type (programing language used)
+## Get ID of file type (programming language used)
# @return Int - 0 == Assembly language; 1 == C language
public method get_language {} {
if {$prog_language == -1} {
@@ -1979,12 +2249,12 @@ public method get_language {} {
} else {
return 0
}
- } {
+ } else {
return $prog_language
}
}
-## Set file type (programing language used)
+## Set file type (programming language used)
# @parm Int lang - -1 == unknown; 0 == Assembly language; 1 == C language
# @return void
public method force_language {lang} {
@@ -2173,7 +2443,7 @@ public method getFileStatistics {} {
if {$found} {continue}
if {[string is wordchar -strict $char]} {
incr words_and_numbers
- } {
+ } else {
incr others
}
}
@@ -2181,7 +2451,7 @@ public method getFileStatistics {} {
# Determinate line type excluding empty lines
if {$last_words == $words && $last_keywords == $keywords && $last_comments < $comments} {
incr commented_lines
- } {
+ } else {
incr normal_lines
}
}
@@ -2200,12 +2470,22 @@ public method getFileStatistics {} {
}
## Set read only mode
- # @parm Bool mode_frag - 1 == Read only; 0 = Read and write
- # @return void
+ # @parm Bool mode_frag - 1 == Read only; 0 == Read and write
+ # @return Bool - true == ok; false == cannot comply!
public method change_RO_MODE {mode_frag} {
if {$editor_to_use} {return}
set ro_mode $mode_frag
+ if {!$ro_mode && [$parentObject cget -S_flag_read_only]} {
+ tk_messageBox \
+ -parent . \
+ -type ok \
+ -icon warning \
+ -title [mc "Read-only project"] \
+ -message [mc "This project has a special purpose, modifications to this project are not allowed."]
+ return 0
+ }
+
# Set to read only
if {$ro_mode} {
$editor configure -state disabled
@@ -2220,7 +2500,7 @@ public method change_RO_MODE {mode_frag} {
set state {disabled}
# Set to normal mode
- } {
+ } else {
$editor configure -state normal
$ins_mode_lbl configure \
-bg {#DDDDDD} \
@@ -2237,6 +2517,7 @@ public method change_RO_MODE {mode_frag} {
$menu entryconfigure [::mc $entry] -state $state
}
::X::adjust_mainmenu_and_toolbar_to_editor $ro_mode {}
+ return 1
}
## Perform program jump
@@ -2257,7 +2538,7 @@ public method ljmp_this_line {} {
set lineNum [$parentObject simulator_getCurrentLine]
if {$lineNum != {}} {
$parentObject move_simulator_line $lineNum
- } {
+ } else {
$parentObject editor_procedure {} unset_simulator_line {}
}
$parentObject Simulator_sync_PC_etc
@@ -2268,8 +2549,8 @@ public method ljmp_this_line {} {
public method lcall_this_line {} {
if {$editor_to_use} {return}
# Determinate target address
- set address [$parentObject simulator_line2address \
- [expr {int([$editor index insert])}] \
+ set address [$parentObject simulator_line2address \
+ [expr {int([$editor index insert])}] \
[$parentObject simulator_get_filenumber $fullFileName] \
]
if {$address == {}} {
@@ -2281,8 +2562,12 @@ public method lcall_this_line {} {
set lineNum [$parentObject simulator_getCurrentLine]
if {$lineNum != {}} {
$parentObject move_simulator_line $lineNum
- } {
+ } else {
$parentObject editor_procedure {} unset_simulator_line {}
}
$parentObject Simulator_sync_PC_etc
-} \ No newline at end of file
+}
+
+# >>> File inclusion guard
+}
+# <<< File inclusion guard