proc split.string.every {s n} {
set r [list]
set sLen [string length $s]
for {set i 0} {$i < $sLen} {incr i $n} {
lappend r [string range $s $i [expr {$i + $n - 1}]]
}
return $r
}
set ::wrapLen 20
proc newline.wrapping.text.instance {win args} {
set subCmd [lindex $args 0]
if {"insert" == $subCmd} {
set i [_$win index [lindex $args 1]]
set charCount [lindex [split $i "."] 1]
set txt [lindex $args 2]
if {([string length $txt] + $charCount) > $::wrapLen} {
set segEnd [expr {$::wrapLen - $charCount}]
uplevel [list _$win insert $i [string range $txt 0 $segEnd]\n]
foreach s [split.string.every \
[string range $txt [expr {$segEnd + 1}] end] $::wrapLen] {
uplevel [list _$win insert end $s\n]
}
} else {
uplevel [linsert $args 0 _$win]
}
} else {
uplevel [linsert $args 0 _$win]
}
}
proc newline.wrapping.text {win args} {
text $win
rename $win _$win
interp alias {} $win {} newline.wrapping.text.instance $win
$win insert end "This is a long line that should wrap into multiple lines."
return $win
}
pack [newline.wrapping.text .t]More advanced wrapping is left as an exercise for the reader.GPS answered a different question in c.l.t: how does one calculate the number of displayed lines in a text widget, as distinguished from the number of logical (\n-separated) lines:
set start [.t index @0,0]
set end [.t index @0,[winfo height .t]]
expr $end - $start + 1 ...This returns the number of logical (\n-separated) lines currently displayed, which is not the same as the number of display lines on screen (which is very hard to calculate if font sizes differ). But, with tip 155:expr [.t count -displaylines @0,0 @0,[winfo height .t]] + 1does the job.

