]> git.lyx.org Git - features.git/commitdiff
- Backported the HTML export feature (Jean-Marc, can configure
authorAsger Ottar Alstrup <alstrup@lyx.org>
Tue, 12 Oct 1999 21:37:10 +0000 (21:37 +0000)
committerAsger Ottar Alstrup <alstrup@lyx.org>
Tue, 12 Oct 1999 21:37:10 +0000 (21:37 +0000)
  check for "tth"?)
- Cleaned up the systemcall stuff a bit
- Better documentation for support/FileInfo.h

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@188 a592a061-630c-0410-9148-cb99ea01b6c8

25 files changed:
CHANGES
ChangeLog
lib/bind/de_menus.bind
lib/bind/fr_menus.bind
lib/bind/hu_menus.bind
lib/bind/menus.bind
lib/bind/pt_menus.bind
lib/bind/sv_menus.bind
lib/lyxrc.example
src/Chktex.C
src/ImportLaTeX.C
src/ImportNoweb.C
src/LaTeX.C
src/Literate.C
src/lyx_cb.C
src/lyxfunc.C
src/lyxrc.h
src/lyxvc.C
src/menus.C
src/support/FileInfo.h
src/support/syscall.C
src/support/syscall.h
src/support/syscontr.C
src/support/syscontr.h
src/support/syssingleton.C

diff --git a/CHANGES b/CHANGES
index 59abf348b9905172f58a2b26986c213c9054ca89..03f5ad47da0158d9679ef82c65f7c50290aca71c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+since 1.0.4
+- New feature: "File->Export->As HTML..." using tth (Asger)
+
 since 1.0.4pre8
 - small fix to qoutes in DocBook. (Jose)
 - blurb about DocBook in LaTeXConfig (Jose)
