#! /bin/sh
: use /bin/sh
# put the : line first on System V

# $Id: lq.sh,v 1.30 95/10/02 23:43:27 lee Exp $

# PATH should include mawk and tput.
# If you don't have mawk, it's a much faster version of awk --
# pick it up!  If you don't have tput, there are public domain
# versions around, or you can do
#
# tput()
# {
# }
#
# to disable the use of bold, underscore, etc.
#
#
# Finally, "rs" is included in the lq-text distribution in the
# src/tools directory.
#

USERPATH="$PATH"
PATH=/usr/local/bin:/usr/5bin:$USERPATH:/home/sqrex/lee/scripts
# but don't export it...

RS=rs
export RS

N=; C='\c'; if test x"`echo -n hello`" = x"hello" ; then N='-n'; C=; fi
export N C
# Single Quote
Q="'"

COLS=`tput cols 2>/dev/null`
if [ x"$COLS" = x"" ]
then
    COLS=80
fi

LEFT=`expr '(' $COLS - 5 ')' / 2`
RIGHT=$LEFT

if test -z "$CMDNAME"
then
    CMDNAME="`basename $0`"
else
    CMDNAME="${CMDNAME}: `basename $0`"
fi
export CMDNAME
PS1="[${CMDNAME}] $PS1" 
PS2="[${CMDNAME}] $PS2" 
export PS1 PS2

KWICMODE=adorned
HELP_PAGER=
PAGER="${PAGER-more}"

LESSPROG="${PAGER-more}"
LQTEXTDIR="${LQTEXTDIR-$HOME/LQTEXTDIR}"
export LQTEXTDIR

if [ x"$1" = x"-d" ]
then
    LQTEXTDIR="$2"
    shift; shift
fi

SGML_CHAR=""
if [ x"$1" = x"-sgml" ]
then
    SGML_CLEVER="-c -C ${SGML_CHAR}"
    SGML_TAG_DESC="as ${SGML_CHAR} characters"
    ENTLIST="-E ${LQTEXTDIR}/entitylist"
    shift
else
    SGML_CLEVER=
    SGML_TAG_DESC="as ASCII"
    ENTLIST=
fi

if [ x"$1" = x"-d" ]
then
    LQTEXTDIR="$2"
    shift; shift
fi

export SGML_TAG_DESC SGML_CLEVER ENTLIST

echo "Using database in $LQTEXTDIR..."

if test -f "${LQTEXTDIR}/update-in-progress"
then
    echo $N "${CMDNAME}: database is locked by process $C" 1>&2
    cat "${LQTEXTDIR}/update-in-progress" 1>&2
    if test -s "${LQTEXTDIR}/update-info"
    then
	echo "${CMDNAME}: further information:" 1>&2
	sed -e "s^${CMDNAME}: *** " "${LQTEXTDIR}/update-info" 1>&2
    fi
    cd "$LQTEXTDIR" || exit 1
    /bin/ls -l update-in-progress 1>&2
    echo "${CMDNAME}: please try again later." 1>&2
    exit 1
fi

# if we have tput, use it; if not, forget it:
if (tput rmso > /dev/null) 2> /dev/null
then
    # Yes, tput works OK
    smso="`tput smso`"; rmso="`tput rmso`"
    smul="`tput smul`"; rmul="`tput rmul`"
    bold="`tput bold`"; rmall="`tput sgr0`"
    rmbold="${rmall}"
    if [ x"${smul}" = x"" ]
    then
	smul="${smso}"; rmul="${rmso}"
    elif [ x"${smso}" = x"" ]
    then
	smso="${smul}"; rmso="${rmul}"
    fi
    if [ x"$bold}" = x"" ]
    then
	VBAR="${smso}[34m|${rmso}"
	bold="${smul}"
	rmbold="${rmul}"
	if [ x"${rmall}" = x"" ]
	then
	    rmall="${rmso}"
	fi
    else
	VBAR="${bold}[34m|${rmbold}"
    fi
else
    smso=""; rmso=""
    smul="_"; rmul="_"
    bold=""; rmbold=""
fi
lqtext="${smul}lq-text${rmul}"

