# Version von mkCmd/mkCmd_wait mit Tcl und fileevent (Block-In, Block-Out)
#
# Copyright (C) 2004  G. Lamprecht, W. Lotz, R. Weibezahn; IWD, Bremen University



####### call programs in foreground, catching output, providing input, waiting for eof #######

proc mkCmd_wait {w c a}  { # starts a command and waits for it's termination
  global vv end_mkCmd bindkeysenab WTB
  TestPut 4 "<$w><$c><$a>"

  if {[catch "which $c"]>0} {# program not found
    writescr $w "\n\n$vv(xtq01)\n*** $vv(ut56): \"$c\"\n$vv(xtq01)\n"; mybell 4; return
  }

  writescr $w "\n$c [join $a]\n\n"
  .a.2.a configure -state normal;   $w configure -state normal
  mkCmd $w $c $a;  tkwait variable end_mkCmd
  if {($bindkeysenab==1)&&($w==".d.tt")} {set cmdxkb CmdXKB} {set cmdxkb ""}
  bindtags $w "CmdXNo CmdX$w $cmdxkb $WTB([AlphNum CmdXNo$w]) . all"; # restore bindings
  focus $w
  .a.2.a configure -state disabled; configureStateDisabled $w; update
}

proc mkCmd_f {} {
  global  window_mkCmd f_mkCmd p_mkCmd end_mkCmd

  if {[eof $f_mkCmd]} {
    set p_mkCmd 1
    set end_mkCmd "end"
    catch "close  $f_mkCmd" m
    bind  $window_mkCmd  <Any-Key> { }
    return
  }
  set c [read $f_mkCmd]
  set  i  [$window_mkCmd  index insert]
  $window_mkCmd  insert insert "$c"
  $window_mkCmd  tag remove end $i insert
  $window_mkCmd  yview -pickplace insert
  update
}

proc mkCmd {w c a} {# startet Kommando, wartet nicht auf Ende
  global  focus_mkCmd end_mkCmd window_mkCmd xtem_path
  global  fid_mkCmd buf_mkCmd f_mkCmd p_mkCmd

# bindings

  set  buf_mkCmd ""
  set  end_mkCmd "start"

# only own bindings during command (=program) execution; 
# will be rest in mkCmd_wait after program termination!
  bindtags  $w  [list $w]

  bind  $w  <Control-Key-c>  {
    set  i  [%W  index insert]
    %W  insert  insert  " INT "
    %W  tag add end $i insert
    %W  insert insert "\n"
    %W  yview -pickplace insert
    catch "exec kill -s SIGINT $p_mkCmd"
    set p_mkCmd 1
    set end_mkCmd "end"
    catch "close  $f_mkCmd"
    bind  $window_mkCmd  <Any-Key> { }
  }
  bind  $w  <Control-Key-d>  {
    set  i  [%W  index insert]
    %W  insert insert " EOF "
    %W  tag add end $i insert
    %W  insert insert "\n"
    %W  yview -pickplace insert
    catch "flush  $f_mkCmd"
    set p_mkCmd 1
    set end_mkCmd "end"
    catch "close  $f_mkCmd"
    bind  $window_mkCmd  <Any-Key> { }
  }
  bind  $w  <BackSpace>  {
    set  n  [string length  $buf_mkCmd]
    if  {$n > 0}  then  {
      %W  delete "insert - 1 chars"
      %W  yview -pickplace insert
      set r [expr $n-2]
      if {"[string range $buf_mkCmd [expr $n-1] end]"== "\\"} {incr r -1}
      set  buf_mkCmd [string  range $buf_mkCmd 0 $r]
    } 
  }
  bind  $w  <Return>  {
    set  i  [%W  index insert]
    %W  insert  insert  "\n"
    %W  yview -pickplace insert
    catch  "puts $i_mkCmd \"$buf_mkCmd\""
    catch  "flush  $i_mkCmd"
    set  buf_mkCmd  ""
  }
  bind  $w  <Key>  {
    set A %A
    if {($A=="")||($A=="\x7f")} break
    set  i  [%W  index insert]
    %W  insert  insert  "$A"
    %W  tag remove err $i insert
    %W  tag remove end $i insert
    %W yview -pickplace insert
    append buf_mkCmd $A; if {$A=="\\"} {append buf_mkCmd $A}
  }
  bind $w <Button-1> "[bind Text <B1-Motion>]; %W mark set insert end"
  bind $w <B1-Motion> "[bind Text <B1-Motion>]"
  bind $w <ButtonRelease-2> {  # differs from /usr/local/lib/tk4.1/text.tc
    catch {puts $i_mkCmd "[selection get -selection PRIMARY]"};
    catch {%W insert end [selection get -selection PRIMARY]};
    %W mark set insert end
    %W yview -pickplace end
  }

  set  focus_mkCmd [focus];  focus $w

  set f_mkCmd [open "| $c $a |& cat" RDWR]
                                                   TestPut 4 "Channel $f_mkCmd"; #####@@@@@
  fileevent $f_mkCmd readable mkCmd_f
  fconfigure $f_mkCmd -blocking 0
  set p_mkCmd [pid $f_mkCmd]
                                                   TestPut 4 "PID: $p_mkCmd"; #####@@@@@

  global i_mkCmd; set i_mkCmd $f_mkCmd; # needed for uniform bindings in mkcommand74ff.b

  set window_mkCmd $w

  return
}

proc killprocess {pid}  {foreach p $pid {catch "exec kill 9 $p"} }
