#!/bin/bash 
#
#  whizzytex --- WhizzyTeX, a WYSIWIG environment for TeX
#  Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2013
#                2015, 2016, 2020, 2021, 2024.
#                INRIA.
#
#  Author         : Didier Remy <Didier.Remy@inria.fr>
#  Version        : 1.5.0
#  Bug Reports    : https://github.com/diremy/whizzytex/issues
#  Web Site       : http://gallium.inria.fr/whizzytex
#  
#  WhizzyTeX is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2, or (at your option)
#  any later version.
#
#  WhizzyTeX is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details 
#  (enclosed in the file GPL).
#
#  See the file COPYING enclosed with the distribution.
#############################################################################
#  File whizzytex (Bash shell-script)
#############################################################################

### Configuration (manual or automatic)

VERSION="1.5.0"

# name (or full path) of the dump latex2e package file (without the extension)
PACKAGE=whizzytex.sty

# Translating DVI to Postscript
DVIPS=dvips

# Translating DVI to DVI, may be set to dvicopy
DVICOPY=mv


# Default LaTeX implementation
MODE=dvi

# Default LateX 
WOUT=././out

INITEX="latex -ini"
LATEX=latex
OUTDIR="-output-directory="
LATEXCOMMANDLINE=
LATEXCOMMANDS=
FORMAT=latex
FMT=fmt
BIBTEX=bibtex

# Default for pdflatex implementation, 
# TODO: set them during configuration. 
PDFLATEX=pdflatex
PDFINITEX="$PDFLATEX -ini"
# PDFLATEXCOMMANDS='\WhizzyDriver{pdftex}'

# Default flags
AUTOCOMPILE=true
AUTORECOMPILE=true

# Default place for configuration files

CONFIGDIR=/etc/whizzytex/

### Configuration (manual only)

# limit the length of error messages sent back to stdout.
TEXERRORMAXLINES=50
TEXERRORAROUND=20

# time limit for running initex in case this could loop, undetectedly!
LIMIT=60

# Signals telling gv and xdvi/advi to refresh
SIGDVI=SIGUSR1
SIGINPUTDVI=SIGUSR2
SIGINPUT=SIGCONT
SIGPS=SIGHUP
SIGPDF=SIGCONT
SIGMUPDF=SIGHUP

# Option to read command, could be use to send timeout, in case, whizzytex 
# should watch other files that those controlled by emacs
# READOPTION=-t 5
READOPTION=

### End of configuration variables

### Environnment for sed to work properly
export LC_CTYPE=C
export LANG=C

TRACE=false

case $# in
 0) echo 'Usage: whizzytex [ OPTIONS ] FILENAME'; exit 1;;
esac

COMMAND="$0"
for i in "$@"; do COMMAND="$COMMAND"'
'"$i"; done
TOUCH=false
MKSLICE=defaultmkslice
MKFILE=defaultmkfile

defaultmkslice () { mv $SLICE $WHIZZY$EXT 2>/dev/null; }
defaultmkfile () { true; }


DO=normal
MAKEINDEX=makeindex
DOINDEX=true
DVI=dvi
VIEW=wdvi
WAUX=waux
RAUX=raux
VIEWCOMMAND="advi -whizzy"
NAVIGATION=true
NEWFILES=newfile
MULTIPLE=true
DUPLEX=false
LEVEL=0

# default
RELOAD=sigreload
RELAODARG=""

# DEBUGGING

# 

llpplaunch () {
    rm -f $WREMOTE && \
    mkfifo $WREMOTE && \
    llpp -remote $WREMOTE "$1"
}


