set manx(tki) 0
# $Header: /home/yew/yew5/users/phelps/spine/tkman/RCS/tkman.tcl,v 1.40 1993/06/26 00:48:10 phelps Exp phelps $

#
# Bird?  Plane?  TkMan!  (TkPerson?)
#
#   by Tom Phelps (phelps@cs.Berkeley.EDU)
#      March 24-25, 1993
#
#
# 24-Mar  hard stuff working
# 25      easy stuff finished up, including documentation
# 29      wrote Makefile and otherwise prepared for distribution
# 31      changed incremental searching
#  1-Apr  posted to comp.lang.tcl
#  2      more portable version posted
#         browsers `send' to `manShowManFound', sink manual section
#  4      SEE ALSO links filter, unpacks compressed pages
#         (both inspired by Paul Raines)
#  5      manX.[zZ] directories, whatis found in text
#  6      workaround for bind bug, sunken text (both Dan Schenck)
#         "Searching for ..." message
#  7      print: now meta-click, works with compressed ones
#         fixed bind problems
#         can type in, e.g., print.3v and print.3s; distinction saved in history
#         .so links work (thanks Dave Lemke)--
#            but don't do this with compressed pages (which HPs don't)
#         various portability/system admin (suggested by model bug reporter Lars Huttar)
#  8      memory pipe replaces tmp file
# 10      Emacs-like point and mark
#         sections loaded on demand (suggested by Lars Huttar)
#         user additions preserved in ~/.tkman 
#         quick view of first n lines
# 11      (>1000 lines), wait cursor, tkinfo shares window with TkMan
# 12      option to preload or not, instant show update moved to bs2tk
# 13      restricted search of paths in MANPATH (anthony baxter)
# 14      case sensitivity switches to searches (anthony baxter)
# 15      tbl, eqn handled (Mark McIntosh)
# 17      incremental searching made more like Emacs, flush volume cache
#         (both suggested by Robert Wilensky)
# 19      fixed handling of compressed pages, section re-viewing much faster
# 20      solution to multiple, identically-named man pages in different directories,
#            at the expense of volume load on demand
# 25      different way to deal with multiples
# 27      hack around Tk text's wordend limitation
# 29      compressed database hack around
#         v1.3.3 released
# 30      dups menu hangs around, different hack around for compressed database
#  2-May  faster startup with database (big thanks to Frank Delahoyde)
#         SuperMan, of dubious value (suggested by Larry Virden)
#  5      demo to UCB Tcl/Tk users
#  7      (none) and (n/a) shown when pulldowns empty (Steve Smoot)
# 14      manTextOpen, manTextClose, manSectButt
#         documented: scan, pipe capability of apropos
#         apropos responsive to selected directory switches (Robert Wilensky)
# 15      more generous focus hits (Steve Smoot), tab moves focus
# 18      v1.3.4 released
# 19      v1.3.5 released (fixed bug which affected first-time users)
#         default fonts changed from pixel specification to point size (Donn Cave)
# 29      man page name searching case insensitive--search time 3->4 seconds
#         (Wayne A. Christopher)
#  1-Jun  multiple instantiations
#  2      output menu for multiple instantiations
#         changed default font to New Century Schoolbook so underscores show up
#  4      switch all man paths on or off (David Taubman)
#  7      . and .. to ~ and / (John Hagerman)
# 25      support for people with only cat directories (6 characters from Mike Beasley)
#         v1.4 released
# ??      stop bothering with everybody's weird macros: format everything
#            with my own set (ignoring cat directories completely)
#            (nroff formatting on the fly is too slow, though)
# ??      tkinfo fully integrated
#

set boilerplate {\
A bird?  A plane?  TkMan!  (TkPerson?)
by Tom Phelps

based on Tcl 6.7/Tk 3.2

Copyright Ó 1993 by T.A. Phelps (phelps@cs.Berkeley.EDU)
University of California, Berkeley
Department of Electrical Engineering and Computer Science
Computer Science Division


The latest version of TkMan is always available by anonymous FTP at
harbor.ecn.purdue.edu in the /pub/tcl/code directory.  Paul Raines has
modified TkMan for use on SGI (and System V?) machines; it's at
bohr.physics.upenn.edu (130.91.48.159) in /pub/tk.


PERMISSION IS GRANTED TO DISTRIBUTE THIS SOFTWARE FREELY, BUT ONE MAY NOT \
CHARGE FOR IT OR INCLUDE IT WITH SOFTWARE WHICH IS SOLD.  If you send me \
bug reports and suggestions for new features, include the versions of \
TkMan, Tcl, Tk, X, and UNIX and your machine and X window manager names.



============
Introduction
------------

I wanted my man page reader to have hypertext.  Along the way of writing
one, I added jumps to section titles, a configurable short cut list of
commonly-referenced man pages, a history list, and two kinds of searching.

Since man page formatting follows conventions but not rigid standards, not
all man pages can be parsed fully.  However, most yield their section
titles and SEE ALSOs and their emphasized words.  TkMan also tries to
filter out the unsightly page footers and headers put in by `nroff', but
nonstandard formatting can slip by.

First I'll describe how to use TkMan, although I hope that most features
are intuitive.  At the end are my address and UC's disclaimer.



===========
Using TkMan
-----------

= Locating a man page =

There are several ways to identify the manual page you desire.  You can
type its name into the entry box at the top of the screen and press return
or click `man'.  The name may be just the name of the command or may
include a `.n' or `(n)' at the end to specify in which section to look.
Man pages are matched using file name globbing (as in `csh'), so you can
use `?' to match any single character, `*' to match any (zero or more)
characters, `[' .. `]' to match any single character in the enclosed class,
and `{' .. `}' to expand the enclosed strings.  If you're running TkMan
from a shell and giving it an initial man page name to load up as an
argument, use this syntax (adequately quoted for protection from the
shell), as opposed to the syntax of the standard `man' command.  Usually
TkMan searches the directories in your MANPATH for the man page, but you
may instead provide a path name for the man page by beginning it with `~',
`/', `.' or `..'; this is the way to access a man page which isn't
installed in a MANPATH man directory.  Further, other Tcl interpreters may
display a man page in TkMan by `send'ing a message to the function
`manShowMan' with the name of the desired man page, for example `send tkman
manShowMan tcl'.  If multiple man page names match the specification, the
first match (as searched for in MANPATH order) is shown and a pulldown menu
appears which contains a list of the other matches.

You can click one of the buttons labeled `1'--`8', `o', `l', or `n' (your
letters may vary) to bring up that volume of man page entries and then
double-click on the name within the listing.  Typing a letter jumps to the
line starting with that letter.

