Index: pkpgcounter/trunk/pkpgpdls/tiff.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/tiff.py (revision 522)
+++ pkpgcounter/trunk/pkpgpdls/tiff.py (revision 527)
@@ -32,5 +32,6 @@
 class Parser(pdlparser.PDLParser) :
     """A parser for TIFF documents."""
-    totiffcommands = [ '/bin/cp "%(infname)s" "%(outfname)s"' ]
+    totiffcommands = [ 'cp "%(infname)s" "%(outfname)s"' ]
+    required = [ "cp" ]
     def isValid(self) :        
         """Returns True if data is TIFF, else False."""
Index: pkpgcounter/trunk/pkpgpdls/pdlparser.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/pdlparser.py (revision 522)
+++ pkpgcounter/trunk/pkpgpdls/pdlparser.py (revision 527)
@@ -23,5 +23,4 @@
 import sys
 import os
-import popen2
 
 KILOBYTE = 1024    
@@ -41,6 +40,7 @@
 class PDLParser :
     """Generic PDL parser."""
-    totiffcommands = None        # Default command to convert to TIFF
-    openmode = "rb"              # Default file opening mode
+    totiffcommands = None       # Default command to convert to TIFF
+    required = []               # Default list of required commands
+    openmode = "rb"             # Default file opening mode
     def __init__(self, parent, (firstblock, lastblock)) :
         """Initialize the generic parser."""
@@ -71,4 +71,27 @@
             self.infile.close()
             
+    def findExecutable(self, command) :
+        """Finds an executable in the PATH and returns True if found else False."""
+        for cmd in [p.strip() for p in command.split("|")] : # | can separate alternatives for similar commands (e.g. a2ps|enscript)
+            for path in os.environ.get("PATH", "").split(":") :
+                fullname = os.path.abspath(os.path.join(os.path.expanduser(path), cmd))
+                if os.path.isfile(fullname) and os.access(fullname, os.X_OK) :
+                    return True
+        return False
+        
+    def isMissing(self, commands) :    
+        """Returns True if some required commands are missing, else False.""" 
+        howmanythere = 0
+        for command in commands :
+            if not self.findExecutable(command) :
+                sys.stderr.write("ERROR: %(command)s is missing or not executable. You MUST install it for pkpgcounter to be able to do what you want.\n" % locals())
+                sys.stderr.flush()
+            else :    
+                howmanythere += 1
+        if howmanythere == len(commands) :
+            return False
+        else :   
+            return True
+        
     def logdebug(self, message) :       
         """Logs a debug message if needed."""