set_traps()
{
    trap "/bin/rm -f $tmp;echo ${rmso}${rmul}${rmall}Quit.; exit" 0 1 15
    trap "/bin/rm -f $tmp;echo ${rmso}${rmul}${rmall}interrupted, bye;exit" 2 3
}

unset_traps()
{
    trap "/bin/rm -f $tmp;echo ${rmso}${rmul}${rmall}Quit.; exit" 0 1 15
    trap : 2 3
}

unset_all_traps()
{
    trap : 0 1 2 3 15
}

set_traps

quit=no


prog=lqkwic
export prog
PRECISION=;
PRECISION_DESC="heuristic matching (the default)"
RANK="all";
RANK_TYPE_DESC="find documents containing ${smul}all${rmul} of the phrases"
PROMPT_DFLT="[31m${bold}>${rmbold} "
PROMPT="${PROMPT_DFLT}"
export PROMPT
MAXHITS="200"
export MAXHITS
sortoptions=
sort=
sortDescription="@none/list files in the order in which they were indexed"

print_info()
{
    if test ! x"$Redirected" = x""
    then
	# don't print stuff in batch mode
	return
    fi

    if test x"$1" != x""
    then
	echo $N "$@$C"
    else
	cat
    fi |
    eval sed -e "'s/^[ 	]*|/${VBAR}/'" \
	-e "'/^[ 	]*#/d'" \
	-e "'s/@</${smul}/g'" \
	-e "'s/@>/${rmul}/g'" \
	-e "'s/@\[/${bold}/g'" \
	-e "'s/@\]/${rmbold}/g'" 
}

main_help()
{
    print_info "\
    | Type phrases one per line, for example
    | @<happiness and good fortune@>
    | and, when you are done, press @<return@> twice.  ${CMDNAME} will then
    | ${RANK_TYPE_DESC}.
    | There are various options you can set;
    | type @<:set@> to see them.
    | Once you've seen the index, you can use the following commands:
    | :view, :index, :files, :help, :less, :page, :prefix, :grep, :nroff
    | 
"
}

short_index_help()
{
    print_info "\
    | Use @<:index@> to see the index again, @<:help@> for other options.
"
}

command_help()
{
    print_info "\
    | @[Options@]
    |    @[-sgml@] turns on special treatment of SGML files
    |    other options are taken as input phrases or commands.
    |
    | @[Commands@]
    |
    | @[:help@]
    |    Shows you this message.
    | @[:view@] [@<n@>,@<n1-n2@>,@<n@>...]
    |    Use @<:view@> to see the text surrounding matches.
    |    The number @<n@> is from the left-hand edge of the index;
    |    @[:set maxhits@] explains @<range@>s in more detail.
    | @[:page@] [@<n@>,@<n1-n2@>,@<n@>...]
    |    Uses ${PAGER} (which you can set
    |    in the \$PAGER Unix environment variable) to show the files matched.
    | @[:less@] [@<n@>,@<n1-n2@>,@<n@>...]
    |    The same as @[:page@] except that it starts on the line number
    |    containing the match, firing up the pager separately on
    |    each file.
    | @[:index@] [@<n@>,@<n1-n2@>,@<n@>...]
    |    This shows the indexfor the phrases you've typed.
    | @[:files@] [@<n@>,@<n1-n2@>,@<n@>...]
    |    This simply lists all of the files that were matched,
    |    in ranked order.
    | @[:prefix@] @<prefix-string@>
    |    Shows all of the words in the database that begin with that prefix,
    |    together with the number of times they occur.
    | @[:grep@] @<egrep-pattern@>
    |    Shows all of the words in the database that match that egrep pattern,
    |    together with the number of times they occur (not the number of files
    |    in which they appear, though).
    | @[:sort@] @<@none@>|@<@path@>|@<@title@>|<@words-before@>|...
    |    This makes the results come out in a different order.
    | @[:nroff@]
    |    runs @<ts@> on the query results.
    | @[:set@] @<option@> ...
    |    Type @<:set@> to see more information about setting options.
    | @[:quit@]
    |    exit the program.
    | @[:shell@] [@<command@> ...]
    |    Use ${SHELL-sh} to run commands.  Same as @[!@]@<command...@>.
    |
    | Commands that take a list of matches (@<n@>,@<n1-n2@>,@<n@>...)
    | only work when you have generated a list of matches.  If you don't give
    | any arguments, you get the whole list.
    |
"
}