Once you have a man page on the screen, you can double-click on the name of
a man page within the text to jump there.  The last few man pages you
looked at can be accessed directly through the `History' pulldown menu.
`Shortcuts' lists your personal favorites and is used just like `History',
with the additional options of adding (by clicking `+') the current man
page or removing (`-') it from the list.

`apropos' information is available by typing the name and clicking
`apropos' or hitting meta-return (for meta information, of course).  The
output of `apropos' is piped through `sort' and `uniq' to remove
duplicates.  To pass the matches through another filter, simply give the
pipe as in a shell, e.g., `search | grep ^g' (each space character is
significant) returns all the search-related commands which begin with the
letter "g".  Hypertext is active within this listing also.


= Working within a man page =

The `whatis' information for a man page, if any, appears at the top of the
screen.

To the extent it follows convention, the man page is parsed to yield its
section and subsection titles (which are directly available from the
`Sections' pulldown) and references to other man pages from its SEE ALSO
section (`Links' pulldown).  One may jump directly to a section within a
man page or a man page referenced in the SEE ALSO section, respectively, by
selecting the corresponding entry from one of these pulldowns.  It may be
handy to tear off the `Sections' and `Links' menus (by dragging the menu
title with mouse button 2 pressed).

You can move about the man page by using the scrollbar, or typing space or
C-v to page down or delete or M-v to scroll up.  C-n and C-p scroll up and
down, respectively, by a single line.  M-< goes to the head and M-> to the
tail of the text.  One may "scan" the page by dragging up and down with
the middle mouse button pressed.  Like Emacs, C-space will mark one's
current location, which can be returned to later with C-x, which exchanges
the then-current position with the saved mark; a second C-x swaps back.

C-s initiates a search.  Subsequently typing a few letters attempts to find
a line with that string, starting its search with the topmost line
currently visible.  A second C-s finds the next match of the string typed
so far.  C-r is similar to C-s but searches backwards.  Escape or C-g
cancels the search.  This incremental search can be use to quickly locate a
particular command-line option or a particular command in a group (as in
`csh').  The bottom of the screen interfaces to (modified) `mkTextSearch'
proc (swiped from a Tcl/Tk demo).  Type in a regular expression to search
for at the bottom and hit return or click `Search' to begin a search.  Hit
`Next' or keep hitting return to search for the next occurance.  [`Prev'
will be added when Tk supports a `tag prevrange' command.]

The tab key moves the focus from the man page type-in line to the text view
of the man page to the search box and back around.


= Other commands =

The `Occasionals' menu holds commands and options which you probably won't
use much.  The first group in this menu is comprised of commands which you
may invoke several times in a single TkMan session.  `Help' returns to this
information screen.  Although virtually made obsolete by TkMan, `Print'
makes a copy of the current man page on dead trees.  By default,
incremental searching is not case sensitive, but regular expression
searching is; these settings can be toggled with the next two menu
checkboxes.  If you install a new manual pages, invoking `Rebuild Database'
will permit them to show up the next time that volume list is shown,
without the bother of re-executing TkMan.

Like `xman' one may instantiate multiple viewers.  When there is more than
one viewer you may choose a man page in one viewer and have its contents
shown in another.  Use the `Output' pulldown (which appears and disappears
as relevant) to select one viewer's output destination to another.  With
this feature one may easily compare two similar man pages for differences,
keep one man page always visible, or examine several man pages from a
volume listing or a SEE ALSO section.

You will probably only use commands in the next two clusters of
`Occasionals' once or twice and leave them set for all executions of TkMan.
Choose between seeing a man page's `whatis' information and the full path
name of the found file with the `Show Path of Found Man' switch.  Until
`wish' has an option to startup iconified, TkMan has a checkbox for that.
At the factory, TkMan is set to format the contents of man volumes on
demand, which entails a little wait the first time that volume is shown, as
opposed to waiting for all volumes to be loaded at startup but no waiting
thereafter; the `Preformat Volumes' switch chooses between these.  Usually
you'll want to search for man pages in all the directories in your MANPATH;
however, you can selectively achieve the effect of removing an entry from
the MANPATH by turning off its corresponding switch.

`Mono' toggles between the proportionally-spaced font and a monospaced one,
for use in those man pages which rely on a constant-width font to align
columns [when Tk supports tabs better, the need for this will diminish].
`Quit' exits TkMan, of course, after saving some status information (see
below).  To exit without saving status information, select the `Quit'
option from the `Occasionals' pulldown.



= Customizing TkMan =

There are three levels of configuration to TkMan.

(1) Transparent.  Simply use TkMan and it will remember your window size
and placement and short cuts (if you quit out of TkMan via the `Quit'
button).


(2) Configuration file.  Other information, like the command(s) used to
print the man page and the fonts used, can be changed by editing one's own
~/.tkman.  Thus, a single copy of TkMan (`tkman') can be shared, but each
user can have his own customized setup.

To change colors add `option' commands, appended to ~/.tkman.
Alternatively, TkMan also works with standard X11 resources.  For instance,
this is how I set my foreground and background colors (X11 resource lines
should be placed in one's `.Xdefaults' file, not in ~/.tkman):

Tk*Foreground: SlateGray4
Tk*Background: beige

Additional useful commands include `wm', which deals with the window
manager; and `bind', which changes keyboard and mouse bindings.  If you
have trouble tailoring TkMan to your likes ask your system administrator
for help before e-mailing me; sys admin's should learn how to use the Tk
commands in question before asking me.

Note that the startup file is processed before defining `proc's,
initializing the data base, and creating the widget hierarchy.  If you want
a command executed after these have taken place (e.g., for `wm' or `bind'),
wrap it in an `after' command.  For instance, the following sets 
TkMan's icon bitmap:

after 2 wm iconbitmap .man @/some/directory/TkMan.xpm


(3) Source code.  Of course, but if you make generally useful changes or
have suggestions for some, please report them back to me so I may share the
wealth with the next release.

If your site has headers or footers which aren't filtered out, you need to
edit `bs2tk.c' to add checks for them.



=========
Addresses
---------

Tom Phelps
University of California, Berkeley
Computer Science Division
571 Evans Hall
Berkeley, CA  94720
USA

(510) 642-8155
phelps@cs.Berkeley.EDU




To do list:

maybe have split screen like xman, or multiple instantiations
support a way of grouping, like SGIs
backwards regexp search when `text' widget has `tag prevrange'
save yview with shortcuts?  history?
link up with Kennard White's texinfo reader
add browsing of header files?



==========
Disclaimer
----------

IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY \
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES \
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF \
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF \
SUCH DAMAGE.

THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, \
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE \
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF \
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, \
ENHANCEMENTS, OR MODIFICATIONS.


$Date: 1993/06/26 00:48:10 $
}



#--------------------------------------------------
#
# set defaults for shared global variables
#
#--------------------------------------------------

# # # # # # # # # # # # # # # # # # # # # # # # # #
# DON'T EDIT THE DEFAULTS HERE--DO IT IN ~/.tkman #
# # # # # # # # # # # # # # # # # # # # # # # # # #