index d7a0c937352f34aaebbc8b329480557390b7ae2d..f8f15495cb6c905f08b1b800c4da5536a1594ea6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+1999-10-12  Asger Alstrup Nielsen  <alstrup@alstrup.galaxy.dk>
+
+       * src/sys*: Cleaned up the Systemcall stuff a bit. Added "kill(int)"
+         method to the SystemCall class which can kill a process, but it's
+         not fully implemented yet.
+
+       * src/*.C: Changed Systemcalls::Startscript() to startscript()
+
+       * src/support/FileInfo.h: Better documentation  
+
+       * src/lyxfunc.C: Added support for buffer-export html
+       
+       * src/menus.C: Added Export->As HTML...
+       
+       * lib/bind/*.bind: Added short-cut for buffer-export html
+
+       * src/lyxrc.*: Added support for new \tth_command
+       
+       * lib/lyxrc.example: Added stuff for new \tth_command
+
 1999-10-12  Lars Gullik Bjønnes  <larsbj@lyx.org>
 
        * src/LaTeX.C: some no-op changes moved declaration of some
index cb494e8f85c594ca27409bb989ac514d4433e08b..b342246e0dc67fc99078a8167fac3c6a70ed9553 100644 (file)
@@ -66,6 +66,7 @@
 \bind "M-d e p"                 "buffer-export postscript"
 \bind "M-d e l"                        "buffer-export linuxdoc"
 \bind "M-d e t"                        "buffer-export ascii"
+\bind "M-d e h"                        "buffer-export html"
 \bind "M-d e b"                        "buffer-export custom"
 \bind "M-d b"                  "lyx-quit"
 \bind "M-d space"              "menu-open Datei" 
index 44d73ca0bc96a1326fba04cd93be29dc16c6f216..352f04aeeb1be09a9db95b877a0a4638344ae3ff 100644 (file)
@@ -49,6 +49,7 @@
 \bind "M-f x d"                        "buffer-export dvi"
 \bind "M-f x p"                        "buffer-export postscript"
 \bind "M-f x a"                        "buffer-export ascii"
+\bind "M-f x h"                        "buffer-export html"
 \bind "M-f x s"                        "buffer-export custom"
 \bind "M-f q"                  "lyx-quit"
 \bind "M-f space"              "menu-open Fichier" 
index 707bf27704878668f7f8de1bfc399ba4c23c957c..b393f434e81451e4613ef708eeddb8d0e7e53a91 100644 (file)
@@ -44,6 +44,7 @@
 \bind "M-f l"                  "buffer-export latex"
 \bind "M-f u"                  "buffer-export linuxdoc"
 \bind "M-f c"                  "buffer-export ascii"
+\bind "M-f h"                  "buffer-export html"
 \bind "M-f s"                  "buffer-export custom"
 \bind "M-f k"                  "lyx-quit"
 \bind "M-f x"                  "lyx-quit"
index 710ffb40e75301de3a146dde060e39dad55050ba..a6fe6a531094e19e7c0052f8f53084e4898d1544 100644 (file)
@@ -48,6 +48,7 @@
 \bind "M-f e p"                 "buffer-export postscript"
 \bind "M-f e d"                 "buffer-export linuxdoc"
 \bind "M-f e t"                 "buffer-export ascii"
+\bind "M-f e h"                        "buffer-export html"
 \bind "M-f e m"                 "buffer-export custom"
 \bind "M-f x"                  "lyx-quit"
 \bind "M-f space"              "menu-open File" 
index ca7695441ea6e4568110f037f0bee9026fa0d0d2..271699285ab85a1222a03a731c59b00624738c7a 100644 (file)
@@ -51,6 +51,7 @@
 \bind "M-a e p"                 "buffer-export postscript"
 \bind "M-a e d"                 "buffer-export linuxdoc"
 \bind "M-a e t"                 "buffer-export ascii"
+\bind "M-a e h"                        "buffer-export html"
 \bind "M-a e m"                 "buffer-export custom"
 \bind "M-a s"                  "lyx-quit"
 \bind "M-a space"              "menu-open Arquivo" 
index ecfd94f5d4b0445eaae2572dee96c23d9209f9cd..91d97db4976514185ba349767ae7f3a92a72e3f1 100644 (file)
@@ -53,6 +53,7 @@
 \bind "M-f l"                  "buffer-export latex"
 \bind "M-f x"                  "buffer-export linuxdoc"
 \bind "M-f S-T"                "buffer-export ascii"
+\bind "M-f h"                  "buffer-export html"
 \bind "M-f S-A"                "buffer-export custom"
 \bind "M-f a"                  "lyx-quit"
 \bind "M-f space"              "menu-open Fil" 
index ac0ff7ee75469d26f7e2065cbc6c0f18affe82cf..95f1eeae2f02d627d4cc1251d7fbdcb05bb5c15f 100644 (file)
 # Example: use this to ignore warnings about using "\ldots" instead of "..."
 #\chktex_command "chktex -n11 -n1 -n3 -n6 -n9 -22 -n25 -n30 -n38"
 
+# Define which program to use to run "tth", the LaTeX to HTML converter
+# You should include options. The default is "tth -t"
+# Example: use this to let math be italic
+#\tth_command "tth -t -i"
+
 # If you want to pass extra flags to the LinuxDoc sgml scripts, insert them
 # here. 
 # Example: the next line activates iso-latin1 support:
index 707b0cdc0c500ed7638d5cc9b09b914ddb7dbaff..a9925def5d69eb211a88bff0c8f3a1cce786d10c 100644 (file)
@@ -46,7 +46,7 @@ int Chktex::run(TeXErrors &terr)
        string log = ChangeExtension(file, ".log", true);
        string tmp = cmd + " -q -v0 -b0 -x " + file + " -o " + log;
         Systemcalls one;
-       int result= one.Startscript(Systemcalls::System, tmp);
+       int result= one.startscript(Systemcalls::System, tmp);
        if (result == 0) {
                result = scanLogFile(terr);
        } else {
index cddd0d75e51354388d9501537675867a41aaea95..0a38e96c3ce75164881d4f77960e9b52548f67b1 100644 (file)
@@ -42,7 +42,7 @@ Buffer * ImportLaTeX::run()
        string tmp = lyxrc->relyx_command + " -f " + file;
         Systemcalls one;
        Buffer * buf = 0;
-       int result= one.Startscript(Systemcalls::System, tmp);
+       int result= one.startscript(Systemcalls::System, tmp);
        if (result==0) {
                string filename = ChangeExtension(file, ".lyx", false);
                // File was generated without problems. Load it.
index f366387a4ddd289c19cee57173fcb5f52f9c59c1..66071111e375ec7d461dff9ba74c765557559d05 100644 (file)
@@ -37,7 +37,7 @@ Buffer * ImportNoweb::run()
                                        documentclass() + " -f " + file;
         Systemcalls one;
        Buffer * buf = 0;
-       int result= one.Startscript(Systemcalls::System, tmp);
+       int result= one.startscript(Systemcalls::System, tmp);
        if (result==0) {
                string filename = file + ".lyx";
                // File was generated without problems. Load it.
index a4999fa2707b52ead0f720cd6da8b5d3cf236e88..0c8318d91b32cc7bf0672b8b3d2b148bb966273e 100644 (file)
@@ -425,7 +425,7 @@ int LaTeX::operator()()
        string tmp = cmd + ' ' + file + " > nul";
 #endif
         Systemcalls one;
-       return one.Startscript(Systemcalls::System, tmp);
+       return one.startscript(Systemcalls::System, tmp);
 }
 
 
@@ -442,7 +442,7 @@ bool LaTeX::runMakeIndex(string const &file)
        string tmp = "makeindex -c -q ";
        tmp += file;
        Systemcalls one;
-       one.Startscript(Systemcalls::System, tmp);
+       one.startscript(Systemcalls::System, tmp);
        return true;
 }
 
@@ -468,7 +468,7 @@ bool LaTeX::runBibTeX(string const &file)
                        string tmp="bibtex ";
                        tmp += ChangeExtension(file, string(), true);
                        Systemcalls one;
-                       one.Startscript(Systemcalls::System, tmp);
+                       one.startscript(Systemcalls::System, tmp);
                        return true;
                }
                
index 28e2f886abf51bc0d84bd0e116498e1cf46b4227..74339838ec15ee3d83f26c20b9baf2aae651af18 100644 (file)
@@ -63,8 +63,8 @@ int Literate::weave(TeXErrors &terr, MiniBuffer *minib)
         //
         tmp1 = literate_cmd + " < " + litfile + " > " + file + " 2> " + litfile + ".out";
         tmp2 = literate_filter + " < " + litfile + ".out" + " > " + litfile + ".log";
-        ret1 = one.Startscript(Systemcalls::System, tmp1);
-        ret2 = two.Startscript(Systemcalls::System, tmp2);
+        ret1 = one.startscript(Systemcalls::System, tmp1);
+        ret2 = two.startscript(Systemcalls::System, tmp2);
         lyxerr.debug() << "LITERATE {" << tmp1 << "} {" << tmp2 << "}" << endl;
        scanres = scanLiterateLogFile(terr);
        if (scanres & Literate::ERRORS) return scanres; // return on literate error
@@ -96,8 +96,8 @@ int Literate::build(TeXErrors &terr, MiniBuffer *minib)
         //
         tmp1 = build_cmd + ' ' + litfile + " > " + litfile + ".out 2>&1";
         tmp2 = build_filter + " < " + litfile + ".out" + " > " + litfile + ".log";
-        ret1 = one.Startscript(Systemcalls::System, tmp1);
-        ret2 = two.Startscript(Systemcalls::System, tmp2);
+        ret1 = one.startscript(Systemcalls::System, tmp1);
+        ret2 = two.startscript(Systemcalls::System, tmp2);
         scanres = scanBuildLogFile(terr);
         lyxerr[Debug::LATEX] << "Done." << endl;
 
index 8b9c11a6cbedeeb6cd3cf134fe0be0b2551e0f53..4e9e78d556dd2058619d9f566d9d0b2aab07405d 100644 (file)
@@ -616,10 +616,10 @@ bool RunScript(Buffer *buffer, bool wait,
 #warning What should we do here?
 #endif         
                minibuffer->Set(_("Executing command:"), cmd);
-               result = one.Startscript(Systemcalls::System, cmd);
+               result = one.startscript(Systemcalls::System, cmd);
        } else {
                minibuffer->Set(_("Executing command:"), cmd);
-               result = one.Startscript(wait ? Systemcalls::Wait
+               result = one.startscript(wait ? Systemcalls::Wait
                                        : Systemcalls::DontWait, cmd);
        }
        PathPop();
@@ -1277,21 +1277,21 @@ int RunLinuxDoc(int flag, string const & filename)
                                MakeDisplayPath(filename), "'...");
                s2 = "sgml2lyx " + lyxrc->sgml_extra_options + ' ' 
                        + name;
-               if (one.Startscript(Systemcalls::System, s2)) 
+               if (one.startscript(Systemcalls::System, s2)) 
                        errorcode = 1;
                break;
        case 0: /* TeX output asked */
                minibuffer->Set(_("Converting LinuxDoc SGML to TeX file..."));
                s2 = "sgml2latex " + add_flags + " -o tex "
                        + lyxrc->sgml_extra_options + ' ' + name;
