#!/bin/sh
# please alter the name and/or path of
# the wish shell below, if it doesn't work \
exec wish8.4 "$0" "$@"

## tpad version 1.2
# WinXP (TM) Notepad clone written in Tcl/Tk
# requires at least Tk 8.4
#
# Please report any bug found to the author.
#
# author: Antonio Bonifati <http://go.to/ninuzzo>
# distributed under GNU GPL
## last revised on: $Date: 2004/01/30 22:00 $

# load a configuration file (required)
if {[file exists ~/.tpadrc]} {
  source ~/.tpadrc
} else {
  source /etc/tpad.conf
}

## service commands
# enable/disable edit menu commands based on selection and clipboard state
proc SetState {menu} {
  global tpad_edit

  if { [selection own] != {.text} || [catch {selection get}] } {
    $menu entryconfigure Copy -state disabled
    if {$tpad_edit} {
      $menu entryconfigure Cut -state disabled
      $menu entryconfigure Delete -state disabled
    }
  } else {
    $menu entryconfigure Copy -state normal
    if {$tpad_edit} {
      $menu entryconfigure Cut -state normal
      $menu entryconfigure Delete -state normal
    }
  }

  if {$tpad_edit} {
    if { [catch {selection get -selection CLIPBOARD}] } {
      $menu entryconfigure Paste -state disabled
    } else {
      $menu entryconfigure Paste -state normal
    }
  }
}

# called every time the modified flag changes state
# sets the title bar and
# enables the undo/redo command if modified becomes true
proc Modified {} {
  global tpad tpad_filename tpad_edit

  if {$tpad_filename=={}} {
    set filename Untitled
  } else {
    set filename $tpad_filename
  }
  set title tpad:$filename
  if {$tpad_edit} {
    if { [.text edit modified] } {
      append title *
      .statusBar.modified configure -text Modified
      .menubar.edit entryconfigure Undo -state normal
      .rightmenu entryconfigure Undo -state normal
      if {$tpad(maxundo)!=1} {
        .menubar.edit entryconfigure Redo -state normal
        .rightmenu entryconfigure Redo -state normal
      }
    } else {
      .statusBar.modified configure -text {}
    }
  }
  wm title . $title
  .statusBar.filename configure -text $filename
}

# sets the current name of the file to edit
# (use an empty string if not defined yet)
proc SetFilename {newFilename} {
  global tpad_filename

  set tpad_filename $newFilename
}

# clears the undo/redo stacks
# sets text as not modified and disables the undo/redo command
# sets the insertion cursor at the beginning of the text
proc Clear {} {
  global tpad tpad_edit

  .text edit modified no
  .text edit reset
  if {$tpad_edit} {
    .menubar.edit entryconfigure Undo -state disabled
    .rightmenu entryconfigure Undo -state disabled
    if {$tpad(maxundo)!=1} {
      .menubar.edit entryconfigure Redo -state disabled
      .rightmenu entryconfigure Redo -state disabled
    }
  }
  .text mark set insert 1.0
  UpdateStatusBar
}

# clears the undo/redo stacks
# sets text as modified and disables the undo/redo command
# sets the insertion cursor at the end of the text
proc Append {} {
  global tpad tpad_edit

  .text edit reset
  if {$tpad_edit} {
    .text edit modified yes
    .menubar.edit entryconfigure Undo -state disabled
    .rightmenu entryconfigure Undo -state disabled
    if {$tpad(maxundo)!=1} {
      .menubar.edit entryconfigure Redo -state disabled
      .rightmenu entryconfigure Redo -state disabled
    }
  } else {
    .text edit modified no
  }
  .text see end
  UpdateStatusBar
}

# arranges for a new text to be edited
proc NewFile {{newFilename {}}} {
  global tpad_edit

  SetFilename $newFilename
  .text configure -state normal ;# added to support -R option
  .text delete 1.0 end ;# clears the text
  Clear
  if {!$tpad_edit} {
    .text configure -state disabled
  }
}