# man(), manx()
set manx(manList) {1 2 3 x 4 5 6 7 8 9 10 l o n p}
set manx(manTitleList) {
   "User Commands" "System Calls" Subroutines WARNING
   Devices "File Formats"
   Games "Miscellaneous" "System Administration" ? ?
   Local Old New Public
}
set manx(userconfig) "### your additions go below"
set manx(init) 0
set manx(single) 0
set manx(search) 1.0
set manx(man) ""
set manx(manfull) ""
set manx(catfull) ""
set manx(name) ""
set manx(num) ""
#set manx(search,string) ""
#set manx(search,oldstring) ""
set manx(try) 0
set manx(lastkeys) ""
set manx(mode) help
set manx(oldmode) help
set manx(vect) 1
set manx(lastMessage) ""
# make history a man?
set manx(history) ""
set manx(paths) ""
foreach i [split $env(MANPATH) :] {
   if {[file exists $i]} {
      lappend manx(paths) $i
      if {![info exists man($i)]} {set man($i) 1} {set man($i) 0}
   }
}
set manx(uid) 1
set manx(outcnt) 1

set man(show,pro) "-adobe-new century schoolbook-medium-r-normal--*-140-*"
set man(show,mono) "-adobe-courier-medium-r-normal--*-120-*"
set man(show,keyword) "-adobe-courier-medium-r-normal--*-120-*"
set man(show,font) $man(show,pro)
set man(show,sc) "-adobe-new century schoolbook-medium-r-normal--*-120-*"
set man(show,bold) "-adobe-new century schoolbook-bold-r-normal--*-120-*"
set man(show,symbol) "-adobe-symbol-medium-r-normal--*-140-*"
set man(show,bigbold) "-adobe-new century schoolbook-bold-r-normal--*-140-*"
set man(show,italic) "-adobe-new century schoolbook-medium-i-normal--*-140-*"
set man(show,bi) "-adobe-new century schoolbook-bold-i-normal--*-120-*"
set man(maxhistory) 15
set man(shortcuts) {}
set man(whatwhere) 0
set man(iconify) 0
set man(subsect) ""
set man(preformat) 0
set man(incr,case) 0
set man(regexp,case) 1
set man(geom) 550x800+150+10
set man(show,fontcolor) [option get . foreground Foreground]
if {$man(show,fontcolor)==""} {set man(show,fontcolor) black}

if [file readable ~/.tkman] {source ~/.tkman}
if {![info exists manx(debug)]} {set manx(debug) 0}
if {![info exists env(MANPATH)]} {set env(MANPATH) /usr/man:/usr/local/man}
if {![info exists manx(lib)]} {set manx(lib) [pwd]}
source $manx(lib)/taputils.tcl



#--------------------------------------------------
#
# tkMan -- make the gui
#
#--------------------------------------------------