while true
do
  case "$1" in
   -kill) DO=kill;;
   -wakeup) DO=wakeup;;
   -formatonly) DO=format;;
   -sliceonly) DO=slice;;
   -batch) DO=batch;;
   -mkslice) MKSLICE="$2"; shift;;
   -mkfile) MKFILE="$2"; shift;;
   -duplex) DUPLEX=true;;
   -trace) TRACE=true;; 
   -makeindex) 
      case "$2" in
        false) DOINDEX=false;;
        *) MAKEINDEX="$2";;
      esac 
      shift;;
   -bibtex) BIBTEX="$2"; shift;;
   -ext) EXT="$2"; shift;;
   -initex) INITEX="$2"; shift;;
   -latex) LATEX="$2"; shift;;
   -format) FORMAT="$2"; shift;;
   -fmt) FMT="$2"; shift;;
   -dvicopy) DVICOPY="$2"; shift;;
   -watch) NEWFILES=newfiles;;
   -dvi|-nodvi)
       MODE=dvi
       VIEW=wdvi;
       NAVIGATION=false;
       MULTIPLE=false;
       case "$2" in
       .) VIEWCOMMAND=xdvi;;
       *) VIEWCOMMAND="$2";;
       esac
       case "$1" in -nodvi) VIEWCOMMAND=noviewer;; esac
       shift;;
   -advi)
       MODE=advi
       LEVEL=2
       VIEW=wdvi;
       case "$2" in
       .) VIEWCOMMAND="advi -whizzy";;
       *) VIEWCOMMAND="$2";;
       esac
       shift;;
   -ps)
       MODE=ps
       VIEW=ps
       NAVIGATION=false;
       MULTIPLE=false;
       case "$2" in
       .) VIEWCOMMAND=gv;;
       *) VIEWCOMMAND="$2";;
       esac
       shift;;
   -pdf|-kpdf|-gpdf|-nopdf|-skim|-mupdf)
       LEVEL=1
       DVI=pdf
       VIEW=wpdf
       NAVIGATION=false;
       MULTIPLE=false;
       INITEX="$PDFINITEX"
       # Perhaps the following line should be added to backup to latex.fmt
       # in case pdflatex.fmt does not exists. 
       # if kpsewhich -format fmt -engine / fmt pdflatex
       # could also be fixed in a local configuration file.
       FORMAT="pdflatex"
       DUPLEX=false
       DVICOPY=pdfcopy
       case "$1" in
           -pdf)
               MODE=pdf
               LATEX="$PDFLATEX"
               RELOAD=xpdfreload
               VIEWCOMMAND=xpdfremote
               ;;
           -kpdf) 
               MODE=kpdf
               LATEX="$PDFLATEX -synctex=1"
               RELOAD=kpdfreload
               VIEWCOMMAND=kpdfremote
               ;;
           -gpdf) 
               MODE=opdf
               LATEX="$PDFLATEX -synctex=1"
               RELOAD=gpdfreload
               VIEWCOMMAND=gpdfremote
               ;;
           -nopdf)
               MODE=pdf
               LATEX="$PDFLATEX"
               RELOAD=true
               VIEWCOMMAND=noviewer
               ;;
           -mupdf)
               MODE=pdf
               LATEX="$PDFLATEX"
               SIGPDF=SIGHUP
               RELOAD=mupdfreload
               VIEWCOMMAND=mupdf
               ;;
       esac
       case "$2" in
       .|xpdf|kpdf|gpdf|noviewer|"") ;;
       llpp) 
          # SIGPDF=SIGUSR1
          MODE=llpp
          LATEX="$PDFLATEX -synctex=15"
          VIEWCOMMAND="llpplaunch"
          RELOAD=llppreload
          ;;
        skim)
          MODE=skim
          LATEX="$PDFLATEX -synctex=1"
          RELOAD=skimreload
          VIEWCOMMAND=Skim
          ;;
       *) warning "Use an xpdf like viewer, or redefine RELOAD."
          VIEWCOMMAND="$2"
          ;;
       esac
       shift
       ;;
   -display)
       export DISPLAY="$2"
       shift;;
   -version)
       echo $VERSION
       exit 0;;
   -*)
       echo 'Unrecognized argument '"$1"'

Usage whizzytex: 

  whizzytex <option> ... <option> <file>

where <option> is 

    -kill 
    -reformat
    -duplex
    -makeindex <makeindex command>
    -ext <latex extension>
    -initex <initex command>
    -latex <latex command>
    -format <latex format file name>
    -bibtex <bibtex command>
    -fmt <format extension>
    -pre <preprocess-command>
    -advi <advi-like previewer command> 
    -dvi <dvi-like previewer command> 
    -ps <Postscript previewer command> 
    -pdf xpdf
    -kpdf kpdf
    -display <X display> 
    -version 

# additional debuging options:

    -formatonly         # dump format and exit
    -batch              # dump format, resume compilation with that format, and exit
  ' 1>&2
       exit 1;;
   *) break;;
  esac
  shift
done

if $TRACE; then set -o xtrace; fi

HERE=$(/bin/pwd)

# Sanity check

case "$1" in 
  *" "*) 
      echo 'Cannot WhizzyTeX a  file '"$1"' whose name contain a space'
      echo '<Quitting>'
      exit 1;;
esac

# Computing basenmae

FULLNAME="$1"
BASENAME=$(basename "$1")
FILEEXT=$(expr "$BASENAME" : '.*\(\.[^.]*\)')
NAME=$(basename "$BASENAME" "$FILEEXT")

# Load configuration files, all files are loaded in order

# PATHS would expose the user to attacks ../whizzy.sh  ../lib/whizzy.sh \

for CONFIG in \
    "$NAME.wsh" \
        whizzy.sh \
        "$CONFIGDIR/whizzytex.conf" {"$HOME",.}/.whizzytexrc \
        {"$CONFIGDIR","$HOME"/.whizzytex}/whizzy.sh 
