]> git.lyx.org Git - lyx.git/blobdiff - lib/configure.py
Make sweave process files with the correct encoding (#6625).
[lyx.git] / lib / configure.py
index a8a9cdb2beb326d890fad35e616eb983591dd06c..48cdb7de7ee3e90f5ae7723f1026f9ea8494e8cf 100644 (file)
@@ -206,6 +206,8 @@ def checkProgAlternatives(description, progs, rc_entry = [], alt_rc_entry = [],
             for ext in extlist:
                 if os.path.isfile( os.path.join(ac_dir, ac_word + ext) ):
                     logger.info(msg + ' yes')
+                    pr = re.compile(r'(\\\S+)(.*)$')
+                    m = None
                     # write rc entries for this command
                     if found_prime == False:
                         if len(rc_entry) == 1:
@@ -219,13 +221,17 @@ def checkProgAlternatives(description, progs, rc_entry = [], alt_rc_entry = [],
                         alt_rc = alt_rc_entry[0]
                         if alt_rc == "":
                             # if no explicit alt_rc is given, construct one
-                            alt_rc = rc_entry[0] + "_alternatives"
+                            m = pr.match(rc_entry[0])
+                            if m:
+                                alt_rc = m.group(1) + "_alternatives" + m.group(2)
                         addToRC(alt_rc.replace('%%', ac_prog))
                     elif len(alt_rc_entry) > 1:
                         alt_rc = alt_rc_entry[idx]
                         if alt_rc == "":
                             # if no explicit alt_rc is given, construct one
-                            alt_rc = rc_entry[idx] + "_alternatives"
+                            m = pr.match(rc_entry[idx])
+                            if m:
+                                alt_rc = m.group(1) + "_alternatives" + m.group(2)
                         addToRC(alt_rc.replace('%%', ac_prog))
                     found_alt = True
                     break
@@ -286,12 +292,10 @@ def checkViewer(description, progs, rc_entry = [], path = []):
     alt_rc_entry = []
     for idx in range(len(progs)):
         if len(rc_entry) == 1:
-            logger.info("rc_entry: " + rc_entry[0])
             rcs = rc_entry[0].split('\n')
             alt = addViewerAlternatives(rcs)
             alt_rc_entry.insert(0, alt)
         elif len(rc_entry) > 1:
-            logger.info("rc_entry: " + rc_entry[idx])
             rcs = rc_entry[idx].split('\n')
             alt = addViewerAlternatives(rcs)
             alt_rc_entry.insert(idx, alt)
@@ -306,12 +310,10 @@ def checkEditor(description, progs, rc_entry = [], path = []):
     alt_rc_entry = []
     for idx in range(len(progs)):
         if len(rc_entry) == 1:
-            logger.info("rc_entry: " + rc_entry[0])
             rcs = rc_entry[0].split('\n')
             alt = addEditorAlternatives(rcs)
             alt_rc_entry.insert(0, alt)
         elif len(rc_entry) > 1:
-            logger.info("rc_entry: " + rc_entry[idx])
             rcs = rc_entry[idx].split('\n')
             alt = addEditorAlternatives(rcs)
             alt_rc_entry.insert(idx, alt)
@@ -326,12 +328,10 @@ def checkViewerNoRC(description, progs, rc_entry = [], path = []):
     alt_rc_entry = []
     for idx in range(len(progs)):
         if len(rc_entry) == 1:
-            logger.info("rc_entry: " + rc_entry[0])
             rcs = rc_entry[0].split('\n')
             alt = addViewerAlternatives(rcs)
             alt_rc_entry.insert(0, alt)
         elif len(rc_entry) > 1:
-            logger.info("rc_entry: " + rc_entry[idx])
             rcs = rc_entry[idx].split('\n')
             alt = addViewerAlternatives(rcs)
             alt_rc_entry.insert(idx, alt)
@@ -347,12 +347,10 @@ def checkEditorNoRC(description, progs, rc_entry = [], path = []):
     alt_rc_entry = []
     for idx in range(len(progs)):
         if len(rc_entry) == 1:
-            logger.info("rc_entry: " + rc_entry[0])
             rcs = rc_entry[0].split('\n')
             alt = addEditorAlternatives(rcs)
             alt_rc_entry.insert(0, alt)
         elif len(rc_entry) > 1:
-            logger.info("rc_entry: " + rc_entry[idx])
             rcs = rc_entry[idx].split('\n')
             alt = addEditorAlternatives(rcs)
             alt_rc_entry.insert(idx, alt)
@@ -380,7 +378,7 @@ def checkDTLtools():
 
 def checkLatex(dtl_tools):
     ''' Check latex, return lyx_check_config '''
-    path, LATEX = checkProg('a Latex2e program', ['latex $$i', 'platex $$i', 'latex2e $$i'])
+    path, LATEX = checkProg('a Latex2e program', ['latex $$i', 'latex2e $$i'])
     path, PPLATEX = checkProg('a DVI postprocessing program', ['pplatex $$i'])
     #-----------------------------------------------------------------
     path, PLATEX = checkProg('pLaTeX, the Japanese LaTeX', ['platex $$i'])
@@ -394,7 +392,6 @@ def checkLatex(dtl_tools):
         if cmdOutput(PLATEX + ' chklatex.ltx').find('pLaTeX2e') != -1:
             # We have the Japanese pLaTeX2e
             addToRC(r'\converter platex   dvi       "%s"   "latex"' % PLATEX)
-            LATEX = PLATEX
         else:
             PLATEX = ''
             removeFiles(['chklatex.ltx', 'chklatex.log'])
@@ -429,6 +426,18 @@ def checkLatex(dtl_tools):
     return ''
 
 
+def checkModule(module):
+    ''' Check for a Python module, return the status '''
+    msg = 'checking for "' + module + ' module"... '
+    try:
+      __import__(module)
+      logger.info(msg + ' yes')
+      return True
+    except ImportError:
+      logger.info(msg + ' no')
+      return False
+
+
 def checkFormatEntries(dtl_tools):  
     ''' Check all formats (\Format entries) '''
     checkViewerEditor('a Tgif viewer and editor', ['tgif'],
@@ -446,6 +455,9 @@ def checkFormatEntries(dtl_tools):
     checkViewerEditor('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'],
         rc_entry = [r'\Format fen        fen     FEN                    "" "%%"        "%%"    ""'])
     #
+    checkViewerEditor('a SVG viewer and editor', ['inkscape'],
+        rc_entry = [r'\Format svg        svg     SVG                    "" "%%" "%%"   "vector"'])
+    #
     path, iv = checkViewerNoRC('a raster image viewer', ['xv', 'kview', 'gimp-remote', 'gimp'],
         rc_entry = [r'''\Format bmp        bmp     BMP                    "" "%s"      "%s"    ""
 \Format gif        gif     GIF                    "" "%s"      "%s"    ""
@@ -493,6 +505,7 @@ def checkFormatEntries(dtl_tools):
 \Format literate   nw      NoWeb                  N  ""        "%%"    "document"
 \Format sweave     Rnw    "Sweave"                S  "" "%%"    "document"
 \Format lilypond   ly     "LilyPond music"        "" ""        "%%"    "vector"
+\Format lilypond-book    lytex "LilyPond book (LaTeX)"   "" "" "%%"    "document"
 \Format latex      tex    "LaTeX (plain)"         L  ""        "%%"    "document"
 \Format pdflatex   tex    "LaTeX (pdflatex)"      "" ""        "%%"    "document"
 \Format xetex      tex    "LaTeX (XeTeX)"         "" ""        "%%"    "document"
@@ -503,9 +516,9 @@ def checkFormatEntries(dtl_tools):
 \Format textparagraph txt "Plain Text, Join Lines" "" ""       "%%"    "document"''' ])
  #
     path, xhtmlview = checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
-        rc_entry = [r'\Format xhtml      html   "LyX HTML"              "" "%%" ""    "document"'])
+        rc_entry = [r'\Format xhtml      xhtml   "LyXHTML"              X "%%" ""    "document"'])
     if xhtmlview == "":
-        addToRC(r'\Format xhtml      html   "LyX HTML"              "" "" "%%"  "document"')
+        addToRC(r'\Format xhtml      xhtml   "LyXHTML"              X "" ""  "document"')
  #
     checkEditor('a BibTeX editor', ['sensible-editor', 'jabref', 'JabRef', \
         'pybliographic', 'bibdesk', 'gbib', 'kbib', \
@@ -539,8 +552,13 @@ def checkFormatEntries(dtl_tools):
     checkViewerEditor('Noteedit', ['noteedit'],
         rc_entry = [r'\Format noteedit   not     Noteedit               "" "%%"        "%%"    "vector"'])
     #
-    checkViewerEditor('an OpenDocument viewer', ['swriter', 'oowriter'],
-        rc_entry = [r'\Format odt        odt     OpenDocument           "" "%%"        "%%"    "document,vector"'])
+    checkViewerEditor('an OpenDocument/OpenOffice viewer', ['swriter', 'oowriter', 'abiword'],
+        rc_entry = [r'''\Format odt        odt     OpenDocument           "" "%%"      "%%"    "document,vector"
+\Format sxw        sxw    "OpenOffice.Org (sxw)"  "" ""        ""      "document,vector"'''])
+    # 
+    checkViewerEditor('a Rich Text and Word viewer', ['swriter', 'oowriter', 'abiword'],
+        rc_entry = [r'''\Format rtf        rtf    "Rich Text Format"      "" ""        ""      "document,vector"
+\Format word       doc    "MS Word"               W  ""        ""      "document,vector"'''])
     #
     # entried that do not need checkProg
     addToRC(r'''\Format date       ""     "date command"          "" ""        ""      ""
@@ -555,15 +573,13 @@ def checkFormatEntries(dtl_tools):
 \Format jlyx       cjklyx "CJK LyX 1.4.x (euc-jp)" "" ""       ""      "document"
 \Format klyx       cjklyx "CJK LyX 1.4.x (euc-kr)" "" ""       ""      "document"
 \Format lyxpreview lyxpreview "LyX Preview"       "" ""        ""      ""
+\Format lyxpreview-lytex  lyxpreview-lytex  "LyX Preview (LilyPond book)" "" ""        ""      ""
 \Format lyxpreview-platex lyxpreview-platex "LyX Preview (pLaTeX)"       "" "" ""      ""
 \Format pdftex     pdftex_t PDFTEX                "" ""        ""      ""
 \Format program    ""      Program                "" ""        ""      ""
 \Format pstex      pstex_t PSTEX                  "" ""        ""      ""
-\Format rtf        rtf    "Rich Text Format"      "" ""        ""      "document,vector"
-\Format sxw        sxw    "OpenOffice.Org (sxw)"  ""  ""       ""      "document,vector"
 \Format wmf        wmf    "Windows Metafile"      "" ""        ""      "vector"
 \Format emf        emf    "Enhanced Metafile"     "" ""        ""      "vector"
-\Format word       doc    "MS Word"               W  ""        ""      "document,vector"
 \Format wordhtml   html   "HTML (MS Word)"        "" "" ""     "document"
 ''')
 
@@ -596,7 +612,7 @@ def checkConverterEntries():
         rc_entry = [r'''\converter literate   latex      "%%"  ""
 \converter literate   pdflatex      "%%"       ""'''])
     #
-    checkProg('a Sweave -> LaTeX converter', ['R CMD Sweave $$i'],
+    checkProg('a Sweave -> LaTeX converter', ['Rscript --vanilla $$s/scripts/lyxsweave.R $$i $$e'],
         rc_entry = [r'''\converter sweave   latex      "%%"    ""
 \converter sweave   pdflatex      "%%" ""'''])
     #
@@ -606,12 +622,22 @@ def checkConverterEntries():
     #
     checkProg('an MS Word -> LaTeX converter', ['wvCleanLatex $$i $$o'],
         rc_entry = [ r'\converter word       latex      "%%"   ""' ])
-    #
-    path, elyxer = checkProg('a LyX -> HTML converter', ['elyxer.py', 'elyxer'],
-      rc_entry = [ r'\converter lyx      html       "python -tt $$s/scripts/elyxer.py --directory $$r $$i $$o" ""' ])
-    if elyxer.find('elyxer') >= 0:
+
+    # eLyXer: search as a Python module and then as an executable (elyxer.py, elyxer)
+    elyxerfound = checkModule('elyxer')
+    if elyxerfound:
+      addToRC(r'''\converter lyx      html       "python -m elyxer --directory $$r $$i $$o"    ""''')
+    else:
+      path, elyxer = checkProg('a LyX -> HTML converter',
+        ['elyxer.py --directory $$r $$i $$o', 'elyxer --directory $$r $$i $$o'],
+        rc_entry = [ r'\converter lyx      html       "%%"     ""' ])
+      if elyxer.find('elyxer') >= 0:
+        elyxerfound = True
+
+    if elyxerfound:
       addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py -e html,png,jpg,jpeg,css $$i $$o"''')
     else:
+      # search for other converters than eLyXer
       # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
       path, htmlconv = checkProg('a LaTeX -> HTML converter', ['htlatex $$i', 'htlatex.sh $$i', \
           '/usr/share/tex4ht/htlatex $$i', 'tth  -t -e2 -L$$b < $$i > $$o', \
@@ -622,13 +648,36 @@ def checkConverterEntries():
       else:
         addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
 
-    # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
-    path, htmlconv = checkProg('a LaTeX -> MS Word converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'", \
-        "htlatex.sh $$i 'html,word' 'symbol/!' '-cvalidate'", \
-        "/usr/share/tex4ht/htlatex $$i 'html,word' 'symbol/!' '-cvalidate'"],
-        rc_entry = [ r'\converter latex      wordhtml   "%%"   "needaux"' ])
-    if htmlconv.find('htlatex') >= 0:
-      addToRC(r'''\copier    wordhtml       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
+    # Check if LyxBlogger is installed.
+    path, lyxblogger = checkProg('A LyX to WordPress Blog Publishing Tool',
+      ['lyxblogger $$i'], rc_entry = [])
+    if lyxblogger.find('lyxblogger') >= 0:
+      addToRC(r'\Format    blog       blog       "LyxBlogger"           "" "" ""  "document"')
+      addToRC(r'\converter xhtml      blog       "lyxblogger $$i"       ""')
+
+    if elyxerfound:
+      addToRC(r'''\converter lyx      wordhtml       "python -m elyxer --html --directory $$r $$i $$o" ""''')
+    else:
+      path, elyxer = checkProg('a LyX -> MS Word converter',
+        ['elyxer.py --directory $$r $$i $$o', 'elyxer --html --directory $$r $$i $$o'],
+        rc_entry = [ r'\converter lyx      wordhtml       "%%" ""' ])
+      if elyxer.find('elyxer') >= 0:
+        elyxerfound = True
+
+    if elyxerfound:
+      addToRC(r'''\copier    wordhtml       "python -tt $$s/scripts/ext_copy.py -e html,png,jpg,jpeg,css $$i $$o"''')
+    else:
+      # search for other converters than eLyXer
+      # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
+      path, htmlconv = checkProg('a LaTeX -> MS Word converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'", \
+          "htlatex.sh $$i 'html,word' 'symbol/!' '-cvalidate'", \
+          "/usr/share/tex4ht/htlatex $$i 'html,word' 'symbol/!' '-cvalidate'"],
+          rc_entry = [ r'\converter latex      wordhtml   "%%" "needaux"' ])
+      if htmlconv.find('htlatex') >= 0:
+        addToRC(r'''\copier    wordhtml       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
+      else:
+        addToRC(r'''\copier    wordhtml       "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
+
     #
     checkProg('an OpenOffice.org -> LaTeX converter', ['w2l -clean $$i'],
         rc_entry = [ r'\converter sxw        latex      "%%"   ""' ])
@@ -726,8 +775,11 @@ def checkConverterEntries():
 \converter agr        ppm        "gracebat -hardcopy -printfile $$o -hdevice PNM $$i 2>/dev/null"      ""''',
             ''])
     #
-    checkProg('a Dot -> PDF converter', ['dot -Tpdf $$i -o $$o'],
-        rc_entry = [ r'\converter dot        pdf        "%%"   ""'])
+    checkProg('a Dot -> Image converter', ['dot'],
+        rc_entry = [
+            r'''\converter dot        eps        "dot -Teps $$i -o $$o"        ""
+\converter dot        png        "dot -Tpng $$i -o $$o"        ""''',
+            ''])
     #
     checkProg('a Dia -> PNG converter', ['dia -e $$o -t png $$i'],
         rc_entry = [ r'\converter dia        png        "%%"   ""'])
@@ -735,6 +787,15 @@ def checkConverterEntries():
     checkProg('a Dia -> EPS converter', ['dia -e $$o -t eps $$i'],
         rc_entry = [ r'\converter dia        eps        "%%"   ""'])
     #
+    checkProg('a SVG -> PDF converter', ['rsvg-convert -f pdf -o $$o $$i', 'inkscape --file=$$p/$$i --export-area-drawing --without-gui --export-pdf=$$p/$$o'],
+        rc_entry = [ r'\converter svg        pdf        "%%"   ""'])
+    #
+    checkProg('a SVG -> EPS converter', ['rsvg-convert -f ps -o $$o $$i', 'inkscape --file=$$p/$$i --export-area-drawing --without-gui --export-eps=$$p/$$o'],
+        rc_entry = [ r'\converter svg        eps        "%%"   ""'])
+    # the PNG export via Inkscape must not have the full path ($$p) for the file
+    checkProg('a SVG -> PNG converter', ['rsvg-convert -f png -o $$o $$i', 'inkscape --without-gui --file=$$i --export-png=$$o'],
+        rc_entry = [ r'\converter svg        png        "%%"   ""'])
+    
     #
     path, lilypond = checkProg('a LilyPond -> EPS/PDF/PNG converter', ['lilypond'])
     if (lilypond != ''):
@@ -747,7 +808,7 @@ def checkConverterEntries():
                 addToRC(r'''\converter lilypond   eps        "lilypond -dbackend=eps --ps $$i" ""
 \converter lilypond   png        "lilypond -dbackend=eps --png $$i"    ""''')
                 addToRC(r'\converter lilypond   pdf        "lilypond -dbackend=eps --pdf $$i"  ""')
-                print '+  found LilyPond version %s.' % version_number
+                logger.info('+  found LilyPond version %s.' % version_number)
             elif int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 6):
                 addToRC(r'''\converter lilypond   eps        "lilypond -b eps --ps $$i"        ""
 \converter lilypond   png        "lilypond -b eps --png $$i"   ""''')
@@ -759,6 +820,38 @@ def checkConverterEntries():
         else:
             logger.info('+  found LilyPond, but could not extract version number.')
     #
+    path, lilypond_book = checkProg('a LilyPond book (LaTeX) -> LaTeX converter', ['lilypond-book'])
+    if (lilypond_book != ''):
+        version_string = cmdOutput("lilypond-book --version")
+        match = re.match('^(\S+)$', version_string)
+        if match:
+            version_number = match.groups()[0]
+            version = version_number.split('.')
+            if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 1):
+                addToRC(r'\converter lyxpreview-lytex ppm "python -tt $$s/scripts/lyxpreview-lytex2bitmap.py" ""')
+                if dvipng == "dvipng":
+                    addToRC(r'\converter lyxpreview-lytex png "python -tt $$s/scripts/lyxpreview-lytex2bitmap.py" ""')
+                else:
+                    addToRC(r'\converter lyxpreview-lytex png "" ""')
+            if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 11):
+                # Note: The --lily-output-dir flag is required because lilypond-book
+                #       does not process input again unless the input has changed,
+                #       even if the output format being requested is different. So
+                #       once a .eps file exists, lilypond-book won't create a .pdf
+                #       even when requested with --pdf. This is a problem if a user
+                #       clicks View PDF after having done a View DVI. To circumvent
+                #       this, use different output folders for eps and pdf outputs.
+                addToRC(r'\converter lilypond-book latex    "lilypond-book --lily-output-dir=ly-eps $$i"                                ""')
+                addToRC(r'\converter lilypond-book pdflatex "lilypond-book --pdf --latex-program=pdflatex --lily-output-dir=ly-pdf $$i" ""')
+                logger.info('+  found LilyPond-book version %s.' % version_number)
+            elif int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 1):
+                addToRC(r'\converter lilypond-book latex  "lilypond-book $$i"                                ""')
+                logger.info('+  found LilyPond-book version %s.' % version_number)
+            else:
+                logger.info('+  found LilyPond-book, but version %s is too old.' % version_number)
+        else:
+            logger.info('+  found LilyPond-book, but could not extract version number.')
+    #
     checkProg('a Noteedit -> LilyPond converter', ['noteedit --export-lilypond $$i'],
         rc_entry = [ r'\converter noteedit   lilypond   "%%"   ""', ''])
     #
@@ -813,12 +906,12 @@ def checkOtherEntries():
     checkProgAlternatives('BibTeX or alternative programs', ['bibtex', 'bibtex8', 'biber'],
         rc_entry = [ r'\bibtex_command "%%"' ],
         alt_rc_entry = [ r'\bibtex_alternatives "%%"' ])
-    checkProg('JBibTeX, the Japanese BibTeX', ['jbibtex', 'bibtex'],
+    checkProg('a specific Japanese BibTeX variant', ['pbibtex', 'jbibtex', 'bibtex'],
         rc_entry = [ r'\jbibtex_command "%%"' ])
     checkProgAlternatives('available index processors', ['texindy', 'makeindex -c -q'],
         rc_entry = [ r'\index_command "%%"' ],
         alt_rc_entry = [ r'\index_alternatives "%%"' ])
-    checkProg('an index processor appropriate to Japanese', ['mendex -c -q', 'makeindex -c -q'],
+    checkProg('an index processor appropriate to Japanese', ['mendex -c -q', 'jmakeindex -c -q', 'makeindex -c -q'],
         rc_entry = [ r'\jindex_command "%%"' ])
     path, splitindex = checkProg('the splitindex processor', ['splitindex.pl', 'splitindex'],
         rc_entry = [ r'\splitindex_command "%%"' ])
@@ -857,10 +950,17 @@ def processLayoutFile(file, bool_docbook):
 
         we expect output:
         
-        "article" "article" "article" "false"
-        "scrbook" "scrbook" "book (koma-script)" "false"
-        "svjog" "svjour" "article (Springer - svjour/jog)" "false"
+        "article" "article" "article" "false" "article.cls"
+        "scrbook" "scrbook" "book (koma-script)" "false" "scrbook.cls"
+        "svjog" "svjour" "article (Springer - svjour/jog)" "false" "svjour.cls,svjog.clo"
     '''
+    def checkForClassExtension(x):
+        '''if the extension for a latex class is not
+           provided, add .cls to the classname'''
+        if not '.' in x:
+            return x.strip() + '.cls'
+        else:
+            return x.strip()
     classname = file.split(os.sep)[-1].split('.')[0]
     # return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclareLaTeXClass[a,b,c]{article}
     p = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
@@ -871,7 +971,14 @@ def processLayoutFile(file, bool_docbook):
             avai = {'LaTeX':'false', 'DocBook':bool_docbook}[classtype]
             if opt == None:
                 opt = classname
-            return '"%s" "%s" "%s" "%s"\n' % (classname, opt, desc, avai)
+                prereq_latex = checkForClassExtension(classname)
+            else:
+                prereq_list = optAll[1:-1].split(',')
+                prereq_list = map(checkForClassExtension, prereq_list)
+                prereq_latex = ','.join(prereq_list)
+            prereq_docbook = {'true':'', 'false':'docbook'}[bool_docbook]
+            prereq = {'LaTeX':prereq_latex, 'DocBook':prereq_docbook}[classtype]
+            return '"%s" "%s" "%s" "%s" "%s"\n' % (classname, opt, desc, avai, prereq)
     logger.warning("Layout file " + file + " has no \DeclareXXClass line. ")
     return ""
 
@@ -923,75 +1030,75 @@ def checkLatexConfig(check_config, bool_docbook):
     if not check_config:
         return None
     # the following will generate textclass.lst.tmp, and packages.lst.tmp
-    else:
-        logger.info(msg + '\tauto')
-        removeFiles(['wrap_chkconfig.ltx', 'chkconfig.vars', \
-            'chkconfig.classes', 'chklayouts.tex'])
-        rmcopy = False
-        if not os.path.isfile( 'chkconfig.ltx' ):
-            shutil.copyfile( os.path.join(srcdir, 'chkconfig.ltx'), 'chkconfig.ltx' )
-            rmcopy = True
-        writeToFile('wrap_chkconfig.ltx', '%s\n\\input{chkconfig.ltx}\n' % docbook_cmd)
-        # Construct the list of classes to test for.
-        # build the list of available layout files and convert it to commands
-        # for chkconfig.ltx
-        p1 = re.compile(r'\Declare(LaTeX|DocBook)Class')
-        testclasses = list()
-        for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
-            glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
-            if not os.path.isfile(file):
+    logger.info(msg + '\tauto')
+    removeFiles(['wrap_chkconfig.ltx', 'chkconfig.vars', \
+        'chkconfig.classes', 'chklayouts.tex'])
+    rmcopy = False
+    if not os.path.isfile( 'chkconfig.ltx' ):
+        shutil.copyfile( os.path.join(srcdir, 'chkconfig.ltx'), 'chkconfig.ltx' )
+        rmcopy = True
+    writeToFile('wrap_chkconfig.ltx', '%s\n\\input{chkconfig.ltx}\n' % docbook_cmd)
+    # Construct the list of classes to test for.
+    # build the list of available layout files and convert it to commands
+    # for chkconfig.ltx
+    declare = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
+    empty = re.compile(r'^\s*$')
+    testclasses = list()
+    for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
+        glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
+        if not os.path.isfile(file):
+            continue
+        classname = file.split(os.sep)[-1].split('.')[0]
+        for line in open(file).readlines():
+            if not empty.match(line) and line[0] != '#':
+                logger.error("Failed to find \Declare line for layout file `" + file + "'")
+                sys.exit(3)
+            if declare.search(line) == None:
                 continue
-            classname = file.split(os.sep)[-1].split('.')[0]
-            for line in open(file).readlines():
-                if p1.search(line) == None:
-                    continue
-                if line[0] != '#':
-                    logger.error("Wrong input layout file with line '" + line)
-                    sys.exit(3)
-                testclasses.append("\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()))
-                break
-        testclasses.sort()
-        cl = open('chklayouts.tex', 'w')
-        for line in testclasses:
-            cl.write(line + '\n')
-        cl.close()
-        #
-        # we have chklayouts.tex, then process it
-        fout = os.popen(LATEX + ' wrap_chkconfig.ltx')
-        while True:
-            line = fout.readline()
-            if not line:
-                break;
-            if re.match('^\+', line):
-                logger.info(line.strip())
-        # if the command succeeds, None will be returned
-        ret = fout.close()
-        #
-        # currently, values in chhkconfig are only used to set
-        # \font_encoding
-        values = {}
-        for line in open('chkconfig.vars').readlines():
-            key, val = re.sub('-', '_', line).split('=')
-            val = val.strip()
-            values[key] = val.strip("'")
-        # chk_fontenc may not exist 
-        try:
-            addToRC(r'\font_encoding "%s"' % values["chk_fontenc"])
-        except:
-            pass
-        if rmcopy:   # remove the copied file
-            removeFiles( [ 'chkconfig.ltx' ] )
-        # if configure successed, move textclass.lst.tmp to textclass.lst
-        # and packages.lst.tmp to packages.lst
-        if os.path.isfile('textclass.lst.tmp') and len(open('textclass.lst.tmp').read()) > 0 \
-            and os.path.isfile('packages.lst.tmp') and len(open('packages.lst.tmp').read()) > 0:
-            shutil.move('textclass.lst.tmp', 'textclass.lst')
-            shutil.move('packages.lst.tmp', 'packages.lst')
-        return ret
+            testclasses.append("\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()))
+            break
+    testclasses.sort()
+    cl = open('chklayouts.tex', 'w')
+    for line in testclasses:
+        cl.write(line + '\n')
+    cl.close()
+    #
+    # we have chklayouts.tex, then process it
+    fout = os.popen(LATEX + ' wrap_chkconfig.ltx')
+    while True:
+        line = fout.readline()
+        if not line:
+            break;
+        if re.match('^\+', line):
+            logger.info(line.strip())
+    # if the command succeeds, None will be returned
+    ret = fout.close()
+    #
+    # currently, values in chhkconfig are only used to set
+    # \font_encoding
+    values = {}
+    for line in open('chkconfig.vars').readlines():
+        key, val = re.sub('-', '_', line).split('=')
+        val = val.strip()
+        values[key] = val.strip("'")
+    # chk_fontenc may not exist 
+    try:
+        addToRC(r'\font_encoding "%s"' % values["chk_fontenc"])
+    except:
+        pass
+    if rmcopy:   # remove the copied file
+        removeFiles( [ 'chkconfig.ltx' ] )
+    # if configure successed, move textclass.lst.tmp to textclass.lst
+    # and packages.lst.tmp to packages.lst
+    if os.path.isfile('textclass.lst.tmp') and len(open('textclass.lst.tmp').read()) > 0 \
+        and os.path.isfile('packages.lst.tmp') and len(open('packages.lst.tmp').read()) > 0:
+        shutil.move('textclass.lst.tmp', 'textclass.lst')
+        shutil.move('packages.lst.tmp', 'packages.lst')
+    return ret
 
 
 def checkModulesConfig():
-  removeFiles(['lyxmodules.lst'])
+  removeFiles(['lyxmodules.lst', 'chkmodules.tex'])
 
   logger.info('+checking list of modules... ')
   tx = open('lyxmodules.lst', 'w')
@@ -1031,12 +1138,12 @@ def processModuleFile(file, bool_docbook):
         We expect output:
           "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category"
     '''
-    p = re.compile(r'\DeclareLyXModule\s*(?:\[([^]]*?)\])?{(.*)}')
-    r = re.compile(r'#+\s*Requires: (.*)')
-    x = re.compile(r'#+\s*Excludes: (.*)')
-    c = re.compile(r'#+\s*Category: (.*)')
-    b = re.compile(r'#+\s*DescriptionBegin\s*$')
-    e = re.compile(r'#+\s*DescriptionEnd\s*$')
+    remods = re.compile(r'\DeclareLyXModule\s*(?:\[([^]]*?)\])?{(.*)}')
+    rereqs = re.compile(r'#+\s*Requires: (.*)')
+    reexcs = re.compile(r'#+\s*Excludes: (.*)')
+    recaty = re.compile(r'#+\s*Category: (.*)')
+    redbeg = re.compile(r'#+\s*DescriptionBegin\s*$')
+    redend = re.compile(r'#+\s*DescriptionEnd\s*$')
 
     modname = desc = pkgs = req = excl = catgy = ""
     readingDescription = False
@@ -1046,18 +1153,20 @@ def processModuleFile(file, bool_docbook):
 
     for line in open(file).readlines():
       if readingDescription:
-        res = e.search(line)
+        res = redend.search(line)
         if res != None:
           readingDescription = False
           desc = " ".join(descLines)
+          # Escape quotes.
+          desc = desc.replace('"', '\\"')
           continue
         descLines.append(line[1:].strip())
         continue
-      res = b.search(line)
+      res = redbeg.search(line)
       if res != None:
         readingDescription = True
         continue
-      res = p.search(line)
+      res = remods.search(line)
       if res != None:
           (pkgs, modname) = res.groups()
           if pkgs == None:
@@ -1066,26 +1175,46 @@ def processModuleFile(file, bool_docbook):
             tmp = [s.strip() for s in pkgs.split(",")]
             pkgs = ",".join(tmp)
           continue
-      res = r.search(line)
+      res = rereqs.search(line)
       if res != None:
         req = res.group(1)
         tmp = [s.strip() for s in req.split("|")]
         req = "|".join(tmp)
         continue
-      res = x.search(line)
+      res = reexcs.search(line)
       if res != None:
         excl = res.group(1)
         tmp = [s.strip() for s in excl.split("|")]
         excl = "|".join(tmp)
         continue
-      res = c.search(line)
+      res = recaty.search(line)
       if res != None:
         catgy = res.group(1)
         continue
-    if modname != "":
-        return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, pkgs, req, excl, catgy)
-    logger.warning("Module file without \DeclareLyXModule line. ")
-    return ""
+
+    if modname == "":
+      logger.warning("Module file without \DeclareLyXModule line. ")
+      return ""
+
+    if pkgs != "":
+        # this module has some latex dependencies:
+        # append the dependencies to chkmodules.tex,
+        # which is \input'ed by chkconfig.ltx
+        testpackages = list()
+        for pkg in pkgs.split(","):
+            if "->" in pkg:
+                # this is a converter dependency: skip
+                continue
+            if pkg.endswith(".sty"):
+                pkg = pkg[:-4]
+            testpackages.append("\\TestPackage{%s}" % (pkg,))
+        cm = open('chkmodules.tex', 'a')
+        for line in testpackages:
+            cm.write(line + '\n')
+        cm.close()
+
+    return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, pkgs, req, excl, catgy)
+    
 
 
 def checkTeXAllowSpaces():
@@ -1094,10 +1223,13 @@ def checkTeXAllowSpaces():
     if lyx_check_config:
         msg = "Checking whether TeX allows spaces in file names... "
         writeToFile('a b.tex', r'\message{working^^J}' )
-        if os.name == 'nt':
-            latex_out = cmdOutput(LATEX + r""" "\nonstopmode\input{\"a b\"}" """)
+        if LATEX != '':
+            if os.name == 'nt':
+                latex_out = cmdOutput(LATEX + r""" "\nonstopmode\input{\"a b\"}" """)
+            else:
+                latex_out = cmdOutput(LATEX + r""" '\nonstopmode\input{"a b"}' """)
         else:
-            latex_out = cmdOutput(LATEX + r""" '\nonstopmode\input{"a b"}' """)
+            latex_out = ''
         if 'working' in latex_out:
             logger.info(msg + 'yes')
             tex_allows_spaces = 'true'
@@ -1113,7 +1245,7 @@ def removeTempFiles():
     if not lyx_keep_temps:
         removeFiles(['chkconfig.vars',  \
             'wrap_chkconfig.ltx', 'wrap_chkconfig.log', \
-            'chklayouts.tex', 'missfont.log', 
+            'chklayouts.tex', 'chkmodules.tex', 'missfont.log', 
             'chklatex.ltx', 'chklatex.log'])
 
 
@@ -1172,9 +1304,9 @@ Options:
     if windows_style_tex_paths != '':
         addToRC(r'\tex_expects_windows_paths %s' % windows_style_tex_paths)
     checkOtherEntries()
+    checkModulesConfig()
     # --without-latex-config can disable lyx_check_config
     ret = checkLatexConfig(lyx_check_config and LATEX != '', bool_docbook)
-    checkModulesConfig() #lyx_check_config and LATEX != '')
     removeTempFiles()
     # The return error code can be 256. Because most systems expect an error code
     # in the range 0-127, 256 can be interpretted as 'success'. Because we expect