]> git.lyx.org Git - lyx.git/blobdiff - lib/configure.py
fix r33152 - part 1
[lyx.git] / lib / configure.py
index be0b71cad8f506ec477cd5ee2fa84db936e1a1ec..cc4e0ce29e351d1551b58c56c8874c8e711d3f76 100644 (file)
@@ -178,9 +178,190 @@ def checkProg(description, progs, rc_entry = [], path = [], not_found = ''):
     return ['', not_found]
 
 
+def checkProgAlternatives(description, progs, rc_entry = [], alt_rc_entry = [], path = [], not_found = ''):
+    ''' 
+        The same as checkProg, but additionally, all found programs will be added
+        as alt_rc_entries
+    '''
+    # one rc entry for each progs plus not_found entry
+    if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
+        logger.error("rc entry should have one item or item for each prog and not_found.")
+        sys.exit(2)
+    logger.info('checking for ' + description + '...')
+    ## print '(' + ','.join(progs) + ')',
+    found_prime = False
+    real_ac_dir = ''
+    real_ac_word = not_found
+    for idx in range(len(progs)):
+        # ac_prog may have options, ac_word is the command name
+        ac_prog = progs[idx]
+        ac_word = ac_prog.split(' ')[0]
+        msg = '+checking for "' + ac_word + '"... '
+        path = os.environ["PATH"].split(os.pathsep) + path
+        extlist = ['']
+        if os.environ.has_key("PATHEXT"):
+            extlist = extlist + os.environ["PATHEXT"].split(os.pathsep)
+        found_alt = False
+        for ac_dir in path:
+            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:
+                            addToRC(rc_entry[0].replace('%%', ac_prog))
+                        elif len(rc_entry) > 1:
+                            addToRC(rc_entry[idx].replace('%%', ac_prog))
+                        real_ac_dir = ac_dir
+                        real_ac_word = ac_word
+                        found_prime = True
+                    if len(alt_rc_entry) == 1:
+                        alt_rc = alt_rc_entry[0]
+                        if alt_rc == "":
+                            # if no explicit alt_rc is given, construct one
+                            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
+                            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
+            if found_alt:
+                break
+        if found_alt == False:
+            # if not successful
+            logger.info(msg + ' no')
+    if found_prime:
+        return [real_ac_dir, real_ac_word]
+    # write rc entries for 'not found'
+    if len(rc_entry) > 0:  # the last one.
+        addToRC(rc_entry[-1].replace('%%', not_found))
+    return ['', not_found]
+
+
+def addViewerAlternatives(rcs):
+    r = re.compile(r'\\Format (\S+).*$')
+    m = None
+    alt = ''
+    for idxx in range(len(rcs)):
+        if len(rcs) == 1:
+            m = r.match(rcs[0])
+            if m:
+                alt = r'\viewer_alternatives ' + m.group(1) + " %%"
+        elif len(rcs) > 1:
+            m = r.match(rcs[idxx])
+            if m:
+                if idxx > 0:
+                    alt += '\n'
+                alt += r'\viewer_alternatives ' + m.group(1) + " %%"
+    return alt
+
+
+def addEditorAlternatives(rcs):
+    r = re.compile(r'\\Format (\S+).*$')
+    m = None
+    alt = ''
+    for idxx in range(len(rcs)):
+        if len(rcs) == 1:
+            m = r.match(rcs[0])
+            if m:
+                alt = r'\editor_alternatives ' + m.group(1) + " %%"
+        elif len(rcs) > 1:
+            m = r.match(rcs[idxx])
+            if m:
+                if idxx > 0:
+                    alt += '\n'
+                alt += r'\editor_alternatives ' + m.group(1) + " %%"
+    return alt
+
+
 def checkViewer(description, progs, rc_entry = [], path = []):