do
  if [ -f "$CONFIG" ]
  then
    echo "Loading configuration file: $CONFIG"
    . "$CONFIG"
    break
  fi
done

# hereafter, configuration should not change

# Selecting source file extension.

case "$EXT" in
 "") EXT="$FILEEXT";;
esac

WHIZZY=_whizzy_$NAME
WHIZZYDIR=${WHIZZY}_d
case "$WOUT" in
    "././out") WOUT="$WHIZZYDIR/out" ;;
esac
LOCK=.${WHIZZY}$EXT
SLICE=${WHIZZY}.new
WSYNCTEX=${WHIZZY}.synctex.gz

WHIZZYOUT="$WOUT/$WHIZZY"
WHIZZYVIEW="$WHIZZYOUT.$VIEW"
NAMEOUT="$WOUT/$NAME"
NAMEVIEW="$NAMEOUT.$VIEW"

WFORMAT="&$WHIZZYOUT"


# Be careful fullnames may contain a space.

INPUT="$HERE/$WHIZZYDIR/input"
OUTPUT="$HERE/$WHIZZYDIR/output"
DEBUGDIR="$HERE/$WHIZZYDIR/"
TMP="$HERE/$WHIZZYDIR/tmp"
SECTIONS="$OUTPUT/sections"
LOG="$TMP/log"
ERR="$TMP/err"
WREMOTE="$TMP/llpp.remote"




INITPHASE=true

info() {
echo "
        COMMAND=$COMMAND
        EXT=$EXT
        MKSLICE=$MKSLICE
        MKFILE=$MKFILE
        INITEX=$INITEX
        LATEX=$LATEX
        OUTDIR=$OUTDIR
        WOUT=$WOUT
        FORMAT=$FORMAT
        MULTIPLE=$MULTIPLE
        DUPLEX=$DUPLEX
        VIEW=$VIEW
        MODE=$MODE
	RELOADARGS
        VIEWCOMMAND=$VIEWCOMMAND
        RELOAD=$RELOAD
        LEVEL=$LEVEL

        BASENAME=$BASENAME
        EXT=$EXT
        NAME=$NAME

        AUTOCOMPILE=$AUTOCOMPILE
        AUTORECOMPILE=$AUTORECOMPILE

        TRACE=$TRACE
        VERSION=$VERSION
"
}

help() {
echo "
The main commands are:
       duplex                   open a new duplex window
       reformat                 reformat and recompile
       autorecompile            recompile if necessary
       viewer-command ARGS      send ARGS a command to the previewer
       recompile                recompile
       clear                    remove .aux files
       whole                    recompile the whole documment
       bibtex                   run bibtex 
       help                     show this
       info                     show variables
       trace [ on | off ]       turn trace on or off
       exit                     exit
       nextslice                reload the slice and moves
       reslice                  reload the same slice, without moving
       rmaux                    rm .aux files


"
}

errlog () { echo "$*" 1>&2; }
fatal () { 
    errlog '*** Fatal error: ' "$*"
    [ -f "$ERR" ] && cat "$ERR"
    echo '<Quitting>' 
    if [ -x /bin/usleep ]; then /bin/usleep 500000; else /bin/sleep 1; fi;
    cleanquit "$1"
}
warning () {
  echo "Warning: " $*
}  

quit () { 
  echo '<Quitting>'
  cleanquit viewer
}

log () {
  if [ -f "$OUTPUT/$1" ] 
  then cat "$OUTPUT/$1"
  fi
  false
}

texlog () { 
  if [ -f "$OUTPUT/$1" ] 
  then
    sed -n -e '/^#/p' -e '/^!/,$p' "$OUTPUT/$1" | head -$TEXERRORAROUND | \
    cat > $OUTPUT/texlog
    shift
    echo '<Viewtexlog>' "$@"
  fi
  false; 
}
errlog "$COMMAND"

$MKFILE "$FULLNAME"
if [ -f "$NAME$EXT" ]
then 
   :
else
   echo "File $NAME$EXT does not exist"
   exit 1
fi

clean () {
   [ -f "$TMP/pids" ] && kill -TERM $(cat "$TMP"/pids) 2>/dev/null
   if $INITPHASE 
   then 
     for i in $WHIZZY.* "${WHIZZY}_nil".* $NAME.{$FMT,$VIEW,$RAUX}
     do 
       if [ -f $i ]; then mv "$i" "$TMP"; fi
     done
   else
     rm -f $WHIZZY.* "${WHIZZY}_nil".* $NAME.{$FMT,$VIEW,$WAUX,$RAUX}
     if $TRACE; then : ; else rm -rf "$WHIZZYDIR"; fi
   fi
   rm -f $LOCK
}

