]> git.lyx.org Git - lyx.git/blob - lib/configure.py
Fix CMake for r31189.
[lyx.git] / lib / configure.py
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # file configure.py
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
7
8 # \author Bo Peng
9 # Full author contact details are available in file CREDITS.
10
11 import sys, os, re, shutil, glob, logging
12
13 # set up logging
14 logging.basicConfig(level = logging.DEBUG,
15     format = '%(levelname)s: %(message)s', # ignore application name
16     filename = 'configure.log',
17     filemode = 'w')
18 #
19 # Add a handler to log to console
20 console = logging.StreamHandler()
21 console.setLevel(logging.INFO) # the console only print out general information
22 formatter = logging.Formatter('%(message)s') # only print out the message itself
23 console.setFormatter(formatter)
24 logger = logging.getLogger('LyX')
25 logger.addHandler(console)
26
27 def writeToFile(filename, lines, append = False):
28     " utility function: write or append lines to filename "
29     if append:
30         file = open(filename, 'a')
31     else:
32         file = open(filename, 'w')
33     file.write(lines)
34     file.close()
35
36
37 def addToRC(lines):
38     ''' utility function: shortcut for appending lines to outfile
39         add newline at the end of lines.
40     '''
41     if lines.strip() != '':
42         writeToFile(outfile, lines + '\n', append = True)
43         logger.debug('Add to RC:\n' + lines + '\n\n')
44
45
46 def removeFiles(filenames):
47     '''utility function: 'rm -f'
48         ignore errors when file does not exist, or is a directory.
49     '''
50     for file in filenames:
51         try:
52             os.remove(file)
53             logger.debug('Removing file %s' % file)
54         except:
55             logger.debug('Failed to remove file %s' % file)
56             pass
57
58
59 def cmdOutput(cmd):
60     '''utility function: run a command and get its output as a string
61         cmd: command to run
62     '''
63     fout = os.popen(cmd)
64     output = fout.read()
65     fout.close()
66     return output.strip()
67
68
69 def setEnviron():
70     ''' I do not really know why this is useful, but we might as well keep it.
71         NLS nuisances.
72         Only set these to C if already set.  These must not be set unconditionally
73         because not all systems understand e.g. LANG=C (notably SCO).
74         Fixing LC_MESSAGES prevents Solaris sh from translating var values in set!
75         Non-C LC_CTYPE values break the ctype check.
76     '''
77     os.environ['LANG'] = os.getenv('LANG', 'C')
78     os.environ['LC'] = os.getenv('LC_ALL', 'C')
79     os.environ['LC_MESSAGE'] = os.getenv('LC_MESSAGE', 'C')
80     os.environ['LC_CTYPE'] = os.getenv('LC_CTYPE', 'C')
81
82
83 def createDirectories():
84     ''' Create the build directories if necessary '''
85     for dir in ['bind', 'clipart', 'doc', 'examples', 'images', 'kbd', \
86         'layouts', 'scripts', 'templates', 'ui' ]:
87         if not os.path.isdir( dir ):
88             try:
89                 os.mkdir( dir)
90                 logger.debug('Create directory %s.' % dir)
91             except:
92                 logger.error('Failed to create directory %s.' % dir)
93                 sys.exit(1)
94
95
96 def checkTeXPaths():
97     ''' Determine the path-style needed by the TeX engine on Win32 (Cygwin) '''
98     windows_style_tex_paths = ''
99     if os.name == 'nt' or sys.platform == 'cygwin':
100         from tempfile import mkstemp
101         fd, tmpfname = mkstemp(suffix='.ltx')
102         if os.name == 'nt':
103             inpname = tmpfname.replace('\\', '/')
104         else:
105             inpname = cmdOutput('cygpath -m ' + tmpfname)
106         logname = os.path.basename(inpname.replace('.ltx', '.log'))
107         inpname = inpname.replace('~', '\\string~')
108         os.write(fd, r'\relax')
109         os.close(fd)
110         latex_out = cmdOutput(r'latex "\nonstopmode\input{%s}"' % inpname)
111         if 'Error' in latex_out:
112             logger.warning("configure: TeX engine needs posix-style paths in latex files")
113             windows_style_tex_paths = 'false'
114         else:
115             logger.info("configure: TeX engine needs windows-style paths in latex files")
116             windows_style_tex_paths = 'true'
117         removeFiles([tmpfname, logname, 'texput.log'])
118     return windows_style_tex_paths
119
120
121 ## Searching some useful programs
122 def checkProg(description, progs, rc_entry = [], path = [], not_found = ''):
123     '''
124         This function will search a program in $PATH plus given path
125         If found, return directory and program name (not the options).
126
127         description: description of the program
128
129         progs: check programs, for each prog, the first word is used
130             for searching but the whole string is used to replace
131             %% for a rc_entry. So, feel free to add '$$i' etc for programs.
132
133         path: additional pathes
134
135         rc_entry: entry to outfile, can be
136             1. emtpy: no rc entry will be added
137             2. one pattern: %% will be replaced by the first found program,
138                 or '' if no program is found.
139             3. several patterns for each prog and not_found. This is used 
140                 when different programs have different usages. If you do not 
141                 want not_found entry to be added to the RC file, you can specify 
142                 an entry for each prog and use '' for the not_found entry.
143
144         not_found: the value that should be used instead of '' if no program
145             was found
146
147     '''
148     # one rc entry for each progs plus not_found entry
149     if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
150         logger.error("rc entry should have one item or item for each prog and not_found.")
151         sys.exit(2)
152     logger.info('checking for ' + description + '...')
153     ## print '(' + ','.join(progs) + ')',
154     for idx in range(len(progs)):
155         # ac_prog may have options, ac_word is the command name
156         ac_prog = progs[idx]
157         ac_word = ac_prog.split(' ')[0]
158         msg = '+checking for "' + ac_word + '"... '
159         path = os.environ["PATH"].split(os.pathsep) + path
160         extlist = ['']
161         if os.environ.has_key("PATHEXT"):
162             extlist = extlist + os.environ["PATHEXT"].split(os.pathsep)
163         for ac_dir in path:
164             for ext in extlist:
165                 if os.path.isfile( os.path.join(ac_dir, ac_word + ext) ):
166                     logger.info(msg + ' yes')
167                     # write rc entries for this command
168                     if len(rc_entry) == 1:
169                         addToRC(rc_entry[0].replace('%%', ac_prog))
170                     elif len(rc_entry) > 1:
171                         addToRC(rc_entry[idx].replace('%%', ac_prog))
172                     return [ac_dir, ac_word]
173         # if not successful
174         logger.info(msg + ' no')
175     # write rc entries for 'not found'
176     if len(rc_entry) > 0:  # the last one.
177         addToRC(rc_entry[-1].replace('%%', not_found))
178     return ['', not_found]
179
180
181 ## Searching some useful programs
182 def checkProgAlternatives(description, progs, rc_entry = [], alt_rc_entry = [], path = [], not_found = ''):
183     ''' 
184         The same as checkProg, but additionally, all found programs will be added
185         as alt_rc_entries
186     '''
187     # one rc entry for each progs plus not_found entry
188     if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
189         logger.error("rc entry should have one item or item for each prog and not_found.")
190         sys.exit(2)
191     # check if alt rcs are given
192     if len(alt_rc_entry) > 1 and len(alt_rc_entry) != len(rc_entry):
193         logger.error("invalid alt_rc_entry specification.")
194         sys.exit(2)
195     logger.info('checking for ' + description + '...')
196     ## print '(' + ','.join(progs) + ')',
197     found_prime = False
198     real_ac_dir = ''
199     real_ac_word = not_found
200     for idx in range(len(progs)):
201         # ac_prog may have options, ac_word is the command name
202         ac_prog = progs[idx]
203         ac_word = ac_prog.split(' ')[0]
204         msg = '+checking for "' + ac_word + '"... '
205         path = os.environ["PATH"].split(os.pathsep) + path
206         extlist = ['']
207         if os.environ.has_key("PATHEXT"):
208             extlist = extlist + os.environ["PATHEXT"].split(os.pathsep)
209         found_alt = False
210         for ac_dir in path:
211             for ext in extlist:
212                 if os.path.isfile( os.path.join(ac_dir, ac_word + ext) ):
213                     logger.info(msg + ' yes')
214                     # write rc entries for this command
215                     if found_prime == False:
216                         if len(rc_entry) == 1:
217                             addToRC(rc_entry[0].replace('%%', ac_prog))
218                         elif len(rc_entry) > 1:
219                             addToRC(rc_entry[idx].replace('%%', ac_prog))
220                         real_ac_dir = ac_dir
221                         real_ac_word = ac_word
222                         found_prime = True
223                     if len(alt_rc_entry) == 1:
224                         addToRC(alt_rc_entry[0].replace('%%', ac_prog))
225                     elif len(alt_rc_entry) > 1:
226                         addToRC(alt_rc_entry[idx].replace('%%', ac_prog))
227                     found_alt = True
228                     break
229             if found_alt:
230                 break
231         if found_alt == False:
232             # if not successful
233             logger.info(msg + ' no')
234     if found_prime:
235         return [real_ac_dir, real_ac_word]
236     # write rc entries for 'not found'
237     if len(rc_entry) > 0:  # the last one.
238         addToRC(rc_entry[-1].replace('%%', not_found))
239     return ['', not_found]
240
241
242 def checkViewer(description, progs, rc_entry = [], path = []):
243     ''' The same as checkProg, but for viewers and editors '''
244     return checkProg(description, progs, rc_entry, path, not_found = 'auto')
245
246
247 def checkDTLtools():
248     ''' Check whether DTL tools are available (Windows only) '''
249     # Find programs! Returned path is not used now
250     if ((os.name == 'nt' or sys.platform == 'cygwin') and
251             checkProg('DVI to DTL converter', ['dv2dt']) != ['', ''] and
252             checkProg('DTL to DVI converter', ['dt2dv']) != ['', '']):
253         dtl_tools = True
254     else:
255         dtl_tools = False
256     return dtl_tools
257
258
259 def checkLatex(dtl_tools):
260     ''' Check latex, return lyx_check_config '''
261     path, LATEX = checkProg('a Latex2e program', ['latex $$i', 'platex $$i', 'latex2e $$i'])
262     path, PPLATEX = checkProg('a DVI postprocessing program', ['pplatex $$i'])
263     #-----------------------------------------------------------------
264     path, PLATEX = checkProg('pLaTeX, the Japanese LaTeX', ['platex $$i'])
265     if PLATEX != '':
266         # check if PLATEX is pLaTeX2e
267         writeToFile('chklatex.ltx', '''
268 \\nonstopmode
269 \\@@end
270 ''')
271         # run platex on chklatex.ltx and check result
272         if cmdOutput(PLATEX + ' chklatex.ltx').find('pLaTeX2e') != -1:
273             # We have the Japanese pLaTeX2e
274             addToRC(r'\converter platex   dvi       "%s"   "latex"' % PLATEX)
275             LATEX = PLATEX
276         else:
277             PLATEX = ''
278             removeFiles(['chklatex.ltx', 'chklatex.log'])
279     #-----------------------------------------------------------------
280     # use LATEX to convert from latex to dvi if PPLATEX is not available    
281     if PPLATEX == '':
282         PPLATEX = LATEX
283     if dtl_tools:
284         # Windows only: DraftDVI
285         addToRC(r'''\converter latex      dvi2       "%s"       "latex"
286 \converter dvi2       dvi        "python -tt $$s/scripts/clean_dvi.py $$i $$o"  ""''' % PPLATEX)
287     else:
288         addToRC(r'\converter latex      dvi        "%s" "latex"' % PPLATEX)
289     # no latex
290     if LATEX != '':
291         # Check if latex is usable
292         writeToFile('chklatex.ltx', '''
293 \\nonstopmode\\makeatletter
294 \\ifx\\undefined\\documentclass\\else
295   \\message{ThisIsLaTeX2e}
296 \\fi
297 \\@@end
298 ''')
299         # run latex on chklatex.ltx and check result
300         if cmdOutput(LATEX + ' chklatex.ltx').find('ThisIsLaTeX2e') != -1:
301             # valid latex2e
302             return LATEX
303         else:
304             logger.warning("Latex not usable (not LaTeX2e) ")
305         # remove temporary files
306         removeFiles(['chklatex.ltx', 'chklatex.log'])
307     return ''
308
309
310 def checkFormatEntries(dtl_tools):  
311     ''' Check all formats (\Format entries) '''
312     checkViewer('a Tgif viewer and editor', ['tgif'],
313         rc_entry = [r'\Format tgif       obj     Tgif                   "" "%%" "%%"    "vector"'])
314     #
315     checkViewer('a FIG viewer and editor', ['xfig', 'jfig3-itext.jar', 'jfig3.jar'],
316         rc_entry = [r'\Format fig        fig     FIG                    "" "%%" "%%"    "vector"'])
317     #
318     checkViewer('a Dia viewer and editor', ['dia'],
319         rc_entry = [r'\Format dia        dia     DIA                    "" "%%" "%%"    "vector"'])
320     #
321     checkViewer('a Grace viewer and editor', ['xmgrace'],
322         rc_entry = [r'\Format agr        agr     Grace                  "" "%%" "%%"    "vector"'])
323     #
324     checkViewer('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'],
325         rc_entry = [r'\Format fen        fen     FEN                    "" "%%" "%%"    ""'])
326     #
327     path, iv = checkViewer('a raster image viewer', ['xv', 'kview', 'gimp-remote', 'gimp'])
328     path, ie = checkViewer('a raster image editor', ['gimp-remote', 'gimp'])
329     addToRC(r'''\Format bmp        bmp     BMP                    "" "%s"       "%s"    ""
330 \Format gif        gif     GIF                    "" "%s"       "%s"    ""
331 \Format jpg        jpg     JPEG                   "" "%s"       "%s"    ""
332 \Format pbm        pbm     PBM                    "" "%s"       "%s"    ""
333 \Format pgm        pgm     PGM                    "" "%s"       "%s"    ""
334 \Format png        png     PNG                    "" "%s"       "%s"    ""
335 \Format ppm        ppm     PPM                    "" "%s"       "%s"    ""
336 \Format tiff       tif     TIFF                   "" "%s"       "%s"    ""
337 \Format xbm        xbm     XBM                    "" "%s"       "%s"    ""
338 \Format xpm        xpm     XPM                    "" "%s"       "%s"    ""''' % \
339         (iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie) )
340     #
341     checkViewer('a text editor', ['sensible-editor', 'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
342         'nedit', 'gedit', 'notepad'],
343         rc_entry = [r'''\Format asciichess asc    "Plain text (chess output)"  "" ""    "%%"    ""
344 \Format asciiimage asc    "Plain text (image)"         "" ""    "%%"    ""
345 \Format asciixfig  asc    "Plain text (Xfig output)"   "" ""    "%%"    ""
346 \Format dateout    tmp    "date (output)"         "" "" "%%"    ""
347 \Format docbook    sgml    DocBook                B  "" "%%"    "document"
348 \Format docbook-xml xml   "Docbook (XML)"         "" "" "%%"    "document"
349 \Format dot        dot    "Graphviz Dot"          "" "" "%%"    "vector"
350 \Format platex     tex    "LaTeX (pLaTeX)"        "" "" "%%"    "document"
351 \Format literate   nw      NoWeb                  N  "" "%%"    "document"
352 \Format sweave     Rnw    "Sweave"                S  "" "%%"    "document"
353 \Format lilypond   ly     "LilyPond music"        "" "" "%%"    "vector"
354 \Format latex      tex    "LaTeX (plain)"         L  "" "%%"    "document"
355 \Format pdflatex   tex    "LaTeX (pdflatex)"      "" "" "%%"    "document"
356 \Format xetex      tex    "LaTeX (XeTeX)"         "" "" "%%"    "document"
357 \Format text       txt    "Plain text"            a  "" "%%"    "document"
358 \Format text2      txt    "Plain text (pstotext)" "" "" "%%"    "document"
359 \Format text3      txt    "Plain text (ps2ascii)" "" "" "%%"    "document"
360 \Format text4      txt    "Plain text (catdvi)"   "" "" "%%"    "document"
361 \Format textparagraph txt "Plain Text, Join Lines" "" ""        "%%"    "document"''' ])
362  #
363     path, xhtmlview = checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
364         rc_entry = [r'\Format xhtml      html   "LyX HTML"              "" "%%" ""    "document"'])
365     if xhtmlview == "":
366         addToRC(r'\Format xhtml      html   "LyX HTML"              "" "" "%%"  "document"')
367  #
368     checkViewer('a BibTeX editor', ['sensible-editor', 'jabref', 'JabRef', \
369         'pybliographic', 'bibdesk', 'gbib', 'kbib', \
370         'kbibtex', 'sixpack', 'bibedit', 'tkbibtex' \
371         'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
372         'nedit', 'gedit', 'notepad'],
373         rc_entry = [r'''\Format bibtex bib    "BibTeX"         "" ""    "%%"    ""''' ])
374     #
375     #checkProg('a Postscript interpreter', ['gs'],
376     #  rc_entry = [ r'\ps_command "%%"' ])
377     checkViewer('a Postscript previewer', ['kghostview', 'okular', 'evince', 'gv', 'ghostview -swap'],
378         rc_entry = [r'''\Format eps        eps     EPS                    "" "%%"       ""      "vector"
379 \Format ps         ps      Postscript             t  "%%"       ""      "document,vector"'''])
380     # for xdg-open issues look here: http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg151818.html
381     checkViewer('a PDF previewer', ['kpdf', 'okular', 'evince', 'kghostview', 'xpdf', 'acrobat', 'acroread', \
382                     'gv', 'ghostview'],
383         rc_entry = [r'''\Format pdf        pdf    "PDF (ps2pdf)"          P  "%%"       ""      "document,vector"
384 \Format pdf2       pdf    "PDF (pdflatex)"        F  "%%"       ""      "document,vector"
385 \Format pdf3       pdf    "PDF (dvipdfm)"         m  "%%"       ""      "document,vector"
386 \Format pdf4       pdf    "PDF (XeTeX)"           X  "%%"       ""      "document,vector"'''])
387     #
388     checkViewer('a DVI previewer', ['xdvi', 'kdvi', 'okular', 'yap', 'dviout -Set=!m'],
389         rc_entry = [r'\Format dvi        dvi     DVI                    D  "%%" ""      "document,vector"'])
390     if dtl_tools:
391         # Windows only: DraftDVI
392         addToRC(r'\Format dvi2       dvi     DraftDVI               ""  ""      ""      "vector"')
393     #
394     checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
395         rc_entry = [r'\Format html       html    HTML                   H  "%%" ""      "document"'])
396     #
397     checkViewer('Noteedit', ['noteedit'],
398         rc_entry = [r'\Format noteedit   not     Noteedit               "" "%%" "%%"    "vector"'])
399     #
400     checkViewer('an OpenDocument viewer', ['swriter', 'oowriter'],
401         rc_entry = [r'\Format odt        odt     OpenDocument           "" "%%" "%%"    "document,vector"'])
402     #
403     # entried that do not need checkProg
404     addToRC(r'''\Format date       ""     "date command"          "" "" ""      ""
405 \Format csv        csv    "Table (CSV)"  "" ""  ""      "document"
406 \Format fax        ""      Fax                    "" "" ""      "document"
407 \Format lyx        lyx     LyX                    "" "" ""      ""
408 \Format lyx13x     lyx13  "LyX 1.3.x"             "" "" ""      "document"
409 \Format lyx14x     lyx14  "LyX 1.4.x"             "" "" ""      "document"
410 \Format lyx15x     lyx15  "LyX 1.5.x"             "" "" ""      "document"
411 \Format lyx16x     lyx16  "LyX 1.6.x"             "" "" ""      "document"
412 \Format clyx       cjklyx "CJK LyX 1.4.x (big5)"  "" "" ""      "document"
413 \Format jlyx       cjklyx "CJK LyX 1.4.x (euc-jp)" "" ""        ""      "document"
414 \Format klyx       cjklyx "CJK LyX 1.4.x (euc-kr)" "" ""        ""      "document"
415 \Format lyxpreview lyxpreview "LyX Preview"       "" "" ""      ""
416 \Format lyxpreview-platex lyxpreview-platex "LyX Preview (pLaTeX)"       "" ""  ""      ""
417 \Format pdftex     pdftex_t PDFTEX                "" "" ""      ""
418 \Format program    ""      Program                "" "" ""      ""
419 \Format pstex      pstex_t PSTEX                  "" "" ""      ""
420 \Format rtf        rtf    "Rich Text Format"      "" "" ""      "document,vector"
421 \Format sxw        sxw    "OpenOffice.Org (sxw)"  ""  ""        ""      "document,vector"
422 \Format wmf        wmf    "Windows Metafile"      "" "" ""      "vector"
423 \Format emf        emf    "Enhanced Metafile"     "" "" ""      "vector"
424 \Format word       doc    "MS Word"               W  "" ""      "document,vector"
425 \Format wordhtml   html   "HTML (MS Word)"        "" "" ""      "document"
426 ''')
427
428
429 def checkConverterEntries():
430     ''' Check all converters (\converter entries) '''
431     checkProg('the pdflatex program', ['pdflatex $$i'],
432         rc_entry = [ r'\converter pdflatex   pdf2       "%%"    "latex"' ])
433
434     checkProg('XeTeX', ['xelatex $$i'],
435         rc_entry = [ r'\converter xetex      pdf4       "%%"    "latex"' ])
436     
437     ''' If we're running LyX in-place then tex2lyx will be found in
438             ../src/tex2lyx. Add this directory to the PATH temporarily and
439             search for tex2lyx.
440             Use PATH to avoid any problems with paths-with-spaces.
441     '''
442     path_orig = os.environ["PATH"]
443     os.environ["PATH"] = os.path.join('..', 'src', 'tex2lyx') + \
444         os.pathsep + path_orig
445
446     checkProg('a LaTeX/Noweb -> LyX converter', ['tex2lyx', 'tex2lyx' + version_suffix],
447         rc_entry = [r'''\converter latex      lyx        "%% -f $$i $$o"        ""
448 \converter literate   lyx        "%% -n -f $$i $$o"     ""'''])
449
450     os.environ["PATH"] = path_orig
451
452     #
453     checkProg('a Noweb -> LaTeX converter', ['noweave -delay -index $$i > $$o'],
454         rc_entry = [r'''\converter literate   latex      "%%"   ""
455 \converter literate   pdflatex      "%%"        ""'''])
456     #
457     checkProg('a Sweave -> LaTeX converter', ['R CMD Sweave $$i'],
458         rc_entry = [r'''\converter sweave   latex      "%%"     ""
459 \converter sweave   pdflatex      "%%"  ""'''])
460     #
461     checkProg('an HTML -> LaTeX converter', ['html2latex $$i', 'gnuhtml2latex $$i', \
462         'htmltolatex -input $$i -output $$o', 'java -jar htmltolatex.jar -input $$i -output $$o'],
463         rc_entry = [ r'\converter html       latex      "%%"    ""' ])
464     #
465     checkProg('an MS Word -> LaTeX converter', ['wvCleanLatex $$i $$o'],
466         rc_entry = [ r'\converter word       latex      "%%"    ""' ])
467     #
468     path, elyxer = checkProg('a LyX -> HTML converter', ['elyxer.py --directory $$r $$i $$o','elyxer --directory $$r $$i $$o'],
469       rc_entry = [ r'\converter lyx      html       "%%"        ""' ])
470     if elyxer.find('elyxer') >= 0:
471       addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py -e html,png,jpg,jpeg,css $$i $$o"''')
472     else:
473       # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
474       path, htmlconv = checkProg('a LaTeX -> HTML converter', ['htlatex $$i', 'htlatex.sh $$i', \
475           '/usr/share/tex4ht/htlatex $$i', 'tth  -t -e2 -L$$b < $$i > $$o', \
476           'latex2html -no_subdir -split 0 -show_section_numbers $$i', 'hevea -s $$i'],
477           rc_entry = [ r'\converter latex      html       "%%"  "needaux"' ])
478       if htmlconv.find('htlatex') >= 0 or htmlconv == 'latex2html':
479         addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
480       else:
481         addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
482
483     # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
484     path, htmlconv = checkProg('a LaTeX -> MS Word converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'", \
485         "htlatex.sh $$i 'html,word' 'symbol/!' '-cvalidate'", \
486         "/usr/share/tex4ht/htlatex $$i 'html,word' 'symbol/!' '-cvalidate'"],
487         rc_entry = [ r'\converter latex      wordhtml   "%%"    "needaux"' ])
488     if htmlconv.find('htlatex') >= 0:
489       addToRC(r'''\copier    wordhtml       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
490     #
491     checkProg('an OpenOffice.org -> LaTeX converter', ['w2l -clean $$i'],
492         rc_entry = [ r'\converter sxw        latex      "%%"    ""' ])
493     #
494     checkProg('an OpenDocument -> LaTeX converter', ['w2l -clean $$i'],
495         rc_entry = [ r'\converter odt        latex      "%%"    ""' ])
496     # According to http://www.tug.org/applications/tex4ht/mn-commands.html
497     # the command mk4ht oolatex $$i has to be used as default,
498     # but as this would require to have Perl installed, in MiKTeX oolatex is
499     # directly available as application.
500     # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
501     # Both SuSE and debian have oolatex
502     checkProg('a LaTeX -> Open Document converter', [
503         'oolatex $$i', 'mk4ht oolatex $$i', 'oolatex.sh $$i', '/usr/share/tex4ht/oolatex $$i',
504         'htlatex $$i \'xhtml,ooffice\' \'ooffice/! -cmozhtf\' \'-coo\' \'-cvalidate\''],
505         rc_entry = [ r'\converter latex      odt        "%%"    "needaux"' ])
506     # On windows it is called latex2rt.exe
507     checkProg('a LaTeX -> RTF converter', ['latex2rtf -p -S -o $$o $$i', 'latex2rt -p -S -o $$o $$i'],
508         rc_entry = [ r'\converter latex      rtf        "%%"    "needaux"' ])
509     #
510     checkProg('a RTF -> HTML converter', ['unrtf --html  $$i > $$o'],
511         rc_entry = [ r'\converter rtf      html        "%%"     ""' ])
512     #
513     checkProg('a PS to PDF converter', ['ps2pdf13 $$i $$o'],
514         rc_entry = [ r'\converter ps         pdf        "%%"    ""' ])
515     #
516     checkProg('a PS to TXT converter', ['pstotext $$i > $$o'],
517         rc_entry = [ r'\converter ps         text2      "%%"    ""' ])
518     #
519     checkProg('a PS to TXT converter', ['ps2ascii $$i $$o'],
520         rc_entry = [ r'\converter ps         text3      "%%"    ""' ])
521     #
522     checkProg('a PS to EPS converter', ['ps2eps $$i'],
523         rc_entry = [ r'\converter ps         eps      "%%"      ""' ])
524     #
525     checkProg('a PDF to PS converter', ['pdf2ps $$i $$o', 'pdftops $$i $$o'],
526         rc_entry = [ r'\converter pdf         ps        "%%"    ""' ])
527     #
528     checkProg('a PDF to EPS converter', ['pdftops -eps -f 1 -l 1 $$i $$o'],
529         rc_entry = [ r'\converter pdf         eps        "%%"   ""' ])
530     #
531     checkProg('a DVI to TXT converter', ['catdvi $$i > $$o'],
532         rc_entry = [ r'\converter dvi        text4      "%%"    ""' ])
533     #
534     checkProg('a DVI to PS converter', ['dvips -o $$o $$i'],
535         rc_entry = [ r'\converter dvi        ps         "%%"    ""' ])
536     #
537     checkProg('a DVI to PDF converter', ['dvipdfmx -o $$o $$i', 'dvipdfm -o $$o $$i'],
538         rc_entry = [ r'\converter dvi        pdf3       "%%"    ""' ])
539     #
540     path, dvipng = checkProg('dvipng', ['dvipng'])
541     if dvipng == "dvipng":
542         addToRC(r'\converter lyxpreview png        "python -tt $$s/scripts/lyxpreview2bitmap.py"        ""')
543     else:
544         addToRC(r'\converter lyxpreview png        ""   ""')
545     #  
546     checkProg('a fax program', ['kdeprintfax $$i', 'ksendfax $$i', 'hylapex $$i'],
547         rc_entry = [ r'\converter ps         fax        "%%"    ""'])
548     #
549     checkProg('a FIG -> EPS/PPM converter', ['fig2dev'],
550         rc_entry = [
551             r'''\converter fig        eps        "fig2dev -L eps $$i $$o"       ""
552 \converter fig        ppm        "fig2dev -L ppm $$i $$o"       ""
553 \converter fig        png        "fig2dev -L png $$i $$o"       ""''',
554             ''])
555     #
556     checkProg('a TIFF -> PS converter', ['tiff2ps $$i > $$o'],
557         rc_entry = [ r'\converter tiff       eps        "%%"    ""', ''])
558     #
559     checkProg('a TGIF -> EPS/PPM converter', ['tgif'],
560         rc_entry = [
561             r'''\converter tgif       eps        "tgif -print -color -eps -stdout $$i > $$o"    ""
562 \converter tgif       png        "tgif -print -color -png -o $$d $$i"   ""
563 \converter tgif       pdf        "tgif -print -color -pdf -stdout $$i > $$o"    ""''',
564             ''])
565     #
566     checkProg('a WMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
567         rc_entry = [ r'\converter wmf        eps        "%%"    ""'])
568     #
569     checkProg('an EMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
570         rc_entry = [ r'\converter emf        eps        "%%"    ""'])
571     #
572     checkProg('an EPS -> PDF converter', ['epstopdf'],
573         rc_entry = [ r'\converter eps        pdf        "epstopdf --outfile=$$o $$i"    ""', ''])
574     #
575     # no agr -> pdf converter, since the pdf library used by gracebat is not
576     # free software and therefore not compiled in in many installations.
577     # Fortunately, this is not a big problem, because we will use epstopdf to
578     # convert from agr to pdf via eps without loss of quality.
579     checkProg('a Grace -> Image converter', ['gracebat'],
580         rc_entry = [
581             r'''\converter agr        eps        "gracebat -hardcopy -printfile $$o -hdevice EPS $$i 2>/dev/null"       ""
582 \converter agr        png        "gracebat -hardcopy -printfile $$o -hdevice PNG $$i 2>/dev/null"       ""
583 \converter agr        jpg        "gracebat -hardcopy -printfile $$o -hdevice JPEG $$i 2>/dev/null"      ""
584 \converter agr        ppm        "gracebat -hardcopy -printfile $$o -hdevice PNM $$i 2>/dev/null"       ""''',
585             ''])
586     #
587     checkProg('a Dot -> PDF converter', ['dot -Tpdf $$i -o $$o'],
588         rc_entry = [ r'\converter dot        pdf        "%%"    ""'])
589     #
590     checkProg('a Dia -> PNG converter', ['dia -e $$o -t png $$i'],
591         rc_entry = [ r'\converter dia        png        "%%"    ""'])
592     #
593     checkProg('a Dia -> EPS converter', ['dia -e $$o -t eps $$i'],
594         rc_entry = [ r'\converter dia        eps        "%%"    ""'])
595     #
596     #
597     path, lilypond = checkProg('a LilyPond -> EPS/PDF/PNG converter', ['lilypond'])
598     if (lilypond != ''):
599         version_string = cmdOutput("lilypond --version")
600         match = re.match('GNU LilyPond (\S+)', version_string)
601         if match:
602             version_number = match.groups()[0]
603             version = version_number.split('.')
604             if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 11):
605                 addToRC(r'''\converter lilypond   eps        "lilypond -dbackend=eps --ps $$i"  ""
606 \converter lilypond   png        "lilypond -dbackend=eps --png $$i"     ""''')
607                 addToRC(r'\converter lilypond   pdf        "lilypond -dbackend=eps --pdf $$i"   ""')
608                 print '+  found LilyPond version %s.' % version_number
609             elif int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 6):
610                 addToRC(r'''\converter lilypond   eps        "lilypond -b eps --ps $$i" ""
611 \converter lilypond   png        "lilypond -b eps --png $$i"    ""''')
612                 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 9):
613                     addToRC(r'\converter lilypond   pdf        "lilypond -b eps --pdf $$i"      ""')
614                 logger.info('+  found LilyPond version %s.' % version_number)
615             else:
616                 logger.info('+  found LilyPond, but version %s is too old.' % version_number)
617         else:
618             logger.info('+  found LilyPond, but could not extract version number.')
619     #
620     checkProg('a Noteedit -> LilyPond converter', ['noteedit --export-lilypond $$i'],
621         rc_entry = [ r'\converter noteedit   lilypond   "%%"    ""', ''])
622     #
623     # FIXME: no rc_entry? comment it out
624     # checkProg('Image converter', ['convert $$i $$o'])
625     #
626     # Entries that do not need checkProg
627     addToRC(r'''\converter lyxpreview ppm        "python -tt $$s/scripts/lyxpreview2bitmap.py"  ""
628 \converter lyxpreview-platex ppm        "python -tt $$s/scripts/lyxpreview-platex2bitmap.py"    ""
629 \converter csv        lyx        "python -tt $$s/scripts/csv2lyx.py $$i $$o"    ""
630 \converter date       dateout    "python -tt $$s/scripts/date.py %d-%m-%Y > $$o"        ""
631 \converter docbook    docbook-xml "cp $$i $$o"  "xml"
632 \converter fen        asciichess "python -tt $$s/scripts/fen2ascii.py $$i $$o"  ""
633 \converter fig        pdftex     "python -tt $$s/scripts/fig2pdftex.py $$i $$o" ""
634 \converter fig        pstex      "python -tt $$s/scripts/fig2pstex.py $$i $$o"  ""
635 \converter lyx        lyx13x     "python -tt $$s/lyx2lyx/lyx2lyx -t 221 $$i > $$o"      ""
636 \converter lyx        lyx14x     "python -tt $$s/lyx2lyx/lyx2lyx -t 245 $$i > $$o"      ""
637 \converter lyx        lyx15x     "python -tt $$s/lyx2lyx/lyx2lyx -t 276 $$i > $$o"      ""
638 \converter lyx        lyx16x     "python -tt $$s/lyx2lyx/lyx2lyx -t 345 $$i > $$o"      ""
639 \converter lyx        clyx       "python -tt $$s/lyx2lyx/lyx2lyx -c big5 -t 245 $$i > $$o"      ""
640 \converter lyx        jlyx       "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp -t 245 $$i > $$o"    ""
641 \converter lyx        klyx       "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr -t 245 $$i > $$o"    ""
642 \converter clyx       lyx        "python -tt $$s/lyx2lyx/lyx2lyx -c big5 $$i > $$o"     ""
643 \converter jlyx       lyx        "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp $$i > $$o"   ""
644 \converter klyx       lyx        "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr $$i > $$o"   ""
645 ''')
646
647
648 def checkDocBook():
649     ''' Check docbook '''
650     path, DOCBOOK = checkProg('SGML-tools 2.x (DocBook), db2x scripts or xsltproc', ['sgmltools', 'db2dvi', 'xsltproc'],
651         rc_entry = [
652             r'''\converter docbook    dvi        "sgmltools -b dvi $$i" ""
653 \converter docbook    html       "sgmltools -b html $$i"        ""''',
654             r'''\converter docbook    dvi        "db2dvi $$i"   ""
655 \converter docbook    html       "db2html $$i"  ""''',
656             r'''\converter docbook    dvi        ""     ""
657 \converter docbook    html       "" ""''',
658             r'''\converter docbook    dvi        ""     ""
659 \converter docbook    html       ""     ""'''])
660     #
661     if DOCBOOK != '':
662         return ('yes', 'true', '\\def\\hasdocbook{yes}')
663     else:
664         return ('no', 'false', '')
665
666
667 def checkOtherEntries():
668     ''' entries other than Format and Converter '''
669     checkProg('ChkTeX', ['chktex -n1 -n3 -n6 -n9 -n22 -n25 -n30 -n38'],
670         rc_entry = [ r'\chktex_command "%%"' ])
671     checkProgAlternatives('BibTeX or alternative programs', ['bibtex', 'bibtex8', 'biber'],
672         rc_entry = [ r'\bibtex_command "%%"' ],
673         alt_rc_entry = [ r'\bibtex_alternatives "%%"' ])
674     checkProg('JBibTeX, the Japanese BibTeX', ['jbibtex', 'bibtex'],
675         rc_entry = [ r'\jbibtex_command "%%"' ])
676     checkProgAlternatives('available index processors', ['texindy', 'makeindex -c -q'],
677         rc_entry = [ r'\index_command "%%"' ],
678         alt_rc_entry = [ r'\index_alternatives "%%"' ])
679     checkProg('an index processor appropriate to Japanese', ['mendex -c -q', 'makeindex -c -q'],
680         rc_entry = [ r'\jindex_command "%%"' ])
681     path, splitindex = checkProg('the splitindex processor', ['splitindex.pl', 'splitindex'],
682         rc_entry = [ r'\splitindex_command "%%"' ])
683     if splitindex == '':
684         checkProg('the splitindex processor (java version)', ['splitindex.class'],
685             rc_entry = [ r'\splitindex_command "java splitindex"' ])
686     checkProg('a nomenclature processor', ['makeindex'],
687         rc_entry = [ r'\nomencl_command "makeindex -s nomencl.ist"' ])
688     ## FIXME: OCTAVE is not used anywhere
689     # path, OCTAVE = checkProg('Octave', ['octave'])
690     ## FIXME: MAPLE is not used anywhere
691     # path, MAPLE = checkProg('Maple', ['maple'])
692     checkProg('a spool command', ['lp', 'lpr'],
693         rc_entry = [
694             r'''\print_spool_printerprefix "-d "
695 \print_spool_command "lp"''',
696             r'''\print_spool_printerprefix "-P",
697 \print_spool_command "lpr"''',
698             ''])
699     # Add the rest of the entries (no checkProg is required)
700     addToRC(r'''\copier    fig        "python -tt $$s/scripts/fig_copy.py $$i $$o"
701 \copier    pstex      "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
702 \copier    pdftex     "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
703 \copier    program    "python -tt $$s/scripts/ext_copy.py $$i $$o"
704 ''')
705
706
707 def processLayoutFile(file, bool_docbook):
708     ''' process layout file and get a line of result
709         
710         Declare lines look like this: (article.layout, scrbook.layout, svjog.layout)
711         
712         \DeclareLaTeXClass{article}
713         \DeclareLaTeXClass[scrbook]{book (koma-script)}
714         \DeclareLaTeXClass[svjour,svjog.clo]{article (Springer - svjour/jog)}
715
716         we expect output:
717         
718         "article" "article" "article" "false"
719         "scrbook" "scrbook" "book (koma-script)" "false"
720         "svjog" "svjour" "article (Springer - svjour/jog)" "false"
721     '''
722     classname = file.split(os.sep)[-1].split('.')[0]
723     # return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclareLaTeXClass[a,b,c]{article}
724     p = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
725     for line in open(file).readlines():
726         res = p.search(line)
727         if res != None:
728             (classtype, optAll, opt, opt1, desc) = res.groups()
729             avai = {'LaTeX':'false', 'DocBook':bool_docbook}[classtype]
730             if opt == None:
731                 opt = classname
732             return '"%s" "%s" "%s" "%s"\n' % (classname, opt, desc, avai)
733     logger.warning("Layout file " + file + " has no \DeclareXXClass line. ")
734     return ""
735
736
737 def checkLatexConfig(check_config, bool_docbook):
738     ''' Explore the LaTeX configuration 
739         Return None (will be passed to sys.exit()) for success.
740     '''
741     msg = 'checking LaTeX configuration... '
742     # if --without-latex-config is forced, or if there is no previous 
743     # version of textclass.lst, re-generate a default file.
744     if not os.path.isfile('textclass.lst') or not check_config:
745         # remove the files only if we want to regenerate
746         removeFiles(['textclass.lst', 'packages.lst'])
747         #
748         # Then, generate a default textclass.lst. In case configure.py
749         # fails, we still have something to start lyx.
750         logger.info(msg + ' default values')
751         logger.info('+checking list of textclasses... ')
752         tx = open('textclass.lst', 'w')
753         tx.write('''
754 # This file declares layouts and their associated definition files
755 # (include dir. relative to the place where this file is).
756 # It contains only default values, since chkconfig.ltx could not be run
757 # for some reason. Run ./configure.py if you need to update it after a
758 # configuration change.
759 ''')
760         # build the list of available layout files and convert it to commands
761         # for chkconfig.ltx
762         foundClasses = []
763         for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
764             glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
765             # valid file?
766             if not os.path.isfile(file): 
767                 continue
768             # get stuff between /xxxx.layout .
769             classname = file.split(os.sep)[-1].split('.')[0]
770             #  tr ' -' '__'`
771             cleanclass = classname.replace(' ', '_')
772             cleanclass = cleanclass.replace('-', '_')
773             # make sure the same class is not considered twice
774             if foundClasses.count(cleanclass) == 0: # not found before
775                 foundClasses.append(cleanclass)
776                 retval = processLayoutFile(file, bool_docbook)
777                 if retval != "":
778                     tx.write(retval)
779         tx.close()
780         logger.info('\tdone')
781     if not check_config:
782         return None
783     # the following will generate textclass.lst.tmp, and packages.lst.tmp
784     else:
785         logger.info(msg + '\tauto')
786         removeFiles(['wrap_chkconfig.ltx', 'chkconfig.vars', \
787             'chkconfig.classes', 'chklayouts.tex'])
788         rmcopy = False
789         if not os.path.isfile( 'chkconfig.ltx' ):
790             shutil.copyfile( os.path.join(srcdir, 'chkconfig.ltx'), 'chkconfig.ltx' )
791             rmcopy = True
792         writeToFile('wrap_chkconfig.ltx', '%s\n\\input{chkconfig.ltx}\n' % docbook_cmd)
793         # Construct the list of classes to test for.
794         # build the list of available layout files and convert it to commands
795         # for chkconfig.ltx
796         p1 = re.compile(r'\Declare(LaTeX|DocBook)Class')
797         testclasses = list()
798         for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
799             glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
800             if not os.path.isfile(file):
801                 continue
802             classname = file.split(os.sep)[-1].split('.')[0]
803             for line in open(file).readlines():
804                 if p1.search(line) == None:
805                     continue
806                 if line[0] != '#':
807                     logger.error("Wrong input layout file with line '" + line)
808                     sys.exit(3)
809                 testclasses.append("\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()))
810                 break
811         testclasses.sort()
812         cl = open('chklayouts.tex', 'w')
813         for line in testclasses:
814             cl.write(line + '\n')
815         cl.close()
816         #
817         # we have chklayouts.tex, then process it
818         fout = os.popen(LATEX + ' wrap_chkconfig.ltx')
819         while True:
820             line = fout.readline()
821             if not line:
822                 break;
823             if re.match('^\+', line):
824                 logger.info(line.strip())
825         # if the command succeeds, None will be returned
826         ret = fout.close()
827         #
828         # currently, values in chhkconfig are only used to set
829         # \font_encoding
830         values = {}
831         for line in open('chkconfig.vars').readlines():
832             key, val = re.sub('-', '_', line).split('=')
833             val = val.strip()
834             values[key] = val.strip("'")
835         # chk_fontenc may not exist 
836         try:
837             addToRC(r'\font_encoding "%s"' % values["chk_fontenc"])
838         except:
839             pass
840         if rmcopy:   # remove the copied file
841             removeFiles( [ 'chkconfig.ltx' ] )
842         # if configure successed, move textclass.lst.tmp to textclass.lst
843         # and packages.lst.tmp to packages.lst
844         if os.path.isfile('textclass.lst.tmp') and len(open('textclass.lst.tmp').read()) > 0 \
845             and os.path.isfile('packages.lst.tmp') and len(open('packages.lst.tmp').read()) > 0:
846             shutil.move('textclass.lst.tmp', 'textclass.lst')
847             shutil.move('packages.lst.tmp', 'packages.lst')
848         return ret
849
850
851 def checkModulesConfig():
852   removeFiles(['lyxmodules.lst'])
853
854   logger.info('+checking list of modules... ')
855   tx = open('lyxmodules.lst', 'w')
856   tx.write('''## This file declares modules and their associated definition files.
857 ## It has been automatically generated by configure
858 ## Use "Options/Reconfigure" if you need to update it after a
859 ## configuration change. 
860 ## "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category"
861 ''')
862   # build the list of available modules
863   foundClasses = []
864   for file in glob.glob( os.path.join('layouts', '*.module') ) + \
865       glob.glob( os.path.join(srcdir, 'layouts', '*.module' ) ) :
866       # valid file?
867       logger.info(file)
868       if not os.path.isfile(file): 
869           continue
870       retval = processModuleFile(file, bool_docbook)
871       if retval != "":
872           tx.write(retval)
873   tx.close()
874   logger.info('\tdone')
875
876
877 def processModuleFile(file, bool_docbook):
878     ''' process module file and get a line of result
879
880         The top of a module file should look like this:
881           #\DeclareLyXModule[LaTeX Packages]{ModuleName}
882           #DescriptionBegin
883           #...body of description...
884           #DescriptionEnd
885           #Requires: [list of required modules]
886           #Excludes: [list of excluded modules]
887           #Category: [category name]
888         The last three lines are optional (though do give a category).
889         We expect output:
890           "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes" "Category"
891     '''
892     p = re.compile(r'\DeclareLyXModule\s*(?:\[([^]]*?)\])?{(.*)}')
893     r = re.compile(r'#+\s*Requires: (.*)')
894     x = re.compile(r'#+\s*Excludes: (.*)')
895     c = re.compile(r'#+\s*Category: (.*)')
896     b = re.compile(r'#+\s*DescriptionBegin\s*$')
897     e = re.compile(r'#+\s*DescriptionEnd\s*$')
898
899     modname = desc = pkgs = req = excl = catgy = ""
900     readingDescription = False
901     descLines = []
902     filename = file.split(os.sep)[-1]
903     filename = filename[:-7]
904
905     for line in open(file).readlines():
906       if readingDescription:
907         res = e.search(line)
908         if res != None:
909           readingDescription = False
910           desc = " ".join(descLines)
911           continue
912         descLines.append(line[1:].strip())
913         continue
914       res = b.search(line)
915       if res != None:
916         readingDescription = True
917         continue
918       res = p.search(line)
919       if res != None:
920           (pkgs, modname) = res.groups()
921           if pkgs == None:
922             pkgs = ""
923           else:
924             tmp = [s.strip() for s in pkgs.split(",")]
925             pkgs = ",".join(tmp)
926           continue
927       res = r.search(line)
928       if res != None:
929         req = res.group(1)
930         tmp = [s.strip() for s in req.split("|")]
931         req = "|".join(tmp)
932         continue
933       res = x.search(line)
934       if res != None:
935         excl = res.group(1)
936         tmp = [s.strip() for s in excl.split("|")]
937         excl = "|".join(tmp)
938         continue
939       res = c.search(line)
940       if res != None:
941         catgy = res.group(1)
942         continue
943     if modname != "":
944         return '"%s" "%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, pkgs, req, excl, catgy)
945     logger.warning("Module file without \DeclareLyXModule line. ")
946     return ""
947
948
949 def checkTeXAllowSpaces():
950     ''' Let's check whether spaces are allowed in TeX file names '''
951     tex_allows_spaces = 'false'
952     if lyx_check_config:
953         msg = "Checking whether TeX allows spaces in file names... "
954         writeToFile('a b.tex', r'\message{working^^J}' )
955         if os.name == 'nt':
956             latex_out = cmdOutput(LATEX + r""" "\nonstopmode\input{\"a b\"}" """)
957         else:
958             latex_out = cmdOutput(LATEX + r""" '\nonstopmode\input{"a b"}' """)
959         if 'working' in latex_out:
960             logger.info(msg + 'yes')
961             tex_allows_spaces = 'true'
962         else:
963             logger.info(msg + 'no')
964             tex_allows_spaces = 'false'
965         addToRC(r'\tex_allows_spaces ' + tex_allows_spaces)
966         removeFiles( [ 'a b.tex', 'a b.log', 'texput.log' ])
967
968
969 def removeTempFiles():
970     # Final clean-up
971     if not lyx_keep_temps:
972         removeFiles(['chkconfig.vars',  \
973             'wrap_chkconfig.ltx', 'wrap_chkconfig.log', \
974             'chklayouts.tex', 'missfont.log', 
975             'chklatex.ltx', 'chklatex.log'])
976
977
978 if __name__ == '__main__':
979     lyx_check_config = True
980     outfile = 'lyxrc.defaults'
981     rc_entries = ''
982     lyx_keep_temps = False
983     version_suffix = ''
984     ## Parse the command line
985     for op in sys.argv[1:]:   # default shell/for list is $*, the options
986         if op in [ '-help', '--help', '-h' ]:
987             print '''Usage: configure [options]
988 Options:
989     --help                   show this help lines
990     --keep-temps             keep temporary files (for debug. purposes)
991     --without-latex-config   do not run LaTeX to determine configuration
992     --with-version-suffix=suffix suffix of binary installed files
993 '''
994             sys.exit(0)
995         elif op == '--without-latex-config':
996             lyx_check_config = False
997         elif op == '--keep-temps':
998             lyx_keep_temps = True
999         elif op[0:22] == '--with-version-suffix=':  # never mind if op is not long enough
1000             version_suffix = op[22:]
1001         else:
1002             print "Unknown option", op
1003             sys.exit(1)
1004     #
1005     # check if we run from the right directory
1006     srcdir = os.path.dirname(sys.argv[0])
1007     if srcdir == '':
1008         srcdir = '.'
1009     if not os.path.isfile( os.path.join(srcdir, 'chkconfig.ltx') ):
1010         logger.error("configure: error: cannot find chkconfig.ltx script")
1011         sys.exit(1)
1012     setEnviron()
1013     createDirectories()
1014     windows_style_tex_paths = checkTeXPaths()
1015     dtl_tools = checkDTLtools()
1016     ## Write the first part of outfile
1017     writeToFile(outfile, '''# This file has been automatically generated by LyX' lib/configure.py
1018 # script. It contains default settings that have been determined by
1019 # examining your system. PLEASE DO NOT MODIFY ANYTHING HERE! If you
1020 # want to customize LyX, use LyX' Preferences dialog or modify directly 
1021 # the "preferences" file instead. Any setting in that file will
1022 # override the values given here.
1023 ''')
1024     # check latex
1025     LATEX = checkLatex(dtl_tools)
1026     checkFormatEntries(dtl_tools)
1027     checkConverterEntries()
1028     (chk_docbook, bool_docbook, docbook_cmd) = checkDocBook()
1029     checkTeXAllowSpaces()
1030     if windows_style_tex_paths != '':
1031         addToRC(r'\tex_expects_windows_paths %s' % windows_style_tex_paths)
1032     checkOtherEntries()
1033     # --without-latex-config can disable lyx_check_config
1034     ret = checkLatexConfig(lyx_check_config and LATEX != '', bool_docbook)
1035     checkModulesConfig() #lyx_check_config and LATEX != '')
1036     removeTempFiles()
1037     # The return error code can be 256. Because most systems expect an error code
1038     # in the range 0-127, 256 can be interpretted as 'success'. Because we expect
1039     # a None for success, 'ret is not None' is used to exit.
1040     sys.exit(ret is not None)