make_match_list()
{
    # $1 is output file
    tmp="$1"
    shift

    if [ x"$1" = x"" ]
    then
	echo "p" >> $tmp
    elif expr "$1" : all > /dev/null
    then
	echo "p" >> $tmp
    else
	echo "$@" | tr ', ' '\012\012' | mawk -F- '
	    (NF == 2) {
		if ($2 < $1) {
		    tmp = $1
		    $1 = $2
		    $2 = tmp
		}
		if ($1 < 1) $1 = 1
		printf "%d,%dp\n", $1, $2
		next
	    }
	    {
		printf "%dp\n", $1
	    }
	' >> $tmp
    fi
}

handle_shell()
{
    shift
    unset_all_traps
    if test -z "$1"
    then
	${SHELL-/bin/sh}
    else
	${SHELL-/bin/sh} -c "$*"
    fi
    print_info "\
    |
    | (${CMDNAME} -- continue)
"
    set_traps
}

# cf. handle_page below...
handle_less()
{
    # handle_less :less n m [...]

    shift

    unset_traps

    case "$*" in
    *[a-zA-Z0-9,-]*)
	;;
    *)
	set all
	;;
    esac

    echo Use control-C q to stop paging...
    eval lqrank ${PRECISION} -r ${RANK} $Phrases |
	lqkwic -S '' -s '${StartByte} ${FileName}${NL}' -o "$*" |
	lqbyteline -f - | {
	    while read line file
	    do
		${LESSPROG} +$line "$file" < /dev/tty
	    done
	}


    set_traps

    short_index_help
}

handle_page()
{
    # view :view n m [...]
    shift

    # now append the sed script:

    case "$*" in
    *[a-zA-Z0-9,-]*)
	;;
    *)
	set all
	;;
    esac

    unset_traps

    # The following line fires up the pager once for each
    # group of files:
    # eval lqrank ${PRECISION} -r ${RANK} $Phrases |
	# lqkwic -o "$*" -S '' -s '${FileName}${NL}' |
	# xargs ${PAGER}

    # the following fires up the pager on all the files.
    # Slower to start, and also may generate an arg list too long
    # error message, in which case go back to the xargs version above.
    PATH="$USERPATH" $PAGER `
	eval lqrank ${PRECISION} -r ${RANK} $Phrases $sort |
	lqkwic -o "$*" -S '' -s '${FileName}${NL}' `

    set_traps

    short_index_help
}

handle_view()
{
    # view :view n m [...]
    shift

    tmp=/tmp/lq.$$
    rm -f $tmp
    make_match_list $tmp "$@"

    unset_traps

    eval lqrank ${PRECISION} -r ${RANK} $Phrases |
	sed -n -f $tmp | lqshow -f -
    set_traps
    rm -f $tmp
    echo
    short_index_help
}

handle_sort()
{
    shift
    case "$1" in
    ""|help|-help)

    print_info "\
    | @[:sort@] @<-key variableName@> [@<options...@>]
    | specifies how results will be sorted.
    | The variableNames are the same as those listed by @<lqkwic -L@>, and
    | you can use the same ! and : syntax described there. print them with:
    | @[:sort@] longhelp
    | 
    | @[Options@]
    |     -lqkwic @<stuff@>    pass @<stuff@> on as an argument to lqkwic;
    |     -d, -f, -i, -n, -r and -u are passed to sort(1).
    |
    | @[Examples@]
    | To sort the output by document title:
    |     @[:sort -key DocumentTitle@]
    | The default (i.e. unsorted)
    |     @[:sort @none@]
    | which is in effect the same as:
    |     @[:sort -key FileNumber -key MatchNumber@]
    | You can use @[:sort longhelp@] for a list of possible sort keys.
    | The sorts beginning with an @-sign are predefined:
    |     @[:sort list@] shows the full list of pre-defined sorts.
    | The current sort is:
    |     ${sortDescription}