@@ -89,4 +112,6 @@
         """   
         if self.totiffcommands :
+            if self.isMissing(self.required) :
+                raise PDLParserError, "At least one of the following commands is missing and should be installed for the computation of ink coverage : %s" % repr(self.required)
             infname = self.filename
             for totiffcommand in self.totiffcommands :
Index: pkpgcounter/trunk/pkpgpdls/ooo.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/ooo.py (revision 526)
+++ pkpgcounter/trunk/pkpgpdls/ooo.py (revision 527)
@@ -31,4 +31,5 @@
     """A parser for OpenOffice.org documents."""
     totiffcommands = [ 'xvfb-run -a abiword --import-extension=.odt --print="| gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r\"%(dpi)i\" -sOutputFile=\"%(outfname)s\" -" "%(infname)s"' ]
+    required = [ "xvfb-run", "xauth", "abiword", "gs" ]
     def isValid(self) :        
         """Returns True if data is OpenDocument, else False."""
Index: pkpgcounter/trunk/pkpgpdls/inkcoverage.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/inkcoverage.py (revision 520)
+++ pkpgcounter/trunk/pkpgpdls/inkcoverage.py (revision 527)
@@ -25,7 +25,11 @@
 import sys
 
-from PIL import Image
+import pdlparser
 
-import pdlparser
+try :
+    from PIL import Image
+except ImportError :    
+    sys.stderr.write("ERROR: You MUST install the Python Imaging Library (python-imaging) for pkpgcounter to work.\n")
+    raise pdlparser.PDLParserError, "The Python Imaging Library is missing."
 
 def getPercent(img, nbpix) :
Index: pkpgcounter/trunk/pkpgpdls/plain.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/plain.py (revision 522)
+++ pkpgcounter/trunk/pkpgpdls/plain.py (revision 527)
@@ -31,4 +31,5 @@
                        'a2ps --borders 0 --quiet --portrait --no-header --columns 1 --output - "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" -',
                      ]  
+    required = [ "a2ps | enscript", "gs" ]
     openmode = "rU"                 
     def isValid(self) :    
Index: pkpgcounter/trunk/pkpgpdls/pdf.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/pdf.py (revision 522)
+++ pkpgcounter/trunk/pkpgpdls/pdf.py (revision 527)
@@ -44,4 +44,5 @@
     """A parser for PDF documents."""
     totiffcommands = [ 'gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" "%(infname)s"' ]
+    required = [ "gs" ]
     openmode = "rU"
     def isValid(self) :    
Index: pkpgcounter/trunk/pkpgpdls/pcl345.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/pcl345.py (revision 522)
+++ pkpgcounter/trunk/pkpgpdls/pcl345.py (revision 527)
@@ -42,4 +42,5 @@
                        'pcl6 -sDEVICE=pswrite -r"%(dpi)i" -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -sOutputFile=- "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r%(dpi)i -sOutputFile="%(outfname)s" -',
                      ]
+    required = [ "pcl6", "gs" ]
     mediasizes = {  # ESC&l####A
                     0 : "Default",
Index: pkpgcounter/trunk/pkpgpdls/postscript.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/postscript.py (revision 522)
+++ pkpgcounter/trunk/pkpgpdls/postscript.py (revision 527)
@@ -25,6 +25,4 @@
 import sys
 import os
-import tempfile
-import popen2
 
 import pdlparser
@@ -34,4 +32,5 @@
     """A parser for PostScript documents."""
     totiffcommands = [ 'gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" "%(infname)s"' ]
+    required = [ "gs" ]
     openmode = "rU"
     def isValid(self) :    
@@ -53,4 +52,6 @@
         """Get the count through GhostScript, useful for non-DSC compliant PS files."""
         self.logdebug("Internal parser sucks, using GhostScript instead...")
+        if self.isMissing(self.required) :
+            raise pdlparser.PDLParserError, "The gs interpreter is nowhere to be found in your PATH (%s)" % os.environ.get("PATH", "")
         infname = self.filename
         command = 'gs -sDEVICE=bbox -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET "%(infname)s" 2>&1 | grep -c "%%HiResBoundingBox:" 2>/dev/null'
Index: pkpgcounter/trunk/pkpgpdls/pclxl.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/pclxl.py (revision 522)
+++ pkpgcounter/trunk/pkpgpdls/pclxl.py (revision 527)
@@ -36,4 +36,5 @@
                        'pcl6 -sDEVICE=pswrite -r"%(dpi)i" -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -sOutputFile=- "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" -',
                      ]
+    required = [ "pcl6", "gs" ]
     mediasizes = { 
                     0 : "Letter",
Index: pkpgcounter/trunk/pkpgpdls/dvi.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/dvi.py (revision 522)
+++ pkpgcounter/trunk/pkpgpdls/dvi.py (revision 527)
@@ -33,4 +33,5 @@
     """A parser for DVI documents."""
     totiffcommands = [ 'dvips -q -o - "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" -' ]
+    required = [ "dvips", "gs" ]
     def isValid(self) :        
         """Returns True if data is DVI, else False."""
Index: pkpgcounter/trunk/pkpgpdls/pil.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/pil.py (revision 522)
+++ pkpgcounter/trunk/pkpgpdls/pil.py (revision 527)
@@ -23,13 +23,18 @@
 """This modules implements a page counter for image formats supported by the Python Imaging Library."""
 
-from PIL import Image
+import pdlparser
 
-import pdlparser
+try :
+    from PIL import Image
+except ImportError :    
+    sys.stderr.write("ERROR: You MUST install the Python Imaging Library (python-imaging) for pkpgcounter to work.\n")
+    raise pdlparser.PDLParserError, "The Python Imaging Library is missing."
+
 import version
 
 class Parser(pdlparser.PDLParser) :
     """A parser for plain text documents."""
-    totiffcommands = [ 'convert "%(infname)s" "%(outfname)s"',
-                     ]  
+    totiffcommands = [ 'convert "%(infname)s" "%(outfname)s"' ]  
+    required = [ "convert" ]
     def isValid(self) :    
         """Returns True if data is an image format supported by PIL, else False."""   
Index: pkpgcounter/trunk/pkpgpdls/mscrap.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/mscrap.py (revision 525)
+++ pkpgcounter/trunk/pkpgpdls/mscrap.py (revision 527)
@@ -32,4 +32,5 @@
     """A parser for that MS crap thing."""
     totiffcommands = [ 'xvfb-run -a abiword --import-extension=.doc --print="| gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r\"%(dpi)i\" -sOutputFile=\"%(outfname)s\" -" "%(infname)s"' ]
+    required = [ "xvfb-run", "xauth", "abiword", "gs" ]
     def isValid(self) :    
         """Returns True if data is MS crap, else False.