proc TkMan {} {
   global man manx env

   if {$manx(uid)==1} {
      set dup 0
      # .man is guaranteed to exist
      set w .man
   } else {
      set dup 1
      set w .man$manx(uid)
   }

   toplevel $w
   wm minsize $w 200 500

   if {!$dup} {
      wm title $w "TkMan v$manx(version)"
      wm iconname $w TkMan
      wm geometry $w $man(geom)
      if {$man(iconify)} {wm iconify $w}
   } else {
      wm title $w "TkMan #$manx(uid)"
      wm geometry $w [lfirst [split $man(geom) +]]
#      wm group $w .man
   }


   ### information bar
   label $w.info -anchor w

   ### man or section or texinfo
   frame $w.kind
   button $w.man -text "man" -command "manShowMan \$manx(typein$w) {} $w"
   bind $w.man <Shift-Button-1> "manSuperMan $w \$manx(typein$w)"
   bind $w.man <Meta-Button-1> "manSuperMan $w \$manx(typein$w)"
   button $w.apropos -text "apropos" -command "manApropos $w \$manx(typein$w)"
   entry $w.mantypein -relief sunken -textvariable manx(typein$w)
   emacsbind $w.mantypein
   bind $w.mantypein <Shift-KeyPress-Return> "manSuperMan $w \$manx(typein$w)"
   bind $w.mantypein <KeyPress-Return> "$w.man invoke"
   # ha! meta information
   bind $w.mantypein <Mod1-KeyPress-Return> "$w.apropos invoke"
   menubutton $w.dups -text ß -font *symbol*140* -menu $w.dups.m -relief raised
   menu $w.dups.m

   pack append $w.kind $w.man {left padx 4 frame e} $w.apropos {left padx 8} \
      $w.mantypein {left padx 10 frame w}

   # link up with Kennard White's texinfo reader here
   if {$manx(tki) && [info exists manx(texinfo)]} {
      button $w.texinfo -text info -command "maninfo $w"
      pack append $w.kind $w.texinfo left
   }

   menubutton $w.vols -text "Volumes" -relief raised -menu $w.vols.m
   menu $w.vols.m
   set ctr 0
   foreach i $manx(manList) {
      $w.vols.m add command -label "($i) [lindex $manx(manTitleList) $ctr]" \
         -command "manShowSection $w $i"
      incr ctr
   }
   label $w.volnow
   pack append $w.kind $w.vols left $w.volnow left


   ### navigation
   frame $w.nav
   menubutton $w.sections -text "Sections" -relief raised -menu $w.sections.m
   menu $w.sections.m
   menubutton $w.links -text "Links" -relief raised -menu $w.links.m
   menu $w.links.m

   frame $w.scf
   menubutton $w.shortcuts -text "Shortcuts" -relief raised -menu $w.shortcuts.m
   menu $w.shortcuts.m
   manShortcuts $w init
   button $w.add -text "+" -padx 4 -command "manShortcuts $w add"
   button $w.sub -text "-" -padx 4 -command "manShortcuts $w sub"
   pack append $w.scf $w.shortcuts left $w.add left $w.sub left

   menubutton $w.history -text History -relief raised -menu $w.history.m
   menu $w.history.m
   $w.history.m add command -label "(none)"


   menubutton $w.output -text "Output" -menu $w.output.m -relief raised
   menu $w.output.m
   set manx(out$w) $w


   ### commands I don't use much
   menubutton $w.occ -text Occasionals -relief raised -menu $w.occ.m
   menu $w.occ.m
   $w.occ.m add command -label "Help" -command \
      "manHelp $w; set manx(lastkeys) {Using TkMan}; manKeyNav $w 4 s; manKeyNav $w 4 g"
   $w.occ.m add command -label Print -command "manPrint $w"
   $w.occ.m add checkbutton -label "Incremental Search Case Sensitive" \
      -variable man(incr,case)
   $w.occ.m add checkbutton -label "Regexp Search Case Sensitive" \
      -variable man(regexp,case)
   $w.occ.m add command -label "Rebuild Database" -command "
      manMessage $w {Rereading Volumes ... }
      $w.show configure -cursor watch; update idletasks
      catch {unset mani}
      foreach i \$manx(manList) {
         manMessage $w \"\$manx(lastMessage) \$i\"; update idletasks
         manReadSection \$i
      }
      $w.show configure -cursor \$manx(cursor)
      manMessage $w {}
   "
   $w.occ.m add command -label "Instantiate New View" -command {
      incr manx(uid)
      incr manx(outcnt)
      TkMan
      manOutput
   }
   $w.occ.m add command -label "Quit, don't update .tkman"  -command "destroy ."
#   $w.occ.m add command -label "Quit" -accelerator M-q \
#      -command "manQuit $w"
   bind all <Meta-KeyPress-q> "$w.occ.m invoke Quit"

   $w.occ.m add separator
   $w.occ.m add checkbutton -label "Show Path of Found Man" -variable man(whatwhere)
   $w.occ.m add checkbutton -label "Startup Iconified" -variable man(iconify)
   $w.occ.m add checkbutton -label "Parse Subsections" -variable man(subsect) \
      -onvalue -b -offvalue ""
   $w.occ.m add checkbutton -label "Preformat Volumes" -variable man(preformat)

   $w.occ.m add separator
   if {[llength $manx(paths)]>2} {
      $w.occ.m add command -label "All Paths On" -command {
         set env(MANPATH) ""
         foreach i $manx(paths) {set man($i) 1; append env(MANPATH) :$i}
	 set env(MANPATH) [string trim $env(MANPATH) :]
         foreach i $manx(manList) {set mani($i,form) ""}
      }
      $w.occ.m add command -label "All Paths Off" -command {
         foreach i $manx(paths) {set man($i) 0}
         foreach i $manx(manList) {set mani($i,form) ""}
         set env(MANPATH) ""
      }
   }
   foreach i $manx(paths) {
      $w.occ.m add checkbutton -label $i -variable man($i) -command {
         foreach i $manx(manList) {set mani($i,form) ""}
         set env(MANPATH) ""
         foreach i $manx(paths) {if {$man($i)} {append env(MANPATH) :$i}}
	 set env(MANPATH) [string trim $env(MANPATH) :]
      }
   }

   pack append $w.nav $w.sections {left padx 8} \
      $w.links {left expand} \
      $w.scf {left expand} \
      $w.history {left expand} \
      $w.occ {left padx 8}


   ### view box
   frame $w.v
   text $w.show -font $man(show,font) -foreground $man(show,fontcolor) -relief sunken \
       -yscrollcommand "$w.vsb set" -exportselection yes -wrap word -border 2 -cursor left_ptr
   set manx(cursor) [lindex [$w.show configure -cursor] 4]

   $w.show tag configure title -font $man(show,bold)
#   $w.show tag configure htitle -background LightGray -borderwidth 3 -relief raised
   $w.show tag configure bold -font $man(show,bold)
   $w.show tag configure symbol -font $man(show,symbol)
   $w.show tag configure high -font $man(show,italic)
   $w.show tag configure mono -font $man(show,keyword)
   $w.show tag configure big -font $man(show,bigbold)
   $w.show tag configure sc -font $man(show,sc)
   $w.show tag configure bi -font $man(show,bi)
   $w.show tag configure search \
      -foreground [lindex [$w.show configure -background] 4] \
      -background [lindex [$w.show configure -foreground] 4]
   # bind letters to jump to that part of list
   bind $w.show <Any-KeyPress> "manKeyNav $w %s %K"
   scrollbar $w.vsb -orient vertical -command "$w.show yview"
   pack append $w.v $w.vsb {right filly} $w.show {top expand fill}


   ### search (snagged from FileSelectionBox--wow, code reuse!)
   frame $w.search
   button $w.search.s -text "Search" -command "
      set manx(tmp) \[manTextSearch $w.show \$manx(search,string$w)\]
      if {\$manx(tmp)==1} {lappend manx(tmp) match} {lappend manx(tmp) matches}
      $w.search.cnt configure -text \$manx(tmp)
      set manx(search) 1.0
      $w.show yview 0
      $w.search.n invoke
   "
   button $w.search.n -text "Next" -command "
      # this catches empty search string error for Search too
      if {\$manx(search,string$w)==\"\"} {
         manMessage $w \"Nothing to search for!  Type a regexp and click `Search'.\"
         return
      }
      set manx(tmp) \[$w.show tag nextrange search \[max \[expr \[lindex \[$w.vsb get\] 2\]+1\].0 \$manx(search)\]\]
      if {\$manx(tmp)==\"\"} {
         manMessage $w \"No more matches; restarting at top.\"
         $w.show yview 0
         set manx(search) 1.0
      } else {
         $w.show yview -pickplace \[lindex \$manx(tmp) 0\]
         update
         manMessage $w \"Viewing lines \[lindex \[$w.vsb get\] 2\] to \[lindex \[$w.vsb get\] 3\].\"
         set manx(search) \[expr \[lindex \[$w.vsb get\] 3\]+1+1\].0
      }
   "
   label $w.search.cnt
   entry $w.search.t -relief sunken -textvariable manx(search,string$w)
   emacsbind $w.search.t
   set manx(search,oldstring$w) ""
   bind $w.search.t <KeyPress-Return> "
      if {\$manx(search,oldstring$w)!=\$manx(search,string$w)} {
         set manx(search,oldstring$w) \$manx(search,string$w)
         $w.search.s invoke
      } else {$w.search.n invoke}"
   pack append $w.search $w.search.s left $w.search.n {left padx 6} \
      $w.search.t {left expand fillx padx 20 frame w} $w.search.cnt left

   ### font
   # mostly mono (Mozart?)
   checkbutton $w.mono -text "Mono" -variable man(show,font) \
      -onvalue $man(show,mono) -offvalue $man(show,pro) \
      -command "$w.show configure -font \$man(show,font)"

   ### quit
   button $w.quit -text "Quit" -command "manQuit $w" -padx 4
   if {$dup} {$w.quit configure -text "Close" -command "destroy $w; incr manx(outcnt) -1; manOutput"}
#   bind $w.quit <Button-1> "[bind Button <Button-1>]; manQuit $w"
#   bind $w.quit <Meta-Button-1> "[bind Button <Button-1>]; destroy ."

   pack append $w.search \
      $w.mono {left padx 6 frame e} \
      $w.quit {left padx 6}



   pack append $w \
      $w.info {top fillx pady 8} \
      $w.kind {top fillx pady 8} \
      $w.nav {top fillx pady 12} \
      $w.v {top expand fill} \
      $w.search {top fillx pady 12}

   # generous hit regions, tab between
   foreach i {info kind nav} {bind $w.$i <Enter> "focus $w.mantypein"}
   foreach i {v show vsb} {bind $w.$i <Enter> "focus $w.show"}
   bind $w.search <Enter> "focus $w.search.t"
   foreach i {mantypein show search.t} {
      bind $w.$i <KeyPress-Tab> "manTab $w"
# bug in Tk bind: below command binds Alt-KeyPress-Tab to KeyPress-Tab's binding
      bind $w.$i <Meta-KeyPress-Tab> "manTab $w -1"
   }

   manHelp $w
   update idletasks; focus $w.show
}