"
	;;
    list)
	print_info "\
    | The following options to @[:sort@] are predefined:
    | @[@path@]          sorts the results by the complete path to the file
    | containing each match, so that all matches in the same file will
    | collate together; this is @[:sort@] -key FileName
    | @[@title@]         sorts the results by the document title.
    | @[@index@]         sorts the results in the order in which the files
    | were added to the index (see @<lqaddfile@>(1))
    | @[@file@]          sorts the results by the last component of the
    | path name, then the next-but-last, and so on: /xyz/boy would come
    | before /abc/girl, as @<boy@> sorts before @<girl@>
    | @[@words-before@]  sorts the results by the word immediately to the
    | left of the matched text, then to the word to the left of that, and
    | so on.
"
	;;
    longhelp|@longhelp)
	lqkwic -L
	;;
    @path)
	sortoptions="-key FileName"
	sortDescription="@path/by complete path to each file"
	;;
    @title)
	sortoptions="-key DocTitle"
	sortDescription="@title/by document title"
	;;
    @index)
	sortoptions="-n -key FID"
	sortDescription="@index/in the order files were added to the index"
	;;
    @file)
	# this is
	sortoptions="-f -d -key !!!FileName:DeleteAfterDot:!SplitAtPunctuation"
	sortDescription="@file/by filename then path, ignoring suffix"
	;;
    @words-before)
	sortoptions="-key -f -d !!!TextBefore:SplitAtPunctuation -key MatchedText"
	sortDescription="@words-before/by the words to the left of the match"
	;;
    @none|none)
	sortoptions="-key FileName"
	sortDescription="@none/list files in the order in which they were indexed"
	;;
    *)
	sortoptions="$*"
	sortDescription="$*"
	;;
    esac
    if test x"$sortoptions" = x""
    then
	sort=
    else
	sort="| lqsort \$sortoptions"
    fi
}

show_index()
{
    shift

    if test x"$KWICMODE" = x"adorned"
    then
	PerDocument="'${smul}"'${DocTitle}'"${rmul}"' == ${DocName}${NL}'"'"
	PerMatch="'"'${MatchNumber/3r}:${TextBefore}'"${bold}"'${MatchedText}'"${rmbold}"'${TextAfter}${NL}'"'"
    else
	PerDocument="'"'${DocTitle} == ${DocName}${NL}'"'"
	PerMatch="'"'${MatchNumber/3r}:${TextBefore}${MatchedText}${TextAfter}${NL}'"'"
    fi

    unset_traps

    eval lqrank ${PRECISION} -r ${RANK} $Phrases $sort |
    eval lqkwic -e ${ENTLIST} -p 1 -g 0 -l$LEFT -r$RIGHT $SGML_CLEVER \
    -s "${PerMatch}" -S "${PerDocument}" -f - ${FILTERPROG}

    set_traps
    rm -f $tmp
}

nroff_index()
{
    shift

    unset_traps
    QUERYSTR=`echo $N $Phrases "$C" | tr '"\012' '/;'`
    export QUERYSTR
    eval lqrank ${PRECISION} -r ${RANK} $Phrases $sort | (
	echo ".ds tS ${QUERYSTR}"
	cat << 'boy'
.de pT
' ev 2
'  sp |0.7c
'  lt 21c-0.5i
'  ps 9
'  tl \*(tSPage %
'  sp |1.5c
' ev
..
'wh 0 pT
.
.de pB
' tm === end of page \\n% ===
' bp
..
.wh -2c pB
.
.de eM
. br
\l'\\n(.lu'
' tm === sending job to printer.
..
.em eM
.
.na
.ffam C
.ft R
.ps 8
.vs 8.5
.po 0.75c
.ll 21c-0.5i \" min. of A4 and US letter
.lt 21c-0.5i \" also needs changing in pT above.
.br
boy
	lqkwic -e ${ENTLIST} -p 1 -g 0 -l$LEFT -r$RIGHT $SGML_CLEVER -s \
'.br${NL}&fB${MatchNumber/3r}fR:${TextBefore}fB${MatchedText}fP${TextAfter}${NL}' \
	-S '.br${NL}f[TI]${DocTitle}f[R] ${DocName}${NL}.br${NL}' \
	-f - |
	sed -e 's/\\/\\e/g' -e 's//\\/g'
    ) | ts
    set_traps
    rm -f $tmp
}


show_text()
{
    tmp=/tmp/lq.$$
    rm -f $tmp

    make_match_list $tmp "$@"

    unset_traps
    eval lqrank ${PRECISION} -r ${RANK} $Phrases $sort | sed -n -f $tmp |
    $prog -f -
    set_traps
    short_index_help
}