-    ''' The same as checkProg, but for viewers and editors '''
-    return checkProg(description, progs, rc_entry, path, not_found = 'auto')
+    ''' The same as checkProgAlternatives, but for viewers '''
+    if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
+        logger.error("rc entry should have one item or item for each prog and not_found.")
+        sys.exit(2)
+    alt_rc_entry = []
+    for idx in range(len(progs)):
+        if len(rc_entry) == 1:
+            rcs = rc_entry[0].split('\n')
+            alt = addViewerAlternatives(rcs)
+            alt_rc_entry.insert(0, alt)
+        elif len(rc_entry) > 1:
+            rcs = rc_entry[idx].split('\n')
+            alt = addViewerAlternatives(rcs)
+            alt_rc_entry.insert(idx, alt)
+    return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
+
+
+def checkEditor(description, progs, rc_entry = [], path = []):
+    ''' The same as checkProgAlternatives, but for editors '''
+    if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
+        logger.error("rc entry should have one item or item for each prog and not_found.")
+        sys.exit(2)
+    alt_rc_entry = []
+    for idx in range(len(progs)):
+        if len(rc_entry) == 1:
+            rcs = rc_entry[0].split('\n')
+            alt = addEditorAlternatives(rcs)
+            alt_rc_entry.insert(0, alt)
+        elif len(rc_entry) > 1:
+            rcs = rc_entry[idx].split('\n')
+            alt = addEditorAlternatives(rcs)
+            alt_rc_entry.insert(idx, alt)
+    return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
+
+
+def checkViewerNoRC(description, progs, rc_entry = [], path = []):
+    ''' The same as checkViewer, but do not add rc entry '''
+    if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
+        logger.error("rc entry should have one item or item for each prog and not_found.")
+        sys.exit(2)
+    alt_rc_entry = []
+    for idx in range(len(progs)):
+        if len(rc_entry) == 1:
+            rcs = rc_entry[0].split('\n')
+            alt = addViewerAlternatives(rcs)
+            alt_rc_entry.insert(0, alt)
+        elif len(rc_entry) > 1:
+            rcs = rc_entry[idx].split('\n')
+            alt = addViewerAlternatives(rcs)
+            alt_rc_entry.insert(idx, alt)
+    rc_entry = []
+    return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
+
+
+def checkEditorNoRC(description, progs, rc_entry = [], path = []):
+    ''' The same as checkViewer, but do not add rc entry '''
+    if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
+        logger.error("rc entry should have one item or item for each prog and not_found.")
+        sys.exit(2)
+    alt_rc_entry = []
+    for idx in range(len(progs)):
+        if len(rc_entry) == 1:
+            rcs = rc_entry[0].split('\n')
+            alt = addEditorAlternatives(rcs)
+            alt_rc_entry.insert(0, alt)
+        elif len(rc_entry) > 1:
+            rcs = rc_entry[idx].split('\n')
+            alt = addEditorAlternatives(rcs)
+            alt_rc_entry.insert(idx, alt)
+    rc_entry = []
+    return checkProgAlternatives(description, progs, rc_entry, alt_rc_entry, path, not_found = 'auto')
+
+
+def checkViewerEditor(description, progs, rc_entry = [], path = []):
+    ''' The same as checkProgAlternatives, but for viewers and editors '''
+    checkEditorNoRC(description, progs, rc_entry, path)
+    return checkViewer(description, progs, rc_entry, path)
 
 
 def checkDTLtools():