-               if (one.Startscript(Systemcalls::System, s2)) 
+               if (one.startscript(Systemcalls::System, s2)) 
                        errorcode = 1;
                break;
        case 1: /* dvi output asked */
                minibuffer->Set(_("Converting LinuxDoc SGML to dvi file..."));
                s2 = "sgml2latex " + add_flags + " -o dvi "
                        + lyxrc->sgml_extra_options + ' ' + name;
-               if (one.Startscript(Systemcalls::System, s2)) {
+               if (one.startscript(Systemcalls::System, s2)) {
                        errorcode = 1;
                } else
                        current_view->currentBuffer()->markDviClean();
@@ -1348,7 +1348,7 @@ int RunDocBook(int flag, string const & filename)
        case 1: /* dvi output asked */
                minibuffer->Set(_("Converting DocBook SGML to dvi file..."));
                s2 = "sgmltools --backend dvi " + name;
-               if (one.Startscript(Systemcalls::System, s2)) {
+               if (one.startscript(Systemcalls::System, s2)) {
                        errorcode = 1;
                } else
                        current_view->currentBuffer()->markDviClean();
index 3b9897713f86dec957bfd541d38b4cccc979ab6f..78db42d0cf3eec5f5eb96a03e366fdf85e223b81 100644 (file)
@@ -58,6 +58,7 @@
 #include "trans_mgr.h"
 #include "ImportLaTeX.h"
 #include "ImportNoweb.h"
+#include "support/syscall.h"
 
 extern bool cursor_follows_scrollbar;
 
@@ -730,6 +731,27 @@ string LyXFunc::Dispatch(int ac,
                        MenuSendto();
                        break;
                }
+               // HTML
+               else if (extyp == "html") {
+                       // First, create LaTeX file
+                       MenuMakeLaTeX(owner->currentBuffer());
+
+                       // And now, run tth
+                       string file = owner->currentBuffer()->getFileName();
+                       file = ChangeExtension(file, ".tex", false);
+                       string result = ChangeExtension(file, ".html", false);
+                       string tmp = lyxrc->tth_command + " < " + file 
+                           + " > " + result ;
+                       Systemcalls one;
+                       int res = one.startscript(Systemcalls::System, tmp);
+                       if (res == 0) {
+                               setMessage(string(
+                                 N_("Document exported as HTML to file: ")) + result);
+                       } else {
+                               setErrorMessage(string(
+                                 N_("An unexpected error occured while converting document to HTML in file:")) + result);
+                       }
+               }
                else {
                        setErrorMessage(string(N_("Unknown export type: "))
                                        + extyp);
index df453839629caed0fe186c1acc9742d5cbfe930e..e3147cfb9008aac2e25c53193be66352aec653e1 100644 (file)
@@ -98,6 +98,8 @@ public:
         LYX_PAPER_SIZE default_papersize;
        /// command to run chktex incl. options
        string chktex_command;
+       /// command to run tth incl. options
+       string tth_command;
        ///
        string sgml_extra_options;
        ///
index f1430b693c6ec9f60255a39f0000a1d8b6384ea2..70f361c3be053a04daf732442823b3e79ae3c927 100644 (file)
@@ -386,7 +386,7 @@ int LyXVC::doVCCommand(string const & cmd)
        lyxerr[Debug::LYXVC] << "doVCCommand: " << cmd << endl;
         Systemcalls one;
        PathPush(_owner->filepath);
-       int ret = one.Startscript(Systemcalls::System, cmd);
+       int ret = one.startscript(Systemcalls::System, cmd);
        PathPop();
        return ret;
 }
index f582e2185f6d86f362fb4a6f4b960370cb744f15..3cbf155a69c3c081a55bab91770a69518fd8a744 100644 (file)
@@ -423,7 +423,8 @@ void Menus::ShowFileMenu(FL_OBJECT *ob, long)
                                        "|as DVI...%x41"
                                        "|as PostScript...%x42"
                                        "|as Ascii Text...%x43"
-                                       "|Custom...%x44"));
+                                       "|as HTML...%x44"
+                                       "|Custom...%x45"));
         else if(LinuxDoc)
             SubFileExport=fl_defpup(FL_ObjWin(ob),
                                      _("Export%t"
@@ -443,7 +444,10 @@ void Menus::ShowFileMenu(FL_OBJECT *ob, long)
        fl_setpup_shortcut(SubFileExport, 41, scex(_("FEX|Dd#d#D")));
        fl_setpup_shortcut(SubFileExport, 42, scex(_("FEX|Pp#p#P")));
        fl_setpup_shortcut(SubFileExport, 43, scex(_("FEX|Tt#t#T")));
-       fl_setpup_shortcut(SubFileExport, 44, scex(_("FEX|mM#m#M")));
+       if (!LinuxDoc && !DocBook) {
+               fl_setpup_shortcut(SubFileExport, 44, scex(_("FEX|Hh#h#H")));
+               fl_setpup_shortcut(SubFileExport, 45, scex(_("FEX|mM#m#M")));
+       }
        
        int FileMenu = fl_defpup(FL_ObjWin(ob),
                                 _("New..."
@@ -592,7 +596,9 @@ void Menus::ShowFileMenu(FL_OBJECT *ob, long)
                break;
        case 43: tmpfunc->Dispatch(LFUN_EXPORT, "ascii");
                break;
-       case 44: tmpfunc->Dispatch(LFUN_EXPORT, "custom"); 
+       case 44: tmpfunc->Dispatch(LFUN_EXPORT, "html");
+               break;
+       case 45: tmpfunc->Dispatch(LFUN_EXPORT, "custom"); 
                break;
        case 17: tmpfunc->Dispatch(LFUN_QUIT); break;
                // Lastfiles:
index 69ea2a361606fb704e7a8917c15e471b0b9cf558..4eeea35899059191df5f64261a7b0cc15e85bd5a 100644 (file)
@@ -31,28 +31,28 @@ public:
        the file that is obtained by tracing the links. */
        FileInfo(string const & path, bool link = false);
 
-       ///
+       /// File descriptor
        FileInfo(int fildes);
 
        ///
        ~FileInfo();
 
-       ///
+       /// Query a new file
        FileInfo& newFile(string const & path, bool link = false);
 
-       ///
+       /// Query a new file descriptor
         FileInfo& newFile(int fildes);
        
-       /// returns a character describing file type (ls -F)
+       /// Returns a character describing file type (ls -F)
        char const * typeIndicator() const;
 
-       ///
+       /// File protection mode
        mode_t getMode() const;
 
-       ///
+       /// Get "preferred" block size for efficient file system I/O
        long getBlockSize() const;
        
-       /// constructs standard mode string (ls style)
+       /// Constructs standard mode string (ls style)
        void modeString(char * szString) const;
        
        /// returns a letter describing a file type (ls style)
@@ -73,34 +73,37 @@ public:
        ///
        time_t getStatusChangeTime() const;
 
-       ///
+       /// Total file size in bytes
        off_t getSize() const;
 
-       ///
+       /// Number of hard links
        nlink_t getNumberOfLinks() const;
 
-       ///
+       /// User ID of owner
        uid_t getUid() const;
-       ///
+
+       /// Group ID of owner
        gid_t getGid() const;
-       ///
+
+       /// Is the file information correct? Did the query succeed?
        bool isOK() const;
-       ///
+
+       /// Permission flags
        enum perm_test {
                rperm = R_OK, // test for read permission
                wperm = W_OK, // test for write permission
                xperm = X_OK, // test for execute (search) permission
                eperm = F_OK  // test for existence of file
        };
-       ///
+       /// Test whether the current user has a given set of permissions
        bool access(int p);
-       ///
+       /// Is the file writable for the current user?
        bool writable() { return access(FileInfo::wperm); }
-       ///
+       /// Is the file readable for the current user?
        bool readable() { return access(FileInfo::rperm); }
-       ///
+       /// Is the file executable for the current user?
        bool executable() { return access(FileInfo::xperm); }
-       ///
+       /// Does the file exist?
        bool exist() { return access(FileInfo::eperm); }
        ///
        bool isLink() const;
@@ -139,4 +142,3 @@ private:
 };
 
 #endif
-
index e30722459f6b7a47aad7cf88e612d766454200db..c5c99eadead36a5b089b2d9fedcefef51a35e616 100644 (file)
 #pragma implementation
 #endif
 
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <signal.h>
 #include <cstdlib>
 #include <cstdio>
-#include "debug.h"
 #include <unistd.h>
+#include "debug.h"
 #include "syscall.h"
 #include "syscontr.h"
 #include "support/lstrings.h"
 
-//----------------------------------------------------------------------
-// Class, which controlls a system-call
-//----------------------------------------------------------------------
-
-// constructor
-Systemcalls::Systemcalls()
-{
-       pid = (pid_t) 0; // yet no child
+Systemcalls::Systemcalls() {
+       pid = (pid_t) 0; // No child yet
 }
 
-// constructor
-// 
-// starts child
-Systemcalls::Systemcalls(Starttype how, string what, Callbackfct cback)
+Systemcalls::Systemcalls(Starttype how, string const & what, Callbackfct cback)
 {
        start   = how;
        command = what;
        cbk     = cback;
-       pid     = (pid_t) 0; // no child yet
+       pid     = (pid_t) 0;
        retval  = 0;
-       Startscript();
+       startscript();
 }
 
-// destructor
-// not yet implemented (?)
-Systemcalls::~Systemcalls()
-{
+Systemcalls::~Systemcalls() {
+#if 0
+       // If the child is alive, we have to brutally kill it
+       if (getpid() != 0) {
+               ::kill(getpid(), SIGKILL);
+       }
+#endif
 }
 
 // Start a childprocess
 // 
 // if child runs in background, add information to global controller.
 
-int Systemcalls::Startscript()
-{
+int Systemcalls::startscript() {
        retval = 0;
        switch (start) {
        case System: 
                retval = system(command.c_str());
-               Callback();
+               callback();
                break;
        case Wait:   
-               pid = Fork();
+               pid = fork();
                if (pid>0) { // Fork succesful. Wait for child
                        waitForChild();
-                       Callback();
+                       callback();
                } else
                        retval = 1;
                break;
        case DontWait:
-               pid=Fork();
+               pid = fork();
                if (pid>0) {
                        // Now integrate into Controller
                        SystemcallsSingletoncontroller::Startcontroller starter;
-                       SystemcallsSingletoncontroller *contr=
-                               starter.GetController();
-                       // Add this to contr
-                       contr->AddCall(*this);
+                       SystemcallsSingletoncontroller * contr = starter.getController();
+                       // Add this to controller
+                       contr->addCall(*this);
                } else
                        retval = 1;
                break;
-               //default:  // error();
-               //break;
        }
        return retval;
 }
 
+void Systemcalls::kill(int tolerance) {
+       if (getpid() == 0) {
+               lyxerr << "LyX: Can't kill non-existing process." << endl;
+               return;
+       }
+       int ret = ::kill(getpid(), SIGHUP);
+       bool wait_for_death = true;
+       if (ret != 0) {
+               if (errno == ESRCH) {
+                       // The process is already dead!
+                       wait_for_death = false;
+               } else {
+                       // Something is rotten - maybe we lost permissions?
+               }
+       }
+       if (wait_for_death) {
+               // Here, we should add the PID to a list of
+               // waiting processes to kill if they are not
+               // dead without tolerance seconds
+#warning Implement this using the timer of the singleton systemcontroller (Asger)
+       }
+}
+
 
 // Wait for child process to finish. Returns returncode from child.
-void Systemcalls::waitForChild()
-{
+void Systemcalls::waitForChild() {
        // We'll pretend that the child returns 1 on all errorconditions.
        retval = 1;
        int status;
@@ -92,7 +106,7 @@ void Systemcalls::waitForChild()
        while (wait) {
                pid_t waitrpid = waitpid(pid, &status, WUNTRACED);
                if (waitrpid == -1) {
-                       perror("LyX: Error waiting for child");
+                       lyxerr << "LyX: Error waiting for child:" << strerror(errno) << endl;
                        wait = false;
                } else if (WIFEXITED(status)) {
                        // Child exited normally. Update return value.
@@ -100,18 +114,17 @@ void Systemcalls::waitForChild()
                        wait = false;
                } else if (WIFSIGNALED(status)) {
                        lyxerr << "LyX: Child didn't catch signal "
-                              << WTERMSIG(status)
-                              <<and died. Too bad." << endl;
+                              << WTERMSIG(status) 
+                              << "and died. Too bad." << endl;
                        wait = false;
                } else if (WIFSTOPPED(status)) {
-                       lyxerr << "LyX: Child (pid: " << pid
+                       lyxerr << "LyX: Child (pid: " << pid 
                               << ") stopped on signal "
-                              << WSTOPSIG(status)
+                              << WSTOPSIG(status) 
                               << ". Waiting for child to finish." << endl;
                } else {
                        lyxerr << "LyX: Something rotten happened while "
-                               "waiting for child "
-                              << pid << endl;
+                               "waiting for child " << pid << endl;
                        wait = false;
                }
        }
@@ -120,9 +133,9 @@ void Systemcalls::waitForChild()
 
 // generate child in background
 
-pid_t Systemcalls::Fork()
+pid_t Systemcalls::fork()
 {
-       pid_t cpid=fork();
+       pid_t cpid= ::fork();
        if (cpid == 0) { // child
                string childcommand(command); // copy
                string rest = split(command, childcommand, ' ');
@@ -130,7 +143,7 @@ pid_t Systemcalls::Fork()
                char *syscmd = 0; 
                char *argv[MAX_ARGV];
                int  index = 0;
-               bool Abbruch;
+               bool more;
                do {
                        if (syscmd == 0) {
                                syscmd = new char[childcommand.length() + 1];
@@ -142,17 +155,17 @@ pid_t Systemcalls::Fork()
                        tmp[childcommand.length()] = '\0';
                        argv[index++] = tmp;
                        // reinit
-                       Abbruch = !rest.empty();
-                       if (Abbruch
+                       more = !rest.empty();
+                       if (more
                                rest = split(rest, childcommand, ' ');
-               } while (Abbruch);
+               } while (more);
                argv[index] = 0;
                // replace by command. Expand using PATH-environment-var.
                execvp(syscmd, argv);
                // If something goes wrong, we end up here:
-               perror("LyX: execvp failed");
+               lyxerr << "LyX: execvp failed: " << strerror(errno) << endl;
        } else if (cpid < 0) { // error
-               perror("LyX: Could not fork");
+               lyxerr << "LyX: Could not fork: " << strerror(errno) << endl;
        } else { // parent
                return cpid;
        }
@@ -162,14 +175,15 @@ pid_t Systemcalls::Fork()
 
 // Reuse of instance
 
-int Systemcalls::Startscript(Starttype how, string what, Callbackfct cback)
+int Systemcalls::startscript(Starttype how, string const & what, 
+                            Callbackfct cback)
 {
        start   = how;
        command = what;
        cbk     = cback;
        pid     = (pid_t) 0; // yet no child
        retval  = 0;
-        return Startscript();
+        return startscript();
 }
 
 
index 37617279a7026c48afd17b74b4df2f9063a1d8e5..11c28fc58de935829d950730879bf511c9340864 100644 (file)
 // -*- C++ -*-
 #include <sys/types.h>
-#include <LString.h>
+
+#include "LString.h"
 
 #ifdef __GNUG__
 #pragma interface
 #endif
 
+/**
+  This class can be used to start child processes.
 
-/*@Doc:
-  Instance starts and represents childprocesses.
+  An instance of the class represents a child process.
   You should use this class if you need to start an external program in LyX.
-  You can start a child in the background and have a callback function
-  executed when the child finishes by using the DontWait starttype.
+  If you wish, you can have a callback function executed when the process
+  finishes.
+  You can chose between three kinds of child processes:
+  1) System processes, which are initiated with the "system" call,
+     where the main thread waits for the system call to return.
+  2) Wait for child process, which are forked, but the main thread waits for
+     the child to end.
+  3) Don't wait, which are forked, but the main thread is not stopped.
+     The process can be considered a background process.
+     A timer will make sure that any callback function is called when
+     the child process ends.
+
+  Notice that any callback associated with a process is called whatever
+  the kind of child process.
   */
 class Systemcalls {
 public:
        ///
        enum Starttype {
-               System,
-               Wait,
-               DontWait
+               System, // Uses system() which uses /bin/sh
+               Wait, // Uses fork() and execvp()
+               DontWait // Uses fork() and execvp()
        };
        
-       /// Callback function gets commandline and returnvalue from child
+       /// Callback function gets commandline and return value from child
        typedef void (*Callbackfct)(string cmd, int retval);
        
        ///
        Systemcalls();
        
-       /** Geberate instance and start childprocess 
+       /** Generate instance and start child process.
          The string "what" contains a commandline with arguments separated 
          by spaces.
          When the requested program finishes, the callback-function is 
-         called with the commandline and the returnvalue from the program.
-         The instance is automatically added to a timercheck if starttype is
-         DontWait (i.e. background execution). When a background child
-         finishes, the timercheck will automatically call the callback
+         called with the commandline and the return value from the program.
+         The instance is automatically added to a timer check if starttype 
+         is DontWait (i.e. background execution). When a background child
+         finishes, the timer check will automatically call the callback
          function.
          */
-       Systemcalls(Starttype how, string what, Callbackfct call = 0);
-       
+       Systemcalls(Starttype how, string const & what, Callbackfct call = 0);
        
        ///
        ~Systemcalls();
        
-       /** Start childprocess. what contains a command on systemlevel. 
+       /** Start childprocess. "what" contains a command at system level.
+        * This is for reuse of the Systemcalls instance.
         */
-       int Startscript(Starttype how, string what, Callbackfct call = 0); // for reuse
+       int startscript(Starttype how, string const & what, 
+                       Callbackfct call = 0);
        
        /** gets PID of childprocess. Used by timer */
-       inline pid_t Getpid() { return pid; }
+       pid_t getpid() { return pid; }
        
        /// Start callback
-       inline void Callback() { if (cbk) cbk(command, retval); }
-       
+       void callback() { if (cbk) cbk(command, retval); }
+
        /** Set return value. Used by timer */
-       inline void setRetValue(int r) { retval = r; }
+       void setRetValue(int r) { retval = r; }
+
+       /** Kill child prematurely.
+       First, a SIGHUP is sent to the child.
+       If that does not end the child process within "tolerance"
+       seconds, the SIGKILL signal is sent to the child.
+       When the child is dead, the callback is called.
+       */
+       void kill(int tolerance = 5);
 private:
        /// Type of execution: system, wait for child or background
-       Starttype    start;
+       Starttype start;
+
        /// Callback function
-       Callbackfct  cbk;
+       Callbackfct cbk;
+
        /// Commmand line
-       string      command;
+       string command;
+
        /// Process ID of child
-       pid_t        pid;
+       pid_t pid;
+
        /// Return value from child
        int retval;
        
        ///
-       int Startscript();
+       int startscript();
        
        ///
-       pid_t Fork();
+       pid_t fork();
        
        /// Wait for child process to finish. Updates returncode from child.
        void waitForChild();
index 8c0bc960c9b17196193aded0335203322d732ca3..51c903a2e0c29a7845242f628107842820360118 100644 (file)
@@ -1,62 +1,59 @@
 #include <config.h>
 
+#include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/wait.h>
 #include "syscontr.h"
 #include "syscall.h"
+#include "debug.h"
 
 #ifdef __GNUG__
 #pragma implementation
 #endif
 
-//----------------------------------------------------------------------
-// Controller-Implementation
-//----------------------------------------------------------------------
 
 //
-// default contstructor
+// Default constructor
 //
 
 SystemcallsSingletoncontroller::SystemcallsSingletoncontroller() 
 {
-       SysCalls = 0;
+       sysCalls = 0;
 }
 
 //
-// destructor
+// Destructor
 // 
 // destroy structs for leaving program
-// open question: should we stop here childs?
+// open question: should we stop childs here?
 // Asger says no: I like to have my xdvi open after closing LyX. Maybe
 // I want to print or something.
 
 SystemcallsSingletoncontroller::~SystemcallsSingletoncontroller()
 {
        ControlledCalls *next;
-       while (SysCalls)
+       while (sysCalls)
        {
-               next = SysCalls->next;
-               delete SysCalls;
-               SysCalls = next;
+               next = sysCalls->next;
+               delete sysCalls;
+              sysCalls = next;
        }
        
 }
 
 //
-// Add childprocessinformation into controlled list
+// Add child process information into controlled list
 //
 
 void 
-SystemcallsSingletoncontroller::AddCall(Systemcalls const &newcall)
-{
-// not yet implemented
-       ControlledCalls *newCall = new ControlledCalls;
+SystemcallsSingletoncontroller::addCall(Systemcalls const &newcall) {
+       ControlledCalls * newCall = new ControlledCalls;
        if (newCall == 0) // sorry, no idea
                return;
-       newCall->next = SysCalls;
+       newCall->next = sysCalls;
        newCall->call = new Systemcalls(newcall);
-       SysCalls = newCall;
+       sysCalls = newCall;
 }
 
 // 
@@ -66,33 +63,43 @@ SystemcallsSingletoncontroller::AddCall(Systemcalls const &newcall)
 //
 
 void 
-SystemcallsSingletoncontroller::Timer()
-{
+SystemcallsSingletoncontroller::timer() {
        // check each entry of our list, if it's finished
         ControlledCalls *prev = 0;
-       for (ControlledCalls *actCall=SysCalls; actCall; actCall=actCall->next) 
-               {
-                       pid_t pid=actCall->call->Getpid();
-                       int stat_loc;
-                       waitpid(pid, &stat_loc, WNOHANG);
-                       if (WIFEXITED(stat_loc) || WIFSIGNALED(stat_loc)) {
+       for (ControlledCalls *actCall=sysCalls; actCall; actCall=actCall->next)
+       {
+               pid_t pid=actCall->call->getpid();
+               int stat_loc;
+               int waitrpid = waitpid(pid, &stat_loc, WNOHANG);
+               if (waitrpid == -1) {
+                       lyxerr << "LyX: Error waiting for child:" 
+                              << strerror(errno) << endl;
+               } else if (WIFEXITED(stat_loc) || WIFSIGNALED(stat_loc)) {
+                       if (WIFEXITED(stat_loc)) {
                                // Ok, the return value goes into retval.
-                               if (WIFEXITED(stat_loc)) {
-                                       actCall->call->setRetValue(WEXITSTATUS(stat_loc));
-                               } else {
-                                       // Child died, so pretend it returned 1
-                                       actCall->call->setRetValue(1);
-                               }
-                               // callback and release
-                               actCall->call->Callback();
-                               if (actCall == SysCalls) {
-                                       SysCalls = actCall->next;
-                               } else {
-                                       prev->next = actCall->next;
-                               }
-                               delete actCall;
-                               actCall = prev;
+                               actCall->call->setRetValue(WEXITSTATUS(stat_loc));
+                       } else {
+                               // Child died, so pretend it returned 1
+                               actCall->call->setRetValue(1);
+                       }
+                       // Callback and release
+                       actCall->call->callback();
+                       if (actCall == sysCalls) {
+                               sysCalls = actCall->next;
+                       } else {
+                               prev->next = actCall->next;
                        }
-                       prev = actCall;
+                       delete actCall;
+                       actCall = prev;
+               } else if (WIFSTOPPED(stat_loc)) {
+                       lyxerr << "LyX: Child (pid: " << pid 
+                              << ") stopped on signal "
+                              << WSTOPSIG(stat_loc) 
+                              << ". Waiting for child to finish." << endl;
+               } else {
+                       lyxerr << "LyX: Something rotten happened while "
+                               "waiting for child " << pid << endl;
                }
+               prev = actCall;
+       }
 }
index 02ae8bdb6f7ab997f7320b7ecfad1c37122bbca7..4080b9b0a91d77fe9a838ad23d656b8974c5c03e 100644 (file)
@@ -9,42 +9,27 @@
 
 class Systemcalls;
 
-///
-class SystemcallsSingletoncontroller{
+class SystemcallsSingletoncontroller {
 public:
-       ///
-       class Startcontroller{
+       class Startcontroller {
        public:
-               ///
                Startcontroller();
-               ///
                 ~Startcontroller();
-               ///
-               static SystemcallsSingletoncontroller *GetController();
-               ///
-                void ReduceRefcount() { refcount--; }
+               static SystemcallsSingletoncontroller * getController();
+                void reduceRefcount() { refcount--; }
        private:
-               ///
-               static SystemcallsSingletoncontroller *contr;
-               ///
+               static SystemcallsSingletoncontroller * contr;
                 static int refcount;
         };
-       ///
        ~SystemcallsSingletoncontroller();
-       ///
-       void AddCall(Systemcalls const &newcall);
-       ///
-       void Timer();
+       void addCall(Systemcalls const & newcall);
+       void timer();
        // private: // DEC cxx does not like that (JMarc)
-       ///
        SystemcallsSingletoncontroller();
 private:
-       ///
        struct ControlledCalls {
-               ///
                Systemcalls *call;
-               ///
-               ControlledCalls *next; };
-       ///
-       ControlledCalls *SysCalls;
+               ControlledCalls *next; 
+       };
+       ControlledCalls * sysCalls;
 };
index a3553c63452efc037fcf27f49637727a902a5d76..926f583cc1aa90899fc2ff2e47b954bbd434a6fa 100644 (file)
@@ -1,8 +1,5 @@
 #include <config.h>
 
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/wait.h>
 #include "syscontr.h"
 
 
@@ -19,30 +16,23 @@ contr = 0;
 int SystemcallsSingletoncontroller::Startcontroller::
 refcount = 0;
 
-// default constructor. 
-// Nothing to do at moment.
 SystemcallsSingletoncontroller::Startcontroller::
-Startcontroller() 
-{
+Startcontroller() {
 }
 
-// default destructor.
-// Nothing to do at moment
 SystemcallsSingletoncontroller::Startcontroller::
-~Startcontroller() 
-{
+~Startcontroller() {
 }
 
 // Give reference to global controller-instance
 // 
 SystemcallsSingletoncontroller *
-SystemcallsSingletoncontroller::Startcontroller::
-GetController()
+SystemcallsSingletoncontroller::Startcontroller::getController()
 { 
-       if (! contr) 
-               { // generate the global controller
-                        contr = new SystemcallsSingletoncontroller;
-               }
+       if (!contr) { 
+               // Create the global controller
+                contr = new SystemcallsSingletoncontroller;
+       }
        refcount++;
        return contr;
 }