#!/usr/bin/wish

# tkwho - shows who is on logged onto the system 
# A simple tk who program to use with session management.
# GPL'd by Alen Peacock, 1998

# Set window title
wm title . "tkwho v0.7" 


# Create a frame
frame .top -borderwidth 2 -background lightgrey -relief raised  
pack .top -side top -fill x

label .top.lab -bg lightgrey -text "TkWho 0.7, Alen Peacock, Initializing..." 
pack .top.lab 

font create HevFont -family Helvetica -size 12
font create HevFontBold -family Helvetica -size 12 -weight bold

# Create a text widget to log the output
frame .t -borderwidth 2 -background lightgrey -relief raised 
scrollbar .t.scroll -bg lightgrey -orient vertical -command [list .t.list yview]
set log [listbox .t.list -yscrollcommand [list .t.scroll set] \
        -bg lightgrey -exportselection false -selectmode extended -width 41 \
        -height 5 -relief flat -font HevFont]
#pack .t.scroll -side right -fill y
pack .t.list -side left -expand 1 -fill both
pack .t -side top -fill both -expand true 

bind .t.list <ButtonPress-3> {user_info %y %X %Y}
bind .t.list <ButtonRelease-3> {user_info_release}
bind .t.list <ButtonPress-1> {user_process %y %X %Y}
bind .t.list <ButtonRelease-1> {user_process_release}
bind .t.list <Motion> {user_motion %y %X %Y}
bind .t.list <Leave> {user_leave}

bind . <Destroy> Exit 

# Run the program and arrange to read its input
proc Run {} {
  global input log YView commandDone
  set commandDone 0
  set YView [lindex [split [.t.list yview]] 0]  ;# save the scroll position 
                                                 # before clearing
  $log delete 0 end
  set input [exec who -i 2>@ stderr] 
  gotCommand $input
}

proc gotCommand {input} {
  global log YView 
  set lines [split $input "\n"]
  foreach {line} $lines {
    regsub -all " +" $line " " line2
    set users [split $line2]
    append entry " " [lindex $users 0] " on since " [lindex $users 2] " "
    append entry [lindex $users 3] " at " [lindex $users 4]
    if [regexp ":" [lindex $users 5]] {
      append entry ", idle for " [lindex $users 5] "."
    } else {
      append entry ", active"
    }
    $log insert end $entry
    if {[llength $users] > 1} {
      .top.lab configure -text "The following users are currently logged on"
      .top.lab configure -foreground red
    }
    set entry ""
  }
  # check to see if list is empty
  if {[.t.list size] < 1} {
    .top.lab configure -text "No users currently logged in"
    .top.lab configure -foreground black
  }
  # check to see if list needs a scrollbar
  if {[$log index @[winfo width .t],[winfo height .t]] < \
          [expr [.t.list size] - 1]} {
    pack .t.scroll -side right -fill y        ;# add scrollbar
    .t.list yview moveto $YView               ;# restore scroll position
  } else {
    pack forget .t.scroll                     ;# remove scrollbar
  }
  
}

# Exit
proc Exit {} {
  global input x
  set x 1
  exit
}

proc user_process {y X Y} {
  user_leave

  set index [.t.list nearest $y]
  set str [.t.list get $index]
  set userline [split $str]
  set username [lindex $userline 1]
  set ps [exec ps auc | grep $username 2>@ stderr]

  if {![winfo exists .user_popup]} {
    set itemindex [.t.list nearest $y]
    set itembbox [.t.list bbox $itemindex]
    if {[lindex $itembbox 1] != "" && [lindex $itembbox 3] != ""} {
      set itemy [expr [lindex $itembbox 1] + [lindex $itembbox 3]] 
      if {$itemy > $y} {
        general_popup "Processes owned by $username" $ps $X $Y
      }
    }
  }
}

proc user_process_release {} {
  if {[winfo exists .user_popup]} {
    destroy .user_popup
  }
}

