head	1.1;
branch	1.1.1;
access;
symbols
	john2:1.1.1.1.0.8
	lapyu1:1.1.1.1.0.6
	john1:1.1.1.1
	lapyu-work:1.1.1.1.0.4
	john-work:1.1.1.1.0.2
	SIXALPHA:1.1.1.1
	TEXLIVE:1.1.1;
locks; strict;
comment	@# @;


1.1
date	2000.10.03.04.02.54;	author plaice;	state Exp;
branches
	1.1.1.1;
next	;

1.1.1.1
date	2000.10.03.04.02.54;	author plaice;	state Exp;
branches;
next	;


desc
@@



1.1
log
@Initial revision
@
text
@#!/usr/bin/perl -w
###############################################################################
# texdoctk v.0.3 (March 11, 2000) - GUI for TeX documentation access
# Copyright (C) 2000  Thomas Ruedas
# This program is provided under the GNU Public License; see the README file
# for details about requirements, installation, configuration and the full
# disclaimer.
###############################################################################
use strict;
use Tk;

$|=1;
my $quiet;
# system variables
my ($texmfmain,$texdocpath,$datadir,
    $dvi_viewer,$dvips_conv,$dvips_opts,$ps_viewer,$pdf_viewer,
    $pdfps_conv,$pdfps_opts,$html_viewer,$htmlps_conv,$htmlps_redir,
    $txt_viewer,$txtps_conv,$txtps_redir,$print_cmd,$print_opts);
my %datvers=("000",100,"001",102,"002",102);