show_filenames()
{
    unset_traps
    eval lqrank ${PRECISION} -r ${RANK} $Phrases $sort |
	lqkwic -o "${@-all}" -S '[${MatchNumber}] ${DocTitle} -- ${DocName}${NL}' -s ''
    set_traps
    short_index_help
}

print_sethelp()
{
    print_info "\
    | @[:set match@] [@<precise@>|@<heuristic@>|@<rough@>]
    |	to set the phrase matching level,
    |	currently $PRECISION_DESC
    | @[:set index@]
    |	to see a Key Word In Context (KWIC) index of the matches
    | @[:set text@]
    |	to browse the actual text that was matched
    | @[:set database@] @<directory@>
    |	to use the database in the named directory.
    |	Current value: $LQTEXTDIR
    | @[:set rank@] [@<all@>|@<most@>|@<any@>]
    |	@<all@> presents only documents containing all the phrases you typed;
    |	@<most@> shows those first, and then documents with all but one of
    |	the phrases, and so on.
    |	@<any@> doesn${Q}t bother sorting the matches; this is the default,
    |	because it${Q}s the fastest.
    |	Currently: ${RANK_TYPE_DESC}
    | @[:set kwicmode@] [@<default|adorned|unadorned@>]
    |   determine whether kwic index results will be displayed with bold and
    |   underline.  The default is adorned.
    | @[:set filter@] [@<default@>|@<none@>|@<command@>]
    |   All kwic index results are piped through @<command@>.
    | @[:set tags@] @<shown|hidden@>
    |	determine whether SGML tags are shown or hidden in the KWIK index
    | @[:set tagchar@] @<c@>
    |	set the character @<c@> as a replacement for hidden SGML tags
    | @[:set maxhits@] @<n@>|@<all@>
    |	show only the first @<n@> matches (currently $MAXHITS)
    | @[:set pager@] @<string@>
    |	set the pager used for messages like this
    | @[:set prompt@] @<string@>
    |	set the prompt for typing in phrases to @<string@>
    |
    | In most cases you can get more specific information by given
    | @[:set@] with a variable and no argument, for example
    |     @[:set kwicmode@]
    |
"
}

set_prompt()
{
    case "$1" in
    default)
	PROMPT="${PROMPT_DFLT}"
	;;
    '"'*'"'|"'"*"'")
	PROMPT=`echo "$1" | sed 's/^\(['"${Q}"'""]\)\(.*\)\1/\2/'`
	;;
    none)
	PROMPT=;
	;;
    ?*)
	PROMPT="$1"
	;;
    *)
	print_info "\
| @[:set prompt@] [@<any string@>|@<default@>|@<none@>]
|	sets the prompt to the @<string@> you type, or to
|	the default of ${VBAR} .
|	You can use single or double quotes, as in
|	@<:set prompt "enter a phrase: "@>
|	The current prompt is ${PROMPT}.
"
	;;
    esac
}

print_set_match_help()
{
    print_info "\
| @[:set match@] @<level@>
| Specify the kind of match you want:
| @<precise@>
|       the phrases you type must be matched as
|       exactly as possible in the database.
| @<heuristic@>,@<normal@>,@<default@> (any one will do)
|       CAPITALS, plural@[s@], possessive@[${Q}s@]
|       in your phrases will only match words in the database, e.g.:
|       @<@[Word@]@<   @[Matches@]@<         @>${VBAR}@< @[Word@]@<   @[Matches@]@<                      @>
#       Word   Matches                 |       Word   Matches
|       boys   boys Boys boy${Q}s ${VBAR} boy    boy boys Boy Boys boy${Q}s Boy${Q}s
|       Boys   Boys            ${VBAR} Boy    Boy Boys Boy${Q}s Boys${Q} etc
|       
| @<rough@>,@<approximate@> (either will do)
|       the phrases you type must occur in the original documents
|       but case is ignored, and there can be extra words in the
|       middle of the phrase.
| see @<lqphrase@> @[-xvv@] for more information.
|
"
}