cleanquit () {
   clean
   trap - SIGTERM
   echo "Quitting ($1)"
   clean
   kill -TERM 0
   exit 0
}
trap "cleanquit SIGTERM" SIGTERM
trap "cleanquit SIGHUP" SIGHUP
trap "cleanquit SIGQUIT" SIGQUIT

cleankill () {
   if [ -f $LOCK ] 
   then
      PID=$(cat $LOCK)
      clean 
      kill -KILL $PID
   else
      clean
   fi
   exit 2
}

wakeup () { [ -f $LOCK ] && kill -CONT $(cat $LOCK); }
runinitex () { ( ulimit -t $LIMIT; $INITEX $OUTDIR$WOUT "$@" ); }
runlatex  () { ( ulimit -t $[ 3 * $LIMIT ] ; $LATEX $OUTDIR$WOUT  "$@" ); }
runslice  () { ( ulimit -t $LIMIT ; $LATEX $OUTDIR$WOUT "$@" ); }


# Making format

echo DVI=$DVI

format () {
    ( echo runinitex \'"&$FORMAT"\' \'"$LATEXCOMMANDLINE$LATEXCOMMANDS"'\nonstopmode\makeatletter\def\WhizzyMode {'$DVI'}\def\SourceFile{\def\whizzy@master}\def\WHIZZYCONFIGDIR{'"$CONFIGDIR"'}\def\WHIZZYHOME{'"$HOME"'}\makeatother\let\Documentclass\documentclass\renewcommand{\documentclass}[2][]{\Documentclass[#1]{#2}\let\WhizzyLevel'"$LEVEL"'\def\WhizzyExt{'"$EXT"'}\input{'"$PACKAGE"'}}\input{'"$NAME$EXT"'}'\';
      runinitex "&$FORMAT" "$LATEXCOMMANDLINE$LATEXCOMMANDS"'\nonstopmode\makeatletter\def\WhizzyMode {'$DVI'}\def\SourceFile{\def\whizzy@master}\def\WHIZZYCONFIGDIR{'"$CONFIGDIR"'}\def\WHIZZYHOME{'"$HOME"'}\makeatother\let\Documentclass\documentclass\renewcommand{\documentclass}[2][]{\Documentclass[#1]{#2}\let\WhizzyLevel'"$LEVEL"'\def\WhizzyExt{'"$EXT"'}\input{'"$PACKAGE"'}}\input{'"$NAME$EXT"'}'
    )
}

#############################################################################

############################################################################
# BEGIN sections

atomiccopy () {
   $DVICOPY "$1" "$TMP/tmp.$$" && mv "$TMP/tmp.$$" "$2";
}

LATER=04$(date +%m%d%H%M.%S)
pdfcopy () {
   mv "$1" "$2"
   touch -t "$LATER" "$2"
}

xpdfremote () {
    case $1 in 
        $NAME.$VIEW) REMOTE=_full_$$ ;; 
        *) REMOTE=_whizzy_$$ ;; 
    esac
    xpdf -remote $REMOTE "$@"
}

kpdfremote () {
    okular --unique "$@"
}

gpdfremote () {
    evince --page-label=Start-Document "$@"
    wmctrl -R emacs@arbois
}


makebibtex () {
  if $BIBTEX $NAMEOUT 1>"$OUTPUT/bibtex"
  then : 
    [ -f $NAMEOUT.bbl ] && cp $NAMEOUT.bbl $WHIZZYOUT.bbl
  else
    echo '<bibtex failed: see log in' "$OUTPUT/bibtex" '>'
  fi 
}

batchmarks () {
    if runlatex $WFORMAT '\WhizzytexInput{'$NAME'}' 1>"$OUTPUT"/latex
    then
      atomiccopy $NAMEOUT.$DVI $NAMEOUT.$VIEW 2>"$OUTPUT"/dvicopy
      [ -f $NAMEOUT.toc ] && cp $NAMEOUT.toc $WOUT/$WHIZZY.toc
      # if grep -e '\(LaTeX Warning: Citation\|No file [^ ]*\.bbl\)' $NAMEOUT.log
      if grep -e 'Warning: There were undefined \(citation\|reference\)s\.' $NAMEOUT.log
      then
        makebibtex
      fi
      if $DOINDEX && grep 'Writing index file' $NAMEOUT.log
      then
         $MAKEINDEX $NAMEOUT.idx 1>"$OUTPUT"/makeindex 
         [ -f $NAME.ind ] && cp $NAMEOUT.ind $WHIZZYOUT.ind
         true
      fi
      # move .raux into .waux so as to preserve the integrity of .raux 
      # when the slice fails. 
      if [ -f $NAMEOUT.$WAUX ]
      then mv $NAMEOUT.$WAUX $NAMEOUT.$RAUX
      else rm -f $NAMEOUT.$RAUX
      fi
    else 
       rm -f $WHIZZYOUT.pag; false
    fi
}

