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.