cwg-dated-1027805573.3ce2ae@DeepEddy.Com said:
> I just checked in a code cleanup which doesn't address this issue,
> but does  take a machete to code right around it.  You ought to 'cvs
> update' and see if  your issue becomes any clearer with all the
> brush removed.
> My patch notes that 'msgid' and 'line' are redundant with one
> another and removes  one or the other from functions which takes
> both.  The callers are then  changed to pass what the function
> expects.  In the case of Msg_Change, the  'line' argument is removed
> and we only have the msgid argument.  Ftoc_ClearCurrent is now the
> first line of MsgChange.
The following patch removes Ftoc_RescanLine in favour of a
Ftoc_RescanLines. It runs scan(1) on a list of lines and updates ftoc
accordingly. The patch also changes all the callers to make use of it.
It also changes Ftoc_ClearCurrent to work of an argument instead of
falsily clearing a message that's still Current on disk. All in an
effort to get a one-to-one disk-display correspondence.
It does add ~30 -- ~ 75 ms (~<10%) to the execution time depending on
folder size due to the invocation of scan. However this version does
not try to second guess the mh version of scan so if you have exotic
scanlines it tells the truth. As a side effect the '+' sign now
corresponds better to what's on disk.
Comments appreciated. I'm going to be offlike for a couple of days,
so I send the cvs diff rather than putting it in the cvs.
/Anders

@@ -558,7 +558,7 @@ proc FtocPickRange { {addcurrent 0} } {
# Ftoc_ClearCurrent and Ftoc_Change are two parts of
# dinking the ftoc display when advancing a message.
+# Make line no longer appear as the currently selected line
-	set ftoc(curLine) [Mh_Cur $ftoc(folder)]
-	$exwin(ftext) tag remove cur $ftoc(curLine).0 $ftoc(curLine).end
-proc Ftoc_Change { line {show show} } {
+#We dont need this any more since we work off the line
+#      set ftoc(curLine) [Mh_Cur $ftoc(folder)]
+#      $exwin(ftext) tag remove cur $ftoc(curLine).0 $ftoc(curLine).end
+     #should check that 0<$line<last line and error otherwise
+     $exwin(ftext) tag remove cur $line.0 $line.end
+# Make newline the currently selected line
+# optionally clear oldline from such attribution
+proc Ftoc_Change { newline {oldline {}}} {
+    if {![info exists oldline] || ($oldline==$newline)} {
$exwin(ftext) tag remove unseen $ftoc(curLine).0 $ftoc(curLine).end
+	    $exwin(ftext) tag remove cur $oldline.0 $oldline.end
+	    Ftoc_RescanLines [list $ftoc(curLine) $oldline]
$exwin(ftext) tag add cur $ftoc(curLine).0 $ftoc(curLine).end
if [catch {expr {$top+1}}] {set top 0}	;# trap 100.-1 format, iconic
-proc Ftoc_RescanLine { ix {plus none} } {
+# This one is not used any more. Kept here for reference
+proc Ftoc_RescanLine_old { ix {plus none} } {
set text [$exwin(ftext) get ${ix}.0 ${ix}.end]
@@ -737,6 +765,57 @@ proc Ftoc_RescanLine { ix {plus none} }
+# Rescans a set of lines and updates the ftoc as needed
+# lines_in: list of line numbers. Ranges (e.g. 200-210) are not allowed
+    Exmh_Debug Ftoc_RescanLines [ time {
+       #Sort the lines and weed out duplicates.
+       #They creep in when we change folders
+       #foreach newCandidate [lsort -integer $lines_in] {
+       #    if {$newCandidate != $lastCandidate} {
+       #       lappend lines $newCandidate
+       #       set lastCandidate $newCandidate
+       #Never mind dupechecking. The only potential is checked for in
+       #Ftoc_Change and the above takes time (~8 ms)
+        set lines [lsort -integer $lines_in]
+           lappend msgnos [Ftoc_MsgNumber $line]
+       set input [open "|$mhProfile(scan-proc) \
+       set texts [split [string trim [read $input] \n ] \n ]
+       for {set i 0} {$i<$ll} {incr i} {
+           set tags [$exwin(ftext) tag names $line.0]
+           $exwin(ftext) configure -state normal
+           $exwin(ftext) delete $line.0 $line.end
+           $exwin(ftext) insert $line.0 [lindex $texts $i]
+	   $exwin(ftext) configure -state disabled
+               $exwin(ftext) tag add $tag $line.0 $line.end
proc Ftoc_NextImplied { {show show} {implied implied} } {
if {$ftoc(implied) && $ftoc(direction) == "prev"} {
@@ -793,7 +872,7 @@ proc Ftoc_NextFolder { {implied no} } {
# If on last message, clear display because the
@@ -809,7 +888,7 @@ proc Ftoc_NextFolder { {implied no} } {
Exmh_Status "End of folder; <Next> => $f" warn
@@ -1113,7 +1192,7 @@ proc FtocCommit {tagname commitProc {cop
@@ -73,10 +73,20 @@ proc Msg_ShowUnseen { {show show} } {
+    # Are there cases where this is not true?
+    if {$ftoc(folder) == $exmh(folder)} {
+        set prevline [Ftoc_FindMsg [Mh_Cur $ftoc(folder)]]
set msg(id) {}		;# Clear current message
set msg(dpy) {}		;# and currently displayed message
@@ -117,13 +127,13 @@ proc Msg_Change {msgid {show show} } {
Exmh_Debug Msg_Change [time [list MsgChange $msgid $show]]
+    global exmh exwin msg mhProfile ftoc
+    set prevline [Ftoc_FindMsg [Mh_Cur $ftoc(folder)]]
+    if {! [Ftoc_Change $line $prevline]} {
-	set curLine [Ftoc_ClearCurrent]			;# Clear +
+	Ftoc_ClearCurrent $ftoc(curLine)        ;# Clear +
set scancmd "exec $mhProfile(scan-proc) [list +$folder] \
-width $ftoc(scanWidth) > [list $cacheFile]"
Exmh_Status "failed to rescan folder $folder: $err" warn
+	Ftoc_Change $ftoc(curline)              ;# Restore it
set display [$exwin(ftext) get 1.0 "end -1 char"]