wordgrep()
{
    if test -z "$2"
    then
	print_info "\
    | Use @[:grep@] @<pattern@>
    | to see words matching the egrep-style @<pattern@> you give.
"
    else
	# use rs to print the output in columns.
	# rs is included in the lq-text distribution in the src/tools
	# directory.  It's pretty useful...
	lqwordlist -n -g "$2" |
	$RS
    fi
}

wordlist()
{
    if test -z "$2"
    then
	print_info "\
    | Use @[:grep@] @<string@>
    | to see words beginning with the prefix @<string@>.
"
    else
	lqwordlist -s -p "$2" |
	mawk '
	    { printf "%5d %-18s\n", $2, $1 }
	' | $RS
    fi
}

handle_set()
{
    case "$2" in
    *show|text)
	prog=lqshow
	echo "displaying text..."
	;;
    *kwic|*kwik|index)
	prog=lqkwic
	echo "displaying index..."
	;;
    maxhits)
	case "$3" in
	[0-9]|[0-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9]*[0-9][0-9])
	    MAXHITS="$3"
	    ;;
	[nN][oO][nN][eE]|[aA][lL][lL])
	    MAXHITS="all"
	    ;;
	*)
	    print_info "\
| @[:set maxhits@] @<number@>|@<all@>
|    Only the first @<n@> lines of output will be shown in the index,
|    unless you explicitly ask for more using a @<range@>, described below.
|    Use @<all@> to see all of the matches by default.
|    The current value is @<$MAXHITS@>.
| 
|    All of the commands such as @[:page@] take a @<range@> of matches
|    as an option.  These can be @[-12@] to specify items up to and including
|    the twelth; @[35-@] to specify items 35 and onward; @[4-7@] to
|    specify items 4, 5, 6 and 7, or @[17@] to specify item 17.  You can
|    separate multiple ranges with spaces or commas, but if you do, the
|    numbers have to increase, so @[-4@] would have to be at the start, and
|    @[12-@] would have to be at the end.
|
|    When you give a @<range@>,
|    the current value of @<maxhits@> is always ignored.
"
	esac
	;;

    filter)
	case "$3" in
	none|cat)
	    FILTERPROG=;
	    print_info "\
| filter reset, kwic index will no longer be filtered.
"
	    ;;
	default)
	    if test x"$FILTER_DEFAULT" = x""
	    then
		FILTERPROG=
	    else
		FILTERPROG="| $FILTER_DEFAULT"
	    fi
	    print_info "\
| filter reset to default value, kwic index will be filtered by:
|    @<${FILTERPROG}@>
"
	    ;;
	?*)
	    FILTERPROG="| $3"
	    print_info "\
| kwic index will be piped through:
$FILTERPROG
| You can use @<:set filter default@> to set it to the default.
"
	    ;;
	*)
	    print_info "\
| @[:set filter@] @<command@>
| subsequent kwic index output (i.e. result lists) will be piped through
| the given command.  For example, you could use
| @[:set filter@] @<more@>
| to have the results paged, or
| @[:set filter@] @<tee -a output@>
| to have them appended to the file called @<output@>.
|
| The current value is
|     @<${FILTERPROG}@>
|
| You can use @[:set filter default@] to set it to the default, and
| @[:set filter none@] to have output sent directly to the terminal
| without any processing.
|
| Note that the kwic index contains terminal escape sequences.  You can
| turn these off with @[:set kwicmode raw@].
"
	    ;;
	esac
	;;
    pager)
	case "$3" in
	raw|none)
	    HELP_PAGER=;
	    ;;
	?*)
	    HELP_PAGER="| $3"
	    print_info "\
| messages will be paged using
| $3
"
	    ;;
	*)
	    print_info "\
| messages are displayed using
|    `echo \"${HELP_PAGER}\" | sed 's/^| //'`
| use @[:set pager@] @<none|command@> to change this.
"
	    ;;
	esac
    ;;
    kwicmode)
	case "$3" in
	raw|off|none|unadorned)
	    KWICMODE=unadorned
	    print_info "\
| kwic index results will be displayed unadorned.
"
	    ;;
	pretty|default|normal|adorned)
	    KWICMODE=adorned
	    print_info "\
| kwic index results will be displayed adorned with bold and underline.
"
	    ;;
	*)
	    print_info "\
| kwic index results will be displayed $KWICMODE with bold and underline.
| use
| @[:set kwicmode@] @<default|adorned|unadorned@>
| to change this.  The default is adorned.
"
	    ;;
	esac
	;;
    database)
	case "$3" in
	?*)
	    if (cd "$3" ) 2> /dev/null
	    then
		echo "${bold}LQTEXTDIR${rmall} set to \"${z}\""
		LQTEXTDIR="$3"; export LQTEXTDIR
	    else
		if test -d "$3"
		then
		    echo "Can${Q}t enter $3 - check permissions"
		else
		    echo "$3 doesn${Q}t seem to be a directory"
		fi
	    fi
	    ;;
	*)
	    print_info "\
| @[:set directory@] @<directory@>
| to browse a different ${lqtext} database,
| where @<directory@> is the name of an ${lqtext}
| directory containing @<README@>, @<data@>, etc.
| The default database is:  \$HOME/LQTEXTDIR
| The current value is:     $LQTEXTDIR
|
"
	esac
	;;
    tags)
	case "$3" in
	show*)
	    SGML_CLEVER=;
	    ENTLIST=
	    echo "${VBAR} SGML tags will be shown in ASCII."
	    SGML_TAG_DESC="as ASCII text"
	    ;;
	hid*)
	    SGML_CLEVER="-c -C ${SGML_CHAR}"
	    SGML_TAG_DESC="as ${SGML_CHAR} characters"
	    ENTLIST="-E ${LQTEXTDIR}/entitylist"
	    print_info "\
| Sequences of SGML tags will be shown ${SGML_TAG_DESC}
| for example, the SGML string
|	ele<A><B>phant</B> indeed!
| will become
|	ele${SGML_CHAR}phant${SGML_CHAR} indeed!
| use @[:set tagchar@] to change the character used.
"
	    ;;
	*)
	    print_info "\
| @[:set tags@] [@<shown@>|@<hidden@>]
|	sets the way SGML tags are presented in the index:
| @<show@> or @<shown@>
|	The tags will be shown as ASCII characters.
| @<hide@> or @<hidden@>
|	The tags will not be shown, but wherever one or more tags was
|	suppressed, a special mark (currently \"${SGML_CHAR}\") will appear.
| 	You can change this character with @[:set tagchar{rmbold} @<c@>
|	where @<c@> is the character you want to use.
"
	esac
	;;

    tagchar)
	case "$3" in
	0[0-9]*)
	    SGML_CHAR=`/usr/5bin/echo "\\\\$3"`
	    ;;
	?)
	    SGML_CHAR="$3"
	    ;;
	*)
	    print_info "\
| @[:set tagchar@] @<c@>
| Here, @<c@> can be a single character, or it can be an octal (base 8)
| number beginning with a zero, which will be used as a font index for
| a single character.
"
	;;
	esac
	SGML_CLEVER="-c -C ${SGML_CHAR}"
	SGML_TAG_DESC="as ${SGML_CHAR} characters"
	print_info "\
| SGML tag character is now \"${SGML_CHAR}\"
| Sequences of SGML tags will be shown ${SGML_TAG_DESC}
| for example, the SGML string
|	ele<A><B>font</B> you say?
| will become
|	ele${SGML_CHAR}font${SGML_CHAR} you say?
"
	;;
    match)
	case "$3" in
	precise|exact)
	    PRECISION="-mp"
	    PRECISION_DESC="precise matching"
	    ;;
	heuristic|default|normal)
	    PRECISION="-mh"
	    PRECISION_DESC="heuristic matching (the default)"
	    ;;
	rough|approximate)
	    PRECISION="-ma"
	    PRECISION_DESC="approximate (rough) matching"
	    ;;
	*)
	    print_set_match_help
	;;
	esac
	print_info "\
| Currently using $PRECISION_DESC
"
    ;;
    prompt)
	set_prompt "$3"
	;;
    rank)
	case "$3" in
	all|and)
	    RANK=all
	    RANK_TYPE_DESC="find documents containing ${smul}all${rmul} of the phrases"
	    ;;
	most)
	    echo "Sorry, ${bold}rank${rmbold} ${smul}most${rmul} unimplemented."
	    ;;
	any|or|none)
	    RANK=none
	    RANK_TYPE_DESC="find documents containing ${smul}any${rmul} of the phrases"
	    ;;
	*)
	    print_info "\
| @[:set rank@] [@<all@>|@<most@>|@<any@>]
|	to set the phrase matching level,
| @<all@>
|	Documents will be retrieved if they contain @<all@> of
|	the phrases you type;
| @<most@>
|	Documents will be retrieved if they contain @<any@> of
|	the phrases you type, but the more of the phrases a document contains,
|	the earlier it will appear in the results.
| @<any@>
|	Documents will be retrieved if they contain @<any@> of
|	the phrases you type.
"
	;;
	esac
    ;;
    *) 
	print_sethelp
       ;;
    esac
}