my ($line,@@dummy);
my @@tmpfiles;
# read system-wide defaults from texdocrc.defaults
my $sysrc=`kpsewhich --progname=texdoctk --format='other text files' texdocrc.defaults`;
chomp $sysrc;
&readrc($sysrc);
@@dummy=split("/",$sysrc);
pop @@dummy;
$datadir=join('/',@@dummy);
# possibly use personal settings instead of defaults
my $myrc="$ENV{HOME}/.texdocrc";
if (-e $myrc) { &readrc($myrc); }
# command line options
if (defined @@ARGV) {
    foreach (@@ARGV) {
      OPTS: {
	  ($ARGV[0] eq "-q") && do { $quiet=1; last OPTS; };
      };
    }
}
# open /dev/null for quiet execution
if ($quiet == 1) { open(NULL,">/dev/null"); }
#
my $special=0;
my @@button;
$button[17]="Miscellaneous";
my (@@packname,@@topic,@@doc,@@keywords,@@maxind);
# read database file
my $i=-1;
my $j;
my $database=join("/",($datadir,"texdoc-local.dat"));
# use default database for installed distribution version if there is no local
unless (-e $database) {
    my $updates=join('/',($texmfmain,"updates.dat"));
    open(UPDATES,"$updates");
    $line=<UPDATES>;
    if ($line =~ /teTeX-1\.0/) {
	while (<UPDATES>) { $line=$_; }
	if ($line =~ /update\s/) {
	    @@dummy=split(' ',$line);
	    $database=join("",("$datadir/texdoc-",$datvers{$dummy[1]},".dat"));
	} else {
	    $database=join("/",($datadir,"texdoc-100.dat"));
	}
    } else {
	print "WARNING: You don't have teTeX-1.0.x installed.
The database for teTeX-1.0 will be used, but some documents will
not be found.\n";
	$database=join("/",($datadir,"texdoc-100.dat"));
    }
    close(UPDATES);
}
open(DATABASE,"$database") || die "Couldn't open $database.\n";
while ($line = <DATABASE>) {
  LINETYPE: {
      ($line =~ /^\@@/) && do { # category
	  ++$i;
	  if ($i == $#button) {
	      pop @@button;
	      push @@button,(substr($line,1,-1));
	      $special=1;
	  } else {
	      $button[$i]=substr($line,1,-1);
	  }
	  $j=0;
	  last LINETYPE;
      };
      ($line =~ /^(#|$)/) && do { # comment line
	  last LINETYPE;
      };
#     list item
      @@dummy=split(";",$line);
      $packname[$i][$j]=$dummy[0];
      $topic[$i][$j]=$dummy[1];
      $doc[$i][$j]=$dummy[2];
      $keywords[$i][$j]=$dummy[3];
      $maxind[$i]=$j;
      ++$j;
  };
}
close(DATABASE);

# Tk
# create frames for main window: commands on top, frame for buttons below
my $main=new MainWindow;
$main->title("TeX Documentation Browser");
$main->bind('<Control-q>'=>\&clean_exit);
$main->bind('<Control-h>'=>\&helptext);
$main->bind('<Control-s>'=>\&mksrch);
$main->bind('<Control-t>'=>\&settings);
my $cmdframe=$main->Frame(-background=>"#ffcc99");
my $buttonframe=$main->Frame;
$cmdframe->pack(-side=>'top',-fill=>'x');
$buttonframe->pack(-side=>'bottom');
# make buttons for command frame
$cmdframe->Button(-text=>'Quit',
		  -command=>\&clean_exit)->pack(-side=>'left');
$cmdframe->Button(-text=>'Search',
		  -command=>\&mksrch)->pack(-side=>'left');
$cmdframe->Button(-text=>'Help',
		  -command=>\&helptext)->pack(-side=>'right');
$cmdframe->Button(-text=>'Settings',
		  -command=>\&settings)->pack(-side=>'right');
# make buttons for category button frame
my $lbut=0;
my $l;
foreach (@@button) { $l=length $_; if ( $l > $lbut) { $lbut=$l; } }
my @@catg;
my ($i2,$i3);
my $nbutt=scalar @@button;
my $ncols=$nbutt/3-1;
foreach (0..$ncols) {
    $i=$_;
    $i2=$i+$nbutt/3;
    $i3=$i+2*$nbutt/3;
    $catg[$i]=$buttonframe->Button(-text=>$button[$i],
				   -width=>$lbut,
				   -command=>[\&tpslct,$i,\@@dummy])->grid
	($catg[$i2]=$buttonframe->Button(-text=>$button[$i2],
					 -width=>$lbut,
					 -command=>[\&tpslct,$i2,\@@dummy]),
	 $catg[$i3]=$buttonframe->Button(-text=>$button[$i3],
					 -width=>$lbut,
					 -command=>[\&tpslct,$i3,\@@dummy]));
}
# disable last button (lower right) if no local specials are found in list
my $ncat;
if ($special == 0) {
    $catg[$#button]->configure(-state=>'disabled');
    $ncat=$nbutt-1;
} else {
    $ncat=$nbutt;
}
# define common default font for labels and text explicitly
my @@deffont=$catg[0]->configure(-font);

MainLoop;

########## SUBROUTINES ########################################################
# toplevel for selecting a topic of a category for viewing or printing
sub tpslct {
    my($opt,@@srchitems)=@@_;
    my (@@lbitems,@@lbdocs,$dspselect,$docselect,$wtitle);
    if ($opt >= 0) {
#       main window buttons
	for ($j=0; $j <= $maxind[$opt]; ++$j) {
	    push @@lbitems,$topic[$opt][$j];
	    push @@lbdocs,$doc[$opt][$j];
	}
	$wtitle=$button[$opt];
    } else {
#       search results
	for ($j=0; $j < $#srchitems; $j+=2) {
	    my $k=$j+1;
	    push @@lbitems,$topic[$srchitems[$j]][$srchitems[$k]];
	    push @@lbdocs,$doc[$srchitems[$j]][$srchitems[$k]];
	}
	$wtitle="Search results";
    }
# toplevel window of category $opt with two frames
    my $tpwin=$main->Toplevel(-title=>$wtitle);
    my $tpdsp=$tpwin->Frame(-relief=>'groove')->pack(-side=>'top');
    my $tpslc=$tpwin->Frame()->pack(-side=>'bottom');
# selection frame with listbox and buttons
#   label for listbox
    my $tplabel=$tpslc->Label(-text=>'Topics')->pack(-anchor=>'w',
						     -side=>'top');
#   listbox with optional scrollbar
    my $tplist=$tpslc->Scrolled("Listbox",
				-scrollbars=>"oe",
				-width=>0,
				-selectmode=>'single',
				-cursor=>'hand2')->pack(-side=>'left');
    $tplist->insert('end',@@lbitems); # fill topics into listbox
#   buttons frame
    my $tpbframe=$tpslc->Frame(-borderwidth=>8);
    $tpbframe->pack(-side=>'right');
#   make buttons for command frame
    $tpbframe->Button(-text=>'View',
		      -command=>sub{&viewslc($docselect,$tpbframe);},
		      -width=>6)->pack(-side=>'top');
    $tpbframe->Button(-text=>'Print',
		      -command=>sub{&prtslc($docselect,$tpbframe);},
		      -width=>6)->pack(-side=>'top');
    $tpbframe->Button(-text=>'Cancel',
		      -command=>sub{destroy $tpwin},
		      -width=>6)->pack(-side=>'bottom');
# display frame
    my $dsplabel=$tpdsp->Label(-text=>'Selection:')->pack(-anchor=>'w',,
							  -fill=>'x',
							  -side=>'left');
    my $dspslc=$tpdsp->Label(-textvariable=>\$dspselect,
			     -borderwidth=>2)->pack(-anchor=>'w',
						    -fill=>'x',
						    -side=>'right');
# handle selection; only one selection possible
    $tplist->bind('<Button-1>'=>sub{my $slctind=$tplist->curselection();
				    $dspselect=$lbitems[$slctind];
				    $docselect=$lbdocs[$slctind];});
#   key bindings
    $tplist->bind('<Double-Button-1>'=>sub{
	&viewslc($docselect,$tpbframe);});
    $tpwin->bind('<Control-v>'=>sub{
	&viewslc($docselect,$tpbframe);});
    $tpwin->bind('<Control-p>'=>sub{
	&prtslc($docselect,$tpbframe);});
    $tpwin->bind('<Control-c>'=>sub{destroy $tpwin});
    $tplist->bind('<Button-3>'=>sub{
	if (defined $docselect) {
	    my $fullpath=join("/",($texdocpath,$docselect));
	    &popmsg(0,"Selected file:\n$fullpath",$tpbframe);
	} else {
	    &popmsg(2,"No selection;\nuse left mouse button.",$tpbframe);
	}});
}

# view document selected in listbox
sub viewslc {
    my($slc,$parframe)=@@_;
    my $viewer;
    my $itype=-1;
    unless (defined $slc) {
	&popmsg(2,"No selection was made.",$parframe);
	return;
    }
    chomp $slc;
    my @@dummy=split('\.',$slc);
  DOC_FORMAT: { # determine document type
      ($dummy[-1] =~ /dvi/) && do { $viewer=$dvi_viewer; last DOC_FORMAT; };
      ($dummy[-1] =~ /ps/) && do { $viewer=$ps_viewer; last DOC_FORMAT; };
      ($dummy[-1] =~ /pdf/) && do { $viewer=$pdf_viewer; last DOC_FORMAT; };
      ($dummy[-1] =~ /txt/ || $dummy[-1] =~ /faq$/) && do {
	  $viewer=$txt_viewer; last DOC_FORMAT;
      };
      ($dummy[-1] =~ /README/i) && do {
	  $viewer=$txt_viewer; last DOC_FORMAT;
      };
      ($dummy[-1] =~ /htm/) && do { $viewer=$html_viewer; last DOC_FORMAT; };
      &popmsg(2,"$dummy[-1]: not a known document format",$parframe);
      return;
  };
    if ($viewer eq "") {
	&popmsg(2,"$dummy[-1]: no viewer available/specified for this format",
		$parframe);
	return;
    }
# build complete path and start viewer if file exists
    my $slcdoc=join("/",($texdocpath,$slc));
    $slcdoc=&finddoc($slcdoc,$slc,$parframe);
    if ($slcdoc ne "") { # change to doc directory in case there are pictures
	my $docpath=substr($slcdoc,0,(rindex($slcdoc,'/',(length $slcdoc))));
	chdir ($docpath);
	if ($quiet == 0) { # show messages
	    system("$viewer $slcdoc");
	} else { # viewer messages written to /dev/null instead of terminal
	    my $dump;
	    open (VIEWQ,"$viewer $slcdoc |");
	    while ($dump=<VIEWQ>) { print NULL $dump; }
	    close(VIEWQ);
	}
    }
}

# print document selected in listbox
sub prtslc {
    my($slc,$parframe)=@@_;
    my $pstmpfile=join("",("/tmp/texdoc_",$$,".ps"));
    push @@tmpfiles,$pstmpfile;
    my $status;
    chomp $slc;
    unless (defined $slc) {
	&popmsg(2,"No selection was made.",$parframe);
	return;
    }
    if ($print_cmd eq "") {
	&popmsg(2,"No printer specified.",$parframe);
	return;
    }
# build complete path and check existence of file
    my @@dummy=split('\.',$slc);
    my $slcdoc=join("/",($texdocpath,$slc));
    $slcdoc=&finddoc($slcdoc,$slc,$parframe);
    if ($slcdoc eq "") { return; }
#   change to doc directory in case there are pictures
    my $docpath=substr($slcdoc,0,(rindex($slcdoc,'/',(length $slcdoc))));
    chdir ($docpath);
  DOC_FORMAT: { # determine document type
#     convert dvi files to ps before printing
      ($dummy[-1] =~ /dvi/) && do {
	  if ($dvips_conv eq "") {
	      &popmsg(2,"No converter available for dvi->ps conversion.",
		      $parframe);
	      return;
	  }
	  &popmsg(0,"Converting dvi to ps for printing and sending file to print...",$parframe);
	  $status=system("$dvips_conv $dvips_opts $slcdoc -o $pstmpfile");
	  if ($status != 0) {
	      &popmsg(2,"Error: Conversion dvi->ps failed!",$parframe);
	  }
	  last DOC_FORMAT;
      };
#     PostScript is printed directly
      ($dummy[-1] =~ /ps/) && do {
	  &popmsg(0,"Sending file to $print_cmd...",$parframe);
	  $pstmpfile=$slcdoc;
	  last DOC_FORMAT;
      };
#     convert pdf files to ps before printing
      ($dummy[-1] =~ /pdf/) && do {
	  if ($pdfps_conv eq "") {
	      &popmsg(2,"No converter available for pdf->ps conversion.",
		      $parframe);
	      return;
	  }
	  &popmsg(0,"Converting pdf to ps for printing and sending file to print...",$parframe);
	  system("$pdfps_conv $pdfps_opts $slcdoc $pstmpfile");
	  last DOC_FORMAT;
      };
#     convert html files to ps before printing
      ($dummy[-1] =~ /htm/) && do {
	  if ($htmlps_conv eq "") {
	      &popmsg(2,"No converter available for html->ps conversion.",
		      $parframe);
	      return;
	  }
	  &popmsg(0,"Converting html to ps for printing and sending file to print...",$parframe);
	  $htmlps_redir=($htmlps_redir == 1) ? ">" :"";
	  system("$htmlps_conv $slcdoc $htmlps_redir $pstmpfile");
	  last DOC_FORMAT;
      };
#     convert txt files to ps before printing
      ($dummy[-1] =~ /txt/ || $dummy[-1] =~ /faq$/
       || $dummy[-1] =~ /README/i) && do {
	  if ($txtps_conv eq "") {
	      &popmsg(2,"No converter available for txt->ps conversion.",
		      $parframe);
	      return;
	  }
	  &popmsg(0,"Converting txt to ps for printing and sending file to print...",$parframe);
	  $txtps_redir=($txtps_redir == 1) ? ">" :"";
	  system("$txtps_conv $slcdoc $txtps_redir $pstmpfile");
	  last DOC_FORMAT;
      };
      &popmsg(2,"$dummy[-1]: cannot print document format",$parframe);
      return;
  };
    system("$print_cmd $print_opts $pstmpfile");
}

# test existence and search a documentation which is not in specified place
sub finddoc {
    my($slcdoc,$slc,$parframe)=@@_;
    my ($dummy,@@dummy);
    unless (-e $slcdoc) {
	my $status=-1;
	@@dummy=split("/",$slc);
	my $rawname=pop @@dummy;
#       Debian compresses larger documentations: see if it is compressed
	foreach ("gz","bz2") {
	    $dummy=join ('.',($slcdoc,$_));
	    if (-e $dummy) {
		$slcdoc="/tmp/texdoc$$\_$rawname";
		push @@tmpfiles,$slcdoc;
		my $dcmp=($_ eq "gz") ? "gzip" : "bzip2";
		$status=system("$dcmp -cd $dummy > $slcdoc");
		if ($status != 0) {
		    &popmsg(2,"$dcmp: Couldn't decompress file, cancelling.",
			    $parframe);
		}
		last;
	    }
	}
	if ($status != 0) {
#           try to find it elsewhere with find
	    &popmsg(1,"Requested documentation not found in specified place;
check $database.\nLooking for $rawname elsewhere\nin $texdocpath...",
		    $parframe);
	    my $findres="/tmp/texdoc_srch$$";
	    system("find $texdocpath -name $rawname >$findres");
	    open(TMPSRCH,"$findres");
	    $slcdoc=<TMPSRCH>;
	    unless (defined $slcdoc) { # nothing found; cancel
		&popmsg(2,"$rawname not found, cancelling.",$parframe);
		$slcdoc="";
	    }
	    close(TMPSRCH);
	    unlink $findres;
	}
    }
    return $slcdoc;
}

# make search entry widget
sub mksrch {
# get the search string
    my $srchentry=$cmdframe->Entry(-cursor=>'xterm',
				   -width=>20,
				   -takefocus=>1)->pack(-side=>'left');
    $srchentry->focus;
    $srchentry->bind('<Return>'=>[\&srchstr, $srchentry]);
# key bindings
    $srchentry->bind('<Control-c>'=>sub{destroy $srchentry});
}

# search a string in @@packname, @@topic and @@keywords
sub srchstr {
    my ($srchentry)=@@_;
    my ($i,$j,$string);
    my (@@results,@@reslist);
    $string=$srchentry->get();
# search
    for ($i=0; $i<$ncat; ++$i) {
	for ($j=0; $j<$maxind[$i]; ++$j) {
	  SRCH: {
	      ($topic[$i][$j] =~ /$string/i) && do {
		  push @@results,($i,$j);
		  last SRCH;
	      };
	      (defined $keywords[$i][$j]) && do {
		  if ($keywords[$i][$j] =~ /$string/i) {
		      push @@results,($i,$j);
		  }
		  last SRCH;
	      };
	      ($packname[$i][$j] =~ /$string/i) && do {
		  push @@results,($i,$j);
		  last SRCH;
	      };
	  };
	}
    }
# destroy entry widget and show results
    destroy $srchentry;
    if (scalar @@results == 0) {
	&popmsg(0,"Search for $string: no matches found.",$cmdframe);
    } else {
#       cancel multiple entries
	my ($omit,$pack1,$pack2);
	@@reslist=($results[0],$results[1]);
	for ($i=0; $i<$#results; $i+=2) {
	    $omit=0;
	    $pack1=$packname[$results[$i]][$results[$i+1]];
	    for ($j=0; $j<$#reslist; $j+=2) {
		$pack2=$packname[$reslist[$j]][$reslist[$j+1]];
		if ($pack1 eq $pack2) { $omit=1; last; }
	    }
	    if ($omit == 0) { push @@reslist,($results[$i],$results[$i+1]); }
	}
	&tpslct(-1,@@reslist);
    }
}

# pop up a note or an error or warning message toplevel window
sub popmsg {
    my($level,$msg,$parframe)=@@_;
    my $degree;
  LEVEL: {
      ($level == 0) && do { $degree="Note"; last LEVEL; };
      ($level == 1) && do { $degree="Warning"; last LEVEL; };
      ($level == 2) && do { $degree="Error"; last LEVEL; };
  };
    my $msgwin=$parframe->Toplevel(-title=>$degree);
    my $lbl=$msgwin->Label(-text=>uc($degree))->pack(-side=>'top', -fill=>'x');
#   get size of message text
    my @@dummy=split("\n",$msg);
    my $nline=scalar @@dummy;
    my $msgwidth=0;
    my $lline;
    foreach (@@dummy) {
	$lline=length $_;
	if ($lline > $msgwidth) { $msgwidth=$lline; }
    }
    my $message=$msgwin->Text(-relief=>'flat',
			      -font=>$deffont[3],
			      -height=>$nline,
			      -width=>$msgwidth)->pack(-side=>'top');
    $msgwin->Button(-text=>'Close',
		    -command=>sub{destroy $msgwin})->pack(-side=>'bottom',
							  -fill=>'x');
    $message->insert('end',$msg);
    $message->configure(-state=>'disabled');
    $msgwin->bind('<Control-c>'=>sub{destroy $msgwin});
}

# show/change settings (don't show this to an expert :-/ )
sub settings {
    my ($quiet_tmp,$dvi_viewer_tmp,$dvips_conv_tmp,$dvips_opts_tmp,
	$ps_viewer_tmp,$pdf_viewer_tmp,$pdfps_conv_tmp,$pdfps_opts_tmp,
	$html_viewer_tmp,$htmlps_conv_tmp,$htmlps_redir_tmp,
	$txt_viewer_tmp,$txtps_conv_tmp,$txtps_redir_tmp,
	$print_cmd_tmp,$print_opts_tmp)=
	    ($quiet,$dvi_viewer,$dvips_conv,$dvips_opts,$ps_viewer,
	     $pdf_viewer,$pdfps_conv,$pdfps_opts,$html_viewer,
	     $htmlps_conv,$htmlps_redir,$txt_viewer,
	     $txtps_conv,$txtps_redir,$print_cmd,$print_opts);
    my $setmenu=$main->Toplevel(-title=>'Viewer/printer settings');
# documentation path
    my $datlabel;
    if ($database =~ /-local\.dat$/) {
        $datlabel="Using local database file";
    } else {
	@@dummy=split("",(substr($database,(index($database,'-',0))+1,-4)));
	my $texmfver=join('.',@@dummy);
	$datlabel="Using database file for v.$texmfver";
    }
    my $docframe=$setmenu->Frame(-relief=>'groove',
				 -borderwidth=>2)->pack(-side=>'top',
							-fill=>'x',
							-ipady=>10,
							-expand=>1);
    $docframe->Label(-text=>"Documentation root path: $texdocpath\n$datlabel")
	->pack(-side=>'top',
	       -anchor=>'w',
	       -ipady=>2,
	       -fill=>'x',
	       -expand=>1);

# stderr treatment
    my $errframe=$setmenu->Frame(-label=>'Viewer error output',
				 -relief=>'groove',
				 -borderwidth=>2)->pack(-side=>'top',
							-fill=>'x',
							-ipady=>10,
							-expand=>1);
    my $errsub=$errframe->Frame()->pack(-side=>'top',
					-anchor=>'w',
					-ipady=>6);
    my $errlabel=$errsub->Label(-text=>'Suppress error messages')
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $errcbut=$errsub->
	Checkbutton(-variable=>\$quiet_tmp)->pack(-side=>'left',
						  -anchor=>'sw');
# DVI
    my $dviframe=$setmenu->Frame(-label=>'DVI',
				 -relief=>'groove',
				 -borderwidth=>2)->pack(-side=>'top',
							-fill=>'x',
							-ipady=>6,
							-expand=>1);
    my $dvisub1=$dviframe->Frame()->pack(-side=>'top',
					 -anchor=>'w');
    my $dvisub2=$dviframe->Frame()->pack(-side=>'top',
					 -anchor=>'w',
					 -ipady=>6);
    my $dvivlabel=$dvisub1->Label(-text=>'Viewer')->pack(-side=>'left');
    my $dviventry=$dvisub1->Entry(-textvariable=>\$dvi_viewer_tmp)
	->pack(-side=>'left');
    my $dviclabel=$dvisub2->Label(-text=>'DVI->PS converter')
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $dvicentry=$dvisub2->Entry(-textvariable=>\$dvips_conv_tmp)
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $dviolabel=$dvisub2->Label(-text=>'Options')->pack(-side=>'left',
							  -anchor=>'sw');
    my $dvioentry=$dvisub2->Entry(-textvariable=>\$dvips_opts_tmp)
	->pack(-side=>'left',
	       -anchor=>'sw');
# PostScript
    my $psframe=$setmenu->Frame(-label=>'PostScript',
				-relief=>'groove',
				-borderwidth=>2)->pack(-side=>'top',
						       -fill=>'x',
						       -ipady=>10,
						       -expand=>1);
    my $psvlabel=$psframe->Label(-text=>'Viewer')->pack(-side=>'left',
							-anchor=>'w');
    my $psventry=$psframe->Entry(-textvariable=>\$ps_viewer_tmp)
	->pack(-side=>'left');
# PDF
    my $pdfframe=$setmenu->Frame(-label=>'PDF',
				 -relief=>'groove',
				 -borderwidth=>2)->pack(-side=>'top',
							-fill=>'x',
							-ipady=>6,
							-expand=>1);
    my $pdfsub1=$pdfframe->Frame()->pack(-side=>'top',
					 -anchor=>'w');
    my $pdfsub2=$pdfframe->Frame()->pack(-side=>'top',
					 -anchor=>'w',
					 -ipady=>6);
    my $pdfvlabel=$pdfsub1->Label(-text=>'Viewer')->pack(-side=>'left',
							 -anchor=>'w');
    my $pdfventry=$pdfsub1->Entry(-textvariable=>\$pdf_viewer_tmp)
	->pack(-side=>'left');
    my $pdfclabel=$pdfsub2->Label(-text=>'PDF->PS converter')
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $pdfcentry=$pdfsub2->Entry(-textvariable=>\$pdfps_conv_tmp)
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $pdfolabel=$pdfsub2->Label(-text=>'Options')->pack(-side=>'left',
							  -anchor=>'sw');
    my $pdfoentry=$pdfsub2->Entry(-textvariable=>\$pdfps_opts_tmp)
	->pack(-side=>'left',
	       -anchor=>'sw');
# HTML
    my $htmlframe=$setmenu->Frame(-label=>'HTML',
				  -relief=>'groove',
				  -borderwidth=>2)->pack(-side=>'top',
							 -fill=>'x',
							 -ipady=>6,
							 -expand=>1);
    my $htmlsub1=$htmlframe->Frame()->pack(-side=>'top',
					   -anchor=>'w');
    my $htmlsub2=$htmlframe->Frame()->pack(-side=>'top',
					   -anchor=>'w',
					   -ipady=>6);
    my $htmlvlabel=$htmlsub1->Label(-text=>'Viewer')->pack(-side=>'left',
							   -anchor=>'w');
    my $htmlventry=$htmlsub1->Entry(-textvariable=>\$html_viewer_tmp)
	->pack(-side=>'left');
    my $htmlclabel=$htmlsub2->Label(-text=>'HTML->PS converter')
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $htmlcentry=$htmlsub2->Entry(-textvariable=>\$htmlps_conv_tmp)
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $htmlrlabel=$htmlsub2->Label(-text=>'Output redirect needed')
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $htmlrcbut=$htmlsub2->
	Checkbutton(-variable=>\$htmlps_redir_tmp)->pack(-side=>'left',
							 -anchor=>'sw');
# plain text
    my $txtframe=$setmenu->Frame(-label=>'Plain text',
				 -relief=>'groove',
				 -borderwidth=>2)->pack(-side=>'top',
							-fill=>'x',
							-ipady=>6,
							-expand=>1);
    my $txtsub1=$txtframe->Frame()->pack(-side=>'top',
					 -anchor=>'w');
    my $txtsub2=$txtframe->Frame()->pack(-side=>'top',
					 -anchor=>'w',
					 -ipady=>6);
    my $txtvlabel=$txtsub1->Label(-text=>'Viewer')->pack(-side=>'left',
							 -anchor=>'w');
    my $txtventry=$txtsub1->Entry(-textvariable=>\$txt_viewer_tmp)
	->pack(-side=>'left');
    my $txtclabel=$txtsub2->Label(-text=>'Text->PS converter')
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $txtcentry=$txtsub2->Entry(-textvariable=>\$txtps_conv_tmp)
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $txtrlabel=$txtsub2->Label(-text=>'Output redirect needed')
	->pack(-side=>'left',
	       -anchor=>'sw');
    my $txtrcbut=$txtsub2->
	Checkbutton(-variable=>\$txtps_redir_tmp)->pack(-side=>'left',
							-anchor=>'sw');
# printer
    my $prtframe=$setmenu->Frame(-label=>'Printer',
				 -relief=>'groove',
				 -borderwidth=>2)->pack(-side=>'top',
							-fill=>'x',
							-ipady=>10,
							-expand=>1);
    my $prtclabel=$prtframe->Label(-text=>'Command')->pack(-side=>'left',
							   -anchor=>'w');
    my $prtcentry=$prtframe->Entry(-textvariable=>\$print_cmd_tmp)
	->pack(-side=>'left');
    my $prtolabel=$prtframe->Label(-text=>'Options')->pack(-side=>'left',
							   -anchor=>'w');
    my $prtoentry=$prtframe->Entry(-textvariable=>\$print_opts_tmp)
	->pack(-side=>'left');
# buttons and key bindings
    my $setbfr=$setmenu->Frame()->pack(-side=>'bottom');
    $setbfr->Button(-text=>'OK',
		    -command=>sub{ if ($quiet_tmp == 1 && $quiet == 0) {
                			open(NULL,">/dev/null");
		                   } elsif ($quiet_tmp == 0 && $quiet == 1) {
                			close(NULL);
		                   }
			           ($quiet,$dvi_viewer,$dvips_conv,
				   $dvips_opts,$ps_viewer,$pdf_viewer,
				   $pdfps_conv,$pdfps_opts,$html_viewer,
				   $htmlps_conv,$htmlps_redir,
				   $txt_viewer,$txtps_conv,$txtps_redir,
				   $print_cmd,$print_opts)=
				       ($quiet_tmp,$dvi_viewer_tmp,
					$dvips_conv_tmp,$dvips_opts_tmp,
					$ps_viewer_tmp,$pdf_viewer_tmp,
					$pdfps_conv_tmp,$pdfps_opts_tmp,
					$html_viewer_tmp,$htmlps_conv_tmp,
					$htmlps_redir_tmp,$txt_viewer_tmp,
					$txtps_conv_tmp,$txtps_redir_tmp,
					$print_cmd_tmp,$print_opts_tmp);
				  destroy $setmenu},
		    -width=>6)->pack(-side=>'left',
				    -padx=>10,
				    -pady=>10);
    $setmenu->bind('<Return>'=>sub{ if ($quiet_tmp == 1 && $quiet == 0) {
                			open(NULL,">/dev/null");
		                    } elsif ($quiet_tmp == 0 && $quiet == 1) {
                		 	close(NULL);
		                    }
			            ($quiet,$dvi_viewer,$dvips_conv,
				    $dvips_opts,$ps_viewer,$pdf_viewer,
				    $pdfps_conv,$pdfps_opts,$html_viewer,
				    $htmlps_conv,$htmlps_redir,
				    $txt_viewer,$txtps_conv,$txtps_redir,
				    $print_cmd,$print_opts)=
					($quiet_tmp,$dvi_viewer_tmp,
					 $dvips_conv_tmp,$dvips_opts_tmp,
					 $ps_viewer_tmp,$pdf_viewer_tmp,
					 $pdfps_conv_tmp,$pdfps_opts_tmp,
					 $html_viewer_tmp,$htmlps_conv_tmp,
					 $htmlps_redir_tmp,$txt_viewer_tmp,
					 $txtps_conv_tmp,$txtps_redir_tmp,
					 $print_cmd_tmp,$print_opts_tmp);
				   destroy $setmenu});
    $setbfr->Button(-text=>'Cancel',
		    -command=>sub{destroy $setmenu})->pack(-side=>'right');
    $setmenu->bind('<Control-c>'=>sub{destroy $setmenu});
}

# help window (toplevel)
sub helptext {
    my $help=$main->Toplevel(-title=>'Help');
    $help->Label(-text=>"texdoctk
TeX documentation browser
v.0.3 (Mar 11, 2000)")->pack(-side=>'top',
			     -ipady=>10,
			     -anchor=>'s');
    my $helpbody=$help->Scrolled("Text",
				 -relief=>'flat',
				 -font=>$deffont[3],
				 -height=>20,
				 -width=>60,
				 -scrollbars=>"e")->pack(-side=>'top');
    while (<DATA>) {
	$_ =~ s/\$sysrc/$sysrc/;
	$helpbody->insert('end',$_);
    }
    $helpbody->configure(-state=>'disabled');
    $help->Button(-text=>'Close',
		  -command=>sub{destroy $help})->pack(-side=>'bottom',
                                                      -fill=>'x');
    $help->bind('<Control-c>'=>sub{destroy $help});
}

# read config file; personal settings override the default settings
sub readrc {
    my($rcfile)=@@_;
    my ($var,$val);
    my $pathflag=0;
#   read defaults resp. personal settings
    open (RC,"$rcfile");
    while ($line = <RC>) {
	if ($line =~ /^($|#)/) { next; }
	chomp $line;
	($var,$val)=split("=",$line);
	if ($var =~ /texdocpath/i) {
	    if (length $val > 0) {
		$pathflag=1;
		eval(join("",("\$",lc($var),"=\$val")));
	    }
	} else {
	    eval(join("",("\$",lc($var),"=\$val")));
	}
    }
    close(RC);
#   find texmf/doc
    if ($rcfile eq $sysrc || $pathflag == 1) {
	$texmfmain=`kpsewhich --expand-path='\$TEXMFMAIN'`;
	chomp $texmfmain;
	$texdocpath=join('/',($texmfmain,$texdocpath));
    }
#   converter stuff and such
    $quiet=($quiet =~ /y/i || $quiet eq "1") ? 1 : 0;
    $htmlps_redir=($htmlps_redir =~ /(y|1)/i) ? 1 : 0;
    $txtps_redir=($txtps_redir =~ /(y|1)/i) ? 1 : 0;
}

# clean up and exit
sub clean_exit {
    foreach (@@tmpfiles) { if (-e $_) { unlink $_; } }
    if ($quiet == 1) { close(NULL); }
    exit;
}

__END__
Many TeX programmers provide more or less detailed manuals for
their programs or packages. They are usually available as .dvi,
.ps, .pdf, .html or plain text files and can be accessed with this
browser, which is simply an interface to find a documentation
more easily. It starts the respective viewer for reading the
selected documentation making use of a database file which
contains the path entries according to the teTeX v.1.0.x texmf/doc
structure.
The documentations are grouped in several categories shown in the
main window; pressing one of its buttons lists all documentations
belonging to this topic.
The topic window lets you select one documentation file, view or
send it to the default printer. By right-clicking on the selected
item you get the complete path of the file.
The search button of the main window allows you to search the
database for a string; it does not search file names. Enter the
string and hit <Return> to start the search or <Control-c> to
cancel.
Defaults for the documentation root directory, the viewers, the
converters, certain options and the printer are set in the global
configuration file $sysrc.
However, each user can put a copy of it as .texdocrc into his home
directory to modify them according to his needs. Additionally, they
can be changed temporarily with the settings menu.

The following key shortcuts are defined for use with the browser:
  <Ctrl-q>	Quit browser (main window)
  <Ctrl-s>	Search a keyword in database (case insensitive)
  <Ctrl-c>	Cancel/close subwindow or search entry widget
  <Ctrl-v>	View selected document (topic windows)
  <Ctrl-p>	Print selected document (topic windows)
  <Ctrl-t>	Open settings menu
  <Ctrl-h>	Open this help
  <Return>	Equivalent to button press;
		OK in selection menu and search
  <Tab>		Next/previous widget
There also is a command line option -q to enable suppression of
viewer messages sent to stderr, in case this was not set in a
configuration file.

Comments and suggestions to:
Thomas Ruedas
ruedas@@geophysik.uni-frankfurt.de
@


1.1.1.1
log
@sun2.dante.de download 2/10/2000 of TeXLive (Omega 1.11)
@
text
@@