@@ -246,25 +427,60 @@ 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) '''
-    checkViewer('a Tgif viewer and editor', ['tgif'],
+    checkViewerEditor('a Tgif viewer and editor', ['tgif'],
         rc_entry = [r'\Format tgif       obj     Tgif                   "" "%%"        "%%"    "vector"'])
     #
-    checkViewer('a FIG viewer and editor', ['xfig', 'jfig3-itext.jar', 'jfig3.jar'],
+    checkViewerEditor('a FIG viewer and editor', ['xfig', 'jfig3-itext.jar', 'jfig3.jar'],
         rc_entry = [r'\Format fig        fig     FIG                    "" "%%"        "%%"    "vector"'])
     #
-    checkViewer('a Dia viewer and editor', ['dia'],
+    checkViewerEditor('a Dia viewer and editor', ['dia'],
         rc_entry = [r'\Format dia        dia     DIA                    "" "%%"        "%%"    "vector"'])
     #
-    checkViewer('a Grace viewer and editor', ['xmgrace'],
+    checkViewerEditor('a Grace viewer and editor', ['xmgrace'],
         rc_entry = [r'\Format agr        agr     Grace                  "" "%%"        "%%"    "vector"'])
     #
-    checkViewer('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'],
+    checkViewerEditor('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'],
         rc_entry = [r'\Format fen        fen     FEN                    "" "%%"        "%%"    ""'])
     #
-    path, iv = checkViewer('a raster image viewer', ['xv', 'kview', 'gimp-remote', 'gimp'])
-    path, ie = checkViewer('a raster image editor', ['gimp-remote', 'gimp'])
+    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"    ""
+\Format jpg        jpg     JPEG                   "" "%s"      "%s"    ""
+\Format pbm        pbm     PBM                    "" "%s"      "%s"    ""
+\Format pgm        pgm     PGM                    "" "%s"      "%s"    ""
+\Format png        png     PNG                    "" "%s"      "%s"    ""
+\Format ppm        ppm     PPM                    "" "%s"      "%s"    ""
+\Format tiff       tif     TIFF                   "" "%s"      "%s"    ""
+\Format xbm        xbm     XBM                    "" "%s"      "%s"    ""
+\Format xpm        xpm     XPM                    "" "%s"      "%s"    ""'''])
+    path, ie = checkEditorNoRC('a raster image editor', ['gimp-remote', 'gimp'],
+        rc_entry = [r'''\Format bmp        bmp     BMP                    "" "%s"      "%s"    ""
+\Format gif        gif     GIF                    "" "%s"      "%s"    ""
+\Format jpg        jpg     JPEG                   "" "%s"      "%s"    ""
+\Format pbm        pbm     PBM                    "" "%s"      "%s"    ""
+\Format pgm        pgm     PGM                    "" "%s"      "%s"    ""
+\Format png        png     PNG                    "" "%s"      "%s"    ""
+\Format ppm        ppm     PPM                    "" "%s"      "%s"    ""
+\Format tiff       tif     TIFF                   "" "%s"      "%s"    ""
+\Format xbm        xbm     XBM                    "" "%s"      "%s"    ""
+\Format xpm        xpm     XPM                    "" "%s"      "%s"    ""'''])
     addToRC(r'''\Format bmp        bmp     BMP                    "" "%s"      "%s"    ""
 \Format gif        gif     GIF                    "" "%s"      "%s"    ""
 \Format jpg        jpg     JPEG                   "" "%s"      "%s"    ""
@@ -277,7 +493,7 @@ def checkFormatEntries(dtl_tools):
 \Format xpm        xpm     XPM                    "" "%s"      "%s"    ""''' % \
         (iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie) )
     #