Phrases=
Shown=no
export Phrases Shown
Redirected=
export Redirected

handle_source()
{
    SourcedFile=/tmp/lqsf.$$
    tmp="$tmp $SourcedFile"
    cp "$2" $SourcedFile
    echo ":reset_input" >> $SourcedFile
    exec < $SourcedFile
    Redirected=yes
}

tf="/tmp/lq.$$"
tmp="$tmp $tf"
cp /dev/null $tf

if test -f "$HOME/.lq-rc"
then
    cat "$HOME/.lq-rc" > $tf
fi

if test $# -ge 1
then
    for i
    do
	echo "$i"
    done >> $tf
    echo >> $tf
fi

if test -s $tf
then
    PROMPT=""
    handle_source :source $tf
fi
/bin/rm -f $tf

while  [ x"$quit" != x"yes" ]
do
    print_info "\
| Type words or phrases to find, one per line, followed by a blank line.
| Use control-D to quit.  Type @<?@> for more information.
"
    x='fhdjfd'
    y=
    while [ x"$x$y" != x"" ]
    do
	echo $N "${PROMPT}$C"

	read x y z || exit

	case "$x" in
	:set)
	    handle_set "$x" "$y" "$z"
	    continue
	    ;;
	:view)
	    handle_view "$x" "$y" "$z"
	    continue
	    ;;
	:index)
	    show_index "$x" "$y" "$z"
	    continue
	    ;;
	:less)
	    handle_less "$x" "$y" "$z"
	    continue
	    ;;
	:nroff)
	    nroff_index "$x" "$y" "$z"
	    continue
	    ;;
	:page)
	    handle_page "$x" "$y" "$z"
	    continue
	    ;;
	:files)
	    show_filenames
	    continue
	    ;;
	:grep)
	    wordgrep "$x" "$y" "$z"
	    continue
	    ;;
	:prefix)
	    wordlist "$x" "$y" "$z"
	    continue
	    ;;
	:shell)
	    handle_shell "$x" "$y" "$z"
	    continue
	    ;;
	!*)
	    x=`echo "$x" | sed -e 's/^!//'`
	    if test ! -z "$x"
	    then
		handle_shell "!" "$x" "$y" "$z"
	    else
		handle_shell "!" "$y" "$z"
	    fi
	    ;;
	:sort)
	    handle_sort "$x" "$y" "$z"
	    continue
	    ;;
	:trace)
	    set -x
	    continue
	    ;;
	:notrace)
	    set +xv
	    continue
	    ;;
	:quit)
	    exit 0
	    ;;
	:comment)
	    contine
	    ;;
	:reset_input)
	    Redirected=;
	    Phrases=;
	    exec 0<&2
	    handle_set :set prompt default #  > /dev/null 2>&1
	    if test ! x"$SourcedFile" = x""
	    then
		/bin/rm -f "$SourcedFile"
	    fi
	    break
	    ;;
	:*)
	    command_help "$x"
	    continue
	    ;;
	'?')
	    main_help
	    ;;

	?*)
	    if [ x"$Shown" = x"yes" ]
	    then
		Phrases=;
		Shown=no
	    fi

	    # doubling of the quote is for shchk, the shell checker:
	    New=`echo "$x $y $z" | sed 's/"/:/g'`
	    Phrases="${Phrases} \"$New\""
	    ;;
	esac
    done
    if [ x"$prog" = x"lqkwic" ]
    then
	show_index ""
    else
	show_text ""
    fi
    Shown=yes
    # echo $N "Type q to quit, or return to continue: $C"
    # read quit
    # case "$quit" in
    # [qQ]*) quit="yes" ;;
    # *)	   quit=no ;;
    # esac
done