# END sections

############################################################################
# BEGIN Worddiff

wordify () { 
  awk '{for (i=1; i<=NF; i++) {print $i}}'
}


worddiff () { 
  FST="$1"
  SND="$2"
  DIF=$WHIZZYOUT.dif
  diff "$FST" "$SND" > "$DIF"
  if [ $(grep -v -e '^[-><]' "$DIF" | wc -l) -eq 1 ] && \
     [ $(wc -l < "$DIF") -lt 3 ] && \
       grep -e '^[1-9][0-9,]*[ac]' "$DIF" > "$DIF".lin
  then
    sed "$DIF" -n -e '/^< /s/^< //p' > "$FST".lin
    sed "$DIF" -n -e '/^> /s/^> //p' > "$SND".lin

    wordify < "$FST".lin > "$FST".wrd
    wordify < "$SND".lin > "$SND".wrd

    diff "$FST".wrd "$SND".wrd > "$DIF".wrd

    if [ $(grep -v -e '^[-><]' "$DIF".wrd | wc -l) -eq 1 ] && \
         grep -e '^[1-9][0-9,]*[ac]' "$DIF".wrd > /dev/null
    then
       (
        echo '<Error in Line'
        cat "$DIF".lin
        echo Word
        grep -e '^[0-9]' "$DIF".wrd
        echo ':'
        sed "$DIF".wrd -n -e 's/^> \(.*\)$/\1/p'; 
        echo '>'
       ) | tr '\n' ' '
       echo     
    else
      false
    fi
  else 
    false
  fi
}

# END Wordify

############################################################################
# So what should we do

case $DO in
  kill) cleankill && exit 0 || exit 1;;
  wakeup) wakeup && exit 0 || exit 1;;
  format)
      mkdir $WHIZZYDIR "$WOUT" 2>/dev/null
      format && exit 0 || exit 1;;
  slice)
      # asumes format exists
      runslice $WFORMAT $TMP/$WHIZZY$EXT && exit 0 || exit 1;;
  slice)
      # asumes format exists
      runslice $WFORMAT $WHIZZY$EXT && exit 0 || exit 1;;
  batch)
      mkdir $WHIZZYDIR "$WOUT" "$OUTPUT" 2>/dev/null
      if format
      then
          if runlatex "&$WOUT/$NAME" $NAME

          then
              echo '# Whole compilation SUCCEEDED'
              exit 0
          else 
              echo '# Whole compilation FAILED'
              exit 1
          fi
      else
          echo 'Formatting FAILED'
          exit 2
      fi
      ;;
  normal)
    # To ensure that only one deamon is running on the spool file.
    if [ -f $LOCK ] && kill -CONT $(cat $LOCK) 2>/dev/null 
    then
      fatal 'Remove running WhizzyTeX process first'
    else
       echo $$ > $LOCK
    fi
   ;;
esac

############################################################################
# We go for good

# These directories are normally created by Emacs
mkdir $WHIZZYDIR "$INPUT" "$OUTPUT" "$TMP" "$WOUT" 2>/dev/null
echo '# Begin Whizzytex command line (one argument per line)' \
        >"$OUTPUT"/command
echo "$COMMAND"  >> "$OUTPUT"/command
echo '# End of command' >> "$OUTPUT"/command

# added le 23/08/04 for ocamlweb

# Preprocessing
checkMKfile () {
  case "$1" in
    "") ;;
    *) 
        if  $MKFILE "$1" >"$OUTPUT"/mkfile 2>"$ERR"
        then true
        else 
          echo '<Preprocessing mkfile failed>'
          [ -f "$ERR" ] && cat "$ERR"
          log mkfile
          false
        fi;;
  esac
}


checkMKfile $FULLNAME
if [ -f "$NAME.$FMT" ] && [ "$NAME$EXT" -ot "$NAME.$FMT" ]
then 
  :
else
  echo -n '<Initial formating '
  if { format >"$OUTPUT"/format 2>"$ERR" || \
       { echo 'failed>'; 
         echo Removing $NAME.aux; 
         echo '<Retrying '; 
         rm -f $NAME.aux && format >"$OUTPUT"/format 2>"$ERR"; }; } \
     && [ -f $NAMEOUT.$FMT ] 
  then
     mv $NAMEOUT.$FMT $WHIZZYOUT.$FMT
     echo 'succeeded>'
  else
     rm -f $NAMEOUT.$FMT
     echo 'failed>'
     set +o xtrace
     texlog format
     echo '<Initialization failed>'; 
     { echo '
        **************************************************************
        An error occured while building the initial format.
        Are you sure that your file can be correctly LaTeX-ed? 
        Check log above and view log files (Emacs menu "View log...")
        for help. You may also start WhizzyTeX in debug mode for 
        additional information.
        **************************************************************
'         
       echo 'You may also try the command'
       echo '     whizzytex -formatonly' $FULLNAME 
     }
     fatal initialization 'Could not build format ---See message above'
  fi