# opens the file if it can and arranges for it to be
# edited for the first time otherwise acts as NewFile
# also implements a log file facility Notepad has
proc OpenFile {newFilename} {
  global tpad_filename tpad tpad_edit

  if { [catch {open $newFilename} fileid] } {
    if {!$tpad_edit} {
      tk_messageBox -title tpad -icon error -message $fileid -type ok
      New
    } elseif { [tk_messageBox -title tpad -type yesno -message "$fileid

Create as new?" -icon error]=={yes} } {
      NewFile $newFilename
    }
  } else {
    .text configure -state normal ;# added to support -R option

    SetFilename $newFilename
    .text delete 1.0 end

    gets $fileid firstline
    .text insert 1.0 "$firstline\n"
    .text insert insert [read $fileid]
    if {[.text get {insert - 1 char}]=="\n"} {
      .text delete {insert - 1 char}
    }
    close $fileid

    if {$tpad(logfac) && $firstline=={.LOG}} {
      if {$tpad_edit} {
        .text insert insert "\n\n"
        InsertDate
        .text insert insert "\n"
      }

      Append
    } else {
      Clear
    }

    if {!$tpad_edit} {
      .text configure -state disabled
    }
  }
}

# save the editing so far done
# without clearing the undo/redo stacks
# also don't include the dummy last line of the text
proc SaveFile {} {
  global tpad_filename

  set fileid [open $tpad_filename w]
  puts $fileid [.text get 1.0 {end - 1 char}]
  close $fileid
  .text edit modified no
}

# provides the user with a last change to save his changes
proc OkToContinue {} {
  if { [.text edit modified] } {
    switch [tk_messageBox -type yesnocancel -message {File modified.

Do you wish to save your changes?} -icon warning -title tpad] {
      yes {return [Save]}

      no {return yes}

      cancel {return no}
    }
  }
  return yes
}

# find the next occurrence of the pattern in the text
# tipically starting from the position of the insertion cursor
proc FindPattern {} {
  global tpad_pattern tpad_dir tpad_case

  # convert option names and compute search start point
  switch $tpad_dir {
    up {
      set dir -backwards
      if { [catch {.text index {sel.first - 1 char}} start] } {
        set start insert
      }
      set stop 1.0
    }

    down {
      set dir -forwards
      set start insert
      set stop end
    }
  }
  switch $tpad_case no {set case -nocase} yes {set case -exact}

  if {[set matchIdx [.text search $dir $case -count len -- \
       $tpad_pattern $start $stop]]!={}} {
    set last [.text index "$matchIdx + $len chars"]
    .text tag remove sel 1.0 end
    .text tag add sel $matchIdx $last
    .text mark set insert $last
    .text see $last
    .text see $matchIdx
    UpdateStatusBar
  } else {
    tk_messageBox -icon info -title tpad \
      -message "Cannot find \"$tpad_pattern\""
  }
}

# gives focus to an entry field
# selects all its contents
# and positions the insertion cursor at the end
proc EntryFocus {entry} {
  focus $entry
  $entry selection range 0 end
  $entry icursor end
}

# returns the line number corresponding to index
proc LineNo {index} {
  return [lindex [split [.text index $index] .] 0]

}

# returns the total number of lines in the text
proc Lines {} {
  return [LineNo {end - 1 char}]
}

# if num is a valid line number in the text
# sets the insertion cursor to the beginning
# of the the line numbered num and adjusts the view
proc GoToLine {num} {
  set lines [Lines]
  set num [string trim $num]

  if {[string is integer -strict $num] && $num>=1 && $num<=$lines} {
    .text mark set insert $num.0
    .text see $num.0
    UpdateStatusBar
    return yes
  } else {
    tk_messageBox -title {tpad. Goto line} -type ok -icon error \
      -message "Illegal line number `$num'\nMust be from 1 to $lines"
    return no
  }
}

proc UpdateStatusBar {} {
  set coords [split [.text index insert] .]
  set row [lindex $coords 0]
  set col [expr [lindex $coords 1] + 1]

  .statusBar.coords configure -text $row,$col
  .statusBar.lines configure -text [Lines]
}

proc DuplicateSelection {args} {
  .text tag remove dupsel 1.0 end

  if {![catch {.text index sel.first}]} {
    eval .text tag add dupsel [.text tag ranges sel]
  }
}

proc UpdateOffset {first last} {
  .vscroll set $first $last
  .statusBar.fraction configure \
    -text [expr round($first*100)]-[expr round($last*100)]%
}

proc WhatIs {} {
  global tpad

  return "tpad Version $tpad(version)
WinXP Notepad clone"
}

proc CmdHelp {} {
  puts "
[WhatIs]

usage: tpad \[-Rh\] \[+#\] \[file ...\]
"
}
## end of service commands

## editor commands
proc New {} {
   if {[OkToContinue]} {
     NewFile
   }
}

# arranges for editing the next file in sequence
# if there's one, otherwise simply disables the Next option
proc Next {} {
  global argv argc tpad_next

  if {$tpad_next<$argc} {
    if {[OkToContinue]} {
      set file [file normalize [lindex $argv $tpad_next]]
      OpenFile $file
      if {[incr tpad_next]==$argc} {
        # disable the Next option in advance
        .menubar.file entryconfigure Next -state disabled
      }
      if {![file writable $file]} {
        .statusBar.modified configure -text Readonly
      }
    }
  } else {
    .menubar.file entryconfigure Next -state disabled
  }
}

proc Open {} {
  if {[OkToContinue]} {
    global tpad

    set newFilename [tk_getOpenFile -title {Open - tpad} \
      -filetypes $tpad(types)]

    if {$newFilename != {}} {
      OpenFile $newFilename
    }
  }
}

# if a filename has been defined acts as SaveFile
# and always returns yes
# (except doing nothing if the text hasn't been modified from last save)
# if no filename has been defined acts as SaveAs
proc Save {} {
  global tpad_filename

  if {$tpad_filename!={}} {
    if { [.text edit modified] } {
      SaveFile
    }
    return yes
  } else {
    return [SaveAs]
  }
}

# save the text on a file with a new name
# returns yes if the user has chosen to save
# no if the user has cancelled the operation
proc SaveAs {} {
  global tpad

  set newFilename [tk_getSaveFile -title {Save As - tpad} \
    -initialfile Untitled -filetypes $tpad(types)]

  if {$newFilename != {}} {
    SetFilename $newFilename
    SaveFile
    return yes
  }
  return no
}

# opens the modal Print setup dialog box
proc PrintSetup {} {
  global tpad
 
  toplevel .prn
  wm group .prn .
  wm title .prn {Print setup}  
  wm resizable .prn no no
  wm transient .prn .
  grab .prn 

  frame .prn.what
  label .prn.what.label -text {Print command} -width 14 -anchor w -underline 0
  entry .prn.what.entry -fg $tpad(fg) -bg $tpad(bg)
  .prn.what.entry delete 0 end
  .prn.what.entry insert 0 $tpad(lpr)
  pack .prn.what.label .prn.what.entry -side left

  frame .prn.but
  button .prn.but.ok -text OK -width 8 -underline 0 -command {
    set tpad(lpr) [.prn.what.entry get]
    .prn.but.cancel invoke
  }
  button .prn.but.cancel -text Cancel -width 8 -underline 0 -command {
    focus .text
    after idle {destroy .prn}
  }

  pack .prn.but.ok -padx {0 30} -side left
  pack .prn.but.cancel

  pack .prn.what .prn.but -padx 10 -pady 12 -anchor w

  bind .prn <Alt-Key-p> {EntryFocus .prn.what.entry}
  bind .prn <Alt-Key-o> {.prn.but.ok invoke}
  bind .prn <Key-Return> {.prn.but.ok invoke}
  bind .prn <Alt-Key-c> {.prn.but.cancel invoke}
  bind .prn <Key-Escape> {.prn.but.cancel invoke}

  ::tk::PlaceWindow .prn widget .
  EntryFocus .prn.what.entry
}

# print the text edited so far
# piping it into lpr(1) or similar
proc Print {} {
  global tpad

  set pipeid [open "|$tpad(lpr)" w]
  puts -nonewline $pipeid [.text get 1.0 end]
  close $pipeid
}

# quit from from the application
proc Quit {} {
  if {[OkToContinue]} {
    global argc tpad_next

    if {[set files [expr $argc - $tpad_next]]>0} {
      switch [tk_messageBox -icon question -title tpad -type yesnocancel \
                -message "$files more files to edit.

Do you wish to load the next file in sequence?"] {
        yes {
	  Next
	  return
        }

        no {exit}

        cancel {return}
      }
    }

    exit
  }
}

# one level undo/redo
proc UndoRedo {} {
  if { [catch {.text edit undo}] } {
    catch {.text edit redo}
  }
  UpdateStatusBar
}

proc Undo {} {
  event generate .text <Control-Key-z>
}

proc Redo {} {
  event generate .text <Control-Key-r>
}

proc Cut {} {
  event generate .text <Control-Key-x>
}

proc Copy {} {
  event generate .text <<Copy>>
}

proc Paste {} {
  event generate .text <Control-Key-v>
}

proc Delete {} {
  event generate .text <Key-Delete>
}

proc SelectAll {} {
  event generate .text <Control-Key-slash>
}

# insert locale specific date and time
# just before the insertion cursor
proc InsertDate {} {
  global tpad
  .text insert [.text index insert] [clock format [clock seconds] \
    -format $tpad(timefmt)]
  UpdateStatusBar
}

proc ToggleWordWrap {} {
  global tpad_wrap

  .text configure -wrap $tpad_wrap
  if {$tpad_wrap != {none}} {
    grid remove .hscroll
  } else {
    grid .hscroll
  }
}

proc ToggleStatusBar {} {
  global tpad_status

  if {$tpad_status} {
    grid .statusBar
  } else {
    grid remove .statusBar
  }
}

# opens the find dialog box
# if it isn't already opened
proc Find {} {
  global tpad tpad_pattern

  if { [info commands .find]!={} } {
    wm deiconify .find
    raise .find
  } else {
    toplevel .find
    wm group .find .
    wm title .find Find
    wm resizable .find no no
    wm transient .find .

    frame .find.but
    button .find.but.find -text {Find Next} -underline 5 -command {
      set tpad_pattern [.find.what.entry get]
      FindPattern
    }
    button .find.but.cancel -text Cancel -underline 0 -command {
      focus .text
      after idle {destroy .find}
    }
    pack .find.but.find .find.but.cancel -fill x -pady {0 3}

    frame .find.what
    label .find.what.label -text Find: -width 8 -anchor w -underline 0
    entry .find.what.entry -width 26 -fg $tpad(fg) -bg $tpad(bg) \
      -validate all -validatecommand {
        if {{%P}=={{}}} {
          .find.but.find configure -state disabled
        } else {
          .find.but.find configure -state normal
        }
        return yes
      }
    .find.what.entry delete 0 end
    .find.what.entry insert 0 $tpad_pattern
    pack .find.what.label .find.what.entry -side left

    checkbutton .find.checkbut -text {Match case} -underline 0 \
      -variable tpad_case -onvalue yes -offvalue no

    labelframe .find.dir -text Direction
    radiobutton .find.dir.up -text Up -underline 0 -variable tpad_dir -value up
    radiobutton .find.dir.down -text Down -underline 0 \
      -variable tpad_dir -value down
    pack .find.dir.up .find.dir.down -side left

    grid .find.what -row 0 -column 0 -columnspan 2 -sticky n -padx 5 -pady 10
    grid .find.checkbut -row 1 -column 0 -sticky s -pady 10
    grid .find.dir -row 1 -column 1 -pady 10
    grid .find.but -row 0 -column 2 -rowspan 2 -sticky n -padx 5 -pady 6

    bind .find <Alt-Key-m> {.find.checkbut toggle}
    bind .find <Alt-Key-u> {.find.dir.up invoke}
    bind .find <Alt-Key-d> {.find.dir.down invoke}
    bind .find <Alt-Key-f> {EntryFocus .find.what.entry}
    bind .find <Alt-Key-n> {.find.but.find invoke}
    bind .find <Key-Return> {.find.but.find invoke}
    bind .find <Alt-Key-c> {.find.but.cancel invoke}
    bind .find <Key-Escape> {.find.but.cancel invoke}

    ::tk::PlaceWindow .find widget .
  }

  EntryFocus .find.what.entry
}

# find the next pattern
# if the pattern is empty (not defined)
# or the Find window is opened, invoke Find instead
proc FindNext {} {
  global tpad_pattern

  if {[info commands .find]!={} || $tpad_pattern=={}} {
    Find
    return
  }
  FindPattern
}

# opens the modal Goto line dialog box
proc GoTo {} {
  global tpad

  toplevel .goto
  wm group .goto .
  wm title .goto {Goto line}
  wm resizable .goto no no
  wm transient .goto .
  grab .goto

  frame .goto.where
  label .goto.where.label -text {Line number} -width 12 -anchor w -underline 0
  spinbox .goto.where.spin -width 11 -fg $tpad(fg) -bg $tpad(bg) \
    -from 1 -to [Lines] -validate key -validatecommand {string is integer %P}
  .goto.where.spin set [LineNo [.text index insert]]
  pack .goto.where.label .goto.where.spin -side left

  frame .goto.but
  button .goto.but.go -text Go -width 8 -underline 0 -command {
    if {[GoToLine [.goto.where.spin get]]} {
      .goto.but.cancel invoke
    } else {
      .goto.where.spin set [LineNo [.text index insert]]
      EntryFocus .goto.where.spin
    }
  }
  button .goto.but.cancel -text Cancel -width 8 -underline 0 -command {
    focus .text
    after idle {destroy .goto}
  }
  pack .goto.but.go -padx {0 30} -side left
  pack .goto.but.cancel

  pack .goto.where .goto.but -padx 10 -pady 12 -anchor w

  bind .goto <Alt-Key-l> {EntryFocus .goto.where.spin}
  bind .goto <Alt-Key-g> {.goto.but.go invoke}
  bind .goto <Key-Return> {.goto.but.go invoke}
  bind .goto <Alt-Key-c> {.goto.but.cancel invoke}
  bind .goto <Key-Escape> {.goto.but.cancel invoke}

  ::tk::PlaceWindow .goto widget .
  EntryFocus .goto.where.spin
}

proc Help {} {
  global tpad
  eval exec $tpad(browsercmd) $tpad(helpath)/index.html &
}

proc About {} {
  tk_messageBox -title About -message "[WhatIs]

by Antonio Bonifati
ant@venus.deis.unical.it"
}
## end of editor commands

## display application
proc Display {} {
  global tpad argv0 argv tpad_edit

  tk_setPalette $tpad(palette)

  # sets window manager options
  wm title . tpad:Untitled
  wm iconname . tpad
  wm command . [concat $argv0 $argv]
  wm group . .
  # catch the kill of the window manager
  wm protocol . WM_DELETE_WINDOW Quit
  # end of window manager options

  # builds the menus
  menu .menubar
  .menubar add cascade -menu .menubar.file -label File -underline 0
  .menubar add cascade -menu .menubar.edit -label Edit -underline 0
  .menubar add cascade -menu .menubar.format -label Format -underline 1
  .menubar add cascade -menu .menubar.view -label View -underline 0
  .menubar add cascade -menu .menubar.help -label Help -underline 0

  menu .menubar.file -tearoff $tpad(tearoff)
  if {$tpad_edit} {
    .menubar.file add command -label New -underline 0 \
      -accelerator Ctrl+N -command New
  } else {
    .menubar.file add command -label Clear -underline 0 \
      -accelerator Ctrl+N -command New
  }
  .menubar.file add command -label Next -underline 2 -command Next
  .menubar.file add command -label Open... \
    -accelerator Ctrl+F12 -underline 0 -command Open
  if {$tpad_edit} {
    .menubar.file add command -label Save \
      -accelerator Shift+F12 -underline 0 -command Save
    .menubar.file add command -label {Save as...} -underline 2 -command SaveAs
  }
  .menubar.file add separator
  .menubar.file add command -label {Print setup...} -underline 1 \
    -command PrintSetup
  .menubar.file add command -label Print -underline 0 \
    -accelerator Ctrl+Shift+F12 -command Print
  .menubar.file add separator
  .menubar.file add command -label Quit -underline 0 -command Quit

  menu .menubar.edit -tearoff $tpad(tearoff) \
    -postcommand {SetState .menubar.edit}
  if {$tpad_edit} {
    if {$tpad(maxundo)!=1} {
      .menubar.edit add command -label Undo \
        -accelerator Ctrl+Z -underline 0 -command Undo -state disabled
      .menubar.edit add command -label Redo \
        -accelerator Ctrl+R -underline 0 -command Redo -state disabled
    } else {
      .menubar.edit add command -label Undo \
        -accelerator Ctrl+Z -underline 0 -command UndoRedo -state disabled
    }
    .menubar.edit add separator
    .menubar.edit add command -label Cut \
      -accelerator Ctrl+X -underline 0 -command Cut
  }
  .menubar.edit add command -label Copy \
    -accelerator Ctrl+C -underline 1 -command Copy
  if {$tpad_edit} {
    .menubar.edit add command -label Paste \
      -accelerator Ctrl+V -underline 0 -command Paste
    .menubar.edit add command -label Delete \
      -accelerator Del -underline 0 -command Delete
  }
  .menubar.edit add separator
  .menubar.edit add command -label Find... -underline 0 -command Find
  .menubar.edit add command -label {Find next} \
    -accelerator F3 -underline 5 -command FindNext
  .menubar.edit add command -label {Goto line...} \
    -accelerator Ctrl+G -underline 0 -command GoTo
  .menubar.edit add separator
  .menubar.edit add command -label {Select all} -underline 0 \
    -accelerator Ctrl+5(kp) -command SelectAll
  if {$tpad_edit} {
    .menubar.edit add command -label Date/time \
      -accelerator F5 -underline 5 -command InsertDate
  }

  menu .menubar.format -tearoff $tpad(tearoff)
  .menubar.format add checkbutton -variable tpad_wrap -onvalue word \
    -offvalue none -label {Word wrap} -underline 0 -command ToggleWordWrap

  menu .menubar.view -tearoff $tpad(tearoff)
  .menubar.view add checkbutton -variable tpad_status -onvalue yes \
    -offvalue no -label {Status bar} -underline 0 -command ToggleStatusBar

  menu .menubar.help -tearoff $tpad(tearoff)
  .menubar.help add command -label Help... -underline 0 -command Help
  .menubar.help add command -label About... -underline 0 -command About

  menu .rightmenu -tearoff $tpad(tearoff) -postcommand {SetState .rightmenu}
  if {$tpad_edit} {
    if {$tpad(maxundo)!=1} {
      .rightmenu add command -label Undo \
        -underline 0 -command Undo -state disabled
      .rightmenu add command -label Redo \
        -underline 0 -command Redo -state disabled
    } else {
      .rightmenu add command -label Undo -underline 0 \
        -command UndoRedo -state disabled
    }
    .rightmenu add separator
    .rightmenu add command -label Cut -underline 0 -command Cut
  }
  .rightmenu add command -label Copy -underline 1 -command Copy
  if {$tpad_edit} {
    .rightmenu add command -label Paste -underline 0 -command Paste
    .rightmenu add command -label Delete -underline 0 -command Delete
  }
  .rightmenu add separator
  .rightmenu add command -label {Select all} -underline 0 -command SelectAll
  # end of menus' definition

  # define the widgets
  text .text -font $tpad(editfont) -fg $tpad(fg) -bg $tpad(bg) \
    -wrap none -setgrid yes -undo yes -maxundo $tpad(maxundo) \
    -insertofftime $tpad(insertofftime) -insertontime $tpad(insertontime) \
    -yscrollcommand UpdateOffset -xscrollcommand {.hscroll set}
  .text tag configure sel -foreground $tpad(selfg) -background $tpad(selbg)
  .text tag configure dupsel -foreground $tpad(selfg) -background $tpad(selbg)
  scrollbar .vscroll -command {.text yview}
  scrollbar .hscroll -command {.text xview} -orient horizontal
  frame .statusBar -pady 2
  label .statusBar.filename -text Untitled \
    -anchor w -borderwidth 1 -font $tpad(statusfont)
  label .statusBar.modified -relief sunken \
    -width 8 -borderwidth 1 -font $tpad(statusfont)
  label .statusBar.lines -relief sunken \
    -width 6 -borderwidth 1 -font $tpad(statusfont)
  label .statusBar.fraction -relief sunken \
    -width 8 -borderwidth 1 -font $tpad(statusfont)
  label .statusBar.coords -relief sunken \
    -width 8 -borderwidth 1 -font $tpad(statusfont)
  pack .statusBar.filename -side left -expand yes -fill x -padx 2
  pack .statusBar.modified .statusBar.lines .statusBar.fraction \
    .statusBar.coords -side left -padx 2
  # end of widgets' definition

  # install or disable X event handlers
  bindtags .text {Text .text . all}
  bind . <Control-Key-n> New
  bind Text <Control-Key-n> {}
  bind . <Control-Key-F12> Open
  bind . <Control-Shift-Key-F12> Print
  catch {bind . <Control-Shift-Key-XF86_Switch_VT_12> Print}
  catch {bind .text <Control-Key-KP_Begin> SelectAll}
  bind .text <Control-Key-Clear> SelectAll
  bind .text <Control-Key-g> GoTo
  bind .text <Key-F3> FindNext
  bind .text <<Modified>> Modified
  bind .text <KeyRelease> UpdateStatusBar
  bind .text <ButtonRelease> UpdateStatusBar
  bind .text <KeyPress> UpdateStatusBar
  bind .text <ButtonPress> UpdateStatusBar
  bind .text <ButtonPress-3> {tk_popup .rightmenu %X %Y}
  bind .text <<Selection>> DuplicateSelection
  if {$tpad_edit} {
    bind . <Shift-Key-F12> Save
    catch {bind . <Shift-Key-XF86_Switch_VT_12> Save}
    bind .text <Key-F5> InsertDate
    if {$tpad(maxundo)!=1} {
      event add <<Redo>> <Control-Key-r>
    } else {
      bind .text <<Undo>> UndoRedo
      bind Text <<Undo>> {}
    }
    bind Text <Control-Key-v> {}
  }
  # end of handlers' definition

  # packing
  . config -menu .menubar
  grid .text -row 0 -column 0 -sticky news
  grid .vscroll -row 0 -column 1 -sticky ns
  grid .hscroll -row 1 -column 0 -sticky ew
  grid .statusBar -row 2 -column 0 -columnspan 2 -sticky we
  grid rowconfigure . 0 -weight 1
  grid columnconfigure . 0 -weight 1
  focus .text
  # end of packing

  ToggleWordWrap
  ToggleStatusBar
  New
  update idletasks
}

# handle command line parameters
proc CmdLine {} {
  global argv0 argv argc tpad_next tpad_edit

  set line {}
  if {[string match *tview $argv0]} {
    set tpad_edit 0
  } else {
    set tpad_edit 1
  }

  # two phases Unix-like command line argument parsing

  # phase 1 - parse options
  for {set tpad_next 0} {yes} {incr tpad_next} {
    set arg [lindex $argv $tpad_next]
    set first [string index $arg 0]
    set rest [string range $arg 1 end]

    switch -- $first {
      + {
        set line $rest
      }

      - {
        foreach opt [split $rest {}] {
          switch -- $opt {
            R {
              set tpad_edit 0
            }

	    h {
	      CmdHelp
	      exit 1
            }

            default {
              puts "$argv0: illegal option -- $opt"
	      CmdHelp
              exit 1
            }
          }
        }
      }

      default {
        break
      }
    }
  }

  Display

  # phase 2 - parse remaining arguments
  # (multiple file sequential editing)
  Next
  if {$line!={}} {
    GoToLine $line
  }
}

CmdLine