proc user_info {y X Y} {
  user_leave
  
  set index [.t.list nearest $y]
  set str [.t.list get $index]
  set userline [split $str]
  set username [lindex $userline 1]

  set finger [exec finger $username 2>@ stderr] 

  if {![winfo exists .user_popup]} {
    set itemindex [.t.list nearest $y]
    set itembbox [.t.list bbox $itemindex]
    if {[lindex $itembbox 1] != "" && [lindex $itembbox 3] != ""} {
      set itemy [expr [lindex $itembbox 1] + [lindex $itembbox 3]] 
      if {$itemy > $y} {
        general_popup "Information on $username" $finger $X $Y
      }
    }
  }
}

proc user_info_release {} {
  if {[winfo exists .user_popup]} {
    destroy .user_popup
  }
}

proc general_popup {title text X Y} {

  set w .user_popup 
  toplevel $w -border 1 -relief solid -background lightgray 
  wm overrideredirect .user_popup 1
  label $w.title -text $title -anchor nw -justify center -font HevFontBold
  label $w.info -text $text -anchor sw -justify left -font HevFont 
  grid $w.title
  grid $w.info
  
  wm geometry $w +$X+$Y
  
  update idletasks
  set width [winfo reqwidth $w]
  set height [winfo reqheight $w]
  set screenwidth [winfo screenwidth $w]
  set screenheight [winfo screenheight $w]

  if {$X < 0} {
    set X 0
  } elseif {[expr $X + $width] > $screenwidth} {
    set X [expr $screenwidth - $width]
  }
  if {[expr $Y + $height] > $screenheight} {
    set Y [expr $screenheight - $height]
  }

  wm geometry $w +$X+$Y
}
  

proc user_motion {y X Y} {
  user_leave
  if {![winfo exists .user_popup]} {
    set itemindex [.t.list nearest $y]
    set itembbox [.t.list bbox $itemindex]
    if {[lindex $itembbox 1] != "" && [lindex $itembbox 3] != ""} {
      set itemy [expr [lindex $itembbox 1] + [lindex $itembbox 3]] 
      if {$itemy > $y} {
        user_popup $y $X $Y
      }
    }
  }
}

proc user_popup {y X Y} {
  
  after 500

  set popup "left or right mouse button for more info"

  set w .user_enter_popup 
  toplevel $w -border 1 -relief solid -background lightgray 
  wm overrideredirect .user_enter_popup 1

  label $w.info -text $popup -anchor sw -justify left -background #ffffcc 
  grid $w.info

  set width 250
  set height 20 
  set screenwidth [winfo screenwidth $w]
  set screenheight [winfo screenheight $w]

  if {$X < 0} {
    set X 0
  } elseif {[expr $X + $width] > $screenwidth} {
    set X [expr $X - $width]
  }
  if {[expr $Y + $height + 20] > $screenheight} {
    set Y [expr $screenheight - $height - 20]
  }

  wm geometry $w +[expr $X + 5]+[expr $Y + 20]
}

proc user_leave {} {
  if {[winfo exists .user_enter_popup]} {
    destroy .user_enter_popup
  }
}

proc bgerror {message} {
  puts -nonewline "caught bgerror: " 
  puts $message
  Exit
}

set centering [lindex $argv 0]
if {[string compare $centering "-center"] == 0} {
  set wwidth 300
  set swidth [winfo screenwidth .]
  set xoffset [expr [expr $swidth / 2] - [expr $wwidth / 2]]
  append geom1 "+" $xoffset "-2"
  wm geometry . $geom1
  update
  set geom [wm geometry .]
  regsub -all "x" $geom " " geom2
  regsub -all "\[\+\]|\[\-\]" $geom2 " " geom3 
  set geoms [split $geom3]
  set wwidth [lindex $geoms 0]
  puts $wwidth
  set swidth [winfo screenwidth .]
  set xoffset [expr [expr $swidth / 2] - [expr $wwidth / 2]]
  append newgeom "+" $xoffset "-2" 
  wm geometry . $newgeom 
}
#wm deiconify .
update
set x 0
set pastUsers 0
while ($x==0) {
  after 100
  update 
  if ($x==0) {
    Run
  }
}

