diff options
Diffstat (limited to 'git-gui/lib')
-rw-r--r-- | git-gui/lib/about.tcl | 6 | ||||
-rw-r--r-- | git-gui/lib/blame.tcl | 25 | ||||
-rw-r--r-- | git-gui/lib/browser.tcl | 3 | ||||
-rw-r--r-- | git-gui/lib/checkout_op.tcl | 6 | ||||
-rw-r--r-- | git-gui/lib/choose_font.tcl | 2 | ||||
-rw-r--r-- | git-gui/lib/choose_repository.tcl | 2 | ||||
-rw-r--r-- | git-gui/lib/commit.tcl | 16 | ||||
-rw-r--r-- | git-gui/lib/console.tcl | 10 | ||||
-rw-r--r-- | git-gui/lib/error.tcl | 4 | ||||
-rw-r--r-- | git-gui/lib/index.tcl | 2 | ||||
-rw-r--r-- | git-gui/lib/merge.tcl | 5 | ||||
-rw-r--r-- | git-gui/lib/option.tcl | 40 | ||||
-rw-r--r-- | git-gui/lib/spellcheck.tcl | 408 |
13 files changed, 503 insertions, 26 deletions
diff --git a/git-gui/lib/about.tcl b/git-gui/lib/about.tcl index 719fc547b3..241ab892cd 100644 --- a/git-gui/lib/about.tcl +++ b/git-gui/lib/about.tcl @@ -4,6 +4,7 @@ proc do_about {} { global appvers copyright oguilib global tcl_patchLevel tk_patchLevel + global ui_comm_spell set w .about_dialog toplevel $w @@ -40,6 +41,11 @@ proc do_about {} { append v "Tcl version $tcl_patchLevel" append v ", Tk version $tk_patchLevel" } + if {[info exists ui_comm_spell] + && [$ui_comm_spell version] ne {}} { + append v "\n" + append v [$ui_comm_spell version] + } set d {} append d "git wrapper: $::_git\n" diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl index 00ecf21333..92fac1bad4 100644 --- a/git-gui/lib/blame.tcl +++ b/git-gui/lib/blame.tcl @@ -80,6 +80,7 @@ constructor new {i_commit i_path} { label $w.header.commit_l \ -text [mc "Commit:"] \ -background gold \ + -foreground black \ -anchor w \ -justify left set w_back $w.header.commit_b @@ -89,6 +90,7 @@ constructor new {i_commit i_path} { -relief flat \ -state disabled \ -background gold \ + -foreground black \ -activebackground gold bind $w_back <Button-1> " if {\[$w_back cget -state\] eq {normal}} { @@ -98,16 +100,19 @@ constructor new {i_commit i_path} { label $w.header.commit \ -textvariable @commit \ -background gold \ + -foreground black \ -anchor w \ -justify left label $w.header.path_l \ -text [mc "File:"] \ -background gold \ + -foreground black \ -anchor w \ -justify left set w_path $w.header.path label $w_path \ -background gold \ + -foreground black \ -anchor w \ -justify left pack $w.header.commit_l -side left @@ -135,7 +140,9 @@ constructor new {i_commit i_path} { -takefocus 0 \ -highlightthickness 0 \ -padx 0 -pady 0 \ - -background white -borderwidth 0 \ + -background white \ + -foreground black \ + -borderwidth 0 \ -state disabled \ -wrap none \ -height 40 \ @@ -148,7 +155,9 @@ constructor new {i_commit i_path} { -takefocus 0 \ -highlightthickness 0 \ -padx 0 -pady 0 \ - -background white -borderwidth 0 \ + -background white \ + -foreground black \ + -borderwidth 0 \ -state disabled \ -wrap none \ -height 40 \ @@ -166,7 +175,9 @@ constructor new {i_commit i_path} { -takefocus 0 \ -highlightthickness 0 \ -padx 0 -pady 0 \ - -background white -borderwidth 0 \ + -background white \ + -foreground black \ + -borderwidth 0 \ -state disabled \ -wrap none \ -height 40 \ @@ -184,7 +195,9 @@ constructor new {i_commit i_path} { -takefocus 0 \ -highlightthickness 0 \ -padx 0 -pady 0 \ - -background white -borderwidth 0 \ + -background white \ + -foreground black \ + -borderwidth 0 \ -state disabled \ -wrap none \ -height 40 \ @@ -213,7 +226,9 @@ constructor new {i_commit i_path} { set w_cviewer $w.file_pane.cm.t text $w_cviewer \ - -background white -borderwidth 0 \ + -background white \ + -foreground black \ + -borderwidth 0 \ -state disabled \ -wrap none \ -height 10 \ diff --git a/git-gui/lib/browser.tcl b/git-gui/lib/browser.tcl index 53d5a62816..ab470d1264 100644 --- a/git-gui/lib/browser.tcl +++ b/git-gui/lib/browser.tcl @@ -39,7 +39,8 @@ constructor new {commit {path {}}} { frame $w.list set w_list $w.list.l - text $w_list -background white -borderwidth 0 \ + text $w_list -background white -foreground black \ + -borderwidth 0 \ -cursor $cursor_ptr \ -state disabled \ -wrap none \ diff --git a/git-gui/lib/checkout_op.tcl b/git-gui/lib/checkout_op.tcl index f243966924..6e1411711b 100644 --- a/git-gui/lib/checkout_op.tcl +++ b/git-gui/lib/checkout_op.tcl @@ -280,7 +280,7 @@ The rescan will be automatically started now. } elseif {[is_config_true gui.trustmtime]} { _readtree $this } else { - ui_status {Refreshing file status...} + ui_status [mc "Refreshing file status..."] set fd [git_read update-index \ -q \ --unmerged \ @@ -320,7 +320,7 @@ method _readtree {} { set readtree_d {} $::main_status start \ [mc "Updating working directory to '%s'..." [_name $this]] \ - {files checked out} + [mc "files checked out"] set fd [git_read --stderr read-tree \ -m \ @@ -447,7 +447,7 @@ If you wanted to be on a branch, create one now starting from 'This Detached Che } else { repository_state commit_type HEAD MERGE_HEAD set PARENT $HEAD - ui_status "Checked out '$name'." + ui_status [mc "Checked out '%s'." $name] } delete_this } diff --git a/git-gui/lib/choose_font.tcl b/git-gui/lib/choose_font.tcl index 0c4051b375..56443b042c 100644 --- a/git-gui/lib/choose_font.tcl +++ b/git-gui/lib/choose_font.tcl @@ -55,6 +55,7 @@ constructor pick {path title a_family a_size} { set w_family $w.inner.family.v text $w_family \ -background white \ + -foreground black \ -borderwidth 1 \ -relief sunken \ -cursor $::cursor_ptr \ @@ -92,6 +93,7 @@ constructor pick {path title a_family a_size} { set w_example $w.example.t text $w_example \ -background white \ + -foreground black \ -borderwidth 1 \ -relief sunken \ -height 3 \ diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl index 0adcf9d958..ae4a4cd0a8 100644 --- a/git-gui/lib/choose_repository.tcl +++ b/git-gui/lib/choose_repository.tcl @@ -38,7 +38,7 @@ constructor pick {} { menu $m_repo if {[is_MacOSX]} { - $w.mbar add cascade -label [mc Apple] -menu .mbar.apple + $w.mbar add cascade -label Apple -menu .mbar.apple menu $w.mbar.apple $w.mbar.apple add command \ -label [mc "About %s" [appname]] \ diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl index 947b201c32..40a7103557 100644 --- a/git-gui/lib/commit.tcl +++ b/git-gui/lib/commit.tcl @@ -218,7 +218,7 @@ A good commit message has the following format: return } - ui_status {Calling pre-commit hook...} + ui_status [mc "Calling pre-commit hook..."] set pch_error {} fconfigure $fd_ph -blocking 0 -translation binary -eofchar {} fileevent $fd_ph readable \ @@ -233,7 +233,7 @@ proc commit_prehook_wait {fd_ph curHEAD msg_p} { if {[eof $fd_ph]} { if {[catch {close $fd_ph}]} { catch {file delete $msg_p} - ui_status {Commit declined by pre-commit hook.} + ui_status [mc "Commit declined by pre-commit hook."] hook_failed_popup pre-commit $pch_error unlock_index } else { @@ -256,7 +256,7 @@ proc commit_commitmsg {curHEAD msg_p} { return } - ui_status {Calling commit-msg hook...} + ui_status [mc "Calling commit-msg hook..."] set pch_error {} fconfigure $fd_ph -blocking 0 -translation binary -eofchar {} fileevent $fd_ph readable \ @@ -271,7 +271,7 @@ proc commit_commitmsg_wait {fd_ph curHEAD msg_p} { if {[eof $fd_ph]} { if {[catch {close $fd_ph}]} { catch {file delete $msg_p} - ui_status {Commit declined by commit-msg hook.} + ui_status [mc "Commit declined by commit-msg hook."] hook_failed_popup commit-msg $pch_error unlock_index } else { @@ -284,7 +284,7 @@ proc commit_commitmsg_wait {fd_ph curHEAD msg_p} { } proc commit_writetree {curHEAD msg_p} { - ui_status {Committing changes...} + ui_status [mc "Committing changes..."] set fd_wt [git_read write-tree] fileevent $fd_wt readable \ [list commit_committree $fd_wt $curHEAD $msg_p] @@ -301,7 +301,7 @@ proc commit_committree {fd_wt curHEAD msg_p} { if {[catch {close $fd_wt} err]} { catch {file delete $msg_p} error_popup [strcat [mc "write-tree failed:"] "\n\n$err"] - ui_status {Commit failed.} + ui_status [mc "Commit failed."] unlock_index return } @@ -345,7 +345,7 @@ A rescan will be automatically started now. if {[catch {set cmt_id [eval git $cmd]} err]} { catch {file delete $msg_p} error_popup [strcat [mc "commit-tree failed:"] "\n\n$err"] - ui_status {Commit failed.} + ui_status [mc "Commit failed."] unlock_index return } @@ -365,7 +365,7 @@ A rescan will be automatically started now. } err]} { catch {file delete $msg_p} error_popup [strcat [mc "update-ref failed:"] "\n\n$err"] - ui_status {Commit failed.} + ui_status [mc "Commit failed."] unlock_index return } diff --git a/git-gui/lib/console.tcl b/git-gui/lib/console.tcl index 5597188d80..c112464ec3 100644 --- a/git-gui/lib/console.tcl +++ b/git-gui/lib/console.tcl @@ -46,7 +46,9 @@ method _init {} { -justify left \ -font font_uibold text $w_t \ - -background white -borderwidth 1 \ + -background white \ + -foreground black \ + -borderwidth 1 \ -relief sunken \ -width 80 -height 10 \ -wrap none \ @@ -180,7 +182,8 @@ method done {ok} { if {$ok} { if {[winfo exists $w.m.s]} { bind $w.m.s <Destroy> [list delete_this $this] - $w.m.s conf -background green -text [mc "Success"] + $w.m.s conf -background green -foreground black \ + -text [mc "Success"] if {$is_toplevel} { $w.ok conf -state normal focus $w.ok @@ -193,7 +196,8 @@ method done {ok} { _init $this } bind $w.m.s <Destroy> [list delete_this $this] - $w.m.s conf -background red -text [mc "Error: Command Failed"] + $w.m.s conf -background red -foreground black \ + -text [mc "Error: Command Failed"] if {$is_toplevel} { $w.ok conf -state normal focus $w.ok diff --git a/git-gui/lib/error.tcl b/git-gui/lib/error.tcl index 8c27678e3a..75650157e5 100644 --- a/git-gui/lib/error.tcl +++ b/git-gui/lib/error.tcl @@ -80,7 +80,9 @@ proc hook_failed_popup {hook msg {is_fatal 1}} { -justify left \ -font font_uibold text $w.m.t \ - -background white -borderwidth 1 \ + -background white \ + -foreground black \ + -borderwidth 1 \ -relief sunken \ -width 80 -height 10 \ -font font_diff \ diff --git a/git-gui/lib/index.tcl b/git-gui/lib/index.tcl index 30a244cc17..3c1fce7475 100644 --- a/git-gui/lib/index.tcl +++ b/git-gui/lib/index.tcl @@ -310,7 +310,7 @@ proc add_helper {txt paths} { update_index \ $txt \ $pathList \ - [concat $after {ui_status {Ready to commit.}}] + [concat $after {ui_status [mc "Ready to commit."]}] } } diff --git a/git-gui/lib/merge.tcl b/git-gui/lib/merge.tcl index 63e14279c1..cc26b07808 100644 --- a/git-gui/lib/merge.tcl +++ b/git-gui/lib/merge.tcl @@ -116,8 +116,7 @@ method _start {} { lappend cmd HEAD lappend cmd $name - set msg [mc "Merging %s and %s" $current_branch $stitle] - ui_status "$msg..." + ui_status [mc "Merging %s and %s..." $current_branch $stitle] set cons [console::new [mc "Merge"] "merge $stitle"] console::exec $cons $cmd [cb _finish $cons] @@ -236,7 +235,7 @@ Continue with resetting the current changes?"] set fd [git_read --stderr read-tree --reset -u -v HEAD] fconfigure $fd -blocking 0 -translation binary fileevent $fd readable [namespace code [list _reset_wait $fd]] - $::main_status start [mc "Aborting"] {files reset} + $::main_status start [mc "Aborting"] [mc "files reset"] } else { unlock_index } diff --git a/git-gui/lib/option.tcl b/git-gui/lib/option.tcl index f812e5e89a..9270512582 100644 --- a/git-gui/lib/option.tcl +++ b/git-gui/lib/option.tcl @@ -5,6 +5,7 @@ proc save_config {} { global default_config font_descs global repo_config global_config global repo_config_new global_config_new + global ui_comm_spell foreach option $font_descs { set name [lindex $option 0] @@ -52,11 +53,23 @@ proc save_config {} { set repo_config($name) $value } } + + if {[info exists repo_config(gui.spellingdictionary)]} { + set value $repo_config(gui.spellingdictionary) + if {$value eq {none}} { + if {[info exists ui_comm_spell]} { + $ui_comm_spell stop + } + } elseif {[info exists ui_comm_spell]} { + $ui_comm_spell lang $value + } + } } proc do_options {} { global repo_config global_config font_descs global repo_config_new global_config_new + global ui_comm_spell array unset repo_config_new array unset global_config_new @@ -111,6 +124,7 @@ proc do_options {} { {b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}} {b gui.matchtrackingbranch {mc "Match Tracking Branches"}} {i-0..99 gui.diffcontext {mc "Number of Diff Context Lines"}} + {i-0..99 gui.commitmsgwidth {mc "Commit Message Text Width"}} {t gui.newbranchtemplate {mc "New Branch Name Template"}} } { set type [lindex $option 0] @@ -159,6 +173,32 @@ proc do_options {} { } } + set all_dicts [linsert \ + [spellcheck::available_langs] \ + 0 \ + none] + incr optid + foreach f {repo global} { + if {![info exists ${f}_config_new(gui.spellingdictionary)]} { + if {[info exists ui_comm_spell]} { + set value [$ui_comm_spell lang] + } else { + set value none + } + set ${f}_config_new(gui.spellingdictionary) $value + } + + frame $w.$f.$optid + label $w.$f.$optid.l -text [mc "Spelling Dictionary:"] + eval tk_optionMenu $w.$f.$optid.v \ + ${f}_config_new(gui.spellingdictionary) \ + $all_dicts + pack $w.$f.$optid.l -side left -anchor w -fill x + pack $w.$f.$optid.v -side right -anchor e -padx 5 + pack $w.$f.$optid -side top -anchor w -fill x + } + unset all_dicts + set all_fonts [lsort [font families]] foreach option $font_descs { set name [lindex $option 0] diff --git a/git-gui/lib/spellcheck.tcl b/git-gui/lib/spellcheck.tcl new file mode 100644 index 0000000000..9be748683c --- /dev/null +++ b/git-gui/lib/spellcheck.tcl @@ -0,0 +1,408 @@ +# git-gui spellchecking support through ispell/aspell +# Copyright (C) 2008 Shawn Pearce + +class spellcheck { + +field s_fd {} ; # pipe to ispell/aspell +field s_version {} ; # ispell/aspell version string +field s_lang {} ; # current language code +field s_prog aspell; # are we actually old ispell? +field s_failed 0 ; # is $s_prog bogus and not working? + +field w_text ; # text widget we are spelling +field w_menu ; # context menu for the widget +field s_menuidx 0 ; # last index of insertion into $w_menu + +field s_i {} ; # timer registration for _run callbacks +field s_clear 0 ; # did we erase mispelled tags yet? +field s_seen [list] ; # lines last seen from $w_text in _run +field s_checked [list] ; # lines already checked +field s_pending [list] ; # [$line $data] sent to ispell/aspell +field s_suggest ; # array, list of suggestions, keyed by misspelling + +constructor init {pipe_fd ui_text ui_menu} { + set w_text $ui_text + set w_menu $ui_menu + array unset s_suggest + + bind_button3 $w_text [cb _popup_suggest %X %Y @%x,%y] + _connect $this $pipe_fd + return $this +} + +method _connect {pipe_fd} { + fconfigure $pipe_fd \ + -encoding utf-8 \ + -eofchar {} \ + -translation lf + + if {[gets $pipe_fd s_version] <= 0} { + if {[catch {close $pipe_fd} err]} { + + # Eh? Is this actually ispell choking on aspell options? + # + if {$s_prog eq {aspell} + && [regexp -nocase {^Usage: } $err] + && ![catch { + set pipe_fd [open [list | $s_prog -v] r] + gets $pipe_fd s_version + close $pipe_fd + }] + && $s_version ne {}} { + if {{@(#) } eq [string range $s_version 0 4]} { + set s_version [string range $s_version 5 end] + } + set s_failed 1 + error_popup [strcat \ + [mc "Unsupported spell checker"] \ + ":\n\n$s_version"] + set s_version {} + return + } + + regsub -nocase {^Error: } $err {} err + if {$s_fd eq {}} { + error_popup [strcat [mc "Spell checking is unavailable"] ":\n\n$err"] + } else { + error_popup [strcat \ + [mc "Invalid spell checking configuration"] \ + ":\n\n$err\n\n" \ + [mc "Reverting dictionary to %s." $s_lang]] + } + } else { + error_popup [mc "Spell checker silently failed on startup"] + } + return + } + + if {{@(#) } ne [string range $s_version 0 4]} { + catch {close $pipe_fd} + error_popup [strcat [mc "Unrecognized spell checker"] ":\n\n$s_version"] + return + } + set s_version [string range $s_version 5 end] + regexp \ + {International Ispell Version .* \(but really (Aspell .*?)\)$} \ + $s_version _junk s_version + + puts $pipe_fd ! ; # enable terse mode + puts $pipe_fd {$$cr master} ; # fetch the language + flush $pipe_fd + + gets $pipe_fd s_lang + regexp {[/\\]([^/\\]+)\.[^\.]+$} $s_lang _ s_lang + + if {$::default_config(gui.spellingdictionary) eq {} + && [get_config gui.spellingdictionary] eq {}} { + set ::default_config(gui.spellingdictionary) $s_lang + } + + if {$s_fd ne {}} { + catch {close $s_fd} + } + set s_fd $pipe_fd + + fconfigure $s_fd -blocking 0 + fileevent $s_fd readable [cb _read] + + $w_text tag conf misspelled \ + -foreground red \ + -underline 1 + + array unset s_suggest + set s_seen [list] + set s_checked [list] + set s_pending [list] + _run $this +} + +method lang {{n {}}} { + if {$n ne {} && $s_lang ne $n && !$s_failed} { + set spell_cmd [list |] + lappend spell_cmd aspell + lappend spell_cmd --master=$n + lappend spell_cmd --mode=none + lappend spell_cmd --encoding=UTF-8 + lappend spell_cmd pipe + _connect $this [open $spell_cmd r+] + } + return $s_lang +} + +method version {} { + if {$s_version ne {}} { + return "$s_version, $s_lang" + } + return {} +} + +method stop {} { + while {$s_menuidx > 0} { + $w_menu delete 0 + incr s_menuidx -1 + } + $w_text tag delete misspelled + + catch {close $s_fd} + catch {after cancel $s_i} + set s_fd {} + set s_i {} + set s_lang {} +} + +method _popup_suggest {X Y pos} { + while {$s_menuidx > 0} { + $w_menu delete 0 + incr s_menuidx -1 + } + + set b_loc [$w_text index "$pos wordstart"] + set e_loc [_wordend $this $b_loc] + set orig [$w_text get $b_loc $e_loc] + set tags [$w_text tag names $b_loc] + + if {[lsearch -exact $tags misspelled] >= 0} { + if {[info exists s_suggest($orig)]} { + set cnt 0 + foreach s $s_suggest($orig) { + if {$cnt < 5} { + $w_menu insert $s_menuidx command \ + -label $s \ + -command [cb _replace $b_loc $e_loc $s] + incr s_menuidx + incr cnt + } else { + break + } + } + } else { + $w_menu insert $s_menuidx command \ + -label [mc "No Suggestions"] \ + -state disabled + incr s_menuidx + } + $w_menu insert $s_menuidx separator + incr s_menuidx + } + + $w_text mark set saved-insert insert + tk_popup $w_menu $X $Y +} + +method _replace {b_loc e_loc word} { + $w_text configure -autoseparators 0 + $w_text edit separator + + $w_text delete $b_loc $e_loc + $w_text insert $b_loc $word + + $w_text edit separator + $w_text configure -autoseparators 1 + $w_text mark set insert saved-insert +} + +method _restart_timer {} { + set s_i [after 300 [cb _run]] +} + +proc _match_length {max_line arr_name} { + upvar $arr_name a + + if {[llength $a] > $max_line} { + set a [lrange $a 0 $max_line] + } + while {[llength $a] <= $max_line} { + lappend a {} + } +} + +method _wordend {pos} { + set pos [$w_text index "$pos wordend"] + set tags [$w_text tag names $pos] + while {[lsearch -exact $tags misspelled] >= 0} { + set pos [$w_text index "$pos +1c"] + set tags [$w_text tag names $pos] + } + return $pos +} + +method _run {} { + set cur_pos [$w_text index {insert -1c}] + set cur_line [lindex [split $cur_pos .] 0] + set max_line [lindex [split [$w_text index end] .] 0] + _match_length $max_line s_seen + _match_length $max_line s_checked + + # Nothing in the message buffer? Nothing to spellcheck. + # + if {$cur_line == 1 + && $max_line == 2 + && [$w_text get 1.0 end] eq "\n"} { + array unset s_suggest + _restart_timer $this + return + } + + set active 0 + for {set n 1} {$n <= $max_line} {incr n} { + set s [$w_text get "$n.0" "$n.end"] + + # Don't spellcheck the current line unless we are at + # a word boundary. The user might be typing on it. + # + if {$n == $cur_line + && ![regexp {^\W$} [$w_text get $cur_pos insert]]} { + + # If the current word is mispelled remove the tag + # but force a spellcheck later. + # + set tags [$w_text tag names $cur_pos] + if {[lsearch -exact $tags misspelled] >= 0} { + $w_text tag remove misspelled \ + "$cur_pos wordstart" \ + [_wordend $this $cur_pos] + lset s_seen $n $s + lset s_checked $n {} + } + + continue + } + + if {[lindex $s_seen $n] eq $s + && [lindex $s_checked $n] ne $s} { + # Don't send empty lines to Aspell it doesn't check them. + # + if {$s eq {}} { + lset s_checked $n $s + continue + } + + # Don't send typical s-b-o lines as the emails are + # almost always misspelled according to Aspell. + # + if {[regexp -nocase {^[a-z-]+-by:.*<.*@.*>$} $s]} { + $w_text tag remove misspelled "$n.0" "$n.end" + lset s_checked $n $s + continue + } + + puts $s_fd ^$s + lappend s_pending [list $n $s] + set active 1 + } else { + # Delay until another idle loop to make sure we don't + # spellcheck lines the user is actively changing. + # + lset s_seen $n $s + } + } + + if {$active} { + set s_clear 1 + flush $s_fd + } else { + _restart_timer $this + } +} + +method _read {} { + while {[gets $s_fd line] >= 0} { + set lineno [lindex $s_pending 0 0] + + if {$s_clear} { + $w_text tag remove misspelled "$lineno.0" "$lineno.end" + set s_clear 0 + } + + if {$line eq {}} { + lset s_checked $lineno [lindex $s_pending 0 1] + set s_pending [lrange $s_pending 1 end] + set s_clear 1 + continue + } + + set sugg [list] + switch -- [string range $line 0 1] { + {& } { + set line [split [string range $line 2 end] :] + set info [split [lindex $line 0] { }] + set orig [lindex $info 0] + set offs [lindex $info 2] + foreach s [split [lindex $line 1] ,] { + lappend sugg [string range $s 1 end] + } + } + {# } { + set info [split [string range $line 2 end] { }] + set orig [lindex $info 0] + set offs [lindex $info 1] + } + default { + puts stderr "<spell> $line" + continue + } + } + + incr offs -1 + set b_loc "$lineno.$offs" + set e_loc [$w_text index "$lineno.$offs wordend"] + set curr [$w_text get $b_loc $e_loc] + + # At least for English curr = "bob", orig = "bob's" + # so Tk didn't include the 's but Aspell did. We + # try to round out the word. + # + while {$curr ne $orig + && [string equal -length [string length $curr] $curr $orig]} { + set n_loc [$w_text index "$e_loc +1c"] + set n_curr [$w_text get $b_loc $n_loc] + if {$n_curr eq $curr} { + break + } + set curr $n_curr + set e_loc $n_loc + } + + if {$curr eq $orig} { + $w_text tag add misspelled $b_loc $e_loc + if {[llength $sugg] > 0} { + set s_suggest($orig) $sugg + } else { + unset -nocomplain s_suggest($orig) + } + } else { + unset -nocomplain s_suggest($orig) + } + } + + fconfigure $s_fd -block 1 + if {[eof $s_fd]} { + if {![catch {close $s_fd} err]} { + set err [mc "Unexpected EOF from spell checker"] + } + catch {after cancel $s_i} + $w_text tag remove misspelled 1.0 end + error_popup [strcat [mc "Spell Checker Failed"] "\n\n" $err] + return + } + fconfigure $s_fd -block 0 + + if {[llength $s_pending] == 0} { + _restart_timer $this + } +} + +proc available_langs {} { + set langs [list] + catch { + set fd [open [list | aspell dump dicts] r] + while {[gets $fd line] >= 0} { + if {$line eq {}} continue + lappend langs $line + } + close $fd + } + return $langs +} + +} |