fi

# Initial file

echo '\begin{document}\WhizzyEmptyPage\end{document}' > ${WHIZZY}_nil$EXT

# Texing...

echo $VIEWCOMMAND 1>&2

# GV does not refresh if the dates are equal (i.e. up 1 second) even when  
# signal with $SIGPS
ANTIDATE=$(date +%m%d%H%M.%S)

           

case $VIEW in
  ps)
    preview () {
        cd $WOUT && $DVIPS -o $WHIZZY.pst $WHIZZY.$DVI 2>/dev/null && \
        { [ ! $WHIZZY.pst -nt $WHIZZY.ps ] && touch -t $ANTIDATE $WHIZZY.pst
          mv $WHIZZY.pst $WHIZZY.ps ; }
    }
    SIG=$SIGPS
    ;;   
  wdvi)
    preview () { atomiccopy $WOUT/$WHIZZY.$DVI $WHIZZYVIEW; }
    SIG=$SIGDVI
    SIGINPUT=$SIGINPUTDVI
    ;;   
  wpdf)
    preview () { atomiccopy $WOUT/$WHIZZY.$DVI $WHIZZYVIEW; }
    SIG=$SIGPDF
    ;;   
esac

newfiles () {
  mv $(find "$INPUT" -type f -print || cleanquit Find) "$HERE"/  2>/dev/null
}
newfile () {
  mv "$INPUT"/$SLICE "$HERE"/  2>/dev/null
}

preprocess () {
  if $MKSLICE $WHIZZY$EXT >"$OUTPUT"/mkslice 2>"$ERR" && [ -f $WHIZZY$EXT ]
  then 
     true
  else
     echo '<Preprocessing failed>'
     [ -f "$ERR" ] && cat "$ERR" && cat "$ERR" >> "$OUTPUT"/mkslice
     log mkslice
     false
  fi
}

PROCESS=false
process () {
  PROCESS=false
#  This line was added for some reason that I forgot...
#  Maybe for not reloading subfiles?
#  At least it avoids errors when hyperref patches \label and \ref
  rm -f $WHIZZY.aux
  echo '<Recompiling>'
  if { runslice $WFORMAT $WHIZZY$EXT && preview; } 1>"$OUTPUT"/slice
  then
     echo "<Compilation succeeded>"
     ln -f $WHIZZY$EXT $WHIZZYOUT.last
     # We say whizzy auxilliary information to avoid yoyo in case of errors. 
     if [ -f $WHIZZYOUT.$WAUX ]
     then mv $WHIZZYOUT.$WAUX $WHIZZYOUT.$RAUX
     else rm -f $WHIZZY.$RAUX
     fi
     true
  else
     echo "<Recompilation failed>"
     if [ -f $WHIZZYOUT.last ] && worddiff  $WHIZZYOUT.last $WHIZZY$EXT
     then 
       :
     else
       if [ -f $WHIZZYOUT.last ] 
       then texlog slice 'l.'$[ $(wc -l < $WHIZZYOUT.last) - 1 ]' '
       else texlog slice
       fi
     fi
     echo '<Continuing>'
     false
  fi
}

############################################################################
# Initial run

# We ensure that the dvi [or pdf] file exists 
if runslice "$WFORMAT" ${WHIZZY}_nil$EXT > "$OUTPUT"/nil
then
  mv  ${WHIZZY}_nil$EXT $WOUT
  mv "$WOUT/${WHIZZY}_nil.$DVI" $WHIZZYOUT.$DVI
  preview || fatal 'Cannot preview initial page'
else
  cat "$OUTPUT"/nil
  fatal 'Cannot build initial page'
fi

# To give it a chance to see citations and other global information.

[ -f $NAMEOUT.bbl ] && cp $NAMEOUT.bbl $WHIZZYOUT.bbl
[ -f $NAMEOUT.ind ] && cp $NAMEOUT.ind $WHIZZYOUT.ind
[ -f $NAMEOUT.toc ] && cp $NAMEOUT.toc $WHIZZYOUT.toc

# process $WHIZZY$EXT is present. Will override $WHIZZYOUT.$DVI if it succeeds

if $NEWFILES; then preprocess && process; fi

# lauch the previewer(s) in background, storing its pid in $ID
# and putting a handler on its termination. 


rm -f "$TMP"/ID

if $MULTIPLE
then
   # we are going to launch $NAMEOUT.$VIEW as a secondary file
   [ -f $NAMEVIEW ] || cp $WHIZZYVIEW $NAMEVIEW
   CLIENTVIEW=$NAMEVIEW