@@ -46,5 +47,9 @@
            or self.firstblock[2112:].startswith("MSWordDoc") :
             self.logdebug("DEBUG: Input file seems to be in a Microsoft shitty file format.")
-            return True
+            # Here we do the missing test because all commands will be needed even in page counting mode
+            if self.isMissing(self.required) :
+                return False
+            else :    
+                return True
         else :    
             return False
Index: pkpgcounter/trunk/pkpgpdls/analyzer.py
===================================================================
--- pkpgcounter/trunk/pkpgpdls/analyzer.py (revision 524)
+++ pkpgcounter/trunk/pkpgpdls/analyzer.py (revision 527)
@@ -57,12 +57,4 @@
         self.mustclose = None
         
-    def findExecutable(self, command) :
-        """Finds an executable in the PATH and returns True if found else False."""
-        for path in os.environ.get("PATH", "").split(":") :
-            fullname = os.path.abspath(os.path.join(os.path.expanduser(path), command))
-            if os.path.isfile(fullname) and os.access(fullname, os.X_OK) :
-                return True
-        return False
-        
     def getJobSize(self) :    
         """Returns the job's size."""
@@ -74,5 +66,5 @@
                 size = pdlhandler.getJobSize()
             except pdlparser.PDLParserError, msg :    
-                raise pdlparser.PDLParserError, "Unknown file format for %s (%s)" % (self.filename, msg)
+                raise pdlparser.PDLParserError, "Unsupported file format for %s (%s)" % (self.filename, msg)
         finally :    
             self.closeFile()
@@ -98,5 +90,5 @@
                     dummyfile.close()
             except pdlparser.PDLParserError, msg :    
-                raise pdlparser.PDLParserError, "Unknown file format for %s (%s)" % (self.filename, msg)
+                raise pdlparser.PDLParserError, "Unsupported file format for %s (%s)" % (self.filename, msg)
         finally :
             self.closeFile()
Index: pkpgcounter/trunk/README
===================================================================
--- pkpgcounter/trunk/README (revision 502)
+++ pkpgcounter/trunk/README (revision 527)
@@ -107,19 +107,29 @@
   3 - That's all !    
   
+DEPENDENCIES :
+
+  Depending on the file formats you plan to work with, and on the accounting
+  mode you want to use (pages vs ink), you may need to install some or all
+  of the additional software listed below. Usually, if one is needed then
+  pkpgcounter will complain. So your best bet is probably to not install
+  anything until pkpgcounter asks you to do so on its standard error
+  stream. Here's the list of software which may be needed for some
+  operations with pkpgcounter :
+
+  - GhostScript (gs)
   
-IMPORTANT : To compute ink coverage, pkpgcounter relies on third party
-software which must be installed. These third party software are :
+  - The Python Imaging Library (python-imaging)
+  
+  - The X Virtual Frame Buffer (xvfb)
+  
+  - The X authority file utility xauth (xbase-clients)
+  
+  - The dvips converter from TeX DVI to PostScript (tetex-bin)
+  
+  - The ImageMagick image manipulation toolkit (imagemagick)
+  
+  - The AbiWord word processor (abiword)
 
-        - GhostScript (this one is needed for all file formats).
-        
-        - The Python Imaging Library, aka PIL (this one is needed for all
-          file formats).
-        
-        - GhostPCL (this one is needed for the PCL3/4/5 and PCLXL formats)
-          
-        - The LaTeX typesetting software, in particular the dvips command
-          (this one is needed for the DVI file format).
-          
-        - ImageMagick (this one is needed for image file formats)  
+  - The GhostPCL/GhostPDL's pcl6 converter from PCL to PostScript
         
 =============================================================================