proc manShortcuts {w cmd} {
   global man manx

   if {$cmd!="init" && ($manx(mode)!="man" || $manx(man)=="")} return
   set n $manx(name); set p $manx(man)

   set index [lsearch $man(shortcuts) $p]
   if {$cmd=="add" && $index==-1} {lappend man(shortcuts) $p} \
   elseif {$cmd=="sub" && $index!=-1} {set man(shortcuts) [lfilter $p $man(shortcuts)]}

   $w.shortcuts.m delete 0 last
   if {[llength $man(shortcuts)]} {
      foreach i $man(shortcuts) {
         $w.shortcuts.m add command -label [file rootname [file rootname $i]] -command "manShowMan $i {} $w"
      }
   } else {
      $w.shortcuts.m add command -label "(none)"
   }
}


proc manOutput {} {
   global manx

   set wins [winfo children .]

   foreach i [lsort $wins] {
         set title "#[string range $i 4 4]"
         if {$title=="#"} {append title 1}
         lappend titleList [list $title $i]
   }

   foreach w $wins {
      $w.output.m delete 0 last
      foreach i $titleList {
         $w.output.m add radiobutton -label [lfirst $i] \
            -variable manx(out$w) -value [lsecond $i]
      }
   }

   if {$manx(outcnt)==1} {
      pack unpack .man.output
   } else {
      foreach w $wins {pack before $w.occ $w.output {left expand}}
   }
}



#--------------------------------------------------
#
# manNewMode -- collect mode change inits in single place
#
#--------------------------------------------------

proc manNewMode {w mode {n {""}}} {
   global man manx

   set manx(oldmode) $manx(mode)
   set manx(mode) $mode
   if {$manx(oldmode)=="info"} {
      if {$mode!="info"} {pack unpack $w.buts}
#rebind keys
   } elseif {$mode=="info"} {
# pack buttons & bind navigation keys
   }

   # reset searching
   set manx(search,string$w) ""
   $w.search.cnt configure -text ""
   set manx(lastkeys) ""
   set manx(vect) 1
   set manx(try) 0
   $w.sections.m delete 0 last
   $w.links.m delete 0 last
   if {$mode!="man"} {
      $w.links.m add command -label "(n/a)"
      if {$mode!="help"} {$w.sections.m add command -label "(n/a)"}
   }
   # should have companions to wordstart that are bounded by whitespace, not nonalpha
   if {!$manx(single)} {
      bind $w.show <Double-Button-1> "manShowMan \[$w.show get {@%x,%y wordstart} {@%x,%y lineend}\] $n $w"
   }

   after 1 $w.show mark set xmark 1.0
}



#--------------------------------------------------
#
# manXXX - miscellaneous medium-level commands
#
#--------------------------------------------------

proc manOpenText {w} {
   global manx

   if {$manx(mode)!="help"} {$w.show configure -cursor watch; update idletasks}
   $w.show configure -state normal
   $w.show delete 0.1 end
}

proc manCloseText {w} {
   global manx

   $w.show configure -state disabled
   $w.show configure -cursor $manx(cursor)
}

proc manSectButt {w n} {
   global manx

   if {[set f [lsearch $manx(manList) $n]]!=-1} {
      $w.volnow configure -text "([lindex $manx(manList) $f]) [lindex $manx(manTitleList) $f]"
   }
}

proc manTab {w {ink 1}} {
#puts stdout "manTab w/focus = [focus]"
   set l "$w.mantypein $w.show $w.search.t"
   set i [lsearch $l [focus]]
#puts -nonewline stdout "manTab: incr $ink, old $i, "
   incr i $ink
   # could use a modulo function here
   if {$i>=[llength $l]} {set i 0}
   if {$i<0} {set i [expr [llength $l]-1]}
#puts stdout "new $i"
   focus [lindex $l $i]
}

proc manMessage {w msg} {
   global manx

   $w.info configure -text $msg
   set manx(lastMessage) $msg
}



#--------------------------------------------------
#
# manInit -- determine which sections exist,
#    load lists thereof if requested
#
#--------------------------------------------------

proc manInit {} {
   global man manx mani env

   if {$manx(init)} return

   set short ""
   set shortT ""

   if {$manx(tki) && [file exists $man(infodir)/dir]} {
      tkiAddInfoPaths $man(infodir)
      set manx(texinfo) ""
   }

   set cnt 0
   foreach j $manx(manList) {
      manMessage .man "$manx(lastMessage) $j"; update idletasks
      if {[manReadSection $j]!=0} {
         lappend short $j
         lappend shortT [lindex $manx(manTitleList) $cnt]
         if {$man(preformat)} {manFormatSect $j}
      }
      incr cnt
   }

   set manx(manList) $short
   set manx(manTitleList) $shortT

   set manx(init) 1
}



#--------------------------------------------------
#
# manReadSection
#
#--------------------------------------------------

proc manReadSection {n} {
   global man manx mani env

   set dirtmp [pwd]

   # follow all paths here, even if search turned off for that dir
   set cnt 0
   foreach i $manx(paths) {
      foreach k [glob -nocomplain $i/$man(mandir)$n*] {
         if {![catch {cd $k}]} {
            if {![catch {set ltmp [glob -nocomplain *]}]} {
               lappend mani($n) [list $k $ltmp]
               incr cnt [llength $ltmp]
               }
         }
      }
   }
   set mani($n,cnt) "$cnt entries"

   cd $dirtmp

   # initially unformatted
   set mani($n,form) ""

   return $cnt
}



#--------------------------------------------------
#
# manx - interface to Kennard White's texinfo
#
#--------------------------------------------------

proc maninfo {w} {
   manNewMode $w info

   bind $w.show <Button-1> {}
   tkiGetAndDisplay {}
}



#--------------------------------------------------
#
# manShowSection -- show listing
#
#--------------------------------------------------

proc manShowSection {w n} {
   global man manx mani

   manNewMode $w section $n
   set head [lindex $manx(manTitleList) [lsearch $manx(manList) $n]]
   manMessage $w $head
   manSectButt $w $n

   manOpenText $w
   if {$mani($n,form)==""} {manFormatSect $n}
   $w.show insert end $mani($n,form)
   $w.search.cnt configure -text $mani($n,cnt)
   manCloseText $w
#   focus $w.show
}

#            \} else \{
#               foreach m [glob -nocomplain $l/*] \{
#                  lappend manx($n) [lfirst [split $m .]]
#               \}

