% File: latex_comm.sl                            -*- mode: SLang -*-
%
% Copyright (c)
%       2006--2007  Jörg Sommer <[email protected]>
%       $Id: latex_comm.sl 199 2007-08-23 23:28:52Z joerg $
%
%       -*- This file is part of Jörg's LaTeX Mode (JLM) -*-
%
% Description:   The dvi viewer Xdvi can communicate with the editor to
%                move the cursor to the possition of the file that is
%                related to the paragraph currently shown.
%
%                This file implements the communication helper for xdvi.
%
% License: This program 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 of
%          the License, or (at your option) any later version.
%
%          This program 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.

% Fixme: This is ugly, but
%   jed-script foo -> __argv = ["foo"]
%   jed --script foo -> __argv = ["jed", "--script", "foo"]

_for(0, length(__argv), 1)
{
   $0 = ();
   if ( is_substr(__argv[$0], "latex_comm.sl") )
   {
       ++$0;
       break;
   }
}

variable args = __argv[[$0:]];

variable STDIN_FILENO = fileno(stdin);
variable STDOUT_FILENO = fileno(stdout);

if ( andelse {length(args) == 1} {args[0] == "watch"} )
{
   variable fifo_name = "/tmp/jed.latex." + string(getpid());

   if (mkfifo(fifo_name, 0600) != 0)
     throw ApplicationError, "Could not create FIFO";

   () = write(STDOUT_FILENO, "communicator created: $fifo_name\n"$);

#ifexists SIGHUP
   variable quit = 0;
   eval("define sig_handler(sig) { quit = 1; }");
   signal(SIGHUP, __get_reference("sig_handler") );
   signal(SIGINT, __get_reference("sig_handler") );
   signal(SIGTERM, __get_reference("sig_handler") );

# iffalse
   % slang 2.0 has a bug---signal is set to restart system calls.
   % However, once a signal is caught, the signal will be set to
   % interrupt them, which is the correct behavior for the interpreter.
   % Force that here.
   () = kill(getpid(), SIGHUP);
   () = kill(getpid(), SIGINT);
   () = kill(getpid(), SIGTERM);
   quit = 0;
# endif
#endif

   try
   {
       forever
       {
           variable fifo = open(fifo_name, O_RDONLY);
           if (fifo == NULL)
             break;
#ifexists quit
           if (quit)
           {
               () = close(fifo);
               break;
           }
#endif
           try
           {
               variable line, last_line;
               while (read(fifo, &line, 128) > 0)
               {
                   () = write(STDOUT_FILENO, line);
                   last_line = line;
               }

               if (andelse {bstrlen(last_line) >= 5}
                    {last_line[[-5:-1]] == "quit\n"B})
                 break;
           }
           finally
             () = close(fifo);
       }
   }
   finally
     () = remove(fifo_name);
}
else
{
   if (length(args) < 2)
     throw NumArgsError, "missing arguments";

   variable stat = stat_file(args[0]);
   !if ( andelse {stat != NULL} {stat_is("fifo", stat.st_mode)} )
     throw InvalidParmError, "File "+args[0]+" do not exist or is not a FIFO";

   variable fifo = open(args[0], O_WRONLY);
   try
   {
       () = write(fifo, strjoin(args[[1:]], " ") + "\n");
   }
   finally
     () = close(fifo);
}