#! /bin/sh
# the next line restarts using wish \
exec /usr/bin/wish4.2 $0 ${1+"$@"}
set manx(version) 1.8
set manx(mintcl) 7.5
set manx(mintk) 4.1
set manx(newuser) ""
set manx(dirnameindex) 3
set man(zcat) "gzip -dcfq"
set man(compress) "gzip -q"
set man(apropos) {man -k}
set man(glimpse) ""
set man(glimpseindex) ""
set man(glimpsestrays) /tmp
set man(format) {groff -Tascii -te -mandoc}
set manx(manpathdef) ""
set man(printers) ""
set man(print) {groff -man -Tps -te -l}
set man(zlist) {gz z Z}
set man(egrep) egrep
set man(sed) sed
set man(rm) rm
set man(chmod) chmod
set man(mkdir) mkdir
set man(sort) sort
set man(uniq) uniq
set man(database) $env(HOME)/.tkmandatabase
set man(mv) mv
set man(cp) cp
set manx(rman) rman
set man(catprint) lpr
set man(catsig) {cat[^/]+(/[^/]+)?$}
set man(shortnames) 0
set man(dpis) {* 75 100}
set manx(changes) {
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 (698 lines, including instructions)
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 since it's so slow (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
28	deleted "focus $w.show" at very end of proc TkMan.  otherwise if start up iconified, then deiconify before done with init, text window doesn't show up. It's the focus problem again.  (David Svoboda)
29	"update, don't quit" (Gordon Lack & Lord Wodehouse)
1 Jul	lengthier criteria for picking which to show from list of matches (Michael Moore and Kwo-Long Lai)
14	option not to move change bars, apropos filter in variable (both Warren Jessop)
18	manKeyNav's key bindings to variables (David Sibley; thanks Wayne Christopher)
	moved Paths, added `All' to Volumes (Neal McBurnett, friend of Scott Schwartz)
	option to save nroff-formatted version (Warren Jessop)
24	margins around text box (colleague of Gordon Lack)
26	character to indicate popup menu (too bulky and unaesthetic, though)
27	keep list of man pages with dots--startup takes a couple more seconds (Warren Jessop)
4 Aug	check to see if man page source is older than nroff (Warren Jessop)
	C-s C-s retrieves last search pattern, as in Emacs
5	multiple instantiations share menu windows--sabotaged by new requirement in Tk 3.3
6	each instance gets own set of variables
	`|command' syntax for arbitrary text-generating command, `<file' syntax for reading raw file
	uses SearchBox mega widget
8	file name completion (if had fast database could do man page name completion and spelling correction)
11	user annotations (first cool new idea since March!) (could have set of different annotations but would that be useful?) (automatically jump to first highlight?)
17	mandesc-like directory dance hall (clamored for by Oyvind Yrke)
	>2000 lines, 70K characters, despite kicking generally useful code into taputils.tcl
	decision: don't integrate tkinfo (it could use the searchbox megawidget, though)
20	changes to tkmandesc (Oyvind Yrke)
21	SGI support worked out (Paul Raines)
13 Sep	greater control of ordering of added (pseudo) volumes (Paul Raines)
15	submitted to comp.sources.testers
	>80K characters
20	fixed printing of .so pages (Larry Virden)
21	various parts of ui disabled for different text box content types
28	1.5 review version available via comp.sources.testers
7 Oct	iconposition, -nosave, tkmangeometry (Chris Siebenmann)
12	reviews received from comp.sources.testers
	C-d/C-m hot keys (Kwo-Long Lai)
	variety of small changes suggested by the anonymous reviewers
	removed gzip requirement for H-P
	if main window owns X selection, zap it before showing another page
13	taking advantage of bs2tk's new reverse compile, do this for cat page printouts
	show hot spot on a single click (many, Robert Wilensky first)
	more small changes suggested by reviewers
	killing TkMan with window manager's kill removes process
21	>90K characters
24	highlights for symbolic links resolved to physical file
2 Nov	1.5 released for Tcl 7.0/Tk 3.3
24 Dec	TKMAN environment variable sets usual options



1994
1 Jan	support for LANG environment variable (Yasuro Kawata)
21	support for saving to H-P's cat.Z (w/o .Z/.gz/.z suffix)
28	fixed deep weirdness, write protected home directory bugs (Dave Glowacki)
1 Apr	first anniversary
12 May	list of all man pages with highlights (Steven S. Dick)
23	help page maintained in HTML, compiled to Tk text and [tn]roff (can zap linebreaks so get good linebreaking on all screen sizes!)
5 Jun	would like to use idiom like: menubutton -menu [set m [menu $w.x.m]], but have to do this: set m $w.x.m; menubutton -menu $m; menu $m
6 Aug	experiment in moving database to Glimpse
10	compressed list of all man page names works great: < 40K in size (with gzip), quick to search (preserves pattern matching), since kept on disk reduces startup time and memory image runs off tkmandesc orderings so can still do wild additions, section dumps efficient
24	search within virtual sections too
	finds names with dots (again)
26	incremental search highlights match
	try to find needed binaries beforehand, abort if can't (Keith Vetter among others)
1 Sep	support for weird /etc/man.conf (Shannon Jaeger)
	dynamically change font dpi
4	handle .so links to compressed pages (grr)
6	validity checks on components of MANPATH
9	hookup with Glimpse for fulltext search only (& optionally)
12	1.6beta testing
16	glimpse AND apropos, both now dumping results into a pseudo volume
	Perl's out, only Tcl for formatting volumes... sigh
17	automatically rebuild database every month
22	if current mandir != mandir used to build database, automatically rebuild it
26	automatically rebuild database if change in MANPATH or tkmandesc commands
27	-rebuildandquit option (Dietmar Theobald)
	instead of monthly rebuilds, simply check dates of mandirs--it takes a noticable amount of time, but not excessively long (Dietmar Theobald)
29	Volume lists dynamically created, once again controlled by Paths (push from Kevin L. Short)
	database validity check information moved into .tkmandatabase
30 Sep	1.6gamma testing
7 Oct	use simple priority number to choose better the right manual page (why didn't I think of this before?)
31 Oct	list of new/changed manual pages, if any, as pseudovolume
	when looking at header&footer, show date of file also
7 Nov	support for keeping Solaris 1, 1b, 1c, ... volumes separate (Will C Lauer)
10&11	preferences panels (code now >100K characters, >3000 lines)
21	Support for proposed Linux FSSTND /var/catman
23	deep-six the problematic mandir variable and suck up all unique names in manN*/* and catN*/* assuming they're in manN*/* => takes to long to build database
25	abolished mandir variable (which so many didn't set correctly)
	if no manN, check for catN automatically.  lose on stray cats, though
29	manDescAdd also makes that directory available to Glimpse
	Tcl code indention: spaces => tabs, saving 9K
7 Dec	1.6delta testing
8	IBM AIX support: first need to convert InfoExplorer files to /usr/man/cat*. can't parse pages (so don't), so lose on Sections, Links.  but everything else OK
9	restored SGI support (oops!)
15	bad variable values in old save file automatically updated (Martin Forssen & Greg McFarlane)
17	"(none)"'s changed to -state disabled's (don't have someone try it and fail)
20	pulldown menus shrink as necessary to fit on screen, if possible (Marty Leisner)
22	Winter Solstice: 1.6 released for use with RosettaMan + new database
	(100th RCS revision, 3628 lines)
24	updated for Tcl 7.4/Tk 4.0
29	new idiom for menubuttons + menus



1995
1 Jan	time to display page once found cut by more than a third by (1) changing while {[gets $fid line]!=1} {eval $line} to while {![eof $fid]} {eval [gets $fid]} and (2) hacking tkText.c to accept multiple (text,tags+mark) pairs
20	right pseudosection set for Shortcuts
24 Mar	tweaks to Glimpse, site-wide installation (John Talintyre)
25	changes for Tk 4.0b3: tk colormodel, -nocase (grr, no easy marks for text widget)
1.7b1	released for Tcl 7.4b3/Tk 4.0b3
26 Apr	chmod a+r for Glimpse indexes (except those in one's home directory) (Jim Ingham)
29 Jun	1.7b2 released for Tcl 7.4b4/Tk 4.0b4
30	1.7b3 released to fix some egregious bug or something
21 Jul	1.7 released for Tcl 7.4/Tk 4.0
	Preferences' Defaults button applies to current panel only (Don Libes)
26	1.7.1 released, advertised widely
1 Aug	miscellaneous small fixes, columns for apropos
	>4000 lines (happened sometime earlier)
	1.7.2 released to fix problem in passing command line options
9	added manDescSGI to place catman directories into user-added volumes according to user-specified patterns (Scott Nelson).  Is this a final solution to the SGI issue?
11	only reset gui if something changed in Preferences
	1.7.3b2 advertised to SGI users
18	option to present subvolumes as submenus under Volumes (original version by Nigel Wade)
	1.7.3 released
24	special case for `whatis' file check on dumb BSDI (John Carroll)
10 Oct	1.7.4 released
2 Nov	1.7.5 released
2 Dec	compensate for varying behavior of sed from flavor to flaver (Vin Shelton)
20	place man page name in window title (Simon Blanchard)



1996
16 Jan	option for unified Glimpse index
31	fix up picking right file when have match both with and without extensions (Carl Mascott)
6 Feb	small changes to take advantage of new features in Tcl 7.5/Tk 4.1 (foreach, tag prevrange)
11	use clock command instead of exec date
12	final comb through of code to clean up any lingering cruft
	take links from manref tags, fixed manBinCheck on fully-specified paths
20	fixed man.conf support (Hagen Finley)
1 Apr	statistics and information screen
26	fix check for out of date Glimpse indexes (Vinnie Shelton)
13 May	option for single-click hyperlinks (someone in CS160--identify yourself for an acknowledgement)
26	try to reattach highlights to right positions when man page changes
27	5000 lines
 3 Jun  searches give warning before wraparound (Rick Macdonald)
20	choose print destination from a list of printers (Peter Maguire)
23	menu of command line options in each section (maybe not such a good idea after all)
10 Jul  automatically set special case bindings files for virgins on Solaris, SGI, SCO
16	fixed bug related to find and the recent page list that caused inordinately long database build times on some systems (Vinnie Shelton)
19	cumulative statistics recording without afffecting other persistent settings
 5 Oct  dispense with stray cats problem by groking man and cat directories for pages (with only a slight increase in database build time)
22	speed up SGI startup (Paul Raines)
 7 Nov	1.8 released



Contemplated

direct translation from source using RosettaMan 3.0
dispense with cached database on disk, if Tcl 8.0's complier is fast enough to construct this at startup and search it, and it doesn't take an inordinate amount of memory
have multiple pages cached in memory in text widgets, repack and use interp alias to point to current one
support "page name#search string" syntax for manShowMan
integrate preferences into help page?
}
proc manHelpDump {t} {
   $t insert end {A bird?  A plane?  TkMan!  (TkPerson?)

 by Tom Phelps 

implemented in John Ousterhout's Tcl 7.5/Tk 4.1, icon drawn by Rei Shinozuka
 Compatible with Sun Solaris, SunOS, Hewlett-Packard HP-UX, OSF/1 aka Digital UNIX, DEC Ultrix, AT&T System V, SGI IRIX, Linux, SCO, IBM AIX, FreeBSD, BSDI -- each of which, believe you me, is in some way different from all the others 

Copyright (c) 1993-1996  Thomas A. Phelps
 All Rights Reserved.
 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 ftp.cs.Berkeley.EDU in the /ucb/people/phelps/tcltk directory. 

PERMISSION IS GRANTED TO DISTRIBUTE THIS SOFTWARE FREELY, WITH THE EXCEPTION THAT ONE MAY NOT CHARGE FOR IT OR INCLUDE IT WITH SOFTWARE WHICH IS SOLD. Walnut Creek, O'Reilly -- this means you too! 

Before reporting a bug, first check the home site to make sure you're using the latest version  of TkMan.  If you send me bug reports and/or suggestions for new features, include your MANPATH, the versions of TkMan, Tcl, Tk, X, and UNIX, your machine and X window manager names, the edited Makefile, a copy of your ~/.tkman file,  and the first few lines of the tkman executable.  Otherwise don't waste my time. 


Introduction

"I encourage you to use TkMan for reading man pages. ... TkMan provides an extremely pleasant GUI for browsing man pages.  I cannot describe all the nice features of TkMan in this small space.  Instead I will merely say that I now actually look forward to reading man pages as long as I can do it with TkMan."
 -- Don Libes, Exploring Expect, page 21 

A graphical manual page browser, TkMan offers two major advantages over man and xman: hypertext links to other man pages (click on a word in the text which corresponds to a man page, and you jump there), and better navigation within long man pages with searches (both incremental and regular expression) and jumps to section headers.  TkMan also offers some convenience features, like a user-configurable list of commonly used man pages, a one-click printout, and integration of whatis and apropos. Further, one may highlight, as if with a yellow marker, arbitrary passages of text in man pages and subsequently jump directly to these passages by selecting an identifying excerpt from a pulldown menu.  Finally, TkMan gives one control over the directory-to-menu volume mapping of man pages with a capability similar to but superior to xman's mandesc in that rather than forcing all who share a man directory to follow a single organization, TkMan gives control to the individual.  For instance,  or a Tcl/Tk programmer may decide to group Tcl/Tk manual pages in their own volume listing, or a nonprogrammer may decide he has no use for instance the programmer routines in volumes 2, 3, 4, 8--and eliminate them from his personal database. 

Other features include:
 * full text search of manual pages (with Glimpse; optional)
 * when multiple pages match the search name, a pulldown list of all matches
 * regular expression searches for manual page names
 * a list of recently added or changed manual pages
 * a "history" list of the most recently visited pages
 * a preferences panel to control fonts, colors, and other system settings
 * compatibility with compressed pages (both as source and formatted)
 * diagnostics on your manual page installation
 * elision of those unsightly page headers and footers
 * and, when attempting to print a page available only in formatted form, reverse compilation into [tn]roff source, which can then be reformatted as good-looking PostScript. 

This help page is shipped with the distribution in HTML form for easy printing. 


Using TkMan

Locating a man page

There are several ways to specify 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 the man button.  The name may be just the name of the command or may end with .n or (n), where n specifies in which section to look.  Man pages are matched using regular expressions, so you can use . to match any single character, * to match any (zero or more) of the previous regular expression, [ .. ] to match any single character in the enclosed class; see egrep for more information.  For instance, .*mail.*.1 searches section 1 (user commands) for commands with "mail" anywhere in their names. Likewise, one can collect all the various manual pages relating to Perl 5 with perl.*, or see a list of all X window managers with .*wm. 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 (which is man section name--that is, the section number comes first, whereas in TkMan it is part of the name. 

Usually TkMan searches the colon-separated list of directories in your MANPATH environment variable 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.  File completion is invoked with Escape. Further, other Tcl interpreters may display a man page in TkMan by sending a message to the function manShowMan with the name of the desired man page, e.g. send tkman manShowMan tcl.n.  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.  Return from reading help or a volume listing to the last man page seen with C-m when the focus is in the main text display area. 

apropos information is available by typing the name and clicking apropos or hitting Shift-Return.  The output of apropos is piped through sort and uniq to remove duplicates.  To pass the matches through additional filters, 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. The results of the last apropos query are available under the Volumes menu. 

If it's installed, you will see a button for glimpse, a full text search program that requires only small index files ("typically 2-5% the size of the original text" but larger percentages for smaller amounts of text),  written by Udi Manber, Sun Wu, and Burra Gopal of the University of Arizona's Department of Computer Science.  In their performance measurements, "a search for Schwarzkopf allowing two misspelling errors in 5600 files occupying 77MB took 7 seconds on a SUN IPC".  For example, one may search for the string `WWW' anywhere in any manual page by typing in `WWW' in the entry line at the top of the screen and clicking on the glimpse button or typing Meta-Return. Escape and C-g can interrupt a search after the current directory is done. To employ glimpse's command line options, simply place them before the search pattern in the entry box, or add them to the default options by editing the man(glimpse) variable in your ~/.tkman startup file (see Customizing TkMan, below). For instance, to search for "perl" as a word and not part of another word (as in "properly"), glimpse for -w perl. Glimpse supports an AND operation denoted by the symbol `;' and an OR operation denoted by the symbol `,'. Refer to the glimpse manual page for more information. The regular expression used by glimpse automatically sets the intrapage search  expression.  For this reason, the case sensitivity of the glimpsing is set to the same as intrapage regular expression searching. A complete set of matches from the last full text search is available under the Volumes menu. 

The Paths pulldown gives you complete control over which directory hierarchies of your MANPATH are searched for man pages and apropos information.  TkMan does not support "modules" of commands and their man pages that are dynamically added to and removed from a user's environment; instead, create the database with all potential modules, and control visibility with Paths.  You can call up a listing of all man pages in a volume through the Volumes pulldown menu and then select one to view by clicking on its name. New `pseudo-volumes' can be added, and arbitrary directories may be added to or deleted from a volume listing using tkmandesc commands, described below. In a volume listing, typing a letter jumps to the line in the listing starting with that letter (capital and lower case letters are distinct).  Return to the last volume seen with C-d when the focus is in the main text display area. 

Whenever you have a man page name in the text display box, whether from apropos, a volume listing or a reference within another man page, you can click on it to hypertext-jump to it.  In point of fact, man pages do not explicitly code man page references, but words that are especially likely to be references are distinguished, though any word may be clicked on to treat it as a man page reference.  Pressing shift while clicking opens up a new viewer box to display the page. 

The last few man pages you looked at can be accessed directly through the History pulldown menu.  The list is sorted top to bottom in order of increasing time since that page was last visited. Shortcuts lists your personal favorites and is used just like History, with the additional options of adding the current man page (by clicking +) or removing it (-) from the list.  A shift-click on - removes all shortcuts. 

(Man pages specified as above are processed through an nroff filter. TkMan can also read raw text from a file or from a command pipeline, which can then be read, searched and highlighted same as a man page.  To read from a file, make the first character in the name a <, as in <~/foo.txt.  To open a pipe, make the first character a | (vertical bar), as in `|gzcat foo.txt.gz' or `|cat ../foo.txt | grep bar' (that's no space after the first |, a space before and after any subsequent ones). After reading a file in this way, the current directory is set to its directory. Commands are not processed by a shell, but the metacharacters ., .., ~ and $ (for environment variables), are expanded nonetheless.  Typing is eased further by file name completion, bound to Escape.  Lone files (i.e., not part of a pipe) are automatically uncompressed--no need to read compressed files through a zcat pipe.  It is not expected that reading raw text will be done much; it is included so the occasional non-man page documentation, say, a FAQ or RFC, may be read from the same environment.) 


Working within a man page

The full pathname of the current manual page is shown at the top of the screen.  Via the Preferences dialog, this can be changed to the whatis information for the page. (whatis information is built by catman.) 

To the extent it follows conventional formatting, a manual 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 throughout the page including its SEE ALSO section (Links pulldown).   One may jump directly to a section within a man page or a referenced man page, respectively, by selecting the corresponding entry from one of these pulldowns. 

Within a man page or raw text file or pipe, you may add ad hoc highlighting, as though with a yellow marker (underlining on monochrome monitors).  Highlighted regions may then be scrolled to directly through the Highlights pulldown menu.  To highlight a region, select the desired text by clicking button 1, dragging to the far extent of the desired region and releasing the button, then click on the + next to Highlights.  To remove any highlights or portions thereof in a region, select it as before but then click on -.  A shift-click on the menu title tours through all the highlights on the page.  A shift-click on - removes all highlights on the page.  A complete set of pages with highlighting is available under the Volumes menu. 

Highlighting information is robust against changes to and reformatting of the page.  Thus you can justify expending some effort in marking up pages with the knowledge that if a man page does change, as when the corresponding software pagkage and its documentation are updated, TkMan will try to reposition them to the corresponding positions in the new pages. Here's how highlight reattachment works. When you highlight a region, the starting and ending positions are saved along with some the content of the highlighted region and context.   When that page is viewed again, if those positions still match the context, the highlight is attached there (this is an exact match).  If not, the context is searched forward and backward for a match, with the closer match chosen if there are matches in both directions (a repositioned match).   If no match is found with the full context, gradually less and less of it is tried,  reasoning that perhaps the content of the context has been changed (repositioned, but with less confidence, triggering a warning dialog). If still no match is found (an orphan), the highlight is reported at the bottom of the page, where it must be reattached manually before leaving the page or it will be forgotten.  (With TkMan v1.8b3 and earlier, highlights were attached by positions only, and when the page modification date changed, the user had the choice of applying  highlights at those same positions regardless of the text there now or throwing out the highlights wholesale.  Old style highlights are automatically updated to the new style that can be automatically and robustly repositioned.  The next time an old style page is viewed, the old style highlights are applied as before, and from those postions new style highlights are composed.)  The annotation reattachment mechanism is inspired by Stanford's ComMentor system. 

You can move about the man page by using the scrollbar or typing a number of key combinations familiar to Emacs aficionados.  Space and C-v page down; delete and M-v page up.  (vi fans will be happy to hear that C-f and C-b also page down and page up, respectively.) C-n and C-p scroll up and down, respectively, by a single line. M-< goes to the top and M-> to the bottom of the text.  One may "scan" the page, which is to say scroll it up and down with the mouse but without the use of the scrollbar, by dragging on the text display 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 an incremental search.  Subsequently typing a few letters attempts to find a line with that string, starting its search at the current match, if any, or otherwise the topmost visible line.   A second C-s finds the next match of the string typed so far.  (If the current search string is empty, a second C-s retrieves the previous search pattern.) C-r is similar to C-s but searches backwards. Escape or C-g cancels searching. Incremental search can be used to quickly locate a particular command-line option or a particular command in a group (as in csh's long list of internal commands). At the bottom of the screen, type in a regular expression to search for (see Tcl's regexp command), and hit return or click Search to begin a search.  Hit C-s, click the down arrow or keep hitting return to search for the next occurance; likewise C-r or the up arrow for previous occurances. 

The Tab key moves the focus from the man page type-in line to the text view of the man page to the search line and back around.  Shift-Tab jumps about in the opposite direction. 


Other commands

The Occasionals menu holds commands and options which you probably won't use frequently.  Help returns to this information screen.  Although virtually made obsolete by TkMan, Kill Trees makes a printout of the current man page on dead, cut, bleached trees, helping to starve the planet of life-giving oxygen.  A list of printers appears in the cascade menu; this list may be edited in Preferences/Misc.  (Even if only one printer is available, it placed in the cascade menu, rather than being directly available.  This is a feature.) (If the [tn]roff source is not available, TkMan asks if it should try to reverse compile the man page.  If successful, this produces much more appealing output than an ASCII dump.)  By default, incremental searching is not case sensitive, but regular expression searching is; these settings can be toggled with the next two menus.  iff upper means that searching is case sensitive if and only if there is at least one uppercase letter in the search expression--that is, all-lowercase searches are not case sensitive; this idea is taken from Emacs. With proportional fonts giving a ragged right margin, any change bars in the right margin will form an uneven line; by opting for Changebars on left, they will form a straight line at the left margin. 

As with xman one may instantiate multiple viewers.  When there is more than one viewer you may choose man pages in one viewer and have their contents shown in another.  Use the Output pulldown (which appears and disappears as relevant) to direct 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 particular volume listing or a SEE ALSO section.  Output only affects the display destination of man pages. 

TkMan uses a database of all manual page names in searching for a match for a particular name.  This database is constructed automatically if it doesn't exist (this includes the first time TkMan is run for a particular user) and whenever it is out of date due to pages being added or changed, or changes in one's MANPATH or tkmandesc commands.  (If you want to add paths to your MANPATH or edit ~/.tkman, you will have to restart to see any changes take effect, however.)  If you install new manual pages or otherwise change the contents of man page directories after TkMan as been started, invoking Rebuild Database will permit them to show up in the next search or volume listing without the bother of quitting and re-executing TkMan.  Rebuild Glimpse Database creates and then maintains the index that is used for full text searches.  The Glimpse database is not updated automatically due to the large amount of time it may take. 

When exited via the Quit button, TkMan saves its state.  One may guard against losing highlighting, shortcuts and other would-be persistent information without quitting by by invoking Checkpoint state to .tkman; Quit, don't update performs the opposite operation. 

At the bottom right corner of the screen, Mono toggles between the proportionally-spaced font and a monospaced one, for use in those man pages that rely on a fixed-width font to align columns.  Quit exits TkMan, of course, after saving some state information (see below).  To exit without saving status information, select the Quit option from the Occasionals pulldown. 


Preferences

The Preferences... choice in the Occasionals pulldown menu brings up a graphical user interface to setting various attributes of TkMan, including fonts, colors, and icons.  Click on a checkbutton at the top of the window to bring up the corresponding group of choices.  After making a set of choices, the Apply button reconfigures the running application to show these changes, OK sets the changes for use now and in the future, Cancel quits the dialog and sets all choices to their settings as of the time Preferences was called up, and Defaults resets the settings in the current group to those set by TkMan out of the box. 

The first line in the Fonts group specifies the font to use for the general user interface, which amounts to the labels on buttons and the text in menus.  The first menu in the line labeled Interface sets the font family, the next menu sets the font size, and the last the font styling (normal, bold, italics, bold-italics). Text display makes these settings for the text box in which the manual page contents are displayed.  For listings of all man pages in a particular volume (as chosen with the Volumes menu), you may wish to use a smaller font so that more names fit on the screen at once. Screen DPI specifies the right set of fonts to use for your monitor. 

Colors sets the foreground and background colors to use for the manual page text display box, the general user interface, and the buttons of the user interface.  In addition it sets the color (or font) in which to show various classes of text in the text box, including manual page references, incremental search hits, regular expression search hits, and highlighted regions. 

The See group specifies what information to display. Usually manual page headers and footers are uninteresting and therefore are stripped out, but a canonical header and footer (along the date the page was installed in the man/mann directory or formatted to the man/catn directory) to be shown at the bottom of every page can be requested.  Solaris and IRIX systems come with many "subvolumes"--that is volumes with names like "3x" and "4dm" that form subgroupings under the main volumes "3" and "4", respectively--and you make use tkmandesc commands to add your own subvolumes.  You can reduce the length of the main Volumes menu by placing all volumes in such groups as cascaded menus. When a highlighted passage is jumped to via the Highlights menu, some number of lines of back context are included; the exact number of lines is configurable.   The information bar at the top of the window can display either the short, one-line description from a manual page's NAME section or the pathname of the page.   Around the man page display area runs a buffer region of a few pixels, the exact width of  which is configurable. Tk deviates from Motif behavior slightly, as for instance in highlighting buttons when they're under the cursor, but you can observe strict Motif behavior. 

The Icon group sets all the options relating to iconification. The pathnames of the icon bitmap and icon mask should be the full pathnames (beginning with a `/').  If Path name to icon bitmap is set to (default), the internal icon by Rei Shinozuka will be used. 

If a man page has not been formatted by nroff, TkMan must first pipe the source text through nroff.  By turing on Cache formatted (nroff'ed) pages in the Misc(ellaneous) group, the nroff-formatted text is saved to disk (if possible), thereby eliminating this time-consuming step the next time the man page is read.  The on & compress setting will compress the page, which saves on disk space (often substantially as much of a formatted page is whitespace), but will make it unavailable to other manual pagers that don't handle compression.   

By default, man page links are activated by single clicking.  If it is changed to double with Mouse click to activate hyperlink, the first click puts the name in the entry box so that it can be used as the apropos or glimpse pattern as well as for man searching.  This click once to select, twice to launch follows the Macintosh convention. 

TkMan can extract section headers from all manual pages, but only some manual page macros format subsection headers in a way that can be distinguished from ordinary text; if your macros do, turn this option on to add subsections to the Sections menu. The History pulldown must balance depth of the list against ease of finding an entry; set your own inflection point with this menu.  Volumes' (recent) choice will show all manual pages that have been added or changed n days, where n is set with this next menu.   

Glimpse works best when searching for relatively uncommon words; guard against getting too many hits by setting the maximum number reported. By default Glimpse indexes are placed at the root of the corresponding man hierarchy, where they can be shared.  For the case when an individual may not have write permission there, a single, unified index can be created and stored locally (though you lose control of it from Paths settings). Unified indexes are faster than distributed.  On the other hand, rebuilding the index generally takes longer, since the distributed version will only have to rebuild the indexes for those directories that changed. For unified indexes and also for "stray cats" (i.e., directories not part of a set of man hierarchy directories), you should specify an auxiliary directory to hold the index. 


Customizing TkMan

There are four levels of configuration. 

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

(2) Preferences editor (see Preferences above). 

(3) Configuration file.  Most interesting settings--those  in the Preferences dialogs and more not available there--can be changed by editing one's own ~/.tkman file.  Thus, a single copy of TkMan (i.e., the executable tkman) can be shared, but each user can have his own customized setup.  (The file ~/.tkman is created/rewritten every time one quits TkMan via the Quit button in the lower right corner.  Therefore, to get a ~/.tkman to edit, first run and quit TkMan.  Do not create one from scratch as it will not have the proper format used for saving other persistent information, and your work will be overwritten, which is to say lost.  As well, be careful not to edit a ~/.tkman file only to have it overwritten when a currently running TkMan quits.) 

Options that match the defaults are commented out (i.e., preceded by a #).  This is so that any changes in TkMan defaults will propagate nicely to end users, while maintaining a list of all interesting variables. To override the default settings for these options, first comment in the line. 

The ~/.tkman save file is the place to add or delete colors to the default set, which will subsequently become menu choices in Preferences, by editing in place the variable man(colors).  One may also edit the order of Shortcuts in the man(shortcuts) variable. Other interesting variables include man(highlight), which can be edited to change the background in place of the foreground, or both the foreground and background, or a color and the font as with the following setting:
set man(highlight) {bold-italics -background #ffd8ffffb332} 

Arbitrary Tcl commands, including tkmandesc commands (described below), can be appended to ~/.tkman (after the ### your additions go below line). 

To set absolutely the volume names for which all directories should be searched, edit the parallel arrays on these existing lines:
set man(manList) ...
set man(manTitleList) ...
 Changing the order volumes in these lists (make sure to keep the two lists in parallel correspondence) changes the precedence of matches when two or more pages have the same name: the page found in the earlier volume in this list is show first. 

Additional useful commands include wm(n), which deals with the window manager; bind(n), which changes keyboard and mouse bindings not related to the text display window; options, which sets the X defaults; and text(n), which describes the text widget. 

(4) 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. 


Command line options

 The environment variable named TKMAN, if it exists, is used to set command line options.  Any options specified explicitly (as from a shell or in a script) override the settings in TKMAN. Any settings made with command-line options apply for the current execution only. Many of these options can be set persistently via the Preferences dialog (under the Occasionals menu). 

-title title 
      Place title in the window's title bar. 

-geometry geometry 
      Specify the geometry for this invocation only.  To assign a persistent geometry, start up TkMan, size and place the window as desired, then (this is important) quit via the Quit button in the lower right corner. 

-iconify and -noiconify 
      Start up iconified or uniconified (the default), respectively. 

-iconname name 
      Use name in place of the uniconified window's title for the icon name. 

-iconbitmap bitmap-path and -iconmask bitmap-path 
      Specify the icon bitmap and its mask. 

-iconposition (+|-)x(+|-)y 
      Place the icon at the given position; -iconposition "" "" cancels any such hints to the window manager. 

-debug or -nodebug 
      Generate (or not) debugging information. 

-startup filename 
      Use filename in place of ~/.tkman as the startup file; "" indictates no startup file. 

-database filename 
      Use filename in place of ~/.tkmandatabase as the name of the file in which to create the database of man page names.  This can point to a shared file to save disk space or share a custom design, or to an OS-specific file for systems with multiple machine architectures that share home directories. 

-rebuildandquit 
      Simply rebuild the database and quit.  This option may be useful in a cron script. 

-quit save and -quit nosave 
      Specify that the startup file (usually ~/.tkman) should be updated (save) or not (nosave) when quitting by the Quit button. 

-v 
      Show the current version of TkMan and exit immediately thereafter. 

-M path-list
 or -M+ path-list
 or -+M path-list 
      As with man, change the search path for manual pages to the given colon-separated list of directory subtrees.  -M+ appends and -+M prepends these directories to the current list. 

-now 
      Start up TkMan without checking to see if the database is out of date. 

--help Display a list of options. 
       


Key bindings

Key bindings related to the text display box are kept in the sb array in ~/.tkman (for more information on Tcl's arrays, refer to the array(n) man page.  In editing the sb(key,...) keyboard bindings, modifiers MUST be listed in the following order: M (for meta), C (control), A (alt).  DO NOT USE SHIFT.  It is not a general modifier: Some keyboards require shift for different characters, resulting in incompatibilities in bindings.  For instance, set sb(key,M-less) pagestart is a valid binding on keyboards worldwide, whereas set sb(key,MS-less) is not.  For this reason, the status of the shift key is supressed in matching for bindings.  To make a binding without a modifier key, precede the character by `-', as in set sb(key,-space) pagedown. 


tkmandesc

Like xman, TkMan gives you directory-by-directory control over named volume contents.  Unlike and superior to xman, however, each individual user controls directory-to-volume placement, rather than facing a single specification for each directory tree that must be observed by all. 

By default a matrix is created by taking the product of directories in the MANPATH crossed with volume names, with the yield of each volume containing all the corresponding subdirectories in the MANPATH.  By adding Tcl commands to your ~/.tkman (see above), you may add new volume names and add, move, copy and delete directories to/from/among directories. 

The interface to this functionality takes the form of Tcl commands, so you may need to learn at least pidgin Tcl--particularly the commands that deal with Tcl lists  (including lappend(n), linsert(n), lrange(n), lreplace(n)) and string matching (string(n), match subcommand)--to use this facility to its fullest.  tkmandesc commands are used to handle the nonstandard format of SGI's manual page directories, and the irix_bindings.tcl in the contrib directory is a good source of examples in the use of tkmandesc commands. 

Directory titles and abbrevations are kept in lists.  Abbreviations MUST be unique (capital letters are distinct from lower case), but need not correspond to actual directories.  In fact, volume letters specified here supercede the defaults in identifying a volume in man page searches. 


COMMANDS

The following commands are appended to the file ~/.tkman (see Customizing TkMan, above). 

To recreate a cross product of current section lists:
manDescDefaults
 This cross product is made implicitly before other tkmandesc commands. Almost always this is what one expects.  If it is not, one may supress the cross product by setting the variable manx(defaults) to a non-null, non-zero value before other tkmandesc commands are invoked. 

To add "pseudo" sections to the current volume name list, at various positions including at end of the list, in alphabetical order, or before or after a specific volume:
manDescAddSects list of (letter, title pairs)
 or manDescAddSects list of (letter, title) pairs sort
 or manDescAddSects list of (letter, title) pairs before sect-letter
 or manDescAddSects list of (letter, title) pairs after sect-letter
 In manual page searches that produce multiple matches, the page found in the earlier volume is the one shown by default. 

To move/copy/delete/add directories:
manDescMove from-list to-list dir-patterns-list
manDescCopy from-list to-list dir-patterns-list
manDescDelete from-list dir-patterns-list
manDescAdd to-list dir-list 

The dir-patterns-list uses the same meta characters as man page searching (see above).  It is matched against MANPATH directories with volume subdirectory appended, as in /usr/man/man3, where /usr/man is a component of the MANPATH and man3 is a volume subdirectory. from-list and to-list are Tcl lists of the unique volume abbreviations (like 1 or 3X); * is an abbreviation for all volumes. 

Adding directories with manDescAdd also makes them available to Glimpse for its indexing. 

Warning: Moving directories from their natural home slightly impairs searching speed when following a reference within a man page.  For instance, say you've moved man pages for X Windows subroutines from their natural home in volume 3 to their own volume called `X'.  Following a reference in XButtonEvent to XAnyEvent(3X11) first searches volume 3; not finding it, TkMan searches all volumes and finally finds it in volume X.  With no hint to look in volume 3 (as given by the 3X11 suffix), the full volume search would have begun straight away.  (Had you clicked in the volume listing for volume X or specified the man page as XButtonEvent.X, volume X would have been searched first, successfully.) 

To help debug tkmandesc scripts, invoke manDescShow to dump to stdout the current correspondence of directories to volumes names. 


EXAMPLES

(1) To collect together all man pages in default volumes 2 and 3 in all directories into a volume called "Programmer Subroutines", add these lines to the tail of ~/.tkman:
manDescAddSects {{p "Programmer Subroutines"}}
manDescMove {2 3} p * 

To place the new section at the same position in the volume pulldown list as volumes 2 and 3:
manDescAddSects {{p "Programmer Subroutines"}} after 2
manDescMove {2 3} p * 

To move only a selected set of directories:
manDescAddSects {{p "Programmer Subroutines"}}
manDescMove * p {/usr/man/man2 /usr/local/man/man3} 

(2) To have a separate volume with all of your and a friend's personal man pages, keeping a duplicate in their default locations:
manDescAddSects {{t "Man Pages de Tom"} {b "Betty Page(s)"}}
manDescCopy *phelps* t *
manDescCopy *page* t * 

(3) To collect the X windows man pages into two sections of their own, one for programmer subroutines and another for the others:
manDescAddSects {{x "X Windows"}} after 1
manDescAddSects {{X "X Subroutines"}} after 3
manDescMove * x *X11*
manDescMove x X *3 

(4) If you never use the programmer subroutines, why not save time and memory by not reading them into the database?
manDescDelete * {*[2348]} (braces prevent Tcl from trying to execute [2348] as a command) 

Alternatively but not equivalently:
manDescDelete {2 3 4 8} * 


tkmandesc vs. xman and SGI

TkMan's tkmandesc capability is patterned after xman's mandesc files.  By placing a mandesc file at the root of a man page directory tree, one may create pseudo volumes and move and copy subdirectories into them.  Silicon Graphics has modified xman so that simply by creating a subdirectory in a regular man subdirectory one creates a new volume.  This is evil.  It violates the individual user's rights to arrange the directory-volume mapping as he pleases, as the mandesc file or subdirectory that spontaneously creates a volume is must be observed by all who read that directory.  By contrast, TkMan places the directory-to-volume mapping control in an individual's own ~/.tkman file. This gives the individual complete control and inflicts no pogrom on others who share man page directories.  Therefore, mandesc files are not supported in any way by TkMan. 

One may still share custom setups, however, by sharing the relevant lines of ~/.tkman.  In fact, a tkmandesc version of the standard SGI man page directory setup is included in the contrib directory of the TkMan distribution.  For assistance with SGI-specific directory manipulation, contact Paul Raines (raines@slac.stanford.edu). 


Platform-specific Support

I estimate that fully 75% of my time writing TkMan has been spent not in adding new features but in supporting all the many, seemingly gratuitous differences in the various flavors of UNIX.  Amazingly, each is different from every other.  TkMan confronts variations in man page organization, that is, directory structure.  The same percentage holds for RosettaMan, which deals with variations in the formatting of the pages themselves, things like what character sequence indicates italics and what do page headers and footers look like.  The result of all this work is that you can do a simple installation of TkMan and it will embrace the specifics of your system's manual page installation. 

Here's the classical organization.  The MANPATH environment variable gives a colon-separated list of directory paths, each of which usually but not necessarily ends in a subdirectory named `man'. In each of these directories, the file `whatis' has a line per man page giving its name and a single line description taken from each page's NAME section.  Subdirectories named man[1-9oln] hold the [tn]roff source, and corresponding subdirectories named cat[1-9oln] cache formatted pages.  Within subdirectories, each page given as name.section-number, for example "ls.1".  The page source should always be available; formatted versions are purely optional, and strictly used as a performance enhancement, saving formatting time at runtime.  (Pages that exist in formatted versions only are known as "stray cats".)  Man pages may be compressed, with the type of compression given by a suffix on the file.  Compression can be particularly successful on formatted pages, which contain long strings of spaces. 

Here are all the ways that I can recall that various flavors of UNIX have "improved" the classical organization.  Each is supported by TkMan.  Clearly TkMan can do all that it does without reliance on any extension beyond the classical organization, so how important were these extensions? 

SunOS 
   + Just great! 

Solaris 
   + Renaming of `whatis' to `windex', which has an extra field 
   + Nonstandard directory names, e.g., `man1s'. 

Ultrix 
   + Just great (nonstandard tabs in formatted man pages handled by RosettaMan). 

OSF/1 aka Digital UNIX 
   + Just great ("missing" headers and footers in formatted pages handled by RosettaMan). 

HP/UX 
   + Compressed page files listed without .Z, which is on its enclosing directory 
   + Concatenates all whatis information into /usr/lib/whatis 

SCO 
   + /etc/default/man configuration file 

FreeBSD 

Linux 
   + /etc/man.config configuration file 
   + FSSTND 

BSDI 
   + Concatenation of all `whatis' files into a single /usr/share/man/whatis.db 
   + Formatted pages given suffix ".0" 
   + /etc/man.conf configuration file 

IBM AIX 
   + Have to convert help files from opaque InfoExplorer format to standard /usr/man format. 
   + Have to prevent man pages from being parsed, since they are just simple ASCII files,  only vaguely resembling man pages 

SGI Irix - absolute worst by far 
   + Only pre-formatted pages in /usr/catman 
   + Consequently, doesn't have [tn]roff 
   + Man sub-subdirectories magically appear as own volumes, with names hidden in their hacked version of xman 
   + Stray cats by default (installs formatted pages only) 
   + Page files named without section but with .z 


RosettaMan

TkMan uses RosettaMan to translate and reformat man pages (see man(5)). RosettaMan (called rman in its executable form)  takes man pages from most of the popular flavors of UNIX and transforms them into any of a number of text source formats.  Since its inception RosettaMan accepted formatted pages, and now with version 3.0 interprets [tn]roff source for superior translations. RosettaMan accepts man pages from SunOS, Sun Solaris, Hewlett-Packard HP-UX, AT&T System V, OSF/1 aka Digital UNIX, DEC Ultrix, SGI IRIX, Linux, FreeBSD, SCO.  It can produce ASCII-only, section headers-only, TkMan, [tn]roff (source), Ensemble, SGML, HTML, MIME, LaTeX, LaTeX2e, RTF, Perl 5 POD.   A modular architecture permits easy addition of additional output formats.  The latest version of RosettaMan is available from  ftp://ftp.cs.berkeley.edu/ucb/people/phelps/tcltk/rman.tar.Z. 


Author

Tom Phelps
 developed at the
 University of California, Berkeley
 Computer Science Division 

phelps@ACM.org 


More Information

 My article "TkMan: A Man Born Again" appears in The X Resource, issue 10, pages 33--46.  Here are the section titles: Introduction, Availability, The User Interface, Navigating among Man Pages, Inspecting Individual Man Pages, Customization, Logical Volumes with tkmandesc, Persistency, The RosettaMan Filter, Extensions, Problems, Future Work, Acknowledgements, Bibliography. 

Two Years with TkMan, a retrospective paper that uses TkMan as an example for various techniques for writing faster and more robust Tcl/Tk programs, was named Best Paper of the 1995 Tcl/Tk Workshop. 

A Berkeley Computer Science Division technical report (CSD-94-802) that is a version of the X Resource article before it was butchered by the editors and the latter paper are available from my World Wide Web page at http://http.cs.berkeley.edu/~phelps/. 


License

TkMan
 Copyright (C) 1993-1996  Thomas A. Phelps  (phelps@ACM.org)
 All Rights Reserved. 

PERMISSION IS GRANTED TO DISTRIBUTE THIS SOFTWARE FREELY, WITH THE EXCEPTION THAT ONE MAY NOT CHARGE FOR IT OR INCLUDE IT WITH SOFTWARE WHICH IS SOLD.  Permission to use, copy, modify, and distribute this software and its documentation for educational, research, internal corporate and non-profit purposes, without fee, and without a written agreement is hereby granted for all cases that do not conflict with the restriction in the first sentence of this paragraph, provided that the above copyright notice, this paragraph, and the following three paragraphs appear in all copies. 

Permission to incorporate this software into commercial products may  be obtained from the Office of Technology Licensing, 2150 Shattuck  Avenue, Suite 510, Berkeley, CA  94704.  

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. 

Help page last revised on $Date: 1996/11/07 23:11:49 $
}
foreach qq {{h1 1.0 1.38} {sc 14.61 14.64} {tt 14.68 14.87} {tt 14.95 14.119} {sc 16.0 16.150} {tt 18.315 18.323} {tt 18.362 18.367} {h1 21.0 21.12} {i 24.15 24.31} {manref 26.72 26.75} {manref 26.80 26.84} {manref 26.479 26.485} {manref 26.490 26.497} {tt 26.836 26.840} {h1 43.0 43.11} {h2 45.0 45.19} {tt 47.139 47.145} {tt 47.159 47.162} {tt 47.233 47.234} {i 47.234 47.235} {tt 47.239 47.240} {i 47.240 47.241} {tt 47.241 47.242} {i 47.250 47.251} {tt 47.353 47.354} {tt 47.386 47.387} {tt 47.452 47.453} {tt 47.457 47.458} {manref 47.516 47.521} {manref 47.559 47.569} {manref 47.734 47.740} {manref 47.786 47.790} {tt 47.1003 47.1006} {tt 47.1025 47.1028} {i 47.1029 47.1036} {i 47.1037 47.1041} {sc 49.71 49.78} {tt 49.197 49.200} {tt 49.202 49.205} {tt 49.207 49.210} {tt 49.214 49.218} {sc 49.284 49.291} {tt 49.340 49.346} {manref 49.363 49.366} {tt 49.415 49.419} {tt 49.449 49.459} {tt 49.504 49.531} {sc 49.622 49.629} {tt 49.795 49.798} {tt 51.0 51.7} {tt 51.65 51.72} {tt 51.113 51.120} {tt 51.138 51.142} {tt 51.147 51.151} {tt 51.266 51.282} {tt 51.390 51.391} {tt 51.455 51.462} {tt 53.45 53.52} {tt 53.643 53.650} {tt 53.668 53.679} {tt 53.681 53.687} {tt 53.692 53.695} {tt 53.766 53.773} {tt 53.910 53.922} {tt 53.940 53.948} {tt 53.1100 53.1107} {tt 53.1129 53.1132} {tt 53.1165 53.1168} {tt 53.1176 53.1178} {tt 53.1211 53.1214} {manref 53.1229 53.1236} {tt 53.1302 53.1309} {tt 53.1561 53.1568} {tt 55.4 55.9} {sc 55.87 55.94} {tt 55.367 55.372} {tt 55.442 55.449} {tt 55.850 55.853} {tt 59.74 59.81} {tt 59.193 59.202} {tt 59.255 59.262} {tt 59.336 59.337} {tt 59.355 59.356} {tt 59.391 59.392} {tt 61.55 61.60} {tt 61.268 61.269} {tt 61.277 61.287} {tt 61.333 61.334} {tt 61.358 61.375} {tt 61.381 61.407} {tt 61.442 61.443} {tt 61.635 61.636} {tt 61.638 61.640} {tt 61.642 61.643} {tt 61.648 61.649} {tt 61.764 61.770} {tt 61.886 61.890} {h2 64.0 64.25} {manref 66.136 66.142} {manref 66.201 66.207} {tt 68.156 68.164} {sc 68.248 68.256} {tt 68.266 68.271} {tt 70.212 70.222} {tt 70.401 70.402} {tt 70.411 70.421} {tt 70.520 70.521} {tt 70.620 70.621} {tt 70.724 70.731} {tt 74.136 74.139} {tt 74.162 74.165} {tt 74.177 74.179} {tt 74.212 74.215} {tt 74.220 74.223} {tt 74.267 74.270} {tt 74.275 74.278} {tt 74.331 74.334} {tt 74.355 74.358} {tt 74.586 74.593} {tt 74.664 74.667} {tt 74.741 74.744} {tt 76.0 76.3} {tt 76.214 76.217} {tt 76.317 76.320} {tt 76.361 76.364} {tt 76.379 76.382} {tt 76.407 76.413} {tt 76.417 76.420} {tt 76.564 76.567} {manref 76.686 76.692} {tt 76.727 76.733} {tt 76.758 76.761} {tt 76.850 76.853} {tt 78.4 78.7} {tt 78.129 78.138} {h2 81.0 81.14} {tt 83.4 83.15} {tt 83.90 83.94} {tt 83.175 83.185} {tt 83.542 83.550} {sc 83.702 83.707} {tt 83.866 83.875} {tt 83.1212 83.1230} {tt 85.8 85.12} {tt 85.177 85.183} {sc 85.472 85.480} {tt 85.491 85.497} {sc 87.313 87.320} {sc 87.379 87.386} {tt 87.395 87.403} {tt 87.600 87.616} {tt 87.738 87.762} {tt 89.20 89.24} {tt 89.184 89.210} {tt 89.212 89.230} {tt 91.42 91.46} {tt 91.194 91.198} {tt 91.327 91.331} {tt 91.348 91.359} {h2 94.0 94.11} {tt 96.4 96.18} {tt 96.33 96.44} {tt 96.305 96.310} {tt 96.378 96.380} {tt 96.429 96.435} {tt 96.538 96.546} {tt 98.190 98.199} {tt 98.325 98.337} {tt 98.499 98.506} {tt 98.595 98.605} {tt 102.223 102.230} {i 102.230 102.231} {tt 102.262 102.269} {i 102.269 102.270} {tt 102.618 102.625} {tt 102.736 102.746} {tt 104.167 104.191} {tt 104.202 104.211} {tt 106.40 106.45} {tt 106.93 106.98} {tt 106.114 106.146} {tt 106.181 106.186} {tt 106.320 106.333} {tt 108.94 108.127} {i 110.97 110.100} {tt 110.236 110.244} {tt 110.255 110.262} {tt 110.384 110.392} {tt 110.393 110.401} {i 110.468 110.469} {i 110.482 110.483} {h1 115.0 115.17} {tt 119.149 119.153} {tt 123.152 123.160} {tt 123.219 123.224} {tt 123.301 123.309} {tt 123.366 123.370} {tt 123.426 123.434} {tt 123.678 123.686} {tt 125.71 125.72} {tt 127.4 127.12} {b 127.143 127.159} {tt 127.173 127.184} {tt 127.235 127.249} {tt 127.296 127.310} {i 127.408 127.411} {i 127.435 127.438} {tt 128.0 128.59} {tt 130.91 130.99} {tt 130.111 130.138} {b 132.81 132.85} {b 132.115 132.123} {tt 133.0 133.20} {tt 134.0 134.25} {manref 137.35 137.40} {manref 137.79 137.86} {manref 137.170 137.177} {manref 137.210 137.217} {h2 142.0 142.20} {sc 144.32 144.37} {sc 144.182 144.187} {tt 144.355 144.366} {tt 146.0 146.7} {i 146.7 146.12} {tt 147.12 147.12} {i 147.12 147.17} {tt 149.0 149.10} {i 149.10 149.18} {tt 150.179 150.183} {tt 152.0 152.8} {tt 152.13 152.23} {tt 155.0 155.10} {i 155.10 155.14} {tt 156.10 156.10} {i 156.10 156.14} {tt 158.0 158.12} {i 158.12 158.23} {tt 158.28 158.38} {i 158.38 158.49} {tt 161.0 161.26} {tt 162.44 162.63} {tt 164.0 164.6} {tt 164.10 164.18} {tt 167.0 167.9} {i 167.9 167.17} {tt 168.10 168.10} {i 168.10 168.18} {tt 168.31 168.39} {tt 170.0 170.10} {i 170.10 170.18} {tt 171.10 171.10} {i 171.10 171.18} {tt 171.31 171.47} {tt 173.0 173.15} {tt 176.0 176.10} {tt 176.15 176.27} {tt 177.45 177.53} {tt 177.74 177.78} {tt 177.88 177.94} {tt 177.117 177.121} {tt 179.0 179.2} {tt 182.0 182.3} {i 182.3 182.12} {tt 183.4 183.8} {i 183.8 183.17} {tt 184.4 184.8} {i 184.8 184.17} {tt 185.14 185.17} {tt 185.117 185.120} {tt 185.133 185.136} {tt 187.0 187.4} {tt 190.0 190.6} {h2 194.0 194.12} {tt 196.61 196.63} {tt 196.73 196.81} {manref 196.134 196.142} {tt 196.169 196.180} {tt 196.249 196.250} {tt 196.263 196.264} {tt 196.276 196.277} {tt 196.449 196.477} {tt 196.529 196.548} {tt 196.721 196.748} {h2 199.0 199.9} {tt 201.5 201.9} {tt 201.110 201.114} {sc 203.75 203.82} {sc 203.195 203.202} {tt 203.236 203.244} {manref 205.177 205.187} {manref 205.189 205.199} {manref 205.201 205.210} {manref 205.212 205.223} {manref 205.246 205.255} {tt 205.257 205.262} {tt 205.417 205.434} {tt 205.442 205.449} {h3 210.0 210.8} {b 212.27 212.35} {tt 212.48 212.56} {tt 215.0 215.15} {tt 216.185 216.199} {tt 219.0 219.16} {i 219.16 219.45} {tt 220.4 220.20} {i 220.20 220.49} {tt 221.4 221.20} {i 221.20 221.49} {i 221.57 221.68} {tt 222.4 222.20} {i 222.20 222.49} {i 222.56 222.67} {tt 226.0 226.12} {i 226.12 226.21} {i 226.22 226.29} {i 226.30 226.47} {tt 227.0 227.12} {i 227.12 227.21} {i 227.22 227.29} {i 227.30 227.47} {tt 228.0 228.14} {i 228.14 228.23} {i 228.24 228.41} {tt 229.0 229.11} {i 229.11 229.18} {i 229.19 229.27} {i 231.4 231.21} {sc 231.110 231.117} {tt 231.171 231.184} {tt 231.192 231.200} {sc 231.223 231.230} {tt 231.235 231.239} {i 231.266 231.275} {i 231.280 231.287} {tt 231.343 231.344} {tt 231.348 231.350} {tt 231.353 231.354} {tt 233.24 233.34} {tt 235.293 235.305} {tt 235.309 235.324} {tt 235.478 235.482} {tt 235.629 235.643} {tt 237.40 237.51} {h3 240.0 240.8} {tt 242.162 242.170} {tt 243.0 243.46} {tt 244.0 244.21} {tt 247.0 247.54} {tt 248.0 248.21} {tt 251.0 251.46} {tt 252.0 252.51} {tt 255.0 255.60} {tt 256.0 256.24} {tt 257.0 257.22} {tt 260.0 260.41} {tt 261.0 261.45} {tt 262.0 262.21} {tt 263.0 263.18} {tt 266.0 266.25} {tt 269.0 269.25} {h3 272.0 272.26} {tt 274.48 274.52} {tt 274.244 274.248} {tt 274.673 274.681} {tt 276.77 276.85} {tt 276.181 276.188} {tt 276.305 276.329} {h1 279.0 279.25} {i 281.225 281.230} {i 283.528 283.532} {i 283.533 283.547} {i 326.16 326.26} {h1 330.0 330.10} {i 332.11 332.21} {manref 332.63 332.69} {i 332.72 332.82} {manref 332.91 332.95} {i 332.380 332.390} {tt 332.806 332.866} {h1 335.0 335.6} {tt 342.0 342.14} {h1 345.0 345.16} {i 347.49 347.63} {i 349.0 349.20} {i 351.92 351.102} {tt 351.216 351.252} {h1 354.0 354.7} {sc 360.0 360.150} {sc 364.0 364.289} {sc 366.0 366.359} } {
	eval $t tag add $qq
}

foreach qq {{introduction1 21.0} {using1 43.0} {locating2 45.0} {working2 64.0} {other2 81.0} {preferences2 94.0} {customizing1 115.0} {command2 142.0} {key2 194.0} {tkmandesc2 199.0} {platspec1 279.0} {rosettaman1 330.0} {author1 335.0} {more1 345.0} {license1 354.0} } {
	eval $t mark set $qq
}

}
image create bitmap icon -data {
#define tkman_width 64
#define tkman_height 64
static char tkman_bits[] = {
   0x33, 0x33, 0x23, 0x00, 0x0e, 0xc6, 0xfc, 0xff, 0x33, 0xb3, 0xe1, 0x00,
   0x06, 0x83, 0xfc, 0xff, 0xcc, 0xfc, 0xc0, 0x01, 0x80, 0x81, 0x77, 0x77,
   0xcc, 0xff, 0x00, 0x03, 0xc0, 0x80, 0xff, 0xff, 0xff, 0xdf, 0x00, 0x0e,
   0x60, 0xc0, 0xff, 0xff, 0xff, 0xc1, 0x00, 0x18, 0x38, 0xc0, 0xfc, 0xff,
   0x0f, 0xc0, 0x01, 0xf0, 0x0f, 0xc0, 0x76, 0x77, 0x00, 0x80, 0x01, 0xe0,
   0x07, 0x60, 0xfe, 0xdf, 0x00, 0x98, 0x03, 0xc0, 0x03, 0x70, 0xfc, 0x0f,
   0x00, 0x88, 0x03, 0xe0, 0x07, 0x30, 0xff, 0x07, 0x00, 0x04, 0x07, 0x70,
   0x0f, 0x18, 0x77, 0x03, 0x00, 0x04, 0x0f, 0xf8, 0x1f, 0xcc, 0xff, 0x03,
   0x00, 0x02, 0x0e, 0xfc, 0x3f, 0xe4, 0xff, 0x01, 0x00, 0x0a, 0x1c, 0xf6,
   0xff, 0xff, 0xff, 0x01, 0x00, 0x07, 0x38, 0x73, 0x77, 0x77, 0xf7, 0x00,
   0x00, 0x83, 0xf0, 0xe9, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x43, 0xe0, 0x00,
   0xff, 0xff, 0x1f, 0x00, 0x80, 0x31, 0x30, 0x22, 0xfe, 0xff, 0x1f, 0x00,
   0x00, 0x78, 0x18, 0x00, 0x74, 0x77, 0x07, 0x00, 0x00, 0x1c, 0x8c, 0x88,
   0xf8, 0xff, 0x03, 0x00, 0x00, 0x06, 0x06, 0x00, 0xc0, 0xdd, 0x07, 0x00,
   0x00, 0x00, 0x23, 0x22, 0x22, 0x22, 0x0f, 0x00, 0x00, 0x80, 0x99, 0x99,
   0x99, 0x99, 0x1d, 0x3c, 0x78, 0xc0, 0x99, 0x99, 0x99, 0x99, 0xf9, 0xff,
   0xff, 0x63, 0x66, 0x66, 0x66, 0x66, 0xf6, 0x83, 0x87, 0x7f, 0x66, 0x66,
   0x66, 0x66, 0xe6, 0x00, 0x01, 0x9c, 0x99, 0x99, 0x99, 0x99, 0xd9, 0x3f,
   0xe0, 0x9f, 0x99, 0x99, 0x99, 0x99, 0xf9, 0x1f, 0xc0, 0x7f, 0x00, 0x00,
   0x00, 0x00, 0x0c, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x8f, 0x07, 0x00,
   0x00, 0x80, 0xff, 0xff, 0xf7, 0x87, 0x07, 0x00, 0x00, 0x80, 0xff, 0xff,
   0xf7, 0xa7, 0x0f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xf7, 0x87, 0xff, 0x03,
   0x00, 0xfc, 0xff, 0xff, 0xff, 0x8b, 0xff, 0x01, 0x00, 0xc0, 0x9f, 0xcf,
   0xe7, 0x83, 0x0f, 0x00, 0x00, 0x80, 0xbf, 0xef, 0xe7, 0xe3, 0x0f, 0x00,
   0x00, 0xc0, 0x80, 0x0f, 0xe0, 0xe3, 0x0f, 0x00, 0x00, 0xfe, 0x88, 0x8f,
   0xe8, 0xfb, 0xf3, 0x07, 0x00, 0x7c, 0x80, 0x0f, 0xe0, 0xfb, 0xe1, 0x03,
   0x00, 0x60, 0xa2, 0x2f, 0xe2, 0xff, 0x20, 0x00, 0x00, 0x20, 0x80, 0x0f,
   0xe0, 0xff, 0x28, 0x00, 0x00, 0x9f, 0x88, 0x8f, 0xe8, 0xff, 0xe0, 0x07,
   0x00, 0x1e, 0x80, 0x0f, 0xe0, 0xff, 0xc1, 0x03, 0x00, 0x38, 0xa2, 0x2f,
   0xe2, 0xfb, 0xc3, 0x00, 0x01, 0x78, 0x80, 0x0f, 0xe0, 0xf3, 0xc7, 0x01,
   0xff, 0x9f, 0x88, 0x8f, 0xe8, 0xeb, 0x8f, 0xff, 0xff, 0x9f, 0x81, 0x0f,
   0xe0, 0xc3, 0x9f, 0xff, 0x00, 0x63, 0xa2, 0x2f, 0xe2, 0xa3, 0x7f, 0x7e,
   0x00, 0x67, 0x86, 0x0f, 0xe0, 0x03, 0x7f, 0x3e, 0x00, 0x9e, 0xc9, 0x9f,
   0xf8, 0x8f, 0x9f, 0x1d, 0x10, 0x9c, 0xd9, 0x1f, 0xf0, 0x87, 0x9f, 0x0f,
   0x30, 0x78, 0xe6, 0x3f, 0xf2, 0xa7, 0x67, 0x06, 0x30, 0x30, 0xe6, 0x1f,
   0xf0, 0x87, 0x67, 0x03, 0x70, 0x60, 0x99, 0x80, 0x08, 0x08, 0xd9, 0x11,
   0xf0, 0xc0, 0x98, 0x01, 0x00, 0x80, 0xd9, 0x00, 0xd0, 0x80, 0x65, 0x22,
   0x22, 0x42, 0x66, 0x08, 0xd0, 0x01, 0x63, 0x06, 0x00, 0x60, 0x36, 0x04,
   0x80, 0x03, 0x97, 0x89, 0x88, 0x90, 0x19, 0x06, 0x80, 0x03, 0x8e, 0x19,
   0x00, 0x98, 0x0d, 0x07, 0x00, 0x04, 0x5c, 0x26, 0x22, 0x66, 0x06, 0x03,
   0x00, 0x00, 0x18, 0x66, 0x00, 0x66, 0x83, 0x02, 0x00, 0x00, 0x30, 0x99,
   0x08, 0x99, 0x21, 0x01, 0x00, 0x00, 0x60, 0x98, 0x81, 0xd9, 0x00, 0x01,
   0x00, 0x00, 0xc0, 0x64, 0x62, 0x66, 0x00, 0x00};
}
image create bitmap face -data {
#define idbw48ed_width 48
#define idbw48ed_height 48
static char idbw48ed_bits[] = {
 0xf0,0xff,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0xff,0xff,0xff,0xf8,0xff,0xff,
 0xff,0xff,0xff,0xfc,0xff,0xff,0xff,0xff,0xff,0xfa,0x3f,0xc5,0xff,0xff,0xff,
 0xf8,0x3f,0x01,0xff,0xff,0xff,0xfc,0x5f,0x02,0xfe,0xff,0xff,0xfd,0x5f,0x00,
 0xf8,0xff,0xff,0xfc,0x3f,0x01,0xf0,0xff,0xff,0xf8,0x2f,0x04,0xe0,0xff,0xff,
 0xfd,0xff,0x01,0x01,0xff,0xff,0xfc,0xff,0x0b,0x00,0xf8,0xff,0xfc,0xff,0x0f,
 0xf4,0xfb,0xff,0xfa,0x1f,0x76,0xfc,0xef,0xff,0xfc,0xef,0x3d,0xfd,0xbf,0xff,
 0xff,0xff,0x56,0x54,0xb8,0xff,0xfc,0xff,0x3f,0xf7,0x95,0xff,0xfd,0xff,0x74,
 0xed,0xb5,0xff,0xfd,0x2f,0x5d,0xfb,0x37,0xff,0xfa,0x5b,0x7c,0x47,0x7f,0xff,
 0xfc,0x1a,0xdd,0x2b,0x98,0xff,0xfa,0x23,0xbe,0x82,0x52,0xff,0xec,0x05,0x9b,
 0x05,0xf4,0xff,0xf0,0x81,0x8e,0x07,0xd0,0xff,0xe8,0x86,0x07,0x0b,0x40,0xbf,
 0xf4,0x41,0x8f,0x0f,0xe0,0xce,0xf8,0xa5,0x5f,0x0b,0xa0,0xaf,0xf0,0x02,0xff,
 0x27,0xd0,0xc3,0xf8,0xd3,0xb7,0x0a,0x60,0xef,0xe8,0xa9,0x54,0x4a,0xd1,0xe7,
 0x78,0xa1,0x15,0x95,0xe8,0x72,0xf4,0xf1,0x17,0x2a,0x50,0x21,0xf8,0xe3,0xcf,
 0x2d,0xe1,0x2f,0xf4,0xd1,0x21,0xbe,0xf0,0x0f,0xb0,0xe7,0x07,0x7d,0xd4,0x07,
 0xe8,0x87,0x4f,0x97,0xf8,0x20,0x40,0xef,0xa3,0x0a,0x7c,0x00,0xc0,0x7d,0x15,
 0x05,0x7b,0x00,0x40,0xff,0x57,0x50,0x3f,0x20,0x80,0x77,0x48,0xc4,0x5b,0x10,
 0x82,0xfc,0x02,0xb0,0x1f,0x04,0x08,0xff,0x0b,0xd0,0x67,0x50,0x00,0xd6,0x45,
 0xf8,0x3f,0x0a,0x00,0xd8,0x0b,0xbf,0x5b,0x22,0x49,0xe0,0xa6,0xfe,0x37,0x05,
 0x64,0xc1,0xff,0xf7,0xce,0x02,0x0a,0xc1,0xff,0xff,0xd3,0x50,0x02,0x81,0xff,
 0xdf,0xd2,0x01};
}
set manx(solaris-bindings) {
# volume titles for Solaris
# written by Will C Lauer (wcl@cadre.com)
#
# With its default settings TkMan collects all volumes starting
# with the same character under a single section (for instance,
# 1, 1b, 1c, 1f, 1m and 1s are all collected under section 1).
# If multiple volumes share the same initial character
# in their man(manList) abbreviation, these
# sections are separated out in the Volumes menu.  The settings
# below separate out all volumes for Solaris.

# New users (those without ~/.tkman startup files) pick up these
# settings automatically.  The settings can also be interpolated
# into an existing startup file manually.

 
set man(manList) {1 1b 1c 1f 1g 1m 1s 2 3 3b 3c 3e 3f 3g 3i 3k 3l 3m 3n 3r 3s 
                  3t 3w 3x 4 4b 5 6 7 8 8c 8s 9 9e 9f 9s l o n p}
set man(manTitleList) {
        "User Commands" "BSD Compat Commands" Communications "FLMI Commands" 
        "Graphics/CAD Commands" "Maintenance Commands" "SunOS Specific Commands"
		"System Calls" Subroutines "BSD Compatibility" "Standard Library"
        "ELF Subroutines" "Fortran Subroutines" "Regexp Subroutines" 
        "Intl Subroutines" "Kvm Subroutines" "Lightweight Processes Subroutines"
        "Math Subroutines" "Networking Subroutines" 
        "Realtime Subroutines" "Standard I/O Subroutines" 
        "Threads Subroutines" "C Subroutines" "Misc Subroutines" 
        "File Formats" "BSD File Formats" "Headers, Tables, and Macros"
        "Games and Demos" "Devices/Special Files" "Maintenance Procedures"
        "Maintenance Procedures" "Maintenance Procedures"
        "DDI/DKI (Device Drv Interfaces)" 
        "DDI/DKI Entry Points" "DDI/DKI Kernel Functions"
        "DDI/DKI Data Structures"
        Local Old New Public
}
}
set manx(irix-bindings) {
#
# Add the SGI's magically-appearing catman volumes and directories,
# a multiyear project of Paul Raines (raines@slac.stanford.edu),
# Craig Ruff (cruff@ncar.ucar.edu), and Scott Nelson (nelson18@llnl.gov)
#

# New users (those without ~/.tkman startup files) pick up these
# settings automatically.  The settings can also be interpolated
# into an existing startup file manually.  Unless you have numerous
# highlights and shortcuts, it probably wouldn't hurt to replace
# the existing startup file if interpolation would be too laborious.


set man(buttbg) gray75
set man(guibg) gray90
set man(textbg) white
set man(manList) {1 2 3 4 5 6 7 8 l o n p D}
set man(manTitleList) {
	"User Commands"  "System Calls"  Subroutines  Devices  "File Formats" 
	Games  Miscellaneous  "System Administration"  Local  Old  New  Public
	"Device Drivers"
}

manDot


### your additions go below

# If you don't want a million volumes popping up in the list, simply delete
# the line that adds that volume.  The man pages in that volume will be
# grouped with the next most specific volume.  For instance, if 1M doesn't
# exist, those pages are placed in volume 1; likewise if a 3Xm doesn't exist
# but an Xm group does.

manDescAddSects {
	{1L  "Commands (Local)"}
	{1P  "Commands (Programmer)"}
	{1M  "Commands (Admin)"}
	{1X  "Commands (X11)"}
	{1Xm "Commands (Xm)"}
	{1Iv "Commands (Inventor)"}
	{1ex "Commands (explorer)"}
	{1dm "Commands (dmedia)"}
} after 1

manDescAddSects {{2f "System Calls (ftn)"}} after 2

manDescAddSects {
	{3dm  "Subroutines (Digital Media)"}
	{3L   "Subroutines (local)"}
	{3X   "Subroutines (X11)"}
	{3Xt  "Subroutines (Xt)"}
	{3Xm  "Subroutines (Motif)"}
	{3Xi  "Subroutines (Xirisw)"}
	{3Xo  "Subroutines (misc X)"}
	{3XS  "Subroutines (X SGI)"}
	{3Vk  "Subroutines (ViewKit)"}
	{3cc  "Subroutines (C++)"}
	{3Iv  "Subroutines (Inventor)"}
	{3ex  "Subroutines (explorer)"}
	{3ogl "Subroutines (OpenGL)"}
	{3gl  "Subroutines (GL)"}
	{3pex "Subroutines (pex)"}
	{3f   "Subroutines (ftn)"}
	{3l   "Subroutines (libblas)"}
	{3il  "Subroutines (il)"}
	{3comp "Subroutines (comp)"}
	{3n   "Subroutines (nonstandard)"}
	{3lib "Subroutines (lib)"}
	{3m   "Subroutines (misc)"}
} after 3

manDescAddSects {
	{4L   "Devices (Local)"}
	{4dm  "Devices (Digital Media)"}
	{4ex  "Devices (Explorer)"}
} after 4

manDescAddSects {
	{5L  "File Formats (Local)"}
	{5Xm "File Formats (Motif)"}
} after 5

manDescAddSects {{7L  "Miscellaneous (Local)"}} after 7

manDescAddSects {{8L  "System Administration (Local)"}} after 8

manDescAddSects {{gnu "GNU stuff"}}



# All directories in the catman hierarchy are matched against
# the volume-pattern pairs below.  If there is a match for the
# directory in the same numerical volume, then the directory is
# grouped with that volume.  Otherwise, a match in any volume
# is taken.  If the directory doesn't match any pattern, it
# is placed in next most specific grouping.  If you edit this list,
# place more general groupings after more specific ones.

manDescSGI {
	{ 1P /p_man/*1* }
	{ 1M /a_man/*1* }
	{ 2 2/standard }
	{ 3dm 3dm/* }
	{ 3Xo {Xau Xext Xi Xnmbx} }
	{ 3XS Sg* }
	{ 3Vk Vk }
	{ 3cc c++ }
	{ 3l libblas }
	{ 3ogl {OpenGL widget} }
	{ 3 p_man/*3*/standard }
	{ 3gl 3/standard }
	{ 3n 3/nonstandard }
	{ 3il il }
	{ 3Xi Xirisw }
	{ 3lib lib }
	{ 3m {3b 3c 3g 3n 3p 3s 3t 3w 3x}}
	{ 3pex pex }
	{ 3comp comp }

	{ f ftn }
	{ Iv Inventor }
	{ ex explorer }
	{ dm {dmedia audio video movie midi} }
	{ X {X X11} }
	{ L {/local* /alt*} }
	{ Xt Xt }
	{ Xm Xm }
	{ gnu gnu }
}
}
set manx(sco-bindings) {
#
# calculate standard SCO UNIX modifications,
# based on information from Bela Lubkin
#

# New users (those without ~/.tkman startup files) pick this up
# automatically.  The code can also be interpolated into an existing
# startup file manually.


### your additions go below

set manx(dirnameindex) 4; # should be set already, but just in case

# Compute sections based on system settings.
set man(manList) ""
set man(manTitleList) ""

#  grep ORDER= /etc/default/man
#  ORDER=C:S:CP:CT:M:F:HW:DOS:UCB:LOCAL:ADM:TCL:ADMN:ADMP:SFF:TC:NADM:NF:NC:PADM:X:XC:MERGE:AS:net:FP:C++:CDMT:Xext:Xm:Xmu:XS:Xt:NET:SLIB:SSC:NS:SAPD

set manx(sco-master) {
	{1 "User Commands"} {3 "Functions"} {4 "File Formats"} {5 Support Files"} {7 "Packages"}
	{A "Administration"}
	{ADM "Operating system administration"}
	{ADMN "TCP/IP administration commands"}
	{ADMP "TCP/IP network protocols"}
	{C "Operating system commands, utilities"}
	{C++ "C++ library"}
	{CDMT "Custom Distribution Mastering Toolkit"}
	{CP "Programming commands"}
	{F "File formats"}
	{FP "Programming file formats"}
	{G Games}
	{H "Hardware and Drivers"}
	{HW "Device drivers, hardware"}
	{L "Local Commands"}
	{LMC "LAN Manager Client commands"}
	{M "Miscellaneous"}
	{MERGE "SCO Merge commands"}
	{NADM "NFS network administration commands"}
	{NC "NFS network user commands"}
	{NET "TLI/XTI transport stack library"}
	{NF "NFS file formats"}
	{NS "NFS, NIS, RPC, XDR network library"}
	{NWG "SCO Gateway for NetWare commands"}
	{PADM "IPX/SPX commands"}
	{PCI "PC-Interface commands"}
	{S "Operating system calls, library"}
	{SAPD "DCE SAP library"}
	{SFF "TCP/IP file formats"}
	{SLIB "Socket library"}
	{SSC "Socket system calls"}
	{TC "TCP/IP network user commands"}
	{TCL "SCO Visual Tcl commands"}
	{WABI "SCO Wabi commands"}
	{X "X server commands"}
	{XC "X client commands"}
	{Xext "X Extensions library"}
	{Xm "OSF/Motif commands, library"}
	{Xmu "X library (miscellaneous utilities)"}
	{XS "X library"}
	{Xt "X Toolkit Intrinsics library"}
}

# build default list based on ORDER= in /usr/default/man
set scolist ""
set manx(sco-config) "/etc/default/man"
#set manx(sco-config) "tmp"
if [file readable $manx(sco-config)] {
	set fid [open $manx(sco-config)]
	while {![eof $fid]} {
		set line [gets $fid]
		if [regexp  "^\[ \t]*ORDER\[ \t]*=\[ \t]*(.*)" $line all tmp] {
			set scolist $tmp
			# want last ORDER= line so don't break
		}
	}
	close $fid

	if {$scolist!=""} {
		# build list in given order
		foreach i [split [string trim $scolist] ":"] {
			if {[lsearch $man(manList) $i]==-1} {	# no duplicates
				lappend man(manList) $i
				if {[set title [lassoc $manx(sco-master) $i]]==""} { set title $i }
				lappend man(manTitleList) $title
			}
		}
	}
}

# if can't find ORDER, build up default list from master list
if {$scolist==""} {
	foreach i $manx(sco-master) {
		lappend man(manList) [lfirst $i]
		lappend man(manTitleList) [lsecond $i]
	}
}
}




proc pipeexp {p} {
set p [string trim $p]

set expp ""
foreach i $p {
if {[regexp {^[.~/$]} $i]} {lappend expp [fileexp $i]} \
else {lappend expp $i}
}
return $expp
}

proc assert {bool msg {boom 0}} {
if {!$bool} {
puts stderr $msg
if $boom {exit 1}
}
}


proc fileexp {f} {
global env

set f [string trim $f]
set l [string length $f]
set expf ""

set dir [pwd]
foreach i [split $f "/"] {
switch -glob $i {
"" {set dir ""}
~  {set dir $env(HOME)}
$* {set val $env([string trim [string range $i 1 end] ()])
if {[string match /* $val]} {set dir $val} {append expf /$val)}}
.  {set dir $dir}
.. {set dir [file dirname $dir]}
default {append expf /$i}
}
}

return $dir$expf
}



proc filetail {f} {
set tail [file tail $f]
if [string match */ $f] {set tail ""}
return $tail
}
proc filedirname {f} {
set dirname [file dirname $f]
if [string match ?*/ $f] {set dirname [string range $f 0 [expr [string length $f]-2]]}
return $dirname
}

proc filecomplete {f} {
set expf [fileexp [filedirname $f]]/[filetail $f]
set posn [string last [filetail $f] $f]; if [string match */ $f] { set posn [string length $f] }
set l [glob -nocomplain $expf*]
set ll [llength $l]

if {!$ll} {
set tail ""
} elseif {$ll==1} {
set tail [file tail $l]
if {[file isdirectory $l]} {append tail /}
} else {
set lf [lfirst $l]; set lfl [string length $lf]
set last $lfl
set ni [expr [string last / $lf]+1]
foreach i $l {
set il [string length $i]
for {set j $ni} {$j<=$last} {incr j} {
if {[string range $lf $j $j]!=[string range $i $j $j]} break
}
set last [min $last [expr $j-1]]
}
set tail [filetail [string range [lfirst $l] 0 $last]]
}

if {$posn>0 && $ll} {
set tail [string range $f 0 [expr $posn-1]]$tail
}

if {$ll<2} {return $tail} {return "$tail $l"}
}



proc isalpha {c} {return [regexp -nocase {[a-z]} $c]}
proc isnum {c} {return [expr [string first $c "123456790"]!=-1]}
proc isalphanum {c} {return [expr [isalpha $c]||[isnum $c]]}

proc stringicap {s} {return [string toupper [string range $s 0 0]][string range $s 1 end]}

proc tr {s c1 c2} {
regsub -all "\[$c1\]" $s $c2 s2
return $s2
}

proc bolg {f {l ""}} {
if {$l==""} {global file; set l $file(globList)}

foreach i $l {
if [regsub ([glob -nocomplain $i])(.*) $f "$i\\2" short] {return $short}
}
return $f
}


proc setinsert {l i e} {
return [linsert [lfilter $e $l] $i $e]
}


proc unsplit {l c} {
foreach i $l {
append l2 $i $c
}
return [string range $l2 0 [expr [string length $l2]-2]]
}

proc bytes2prefix {x} {
set pfx {bytes KB MB GB TB QB}
set bp 20
set k 1024.0
set sz $k

set y BIG
for {set i 0} {$i<[llength $pfx]} {incr i} {
if {$x<$sz} {
set y [format " %0.0f [lindex $pfx $i]" [expr $x/($sz/$k)]]
break
} elseif {$x<[expr $sz*$bp]} {
set y [format " %0.1f [lindex $pfx [expr $i+1]]" [expr ($x+0.0)/$sz]]
break
}

set sz [expr $sz*$k]
}

return $y
}




proc quote {x} {return $x}

proc uniqlist {l} {
set e ""
set l2 ""
foreach i $l {
if {$e!=$i} {
lappend l2 $i
set e $i
}
}
return $l2
}


proc min {args} {
if {[llength $args]==1} {set args [lindex $args 0]}
set x [lindex $args 0]
foreach i $args {
if {$i<$x} {set x $i}
}
return $x
}

proc avg {args} {
set sum 0.0

if {$args==""} return

foreach i $args {set sum [expr $sum+$i]}
return [expr ($sum+0.0)/[llength $args]]
}

proc max {args} {
if {[llength $args]==1} {set args [lindex $args 0]}
set x [lindex $args 0]
foreach i $args {
if {$i>$x} {set x $i}
}
return $x
}


proc lfirst {l} {return [lindex $l 0]}
proc lsecond {l} {return [lindex $l 1]}
proc lthird {l} {return [lindex $l 2]}
proc lfourth {l} {return [lindex $l 3]}
proc lfifth {l} {return [lindex $l 4]}
proc lsixth {l} {return [lindex $l 5]}
proc lseventh {l} {return [lindex $l 6]}
proc lrest {l} {return [lrange $l 1 end]}

proc llast {l} {
set end [llength $l]
if {!$end} {return ""}
return [lindex $l [expr $end-1]]
}

proc setappend {l e} {
return "[lfilter $e $l] $e"
}

proc lfilter {p l} {
set l2 ""

foreach i $l {
if ![string match $p $i] "lappend l2 [list $i]"
}
return $l2
}

proc lmatches {p l} {
set l2 ""
foreach i $l { if [string match $p $i] {lappend l2 [list $i]} }
return $l2
}

proc lassoc {l k} {
foreach i $l {
if {[lindex $i 0]==$k} {return [lrange $i 1 end]}
}
return ""
}

proc lset {l args} {
foreach val $l var $args {
upvar $var x
set x $val
}
}

proc lbssoc {l k} {

foreach i $l {
if {[lindex $i 1]==$k} {return [lindex $i 0]}
}
return ""
}

proc lreverse {l} {
set l2 ""
for {set i [expr [llength $l]-1]} {$i>=0} {incr i -1} {
lappend l2 [lindex $l $i]
}
return $l2
}



proc geom2posn {g} {
if [regexp {(=?[0-9]+x[0-9]+)([-+]+[0-9]+[-+]+[0-9]+)} $g both d p] {
return $p
} else { return $g }
}

proc geom2size {g} {
if [regexp {(=?[0-9]+x[0-9]+)([-+]+[0-9]+[-+]+[0-9]+)} $g both d p] {
return $d
} else { return $g }
}






set name2charList {
minus plus percent ampersand asciitilde at less greater equal
numbersign dollar asciicircum asterisk quoteleft quoteright
parenleft parenright bracketleft bracketright braceleft braceright
semicolon colon question slash bar period underscore backslash
exclam comma
}

proc name2char {c} {
global name2charList

if {[set x [lsearch $name2charList $c]]!=-1} {
return [string index "-+%&~@<>=#$^*`'()\[\]{};:?/|._\\!," $x]
} else {return $c}
}

proc key_state2mnemon {n} {
set mod ""

if {$n>=16} {append mod A; set n [expr $n-16]}
if {$n>=8} {append mod M; set n [expr $n-8]}
if {$n>=4} {append mod C; set n [expr $n-4]}
if {$n>=2} {append mod A; set n [expr $n-2]}
if {$n} {append mod S}

return $mod
}

proc lmatch {mode list {pattern ""}} {
if {$pattern==""} {set pattern $list; set list $mode; set mode "-glob"}
return [expr [lsearch $mode $list $pattern]!=-1]
}



proc stringremove {s {c " "}} {
regsub -all -- \\$c $s "" s2
return $s2
}


proc stringregexpesc {s} { 
return [stringesc $s {\||\*|\+|\?|\.|\^|\$|\\|\[|\]|\(|\)|\-}]
}
proc stringesc {s {c {\\|\$|\[|\{|\}|\]|\"}}} {
regsub -all -- $c $s {\\&} s2
return $s2
}


proc tk_listboxNoSelect args {
foreach w $args {
bind $w <Button-1> {format x}
bind $w <B1-Motion> {format x}
bind $w <Shift-1> {format x}
bind $w <Shift-B1-Motion> {format x}
}
}


proc listboxshowS {lb s {first 0} {cnstr yes}} {
set sz [$lb size]

for {set i $first} {$i<$sz} {incr i} {
if [string match $s [$lb get $i]] {
listboxshowI $lb $i $cnstr
return $i
}
}
return -1
}

proc listboxshowI {lb high {cnstr yes}} {
set high [max 0 [min $high [expr [$lb size]-1]]]

set hb [lindex [split [$lb cget -geometry] x] 1]
set hx [max 0 [expr [$lb size]-$hb]]
if {$cnstr=="yes"} {set hl [expr $high<$hb?0:[min $high $hx]]} {set hl $high}
$lb select from $high
$lb yview $hl
}

proc listboxreplace {lb index new} {
$lb delete $index
$lb insert $index $new
$lb select from $index
}



proc listboxmove {l1 l2} {
listboxcopy $l1 $l2
$l1 delete 0 end
}

proc listboxcopy {l1 l2} {

$l2 delete 0 end
listboxappend $l1 $l2
catch {$l2 select from [$l1 curselection]}
}

proc listboxappend {l1 l2} {

set size [$l1 size]

for {set i 0} {$i<$size} {incr i} {
$l2 insert end [$l1 get $i]
}
}


option add *Text.borderwidth 2



proc tabgroup {args} {
if [llength $args]==1 {set wins [lindex $args 0]} {set wins $args}

set l [llength $wins]
for {set i 0} {$i<$l} {incr i} {
set w [lindex $wins $i]
set pw [lindex $wins [expr ($i-1)%$l]]
set nw [lindex $wins [expr ($i+1)%$l]]

bind $w <KeyPress-Tab> "focus $nw; break"
bind $w <Shift-KeyPress-Tab> "focus $pw; break"
}
}


proc winstderr {w msg {type "bell & flash"}} {
if {![winfo exists $w]} return
set bell [string match "*bell*" $type]
set flash [string match "*flash*" $type]

set fg [$w cget -foreground]; set bg [$w cget -background]

set msgout [string range $msg 0 500]
if {[string length $msg]>500} {
append msgout " ... (truncated; full message sent to stdout)"
puts stderr $msg
}
winstdout $w $msgout
if {$flash} {$w configure -foreground $bg -background $fg}
if {$bell} bell
if {$flash} {
update idletasks; after 500
$w configure -foreground $fg -background $bg
}
}

proc winstdout {w {msg AnUnLiKeMeSsAgE} {update 0}} {
if {![winfo exists $w]} return
if {$update=="update"} {set update 1}

if {$msg!="AnUnLiKeMeSsAgE"} {
$w configure -text $msg
if {$update} { update idletasks }
}
return [$w cget -text]
}

proc yviewcontext {w l c} {
if {$l=="sel"} {
set cnt [scan [$w tag ranges sel] %d l]
if {$cnt<=0} return
}

incr l -1; # 0-based!

scan [$w index end] %d n
set prev [expr $l-$c]; set next [expr $l+$c]

if {$prev>=0} {$w yview -pickplace $prev}
if {$next<=$n} {$w yview -pickplace $next}
$w yview -pickplace $l
}


proc screencenter {xy wh} {
if {$xy=="x"} {
return [expr ([winfo screenwidth .]-$wh)/2]
} {
return [expr ([winfo screenheight .]-$wh)/2]
}
}


proc cursorBusy {{up 1}} {
if {[. cget -cursor]!="watch"} {
cursorSet watch; if $up {update idletasks}
}
}
proc cursorSet {c {w .}} {
global cursor
set cursor($w) [$w cget -cursor]
$w configure -cursor $c
foreach child [winfo children $w] {cursorSet $c $child}
}
proc cursorUnset {{w .}} {
global cursor
catch {$w configure -cursor $cursor($w)}
foreach child [winfo children $w] {cursorUnset $child}
}

proc mon2Month {m} {
set mons {jan feb mar apr may jun jul aug sep oct nov dec}
set Months {January February March April May June July August September October November December}
set ml [string tolower $m]
if {[set x [lsearch -exact $mons $ml]]!=-1} {
set m [lindex $Months $x]
}

return $m
}

proc configurestate {wins {flag "menu"}} {
set flag0 $flag
foreach w $wins {
set flag $flag0
if {$flag=="menu"} {
if {[winfo class $w]=="Menubutton"} {
set m [$w cget -menu]; set end [$m index end]
set flag [expr {$end!="none" && (![$m cget -tearoff] || $end>0)} ]
} else { set flag 0 }
}
$w configure -state [expr $flag?"normal":"disabled"]
}
}

proc linebreak {string {breakat 70}} {
set ch 0; set lastw ""
set broke ""

foreach word $string {
if {[string match "*." $lastw]} {append broke " "}

set wlen [string length $word]
if {$ch+$wlen<$breakat} {
if {$ch>0} {append broke " "; incr ch}
append broke $word; incr ch $wlen
} else {
append broke "\n" $word
set ch $wlen
}

set lastw $word
}

return $broke
}


proc recently {then} {
set datainfo "%Y %B %d %H %M %S"
set format "%d %s %d %d %s %s"
set now [clock seconds]
scan [clock format $now -format $datainfo] $format year month day hour min sec
set midnight [clock scan "$day $month"]
scan [clock format $then -format $datainfo] $format oyear omonth oday ohour omin osec

set secday [expr 24*60*60]
set secmonth [expr 30*$secday]
set secyear [expr 365*$secday]

set age [expr $now-$then]
if {$age>=$secyear} {
set r "$oday $omonth $oyear"
} else {
if {$age>=$secmonth} {
set r "$ohour:$omin, $oday $omonth"
} else {
set r "$ohour:$omin"
if {[expr $midnight-$secday]>=$then} {
append r ", $oday $omonth"
} else {
append r ":$osec"
if {$day!=$oday} {
append r " yesterday"
} else { append r " today" }
}
}
}

return $r
}




set sbx(boilerplate) {
Searchbox
Copyright (c) 1993-1996  T.A. Phelps

Permission to use, copy, modify, and distribute this software and its
documentation for educational, research and non-profit purposes, 
without fee, and without a written agreement is hereby granted, 
provided that the above copyright notice and the following three 
paragraphs appear in all copies.  

Permission to incorporate this software into commercial products may 
be obtained from the Office of Technology Licensing, 2150 Shattuck 
Avenue, Suite 510, Berkeley, CA  94704. 

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.
}



set sb(key,*) "add modifiers in this order: M, C, A"


set sb(key,C-x) exchangepointandmark
set sb(key,C-space) setmark
set sb(key,-Delete) pageup
set sb(key,C-h) pageup
set sb(key,M-v) pageup
set sb(key,-BackSpace) pageup
set sb(key,-space) pagedown
set sb(key,C-v) pagedown
set sb(key,-Escape) searchkill
set sb(key,C-g) searchkill
set sb(key,C-n) nextline
set sb(key,C-p) prevline
set sb(key,-Up) prevline
set sb(key,-Down) nextline
set sb(key,-Left) prevline
set sb(key,-Right) nextline
set sb(key,C-s) incrsearch
set sb(key,C-r) revincrsearch
set sb(key,M-question) help
set sb(key,-Help) help
set sb(key,C-l) clearscreen



set sb(key,C-f) pagedown
set sb(key,C-b) pageup



set sb(key,-F27) pagestart
set sb(key,-F29) pageup
set sb(key,-F35) pagedown
set sb(key,-R13) pageend


set sbx(wrap-msg) "No more matches; try again to wrap around"


set sb(key,M-less) pagestart
set sb(key,M-greater) pageend

foreach e [array names sb] {
set sbdef($e) $sb($e)
}


if {[info tclversion]<7.4 || $tk_version<4.0} {
puts stderr "Tcl 7.4/Tk 4.0 minimum versions required"
puts stderr "You have Tcl [info tclversion]/Tk $tk_version"
exit 1
}





proc searchboxSearch {pat regexp casesen tag t {wmsg ""} {wcnt ""}} {
global sbx

if {$casesen==-1} {set casesen [expr {[string tolower $pat]!=$pat}]}
set caseopt [expr !$casesen?"-nocase":""]
if {$regexp} {set type "regexp"} {set type "exact"}

if {$pat==""} {
winstderr $wmsg "Nothing to search for!  Type in a [expr $regexp?{regular expression}:{string}]."
return 0
}

if {$type=="regexp"&&[catch {regexp $pat bozomaniac}]} {
winstderr $wmsg "Malformed regular expression."
return 0
}

$t tag remove $tag 1.0 end

set cnt 0
set index 1.0
set len 0
while {[set index [eval "$t search -forwards -$type $caseopt -count len -- {$pat} {$index+$len chars} end"]]!=""} {
$t tag add $tag $index "$index + $len chars"
incr cnt
}


if {$cnt==0} {set txt "no matches"} elseif {$cnt==1} {set txt "$cnt match"} {set txt "$cnt matches"}
$wcnt configure -text $txt

set sbx(ratend$t) 0; set sbx(ratstart$t) 0
searchboxNext $tag $t $wmsg 0

return $cnt
}




proc searchboxNext {tag t {wmsg ""} {yoff ""}} {
global sbx

if {[$t tag ranges $tag]==""} { winstderr $wmsg "No matches!"; return }

if {$yoff==""} {set yoff [winfo height $t]}
set hit [$t tag nextrange $tag [$t index @0,$yoff]]
if {$hit==""} {
if {$sbx(ratend$t)} {
set hit [$t tag nextrange $tag 1.0]
set sbx(ratend$t) 0
} else {
winstderr $wmsg $sbx(wrap-msg)
set sbx(ratend$t) 1
}
}
if {$hit!=""} {
$t see [lindex $hit 0]
}
}

proc searchboxPrev {tag t {wmsg ""}} {
global sbx

if {[$t tag ranges $tag]==""} { winstderr $wmsg "No matches!"; return }

set hit [$t tag prevrange $tag [$t index @0,0]]
if {$hit==""} {
if {$sbx(ratstart$t)} {
set hit [$t tag prevrange $tag end]
set sbx(ratstart$t) 0
} else {
winstderr $wmsg $sbx(wrap-msg)
set sbx(ratstart$t) 1
}
}

if {$hit!=""} {
$t see [lindex $hit 0]
}
}



proc searchboxKeyNav {m k casesen t {wmsg ""} {firstmode 0}} {
global sb sbx

if {[regexp {(Shift|Control|Meta|Alt)_.} $k]} {return 0}
if {![info exists sbx(try$t)]} {
set sbx(try$t) 0
set sbx(vect$t) 1
set sbx(lastkeys$t) ""
set sbx(iatstart$t) 0; set sbx(iatend$t) 0
if ![info exists sbx(lastkeys-old$t)] {set sbx(lastkeys-old$t) ""}
}


if {!$firstmode && ($sbx(try$t) || $sbx(lastkeys$t)!="")} {
switch -exact -- $k {
space {set k " "}
BackSpace -
Delete {
set k ""
set last [expr [string length $sbx(lastkeys$t)]-2]
set sbx(lastkeys$t) [string range $sbx(lastkeys$t) 0 $last]
set sbx(try$t) 1
}
default { if {$m==""||$m=="S"} {set k [name2char $k]} }
}
}


set m [string trimright $m "S"]; # strip shift as a modifier
set mk $m-$k
if {$m=="literal"} {set op $k} \
elseif {[info exists sb(key,$mk)]} {set op $sb(key,$mk)} \
elseif {$m=="" && [string length $k]<=1} {set op default} \
else {return 0}

switch -exact -- $op {
exchangepointandmark {
set tmp [$t index @0,0]
$t yview xmark
update
$t mark set xmark $tmp
}
setmark {$t mark set xmark [$t index @0,0]}
pageup {$t yview scroll -1 pages}
pagedown {$t yview scroll 1 pages}
pagestart {$t yview moveto 0}
pageend {$t yview moveto 1}
searchkill {
if {$sbx(lastkeys$t)!=""} {set sbx(lastkeys-old$t) $sbx(lastkeys$t)}
set sbx(lastkeys$t) ""; set sbx(try$t) 0
winstdout $wmsg ""
}
clearscreen {winstdout $wmsg ""}
nextline {$t yview scroll 1 units}
prevline {$t yview scroll -1 units}
default {
if {$op=="incrsearch"} {
if {$sbx(try$t)&&$sbx(lastkeys$t)==""} {set sbx(lastkeys$t) $sbx(lastkeys-old$t)}
set sbx(vect$t) 1; set sbx(try$t) 1
} elseif {$op=="revincrsearch"} {
if {$sbx(try$t)&&$sbx(lastkeys$t)==""} {set sbx(lastkeys$t) $sbx(lastkeys-old$t)}
set sbx(vect$t) -1; set sbx(try$t) 1
} elseif {$firstmode} {
set sbx(lastkeys$t) $k
set sbx(try$t) 1
} elseif {$sbx(try$t)} {
append sbx(lastkeys$t) $k
}

set keys $sbx(lastkeys$t)
if {$casesen==-1} {set casesen [expr {[string tolower $keys]!=$keys}]}
set caseopt [expr !$casesen?"-nocase":""]
if {$sbx(try$t)==0 && $keys==""} {return 0}
winstdout $wmsg "Searching for \"$keys\" ..."


if {$firstmode} {
set start 1.0; set end end
} elseif {[set ranges [$t tag ranges isearch]]!=""} {
set start [lindex $ranges 0]; set end 1.0
if {$op=="incrsearch"} {set start [$t index "$start+1c"]}
if {$sbx(vect$t)==1} {set end "end"}
} else {
if {$sbx(vect$t)==1} {
set start [$t index @0,0]; set end "end"
} else {
set start [$t index @0,[winfo height $t]]; set end "1.0"
}
}

set dir [expr {$sbx(vect$t)==1?"-forwards":"-backwards"}]
set type [expr $firstmode?"-regexp":"-exact"]
set pfx [expr $firstmode?"^":""]
set search "$t search $dir $type $caseopt -count klen -- {$pfx$keys} $start"
set found [eval "$search $end"]
set anywhere [eval $search]

if {$anywhere!=""} {
if {$found!=""} {
$t tag remove isearch 1.0 end
$t tag add isearch $found "$found + $klen c"
$t see $found
set sbx(iatstart$t) 0; set sbx(iatend$t) 0
} else {
if {$sbx(vect$t)==1} {
if {$sbx(iatstart$t)} {
$t yview moveto 0; $t tag remove isearch 1.0 end
return [searchboxKeyNav $m $k $casesen $t $wmsg $firstmode]
} else {
winstderr $wmsg $sbx(wrap-msg)
set sbx(iatstart$t) 1
}
} else {
if {$sbx(iatend$t)} {
$t yview moveto 1; $t tag remove isearch 1.0 end
return [searchboxKeyNav $m $k $casesen $t $wmsg $firstmode]
} else {
winstderr $wmsg $sbx(wrap-msg)
set sbx(iatend$t) 1
}
}
}
} else {
$t tag remove isearch 1.0 end
winstderr $wmsg "\"$keys\" not found"
set sbx(try$t) 0
}
}
}

return 1
}




proc searchboxSaveConfig {fid} {
global sb sbx sbdef

puts $fid "#\n# SearchBox\n#\n"
foreach i [lsort [array names sb]] {
set co ""
if {[info exists sbdef($i)] && $sbdef($i)==$sb($i)} {set co "#"}
puts $fid "${co}set sb($i) [list $sb($i)]"
}
puts $fid "\n"
}



if {[info procs winstdout]==""} {

proc winstderr {w msg {type "bell & flash"}} {
if {![winfo exists $w]} return
set bell [string match "*bell*" $type]
set flash [string match "*flash*" $type]

set fg [$w cget -foreground]; set bg [$w cget -background]

set msgout [string range $msg 0 500]
if {[string length $msg]>500} {
append msgout " ... (truncated; full message sent to stdout)"
puts stderr $msg
}
winstdout $w $msgout
if {$flash} {$w configure -foreground $bg -background $fg}
if {$bell} bell
if {$flash} {
update idletasks; after 500
$w configure -foreground $fg -background $bg
}
}

proc winstdout {w {msg AnUnLiKeMeSsAgE} {update 0}} {
if {![winfo exists $w]} return
if {$msg!="AnUnLiKeMeSsAgE"} {
$w configure -text $msg
if {$update} { update idletasks }
}
return [$w cget -text]
}

}









wm withdraw .; update idletasks
option add *Menubutton.relief raised
option add *padX 2
option add *padY 2
option add *Button.padX 2
option add *Button.padY 2
option add *Menubutton.padX 2
option add *Menubutton.padY 2
option add *Radiobutton.padX 2
option add *Radiobutton.padY 2



proc TkMan {} {
global man manx mani env

set dup [expr $manx(uid)>1]
if {!$dup} {
set w .man
} else {
set w .man$manx(uid)
toplevel $w -class TkMan
}
set t $w.show; set wi $w.info

bind $w <Unmap> "wm iconname $w \[subst \$manx(iconname)\]"


set manx(man$w) ""
set manx(manfull$w) ""
set manx(catfull$w) ""
set manx(name$w) ""
set manx(num$w) ""
set manx(cursect$w) 1
set manx(lastvol$w) 1
set manx(hv$w) [set manx(oldmode$w) [set manx(mode$w) help]]


wm minsize $w 200 200
wm iconname $w "TkMan"

if {!$dup} {
set manx(title$w) $manx(title)
wm geometry $w $manx(geom)
wm protocol $w WM_DELETE_WINDOW {exit 0}

if {$manx(iconify)} {
wm iconify $w
update idletasks
}
} else {
set manx(title$w) "$manx(title) #$manx(uid)"
wm geometry $w [lfirst [split $manx(geom) "+-"]]
}
wm title $w $manx(title$w)


label $wi -anchor w

frame $w.kind
button $w.man -text "man" -command "incr stat(man-button); manShowMan \$manx(typein$w) {} $w"
button $w.apropos -text "apropos" -command "manApropos \$manx(typein$w) $w"
if {$man(glimpse)!=""} {button $w.glimpse -text "glimpse" -command "manGlimpse \$manx(typein$w) $w"}
entry $w.mantypein -relief sunken -textvariable manx(typein$w) -width 25
bind Entry <Key-Delete> [bind Entry <Control-Key-h>]
bind Entry <Control-KeyPress-w> {%W delete 0 end}
bind $w.mantypein <KeyPress-Return> "$w.man invoke"
bind $w.mantypein <Shift-KeyPress-Return> "$w.apropos invoke"
if {$man(glimpse)!=""} {
foreach m {"Meta" "Alt"} {
bind $w.mantypein <$m-KeyPress-Return> "$w.glimpse invoke"
}
}
menubutton [set mb $w.dups] -text "\337" -menu [set m $mb.m]; menu $m

pack $w.man -in $w.kind -side left -padx 2 -anchor e
pack $w.apropos -in $w.kind -side left -padx 3
if {$man(glimpse)!=""} { pack $w.glimpse -in $w.kind -side left -padx 3	}
pack $w.mantypein -fill x -expand yes -in $w.kind -side left -ipadx 5 -anchor w

menubutton [set mb $w.paths] -text "Paths" -menu [set m $mb.m]; menu $m
if {[llength $manx(paths)]>2} {
$m add command -label "All Paths On" -command {
foreach i $manx(paths) {set man($i) 1}
manResetEnv
}
$m add command -label "All Paths Off" -command {
foreach i $manx(paths) {set man($i) 0}
manResetEnv
}
$m add command -label "Save Paths Selections" -command {
set manx(pathstat) ""
foreach i $manx(paths) {lappend manx(pathstat) $man($i)}
}
$m add command -label "Restore Paths Selections" -command {
foreach i $manx(paths) j $manx(pathstat) {set man($i) $j}
manResetEnv
}
$m add separator
}
foreach i $manx(paths) {
$m add checkbutton -label $i -variable man($i) -command {manResetEnv}
}
manMenuFit $m


menubutton [set mb $w.vols] -text "Volumes" -menu [set m $mb.m]; menu $m -tearoff no

pack [frame $w.filler] -in $w.kind -side left -fill x -expand yes
pack $w.vols $w.paths -in $w.kind -side left -padx 4


frame $w.nav
menubutton [set mb $w.sections] -text "Sections" -menu [set m $mb.m]; menu $m -tearoff no
menubutton [set mb $w.links] -text "Links" -menu [set m $mb.m]; menu $m

frame $w.hlf
menubutton [set mb $w.high] -text "Highlights" -menu [set m $mb.m]; menu $m -tearoff no
bind $mb <Shift-Button-1> "manHighlights $w get 1; break"
button $w.hadd -text "+" -padx 4 -command "
if \[llength \[$t tag nextrange sel 1.0\]\]==0 {
manWinstderr $w {Select a range of characters to highlight.}
return
}
incr stat(page-highlight-add)
set mani(high,form) {}
$t tag add highlight sel.first sel.last
selection clear $t
manHighlights $w
"
button $w.hsub -text "-" -padx 4 -command "
if \[llength \[$t tag nextrange sel 1.0\]\]==0 {
manWinstderr $w {Select a range of highlighted characters to unhighlight.}
return
}
$t tag remove highlight sel.first sel.last
incr stat(page-highlight-sub)
set mani(high,form) {}
selection clear $t
manHighlights $w
"
bind $w.hsub <Shift-Button-1> "$t tag remove highlight 1.0 end; manHighlights $w"
pack $w.high $w.hadd $w.hsub -in $w.hlf -side left -padx 1


frame $w.scf
menubutton [set mb $w.shortcuts] -text "Shortcuts" -menu [set m $mb.m]; menu $m -tearoff no
button $w.sadd -text "+" -padx 4 -command "incr stat(page-shortcut-add); manShortcuts $w add"
button $w.ssub -text "-" -padx 4 -command "incr stat(page-shortcut-sub); manShortcuts $w sub"
bind $w.ssub <Shift-Button-1> "set man(shortcuts) {}; manShortcuts $w init"
pack $w.shortcuts $w.sadd $w.ssub -in $w.scf -side left -padx 1
manShortcuts $w init


menubutton [set mb $w.history] -text "History" -menu [set m $mb.m] -state disabled; menu $m -tearoff no
set manx(history$w) ""

menubutton [set mb $w.output] -text "Output" -menu [set m $mb.m]; menu $m -tearoff no
set manx(out$w) $w


menubutton [set mb $w.occ] -text "Occasionals" -menu [set m $mb.m]; menu $m
$m add command -label "Help" -command "manHelp $w"
$m add command -label "Statistics and Information" -command "manInfo $w"
$m add command -label "Instantiate New View" -command manInstantiate
$m add command -label "Rebuild Database" -command "manReadSects $w 1 {Rebuilding database ...}" \
-state [expr [file writable [file dirname $manx(database)]]?"normal":"disabled"]

if {$man(glimpseindex)!=""} {
$m add command -label "Rebuild Glimpse Index" -command "manGlimpseIndex $w"
if {$man(time-lastglimpse)!=-1} {$m entryconfigure last -label "Rebuild Glimpse Index (last $man(time-lastglimpse))"}
}
$m add cascade -label "Kill Trees" -menu [set m2 $m.kill]; menu $m2 -tearoff no
$m add cascade -label "Incremental Search Case Sensitive" -menu [set m2 $m.m2]
menu $m2 -tearoff no
$m2 add radiobutton -label "yes" -variable man(incr,case) -value 1
$m2 add radiobutton -label "no" -variable man(incr,case) -value 0
$m2 add radiobutton -label "iff upper" -variable man(incr,case) -value -1
$m add cascade -label "Regexp Search Case Sensitive" -menu [set m2 $m.m3]
menu $m2 -tearoff no
$m2 add radiobutton -label "yes" -variable man(regexp,case) -value 1
$m2 add radiobutton -label "no" -variable man(regexp,case) -value 0
$m2 add radiobutton -label "iff upper" -variable man(regexp,case) -value -1
if {$man(glimpse)!=""} { $m entryconfigure end -label "Regexp and Glimpse Case Sensitive" }	
$m add checkbutton -label "Changebars on Left" -variable man(changeleft) -onvalue "-c" -offvalue ""
$m add command -label "Preferences..." -command manPreferences
$m add command -label "Checkpoint state to $manx(startup-short)" \
-command "manSave; manWinstdout $w {[bolg $manx(startup) ~] updated}"
$m add separator
$m add command -label "Quit, don't update $manx(startup-short)" -command "exit 0"


foreach i {sections hlf links history scf occ} {pack $w.$i -in $w.nav -side left}
foreach i {hlf history occ} {pack configure $w.$i -padx 6}
pack configure $w.links -expand yes -anchor e
pack configure $w.scf -expand yes -anchor w


frame $w.vf
text $t \
-relief sunken -borderwidth 2 \
-yscrollcommand "$w.v set" -exportselection yes -wrap word -cursor $manx(cursor) \
-height 10 -width 5 -insertwidth 0
$t tag configure info -lmargin2 0.5i
bind $w <Configure> "
set tmp \[expr \[winfo width $t\]-2*\[$t cget -padx\]-10\]
$t tag configure info -tabs \[list 0.3i \$tmp right\]
$t tag configure high -tabs \[list \$tmp right\]
"
foreach b {Double-Button-1 Shift-Button-1} { bind Text <$b> {} }
$t tag configure apropos -wrap word

bind $t <Any-KeyPress> "if \[manKeyNav $w \[key_state2mnemon %s\] %K\] break"
bind $t <Control-KeyPress-d> "manShowSection $w \$manx(lastvol$w)"
bind $t <Control-KeyPress-m> "manShowMan \$manx(lastman) {} $w"

bind $t <Button1-Motion> "manHotSpot clear $t 1.0"
bind $t <Button-1> "manHotSpot show %W @%x,%y"
set manx(hotman$t) ""

scrollbar $w.v -orient vertical -command "$t yview"
pack $w.v -in $w.vf -side $man(scrollbarside) -fill y
pack $t -in $w.vf -side $man(scrollbarside) -fill both -expand yes

foreach b [list $w.man $w.apropos] {
bind $b <Shift-ButtonRelease-1> {set manx(shift) 1 }
}
if {$man(glimpse)!=""} {bind $w.glimpse <Shift-ButtonRelease-1> {set manx(shift) 1} }
foreach mb [list $w.vols $w.links $w.history $w.shortcuts] {
bind $mb.m <Shift-ButtonRelease-1> {set manx(shift) 1 }
}



frame $w.search
button $w.search.s -text "Search" -command "
incr stat(page-regexp-next)
set manx(search,cnt$w) \[searchboxSearch \$manx(search,string$w) 1 \$man(regexp,case) search $t $wi $w.search.cnt\]
"
button $w.search.next -text "\xdf" -command "incr stat(page-regexp-next); searchboxNext search $t $wi"
button $w.search.prev -text "\xdd" -command "incr stat(page-regexp-prev); searchboxPrev search $t $wi"
label $w.search.cnt
entry $w.search.t -relief sunken -textvariable manx(search,string$w)
set manx(search,cnt$w) 0
set manx(search,oldstring$w) ""
bind $w.search.t <KeyPress-Return> "
if {\$manx(search,oldstring$w)!=\$manx(search,string$w) || !\$manx(search,cnt$w)} {
set manx(search,oldstring$w) \$manx(search,string$w)
$w.search.s invoke
} else {$w.search.next invoke}"
bind $w.search.t <Control-KeyPress-s> "incr stat(page-incr-next); $w.search.next invoke"
bind $w.search.t <Control-KeyPress-r> "incr stat(page-incr-prev); $w.search.prev invoke"
bind $w.search.t <Control-KeyPress-n> "manKeyNav $w C n"
bind $w.search.t <Control-KeyPress-p> "manKeyNav $w C p"
pack $w.search.s -side left
pack $w.search.next $w.search.prev -side left -padx 4
pack $w.search.t -side left -fill x -expand yes -ipadx 10 -anchor w
pack $w.search.cnt -side left


checkbutton $w.mono -text "Mono" -variable man(currentfont) \
-command "
incr stat(page-mono)
$t configure -font \$man(currentfont)
manManTabSet $w
"

button $w.quit -text "Quit" -command "manSave; exit 0" -padx 4
if !$manx(quit) {$w.quit configure -command "exit 0"}
if $dup {$w.quit configure -text "Close" -command "destroy $w; incr manx(outcnt) -1; manOutput"}
bind all <Meta-KeyPress-q> "$w.quit invoke"

pack $w.mono -in $w.search -side left -padx 3 -anchor e
pack $w.quit -in $w.search -side left -padx 3


pack $wi $w.kind -fill x -pady 4
pack $w.nav -fill x -pady 6
pack $w.vf -fill both -expand yes
pack $w.search -fill x -pady 6


foreach i {info kind nav} {bind $w.$i <Enter> "focus $w.mantypein"}
foreach i {vf show v} {bind $w.$i <Enter> "focus $t"}
bind $w.search <Enter> "focus $w.search.t"
tabgroup $w.mantypein $t $w.search.t
foreach i {mantypein show search.t} {
foreach k {KeyPress-Escape Control-KeyPress-g} {
bind $w.$i <$k> {+ set STOP 1 }
}
}
foreach k {KeyPress-Escape Control-KeyPress-g} {
bind $t <$k> "+ if \[manKeyNav $w \[key_state2mnemon %s\] %K\] break"
}
bind $w.mantypein <KeyPress-Escape> "+
if \[regexp {^\[<|.~/$\]} \$manx(typein$w)\] {manFilecomplete $w}
"

manMakeVolList $w
manPreferencesSetMain $w

manHelp $w

return $w
}

rename winstdout winstdout-default
rename winstderr winstderr-default
proc winstdout {w {msg AnUnLiKeMeSsAgE} {update 0}} { return [manWinstdout [winfo parent $w] $msg $update] }
proc winstderr {w msg {type "bell & flash"}} { return [manWinstderr [winfo parent $w] $msg] }

proc manWinstderr {w msg} {
global man
return [winstderr-default $w.info $msg $man(error-effect)]
}

proc manWinstdout {w {msg AnUnLiKeMeSsAgE} {update 0}} {
return [winstdout-default $w.info $msg $update]
}

proc manManTabSet {w} {
set t $w.show

set state [$t cget -state]; $t configure -state normal
$t insert @0,0 "     \n"
$t configure -tabs [lindex [$t dlineinfo @0,0] 2]
$t delete @0,0 @0,0+6c
$t configure -state $state
}

proc manMakeVolList {w} {
global man manx

set m $w.vols.m
if ![winfo exists $m] return
destroy $m
menu $m -tearoff no

$m add command -label "Last volume viewed" -accelerator "C-d" -state disabled \
-command "manShowSection $w \$manx(lastvol$w)"
$m add separator

set iapropos [lsearch -exact $manx(manList) "apropos"]

set ctr 0
foreach i $manx(manList) j $manx(manTitleList) {

set menu $m; set label "($i) $j"

if $man(subvols) {
set l1 [string range $i 0 0]
set p [lsearch -exact $manx(manList) $l1]
set c [lsearch -glob $manx(manList) "$l1?*"]; if {$c>=$iapropos} {set c -1}

if {$p!=-1 && $c!=-1} {
set menu $m.$p
if {$ctr==$p} {set label "general"}

if ![winfo exists $menu] {
menu $menu -tearoff no
$m add cascade -label "($i) [lindex $manx(manTitleList) $p]" -menu $menu
}
}
}

$menu add command -label $label -command "manShowSection $w $i"
incr ctr
}

manMenuFit $m
}




proc manShortcuts {w cmd} {
global man manx

set me $manx(name$w)
if {![string match "<*" $me]} { append me ".$manx(cursect$w)" }

set modeok [lmatch {man txt} $manx(mode$w)]
if {$cmd!="init" && (!$modeok || $manx(man$w)=="")} return

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

foreach win [lmatches ".man*" [winfo children .]] {
set m [set mb $win.shortcuts].m
$m delete 0 last
set len [llength $man(shortcuts)]
if {$len} {
foreach i $man(shortcuts) {
if {![regexp {^[<|]} $i]} {
if {[lsearch $manx(mandot) $i]>-1} {set name $i} {set name [file rootname $i]}
} else {set name $i}
$m add command -label $name -command "incr stat(man-shortcut); manShowMan [list $i] {} $win"
}
}

configurestate $mb
manShortcutsStatus $win
manMenuFit $m
}
}


proc manShortcutsStatus {w} {
global man manx

set me $manx(name$w)
if {![string match "<*" $me]} { append me ".$manx(cursect$w)" }

set modeok [lmatch {man txt} $manx(mode$w)]
set present [expr [lsearch -exact $man(shortcuts) $me]!=-1]
configurestate $w.sadd [expr $modeok&&!$present]
configurestate $w.ssub [expr $modeok&&$present]
}



proc manHotSpot {cmd t xy} {
global man manx

set manchars {[ a-z0-9_.~/$+()-:<]}


if {$cmd=="clear"} {
$t tag remove hot 1.0 end
set manx(hotman$t) ""
return
}

$t tag remove hot 1.0 end
set manx(hotman$t) ""

scan [$t index $xy] "%d.%d" line char
scan [$t index "$line.$char lineend"] "%d.%d" bozo lineend

set c [$t get $line.$char]
if {$c=="("} {
if {$char>0 && [$t get $line.$char-1c]!=" "} {incr char -1} {incr char}
} elseif {$c==")"} {
if {$char>0} {incr char -1}
}


set lparen 0; set rparen 0
set fspace 0

for {set cn $char} {$cn<=$lineend && [regexp -nocase $manchars [set c [$t get $line.$cn]]]} {incr cn} {
if {$c=="("} {
if {!$lparen} {set lparen $cn} else break
} elseif {$c==")"} {
if {!$rparen} {set rparen $cn; incr cn}
break
} elseif {$c==":" && ([$t get $line.$cn+1c]==" " || [$t get $line.$cn-1c]==" ")} {
break
} elseif {$c==" "} {
if {!$lparen && !$fspace && $cn<$lineend && [$t get $line.$cn+1c]=="("} {set fspace 1} else break
}
}
incr cn -1

for {set c0 $char} {$c0>=0 && [regexp -nocase $manchars [set c [$t get $line.$c0]]]} {incr c0 -1} {
if {$c=="("} {
if {!$lparen} {set lparen $c0} else break
} elseif {$c==")"} {
break
} elseif {$c==":" && ([$t get $line.$c0+1c]==" " || [$t get $line.$c0-1c]==" ")} {
break
} elseif {$c==" "} {
if {$lparen==[expr $c0+1] && !$fspace} {set fspace 1} else break
}
}
incr c0

if {!$lparen^!$rparen} {
if {$lparen} {
if {$char>$lparen} {set c0 [expr $lparen+1]} {set cn [expr $lparen-1]}
set lparen 0
} else {
incr cn -1
}

} elseif {$lparen && [lsearch $man(manList) [$t get $line.$lparen+1c]]==-1} {
if {$char>$lparen} {set c0 [expr $lparen+1]} {set cn [expr $lparen-1]}
set lparen 0

} elseif {$lparen==[expr $rparen-1] && $lparen>0} {
set cn [expr $lparen-1]

} elseif {$lparen && $rparen && [$t get $line.$c0]=="/"} {
incr c0
} 

while {$c0>0 && [lsearch {" "} [$t get $line.$c0]]>=0} {incr c0}
while {$cn>$c0 && [lsearch {. - , " "} [$t get $line.$cn]]>=0} {incr cn -1}


$t tag add hot $line.$c0 $line.$cn+1c
set manx(hotman$t) [string trim [$t get $line.$c0 $line.$cn+1c]]
}


proc manInstantiate {} {
global manx

incr manx(uid)
incr manx(outcnt)
set w [TkMan]
manOutput

return $w
}


proc manOutput {} {
global manx

set wins [lmatches ".man*" [winfo children .]]

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

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

foreach w $wins {
if ![winfo exists $manx(out$w)] {set manx(out$w) $w}
}

if {$manx(outcnt)==1} {
pack forget .man.output
} else {
foreach w $wins {pack $w.output -before $w.occ -padx 2 -side left -expand yes}
}
}

proc manWinSort {a b} {
set an [string range $a 4 end]
set bn [string range $b 4 end]
if {$an==""} {return -1} elseif {$bn==""} {return 1}

if {$an<$bn} {return -1} elseif {$an==$bn} {return 0} else {return 1}
}




proc manHighView {w} {
global manx

set t $w.show
if ![catch {set y $manx(yview,$manx(hv$w))}] {
$t yview moveto $y
$t mark set xmark [$t index @0,0]
}
manHighlights $w get
}



proc manHighlights {w {cmd update} {auto 0}} {
global high man manx mani stat

set m [set mb $w.high].m
$m delete 0 last
set t $w.show
set status ""
set res ""

set f $manx(hv$w)
if ![catch {set sf [file readlink $f]}] {
if [string match /* $sf] {
set f $sf
} else {
set f [file dirname $f]
set strip 1
while {$strip} {
switch -glob $f {
../* {set f [file dirname $f]; set sf [string range $sf 3 end]}
./* {set sf [string range $sf 2 end]}
default {set strip 0}
}
}
append f /$sf
}
}
set var high($manx(manfull$w))
set tags ""
if {$cmd=="update"} {
set tags [clock seconds]
set rawtags [$t tag ranges highlight]
for {set i 0} \$i<[llength $rawtags] {incr i 2} {
set first [lindex $rawtags $i]
set last [lindex $rawtags [expr $i+1]]
eval lappend tags [manHighCompose $t $first $last]
}

set mani(high,form) {}
DEBUG {puts "updating highlights to $tags"}
if {[llength $tags]>1} {set $var $tags} {catch {unset $var}}
set status "updated"

} elseif {[info exists $var]} {
set tags [set $var]

if {[llength [lsecond $tags]]>1} {
set losertxt ""; set dicey 0
set res "new style"

set newtags [lfirst $tags]
for {set i 1} \$i<[llength $tags] {incr i 2} {
set ftuple [lindex $tags $i]
set first [lfirst $ftuple]; set firsttxt [lsecond $ftuple]
set predelta [lthird $ftuple]; set fhooklen [lfourth $ftuple]

set ltuple [lindex $tags [expr $i+1]]
set ldelta [lfirst $ltuple]; set lasttxt [lsecond $ltuple]
set postdelta [lthird $ltuple]; set lhooklen [lfourth $ltuple]

set new [manHighlightAttach $t  $first $firsttxt $predelta $fhooklen   $ldelta $lasttxt $postdelta $lhooklen]
set status [lfirst $new]; set firstnew [lsecond $new]; set ldeltanew [lthird $new]
if {$status=="LOSE"} {
incr stat(high-lose)
append losertxt "[string range $firsttxt 0 [expr $predelta-1]] / [string range $firsttxt $predelta end] ($first)   ...   [string range $lasttxt 0 [expr [string length $lasttxt]-$postdelta]] / [string range $lasttxt [expr [string length $lasttxt]-$postdelta+1] end] (+$ldelta)\n"
append res ", lost one"
} elseif {$firstnew!=$first || $ldeltanew!=$ldelta} {
incr stat(high-move)
eval lappend newtags [manHighCompose $t $firstnew "$firstnew+${ldeltanew}c"]
if {$status=="DICEY"} { set dicey 1; append res ", dicey move" }
} else {
incr stat(high-exact)
lappend newtags $ftuple $ltuple
append res ", exact"
}
}

set warningtxt ""

if {$losertxt!=""} {
manTextPlug $t end "\n\n\nCouldn't attach these highlights:\n" {} $losertxt {} "\n"
append warningtxt "Some highlights could not be repositioned.  See the bottom of the page for a list.  They will be forgotten unless they are reapplied manually now.   "
}
if {$dicey} {
append warningtxt "Some highlights may have been repositioned incorrectly.  You may want to verify them now.   "
}
if {$warningtxt!="" && !$auto} {
tk_dialog .dialog "Warning" $warningtxt "" 0 " OK "
}

set $var $newtags
set tags $newtags

} else {
set res "old style"
if {![file isfile $f] || [file mtime $f]<=[lfirst [set $var]]} {
append res ", OK"
} else {
if {!$auto && ![tk_dialog .dialog "Warning" "Highlights out of date for $f.  Delete them?" "" 1 "No" "Yes"]} {
set $var [set tags "[file mtime $f] [lrange [set $var] 1 end]"]
}
append res ", out of date"
}

after 1 manHighlights $w update
}
}


$t tag remove highlight 1.0 end

for {set i 1} \$i<[set len [llength $tags]] {incr i 2} {
set first [lindex $tags $i]; set last [lindex $tags [expr $i+1]]
if {[llength $first]>1} { set first [lfirst $first]; set last "$first+[lfirst $last]c" }
$t tag add highlight $first $last
if {$auto} { $t yview -pickplace $last; update idletasks; after 1000 }
set label \
[string range [manHighNormalize [$t get $first $last]] 0 $man(high,hcontext)]
$m add command -label $label \
-command "incr stat(page-highlight-go); $t yview \[$t index \"$first - \$man(high,vcontext) lines\"\]"
}

configurestate [list $mb $w.hsub] "$len>1"
manMenuFit $m

return $res
}


proc manHighlightsUpdate {{w .man}} {
global high mani manx

if ![llength [array names high]] return

set t $w.show

set highup 1
foreach i [array names high] {
if [llength [lsecond $high($i)]]>1 { set highup 0; break }
}
if {!$highup || ![tk_dialog .dialog "Update TkMan Highlights?" "Do you want to update your [llength [array names high]] highlighted pages to use new style highlights that are robust to changes in the man page, automatically and in batch now?  Otherwise they can be updated manually one by one at any time." "" 1 " Manual " " Automatic "]} {
return
}


wm deiconify $w
manShowSection $w high

rename manHighView manHighViewX
proc manHighView {w} {}

set newform "The results below will become permanent unless you exit via \"Occasionals / Quit, don't update $manx(startup-short)\"\n\n\n"

foreach man [array names high] {

append newform "$man\t"

if {[llength [lsecond $high($man)]]>1} { append newform "new style\n"; continue }

set stat [manShowMan $man]; update idletasks
if {$stat==""} {
catch {unset high($man)}
set r "doesn't exist"
} else {
set r [manHighlights $w get 1]
update

$t yview 0
}

append newform "$r\n"
}

rename manHighView {}
rename manHighViewX manHighView

set mani(high,form) $newform
manShowSection $w high
}



proc manHighCompose {t first last} {
set excerptmax 30; set hookmax 20

scan [$t index $first] "%d.%d" fline fchar
scan [$t index $last] "%d.%d" lline lchar
set rlen [string length [$t get $first $last]]
set elen [min $excerptmax $rlen]
DEBUG {puts "EXCERPTING first=$first, last=$last, rlen=$rlen, elen=$elen"}

scan [$t index [set fsi "$first linestart"]] "%d.%d" junk fstartchar
scan [$t index [set fei "$first lineend"]] "%d.%d" junk fendchar
set exhooklen [min $elen [expr $fendchar-$fchar+1]]
DEBUG {puts "first\tfstartchar=$fstartchar, fendchar=$fendchar, exhooklen = $exhooklen"}
if {$exhooklen>=$hookmax} {
set hooklen [string length [manHighNormalize [$t get $first $first+${exhooklen}c]]]
set prelen 0
set excerpttxt [manHighNormalize [$t get $first $first+${elen}c]]
} else {
set prei "$first-[expr $hookmax-$exhooklen]c"; if [$t compare $prei < $fsi] { set prei $fsi }
set excerpttxt [manHighNormalize [$t get $prei $first+${elen}c]]
set posti "$first+${elen}c"; if [$t compare $posti > $fei] { set posti $fei }
set hooklen [string length [manHighNormalize [$t get $prei $posti]]]
set prelen [expr $hooklen-[string length [manHighNormalize [$t get $first $posti]]]]
}
DEBUG {puts "|$excerpttxt|, $prelen, $hooklen"}
set firsttag [list $first $excerpttxt $prelen $hooklen]


if {!$hooklen} { return "" }


scan [$t index [set esi "$last linestart"]] "%d.%d" junk lstartchar
scan [$t index [set eei "$last lineend"]] "%d.%d" junk lendchar
set exhooklen [min $elen [expr $lchar-$lstartchar+1]]
DEBUG {puts "end\tlstartchar=$lstartchar, lendchar=$lendchar, exhooklen = $exhooklen"}
if {$exhooklen>=$hookmax} {
set hooklen [string length [manHighNormalize [$t get $last-${exhooklen}c $last]]]
set postlen 0
set excerpttxt [manHighNormalize [$t get $last-${elen}c $last]]
} else {
set posti "$last+[expr $hookmax-$exhooklen]c"; if [$t compare $posti > $eei] { set posti $eei }
set excerpttxt [manHighNormalize [$t get $last-${elen}c $posti]]
set prei "$last-${elen}c"; if [$t compare $prei < $esi] { set prei $esi }
set hooklen [string length [manHighNormalize [$t get $prei $posti]]]
set postlen [expr $hooklen-[string length [manHighNormalize [$t get $prei $last]]]]
}
set lasttag [list $rlen $excerpttxt $postlen $hooklen]
DEBUG {puts "|$excerpttxt|, $hooklen, $postlen"}

return [list $firsttag $lasttag]
}



proc manHighNormalize {raw {maxlen 0}} {
set ws "\[\t\n \]"
set new [string trim $raw]

regsub "\\|+\n" $new "\n" new
regsub "^\\|+$ws" $new "\n" new

regsub -all -- "-\n" $new "\n" new
regsub -all "$ws+" $new " " new

if {$maxlen} { set new [string range $new 0 $maxlen] }

return $new
}

proc manHighRegexp {normal} {
set regexp [stringregexpesc $normal]
regsub -all "\[\t\n \]+" $regexp "\[\t\n |-\]*" regexp
return $regexp
}


proc manHighlightAttach {t first firsttxt predelta fhooklen  ldelta lasttxt postdelta lhooklen   {status "GOOD"}} {
DEBUG {puts "ATTACH: $first $firsttxt $predelta $fhooklen   $ldelta $lasttxt $postdelta $lhooklen  $status"}

if {!$fhooklen} { set fhooktxt $firsttxt } else {
set len [string length $firsttxt]
set fhooktxt [string range $firsttxt 0 [expr $fhooklen-1]]
set fextxt [string range $firsttxt $predelta end]
set fpretxt [string range $firsttxt 0 [expr $predelta-1]]
}
if {!$lhooklen} { set lhooktxt $lasttxt } else {
set len [string length $lasttxt]
set lhooktxt [string range $lasttxt [expr $len-$lhooklen] end]
set lextxt [string range $lasttxt 0 [expr $len-$postdelta-1]]
set lhookextxt [string range $lhooktxt 0 [expr [string length $lhooktxt]-$postdelta-1]]
set lposttxt [string range $lasttxt [expr $len-$postdelta] end]
}

DEBUG {puts "first = $first, |$fhooktxt|\nlast = +$ldelta, |$lhooktxt|"}



if [$t compare $first >= end] { set first [$t index end-1l] }
set flen [string length $fhooktxt]
set fpt ""

set found 0
set fregexp [manHighRegexp $fhooktxt]
set ffw [$t search -forwards -regexp $fregexp $first end]
set fbk [$t search -backwards -regexp $fregexp $first 1.0]
if {$ffw=="" && $fbk==""} {
} elseif {$ffw==""} {
set fpt $fbk
set found 1
DEBUG {puts "only found backward from $first at $fbk"}
} elseif {$fbk==""} {
set fpt $ffw
set found 1
DEBUG {puts "only found foward from $first at $ffw"}
} else {
scan $first "%d.%d" line char
scan $ffw "%d.%d" fline fchar; set difffw [expr $fline-$line]; set dcfw [expr abs($fchar-$char)]
scan $fbk "%d.%d" bline bchar; set diffbk [expr $line-$bline]; set dcbk [expr abs($char-$bchar)]
if {$diffbk<$difffw} {set fpt $fbk} elseif {$difffw<$diffbk} {set fpt $ffw} {
if {$dcbk<$dcfw} {set fpt $fbk} else {set fpt $ffw}
}
set found 1
DEBUG {puts "found point $first forward ($ffw) and back ($fbk), closer is $fpt"}
}
scan $fpt "%d.%d" fline fchar


if {$found} {
if {$fhooklen} {

set must [$t search -forwards -regexp -count delta [manHighRegexp $fpretxt] $fpt end]
set fpt [$t index "$fpt+${delta}c"]

set txt [$t get $fpt "$fpt+1000c"]
if ![regexp -indices -- [manHighRegexp $fextxt] $txt all] { set found 0 }

} elseif {$flen>=20} {
if {[expr abs($line-$fline)>200]} { set found 0 }
}
}

if {!$found} {
if {$fhooklen} {
return [manHighlightAttach $t $first $fextxt 0 0  $ldelta $lasttxt $postdelta $lhooklen  $status]

} elseif {$flen>10} {
set chop [max 9 [expr int($flen/2)]]
return [manHighlightAttach $t $first [string range $fhooktxt 0 $chop] 0 0  $ldelta $lasttxt $postdelta $lhooklen "DICEY"]
} else {
return "LOSE"
}
}



set found 0
set llen [string length $lhooktxt]
set last "$fpt+${ldelta}c-${llen}c"
set lregexp [manHighRegexp $lhooktxt]
set lfw [$t search -forwards -regexp -count lfwcnt $lregexp $last end]
set lbk [$t search -backwards -regexp -count lbkcnt $lregexp $last $fpt]
if {$lfw=="" && $lbk==""} {
} elseif {$lfw==""} {
set lpt $lbk
set llen $lbkcnt
set found 1
DEBUG {puts "end only found backward from $fpt at $lbk"}
} elseif {$lbk==""} {
set lpt $lfw
set llen $lfwcnt
set found 1
DEBUG {puts "end only found foward from $fpt at $lfw"}
} else {
scan $fpt "%d.%d" line char
scan $lfw "%d.%d" fline fchar; set difffw [expr $fline-$line]; set dcfw [expr abs($fchar-$char)]
scan $lbk "%d.%d" bline bchar; set diffbk [expr $line-$bline]; set dcbk [expr abs($char-$bchar)]
if {$diffbk<$difffw} {set lpt $lbk; set llen $lbkcnt} elseif {$difffw<$diffbk} {set lpt $lfw; set llen $lfwcnt} {
if {$dcbk<$dcfw} {set lpt $lbk; set llen $lbkcnt} else {set lpt $lfw; set llen $lfwcnt}
}
set found 1
DEBUG {puts "found end point $fpt forward ($lfw) and back ($lbk), closer is $lpt"}
}


if {$found} {
if {$lhooklen} {
set e [manHighRegexp $lhookextxt]
set posti [$t search -count llen -regexp $e $lpt end]
DEBUG {puts "$t search -count llen -regexp $e $lpt end"}


set e [manHighRegexp $lextxt]; append e "\$"
set txt [$t get "$lpt-1000c" "$lpt+${llen}c"]
if ![regexp -indices -- $e $txt all] { set found 0 }
}

set nldelta [string length [$t get $fpt "$lpt+${llen}c"]]

if {$llen>=20} {
if {$nldelta>[expr 10*$ldelta]} { set found 0 }
}
}

if {!$found} {
if {$lhooklen} {
return [manHighlightAttach $t $fpt $firsttxt $predelta $fhooklen   $ldelta $lextxt 0 0  $status]

} elseif {$llen>10} {
set chop [max 9 [expr int($llen/2)]]
set d [expr $llen-$chop]; set lhooktxt [string range $lhooktxt $d end]
return [manHighlightAttach $t $fpt $firsttxt $predelta $fhooklen  $ldelta $lhooktxt 0 0  "DICEY"]

} else {
set nldelta $ldelta
set status DICEY
}
}


return [list $status $fpt $nldelta]
}



proc manFilecomplete {w} {
global manx

set t $w.show; set wi $w.info
set line $manx(typein$w)
set file [string trim [llast $line] "<"]
set posn [string last $file $line]

set ll [llength [set fc [filecomplete $file]]]

if {!$ll} {
manWinstderr $w "no matches"
return
} elseif {$ll>=2} {
foreach i $fc {lappend matches [file tail $i]}
if {$ll<10} {
manWinstderr $w [lrest $matches]
} else {
manTextOpen $w
$t insert end [lrest $matches]
manTextClose $w
}
set fc [lfirst $fc]
}

set manx(typein$w) [string range $line 0 [expr $posn-1]]$fc

$w.mantypein icursor end
$w.mantypein xview moveto 1
}



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

set t $w.show

set manx(yview,$manx(hv$w)) [lfirst [$t yview]]

set manx(oldmode$w) $manx(mode$w)
set manx(mode$w) $mode
set manx(manfull$w) ""
set manx(catfull$w) ""
set manx(man$w) ""
set manx(name$w) ""
set manx(num$w) ""

set manx(search,oldstring$w) ""
$w.search.cnt configure -text ""
searchboxKeyNav "" Escape 0 $t $w.info 0
after 5 selection clear $t

set manx(vect) 1
set manx(try) 0
destroy $w.sections.m; menu $w.sections.m -tearoff no
$w.links.m delete 0 last



set high(0) disabled; set high(1) normal

set h $high([lmatch {man help info} $mode]); $w.sections configure -state $h
set h $high([lmatch {man txt help} $mode])
foreach i {hadd} {$w.$i configure -state $h}
if {![lmatch {man txt help} $mode]} {
foreach i {high hsub} {$w.$i configure -state disabled}
}
set h $high([lmatch {man help} $mode]); $w.links configure -state $h
if {![lmatch {man txt} $mode]} {
foreach i {sadd ssub} {$w.$i configure -state disabled}
}
set h $high([lmatch man $mode]); $w.occ.m entryconfigure "Kill Trees" -state $h

manHyper $w $n
}


proc manHyper {w {n ""}} {
global man manx

set t $w.show

foreach i {"Double-" ""} {
foreach j {"" "Alt-" "Shift-"} {
bind $t <${j}${i}ButtonRelease-1> "format nothing"
}
}

if {$man(hyperclick)=="double"} {set mod "Double-" } { set mod "" }
bind $t <ButtonRelease-1> "
if {\$manx(hotman$t)!={}} { set manx(typein$w) \$manx(hotman$t) }
"
bind $t <${mod}ButtonRelease-1> "+
if {\$manx(hotman$t)!={}} { incr stat(man-hyper); manShowMan \$manx(hotman$t) $n $w }
"
bind $t <Shift-${mod}ButtonRelease-1> "
if {\$manx(hotman$t)!={}} { incr stat(man-hyper); set manx(shift) 1; manShowMan \$manx(hotman$t) $n $w }
"
bind $t <Alt-${mod}ButtonRelease-1> "
if {\$manx(hotman$t)!={}} { set manx(typein$w) \$manx(hotman$t); manShowMan <\$manx(hotman$t) $w }
"

}




proc manTextPlug {t posn args} {
set state [$t cget -state]
$t configure -state normal
eval $t insert $posn $args
$t configure -state $state
}

proc manTextOpen {w} {
global man

cursorBusy
set t $w.show
$t configure -state normal
$t delete 1.0 end
foreach i [$t mark names] {if {$i!="insert"&&$i!="current"} {$t mark unset $i}}
$t configure -font $man(currentfont)
}

proc manTextClose {w} {
set t $w.show

if {[$t get "end -1c"]=="\n"} {$t delete "end -1c"}

$t configure -state disabled
cursorUnset
$t mark set xmark 1.0
}

proc manResetEnv {} {
global env man manx mani

set manpath {}
foreach i $manx(paths) {if {$man($i)} {append manpath :$i}}
set env(MANPATH) [string range $manpath 1 end]

foreach i $manx(manList) {
if {[lsearch $manx(specialvols) $i]==-1 || $i=="all"} {set mani($i,form) ""}
}
}

proc manSetSect {w n} {
global manx mani

set manx(cursect$w) *

if [regexp {^/} $n] {
set dir [file dirname $n]
foreach vol $mani(manList) {
if [lsearch -exact $mani($vol,dirs) $dir]!=-1 {
set manx(cursect$w) $vol
break
}
}

} elseif {[set f [lsearch $manx(manList) $n]]!=-1} {
set manx(cursect$w) $n
}
}

proc manMenuFit {m} {
global man manx

if {[winfo class $m]!="Menu"} {puts stderr "$m not of Menu class"; exit 1}
if {[$m index last]=="none"} return

set sh [winfo screenheight $m]

set ok 0
for {set i [expr [lsearch $manx(sizes) $man(gui-points)]+1]} {$i>=0} {incr i -1} {
set p [lindex $manx(pts) $i]
set f [spec2font $man(gui-family) $man(gui-style) $p]
$m configure -font $f; update idletasks
set mh [winfo reqheight $m]
if {$mh<$sh} {set ok 1; break}
}

if {!$ok} {
set ctr 0
while {[winfo reqheight $m]>=$sh} {
$m delete last; incr ctr; update idletasks
}
$m delete last; incr ctr
$m add command -label "($ctr too many to show)" -state disabled
}
}



proc manInit {} {
global man manx mani

if {$manx(init)} return

manReadSects
manResetEnv
set manx(init) 1
}


proc manReadSects {{w .man} {force 0} {msg "Building database ..."}} {
global man manx mani env

set wi $w.info
zapZ! manx(database)

set dbdir [file dirname $manx(database)]
set database [lfirst [glob -nocomplain $manx(database).$manx(zglob)]]

if {$database=="" || $force || $manx(rebuildandquit)} {
cursorBusy
manWinstdout $w $msg 1

catch {eval exec $man(rm) -f [glob $manx(database).$manx(zglob)]}
set tmpfile $dbdir/.tkmantmp
if [catch {set fid [open $tmpfile w]} info] {
puts stderr "Cannot write temporary information to $tmpfile\n=> $info"
exit 1
}
set manx(manList) ""; set manx(manTitleList) ""; set manx(mandot) ""
set manx(newmen) {}
set lastv ""
set total 0
set buildtime [time {
foreach i $mani(manList) j $mani(manTitleList) {
set nowv [string range $i 0 0]
if {$nowv==$lastv} {set more [string range $i 1 end]} {set more " $i"}
set lastv $nowv
manWinstdout $w "[manWinstdout $w]$more" 1
if {[set cnt [manReadSection $i $fid]]!=0} {
lappend manx(manList) $i; lappend manx(manTitleList) $j
incr total $cnt
}
}}]
close $fid
set man(time-lastdatabase) [expr [lfirst $buildtime]/1000000]

if [catch {set fid [open $manx(database) w]} info] {
puts stderr "Cannot write database to $manx(database)\n=> $info"
exit 1
}
puts $fid "#\n# TkMan v$manx(version) database\n#"
puts $fid "# created at [clock format [clock seconds]]"
puts $fid "# build time $man(time-lastdatabase) seconds for $total pages"
puts $fid "#"

puts $fid "# set manx(db-manpath) $manx(MANPATH0)"
puts $fid "# set manx(db-signature) [manDBsignature]"

puts $fid "# set manx(newmen) [list $manx(newmen)]"

foreach i {manList manTitleList mandot} {
puts $fid "# set manx($i) {$manx($i)}"
}

set fid2 [open $tmpfile]
puts -nonewline $fid [read $fid2]
close $fid2
close $fid

if [catch {eval exec $man(compress) $manx(database)} info] {
if ![string match "*%*" $info] {
puts stderr "Problem compressing database\n=> $info"
exit 1
}
}
eval exec $man(rm) -f $tmpfile
set database [glob $manx(database).$manx(zglob)]

cursorUnset
manWinstdout $w "Database created in file [bolg $database ~]"

}
if $manx(rebuildandquit) {exit 0}



set manx(database) $database

set fid [open "|$man(zcat) $manx(database)"]
while {[gets $fid line]!=-1 && [regexp {^#} $line]} {
if {[regexp {^# (set .*)} $line all set]} {eval $set}
}
catch {close $fid}




set maxdir ""; set maxdirtime 0
foreach i $mani(manList) {
scan [manLatest $mani($i,dirs)] "%d %s" mstime msdir
set mani($i,update) $mstime
if {$maxdirtime<$mstime} {set maxdirtime $mstime; set maxdir $msdir}
}
set manx($manx(glimpsestrays),latest) $maxdirtime

ASSERT file exists $database
set rmsg ""
if {$manx(now)} {
set manx(now) 0
} elseif {[file mtime $database]<$maxdirtime || 
([file mtime $database]<$manx(mtimeargv0) && !$manx(debug))} {
set rmsg "Database out of date"
} elseif {$manx(MANPATH0)!=$manx(db-manpath)} {
set rmsg "MANPATH changed"
DEBUG {puts "$manx(db-manpath) => $manx(MANPATH0)"}
} elseif {[manDBsignature]!=$manx(db-signature)} {
set rmsg "New tkmandesc configuration"
DEBUG {puts "$manx(db-signature) =>\n[manDBsignature]"}
}
if {[string length $rmsg]} {
if ![file writable $dbdir] {
after 2 "manWinstderr $w \"$rmsg ... but database directory not writable\""
} else {
manReadSects $w 1 "$rmsg, rebuilding ..."
set newupdate [file mtime $manx(database)]
if {$newupdate<$maxdirtime} {
set errmsg "
Problem with file and directory times...\a\a
The newly created database ($manx(database)) has its time set
earlier than the $maxdir directory and perhaps others.
Unless corrected, the database will be rebuilt every time
TkMan is started.  Perhaps you need to reset your system clock.
"
puts stderr [linebreak $errmsg 70]
}

return
}
}

if ![llength $manx(manList)] {
puts stderr "Can't find any man pages!"
puts stderr "MANPATH = $env(MANPATH)"
exit 1
}

foreach i $manx(manList) {set mani($i,form) ""}

foreach i $manx(extravols) {
set letter [lfirst $i]; set title [lsecond $i]; set msg [lthird $i]
lappend manx(manList) $letter; lappend manx(manTitleList) $title
set mani($letter,form) $msg; set mani($letter,cnt) 0; set mani($letter,update) ""
}


foreach win [lmatches ".man*" [winfo children .]] {
manMakeVolList $win
$win.occ.m entryconfigure "Rebuild Database*" -label "Rebuild Database (last took $man(time-lastdatabase) sec)"
}
}


proc manLatestMan {root} {

set men [glob -nocomplain "$root/man?*"]
if {$men==""} {
set men [glob -nocomplain "$root/*"]
}

return [manLatest $men]
}

proc manLatest {dirs} {
global mani

set max 0; set maxdir ""
foreach sub $dirs {
if {[file isdirectory $sub]} {
set mtime [file mtime $sub]
set mani($sub,update) $mtime
if {$mtime>$max} { set max $mtime; set maxdir $sub }
}
}

return [list $max $maxdir]
}




proc manDBsignature {} {
global mani

set sig "X"
foreach i $mani(manList) {
if [llength $mani($i,dirs)] {append sig $i[llength $mani($i,dirs)]}
}
return $sig
}




proc manReadSection {n fid} {
global man manx mani env

if ![llength $mani($n,dirs)] {return 0}

set title [lindex $mani(manTitleList) [lsearch $mani(manList) $n]]
DEBUG { puts -nonewline stderr $n }
set first 1
set cnt 0

set recentdef [expr [clock seconds]-$man(recentdays)*24*60*60]
set short {}
foreach i $mani($n,dirs) {
foreach f [glob -nocomplain $i/*] {
catch [
if {[file isfile $f] && [file mtime $f]>$recentdef && ![string match "*~" $f]} {
lappend short [zapZ [file tail $f]]
}]
}
}
if {$short!=""} {lappend manx(newmen) [list $n $short]}


foreach i $mani($n,dirs) {
set dirs "$i/*"
set root [file dirname $i]
if {[regsub {/man([^/]+)$} $i {/cat\1} d2] && [file isdirectory $d2] && [file readable $d2]} {
lappend dirs "$d2/*"
}
DEBUG {	puts "  checking $dirs" }

if {[catch {set escmen [stringesc [eval glob $dirs]]}]} continue
regsub -all " " $escmen "\n" fullmen; append fullmen "\n"
if {$first} {puts $fid "$n [list $title]"; set first 0}

foreach k [exec $man(sed) -e {/~$/d} -e {/.bak$/d} -e {s/\.gz$//} -e {s/\.Z$//} -e {s/\.[^/\.]*$//} -e s'$d2'$i' << $fullmen | $man(sort) | $man(uniq)] {
puts $fid $k
incr cnt

set f [file tail $k]
if {[string match "*.*" $f]} {lappend manx(mandot) $f}
}
}

return $cnt
}


proc manFormatSect {n} {
global man manx mani high

set form ""

if {$n=="high"} {
set mani(high,form) ""
set ltmp [lsort -command manSortByName [array names high]]
foreach k $ltmp {
if {[llength $k]>1} continue
append mani(high,form) $k
if {[llength [lsecond $high($k)]]>1} { append mani(high,form) "\t[recently [lfirst $high($k)]]" }
append mani(high,form) "\n"
}
set mani(high,cnt) [llength $mani(high,form)]
if {$mani(high,cnt)==0} {set mani(high,form) "No manual pages have been annotated.\n"}

return

} elseif {$n=="recent"} {
set first 1; set form ""; set cnt 0
foreach i $manx(newmen) {
set vol [lfirst $i]; set names [lsecond $i]
if {$first} {set first 0} {append form "\n\n\n"}
if {[set index [lsearch $mani(manList) $vol]]!=-1} {
set voltxt "Volume $vol, \"[lindex $mani(manTitleList) $index]\", updated at [recently $mani($vol,update)]"
} else { set voltxt $vol }
append form "$voltxt\n\n"
foreach j $names {append form $j "\t"; incr cnt}
}
set mani(recent,cnt) $cnt
if {$mani(recent,cnt)==0} {
set form "There are no manual pages less than $man(recentdays) day"
if {$man(recentdays)>1} {append form "s"}
append form " old.\n"
append form "You can change the definition of `recent' in Occasionals/Preferences/Misc.\n"
}
set mani(recent,form) $form
return
}


set nextn [lindex $manx(manList) [expr [lsearch -exact $manx(manList) $n]+1]]
if {$n=="all"} {set sect ""} {set sect "-e {/^$n /,/^$nextn /!d}"}
set sed "$man(sed) $sect -e {/ /d}"
foreach i $manx(paths) {
if {[info exists man($i)] && !$man($i)} {
append sed " -e {\\?^$i?d}"
}
}
append sed " -e {s/.*\\///g}"
DEBUG {puts "sed = $sed"}
set ltmp [eval exec "$man(zcat) $manx(database) | $sed | $man(sort)"]

if {$man(volcol)=="0"} {set sep "   "} {set sep "\t"}
set cnt 0

set pr ""; set pl ""
set online 0; set skip 0
foreach ir $ltmp {
set il [string tolower [string range $ir 0 0]]

if {$pl!=$il && $online>0} {
append form "\n\n"
set online 0
}

if {$pr!=$ir} {
if {$online!=0} {append form $sep}
append form $ir; incr online
}

set pr $ir; set pl $il
incr cnt
}

if {!$cnt} {set form "No man pages in currently enabled paths.\nTry turning on some under the Paths pulldown menu."}
set mani($n,form) $form
set mani($n,cnt) $cnt
}





proc manDescDefaults {} {
global man manx mani env

manDescManiCheck return

if [info exists env(LANG)] {set langs [split $env(LANG) ":"]} {set langs ""}
foreach i $mani(manList) { set mani($i,dirs) {} }
foreach i $manx(paths) { set mani($i,dirs) {} }
set mani($man(glimpsestrays),dirs) {}
set curdir [pwd]

foreach i $manx(paths) {
cd $i
set alldirs [glob -nocomplain $manx(subdirs)]
foreach l $langs {
set alldirs [concat $alldirs [glob -nocomplain $l/$manx(subdirs)]]
}
DEBUG {puts "    sorted alldirs = [lsort -command bytypenum $alldirs]"}
foreach d [lsort -command bytypenum $alldirs] {
if {[string match "*/*" $d]} {
set lang "[file dirname $d]/"; set dir [file tail $d]
} else {set lang ""; set dir $d }
set dirsig [string range $dir $manx(dirnameindex) end]
if {[string match "cat*" $dir]} {set dirsig [file rootname $dirsig]}
set num [file rootname $dirsig]; set num1 [string index $num 0]

if {[lsearch -exact $mani(manList) $num]!=-1} {set n $num} {set n $num1}

set pat "^[stringregexpesc $i]/${lang}(man|cat)[stringregexpesc $dirsig]\$"
set dir $i/$d
if {[lsearch -regexp $mani($i,dirs) $pat]==-1 && [manPathCheckDir $dir]==""} {
lappend mani($i,dirs) $dir
lappend mani($n,dirs) $dir
}
}
DEBUG {puts "mani($i,dirs) = $mani($i,dirs)"}
}
DEBUG {foreach i $mani(manList) { puts "mani($i,dirs) = $mani($i,dirs)" }}

cd $curdir
set manx(defaults) 1
}

proc bytypenum {a b} {
if [string match "*/*" $a] { set al [file dirname $a]; set a [file tail $a] } {set al ""}
if [string match "*.Z" $a] { set as [file extension $a]; set a [file rootname $a] } {set as ""}
set at [string range $a 0 2]
if [string match "*/*" $b] { set bl [file dirname $b]; set b [file tail $b] } {set bl ""}
if [string match "*.Z" $b] { set bs [file extension $b]; set b [file rootname $b] } {set bs ""}
set bt [string range $b 0 2]

if {$al!=$bl} {
if {$al==""} {return 1} elseif {$bl==""} {return -1} elseif {$al<$bl} {return -1} {return 1}
} elseif {$at!=$bt} {
if {$at=="man"} {return -1} {return 1}
} elseif {$as!=$bs} {
if {$as==""} {return 1} {return -1}
} else {
if {$a<$b} {return -1} {return 1}
}

return 0
}



proc manDescMove {from to dirs} {manDesc move $from $to $dirs}
proc manDescDelete {from dirs} {manDesc delete $from "" $dirs}
proc manDescCopy {from to dirs} {manDesc copy $from $to $dirs}
set manx(mandesc-warnings) ""
proc manDescAdd {to dirs} {
global mani manx man

set manx(mandesc-warnings) ""
set warnings ""

manDescManiCheck
foreach d $dirs {
if {[set warnmsg [manPathCheckDir $d]]!=""} {
append warnings $warnmsg
} else {
foreach t $to {lappend mani($t,dirs) $d}

DEBUG {puts "MANPATH for $d?"}
set mp $d
while {[string match "/*" $mp] && $mp!="/"} {
if {[lsearch -exact $manx(paths) $mp]>=0} {
DEBUG {puts "\tyes, in $mp"}
lappend mani($mp,dirs) $d; break
} else {set mp [file dirname $mp]}
}
if {$mp=="/"} { lappend mani($man(glimpsestrays),dirs) $d
DEBUG {puts "\tno, added to strays\n\t\tnow mani($man(glimpsestrays),dirs) =  $mani($man(glimpsestrays),dirs)"}
}
}
}


if {$warnings!=""} {
if ![string match *manDescAdd* $manx(mandesc-warnings)] {
append manx(mandesc-warnings) "Problems with manDescAdd's...\n"
}
append manx(mandesc-warnings) $warnings
}
}


proc manDesc {cmd from to dirs} {
global man manx mani

manDescManiCheck
if {$from=="*"} {set from $mani(manList)}
if {$to=="*"} {set to $mani(manList)}
foreach n [concat $from $to] {
if [lsearch $mani(manList) $n]==-1 {
puts stderr "$cmd: Section letter `$n' doesn't exist."
exit 1
}
}

DEBUG {puts stdout "$cmd {$from} {$to} {$dirs}"}
foreach d $dirs {
foreach f $from {
set newdir {}
foreach fi $mani($f,dirs) {
if [string match $d $fi] {
if {$cmd=="copy"} {lappend newdir $fi}
if {$cmd=="copy"||$cmd=="move"} {
foreach t $to {if {$f!=$t} {lappend mani($t,dirs) $fi} {lappend newdir $fi}}
}
} else {lappend newdir $fi}
}
set mani($f,dirs) $newdir
DEBUG {puts stdout $f:$mani($f,dirs)}
}
}
}

proc manDescAddSects {l {posn "end"} {what "n"}} {
global man mani

manDescManiCheck
if {$posn=="before"||$posn=="after"} {set l [lreverse $l]}
foreach i $l {
set n [lfirst $i]; set tit [lsecond $i]
if [lsearch $mani(manList) $n]!=-1 {
puts stderr "Section letter `$n' already in use; request ignored."
continue
}

if {$posn=="end"} {
lappend mani(manList) $n
lappend mani(manTitleList) $tit

} elseif {$posn=="before"||$posn=="after"} {
if [set ndx [lsearch $mani(manList) $what]]==-1 {
puts stderr "Requested $posn $what, but $what doesn't exist; request ignored"
continue
}
if {$posn=="after"} {incr ndx}
set mani(manList) [linsert $mani(manList) $ndx $n]
set mani(manTitleList) [linsert $mani(manTitleList) $ndx $tit]

} elseif {$posn=="sort"} {
lappend mani(manList) $n
set mani(manList) [lsort $mani(manList)]
set ndx [lsearch $mani(manList) $n]
set mani(manTitleList) [linsert $mani(manTitleList) $ndx $tit]
}

set mani($n,dirs) {}
}
}



proc manDescManiCheck {{action "exit"}} {
global man mani manx env

if {!$manx(manDot)} manDot

if ![info exists mani(manList)] {
set mani(manList) $man(manList)
set mani(manTitleList) $man(manTitleList)

manManpathSet
manManpathCheck

if {$action=="return"} return
manDescDefaults
}
}



proc manDescSGI {patterns} {
global man manx mani


set paterrs 0
foreach pat $patterns {
set mapto [lfirst $pat]; set patlist [lsecond $pat]

if [lsearch -regexp $mani(manList) ".?$mapto"]==-1 {
puts stderr "no volume corresponding to $mapto mapping (patterns: $patlist)"
incr paterrs
}

foreach p $patlist {
foreach pat2 $patterns {
if {$pat==$pat2} break
set mapto2 [lfirst $pat2]; set patlist2 [lsecond $pat2]
foreach p2 $patlist2 {
if [string match $p2 $p] {
puts stderr "pattern $p never reached -- $mapto2's $p2 precludes it"
incr paterrs
}
}
}
}
}

lappend patterns {"" {""}}
DEBUG {puts "mani(manList) => $mani(manList)"}

set catmen {}
foreach d $manx(paths) {
if [string match "*/catman" $d] { lappend catmen $d }
}
if ![llength $catmen] {
puts stderr "No sneaky catman directories found in MANPATH:\n\t$manx(MANPATH0)"
return
}


set rcats $catmen; set catmandirs {}
for {set i 0} {$i<[llength $rcats]} {incr i} {
foreach f [glob -nocomplain [lindex $rcats $i]/*] {
if {![string match "*.z" $f] && [file isdirectory $f] && [lsearch -exact $rcats $f]==-1} {
lappend rcats $f; lappend catmandirs $f
}
}
}

foreach dir $catmandirs {
if [regexp {(catman|_man)$} $dir] continue
set tail [file tail $dir]
set vol [file tail [file dirname $dir]]
if ![regexp "^(man|cat)" $vol] { set vol $tail; set tail "" }

set volnum [string range $vol 3 3]

DEBUG {puts -nonewline "$dir ($vol:$tail ($volnum)) => "}
set matched 0
foreach pat $patterns {
set mapto [lfirst $pat]; set patlist [lsecond $pat]
foreach dp $patlist {
if [string match "*$dp" $dir] {
DEBUG {puts -nonewline "match on $dp => "}
set matched 1
if [lsearch -exact $mani(manList) "$volnum$mapto"]!=-1 {
DEBUG {puts $volnum$mapto}
manDescAdd "$volnum$mapto" $dir

} elseif [lsearch -exact $mani(manList) $mapto]!=-1 {
DEBUG {puts $mapto}
manDescAdd $mapto $dir

} elseif [lsearch -exact $mani(manList) $volnum]!=-1 {
DEBUG {puts $volnum}
manDescAdd $volnum $dir

} else {
DEBUG {puts "can't place"}
}

break
}
}
if {$matched} break
}
DEBUG {if {!$matched} {puts "CAN'T MATCH\a\a"}}
}
}



proc manDescShow {} {
global man manx mani

manDescManiCheck
puts stdout "*** manDescShow"
foreach i $mani(manList) {
puts stdout $i:$mani($i,dirs)
}
}



proc manBug {w} {
global man manx mani high default stat env argv0

if $manx(shift) { set manx(shift) 0; set w [manInstantiate] }
set t $w.show; set wi $w.info; set m $w.sections.m

manNewMode $w bug; incr stat(bug)
set manx(hv$w) bug
set head "Submit Bug Report"
wm title $w $head
manWinstdout $w $head
$w.search.cnt configure -text ""

manTextOpen $w

$t insert end "Select all the text below and paste into your e-mail program.\n"
$t insert end "Before submitting a bug report, first check the home ftp site (ftp://ftp.cs.berkeley.edu/ucb/people/phelps/tcltk) to make sure it hasn't already been fixed in a later version." i "\n\n"


$t insert end "To: phelps@ACM.org\n"
$t insert end "Subject: TkMan bug report\n\n"

$t insert end "Describe the problem:\n\n\n\n" h1


$t insert end "System description information\n\n" h1

$t insert end "X Windows version: _____\n"
$t insert end "window manager: ______\n"

global tk_patchLevel
$t insert end "TkMan version $manx(version)\n"
$t insert end "MANPATH = $manx(MANPATH0)\n"
$t insert end "Tcl [info patchlevel]/Tk $tk_patchLevel\n"
catch { $t insert end "Hardware: [exec uname -a]\n" }

if {[file readable $manx(startup)]} {
$t insert end "\n\nVariables overridden in [bolg $manx(startup) ~]\n\n" h1
set allold 1
foreach i [lsort [array names default]] {
set new [tr $man($i) \n " "]; if {$new==""} {set new "(null)"}
set old [tr $default($i) \n " "]; if {$old==""} {set old "(null)"}
if {$new!=$old} {
$t insert end "man(" {} $i b ") = " {} $new tt ", " {} "formerly " i $old tt "\n"
set allold 0
}
}
if {$allold} { $t insert end "None\n" }
$t insert end "\n\n\n"
}

if 0 {
if [file readable $argv0] {
$t insert end "First few lines of `tkman' executable\n\n" h1
set fid [open $argv0]
for {set i 0} \$i<6 {incr i} {$t insert end [gets $fid] {} \n}
catch {close $fid}
}

}

manTextClose $w
manHighView $w
}



proc manInfo {w} {
global man manx mani high default stat env

if $manx(shift) { set manx(shift) 0; set w [manInstantiate] }
set t $w.show; set wi $w.info; set m $w.sections.m

manNewMode $w info; incr stat(info)
set manx(hv$w) info
set head "Statistics and Information"
wm title $w $head
manWinstdout $w $head

manTextOpen $w

$m add command -label "Statistics" -command "incr stat(page-section); $t yview 1.0"
$t insert end "Statistics  " h1

$t insert end "since startup at [clock format $manx(startuptime) -format $man(date-format)]" i
$t insert end "\t\[cumulative since [clock format $stat(cum-time) -format $man(date-format)]\]\n\n" i
manStatsSet

foreach i $manx(modes) desc $manx(mode-desc) {
$t insert end "$stat($i)\t$desc " "" "\[$stat(cum-$i)\]\n" i
if {$i=="man"} {
$t delete end-1c
$t insert end ", $stat(man-no) not found " "" "\[$stat(cum-man-no)\]\n" i
$t insert end "\t"
set first 1
foreach j $manx(stats) desc $manx(stats-desc) {
if [string match "man-*" $j] {
if {!$first} {$t insert end ",  "}
$t insert end "$stat($j)  $desc " "" "\[$stat(cum-$j)\]" i
set first 0
}
}
$t insert end "\n"
}
}

set pageops 0; set cpageops 0
foreach i [array names stat page-*] {
incr pageops $stat($i)
incr cpageops $stat(cum-$i)
}
$t insert end "$pageops\tpage navigation operations " "" "\[$cpageops\]\n" i
$t insert end "\t"
set first 1
foreach j $manx(stats) desc $manx(stats-desc) {
if [string match "page-*" $j] {
if {!$first} {$t insert end ",  "}
$t insert end "$stat($j)  $desc " "" "\[$stat(cum-$j)\]" i
set first 0
}
}
$t insert end "\n"

$t insert end "$stat(high-move)\thighlights repositioned automatically  " "" "\[$stat(cum-high-move)\]\n" i
$t insert end "$stat(high-lose)\thighlights unattachable  " "" "\[$stat(cum-high-lose)\]\n" i

$t insert end "$stat(print)\tpages printed  " "" "\[$stat(cum-print)\]\n" i

global tk_patchLevel
$t insert end "\nTkMan version $manx(version)\n"
$t insert end "Running under Tcl [info patchlevel]/Tk $tk_patchLevel\n"
$t insert end "[info cmdcount] Tcl commands executed\n"
catch { $t insert end "Hardware: [exec uname -a]\n" }


if {[file readable $manx(startup)]} {
$m add command -label "Variables" -command "incr stat(page-section); $t yview [$t index end]"
$t insert end "\nVariables overridden in [bolg $manx(startup) ~]\n\n" h1
set allold 1
foreach i [lsort [array names default]] {
set new [tr $man($i) \n " "]; if {$new==""} {set new "(null)"}
set old [tr $default($i) \n " "]; if {$old==""} {set old "(null)"}
if {$new!=$old} {
$t insert end "man(" {} $i b ") = " {} $new tt ", " {} "formerly " i $old tt "\n"
set allold 0
}
}
if {$allold} { $t insert end "None\n" }
}

$m add command -label "Full Paths" -command "incr stat(page-section); $t yview [$t index end]"
$t insert end "\nFull paths of supporting executables\n\n" h1
set allfull 1
foreach i $manx(binvars) {
set val [set $i]
$t insert end "$i = $val.   "
foreach j [split $val "|"] {
set bin [lfirst $j]
if ![string match "/*" $bin] {
$t insert end "  $bin" b " => " "" $stat(bin-$bin) tt
set allfull 0
}
if [info exists stat(bin-$bin-vers)] { $t insert end "  (v$stat(bin-$bin-vers))" }
}
$t insert end "\n"
}
if {!$allfull} {
$t insert end "\n" "" "PATH" tt "  environment variable is " "" $env(PATH) tt "\n"
}


$m add command -label "Dates" -command "incr stat(page-section); $t yview [$t index end]"
$t insert end "\nDates\n\n" h1
if {[file readable $manx(startup)]} {
$t insert end "Startup " b "file last save\n\t" {} $manx(startup) tt "\t" {} [recently [file mtime $manx(startup)]] i "\n"
}
$t insert end "Man page " {} "database" b " last update\n\t" {} $manx(database) tt "\t" {} [recently [file mtime $manx(database)]] i "\n"
if {$man(glimpse)!=""} {
if {$man(indexglimpse)=="distributed"} {
$t insert end "Distributed Glimpse " {} "indexes" b " latest updates\n"
set paths $manx(paths)
} else { 
$t insert end "Unified Glimpse " {} "index" b " latest update\n"
set paths $man(glimpsestrays)
}

foreach i $paths {
set db $i/.glimpse_index
$t insert end "\t" {} $i tt "\t"
if [file exists $db] {
$t insert end [recently [file mtime $db]] i "\n"
} else { $t insert end "no index" b "\n" }
}
}


$m add command -label "Volume Mappings" -command "incr stat(page-section); $t yview [$t index end]"
$t insert end "\nVolume-to-directory mappings\n\n" h1

set manpath0 [join $manx(paths) ":"]
$t insert end "MANPATH" sc ": " "" $manpath0 tt "\n"
if {$manx(MANPATH0)!=$manpath0} {
$t insert end "As cleaned up from original " "" "MANPATH" sc ": "
foreach path [split $manx(MANPATH0) ":"] {
$t insert end $path [expr [lsearch -exact $manx(paths) $path]==-1?"i":"tt"] ":" tt
}
$t delete end-2c; $t insert end "\n"
}
$t insert end "\n"

foreach i $mani(manList) {
if {![llength $mani($i,dirs)]} continue
$t insert end "Volume $i, [lindex $mani(manTitleList) [lsearch $mani(manList) $i]]\n" b
foreach j $mani($i,dirs) { 
$t insert end "\t" {} $j tt "\t" {} [recently $mani($j,update)] i "\n"
}
}


$m add command -label "Change Log" -command "incr stat(page-section); $t yview [$t index end]"
$t insert end "\nLog of Some Less-trivial Changes\n" h1
$t insert end $manx(changes)

$t tag add info 1.0 end
manTextClose $w

scan [$t index end] %d eot
$w.search.cnt configure -text "$eot lines"

manHighView $w
}



proc manShowSection {w n} {
global man manx mani high font stat

if {[lsearch $manx(manList) $n]==-1} { manWinstderr $w "Volume $n not found"; return }
if $manx(shift) { set manx(shift) 0; set w [manInstantiate] }
set t $w.show; set wi $w.info

manNewMode $w section $n; incr stat(section)
wm title $w "$manx(title$w): Volume $n"
set manx(lastvol$w) $n
set manx(hv$w) $n

set head [lindex $manx(manTitleList) [lsearch $manx(manList) $n]]

if {$mani($n,form)==""} {
cursorBusy
manWinstdout $w "Formatting $head ..." 1
manFormatSect $n
cursorUnset
}

set info $head
manWinstdout $w $info
manSetSect $w $n

manTextOpen $w
$t insert end $mani($n,form)
$w.search.cnt configure -text "$mani($n,cnt) entries"
manTextClose $w

manHighView $w
if {$n=="apropos" || $n=="high"} { set tag $n } else { set tag volume }
$t tag add $tag 1.0 end

set lastvol [$w.vols.m cget -tearoff]
$w.vols.m entryconfigure $lastvol -label "($n) $head" -state normal
set manx(name$w) $head
}


proc manSortByName {a b} {
set c [string tolower [file tail $a]]; set d [string tolower [file tail $b]]
if {$c<$d} {set cmp -1} elseif {$c==$d} {set cmp 0} {set cmp 1}
return $cmp
}




proc manShowMan {fname {goodnum ""} {w .man}} {
global man manx mani env stat

if $manx(shift) { set manx(shift) 0; set w [manInstantiate] }
set wi $w.info

if {[string trim $fname]==""} return
if {[lsearch $manx(specialvols) $goodnum]!=-1} {set goodnum ""}

if {[regexp {^(\.\./|\./|[~/$])} $fname]} {
return [manShowManFound [fileexp [lfirst $fname]] 0 $w]
}


if {[regexp {^[|<]} $fname]} {manShowText $fname $w; return}



regsub "\\\\" $fname "\a" fname

set oname [string trimright [string trim [lfirst $fname] { ,?!;"'}] .]
if {$goodnum!=""} {set tmp "($goodnum)"} {set tmp ""}
manWinstdout $w "Searching for \"$oname$tmp\" ..." 1
set fname [string tolower $oname]; # lc w/  () for regexp
set sname [string trim $fname ()]; # lc w/o ()
set oname [string trim $oname ()]; # original case w/o ()

set name $sname; set num ""; set ext ""

if {[regexp -nocase {([a-z0-9_.+-]+)([\t ]*)\(([^)]?)(.*)\)} $fname \
all name spc num ext]} {

} elseif {[regexp {(.+)\.(.)([^.]*)$} $oname all namex sectx extx]
&& [lsearch -exact $manx(manList) $sectx]!=-1
&& [lsearch -exact $manx(mandot) $oname]==-1} {
set name $namex; set num $sectx; set ext $extx
DEBUG {puts "num = $num"}
}


if {$goodnum!=""} {
set num $goodnum
}

if {[lsearch -exact $manx(manList) "$num$ext"]!=-1} {
set num "$num$ext"; set ext ""
}


set ext [string tolower $ext]
if $man(shortnames) {set name [string range $name 0 10].*}
if [catch {regexp $name validregexpcheck}] { set name [stringregexpesc $name] }
foreach v {fname sname oname name} { regsub "\a" [set $v] "\\" $v }

cursorBusy
DEBUG {puts stdout "$name : $num : $ext"}
set time [time {
set foundList [manShowManSearch $name $num $ext]
}]
cursorUnset
DEBUG {puts stdout "search time: $time"}

set found [llength $foundList]
if {!$found} {
DEBUG {puts stdout "$name not found: $ext, $num, [file rootname $name], [stringregexpesc $name]"}
if {$ext!=""} {
manShowMan $name $num $w; return
} elseif {$num!="" || [file rootname $name]!=$name} {
manShowMan [file rootname $name] {} $w
return
} elseif {$name!=[stringregexpesc $name] && ![string match {*\\*} $name]} {
manShowMan [stringregexpesc $name] {} $w
return
}
}

if {!$found} {
manWinstderr $w "$sname not found"
incr stat(man-no)
set r "ERROR: manual page not found"
} else {
set orname [file rootname $oname]
set prioritylist [lsort -command {manShowManSort $orname $manx(cursect$w) $num $ext} $foundList]
return [manShowManFound $prioritylist 0 $w]
}
}


proc manShowManSort {orname onum num ext a b} {
global manx

set pa [manShowManPriority $a $num $ext $orname $onum]
set pb [manShowManPriority $b $num $ext $orname $onum]

if {$pa>$pb} {set r -1} elseif {$pa<$pb} {set r 1} else {set r 0}
return $r
}

proc manShowManPriority {m num ext orname onum} {
global man manx mani

set d [file dirname $m]; set t [file tail $m]
set r [file rootname $t]; set n [file extension $t]
set e [string range $n 2 end]; set n [string range $n 1 1]

set pri 0
if {$n==$num} {incr pri 16} elseif {$n==$onum} {incr pri 1}
if {$r==$orname} {incr pri 8} elseif {[string tolower $r]==[string tolower $orname]} {incr pri 4}
if {$e==$ext} {incr pri 2}
set pri [expr $pri<<7]

set p -1; set l [llength $manx(paths)]
while {$d!="/" && [set p [lsearch -glob $manx(paths) $d*]]==-1} {
set d [file dirname $d]
}

if {$p==-1} {set p $l}
incr pri [expr $l-$p]
set pri [expr $pri<<7]

set l [llength $mani(manList)]
set p [lsearch -exact $mani(manList) $n]; if {$p==-1} {set p $l}
incr pri [expr $l-$p]

return $pri
}



proc manShowManSearch {name num ext} {
global man manx

set sed $man(sed)
if [lsearch $manx(manList) $num]==-1 {
set num ""
} else {
append sed " -e {/^$num /,/^\[^$num\] /!d}"
}
append sed " -e {/^. /d}"
DEBUG {puts "sed = $sed"}


set foundList ""

set pat "/${name}\$"

DEBUG {puts stderr "searching for $pat"}
DEBUG {puts stderr "set fid \[open \"|$man(zcat) $manx(database) | $sed | $man(egrep) -i $pat\"\]"}
set fid [open "|$man(zcat) $manx(database) | $sed | $man(egrep) -i {$pat}"]
while {[gets $fid f]!=-1} {
set d [file dirname [file dirname $f]]
if {(![info exists man($d)] || $man($d))} {
if {[set actual [glob -nocomplain "$f.?*"]]==""} {
if {[regsub {/man([^/]+)$} [file dirname $f] {/cat\1} d2]} {
set actual [glob -nocomplain "$d2/[file tail $f].?*"]
}
}
foreach i $actual {
zapZ! i
if {[lsearch $foundList $i]==-1} {lappend foundList $i}
}
}
}
catch {close $fid}

return $foundList
}




proc manShowManFound {f {keep 0} {w .man}} {
global man manx stat

set t $manx(out$w).show; set wi $w.info

set flen [llength $f]
if {$flen>1} {
pack $w.dups -before $w.mantypein -side left -anchor e; $w.dups configure -state active
set m $w.dups.m
$m delete 0 last
foreach i $f {$m add command -label $i -command "incr stat(man-dups); manShowManFound $i 1 $w"}
manMenuFit $m

set f [lfirst $f]
} elseif {!$keep} {pack forget $w.dups}

set f [zapZ [string trim $f]]

manNewMode $w man; incr stat(man)


if {[winfo exists $manx(out$w)]} {set w $manx(out$w)} {set manx(out$w) $w}
if {[set fg [lfirst [glob -nocomplain $f$manx(zoptglob)]]]!=""} {
set f $fg
} else {manWinstderr $w "$f doesn't exist"; return}
if [file isdirectory $f] {
manWinstderr $w "$f is a directory"
return
}
set f0 $f

set tmpdir [file dirname $f]

set so 0
set line1 [set line2 ""]
if {[file readable $f]} {
set fid [open "|[manManPipe $f]"]
while {([string trim $line1]=="" || [regexp {^[.']\\"} $line1]) && ![eof $fid]} {gets $fid line1}
while {[string trim $line2]=="" && ![eof $fid]} {gets $fid line2}
catch {close $fid}
if {[regexp {^\.so (man.+/.+)} $line1 all newman]} {
DEBUG {puts stderr "*** single-line .so => $manx(manfull$w): $line1"}
if [catch {set f [lfirst [glob [file dirname $tmpdir]/$newman*$manx(zoptglob)]]}] return
set tmpdir [file dirname $f]
set so 1
DEBUG {puts stderr "*** new f => $f"}
}
}

set manx(manfull$w) $f
set manx(man$w) [zapZ [file tail $f]]
set manx(name$w) [string trimright [file rootname $manx(man$w)] "\\"]

set fdir [zapZ [file dirname $manx(manfull$w)]]
set topdir [file dirname $fdir]
set manx(num$w) [string range [file tail $fdir] $manx(dirnameindex) end]
if {[lsearch $man(manList) $manx(num$w)]==-1} {set manx(num$w) [string index $manx(num$w) 0]}
set manx(cat) "$topdir/cat$manx(num$w)"


set fsstnd ""
if {[regexp {^/usr/(.*)man$} $topdir all blah]} {
set fsstnd "/var/catman/${blah}cat$manx(num$w)/$manx(man$w)$manx(zoptglob)"
DEBUG {puts "*** fsstnd = $fsstnd"}
}


set gotcat 0
if {[regexp $man(catsig) $fdir]} {
set manx(catfull$w) $manx(manfull$w)

if {$line2=="  Purpose"} {
manShowText $f $w 1
set manx(typein$w) [set manx(name$w) [file rootname [set manx(man$w) [file tail $f]]]]
return
}
set gotcat 1
} else {
DEBUG {puts "regexp on $topdir"}
set bsdi "$manx(cat)/[file rootname $manx(man$w)].0$manx(zoptglob)"
set irix "$manx(cat)/[file rootname $manx(man$w)].z"
set manx(catfull$w) "$manx(cat)*/$manx(man$w)$manx(zoptglob)"
DEBUG {puts "manx(man\$w) = $manx(man$w), catfull = $manx(catfull$w)"}


if [catch {set manfullmtime [file mtime $manx(manfull$w)]}] {set manfullmtime 0}

foreach catme [list $manx(catfull$w) $fsstnd $bsdi $irix] {
if {$catme==""} continue
if {[set path [lfirst [glob -nocomplain $catme]]]!=""
&& [file readable $path] && [file mtime $path]>=$manfullmtime} {
set manx(catfull$w) $path
set gotcat 1
break
}
}
}


if {$gotcat} {
set pipe [manManPipe $manx(catfull$w)]
} elseif {[file exists $manx(manfull$w)]} {
if {[string match */man?* $tmpdir]} {
set topdir [file dirname $tmpdir]
} else {set topdir $tmpdir}
if [catch {cd $topdir}] {
manWinstderr $w "Can't cd into $topdir.  This is bad."
return
}
if {[string match "*compress" $man(nroffsave)] && [file writable "$manx(cat).Z"]} {
append manx(cat) ".Z"
}
if {[string match "on*" $man(nroffsave)]} {
set saveerr ""

if {![file writable $manx(cat)] && [file writable "/var/catman"] && $fsstnd!=""} {
set manx(cat) [file dirname $fsstnd]
}

set idir ""
foreach dir [split [string range $manx(cat) 1 end] "/"] {
if {![file exists $idir/$dir]} {
DEBUG {puts "\tmaking $idir/$dir"}
if [catch "exec $man(mkdir) $idir/$dir" info] {
DEBUG {puts "\t  ERROR: $info"}
set saveerr $info
break
} else {
catch {
if {"$idir/$dir"!=$manx(cat) || ![string match cat* $dir] ||
![file isdirectory [set permme "$idir/man[string range $dir 3 end]"]]} {
set permme $idir
}
file stat $permme dirstat
set perm [format "%o" [expr $dirstat(mode)&0777]]
DEBUG { puts "\tsetting permission of directory $idir/$dir to $perm, from $permme" }
eval exec $man(chmod) $perm "$idir/$dir"
}
}
}
append idir "/$dir"
}

if {$saveerr!=""} {
} elseif {![file writable $manx(cat)]} {
set saveerr "CAN'T SAVE: $manx(cat) not writable"
} else {
set path [set manx(catfull$w) $manx(cat)/$manx(man$w)]
if $manx(fBSDI) {[set path [set manx(catfull$w) "$manx(cat)/[file rootname $manx(man$w)].0"]]}

manWinstdout $w "Saving copy formatted by nroff ..." 1
if [catch {eval "exec [manManPipe $manx(manfull$w)] | $man(format) > $path"} info] {
set saveerr "CAN'T SAVE: $info"
} else {
catch {
file stat [file dirname $manx(manfull$w)] dirstat
set perm [format "%o" [expr $dirstat(mode)&0666]]
DEBUG { puts "\tsetting permission of $path to $perm, from $manx(manfull$w)" }
eval exec $man(chmod) $perm $path
}

if {[string match "*compress" $man(nroffsave)]} {
manWinstdout $w "Compressing ..." 1
if [catch "exec $man(compress) $manx(catfull$w)" info] {
set saveerr "CAN'T COMPRESS:  $info"
} elseif {[file extension $manx(cat)]==".Z"} {	# H-P
eval exec $man(mv) [glob $manx(catfull$w).$manx(zglob)] $manx(catfull$w)
set path $manx(catfull$w)
} else {
set path [set manx(catfull$w) [lfirst [glob $manx(catfull$w).$manx(zglob)]]]
}
}
set pipe [manManPipe $path]
}
}

if {$saveerr!=""} {
after 20 manWinstdout $w "{$saveerr}"
set path $manx(manfull$w)
set manx(catfull$w) ""
set pipe "[manManPipe $path] | $man(format)"
}

} else {
set path $manx(manfull$w)
set manx(catfull$w) ""
set pipe "[manManPipe $path] | $man(format)"
}

} elseif [catch {[file readlink $manx(manfull$w)]}] {
manWinstderr $w "$manx(manfull$w) is a symbolic link that points nowhere"
return
} else {
manWinstderr $w "$manx(manfull$w) not found"
return
}


set errflag 0
set msg [expr [string match "*/*roff*" $pipe]?"Formatting and filtering":"Filtering"]
manWinstdout $w "$msg $manx(name$w) ..." 1


append pipe " | $manx(rman) -f TkMan $man(subsect) $man(headfoot) $man(changeleft) $man(zaphy)"
DEBUG {puts stderr "pipe = $pipe"}

if [catch {set fid [open "|$pipe"]} info] {
manWinstderr $w "ERROR: $info"
DEBUG {puts "can't open pipe: $info"}
return
}

manTextOpen $w
set time [time {
while {![eof $fid]} {eval [gets $fid]}
}]
DEBUG {puts "formatting time: $time"}
if {$man(headfoot)!=""} {
if {$manx(catfull$w)!=""} {
set f $manx(catfull$w); set info "formatted"
} else {set f $manx(manfull$w); set info "installed"}

set fileinfo [clock format [file mtime $f] -format $man(date-format)]
$t insert end "( $f $info at $fileinfo )\n" sc
}
manTextClose $w
manWinstdout $w ""

if [catch {close $fid} info] {
manWinstderr $w "ERROR: $info"
DEBUG {puts "can't close pipe: $info"}
return
}

if {$so} {
set manx(manfull$w) $f0
set manx(man$w) [zapZ [file tail $f0]]
set manx(name$w) [file rootname $manx(man$w)]
}

manShowManFoundSetText $w $manx(out$w).show [bolg [zapZ $manx(manfull$w)] ~]
manWinstdout $w ""
if {$man(whatwhere)} {
manWinstdout $w $manx(manfull$w)
} else {
scan [$t index end] %d n
set n [max $n 20]
for {set i 1} {$i<=$n} {incr i} {
if {[regexp -- {- (.*)} [$t get $i.0 "$i.0 lineend"] all info]} {
incr i
while {[regexp { +(.*)} [$t get $i.0 "$i.0 lineend"] all spaces more]} {
append info " $more"
incr i
}
manWinstdout $w "$info"
break
}
}
}


cd $tmpdir
manShowManStatus $w
wm title $w "$manx(title$w): $manx(man$w)"
set manx(lastman) $manx(manfull$w)

return $manx(manfull$w)
}


proc manShowManFoundSetText {w t key} {
global man manx

set m [set mb $w.sections].m
set ml {}; foreach i [$t mark names] { if [string match "js*" $i] { lappend ml $i } }
set ml [lsort -command "bytextposn $t " $ml]
set ctr 0
foreach i $ml {
set pfx [expr {[string match "jss*" $i]?"   ":""}]
set txt [$t get "$i linestart" "$i lineend"]
if {![regexp {[a-z]} $txt] && [string length $txt]>3} { set txt [string tolower $txt] }

set nextsect [lindex $ml [expr [lsearch -exact $ml $i]+1]]; if {$nextsect==""} {set nextsect end}
set opts {}
set optposn $i
set expr "^\\|*\[ \t\]+(-.*)"; set expr2 "^\\|*\[ \t\]+(\[^-\].*)"
while {[set optposn [$t search -forwards -regexp $expr $optposn+1l $nextsect]]!=""} {
set opttxt [$t get $optposn "$optposn lineend"]
regexp $expr $opttxt all opttxt
for {set more 1} {$more<=3 && [$t compare [set optposn2 $optposn+${more}l] < $nextsect]} {incr more} {
set opttxt2 [$t get $optposn2 "$optposn2 lineend"]
if [regexp $expr2 $opttxt2 all opttxt2] { append opttxt " " $opttxt2 } else break
}
lappend opts [list $optposn [manHighNormalize $opttxt $man(high,hcontext)]]
}

if {[llength $opts]<=2 || !$man(optmenus)} {
$m add command -label "$pfx$txt" -command "incr stat(page-section); $t yview $i"
} else {
$m add cascade -label "$pfx$txt" -menu [set m2 $m.opts$ctr]; incr ctr
menu $m2 -tearoff no
$m2 add command -label "(top of section)" -command "incr stat(page-section); $t yview $i"
foreach j $opts {
set optposn [lfirst $j]; set opttxt [lsecond $j]
$m2 add command -label $opttxt -command "incr stat(page-section); $t yview $optposn"
}
manMenuFit $m2
}
}
if {![string match "_*" $key] && $man(headfoot)!=""} {
$m add separator
$m add command -label "Header and Footer" -command "incr stat(page-section); $t yview headfoot"
}
configurestate $mb
manMenuFit $w.sections.m


set refs [$t tag ranges manref]
set reflist {}
set m [set mb $w.links].m
for {set i 0} \$i<[llength $refs] {incr i 2} {
lappend reflist [$t get [lindex $refs $i] [lindex $refs [expr $i+1]]]
}
foreach ref [uniqlist [lsort $reflist]] {
$m add command -label $ref -command "incr stat(man-link); manShowMan $ref {} $w"
}

configurestate $mb
manMenuFit $m


set manx(hv$w) $key

manHighView $w

focus $t
}


proc manManPipe {f} {
global man manx

if {[regexp $manx(zregexp) $f] || [regexp $manx(zregexp) [file dirname $f]]} {
set pipe $man(zcat)
} else {set pipe "cat"}

return "$pipe $f"
}

proc manShowManStatus {w} {
global man manx

set t $manx(out$w).show; set wi $w.info


manSetSect $w $manx(manfull$w)

set manx(typein$w) $manx(name$w)
$w.mantypein icursor end

set manx(history$w) \
[lrange [setinsert $manx(history$w) 0 [list $manx(manfull$w)]] 0 [expr $man(maxhistory)-1]]
set m [set mb $w.history].m
$m delete 0 last
foreach i $manx(history$w) {
if {[llength [lfirst $i]]>=2} {set l [lfirst $i]} {set l $i}
if {![regexp {^[|<]} $l]} {
set l [zapZ [file tail $l]]
}
$m add command -label $l -command "incr stat(man-history); manShowMan $i {} $w"
}
configurestate $mb
manMenuFit $m


manShortcutsStatus $w


scan [$t index end] "%d" linecnt 
$w.search.cnt configure -text "$linecnt lines"
}


proc zapZ! {f} {
uplevel 1 set $f \[zapZ \[set $f\]\]
}
proc zapZ {f} {
global manx
return [expr {[regexp $manx(zregexp) $f]?[file rootname $f]:$f}]
}



proc manShowText {f0 {w .man} {keep 0}} {
global man manx stat

set wi $w.info


set t $manx(out$w).show

if {[string match <* $f0]} {
set f [fileexp [string range $f0 1 end]]
if {[regexp $manx(zregexp) $f]} {set f "|$man(zcat) $f"}
} else {set f [pipeexp $f0]}


manNewMode $w txt; incr stat(txt)

manTextOpen $w
if {[catch {
set fid [open $f]
while {![eof $fid]} {$t insert end [gets $fid]\n}
close $fid
}]} {manTextClose $w; manWinstderr $w "Trouble reading $f0"; return}
manTextClose $w
if {!$keep} {pack forget $w.dups}

if [file isfile $f] {cd [file dirname [glob $f]]}



set manx(man$w) $f0
set manx(num$w) X
set manx(hv$w) [bolg [zapZ $f] ~]
set manx(manfull$w) $f0
set manx(catfull$w) $f
set manx(name$w) $f0
set tmp $man(whatwhere)
set man(whatwhere) 1
manShowManStatus $w
set man(whatwhere) $tmp

manWinstdout $w $manx(manfull$w)
manHighView $w
focus $t

return $f
}




proc manApropos {name {w .man}} {
global man manx mani stat

if $manx(shift) { set manx(shift) 0; set w [manInstantiate] }
set wi $w.info; set t $w.show

if {$name==""} {set name $manx(man$w)}
if {$name==""} {
manWinstderr $w "Type in keywords to search for"
return
}

set mani(apropos,form) "Apropos search for \"$name\"\n\n"
manWinstdout $w "Apropos search for \"$name\" ..." 1

DEBUG {puts "manApropos: exec $man(apropos) $name $man(aproposfilter) 2>/dev/null"}
if {[catch {set tmp [eval exec "$man(apropos) $name $man(aproposfilter) 2>/dev/null"]} info] || $tmp==""} {
if {$info!=""} {
append mani(apropos,form)
} else {
append mani(apropos,form) "Nothing related found.\n"
}
if {$man(glimpse)!=""} { append mani(apropos,form) "Try a full text search with Glimpse.\n" }
set mani(apropos,cnt) 0
} else {
manNewMode $w aprops; incr stat(apropos)
set mani(apropos,update) [clock seconds]
set cnt 0
foreach line [split $tmp "\n"] {
regsub "^\\.\[^ \t\]+" $line "" line
regsub -all "\[\t \]+" $line " " line
regsub " - " $line "\t - " line
if {[lfirst $line]==[lsecond $line]} { regsub {^[ ]*[^ ]+[ ]*} $line "" line }

append mani(apropos,form) $line "\n"
incr cnt
}

set mani(apropos,cnt) $cnt
set manx(yview,apropos) 0
}

manShowSection $w apropos
}




proc manGlimpse {name {w .man}} {
global man manx

set dirs $man(glimpsestrays)

set l [llength $name]; incr l -1
set auxopts [lrange $name 0 [expr $l-1]]; set name [lindex $name $l]
if {$man(indexglimpse)=="distributed"} {
foreach d $manx(paths) {
if {$man($d)} {	lappend dirs $d }
}
} else {
}

manGlimpse2 $name $dirs $auxopts $w
}

proc manGlimpse2 {name dirs {auxopts ""} {w .man}} {
global man manx mani sbx env stat STOP

if $manx(shift) {set manx(shift) 0; set w [manInstantiate]}
set t $manx(out$w).show; set wi $w.info

if {$name==""} {set name $manx(man$w)}
if {$name==""} {
manWinstderr $w "Type in regular expression for full text search"
return
}
set showname $name
regsub -all {([^\]);} $name {\1\;} name

set opts "-ly"
set casesen $man(regexp,case); if {$casesen==-1 && [string tolower $name]!=$name} {set casesen 1}
if {!$casesen} {append opts "i"}
if {$man(maxglimpse)!="none"} {append opts " -L $man(maxglimpse)"}
set redirect ""
if [regexp { -[^ ]*N[^ ]* } "$man(glimpse) $name"] {append redirect "2>/dev/null"}

set STOP 0
cursorBusy

set foundList ""
set errorList ""
foreach d $dirs {
if ![file readable $d/.glimpse_index] {
continue
}
manWinstdout $w "Glimpsing for \"$showname\" in $d ..."; update
DEBUG {puts "$man(glimpse) $auxopts $opts -H $d $name"}
if {$STOP} {set STOP 0; break}
if ![catch {set matches [eval exec -keepnewline "$man(glimpse) $auxopts $opts -H $d {$name} $redirect"]} info] {
append foundList $matches
} else {
append errorList "can't glimpse $d: $info\n"
manWinstderr $w "error with glimpsing: $info"
}
}
manWinstdout $w ""
cursorUnset

set found [llength $foundList]; set error [string length $errorList]
if {!$found && !$error} {
manWinstderr $w "$name not found in full text search"
} else {
manNewMode $w super; incr stat(super)
set mani(glimpse,form) "Glimpse full text search for \"$name\"\n\n"
set mani(glimpse,update) [clock seconds]

if $error {
append mani(glimpse,form) "Errors while Glimpsing\n\n" $errorList "\n\n"
}

foreach i [lsort -command manSortByName $foundList] {
append mani(glimpse,form) "$i\n"
}
set mani(glimpse,cnt) $found
set manx(yview,glimpse) 0

set manx(search,string$w) [tr [tr [llast $name] ";" "|"] "," "|"]
set sbx(lastkeys-old$t) [llast $name]

manShowSection $w glimpse
}
}



proc manGlimpseIndex {{w .man}} {
global man manx mani


if {$man(indexglimpse)=="distributed"} {
set dirpairs {}
if [llength $mani($man(glimpsestrays),dirs)] {
lappend dirpairs [list $man(glimpsestrays) $mani($man(glimpsestrays),dirs)]
}
foreach dir $manx(paths) {
lappend dirpairs [list $dir $mani($dir,dirs)]
}
} else {
set dirs $mani($man(glimpsestrays),dirs)
foreach dir $manx(paths) {
set dirs [concat $dirs $mani($dir,dirs)]
}
set dirpairs [list [list $man(glimpsestrays) $dirs]]
}

set buildsec [expr [lfirst [time {manGlimpseIndex2 $dirpairs $w}]]/1000000]

if {$buildsec<[expr 60*60]} {set buildfmt "%M:%S"} {set buildfmt "%T"}
if {$buildsec>30 || $man(time-lastglimpse)==-1} {
set man(time-lastglimpse) [clock format $buildsec -format $buildfmt]
}

foreach win [lmatches ".man*" [winfo children .]] {
$w.occ.m entryconfigure "Rebuild Glimpse*" -label "Rebuild Glimpse Index (last $man(time-lastglimpse))"
}

}


proc manGlimpseIndex2 {dirpairs {w .man}} {
global man manx mani env

manNewMode $w super
set t $manx(out$w).show; set wi $w.info

manWinstdout $w "Rebuilding Glimpse database ... "
manShowSection $w glimpse
manTextOpen $w; update idletasks
set cnt [llength $dirpairs]; set cur 1
set foneup 0

foreach pair $dirpairs {
set dir [lfirst $pair]; set dirs [lsecond $pair]
$t insert end "Working on $dir" b " ($cur of $cnt), "
set dircnt [llength $dirs]; set dirtxt [expr $dircnt==1?"directory":"directories"]
$t insert end "$dircnt $dirtxt"
$t insert end "\n\n"
$t see end; update idletasks

if {!$dircnt} {
$t insert end "Nothing to index.\n"
incr cur; $t insert end "\n\n"
continue
}

set gzt ".glimpse_filters"
set gf "$dir/.glimpse_filenames"
set gz "$dir/$gzt"
set gfe [expr [llength [glob -nocomplain $dir/.glimpse_{filenames,index}]]==2]


set outofdate [expr {!$gfe || [file size $gf]==0 || ([file exists $gz] && [file mtime $gz]>[file mtime $gf]) || [file mtime $gf]<$manx($dir,latest)}]

if {!$outofdate} {
$t insert end "Glimpse index still current.\n" indent

set foneup 1
incr cur; $t insert end "\n\n"
continue
}


if {![file writable $dir]} {
$t insert end "Glimpse index out of date but directory not writable" indent
if {$gfe} {
$t insert end " ... but old Glimpse files found\n" indent
$t insert end "Full text seaching available here using existing files.\n" indent
} else {
$t insert end " ... and Glimpse files not found\n" indent
$t insert end "No full text searching available here.\n" {indent bi}
}

incr cur; $t insert end "\n\n"
continue
}


set gex "$dir/.glimpse_exclude"
if ![file exists $gex] {
set fid [open $gex "w"]
puts $fid {.glimpse_exclude$}
puts $fid {~$}
puts $fid {.bak$}
close $fid
}

if ![file exists $gz] {
set fcat [expr [lsearch -regexp $dirs {/cat[^/]*$}]!=-1]
set fhp [expr [lsearch -regexp $dirs {\.Z$}]!=-1]
set fz 0
foreach d $dirs {
cd $d
if {[lsearch -regexp [glob -nocomplain *] $manx(zregexp)]!=-1} {set fz 1; break}
}

set fid [open $gz "w"]
if $fhp {puts $fid "*.Z/*\tzcat <"}
if {$fz} {
set zcat [file tail [lfirst $man(zcat)]]
switch -glob -- $zcat {
gz* {puts $fid "*.z\t$man(zcat)\n*.Z\t$man(zcat)\n*.gz\t$man(zcat)"}
default {
puts $fid "*.$manx(zglob)\t[string trimright $man(zcat) { <}]"
}
}
}
if $fcat {puts $fid "*/cat*/*\trman <"}
close $fid
}


if [catch {set fid [open "|$man(glimpseindex) -z -H $dir $dirs"]} info] {
DEBUG {puts "error on: $man(glimpseindex) -z -H $dir $dirs]: $info"}
$t insert end "$info\n" bi
catch {close $fid}
} else {
DEBUG {puts "$man(glimpseindex) -z -H $dir $dirs"}
set blankok 0
while {![eof $fid]} {
gets $fid line
if {![regexp {(^This is)} $line] && ($line!="" || $blankok)} {
$t insert end "$line\n" tt; $t see end; update idletasks
set blankok 1
}
}
if [catch {close $fid} info] { $t insert end "ERRORS\n" {indent bi} $info indent2 "\n" }

if {[file size $gf]==0} {
$t insert end "No files could be indexed.  No full text searching available here.\n" {indent bi}
if [file exists $gz] {
$t insert end "Try checking your $gzt file in $dir.  If $gzt wasn't created by TkMan, try deleting it and letting TkMan create one of its own.\n" indent
}
} else {
catch {
file stat $dir dirstat
set perm [format "%o" [expr $dirstat(mode)&0666]]
eval exec $man(chmod) $perm [glob $dir/.glimpse_*]
}
}
}

incr cur
$t insert end "\n\n"
}

if {$foneup} {
$t insert end "\nTo force re-indexing of directories that TkMan claims are current, remove all Glimpse index files in that directory, as with `rm <dir> .glimpse_*'.\n" i
}

$t see end
manTextClose $w

set mani(glimpse,form) [$t get 1.0 end]

manWinstdout $w ""
}



proc manPrint {w {printer ""}} {
global man manx stat env

set t $w.show; set wi $w.info

set f [string trim $manx(manfull$w)]
if {$f=="" || ![file exists $f]} return
set tail [zapZ [file tail $f]]; set name [file rootname $tail]; set sect [file extension $tail]
if {$sect==""} {set sect [string index [file tail [file dirname $f]] $manx(dirnameindex)]}

set tmp [manWinstdout $w]
manWinstdout $w "Printing $f ..." 1
set curdir [pwd]
set topdir [file dirname $f]
set printpipe $man(print)
if {[regexp -- $man(catsig) $topdir]} {
set printpipe $man(catprint)
if {[tk_dialog .dialog "NO GUARANTEES" "No troff source.  Try to reverse compile cat-only page?" \
"" 1 No Yes]} {
set printpipe "$manx(rman) -f roff $man(changeleft) -n $name -s $sect $man(subsect) | $man(print)"
}
}
if {[regexp $man(catsig) $topdir] || [string match */man?* $topdir]} {
set topdir [file dirname $topdir]
}

catch {cd $topdir}
DEBUG {puts stderr "print pipe = [manManPipe $f] | $printpipe"}

set env(PRINTER) $printer; set env(LPDEST) $printer
eval exec [manManPipe $f] | $printpipe
manWinstdout $w $tmp
cd $curdir
incr stat(print)
}




proc manHelp {w} {
global man manx stat

set t $w.show; set wi $w.info

manNewMode $w help; incr stat(help)
wm title $w "$manx(title$w) v$manx(version)"
set manx(manfull$w) "_help"
set manx(name$w) "_help"

manTextOpen $w
manHelpDump $t
$t tag remove h1 1.0 "1.0 lineend"; $t tag add title 1.0 "1.0 lineend"
$t delete 2.0
$t delete 7.10 7.14; $t insert 7.10 "\251"; $t tag add symbol 7.10
foreach bm {icon face} {
$bm configure -foreground black -background white
label $t.$bm -image $bm
}
$t window create 2.0 -window $t.icon -padx 8 -pady 8
$t mark set insert "author1+2lines lineend"
$t insert insert "\t"
$t window create insert -window $t.face -align bottom -padx 8 -pady 8

manManpathCheck
set fWarn 0
foreach warn {manpathset manpath mandesc expire} {
if {$manx($warn-warnings)!=""} {
$t insert 1.0 $manx($warn-warnings)\n\n
set fWarn 1
}
}
if $fWarn {	$t insert 1.0 "Warnings\n\n" b }

$t insert 1.0 $manx(updateinfo)

manTextClose $w


set cnt 0
foreach i [lsort -command "bytextposn $t " [$t mark names]] {
if {[string match "*1" $i]} { $t mark set js$cnt $i; incr cnt }
if {[string match "*2" $i]} { $t mark set jss$cnt $i; incr cnt }
}

manShowManFoundSetText $w $t "_help"


update idletasks
after 1 "manWinstdout $w \"TkMan v$manx(version) of $manx(date)\""
}

proc bytextposn {t a b} {
set ap [$t index $a]; set bp [$t index $b]
if {$ap<$bp} {set cmp -1} elseif {$ap>$bp} {set cmp 1} else {set cmp 0}
return $cmp
}



proc manKeyNav {w m k} {
global man manx

set t $w.show; set wi $w.info

set firstmode [expr {$manx(mode$w)=="section" || $manx(mode$w)=="apropos"}]
set casesen [expr $firstmode?1:$man(incr,case)]

set fFound [searchboxKeyNav $m $k $casesen $t $wi $firstmode]

return $fFound
}




proc manPreferencesMake {{w0 ""}} {
global prefedit manx man bozo

set w .prefs
if {[winfo exists $w]||$w0==""} {return $w}

toplevel $w
wm geometry $w $prefedit(geom-prefs)
wm title $w "Preferences"
wm withdraw $w

set f [frame $w.pages]
foreach i {Fonts Colors See Icon Misc} {
set il [string tolower $i]
radiobutton $f.$il -text $i -command manPreferences -variable manx(prefscreen) -value $il
}
pack $f.fonts $f.colors $f.see $f.icon $f.misc -side left -fill x -padx 4

frame $w.sep1 -height 2 -background $prefedit(guifg)


set g [frame $w.[set group "fonts"]]

foreach i {{gui Interface} {text "Text display"} {vol "Volume listings"}} {
set var [lfirst $i]; set txt [lsecond $i]
lappend manx(vars-$group) $var-family $var-style $var-points
set f [frame $g.font$var]
label $f.l -text $txt
[eval tk_optionMenu $f.family prefedit($var-family) $man(families)] configure -tearoff no
[eval tk_optionMenu $f.style prefedit($var-style) $manx(styles)] configure -tearoff no
[eval tk_optionMenu $f.points prefedit($var-points) $manx(sizes)] configure -tearoff no
pack $f.l -side left -fill x
pack $f.style $f.points $f.family -side right -padx 2
}

set f [frame $g.dpi]
label $f.l -text "Screen dots per inch (DPI)"
[eval tk_optionMenu $f.dpi prefedit(dpi) $prefedit(dpis)] configure -tearoff no
lappend manx(vars-$group) "dpi"
pack $f.l -side left -fill x
pack $f.dpi -side right

pack $g.fontgui $g.fonttext $g.fontvol $g.dpi -fill x -pady 3 -padx 4


set g [frame $w.[set group "colors"]]

foreach i {{text "Text"} {gui "Interface"} {butt "Buttons"} {active "Active Regions"}} {
set var [lfirst $i]; set txt [lsecond $i]
lappend manx(vars-$group) ${var}fg ${var}bg
set f [frame $g.$var]
label $f.l -text $txt
foreach j {{fg "foreground"} {bg "background"}} {
set jvar [lfirst $j]; set jtxt [lsecond $j]
if {$jvar=="fg"} {set jopp "bg"} {set jopp "fg"}
set mb $f.$var$jvar
[set m [eval tk_optionMenu $mb prefedit($var$jvar) $man(colors)]] configure -tearoff no
if {$manx(mono)} {
foreach k $man(colors) {
set copp [lindex $prefedit(colors) [expr 1-[lsearch $prefedit(colors) $k]]]
$m entryconfigure $k -command "set prefedit($var$jopp) $copp; set prefedit($var$jvar) $k"
}
}
}
pack $f.l -side left -fill x
pack $f.${var}bg [label $f.${var}on -text "on"] $f.${var}fg -side right -padx 4
}

foreach i {{manref f "Man page references"} {isearch b "Incremental search hits"}
{search b "Regexp search hits"} {highlight b "Highlights"}} {
set var [lfirst $i]; set fb [lsecond $i]; set txt [lthird $i]
lappend manx(vars-$group) $var
set f [frame $g.$var]
label $f.l -text $txt

[set m [eval tk_optionMenu [set mb $f.$var] prefedit($var) $manx(highs)]] configure -tearoff no
foreach k $manx(highs) {
if {[lsearch $man(colors) $k]==-1} {set val $k} \
else {if {$fb=="f"} { set val "-foreground [list $k]"} { set val "-background [list $k]" } }
$m entryconfigure $k -command "set prefedit($var) [list $val]"
}
pack $f.l -side left -fill x
pack $mb -side right -padx 4
}

pack $g.text $g.gui $g.butt $g.active $g.manref $g.isearch $g.search $g.highlight \
-fill x -expand yes -pady 3 -padx 4


set g [frame $w.[set group "see"]]

foreach i {{headfoot "Show header, footer, date at bottom"} {scrollbarside "Scrollbar side"}
{whatwhere "Information bar shows"} {textboxmargin "Text box internal margin"}
{volcol "Width of columns in Volumes list"}
{high,vcontext "Back context for Highlights jump"}
{strictmotif "Strict Motif behavior"} 
{error-effect "Status line error/warning effect"}
{optmenus "Sections submenus for command line options"}
{subvols "Subvolumes as submenus in Volumes"} 
{apropostab "Tab stop in apropos list"}} {
set var [lfirst $i]; set txt [lsecond $i]
lappend manx(vars-$group) $var
set f [frame $g.$var]
label $f.l -text $txt
[set m [eval tk_optionMenu $f.high bozo($var) $manx(${var}-t)]] configure -tearoff no
set j 0
foreach mv $manx(${var}-v) {
$m entryconfigure $j -command "set prefedit($var) [list $mv]"
incr j
}
trace variable prefedit($var) w manPrefBozo
pack $f.l -side left -fill x
pack $f.high -side right
}

pack $g.headfoot $g.subvols $g.optmenus $g.high,vcontext $g.volcol $g.apropostab $g.whatwhere $g.scrollbarside $g.textboxmargin $g.error-effect $g.strictmotif \
-fill x -pady 3 -padx 4



set g [frame $w.[set group "icon"]]

foreach i {{iconify "Iconify on startup"} } {
set var [lfirst $i]; set txt [lsecond $i]
lappend manx(vars-$group) $var
set f [frame $g.$var]
label $f.l -text $txt
[set m [eval tk_optionMenu $f.high bozo($var) $manx(${var}-t)]] configure -tearoff no
set j 0
foreach mv $manx(${var}-v) {
$m entryconfigure $j -command "set prefedit($var) [list $mv]"
incr j
}
trace variable prefedit($var) w manPrefBozo
pack $f.l -side left -fill x
pack $f.high -side right
}

foreach i {{iconname "Name when iconified"}
{iconbitmap "Path name of icon bitmap"} {iconmask "Path name of icon mask"}
{iconposition "Icon position (+|-)x(+|-)y"}} {
set var [lfirst $i]; set txt [lsecond $i]
lappend manx(vars-$group) $var
set f [frame $g.$var]
label $f.l -text $txt
entry $f.e -textvariable prefedit($var) -relief sunken

pack $f.l -side left -fill x
pack $f.e -side right
}
set ring {iconname iconbitmap iconmask iconposition}; set ringl [llength $ring]
for {set i 0} {$i<$ringl} {incr i} {
set wig $g.[lindex $ring $i].e
foreach k {Tab Return} { bind $wig <KeyPress-$k> "focus $g.[lindex $ring [expr ($i+1)%$ringl]].e"; break }
bind $wig <Shift-KeyPress-Tab> "focus $g.[lindex $ring [expr ($i-1)%$ringl]].e; break"
}

foreach wig {iconbitmap iconposition} {
set e $g.$wig.e
bind $e <KeyPress-Escape> "manFilecompleteLocal $e"
}

pack $g.iconify $g.iconname $g.iconbitmap $g.iconmask $g.iconposition \
-fill x -pady 3 -padx 4


set g [frame $w.[set group "misc"]]

foreach i {{nroffsave "Cache formatted (nroff'ed) pages"}
{hyperclick "Mouse click to activate hyperlink"}
{subsect "Parse man page subsections"}
{recentdays {"Recent" volume age, in days}}
{maxhistory "Maximum length of history list"}
{indexglimpse "Glimpse indexing"}
{maxglimpse "Maximum Glimpse hits (per man hierarchy)"}
{zaphy "Prevent hyphenation (silly)"}} {
set var [lfirst $i]; set txt [lsecond $i]
lappend manx(vars-$group) $var
set f [frame $g.$var]
label $f.l -text $txt
[set m [eval tk_optionMenu $f.high bozo($var) $manx(${var}-t)]] configure -tearoff no
set j 0
foreach mv $manx(${var}-v) {
$m entryconfigure $j -command "set prefedit($var) [list $mv]"
incr j
}
trace variable prefedit($var) w manPrefBozo
pack $f.l -side left -fill x
pack $f.high -side right
}


foreach i {{glimpsestrays "Distributed stray cats / unified index"}
{printers "Printer list (space separated)"}} {
set var [lfirst $i]; set txt [lsecond $i]

set f [frame $g.$var]
label $f.l -text $txt
entry $f.e -width 25 -textvariable prefedit($var) -relief sunken

pack $f.l -side left -fill x
pack $f.e -side right
}


pack $g.nroffsave $g.printers $g.hyperclick $g.subsect $g.maxhistory $g.recentdays \
$g.maxglimpse $g.indexglimpse $g.glimpsestrays \
$g.zaphy \
-fill x -pady 3 -padx 4


frame $w.bsep -relief sunken -height 2 -background $prefedit(guifg)
set f [frame $w.butts]
button $f.ok -text "OK" -padx 6 -command "grab release $w; wm withdraw $w; manPreferencesSet"
button $f.apply -text "Apply" -command "manPreferencesSet"
button $f.cancel -text "Cancel" -command "
grab release $w; wm withdraw $w
manPreferencesGet cancel; manPreferencesSet
"
button $f.default -text "Defaults" -command "manPreferencesGet default"
pack $f.ok $f.apply $f.default $f.cancel -side right -padx 4


pack $w.pages $w.sep1 $w.bsep $w.butts \
-side top -fill x -pady 3 -padx 4

return $w
}

proc manPrefBozo {array var op} {
global prefedit manx bozo
set bozo($var) [lindex $manx($var-t) [lsearch $manx($var-v) $prefedit($var)]]
}


proc manFilecompleteLocal {t} {
set line [$t get]
set fc [filecomplete $line]
set ll [llength $fc]

if {!$ll} {
bell
return
}

$t delete 0 end
$t insert 0 [lfirst $fc]
$t icursor end
$t xview moveto 1
}


proc manPreferencesGet {{cmd "fill"}} {
global man manx default prefedit cancel curedit

if {$cmd=="fill"} {
foreach i [array names default] {set prefedit($i) [set curedit($i) [set cancel($i) $man($i)]]}
} elseif {$cmd=="default"} {
foreach i $manx(vars-$manx(prefscreen)) {set prefedit($i) $default($i)}
} elseif {$cmd=="cancel"} {
foreach i [array names default] {set prefedit($i) $cancel($i)}
} elseif {$cmd=="man"} {
foreach i [array names default] {set man($i) $prefedit($i)}
} elseif {$cmd=="curedit"} {
foreach i [array names default] {set curedit($i) $prefedit($i)}
}
}

set manx(prefscreen) "fonts"
set manx(oldprefscreen) ""
proc manPreferences {{screen ""}} {
global manx

set w [manPreferencesMake bozo]
raise $w
if {$screen==""} {set screen $manx(prefscreen)} {set manx(prefscreen) $screen}
set prev $manx(oldprefscreen)

if {$screen!=$prev} {
if {$prev!=""} {
pack forget $w.$prev
}

pack $w.$screen -after $w.sep1 -fill x

set manx(oldprefscreen) $screen
}

if ![winfo ismapped $w] {
manPreferencesGet fill
wm deiconify $w; grab set $w
}
}

proc manPresDefaultsSet {} {
global man font

foreach i {{gui ""} {butt "Button."} {butt "Menubutton."} {butt "Radiobutton."} \
{butt "Checkbutton."} {text "Text."}} {
set var [lfirst $i]; set txt [lsecond $i]
if [info exists man(${var}-family)] {
option add Tkman*${txt}Font \
[spec2font $man(${var}-family) $man(${var}-style) $man(${var}-points)] 61
}
option add Tkman*${txt}Foreground $man(${var}fg) 61
option add Tkman*${txt}Background $man(${var}bg) 61
}

option add Tkman*activeForeground $man(activefg) 61
option add Tkman*activeBackground $man(activebg) 61
option add Tkman*highlightBackground $man(activebg) 61

option add Tkman*selectColor $man(buttfg) 61

set font(pro) [spec2font $man(text-family) $man(text-style) $man(text-points)]
set font(mono) [spec2font "Courier" $man(text-style) $man(text-points) "s"]
set font(vol) [spec2font $man(vol-family) $man(vol-style) $man(vol-points)]
if {[string match "*Courier*" $man(currentfont)]} {
set man(currentfont) $font(mono)
} else {set man(currentfont) $font(pro)}
}


proc manPreferencesSet {} {
global man manx mani prefedit curedit default

set change 0
foreach i [array names default] {
if {$curedit($i)!=$prefedit($i)} {
set change 1
break
}
}
if !$change return

set mani($prefedit(glimpsestrays),dirs) $mani($man(glimpsestrays),dirs)

manPreferencesGet man


manPresDefaultsSet
resetfonts [spec2font $man(gui-family) $man(gui-style) $man(gui-points)]
resetcolors

foreach w [lmatches ".man*" [winfo children .]] {manPreferencesSetMain $w}

manPreferencesGet curedit
}


proc manPreferencesSetMain {w} {
global man manx font curedit tk_strictMotif

if ![string match ".man*" $w] return

foreach i {iconname iconposition iconbitmap iconmask} {
if {$man($i)!=$curedit($i)} {set manx($i) $man($i)}
}
set num [string range $w 4 end]
if {$num==""} {set name $manx(iconname)} {set name "$manx(iconname) #$num"}
wm iconname $w $name
if {[regexp $manx(posnregexp) $manx(iconposition) all x y]} {
wm iconposition $w $x $y
}
foreach i {iconbitmap iconmask iconwindow} {wm $i $w ""}

if {$manx(iconbitmap)=="(default)" || $manx(iconbitmap)=="default"} {
set iw ".iconwindow[string range $w 4 end]"
if ![winfo exists $iw] {toplevel $iw; label $iw.l -image icon; pack $iw.l}
wm iconwindow $w $iw
} else {
foreach i {iconbitmap iconmask} {
if {$manx($i)!=""} {
if [catch {wm $i $w @$manx($i)} info] {
puts stderr "Bad $i: $manx($i).  Fix in Preferences/Icon."
}
}
}
}



$w.mono configure -onvalue $font(mono) -offvalue $font(pro)
pack $w.v -side $man(scrollbarside)
set tk_strictMotif $man(strictmotif)
set symbolfont [spec2font "symbol" "normal" $man(gui-points)]
$w.dups configure -font $symbolfont
$w.search.next configure -font $symbolfont; $w.search.prev configure -font $symbolfont
$w.mono configure -font [spec2font "Courier" $man(gui-style) $man(gui-points)]
foreach i [list $w.occ.m $w.paths.m $w.occ.m.m2 $w.occ.m.m3] {
$i configure -selectcolor $man(guifg)
}

$w.v configure -troughcolor $man(guibg)
$w.v configure -background [expr {$man(buttbg)!=$man(guibg)?$man(buttbg):$man(guibg)}]

set t $w.show
$t configure -padx $man(textboxmargin) -pady $man(textboxmargin)
$t configure -font $man(currentfont)
manManTabSet $w
$t tag configure volume -font $font(vol) -tabs $man(volcol)
$t tag configure apropos -tabs $man(apropostab) -lmargin2 $man(apropostab)

$t tag configure sel -foreground "$man(textbg)" -background "$man(textfg)"

foreach v $manx(tags) {
$t tag configure $v -font "" -foreground "" -background "" -underline no
set change ""; set newfont 0
set fam $man(text-family); set sty $man(text-style); set poi $man(text-points); set poi2 "m"
foreach g $man($v) {
switch -exact -- $g {
normal {}
underline {append change " -underline yes"}
reverse {append change " -foreground {$man(textbg)} -background {$man(textfg)}"}
italics { set sty $g; set newfont 1 }
bold -
bold-italics {
set sty $g; set poi2 "s"; set newfont 1
}
mono { set fam "Courier"; set poi2 "s"; set newfont 1 }
symbol { set fam "Symbol"; set sty "normal"; set newfont 1 }
small -
medium -
large {
set poi $g; set newfont 1
}
s -
m -
l {
set poi2 $g; set newfont 1
}
left -
right -
center {
append change " -justify $g"
}
default {append change " " [list $g]}
}
}
if {$newfont} {append change " -font \"[spec2font $fam $sty $poi $poi2]\""}
eval $t tag configure $v $change
}
$t tag raise sel


if {[[set m2 $w.occ.m.kill] index end]=="none" || $curedit(printers)!=$man(printers) } {
set plist [string trim $man(printers)]
if [lsearch $plist $manx(printer)]==-1 { set plist [concat $manx(printer) $plist] }

$m2 delete 0 end
foreach p $plist { $m2 add command -label $p -command "manPrint $w $p" }
if ![llength $plist] { $m2 add command -label "(default)" -command "manPrint $w" }
}

if {$curedit(hyperclick)!=$man(hyperclick)} {manHyper $w ""}
if {$curedit(subvols)!=$man(subvols)} {manMakeVolList $w}
}


proc resetfonts {font {w .}} {
if ![catch {set oldfont [$w configure -font]}] {
if {$oldfont==$font} return
$w configure -font $font
}

foreach c [winfo children $w] {
resetfonts $font $c
}
}

proc resetcolors {{w .}} {
global man curedit

set c [winfo class $w]
set g "gui"; if {$c=="Text"} {set g "text"} elseif {[string match "*utton" $c]} {set g "butt"}
set foreground [set selector [set insertbackground $man(${g}fg)]]
set background $man(${g}bg)
set ofg $curedit(${g}fg)
set obg $curedit(${g}bg)

foreach i {foreground background insertbackground selector} {
if ![catch {set color [$w cget -$i]}] {
if {$color==$ofg} {$w configure -$i $foreground} \
elseif {$color==$obg} {$w configure -$i $background}
}
}

set activeforeground $man(activefg)
set activebackground $man(activebg)
set highlightbackground $activebackground
foreach i {activeforeground activebackground highlightbackground} {
catch {$w configure -$i [set $i]}
}

foreach c [winfo children $w] {
resetcolors $c
}
}


proc spec2font {{family "times"} {style "normal"} {points "medium"} {size "m"}} {
global man manx

set dpi $man(dpi)
switch -exact -- $style {
normal {set style "medium-r"}
bold {set style "bold-r"}
italics {
if [regexp -nocase $manx(xmono) $family] {set style "medium-o"} {set style "medium-i"}
}
bold-italics {
if [regexp -nocase $manx(xmono) $family] {set style "bold-o"} {set style "bold-i"}
}
default {puts stderr "nonexistent style: $style"; exit 1}
}

if {[set pts [lsearch $manx(sizes) $points]]!=-1} {
set p "[lindex [lrange $manx(pts) $pts end] [lsearch {s m l} $size]]"
} else {set p $points}
append p "0"

set font "-*-$family-$style-normal-*-*-$p-$dpi-$dpi-*"

return $font
}



proc manSave {} {
global man manx env

if {$manx(savegeom)} {set man(geom) [wm geometry .man]}
set w [manPreferencesMake]
if [winfo exists $w] {set man(geom-prefs) [geom2posn [wm geometry $w]]}

set nfn $manx(startup)
set ofn $manx(startup)-bkup

if {![file exists $nfn] || [file writable $nfn]} {
if {[file exists $nfn]} {eval exec $man(cp) $nfn $ofn}
if [catch {set fid [open $nfn w]}] {
manWinstderr .man "$nfn is probably on a read-only filesystem"
return
}
foreach p [info procs *SaveConfig] {eval $p $fid}
puts $fid "manDot\n"
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
}

}




proc manSaveConfig {fid} {
global man manx high default


puts $fid "#\n# TkMan v$manx(version)"
puts $fid "# configuration saved on [clock format [clock seconds]]"
puts $fid "#\n"

set preamble {
Elements of the man array control many aspects of operation.
Most, but not all, user-controllable parameters are available
in the Preferences panel.  All parameters are listed below.
Those that are identical to their default values are commented
out (preceded by \"#\") so that changes in the defaults will propagate nicely.
If you want to override the default, uncomment it and change the value
to its new, persistent setting.
}
foreach line [split [linebreak $preamble] "\n"] {
puts $fid "# $line"
}
puts $fid ""



manStatsSet; # update its value
foreach i [lsort [array names man]] {
if {[info exists default($i)]} {
if {$default($i)==$man($i)} {set co "#"} {set co ""}
puts $fid "${co}set [list man($i)] [tr [list $man($i)] \n \n$co]"
} elseif {[string match "/*" $i]} {puts $fid "set man($i) $man($i)"}
}

puts $fid "\n\n#\n# Highlights\n#\n"
foreach i [lsort [array names high]] {
puts $fid "set [list high($i)] [list $high($i)]"
}

puts $fid "\n"
}




proc manStatsSaveFile {} {
global man manx

DEBUG {puts -nonewline "manStatsSaveFile"}
if {$manx(statsdirty) && [file readable $manx(startup)] && [file writable $manx(startup)]} {
set fid [open $manx(startup)]; set startup [read $fid]; close $fid

set stats "set man(stats) [list [manStatsSet]]\n"

if [regsub "set man\\(stats\\)\[^\n\]+\n" $startup $stats nstartup] {
set startup $nstartup
DEBUG {puts -nonewline "\tfound existing variable"}
} elseif [regsub "\n\n$manx(userconfig)\n" $startup "\n$stats\n$manx(userconfig)\n" startup] {
DEBUG {puts -nonewline "\tinserted before userconfig"}
} else {
set startup [concat $startup $stats]
DEBUG {puts -nonewline "\tappended"}
}

set fid [open $manx(startup) "w"]; puts -nonewline $fid $startup; close $fid
DEBUG {puts -nonewline "\tsaved to file"}
}
DEBUG {puts ""}

after [expr 5*60*1000] manStatsSaveFile
}


proc manStatsSet {} {
global man manx stat

DEBUG {puts "manStatsSet"}
trace vdelete stat w manStatsDirty
scan $man(stats) "%d" stat(cum-time)
set newstats $stat(cum-time)

foreach i $manx(all-stats) {
if {[set val [lassoc $man(stats) $i]]!=""} {
set stat(cum-$i) $val
} else {
set stat(cum-$i) $stat($i)
}

incr stat(cum-$i) [expr $stat($i)-$stat(cur-$i)]
set stat(cur-$i) $stat($i)

lappend newstats [list $i $stat(cum-$i)]
}

set man(stats) $newstats
trace variable stat w manStatsDirty
set manx(statsdirty) 0

return $man(stats)
}

proc manStatsDirty {name1 name2 op} {
global manx
DEBUG {puts "manStatsDirty: $name2"}
set manx(statsdirty) 1
}





proc manDot {} {
global manx

manManManx

manPresDefaultsSet
toplevel .man -class TkMan
manPreferencesGet fill

set manx(manDot) 1
}

proc manManManx {} {
global man manx
foreach i {
iconify iconname iconbitmap iconmask iconposition
geom database glimpsestrays
} {
if {![info exists manx($i)]} {set manx($i) $man($i)}
}
}



set manx(manpathset-warnings) ""
proc manManpathSet {} {
global manx env

set manx(manpathset-warnings) ""
set ws "\[ \t\]"; set nws "\[^ \t\]"

if {![info exists env(MANPATH)] || $env(MANPATH)==""} {
set manpath ""; set manpathsrc ""; set def [string trim $manx(manpathdef)]

if ![catch {set gmanpath [exec gmanpath -q]}] {
set manpathsrc "given by gmanpath"
set manpath $gmanpath


} elseif {[file readable [set manconf "/etc/man.conf"]]} {
set manpathsrc "read from $manconf"
set manpathlist {}

set fid [open $manconf]
while {![eof $fid]} {
gets $fid line
if {[regexp "^_default$ws+(.*)" $line all dirs]
|| [regexp "^\[a-zA-Z\]$nws*$ws+($nws+)\$" $line all dirs]} {
set onoff [string match "_default*" $line]
foreach globdir $dirs {
set hassubdirs [string match "*/" $globdir]
foreach dir [glob -nocomplain [string trimright $globdir "/"]] {
if {!$hassubdirs} {
if {![string match "*/man" $dir]} {set dir [file dirname $dir]}
if {![string match "*/man" $dir]} continue
}
if {[lsearch $manpathlist $dir]==-1} {
lappend manpathlist $dir
if {![info exists man($dir)]} {set man($dir) $onoff}
append manpath "$dir:"
}
}
}
}
}
close $fid


} elseif {[file readable [set manconf "/etc/man.config"]] || [file readable [set manconf "/etc/manpath.config"]]} {
set manpathsrc "read from $manconf"
set manpathlist ""

set fid [open $manconf]
while {![eof $fid]} {
gets $fid line
if {[regexp "^(MANDATORY_)?MANPATH$ws+(.*)" $line all junk man]} {
append manpath ":$man"; lappend manpathlist $man
} elseif {[regexp "^MANPATH_MAP$ws+($nws+)$ws+($nws+)" all bin man]} {
if {[lsearch $manx(bin-paths) $bin]!=-1 && [lsearch $manpathlist $man]==-1} {
append manpath ":$man"; lappend manpathlist $man
}
}
}
close $fid


} elseif {[file readable [set manconf "/etc/default/man"]]} {
set fid [open $manconf]
while {![eof $fid]} {
if {[regexp "^\[ \t]*MANPATH\[ \t]*=\[ \t]*(.*)" [gets $fid] all tmp]} {
regsub "scohelp:" $tmp "" man
}
}
close $fid

set manpathsrc "set to system default in $manconf"
set manpath $man

} elseif {[file readable /usr/catman] || [file readable /usr/share/catman]} {
set manpathsrc "set to the IRIX default"
set manpath "/usr/share/catman:/usr/share/man:/usr/catman:/usr/man"


} elseif {$def!=""} {
set manpathsrc "set to local default"
set manpath $def


} else {
set manpathsrc "calculated from your PATH"

foreach i $manx(bin-paths) {
if {$i==""} continue
if [regexp {(.*)/bin(/.*)?} $i all dirtop] {
set i $dirtop/man
if {[manPathCheckDir $i]==""} {
append manpath "$i:"
}
}
}
}


set manpath [string trim $manpath ":"]
set env(MANPATH) $manpath

regsub -all ":" $manpath ":\n    " manpathshow
append manx(manpathset-warnings) "You don't have a MANPATH environment variable set, but you should.\n"
append manx(manpathset-warnings) "Assuming a MANPATH, $manpathsrc, of:\n    $manpathshow\n\n"
}

set manx(MANPATH0) $env(MANPATH)
DEBUG {puts stderr "env(MANPATH) => $env(MANPATH)"}
}



set manx(manpath-warnings) ""
set manx(fBSDI) [file readable [set whatis "/usr/share/man/whatis.db"]]

proc manManpathCheck {} {
global man manx env

set manx(manpath-warnings) ""
set manx(paths) {}
set manpatherr ""
set whatiserr 0
set glimpseerr 0
set glimpseuptodate 1
set pass 0


set fHPUX 0; if {!$manx(fBSDI)} { set fHPUX [file readable [set whatis "/usr/lib/whatis"]] }


foreach root [split $manx(MANPATH0) ":"] {
if {[string match "./*" $root] || [string match "../*" $root]} {
append manpatherr "$root ignored -- relative paths are incompatible with TkMan\n"
continue
}
if [string match "~*" $root] {set root [glob -nocomplain $root]}
if {[string trim $root]==""} continue

if {[string match "/?*/" $root ]} {
append manpatherr "$root -- spurious trailing slash character (\"/\")\n"
set root [string trimright $root "/"]
}

if {$root=="/"} {
append manpatherr "$root -- root directory not allowed\n"
} elseif {[lsearch $manx(paths) $root]>=0} {
append manpatherr "$root -- duplicated path\n"
} elseif {[set tmp [manPathCheckDir $root]]!=""} {
append manpatherr $tmp
} elseif {![string match "*/catman" $root] && [glob -nocomplain $root/$manx(subdirs)]==""} {
append manpatherr "$root -- no subdirectories matching $manx(subdirs) glob pattern\n"
if {![string match "*/man" $root] && [glob -nocomplain "[file dirname $root]/$manx(subdirs)"]!=""} {
append manpatherr "    => try changing it to [file dirname $root]\n"
} elseif {[file exists $root/man]} {
append manpatherr "    => try changing it to $root/man\n"
}
} else {
lappend manx(paths) $root
if {![info exists man($root)]} {set man($root) 1}
lappend manx(pathstat) $man($root)
set manx($root,latest) [lfirst [manLatestMan $root]]

if {!$manx(fBSDI) && !$fHPUX} {
if ![file exists [set whatis $root/windex]] {
set whatis $root/whatis
}
}

if {![file exists $whatis]} {
append manpatherr "$root -- no `whatis' file for apropos\n"
if {!$whatiserr} {
append manpatherr "    => generate `whatis' with mkwhatis/catman\n"
set whatiserr 1
}
} elseif {![file readable $whatis]} {
append manpatherr "$whatis not readable\n"
} elseif {[file mtime $whatis]<$manx($root,latest)} {
append manpatherr "$whatis out of date\n"
}

if {$man(glimpse)!=""} {
set g $root; if {$man(indexglimpse)!="distributed"} {set g $man(glimpsestrays)}
set gi $g/.glimpse_index

if {$man(indexglimpse)=="distributed" || $pass==0} {
if {[glob -nocomplain $g/.glimpse*]==""} {
append manpatherr "$g -- no Glimpse support\n"
if {!$glimpseerr} {
append manpatherr "    => try building Glimpse database (under Occasionals)\n"
set glimpseerr 1; set glimpseuptodate 0
}
} elseif {![file readable $gi]} {
append manpatherr "$g -- Glimpse index exists but not readable\n"
}
}

if {[file readable $gi] && [file mtime $gi]<$manx($root,latest)} {
append manpatherr "$root -- Glimpse index out of date\n"
}
}
}

incr pass
}

if {$manpatherr!=""} {
append manx(manpath-warnings) "Problems in paths of MANPATH environment variable...\n" $manpatherr "\n"
}

if ![llength $manx(paths)] {
puts stderr "NO VALID DIRECTORIES IN MANPATH!\a"
exit 1
}
}

proc manPathCheckDir {dir} {
set warning ""

if {![file exists $dir]} {
set warning "doesn't exist"
} elseif {![file isdirectory $dir]} {
set warning "not a directory"
} elseif {![file readable $dir]} {
set warning "not readable\n    => check permissions"
} elseif {![file executable $dir]} {
set warning "not searchable (executable)\n    => check permissions"
} elseif {[glob -nocomplain $dir/*]==""} {
set warning "is empty"
}

if {$warning!=""} {set warning "$dir -- $warning\n"}
return $warning
}

proc manBinCheck {} {
global man manx env stat

set err 0
foreach var $manx(binvars) {
set val [set $var]
if {$val==""} continue

foreach pipe [split $val "|"] {
set bin [lfirst $pipe]
set found 0

if {[string match "/*" $bin]} {set pathlist [file dirname $bin]; set tail [file tail $bin]
} else {set pathlist $manx(bin-paths); set tail $bin}

foreach dir $pathlist {
if {$dir=="."} continue
set fullpath $dir/$tail
if {[file isfile $fullpath] && [file executable $fullpath]} {
set found 1
set stat(bin-$bin) $fullpath
break
}
}

if {!$found} {
puts stderr "$bin not found--check the $var variable in $manx(startup) or the Makefile."
incr err
} else {
if {$var=="man(egrep)"} {
set ename "tkman"; set evol "1"; set eext "tk"
set eman "/usr/man/man1/$ename.$evol$eext"
set eregexp "/${ename}(\\..$eext\[^/\]*)?$"
set ematch ""
set egreperr [catch {set ematch [exec echo $eman | $fullpath $eregexp]} info]
if {$egreperr || $ematch!=$eman} {
puts stderr "Change `egrep' in Makefile or `man(egrep)' in $manx(startup),\nfrom $man(egrep), which maps to $fullpath,\nto something that can handle extended or full regular expressions."
incr err
continue
}
}

if {[set info [lassoc $manx(bin-versioned) $tail]]!=""} {
lset $info flag minvers
set execerr [catch {set lines [exec $fullpath $flag < /dev/null]} info]
} elseif {[string match "g*" $tail]} {
set minvers 0.0
set execerr [catch {set lines [exec $fullpath $flag < /dev/null]} info]
set execerr 0; set lines $info
} else continue

if {$execerr && $minvers==0.0} {
} elseif {$execerr} {
puts "ERROR executing \"$fullpath $flag\": $info\a"
incr err
} else {
set line ""; foreach line [split $lines "\n"] { if {$line!=""} break }
set vers unknown
if {$line=="" || ![regexp $manx(bin-versregexp) $line vers cmpvers] || $cmpvers<$minvers} {
if {$minvers!=0.0} {
puts stderr "$bin is version $vers--must be at least $minvers."
incr err
}
} else { set stat(bin-$bin-vers) $vers }
}
}
}
}

if {$err} {exit 1}
}

proc manParseCommandline {} {
global manx argv argv0 env

for {set i 0} \$i<[llength $argv] {incr i} {
set arg [lindex $argv $i]; set val [lindex $argv [expr $i+1]]
switch -glob -- $arg {
-help -
-h* -
--help {
set helptxt {
[-M <MANPATH>] [-M+ <paths to append to MANPATH>] [-+M <paths to prepend to MANPATH>]
[-[!]now] [-rebuildandquit] [-[!]iconify] [-version]
[-title <string>] [-startup <file>] [-database <file>] [-[!]debug] <man page>
}
puts -nonewline "tkman"
foreach line [split [linebreak $helptxt 70] "\n"] { puts "\t$line" }
exit 0
}
-M {set env(MANPATH) $val; incr i}
-M+ {append env(MANPATH) ":$val"; incr i}
-+M {set env(MANPATH) "$val:$env(MANPATH)"; incr i}
-now {set manx(now) 1}
-notnow {set manx(now) 0}
-iconname {set manx(iconname) $val; incr i}
-iconmask {set manx(iconmask) $val; incr i}
-iconposition {set manx(iconposition) $val; incr i}
-iconbitmap {set manx(iconbitmap) $val; incr i}
-icon* {set manx(iconify) 1}
-noicon* {set manx(iconify) 0}
-rebuild* {set manx(rebuildandquit) 1}
-quit {if [string match no* $val] {set manx(quit) 0}; incr i}
--v* -
-v* {puts stdout "TkMan v$manx(version) of $manx(date)"; exit 0}
-t* {set manx(title) $val; incr i}
-s* {set manx(startup) $val; incr i}
-database {set manx(database) $val; incr i}
-d* {set manx(debug) 1; set manx(quit) 0; set manx(iconify) 0}
-nod* {set manx(debug) 0}
-* {puts stdout "[file tail $argv0]: unrecognized option: $arg"; exit 1}
default {
after 2000 manShowMan $arg {{}} .man
break
}
}
}
if {[info exists geometry]} {set manx(geom) $val}
}


proc ASSERT {args} {
if {![uplevel 1 eval $args]} {
puts "ASSERTION VIOLATED: $args"
exit 1
}
}

proc DEBUG {args} {
global manx
if $manx(debug) {uplevel 1 eval $args}
}



if {[info tclversion]<$manx(mintcl) || $tk_version<$manx(mintk)} {
puts -nonewline stderr "Tcl $manx(mintcl)/Tk $manx(mintk) minimum versions required.  "
puts stderr "You have Tcl [info tclversion]/Tk $tk_version"
exit 1
} elseif {int([info tclversion])-int($manx(mintcl))>=1 || int($tk_version)-int($manx(mintk))>=1} {
puts stderr "New major versions of Tcl and/or Tk may have introduced\nincompatibilies in TkMan.\nCheck the TkMan home ftp site for a possible new version.\n"
}





set w .man


set man(manList) {1 2 3 4 5 6 7 8 9 l o n p D}
set man(manTitleList) {
"User Commands" "System Calls" Subroutines
Devices "File Formats"
Games "Miscellaneous" "System Administration" "*** check contrib/*_bindings ***"
Local Old New Public "*** check contrib/*_bindings ***"
}
set man(stats) [clock seconds]
set man(time-lastglimpse) -1
set man(time-lastdatabase) -1
set man(families) {Times "New Century Schoolbook" Lucida Courier Helvetica}
set manx(styles) {normal bold italics bold-italics}
set manx(pts) {10 12 14 18 24}
set manx(sizes) {small medium large}
set man(gui-family) "Times"
set man(gui-style) "bold"
set man(gui-points) "medium"
set man(text-family) "New Century Schoolbook"
set man(text-style) "normal"
set man(text-points) "medium"
set man(vol-family) "Times"
set man(vol-style) "normal"
set man(vol-points) "small"
set man(dpi) [lfirst $man(dpis)]
if {$man(dpis)=={* 75 100}} {
button .x
if {[winfo fpixels . 1i]<100 && [set man(dpi) 75] && ![catch {.x configure -font [spec2font]}]} {
} elseif {[set man(dpi) 100] && ![catch {.x configure -font [spec2font]}]} {
} else {set man(dpi) *}
destroy .x
}
set man(currentfont) [spec2font $man(text-family) $man(text-style) $man(text-points)]

set manx(tags) {h1 h2 h3 tt sc y b bi i search isearch manref title highlight hot indent indent2}
set man(tt) mono
set man(sc) s
set man(y) symbol
set man(b) bold
set man(bi) bold-italics
set man(i) italics
set man(h1) {bold l}
set man(h2) {bold m}
set man(h3) {bold s}
set man(isearch) {-background gray}
set man(search) reverse
set man(manref) {mono -foreground blue}
set man(title) {bold large l}
set man(hot) {-underline yes}
set man(highlight) {-background #ffd8ffffb332}; # a pale yellow
set man(indent) {-lmargin1 5m -lmargin2 10m}
set man(indent2) {-lmargin1 10m -lmargin2 15m}

set man(maxhistory) 15; set manx(maxhistory-v) [set manx(maxhistory-t) {5 10 15 20 30 40 50}]
set man(recentdays) 14; set manx(recentdays-v) [set manx(recentdays-t) {1 2 7 14 30 60 90 180}]
set man(shortcuts) {}
set man(indexglimpse) "distributed"; set manx(indexglimpse-v) [set manx(indexglimpse-t) {"distributed" "unified"}]
set man(maxglimpse) 200; set manx(maxglimpse-v) [set manx(maxglimpse-t) {25 50 100 200 500 1000 "none"}]
set man(whatwhere) 1; set manx(whatwhere-v) {1 0}; set manx(whatwhere-t) {"pathname" "description"}
set man(iconify) 0; set manx(iconify-v) {1 0}; set manx(iconify-t) {"yes" "no"}
set man(subsect) ""; set manx(subsect-v) {"-b" ""}; set manx(subsect-t) {"yes" "no"}
set man(nroffsave) "off"; set manx(nroffsave-v) [set manx(nroffsave-t) {"off" "on" "on & compress"}]
set man(headfoot) "-k"; set manx(headfoot-v) {"-k" ""}; set manx(headfoot-t) {"yes" "no"}
set man(hyperclick) "single"; set manx(hyperclick-v) [set manx(hyperclick-t) {"double" "single"}]
set man(incr,case) -1
set man(regexp,case) -1
set man(aproposfilter) {| sort | uniq}
set man(scrollbarside) right; set manx(scrollbarside-v) [set manx(scrollbarside-t) {"left" "right"}]
set man(zaphy) ""; set manx(zaphy-v) {"-y" ""}; set manx(zaphy-t) {"yes" "no"}
set man(strictmotif) 0; set manx(strictmotif-v) {1 0}; set manx(strictmotif-t) {"yes" "no"}
set man(subvols) 1; set manx(subvols-v) {1 0}; set manx(subvols-t) {"yes" "no"}
set man(optmenus) 1; set manx(optmenus-v) {1 0}; set manx(optmenus-t) {"yes" "no"}
set man(textboxmargin) 5; set manx(textboxmargin-v) [set manx(textboxmargin-t) {0 1 2 3 4 5 7 10}]
set man(error-effect) "bell & flash"; set manx(error-effect-v) [set manx(error-effect-t) {"bell & flash" "bell" "flash" "none"}]
set man(volcol) 4.0c; set manx(volcol-v) {0 1.5c 2.0c 2.5c 3.0c 3.5c 4.0c 4.5c 5.0c 7.5c 10.0c}; set manx(volcol-t) {"no columns" "1.5 cm" "2 cm" "2.5 cm/~1 inch" "3 cm" "3.5 cm" "4 cm" "4.5 cm" "5.0 cm/~2 inches" "7.5 cm" "10 cm"}
set man(apropostab) "4.5c"; set manx(apropostab-v) {0 3.0c 4.0c 4.5c 5.0c 5.5c 6.0c 7.5c 10.0c}; set manx(apropostab-t) {"none" "3 cm" "4 cm" "4.5 cm" "5 cm" "5.5 cm" "6 cm" "7.5 cm" "10 cm"}
set man(changeleft) "-c"
set man(prefersource) 1
set man(high,hcontext) 50
set man(high,vcontext) 10; set manx(high,vcontext-v) [set manx(high,vcontext-t) {0 2 5 7 10 15 20}]
set man(geom) 570x800+150+10
set man(geom-prefs) +300+300
set man(iconname) {TkMan: $manx(name$w)}
set man(iconbitmap) "(default)"
set man(iconmask) ""
set man(iconposition) ""
set man(startup) $env(HOME)/.tkman

set man(date-format) "%H:%M, %e %B %Y"

set man(colors) {black white red "light yellow" yellow orange green blue beige SlateGray4 gray75 gray90}


checkbutton .a
set man(textfg) [set man(buttfg) [set man(guifg)  [.a cget -foreground]]]
set man(textbg) [set man(guibg) [set man(buttbg) [.a cget -background]]]
set man(activefg) [.a cget -activeforeground]
set man(activebg) [.a cget -activebackground]
destroy .a

set manx(mono) [expr [winfo depth .]==1]
if $manx(mono) {
set man(foreground) "black"
set man(background) "white"
set man(colors) {black white}
set man(textfg) [set man(activebg) [set man(buttfg) [set man(guifg) "black"]]]
set man(textbg) [set man(activefg) [set man(buttbg) [set man(guibg) "white"]]]

set man(search) [set man(isearch) "reverse"]
set man(highlight) "bold-italics"
set man(manref) "mono underline"

}


foreach i [array names man] {set default($i) $man($i)}



set manx(title) "TkMan"
regexp "..../../.." {$Date: 1996/11/08 23:52:25 $} manx(date)
set manx(date-seconds) [clock scan [string range $manx(date) 5 end]/[string range $manx(date) 0 3]]
set manx(mtimeargv0) [file mtime $argv0]
set manx(expire-warnings) ""
if {[clock seconds] > [clock scan "2 years" -base $manx(date-seconds)]} {
set manx(expire-warnings) "This is a very old copy of TkMan.  Please check ftp://ftp.cs.berkeley.edu/people/phelps/ucb/tcltk for the latest and greatest."
}
set manx(manList) $man(manList)
set manx(manTitleList) $man(manTitleList)
set manx(userconfig) "### your additions go below"
set manx(posnregexp) {([-+]?[0-9]+)([-+][0-9]+)}
set manx(init) 0
set manx(manDot) 0
set manx(cursor) left_ptr
set manx(yview,help) 0
set manx(paths) ""
set manx(pathstat) ""
set manx(uid) 1
set manx(outcnt) 1
set manx(debug) 0
set manx(defaults) 0
set manx(startup) $man(startup)
set manx(savegeom) 1
set manx(lastman) TkMan
set manx(quit) 1
set manx(mandot) ""
set manx(db-manpath) ""
set manx(db-signature) ""
set manx(rebuildandquit) 0
set manx(now) 0
set manx(newmen) ""
set manx(xmono) {courier|helvetica}
set manx(subdirs) "{man,cat}?*"
set manx(shift) 0
if [info exists env(PRINTER)] { set manx(printer) $env(PRINTER) } \
elseif [info exists env(LPDEST)] { set manx(printer) $env(LPDEST) } \
else { set manx(printer) "" }

set manx(bin-versregexp) {([0-9]+\.[0-9]+)([^ ,;]+)?} ;#(\.[0-9]+)?
set manx(bin-versioned) {{rman "-v" 2.4} {glimpse "-V" 2.1} {glimpseindex "-V" 2.1}}
set manx(modes) {man help section txt apropos super info}
set manx(mode-desc) {"manual pages seen" "references to help page" "volume listings invoked" "text files seen" "apropos listings" "Glimpse full-text searches" "ganders at this page"}
DEBUG { assert [llength $manx(modes)]!=[llength $manx(mode-desc)] "mismatched modes lists" 1 }
set manx(stats) {man-hyper man-dups man-button man-link man-history man-shortcut page-section page-highlight-go page-highlight-add page-highlight-sub page-shortcut-add page-shortcut-sub page-regexp-next page-regexp-prev page-incr-next page-incr-prev page-mono high-exact high-move high-lose print}
set manx(stats-desc) {"via hyperlink" "via multiple matches pulldown" "via man button or typein box" "via links menu" "via history menu" "via shortcut menu" "jumps to section header" "jump to highlight" "highlight additions" "highlight deletions" "shortcut additions" "shortcut deletions" "regular expression searches forward" "regular expression searches backward" "incremental searches forward" "incremental searches backward" "swaps between proportional font and monospaced" "exact" "repositioned" "lost" "pages printed"}
DEBUG { assert [llength $manx(stats)]!=[llength $manx(stats-desc)] "mismatched stats lists" 1 }
set stat(man-no) 0
set manx(all-stats) [concat $manx(modes) $manx(stats) "man-no"]
foreach i $manx(all-stats) {set stat(cur-$i) [set stat($i) 0]}



if [info exists env(TKMAN)] {set argv "$env(TKMAN) $argv"}
if {![info exists env(PATH)] || $env(PATH)==""} { set env(PATH) "/usr/local/bin:/usr/bin" }
set manx(bin-paths) [split [string trim $env(PATH) ":"] ":"]

manParseCommandline
set manx(startup-short) [file tail $manx(startup)]

if {![file exists $manx(startup)]} {eval $manx(newuser)}

set manx(savefilevers) "unknown"
set manx(updateinfo) ""


if {$manx(startup)!="" && ![file exists $manx(startup)] && [file writable [file dirname $manx(startup)]]} {
catch {
set os [string tolower [exec uname -s]]; set osvers [exec uname -r]
set setup ""; # most OSes work without configuration file

if {$os=="sunos" && $osvers>=5.0} {
set setup solaris 
} elseif {[string match "irix*" $os]} {
set setup irix
} elseif {$os=="sco_sv"} {
set setup $os
}

if {$setup!="" && [info exists manx($setup-bindings)]} {
set fid [open $manx(startup) "w"]
puts $fid $manx($setup-bindings)
close $fid
}
}
}



if {$manx(startup)!="" && [file readable $manx(startup)]} {
set fid [open $manx(startup)]

if [string match "#!*" [gets $fid line]] {
puts stderr "$manx(startup) looks like an executable."
puts stderr "You should delete it, probably."
exit 1
}

while {![eof $fid]} {
if {[regexp {^# TkMan v([0-9.]+.*)} $line all manx(savefilevers)]} {
break
}
gets $fid line
}
catch {close $fid}
DEBUG {puts "*** savefilevers = $manx(savefilevers)"}

source $manx(startup)

if {$manx(savefilevers)=="unknown" || [string range $manx(savefilevers) 0 2]<1.6} {
set manx(updateinfo) "Startup file information updated from version $manx(savefilevers) to version $manx(version).\n"

foreach var {catsig compress zcat} {
set man($var) $default($var)
}

foreach k {greater less question} {
set var "sb(key,MS-$k)"
if [info exists $var] {unset $var}
}

append manx(updatedinfo) "    Added call to manDot\n"


append manx(updateinfo) "Save updates via the Quit button or Occasionals/Checkpoint, or cancel updates via \"Occasionals / Quit, don't update\".\n"
if ![catch "exec $man(cp) $manx(startup) [set ofn $manx(startup)-$manx(savefilevers)]"] {
append manx(updateinfo) "Old startup file saved as $ofn\n"
}
append manx(updateinfo) "\n\n"
}
if {!$manx(manDot)} {
manDot
}
}
catch {unset high(*)}


set manx(highs) [concat $manx(styles) reverse underline mono $man(colors)]

set manx(extravols) [list {apropos "apropos list" "No apropos list"}]
if {$man(glimpse)!=""} { lappend manx(extravols) {glimpse "glimpse list" "No glimpse list"} }
lappend manx(extravols) {recent "Recently added/changed" {}} {high "All with Highlights" {}} {all "All Enabled Volumes" {}}
foreach i $manx(extravols) { lappend manx(specialvols) [lfirst $i] }

set manx(zregexp) "\\.("
set manx(zglob) "{"
set manx(zoptglob) "{,"
foreach z $man(zlist) {
append manx(zregexp) "$z|"
append manx(zglob) "$z,"
append manx(zoptglob) ".$z,"
}
foreach z {zregexp zglob zoptglob} { set manx($z) [string trimright $manx($z) ",|"] }
append manx(zregexp) ")\$"
append manx(zglob) "}"
append manx(zoptglob) "}"



set manx(binvars) {
manx(rman) man(glimpse) man(glimpseindex)
man(format) man(print) man(catprint) man(apropos) man(zcat) man(compress) 
man(sed) man(egrep) man(cp) man(mv) man(rm) man(mkdir) man(chmod) man(sort)
}
manBinCheck


if {[llength $man(manList)]!=[llength $man(manTitleList)]} {
puts stderr "Length of section abbreviations differs from length of section titles:\n\nlength [llength $man(manList)]:\t$man(manList)\n\nlength [llength $man(manTitleList)]:\t$man(manTitleList)"
exit 1
}

set manx(glimpseindex) ""
if {$man(glimpse)!="" && $man(glimpseindex)!=""} {
foreach p $manx(paths) {
if {![file writable $p]} {set manx(glimpseindex) $man(glimpseindex); break}
}
}


if !$manx(defaults) manDescDefaults

set manx(statsdirty) 0
manStatsSet
manStatsSaveFile;	# should just set timer this time through, not save to a file

if {[llength $mani($manx(glimpsestrays),dirs)]==0} {set manx(glimpsestrays) ""}

set STOP 0
TkMan

set manx(startuptime) [clock seconds]
set starttime [time manInit]

DEBUG {
puts stdout "init takes $starttime"

set t $w.show

entry $w.in -relief sunken -textvariable manx(debugcmd)
bind $w.in <KeyPress-Return> {manWinstdout .man "[eval $manx(debugcmd)]"}
pack $w.in -fill x

proc manStatsSaveFile args {}
}

manHighlightsUpdate