else
   CLIENTVIEW=''
fi

(echo '# Begin Viewer command line (one argument per line)'; \
 echo "$VIEWCOMMAND"; echo "$WHIZZYVIEW"; echo "$CLIENTVIEW"; \
 echo '2>'"$OUTPUT"/view; \
 echo '# End of command' ) >> "$OUTPUT"/command


# Create a fifo and assign it to descriptor 3 in read-write mode.
rm -f "$INPUT/view.$$"
mkfifo "$INPUT/view.$$"
exec 3<>"$INPUT/view.$$"
rm "$INPUT/view.$$"

noviewer () {
  trap "" SIGUSR1 SIGUSR2 SIGCONT
  echo Starting...
  while true; do echo $$; sleep 10; done
  echo Done...
}

{
  $VIEWCOMMAND "$WHIZZYVIEW" "$CLIENTVIEW" <&3 2>"$OUTPUT"/view &
  ID=$!
  echo $ID > "$TMP"/ID
  echo $ID >> "$TMP"/pids
  wait $ID && quit || fatal 'Viewing process terminated abnormally'
  } &

sendcommand () {
    echo -n "$1" >&3 && kill -$SIGINPUT $ID \
        || fatal 'Previewer cannot receive commands' $SIG
}

sigreload () {
   kill -$SIG $ID || fatal 'Previewer is not responding to signal' $SIG
}

skimreload () {
    if [ $WSYNCTEX -a ! $WSYNCTEX -ot $WHIZZY$EXT ]
    then
        gunzip -c $WSYNCTEX | sed -e '2,2 s/_whizzy_//' | \
            gzip -c > $OUTPUT/$WSYNCTEX &&
            mv $OUTPUT/$WSYNCTEX $WSYNCTEX
    fi
}

xpdfreload () {
   case "$1" in cursor) 
       $VIEWCOMMAND $WHIZZYVIEW +Start-Document;;
   esac
   $VIEWCOMMAND -reload
}

kpdfreload () {
   case "$1" in cursor) 
       $VIEWCOMMAND "$WHIZZYVIEW#Start-Document" 2>/dev/null ;;
   esac
   $VIEWCOMMAND "$WHIZZYVIEW" 2>/dev/null
}

gpdfreload () {
   case "$1" in 
     cursor) 
       $VIEWCOMMAND --page-label=Start-Document "$WHIZZYVIEW" 2>/dev/null ;;
     *) $VIEWCOMMAND "$WHIZZYVIEW" 2>/dev/null
   esac
   wmctrl -R emacs@arbois
}

llppreload() {
  if [ -f ${WHIZZYOUT}.mark ]
  then
      echo reload >> $WREMOTE
      PAGE=$(cat ${WHIZZYOUT}.mark)
      PAGE=$(expr "$PAGE" : ".*page=\([0-9]*\);")
      PAGE=$(expr "$PAGE" - 1)
      echo "goto ${PAGE} 0 0" >> $WREMOTE
  else
      echo reload >> $WREMOTE
  fi
}


WINDOWID="unset"
# Require xwinfo and xdotool
mupdfreload () {
    kill -$SIG $ID || fatal 'Previewer is not responding to signal' $SIG
    case "$WINDOWID" in
        unset)
            WINDOWID=$(xwininfo -root -tree | grep "$NAME".wpdf)
            case /$WINDOWID/ in
                //) WINDOWID=none;;
                *) WINDOWID=$(expr "$WINDOWID" : " *\([^ ]*\) *");;
            esac
            ;;
    esac
    case "$WINDOWID" in
        unset|none) ;;
        *)
            if [ -f ${WHIZZY}.mark ]
            then
                PAGE=$(cat ${WHIZZY}.mark)
                PAGE=$(expr "$PAGE" : ".*page=\([0-9]*\);")
                xdotool type --window "$WINDOWID" "${PAGE}g" 2>/dev/null 
            fi
            ;;
    esac
}

wholereload () {
   if $MULTIPLE; then sigreload; fi
}


# Recompilation should run in batch, with a status
# recompilation=ok recompilation=ko recompilation=needed recompilation=on
# in file $(TMP)/recompilation 
whole () {
   echo '<Recompiling whole document>'
#    echo 'BEFORE: '$(stat -c 'inode:%i, time:%Z' $NAMEVIEW)
   if batchmarks </dev/null >"$LOG"
   then
      echo '<Whole document updated>'
#       echo 'AFTER: '$(stat -c 'inode:%i, time:%Z' $NAMEVIEW)
      if $1; then echo '<Pages and sections updated>'; fi
      if [ -f "$TMP"/DID ]
          then kill -$SIG $(cat "$TMP"/DID) || rm -f "$TMP"/DID
      fi
      true
   else
      echo '<Whole document recompilation failed>'
   fi
}
# So as to start immediately...
if $AUTOCOMPILE; then whole; fi

