#
# Module for file I/O for Text widgets
#


# Writes contents of w out to descriptor f.
proc th_Text_write_file {w f} {puts -nonewline $f [$w get 1.0 "end -1c"]}

# Changes w to contain contents of file descriptor f.
proc th_Text_read_file {w f {gradual 0}} {
  $w delete 1.0 end
  if $gradual {
    th_Text_gradual_read $w $f [$w index insert]
  } else {
    $w insert insert [read $f]}
  $w mark set insert 1.0
  $w see 1.0
}

# Inserts contents of f at insert in w.
proc th_Text_insert_file {w f {gradual 0}} {
  global auto_index
  $w mark set file_start insert
  set i [$w index insert]
  if $gradual {
    th_Text_gradual_read $w $f [$w index insert]
  } else {
    $w insert insert [read $f]}
  if {([info procs th_Text_undoable_replace] != "") &&
     ([lsearch [array names auto_index] th_Text_undoable_replace] >= 0)} {
    th_Text_undoable_replace $w $i insert "" "Insert file"}
  $w mark set insert $i
  $w see insert
  $w mark unset file_start
}


# fills text widget w with contents from "$file", which must be opened for
# reading. Does not clear text widget. Uses non-blocking 'fileevent' cmd so
# user can watch while f loads.
proc th_Text_gradual_read {w f index} {
  # Enable user to interrupt with a Cancel binding.
  global TH

  set binding [th_bind $w Cancel]
  th_bind $w Cancel "bell ; exec kill -9 [pid $f]"
  $w mark set new_stuff $index
  set TH(Gradual,Done,$w) 0
  fileevent $f readable "th_Text_fileevent_read $w $f"
  tkwait variable TH(Gradual,Done,$w)
  $w mark unset new_stuff
  th_bind $w Cancel $binding
}

# Called whenever file f becomes readable.
proc th_Text_fileevent_read {w f} {
# Turn off file-events, until we finish inserting the line.
  fileevent $f readable ""

  if {![eof $f]} { set result [gets $f line] } else {$w delete new_stuff-1c}
  global TH
  if {($result < 0) || [eof $f]} {
    set TH(Gradual,Done,$w) 1
    return
  }
  $w insert new_stuff "$line\n"
  if {[$w compare insert == new_stuff]} { $w see insert }

# Turn back on file events, now that we're done updating the display.
  fileevent $f readable "th_Text_fileevent_read $w $f"
}

# Maintains the insert and view at the same points while executing cmd.
proc th_Text_save_view {w cmd} {
  set view [$w index @0,0]
  set insert [$w index insert]
  eval $cmd
  scan $view "%d.%d" y x ; incr y -1
  $w yview moveto 0 ; $w xview moveto 0
  $w yview scroll $y units ; $w xview scroll $x units
  $w mark set insert $insert
}