-    checkViewer('a text editor', ['sensible-editor', 'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
+    checkViewerEditor('a text editor', ['sensible-editor', 'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
         'nedit', 'gedit', 'notepad'],
         rc_entry = [r'''\Format asciichess asc    "Plain text (chess output)"  "" ""   "%%"    ""
 \Format asciiimage asc    "Plain text (image)"         "" ""   "%%"    ""
@@ -288,16 +504,23 @@ def checkFormatEntries(dtl_tools):
 \Format dot        dot    "Graphviz Dot"          "" ""        "%%"    "vector"
 \Format platex     tex    "LaTeX (pLaTeX)"        "" "" "%%"    "document"
 \Format literate   nw      NoWeb                  N  ""        "%%"    "document"
+\Format sweave     Rnw    "Sweave"                S  "" "%%"    "document"
 \Format lilypond   ly     "LilyPond music"        "" ""        "%%"    "vector"
 \Format latex      tex    "LaTeX (plain)"         L  ""        "%%"    "document"
 \Format pdflatex   tex    "LaTeX (pdflatex)"      "" ""        "%%"    "document"
+\Format xetex      tex    "LaTeX (XeTeX)"         "" ""        "%%"    "document"
 \Format text       txt    "Plain text"            a  ""        "%%"    "document"
 \Format text2      txt    "Plain text (pstotext)" "" ""        "%%"    "document"
 \Format text3      txt    "Plain text (ps2ascii)" "" ""        "%%"    "document"
 \Format text4      txt    "Plain text (catdvi)"   "" ""        "%%"    "document"
 \Format textparagraph txt "Plain Text, Join Lines" "" ""       "%%"    "document"''' ])
  #
-    checkViewer('a BibTeX editor', ['sensible-editor', 'jabref', 'JabRef', \
+    path, xhtmlview = checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
+        rc_entry = [r'\Format xhtml      xhtml   "LyXHTML"              X "%%" ""    "document"'])
+    if xhtmlview == "":
+        addToRC(r'\Format xhtml      xhtml   "LyXHTML"              X "" ""  "document"')
+ #
+    checkEditor('a BibTeX editor', ['sensible-editor', 'jabref', 'JabRef', \
         'pybliographic', 'bibdesk', 'gbib', 'kbib', \
         'kbibtex', 'sixpack', 'bibedit', 'tkbibtex' \
         'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
@@ -306,17 +529,18 @@ def checkFormatEntries(dtl_tools):
     #
     #checkProg('a Postscript interpreter', ['gs'],
     #  rc_entry = [ r'\ps_command "%%"' ])
-    checkViewer('a Postscript previewer', ['kghostview', 'evince', 'gv', 'ghostview -swap'],
+    checkViewer('a Postscript previewer', ['kghostview', 'okular', 'evince', 'gv', 'ghostview -swap'],
         rc_entry = [r'''\Format eps        eps     EPS                    "" "%%"      ""      "vector"
 \Format ps         ps      Postscript             t  "%%"      ""      "document,vector"'''])
-    #
-    checkViewer('a PDF previewer', ['kpdf', 'evince', 'kghostview', 'xpdf', 'acrobat', 'acroread', \
+    # for xdg-open issues look here: http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg151818.html
+    checkViewer('a PDF previewer', ['kpdf', 'okular', 'evince', 'kghostview', 'xpdf', 'acrobat', 'acroread', \
                    'gv', 'ghostview'],
         rc_entry = [r'''\Format pdf        pdf    "PDF (ps2pdf)"          P  "%%"      ""      "document,vector"
 \Format pdf2       pdf    "PDF (pdflatex)"        F  "%%"      ""      "document,vector"
-\Format pdf3       pdf    "PDF (dvipdfm)"         m  "%%"      ""      "document,vector"'''])
+\Format pdf3       pdf    "PDF (dvipdfm)"         m  "%%"      ""      "document,vector"
+\Format pdf4       pdf    "PDF (XeTeX)"           X  "%%"      ""      "document,vector"'''])
     #
-    checkViewer('a DVI previewer', ['xdvi', 'kdvi'],
+    checkViewer('a DVI previewer', ['xdvi', 'kdvi', 'okular', 'yap', 'dviout -Set=!m'],
         rc_entry = [r'\Format dvi        dvi     DVI                    D  "%%"        ""      "document,vector"'])
     if dtl_tools:
         # Windows only: DraftDVI
@@ -325,11 +549,16 @@ def checkFormatEntries(dtl_tools):
     checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
         rc_entry = [r'\Format html       html    HTML                   H  "%%"        ""      "document"'])
     #
-    checkViewer('Noteedit', ['noteedit'],
+    checkViewerEditor('Noteedit', ['noteedit'],
         rc_entry = [r'\Format noteedit   not     Noteedit               "" "%%"        "%%"    "vector"'])
     #
-    checkViewer('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"          "" ""        ""      ""
@@ -348,12 +577,9 @@ def checkFormatEntries(dtl_tools):
 \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"
+\Format wordhtml   html   "HTML (MS Word)"        "" "" ""     "document"
 ''')
 
 
@@ -361,6 +587,9 @@ def checkConverterEntries():
     ''' Check all converters (\converter entries) '''
     checkProg('the pdflatex program', ['pdflatex $$i'],
         rc_entry = [ r'\converter pdflatex   pdf2       "%%"   "latex"' ])
+
+    checkProg('XeTeX', ['xelatex $$i'],
+        rc_entry = [ r'\converter xetex      pdf4       "%%"   "latex"' ])
     
     ''' If we're running LyX in-place then tex2lyx will be found in
             ../src/tex2lyx. Add this directory to the PATH temporarily and
@@ -381,6 +610,10 @@ def checkConverterEntries():
     checkProg('a Noweb -> LaTeX converter', ['noweave -delay -index $$i > $$o'],
         rc_entry = [r'''\converter literate   latex      "%%"  ""
 \converter literate   pdflatex      "%%"       ""'''])
+    #
+    checkProg('a Sweave -> LaTeX converter', ['R CMD Sweave $$i'],
+        rc_entry = [r'''\converter sweave   latex      "%%"    ""
+\converter sweave   pdflatex      "%%" ""'''])
     #
     checkProg('an HTML -> LaTeX converter', ['html2latex $$i', 'gnuhtml2latex $$i', \
         'htmltolatex -input $$i -output $$o', 'java -jar htmltolatex.jar -input $$i -output $$o'],
@@ -388,20 +621,35 @@ def checkConverterEntries():
     #
     checkProg('an MS Word -> LaTeX converter', ['wvCleanLatex $$i $$o'],
         rc_entry = [ r'\converter word       latex      "%%"   ""' ])
-    # 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', \
-        'latex2html -no_subdir -split 0 -show_section_numbers $$i', 'hevea -s $$i'],
-        rc_entry = [ r'\converter latex      html       "%%"   "needaux"' ])
-    if htmlconv.find('htlatex') >= 0 or htmlconv == 'latex2html':
-      addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
+    # 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:
-      addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
+      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', \
+          'latex2html -no_subdir -split 0 -show_section_numbers $$i', 'hevea -s $$i'],
+          rc_entry = [ r'\converter latex      html       "%%" "needaux"' ])
+      if htmlconv.find('htlatex') >= 0 or htmlconv == 'latex2html':
+        addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
+      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'"],
+        "/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"''')
@@ -461,7 +709,7 @@ def checkConverterEntries():
     else:
         addToRC(r'\converter lyxpreview png        ""  ""')
     #  
-    checkProg('a fax program', ['kdeprintfax $$i', 'ksendfax $$i'],
+    checkProg('a fax program', ['kdeprintfax $$i', 'ksendfax $$i', 'hylapex $$i'],
         rc_entry = [ r'\converter ps         fax        "%%"   ""'])
     #
     checkProg('a FIG -> EPS/PPM converter', ['fig2dev'],
@@ -511,6 +759,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 != ''):
@@ -519,7 +776,12 @@ def checkConverterEntries():
         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]) >= 6):
+            if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 11):
+                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
+            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"   ""''')
                 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 9):
@@ -581,10 +843,21 @@ def checkOtherEntries():
     ''' entries other than Format and Converter '''
     checkProg('ChkTeX', ['chktex -n1 -n3 -n6 -n9 -n22 -n25 -n30 -n38'],
         rc_entry = [ r'\chktex_command "%%"' ])
-    checkProg('BibTeX', ['jbibtex', 'bibtex'],
-        rc_entry = [ r'\bibtex_command "%%"' ])
-    checkProg('an index processor', ['texindy', 'makeindex -c -q'],
-        rc_entry = [ r'\index_command "%%"' ])
+    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'],
+        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', '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 "%%"' ])
+    if splitindex == '':
+        checkProg('the splitindex processor (java version)', ['splitindex.class'],
+            rc_entry = [ r'\splitindex_command "java splitindex"' ])
     checkProg('a nomenclature processor', ['makeindex'],
         rc_entry = [ r'\nomencl_command "makeindex -s nomencl.ist"' ])
     ## FIXME: OCTAVE is not used anywhere
@@ -683,75 +956,74 @@ 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
+    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):
+            continue
+        classname = file.split(os.sep)[-1].split('.')[0]
+        for line in open(file).readlines():
+            if p1.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
+            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
 
 
 def checkModulesConfig():
-  removeFiles(['lyxmodules.lst'])
+  removeFiles(['lyxmodules.lst', 'chkmodules.tex'])
 
   logger.info('+checking list of modules... ')
   tx = open('lyxmodules.lst', 'w')
@@ -759,6 +1031,7 @@ def checkModulesConfig():
 ## It has been automatically generated by configure
 ## Use "Options/Reconfigure" if you need to update it after a
 ## configuration change. 
+## "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category"
 ''')
   # build the list of available modules
   foundClasses = []
@@ -780,22 +1053,24 @@ def processModuleFile(file, bool_docbook):
 
         The top of a module file should look like this:
           #\DeclareLyXModule[LaTeX Packages]{ModuleName}
-          #BeginDescription
+          #DescriptionBegin
           #...body of description...
-          #EndDescription
+          #DescriptionEnd
           #Requires: [list of required modules]
           #Excludes: [list of excluded modules]
-        The last two lines are optional
+          #Category: [category name]
+        The last three lines are optional (though do give a category).
         We expect output:
-          "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes"
+          "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*$')
 
-    modname = desc = pkgs = req = excl = ""
+    modname = desc = pkgs = req = excl = catgy = ""
     readingDescription = False
     descLines = []
     filename = file.split(os.sep)[-1]
@@ -835,8 +1110,28 @@ def processModuleFile(file, bool_docbook):
         tmp = [s.strip() for s in excl.split("|")]
         excl = "|".join(tmp)
         continue
+      res = c.search(line)
+      if res != None:
+        catgy = res.group(1)
+        continue
     if modname != "":
-        return '"%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, pkgs, req, excl)
+        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)
     logger.warning("Module file without \DeclareLyXModule line. ")
     return ""
 
@@ -866,7 +1161,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'])
 
 
@@ -925,9 +1220,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