proc manFormatSect {n} {
   global man mani

   set ltmp ""

   foreach i $mani($n) {
      # directory turned off
      if {$man([file dirname [lfirst $i]])} {
         foreach j [lsecond $i] {
            lappend ltmp $j
         }
      }
   }

   # specialized version of uniqlist
   set pr ""; set pe ""; set pl ""
   set online 0; set skip 0
   foreach i [lsort $ltmp] {
      set ir [file rootname $i]; set ie [file extension $i]; set il [string range $i 0 0]
      if {$ie==".gz"||$ie==".z"||$ie==".Z"} {set ie [file extension $ir]; set ir [file rootname $ir]}

      if {$online>50} {
         append mani($n,form) "\n"
         set online 0
      } elseif {$pl!=$il && $online>0 && ($n==3 || ![string match {[A-Z]} $il])} {
         append mani($n,form) "\n\n"
         set online 0
      }

      if {$pr!=$ir} {
         if {$online!=0} {append mani($n,form) "  "}
         append mani($n,form) $ir; incr online
         set skip 0
      } elseif {$pe==$ie} {
#         append mani($n,form) +
#         set skip 0
      } else {
         if {$online!=0} {
            if {!$skip} {append mani($n,form) $pe}
            append mani($n,form) "  "
         }
         append mani($n,form) $i; incr online
         set skip 1
      }

      set pr $ir; set pe $ie; set pl $il
   }
}



#--------------------------------------------------
#
# manShowMan -- given various formats of names,
#    search for that man page.  if successful, call manShowManFound
#
# don't use `man' to show because may want to *always*
#    format with my own macros
#
#--------------------------------------------------