## Reformating

reformat () {
  echo '<Reformating>'
  touch -r $NAME$EXT $WHIZZY.$FMT
  if format 1>"$OUTPUT"/format 2>"$ERR"
  then
      mv -f $NAMEOUT.$FMT $WHIZZYOUT.$FMT
      echo '<Reformatting succeeded>'
      PROCESS=true
      # do the slice with the new format (quick)
      # was commented if why?
      process && $RELOAD $1
      if $AUTORECOMPILE; then whole; fi
  else
      echo '<Reformatting failed>'
      texlog format
      echo '<Continuing with the old format>'
  fi
}

## Duplex

duplex () {
  [ -f $NAMEVIEW ] || \
  { cp $WHIZZYVIEW $NAMEVIEW; 
    warning '(duplex) Using ' $WHIZZYVIEW ' instead of missing ' $NAMEVIEW
  }
  $VIEWCOMMAND $NAMEVIEW &
  echo $! > "$TMP"/DID
  echo $! >> "$TMP"/pids
}

if $DUPLEX; then duplex; fi

## wait for viewer, this is here, so luckily one does not need to wait

while [ ! -f "$TMP"/ID ];
do if [ -x /bin/usleep ]; then /bin/usleep 10; else /bin/sleep 1; fi; done
ID=$(cat "$TMP"/ID)



## The loop watching changes

# to be fixed
viewps () {
  slice=$1
  if $slice; then file=$WHIZZY; else file=$NAME; fi
  if [ -f "$file".wdvi ]
  then 
    ( $DVIPS -o "$file".ps $1 && gv "$TMP"/$1.ps ) >"$OUTPUT"/viewps 2>"$ERR" &
  else echo "$file.wdvi not found"
  fi
}

INITPHASE=false
RELOADARG=""

SWITCHED=false
kpdfswitch () {
  if $SWITCHED
  then
      SWITCHED=false
      $VIEWCOMMAND "$WHIZZYVIEW" 
  else
      SWITCHED=true
      $VIEWCOMMAND "$NAMEVIEW" 
  fi
}

llppswitch () {
  if $SWITCHED
  then
      SWITCHED=false
      echo "gotor \"$WHIZZY.$VIEW\"" >> $WREMOTE
  else
      SWITCHED=true
      echo "gotor \"$NAME.$VIEW\"" >> $WREMOTE
  fi
}

case $MODE in
    advi) SWITCH="sendcommand w" ;;
    kpdf) SWITCH=kpdfswitch ;;
    llpp) SWITCH=llppswitch ;;
    *)    SWITCH=true ;;
esac

echo '<Initialization succeeded, entering loop>'
while true
do
  if [ ! -d $WHIZZYDIR ]
  then fatal 'No more _whizzy_ directory'
################## Reformating now done from Emacs.
#    elif [ $WHIZZY.$FMT -ot $NAME$EXT ]
#    then reformat
  elif $NEWFILES && preprocess || $PROCESS
  then process && $RELOAD $RELOADARG
  else
     echo '<Waiting>'
     read $READOPTION COMMAND REST
     case "$COMMAND" in
         duplex) duplex ;;
         reload) $RELOAD ;;
       reformat) checkMKfile $REST; reformat $RELOAD ;;
       autorecompile)
         case $REST in
           on) AUTORECOMPILE=true;;
           off) AUTORECOMPILE=false;;
         esac;;
       viewer-command) 
         if $NAVIGATION && [ -n "$REST" ]; then sendcommand $REST; fi;;
       recompile) whole && wholereload ;;
       # maybe more should be removed.
       clear) rm -f $NAMEOUT.aux ;;
       whole) checkMKfile $REST; whole $DOMAKS && wholereload;;
       bibtex) makebibtex;;
       viewps-slice) viewps true;;
       viewps-whole) viewps false;;
       printenv) printenv;;
#       bash) bash -c "$REST";;
       help) help;;
       info) info;;
       rmaux) 
             rm ${WHIZZYOUT}.aux ${NAMEOUT}.aux ;;
       trace)
          case $REST in
              on) set -o xtrace; TRACE=true;; 
             off) set +o xtrace; TRACE=false;; 
          esac
          echo "<trace is $TRACE>"
          ;;
       exit) break ;;
       nextslice) RELOADARG="";;
       reslice) RELOADARG="$REST";;
       switch) $SWITCH ;;
       # nextslice) preprocess && process && $RELOAD ;;
       # reslice) preprocess && process && $RELOAD $REST;;
       "") ;;
       *) echo 'Command not understood' : "$COMMAND" ;;
     esac
  fi
done

cleanquit Exit

# whizzytex ends here