proc manShowMan {fname {goodnum ""} {w .man}} {
   global man manx mani env
#puts stdout "manShowMan: $fname $goodnum $w"

   if {[string trim $fname]==""} return
   set wtmp $w
   if {[winfo exists $manx(out$w)]} {set w $manx(out$w)} {set manx(out$w) $w}

   # given full path?  if so, don't need to search
   if {[regexp {^(\.|~|/)} $fname]} {
      if {[string match ./* $fname]} {set fname [pwd]/[string range $fname 2 end]}
      if {[string match ../* $fname]} {
         set dirtmp [pwd]
         while {[string match ../* $fname]} {
            set dirtmp [file dirname $dirtmp]
            set fname [string range $fname 3 end]
         }
         set fname $dirtmp/$fname
      }
      manShowManFound [glob $fname] 0 $w
      return
   }


   # need to search for name

   set fname [string tolower [string trim [lfirst $fname] { .,?!;"'}]]
   manMessage $w "Searching for $fname ..."; update idletasks
   set sname [string trim $fname ()]

   if {$goodnum!=""} {
      set name $sname
      set num $goodnum
      set ext ""
   } elseif {![regexp -nocase {([a-z0-9_.]+)([\t ]*)\(([^)])(.*)\)} \
      $fname all name spc num ext]} {
      # no .z's here
      set name [file rootname $sname]
      set tmp [string range [file extension $sname] 1 end]
      set num [string range $tmp 0 0]
      set ext [string range $tmp 1 end]
#puts stdout "\t. $name : $num : $ext"
   }
   set num [string tolower $num]; set ext [string tolower $ext]
#puts stdout "$name : $num : $ext"

   $w.show configure -cursor watch; update idletasks

   # search for man page
   set found 0
   set foundList ""

   foreach i [if {$num!=""} {format $num} {format $manx(manList)}] {
      foreach j $mani($i) {
         set curdir [lfirst $j]
#puts stdout "curdir = $curdir, file dirname = [file dirname $curdir]"
         if {!$man([file dirname $curdir])} continue
#puts stdout "\tsearching"
         foreach k [lsecond $j] {
            if {[string match $name.* [string tolower $k]]
               && [file readable $curdir/$k] && [file isfile $curdir/$k]} {
               lappend foundList $curdir/$k
            }
	 }
      }
   }
   set found [llength $foundList]

   # if no matches with extension, look for one without
   if {!$found} {
      if {$ext!=""} {manShowMan $name $num $w} \
      elseif {$num!=""} {manShowMan $name {} $w}
   }

   $w.show configure -cursor $manx(cursor)

   if {!$found} {
      manMessage $w "$sname not found"
      return
   } elseif {$found>1} {
      after 1 pack before $w.mantypein $w.dups left; $w.dups configure -state active
      $w.dups.m delete 0 last
      foreach i $foundList {$w.dups.m add command -label $i -command "manShowManFound $i 1 $w"}

      # show closest match
      set show [lfirst $foundList]
#puts "query $name $num $ext"
      foreach i $foundList {
         set ir [file rootname $i]; set in [file extension $i]
         if {[string match {.[zZ]} $in]} {set ie [file extension $ir]; set ir [file rootname $ir]}
         set ie [string range $in 2 end]; set in [string range $in 1 1]
#puts "\tdatabase $ir $in $ie"
         if {$in==$num && $ie==$ext} {set show $i; break} \
	 elseif {$in==$num && $show==""} {set show $i}
      }
      manShowManFound $show 1 $w
   } else {manShowManFound $foundList 0 $w}

   set w $wtmp
}



#--------------------------------------------------
#
# manShowManFound -- display man page and update gui with parse info
#
#--------------------------------------------------

proc manShowManFound {f {keep 0} {w .man}} {
# interestingly, [file exists ""]==1, hence /dev/null/bozo
   global man manx

   manNewMode $w man

   # set variables
   set manx(manfull) $f
   set manx(man) [file tail $f]
   if {[regexp {\.[zZ]$} $manx(man)]} {set manx(man) [file rootname $manx(man)]}
   set manx(name) [file rootname $manx(man)]
   set manx(num) [string range [file extension $manx(man)] 1 1]
   set manx(catfull) [file dirname [file dirname $f]]/cat$manx(num)*/$manx(man)*
   manMessage $w "Formatting $manx(name) ..."; update idletasks
   if {!$keep} {pack unpack $w.dups}

   # text box
   set manx(links) ""
   if {[set path [lfirst [glob -nocomplain $manx(catfull)]]]!=""} {
      set fm [set manx(catfull) $path]
   } elseif {[file exists $manx(manfull)]} {
      set fm "[set path $manx(manfull)] | $man(format)"
   } else {
      manMessage $w "$manx(manfull) not found"
      return
   }

   manOpenText $w

   if {[string match {*.[zZ]} $path] ||
       [string match {*.[zZ]} [file dirname $path]]} {
       set pipe $man(zcat)} else {set pipe cat}
   append pipe " $fm | bs2tk $man(subsect)"

#   set dirtmp [pwd]
   if {[catch {cd [file dirname [file dirname $fm]]}]} {
      manMessage $w "Can't cd into [file dirname $fm].  This is bad."
      return
   }
   # source should take a pipe argument
   #   source |$pipe
   if {[catch {set fid [open "|$pipe"]}]} {
      manMessage $w "Deep weirdness with $path.  Tell your sys admin."
      return
   }
   while {![eof $fid]} {eval [gets $fid]}
   close $fid
#   cd $dirtmp

   manCloseText $w
#   focus $w.show

   # for relative names w/. and ..
   cd [file dirname $fm]

   manShowManStatus $w
}



proc manShowManStatus {w} {
   global man manx

   ### update status information

   # show section
   manSectButt $w $manx(num)

   # typein field
   set manx(typein$w) $manx(name)

   # history - save entire path
   set manx(history) [lrange [setinsert $manx(history) 0 $manx(manfull)] 0 [expr $man(maxhistory)-1]]
   # should do this as a postcommand, but that's too messy
   $w.history.m delete 0 last
   foreach i $manx(history) {
      $w.history.m add command -label [file tail $i] -command "manShowMan $i {} $w"
   }

   # hyperlinks
   set E 0
   foreach i $manx(links) {
       foreach j [split $i ,.] {
          if {[regexp {\([1-9lonp].*\)} $j]} {
             $w.links.m add command -label $j -command "manShowMan $j {} $w"
             incr E
          }
       }
   }
   if {!$E} {$w.links.m add command -label "(none)"}

   # start searches back at top
   set manx(search) 1.0

   # whatis information -- find by scanning text
   manMessage $w ""
   if {$man(whatwhere)} {
      manMessage $w $manx(manfull)
   } else {
      scan [$w.show index end] %d n
      set n [max $n 20]
      for {set i 1} {$i<=$n} {incr i} {
         if {[regexp {- (.*)} [$w.show get $i.0 "$i.0 lineend"] all info]} {
            incr i
            while {[regexp {( +)(.*)} [$w.show get $i.0 "$i.0 lineend"] all spaces more]} {
               append info " $more"
               incr i
            }
            manMessage $w "$info"
            break
         }
      }
   }
}



#--------------------------------------------------
#
# manShowText -- use searching, etc. facilities for non-man page text
#    to use via `send', pass full path name of text file to show
#
#--------------------------------------------------

proc manShowText {f {w .man}} {
   global manx

   manNewMode $w txt

   if {![file readable $f] || [file isdirectory $f]} return

   manOpenText $w
   
   set fid [open $f]
   while {![eof $fid]} {$w.show insert end [gets $fid]}
   close $fid

   manCloseText $w


   ### update status information

   # no section
   manSectButt $w X

   # typein field
   set manx(typein$w) [file tail $f]

   # what/where
   manMessage $w $f
}



#--------------------------------------------------
#
# manApropos -- show `apropos' (`man -k') information, w/dups filtered out
#
#--------------------------------------------------

proc manApropos {w name} {
   global manx

   if {$name==""} {set name $manx(man)}
   if {$name==""} {return}

   manNewMode $w apropos
   set fid [open "|man -k $name | sort | uniq"]
   manOpenText $w
   while {![eof $fid]} {
      gets $fid line
      $w.show insert end "$line\n"
#      if {[regexp {^[a-zA-Z_\t ]+\([^)]*\)} "$line" link]} {
#	 $w.links.m add command -label "$link" -command "manShowMan \"$link\" {} $w"
#      }
   }
   close $fid

   manCloseText $w
#   focus $w.show
}



#--------------------------------------------------
#
# manSuperMan -- crossreference keyword (this is expensive!)
#
#--------------------------------------------------

# G.B. Shaw reference
proc manSuperMan {w fname} {
   global man manx env

   if {$fname==""} {set name $manx(man)}
   if {$fname==""} {return}
#   set dirtmp [pwd]

   manNewMode $w super

   if {![regexp -nocase {([a-z0-9_]+)([\t ]*)\(([^)])(.*)\)} \
      $fname all name spc num ext]} {
      set name [file rootname $fname]
      set tmp [string range [file extension $fname] 1 end]
      set num [string range $tmp 0 0]
      set ext [string range $tmp 1 end]
   }
   set num [string tolower $num]; set ext [string tolower $ext]
   if {$num!=""} {set numList $num} {set numList $manx(manList)}

   set foundList ""
   set cnt [llength $manx(paths)]
   foreach i $manx(paths) {
      set curdir [lfirst $i]
      manMessage $w "Wait $cnt ..."; update idletasks
      incr cnt -1
      if {!$man($curdir)} continue

      foreach j $numList {
         foreach k [glob -nocomplain $curdir/man$j*] {
            if {[catch {cd $k}]} continue
            catch {
            foreach l [eval exec egrep -il $name [glob *]] {
               lappend foundList $k/$l
            }}
         }
      }
   }


   set found [llength $foundList]
   if {$found} {
      $w.dups.m delete 0 last
      foreach i $foundList {
         $w.dups.m add command -label [file tail $i] -command "manShowManFound $i 1 $w"
      }
      manShowManFound [lfirst $foundList] 1 $w
      after 1 pack before $w.mantypein $w.dups left; $w.dups configure -state active
   }

#   cd $dirtmp
}



#--------------------------------------------------
#
# manPrint -- kill trees
#
#--------------------------------------------------

proc manPrint {w} {
   global man manx

   if {$manx(mode)!="man"} {
      manMessage $w "TkMan only prints man pages."
      return
   }

   set f [string trim $manx(manfull)]
   if {$f=="" || ![file exists $f]} return

   if {[string match {*.[zZ]} $f]
       || [string match {*.[zZ]} [file dirname $f]]} {
       set pipe $man(zcat)} else {set pipe cat}

   eval exec $pipe $f | $man(print)
}



#--------------------------------------------------
#
# manTextSearch 
#
#--------------------------------------------------

proc manTextSearch {w string} {
   global man

   if {$string==""} return
   return [regexpTextSearch $w $string search [expr !$man(regexp,case)]]
}



#--------------------------------------------------
#
# manHelp -- dump boilerplate, decorate w/regexp-added tags
#
#--------------------------------------------------

proc manHelp {w} {
   global boilerplate manx

   manNewMode $w help

   manOpenText $w
   $w.show insert end $boilerplate

   $w.show tag add big 1.0 "1.0 lineend"
   scan [$w.show index end] %d numLines
   for {set i 1} {$i <= $numLines} {incr i} {
      set line [$w.show get $i.0 "$i.0 lineend"]
      if {[string match ==* $line]} {
         set j [expr $i+1]
         set line [$w.show get $j.0 "$j.0 lineend"]
         $w.sections.m add command -label $line -command "$w.show yview $i"
         $w.show tag add title $j.0 "$j.0 lineend"
      } elseif {[regexp -nocase {^= [a-z ]+ =} $line]} {
         $w.show tag add high $i.0 "$i.0 lineend"
      }
   }
   regexpTextSearch $w.show {Ó} symbol
#   regexpTextSearch $w.show {Please.*!} high
   regexpTextSearch $w.show {(`[^']+')|([MC]-.)|([a-z]+@[A-Za-z.]+)} mono
   regexpTextSearch $w.show {[A-Z][^a-z.?!]*[A-Z]} sc

   manCloseText $w

   update idletasks
   after 1 "manMessage $w \"TkMan v$manx(version) by Tom Phelps (phelps@cs.Berkeley.EDU)\""
}



#--------------------------------------------------
#
# manKeyNav -- keyboard-based navigation and searching
#
#--------------------------------------------------

proc manKeyNav {w m k} {
   global man manx
   if {[regexp {(Shift|Control|Meta)_.} $k]} return
   if {$k=="Help"} {$w.occ.m invoke Help; return}

   # get initial values
   set minele 1
   set firstmode [expr {$manx(mode)=="section" || $manx(mode)=="apropos"}]
   if {[winfo class $w.show]=="Text"} {set off 1; scan [$w.show index end] %d numLines} \
   elseif {[winfo class $w.show]=="Listbox"} {set off 0; set numLines [$w.show size]; set minele 0}
   scan [$w.vsb get] "%d %d %d %d" total window first last


   # some translations
   if {$manx(try) || $manx(lastkeys)!=""} {
      case $k {
         space {set k " "}
         Delete {
            set k ""
            set last [expr [string length $manx(lastkeys)]-2]
            set manx(lastkeys) [string range $manx(lastkeys) 0 $last]
            set manx(try) 1
         }
         default { if {$m<=1} {set k [name2char $k]} }
      }
   }


   # commands
   set mk $m-$k
   case $mk {
      {4-x} {
         # yview w/o parameter should return current value
         set tmp [expr [lindex [$w.vsb get] 2]+1].0
         $w.show yview xmark
         update
         $w.show mark set xmark $tmp
      }
      {4-space} {$w.show mark set xmark [expr [lindex [$w.vsb get] 2]+1].0}
      {0-space 4-v} {$w.show yview [min [expr $first+$window-1] [expr $numLines-$window]]}
      {0-Delete 8-v} {$w.show yview [max [expr $first-$window+1] 0]}
      {9-less} {$w.show yview 0}
      {9-greater} {$w.show yview [max [expr $numLines-$window] 0]}
      {0-Escape 4-g} {set manx(lastkeys) ""; set manx(try) 0; manMessage $w ""}
      {4-l} {$w.show yview [max [expr $first-$window/2] 0]}
      {4-n} {$w.show yview [min [expr $first+1] [expr $numLines-$window]]}
      {4-p} {$w.show yview [max [expr $first-1] 0]}
      default {
         # incremental search
         if {$mk=="4-s"} {
            incr off; set manx(vect) 1; set manx(try) 1
         } elseif {$mk=="4-r"} {
            incr off -1; set manx(vect) -1; set manx(try) 1
         } elseif {$firstmode} {
            set manx(lastkeys) $k
         } elseif {$manx(try)} {
	    append manx(lastkeys) $k
         } else return

         if {$firstmode} {
            set curline 0
         } else {
            set curline [lindex [$w.vsb get] 2]
            manMessage $w "Searching for \"$manx(lastkeys)\" ..."; update idletasks
         }
         if {[set keys $manx(lastkeys)]==""} return

         set klen [string length $keys]
         set found -1
         for {set i [expr $curline+$off]} {$minele<=$i && $i<=$numLines} {incr i $manx(vect)} {
            if {$firstmode} {
               if {"$keys"=="[$w.show get $i.0 $i.$klen]"} {set found 0; break}
            } elseif {!$man(incr,case)} {
               if {[set found [string first [string tolower $keys] \
                  [string tolower [$w.show get $i.0 "$i.0 lineend"]]]]!=-1} \
                  break;
            } elseif {[set found [string first $keys [$w.show get $i.0 "$i.0 lineend"]]]!=-1} {
               break
            }
         }

         # show results
         if {$found!=-1} {
            $w.show yview [expr $i-1]
            if {!$firstmode} {manMessage $w "\"$keys\" found on line $i"}
         } elseif {$mk=="4-s"} {
            $w.show yview 0
            manMessage $w "No more matches found; restarting search at top."
         } elseif {$mk=="4-r"} {
             $w.show yview $total
	    manMessage $w "No more match found; restarting search at bottom."
         } else {
            manMessage $w "\"$keys\" not found"
            # turn off searching once can't match what you have
            set manx(try) 0
         }
      }
   }
}



#--------------------------------------------------
#
# manQuit -- manage merging with old config file
# if passed name of save file, could put this into utils
#
#--------------------------------------------------

proc manQuit {w} {
   global man manx

   set man(geom) [wm geometry $w]
   set nfn [glob ~/.tkman]
   set ofn [glob ~/.oldtkman]

   if {![file exists $nfn] || [file writable $nfn]} {
      if {[file exists $nfn]} {exec cp $nfn $ofn}
      set fid [open $nfn w]
      manSaveConfig $fid
      puts $fid $manx(userconfig)

      if {[file exists $ofn]} {
         set ofid [open $ofn]
         set p 0
         while {[gets $ofid line]!=-1} {
            if {$p} {puts $fid $line} \
            elseif {$manx(userconfig)=="$line"} {set p 1}
         }
      }
      close $fid
   }

   destroy .
   # don't delete ~/.oldtkman
}



#--------------------------------------------------
#
# manSaveConfig -- dump persistent variables into passed file id
#
#--------------------------------------------------

proc manSaveConfig {fid} {
   global man manx

# if only persistent stuff in man array,
# could have general SaveConfig in utils.tcl

   puts $fid "#\n# TkMan v$manx(version)\n#\n"
   foreach i [lsort [array names man]] {
      puts $fid "set man($i) {$man($i)}"
   }
   puts $fid "\n"
}




### start up

if $manx(tki) {
set tkiEmbed 1
source $manx(lib)/tkinfo.tcl
source $manx(lib)/topgetopt.tcl
}


# process command-line args

foreach i $argv {
   case $i in {
      -v {puts stdout "TkMan v$manx(version)"; exit 0}
      -icon* {set man(iconify) 1}
      -d* {set manx(debug) 1}
      default {
         after 2000 manShowMan $i {{}} .man
         # permit several???
         break
      }
   }
}



wm withdraw .
TkMan
#tkwait visibility .man
update idletasks

if {$manx(debug)} {
   puts stdout "init takes [time manInit]"
} else {

   set manx(tmp) $manx(lastMessage)
   manMessage .man "Reading Volumes ... "
   manInit

   .man.vols.m delete 0 last
   set ctr 0
   foreach i $manx(manList) {
      .man.vols.m add command -label "($i) [lindex $manx(manTitleList) $ctr]" \
         -command "manShowSection .man $i"
      incr ctr
   }
   manMessage .man $manx(tmp)
}




# debugging

if {$manx(debug)} {
   entry .man.in -relief sunken -textvariable manx(debugcmd)
   emacsbind .man.in
   bind .man.in <KeyPress-Return> {manMessage .man "[eval $manx(debugcmd)]"}
   pack append .man .man.in {top fillx}
}
