]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/lyx_2_0.py
Fix a minor bug in the xymatrix lyx2lyx stuff and make it a bit more
[lyx.git] / lib / lyx2lyx / lyx_2_0.py
1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2008 José Matos  <jamatos@lyx.org>
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 """ Convert files to the file format generated by lyx 2.0"""
21
22 import re, string
23 import unicodedata
24 import sys, os
25
26 from parser_tools import find_token, find_end_of, find_tokens, get_value, get_value_string
27
28 ####################################################################
29 # Private helper functions
30
31 def find_end_of_inset(lines, i):
32     " Find end of inset, where lines[i] is included."
33     return find_end_of(lines, i, "\\begin_inset", "\\end_inset")
34
35
36 def add_to_preamble(document, text):
37     """ Add text to the preamble if it is not already there.
38     Only the first line is checked!"""
39
40     if find_token(document.preamble, text[0], 0) != -1:
41         return
42
43     document.preamble.extend(text)
44
45
46 def insert_to_preamble(index, document, text):
47     """ Insert text to the preamble at a given line"""
48
49     document.preamble.insert(index, text)
50
51
52 def read_unicodesymbols():
53     " Read the unicodesymbols list of unicode characters and corresponding commands."
54     pathname = os.path.abspath(os.path.dirname(sys.argv[0]))
55     fp = open(os.path.join(pathname.strip('lyx2lyx'), 'unicodesymbols'))
56     spec_chars = []
57     # Two backslashes, followed by some non-word character, and then a character
58     # in brackets. The idea is to check for constructs like: \"{u}, which is how
59     # they are written in the unicodesymbols file; but they can also be written
60     # as: \"u or even \" u.
61     r = re.compile(r'\\\\(\W)\{(\w)\}')
62     for line in fp.readlines():
63         if line[0] != '#' and line.strip() != "":
64             line=line.replace(' "',' ') # remove all quotation marks with spaces before
65             line=line.replace('" ',' ') # remove all quotation marks with spaces after
66             line=line.replace(r'\"','"') # replace \" by " (for characters with diaeresis)
67             try:
68                 [ucs4,command,dead] = line.split(None,2)
69                 if command[0:1] != "\\":
70                     continue
71                 spec_chars.append([command, unichr(eval(ucs4))])
72             except:
73                 continue
74             m = r.match(command)
75             if m != None:
76                 command = "\\\\"
77                 # If the character is a double-quote, then we need to escape it, too,
78                 # since it is done that way in the LyX file.
79                 if m.group(1) == "\"":
80                     command += "\\"
81                 commandbl = command
82                 command += m.group(1) + m.group(2)
83                 commandbl += m.group(1) + ' ' + m.group(2)
84                 spec_chars.append([command, unichr(eval(ucs4))])
85                 spec_chars.append([commandbl, unichr(eval(ucs4))])
86     fp.close()
87     return spec_chars
88
89
90 unicode_reps = read_unicodesymbols()
91
92
93 def put_cmd_in_ert(string):
94     for rep in unicode_reps:
95         string = string.replace(rep[1], rep[0].replace('\\\\', '\\'))
96     string = string.replace('\\', "\\backslash\n")
97     string = "\\begin_inset ERT\nstatus collapsed\n\\begin_layout Plain Layout\n" \
98       + string + "\n\\end_layout\n\\end_inset"
99     return string
100
101
102 def lyx2latex(document, lines):
103     'Convert some LyX stuff into corresponding LaTeX stuff, as best we can.'
104     # clean up multiline stuff
105     content = ""
106     ert_end = 0
107
108     for curline in range(len(lines)):
109       line = lines[curline]
110       if line.startswith("\\begin_inset ERT"):
111           # We don't want to replace things inside ERT, so figure out
112           # where the end of the inset is.
113           ert_end = find_end_of_inset(lines, curline + 1)
114           continue
115       elif line.startswith("\\begin_inset Formula"):
116           line = line[20:]
117       elif line.startswith("\\begin_inset Quotes"):
118           # For now, we do a very basic reversion. Someone who understands
119           # quotes is welcome to fix it up.
120           qtype = line[20:].strip()
121           # lang = qtype[0]
122           side = qtype[1]
123           dbls = qtype[2]
124           if side == "l":
125               if dbls == "d":
126                   line = "``"
127               else:
128                   line = "`"
129           else:
130               if dbls == "d":
131                   line = "''"
132               else:
133                   line = "'"
134       elif line.isspace() or \
135             line.startswith("\\begin_layout") or \
136             line.startswith("\\end_layout") or \
137             line.startswith("\\begin_inset") or \
138             line.startswith("\\end_inset") or \
139             line.startswith("\\lang") or \
140             line.strip() == "status collapsed" or \
141             line.strip() == "status open":
142           #skip all that stuff
143           continue
144
145       # this needs to be added to the preamble because of cases like
146       # \textmu, \textbackslash, etc.
147       add_to_preamble(document, ['% added by lyx2lyx for converted index entries',
148                                  '\\@ifundefined{textmu}',
149                                  ' {\\usepackage{textcomp}}{}'])
150       # a lossless reversion is not possible
151       # try at least to handle some common insets and settings
152       if ert_end >= curline:
153           line = line.replace(r'\backslash', r'\\')
154       else:
155           line = line.replace('&', '\\&{}')
156           line = line.replace('#', '\\#{}')
157           line = line.replace('^', '\\^{}')
158           line = line.replace('%', '\\%{}')
159           line = line.replace('_', '\\_{}')
160           line = line.replace('$', '\\${}')
161
162           # Do the LyX text --> LaTeX conversion
163           for rep in unicode_reps:
164             line = line.replace(rep[1], rep[0] + "{}")
165           line = line.replace(r'\backslash', r'\textbackslash{}')
166           line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}')
167           line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}')
168           line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}')
169           line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}')
170           line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}')
171           line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}')
172           line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}')
173           line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}')
174           line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'')
175       content += line
176     return content
177
178
179 def latex_length(string):
180     'Convert lengths to their LaTeX representation.'
181     i = 0
182     percent = False
183     # the string has the form
184     # ValueUnit+ValueUnit-ValueUnit or
185     # ValueUnit+-ValueUnit
186     # the + and - (glue lengths) are optional
187     # the + always precedes the -
188
189     # Convert relative lengths to LaTeX units
190     units = {"text%":"\\textwidth", "col%":"\\columnwidth",
191              "page%":"\\pagewidth", "line%":"\\linewidth",
192              "theight%":"\\textheight", "pheight%":"\\pageheight"}
193     for unit in units.keys():
194         i = string.find(unit)
195         if i != -1:
196             percent = True
197             minus = string.rfind("-", 1, i)
198             plus = string.rfind("+", 0, i)
199             latex_unit = units[unit]
200             if plus == -1 and minus == -1:
201                 value = string[:i]
202                 value = str(float(value)/100)
203                 end = string[i + len(unit):]
204                 string = value + latex_unit + end
205             if plus > minus:
206                 value = string[plus+1:i]
207                 value = str(float(value)/100)
208                 begin = string[:plus+1]
209                 end = string[i+len(unit):]
210                 string = begin + value + latex_unit + end
211             if plus < minus:
212                 value = string[minus+1:i]
213                 value = str(float(value)/100)
214                 begin = string[:minus+1]
215                 string = begin + value + latex_unit
216
217     # replace + and -, but only if the - is not the first character
218     string = string[0] + string[1:].replace("+", " plus ").replace("-", " minus ")
219     # handle the case where "+-1mm" was used, because LaTeX only understands
220     # "plus 1mm minus 1mm"
221     if string.find("plus  minus"):
222         lastvaluepos = string.rfind(" ")
223         lastvalue = string[lastvaluepos:]
224         string = string.replace("  ", lastvalue + " ")
225     if percent ==  False:
226         return "False," + string
227     else:
228         return "True," + string
229         
230
231 ####################################################################
232
233
234 def revert_swiss(document):
235     " Set language german-ch to ngerman "
236     i = 0
237     if document.language == "german-ch":
238         document.language = "ngerman"
239         i = find_token(document.header, "\\language", 0)
240         if i != -1:
241             document.header[i] = "\\language ngerman"
242     j = 0
243     while True:
244         j = find_token(document.body, "\\lang german-ch", j)
245         if j == -1:
246             return
247         document.body[j] = document.body[j].replace("\\lang german-ch", "\\lang ngerman")
248         j = j + 1
249
250
251 def revert_tabularvalign(document):
252    " Revert the tabular valign option "
253    i = 0
254    while True:
255        i = find_token(document.body, "\\begin_inset Tabular", i)
256        if i == -1:
257            return
258        j = find_token(document.body, "</cell>", i)
259        if j == -1:
260            document.warning("Malformed LyX document: Could not find end of tabular cell.")
261            i = j
262            continue
263        # don't set a box for longtables, only delete tabularvalignment
264        # the alignment is 2 lines below \\begin_inset Tabular
265        p = document.body[i+2].find("islongtable")
266        if p > -1:
267            q = document.body[i+2].find("tabularvalignment")
268            if q > -1:
269                document.body[i+2] = document.body[i+2][:q-1]
270                document.body[i+2] = document.body[i+2] + '>'
271            i = i + 1
272
273        # when no longtable
274        if p == -1:
275          tabularvalignment = 'c'
276          # which valignment is specified?
277          m = document.body[i+2].find('tabularvalignment="top"')
278          if m > -1:
279              tabularvalignment = 't'
280          m = document.body[i+2].find('tabularvalignment="bottom"')
281          if m > -1:
282              tabularvalignment = 'b'
283          # delete tabularvalignment
284          q = document.body[i+2].find("tabularvalignment")
285          if q > -1:
286              document.body[i+2] = document.body[i+2][:q-1]
287              document.body[i+2] = document.body[i+2] + '>'
288
289          # don't add a box when centered
290          if tabularvalignment == 'c':
291              i = j
292              continue
293          subst = ['\\end_layout', '\\end_inset']
294          document.body[j:j] = subst # just inserts those lines
295          subst = ['\\begin_inset Box Frameless',
296              'position "' + tabularvalignment +'"',
297              'hor_pos "c"',
298              'has_inner_box 1',
299              'inner_pos "c"',
300              'use_parbox 0',
301              # we don't know the width, assume 50%
302              'width "50col%"',
303              'special "none"',
304              'height "1in"',
305              'height_special "totalheight"',
306              'status open',
307              '',
308              '\\begin_layout Plain Layout']
309          document.body[i:i] = subst # this just inserts the array at i
310          i += len(subst) + 2 # adjust i to save a few cycles
311
312
313 def revert_phantom(document):
314     " Reverts phantom to ERT "
315     i = 0
316     j = 0
317     while True:
318       i = find_token(document.body, "\\begin_inset Phantom Phantom", i)
319       if i == -1:
320           return
321       substi = document.body[i].replace('\\begin_inset Phantom Phantom', \
322                 '\\begin_inset ERT\nstatus collapsed\n\n' \
323                 '\\begin_layout Plain Layout\n\n\n\\backslash\n' \
324                 'phantom{\n\\end_layout\n\n\\end_inset\n')
325       substi = substi.split('\n')
326       document.body[i : i+4] = substi
327       i += len(substi)
328       j = find_token(document.body, "\\end_layout", i)
329       if j == -1:
330           document.warning("Malformed LyX document: Could not find end of Phantom inset.")
331           return
332       substj = document.body[j].replace('\\end_layout', \
333                 '\\size default\n\n\\begin_inset ERT\nstatus collapsed\n\n' \
334                 '\\begin_layout Plain Layout\n\n' \
335                 '}\n\\end_layout\n\n\\end_inset\n')
336       substj = substj.split('\n')
337       document.body[j : j+4] = substj
338       i += len(substj)
339
340
341 def revert_hphantom(document):
342     " Reverts hphantom to ERT "
343     i = 0
344     j = 0
345     while True:
346       i = find_token(document.body, "\\begin_inset Phantom HPhantom", i)
347       if i == -1:
348           return
349       substi = document.body[i].replace('\\begin_inset Phantom HPhantom', \
350                 '\\begin_inset ERT\nstatus collapsed\n\n' \
351                 '\\begin_layout Plain Layout\n\n\n\\backslash\n' \
352                 'hphantom{\n\\end_layout\n\n\\end_inset\n')
353       substi = substi.split('\n')
354       document.body[i : i+4] = substi
355       i += len(substi)
356       j = find_token(document.body, "\\end_layout", i)
357       if j == -1:
358           document.warning("Malformed LyX document: Could not find end of HPhantom inset.")
359           return
360       substj = document.body[j].replace('\\end_layout', \
361                 '\\size default\n\n\\begin_inset ERT\nstatus collapsed\n\n' \
362                 '\\begin_layout Plain Layout\n\n' \
363                 '}\n\\end_layout\n\n\\end_inset\n')
364       substj = substj.split('\n')
365       document.body[j : j+4] = substj
366       i += len(substj)
367
368
369 def revert_vphantom(document):
370     " Reverts vphantom to ERT "
371     i = 0
372     j = 0
373     while True:
374       i = find_token(document.body, "\\begin_inset Phantom VPhantom", i)
375       if i == -1:
376           return
377       substi = document.body[i].replace('\\begin_inset Phantom VPhantom', \
378                 '\\begin_inset ERT\nstatus collapsed\n\n' \
379                 '\\begin_layout Plain Layout\n\n\n\\backslash\n' \
380                 'vphantom{\n\\end_layout\n\n\\end_inset\n')
381       substi = substi.split('\n')
382       document.body[i : i+4] = substi
383       i += len(substi)
384       j = find_token(document.body, "\\end_layout", i)
385       if j == -1:
386           document.warning("Malformed LyX document: Could not find end of VPhantom inset.")
387           return
388       substj = document.body[j].replace('\\end_layout', \
389                 '\\size default\n\n\\begin_inset ERT\nstatus collapsed\n\n' \
390                 '\\begin_layout Plain Layout\n\n' \
391                 '}\n\\end_layout\n\n\\end_inset\n')
392       substj = substj.split('\n')
393       document.body[j : j+4] = substj
394       i += len(substj)
395
396
397 def revert_xetex(document):
398     " Reverts documents that use XeTeX "
399     i = find_token(document.header, '\\use_xetex', 0)
400     if i == -1:
401         document.warning("Malformed LyX document: Missing \\use_xetex.")
402         return
403     if get_value(document.header, "\\use_xetex", i) == 'false':
404         del document.header[i]
405         return
406     del document.header[i]
407     # 1.) set doc encoding to utf8-plain
408     i = find_token(document.header, "\\inputencoding", 0)
409     if i == -1:
410         document.warning("Malformed LyX document: Missing \\inputencoding.")
411     document.header[i] = "\\inputencoding utf8-plain"
412     # 2.) check font settings
413     l = find_token(document.header, "\\font_roman", 0)
414     if l == -1:
415         document.warning("Malformed LyX document: Missing \\font_roman.")
416     line = document.header[l]
417     l = re.compile(r'\\font_roman (.*)$')
418     m = l.match(line)
419     roman = m.group(1)
420     l = find_token(document.header, "\\font_sans", 0)
421     if l == -1:
422         document.warning("Malformed LyX document: Missing \\font_sans.")
423     line = document.header[l]
424     l = re.compile(r'\\font_sans (.*)$')
425     m = l.match(line)
426     sans = m.group(1)
427     l = find_token(document.header, "\\font_typewriter", 0)
428     if l == -1:
429         document.warning("Malformed LyX document: Missing \\font_typewriter.")
430     line = document.header[l]
431     l = re.compile(r'\\font_typewriter (.*)$')
432     m = l.match(line)
433     typewriter = m.group(1)
434     osf = get_value(document.header, '\\font_osf', 0) == "true"
435     sf_scale = float(get_value(document.header, '\\font_sf_scale', 0))
436     tt_scale = float(get_value(document.header, '\\font_tt_scale', 0))
437     # 3.) set preamble stuff
438     pretext = '%% This document must be processed with xelatex!\n'
439     pretext += '\\usepackage{fontspec}\n'
440     if roman != "default":
441         pretext += '\\setmainfont[Mapping=tex-text]{' + roman + '}\n'
442     if sans != "default":
443         pretext += '\\setsansfont['
444         if sf_scale != 100:
445             pretext += 'Scale=' + str(sf_scale / 100) + ','
446         pretext += 'Mapping=tex-text]{' + sans + '}\n'
447     if typewriter != "default":
448         pretext += '\\setmonofont'
449         if tt_scale != 100:
450             pretext += '[Scale=' + str(tt_scale / 100) + ']'
451         pretext += '{' + typewriter + '}\n'
452     if osf:
453         pretext += '\\defaultfontfeatures{Numbers=OldStyle}\n'
454     pretext += '\usepackage{xunicode}\n'
455     pretext += '\usepackage{xltxtra}\n'
456     insert_to_preamble(0, document, pretext)
457     # 4.) reset font settings
458     i = find_token(document.header, "\\font_roman", 0)
459     if i == -1:
460         document.warning("Malformed LyX document: Missing \\font_roman.")
461     document.header[i] = "\\font_roman default"
462     i = find_token(document.header, "\\font_sans", 0)
463     if i == -1:
464         document.warning("Malformed LyX document: Missing \\font_sans.")
465     document.header[i] = "\\font_sans default"
466     i = find_token(document.header, "\\font_typewriter", 0)
467     if i == -1:
468         document.warning("Malformed LyX document: Missing \\font_typewriter.")
469     document.header[i] = "\\font_typewriter default"
470     i = find_token(document.header, "\\font_osf", 0)
471     if i == -1:
472         document.warning("Malformed LyX document: Missing \\font_osf.")
473     document.header[i] = "\\font_osf false"
474     i = find_token(document.header, "\\font_sc", 0)
475     if i == -1:
476         document.warning("Malformed LyX document: Missing \\font_sc.")
477     document.header[i] = "\\font_sc false"
478     i = find_token(document.header, "\\font_sf_scale", 0)
479     if i == -1:
480         document.warning("Malformed LyX document: Missing \\font_sf_scale.")
481     document.header[i] = "\\font_sf_scale 100"
482     i = find_token(document.header, "\\font_tt_scale", 0)
483     if i == -1:
484         document.warning("Malformed LyX document: Missing \\font_tt_scale.")
485     document.header[i] = "\\font_tt_scale 100"
486
487
488 def revert_outputformat(document):
489     " Remove default output format param "
490     i = find_token(document.header, '\\default_output_format', 0)
491     if i == -1:
492         document.warning("Malformed LyX document: Missing \\default_output_format.")
493         return
494     del document.header[i]
495
496
497 def revert_backgroundcolor(document):
498     " Reverts background color to preamble code "
499     i = 0
500     colorcode = ""
501     while True:
502       i = find_token(document.header, "\\backgroundcolor", i)
503       if i == -1:
504           return
505       colorcode = get_value(document.header, '\\backgroundcolor', 0)
506       del document.header[i]
507       # don't clutter the preamble if backgroundcolor is not set
508       if colorcode == "#ffffff":
509           continue
510       # the color code is in the form #rrggbb where every character denotes a hex number
511       # convert the string to an int
512       red = string.atoi(colorcode[1:3],16)
513       # we want the output "0.5" for the value "127" therefore add here
514       if red != 0:
515           red = red + 1
516       redout = float(red) / 256
517       green = string.atoi(colorcode[3:5],16)
518       if green != 0:
519           green = green + 1
520       greenout = float(green) / 256
521       blue = string.atoi(colorcode[5:7],16)
522       if blue != 0:
523           blue = blue + 1
524       blueout = float(blue) / 256
525       # write the preamble
526       insert_to_preamble(0, document,
527                            '% Commands inserted by lyx2lyx to set the background color\n'
528                            + '\\@ifundefined{definecolor}{\\usepackage{color}}{}\n'
529                            + '\\definecolor{page_backgroundcolor}{rgb}{'
530                            + str(redout) + ', ' + str(greenout)
531                            + ', ' + str(blueout) + '}\n'
532                            + '\\pagecolor{page_backgroundcolor}\n')
533
534
535 def revert_splitindex(document):
536     " Reverts splitindex-aware documents "
537     i = find_token(document.header, '\\use_indices', 0)
538     if i == -1:
539         document.warning("Malformed LyX document: Missing \\use_indices.")
540         return
541     indices = get_value(document.header, "\\use_indices", i)
542     preamble = ""
543     if indices == "true":
544          preamble += "\\usepackage{splitidx}\n"
545     del document.header[i]
546     i = 0
547     while True:
548         i = find_token(document.header, "\\index", i)
549         if i == -1:
550             break
551         k = find_token(document.header, "\\end_index", i)
552         if k == -1:
553             document.warning("Malformed LyX document: Missing \\end_index.")
554             return
555         line = document.header[i]
556         l = re.compile(r'\\index (.*)$')
557         m = l.match(line)
558         iname = m.group(1)
559         ishortcut = get_value(document.header, '\\shortcut', i, k)
560         if ishortcut != "" and indices == "true":
561             preamble += "\\newindex[" + iname + "]{" + ishortcut + "}\n"
562         del document.header[i:k+1]
563         i = 0
564     if preamble != "":
565         insert_to_preamble(0, document, preamble)
566     i = 0
567     while True:
568         i = find_token(document.body, "\\begin_inset Index", i)
569         if i == -1:
570             break
571         line = document.body[i]
572         l = re.compile(r'\\begin_inset Index (.*)$')
573         m = l.match(line)
574         itype = m.group(1)
575         if itype == "idx" or indices == "false":
576             document.body[i] = "\\begin_inset Index"
577         else:
578             k = find_end_of_inset(document.body, i)
579             if k == -1:
580                  return
581             content = lyx2latex(document, document.body[i:k])
582             # escape quotes
583             content = content.replace('"', r'\"')
584             subst = [put_cmd_in_ert("\\sindex[" + itype + "]{" + content + "}")]
585             document.body[i:k+1] = subst
586         i = i + 1
587     i = 0
588     while True:
589         i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
590         if i == -1:
591             return
592         k = find_end_of_inset(document.body, i)
593         ptype = get_value(document.body, 'type', i, k).strip('"')
594         if ptype == "idx":
595             j = find_token(document.body, "type", i, k)
596             del document.body[j]
597         elif indices == "false":
598             del document.body[i:k+1]
599         else:
600             subst = [put_cmd_in_ert("\\printindex[" + ptype + "]{}")]
601             document.body[i:k+1] = subst
602         i = i + 1
603
604
605 def convert_splitindex(document):
606     " Converts index and printindex insets to splitindex-aware format "
607     i = 0
608     while True:
609         i = find_token(document.body, "\\begin_inset Index", i)
610         if i == -1:
611             break
612         document.body[i] = document.body[i].replace("\\begin_inset Index",
613             "\\begin_inset Index idx")
614         i = i + 1
615     i = 0
616     while True:
617         i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
618         if i == -1:
619             return
620         if document.body[i + 1].find('LatexCommand printindex') == -1:
621             document.warning("Malformed LyX document: Incomplete printindex inset.")
622             return
623         subst = ["LatexCommand printindex", 
624             "type \"idx\""]
625         document.body[i + 1:i + 2] = subst
626         i = i + 1
627
628
629 def revert_subindex(document):
630     " Reverts \\printsubindex CommandInset types "
631     i = find_token(document.header, '\\use_indices', 0)
632     if i == -1:
633         document.warning("Malformed LyX document: Missing \\use_indices.")
634         return
635     indices = get_value(document.header, "\\use_indices", i)
636     i = 0
637     while True:
638         i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
639         if i == -1:
640             return
641         k = find_end_of_inset(document.body, i)
642         ctype = get_value(document.body, 'LatexCommand', i, k)
643         if ctype != "printsubindex":
644             i = i + 1
645             continue
646         ptype = get_value(document.body, 'type', i, k).strip('"')
647         if indices == "false":
648             del document.body[i:k+1]
649         else:
650             subst = [put_cmd_in_ert("\\printsubindex[" + ptype + "]{}")]
651             document.body[i:k+1] = subst
652         i = i + 1
653
654
655 def revert_printindexall(document):
656     " Reverts \\print[sub]index* CommandInset types "
657     i = find_token(document.header, '\\use_indices', 0)
658     if i == -1:
659         document.warning("Malformed LyX document: Missing \\use_indices.")
660         return
661     indices = get_value(document.header, "\\use_indices", i)
662     i = 0
663     while True:
664         i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
665         if i == -1:
666             return
667         k = find_end_of_inset(document.body, i)
668         ctype = get_value(document.body, 'LatexCommand', i, k)
669         if ctype != "printindex*" and ctype != "printsubindex*":
670             i = i + 1
671             continue
672         if indices == "false":
673             del document.body[i:k+1]
674         else:
675             subst = [put_cmd_in_ert("\\" + ctype + "{}")]
676             document.body[i:k+1] = subst
677         i = i + 1
678
679
680 def revert_strikeout(document):
681     " Reverts \\strikeout character style "
682     while True:
683         i = find_token(document.body, '\\strikeout', 0)
684         if i == -1:
685             return
686         del document.body[i]
687
688
689 def revert_uulinewave(document):
690     " Reverts \\uuline, and \\uwave character styles "
691     while True:
692         i = find_token(document.body, '\\uuline', 0)
693         if i == -1:
694             break
695         del document.body[i]
696     while True:
697         i = find_token(document.body, '\\uwave', 0)
698         if i == -1:
699             return
700         del document.body[i]
701
702
703 def revert_ulinelatex(document):
704     " Reverts \\uline character style "
705     i = find_token(document.body, '\\bar under', 0)
706     if i == -1:
707         return
708     insert_to_preamble(0, document,
709             '% Commands inserted by lyx2lyx for proper underlining\n'
710             + '\\PassOptionsToPackage{normalem}{ulem}\n'
711             + '\\usepackage{ulem}\n'
712             + '\\let\\cite@rig\\cite\n'
713             + '\\newcommand{\\b@xcite}[2][\\%]{\\def\\def@pt{\\%}\\def\\pas@pt{#1}\n'
714             + '  \\mbox{\\ifx\\def@pt\\pas@pt\\cite@rig{#2}\\else\\cite@rig[#1]{#2}\\fi}}\n'
715             + '\\renewcommand{\\underbar}[1]{{\\let\\cite\\b@xcite\\uline{#1}}}\n')
716
717
718 def revert_custom_processors(document):
719     " Remove bibtex_command and index_command params "
720     i = find_token(document.header, '\\bibtex_command', 0)
721     if i == -1:
722         document.warning("Malformed LyX document: Missing \\bibtex_command.")
723         return
724     del document.header[i]
725     i = find_token(document.header, '\\index_command', 0)
726     if i == -1:
727         document.warning("Malformed LyX document: Missing \\index_command.")
728         return
729     del document.header[i]
730
731
732 def convert_nomencl_width(document):
733     " Add set_width param to nomencl_print "
734     i = 0
735     while True:
736       i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
737       if i == -1:
738         break
739       document.body.insert(i + 2, "set_width \"none\"")
740       i = i + 1
741
742
743 def revert_nomencl_width(document):
744     " Remove set_width param from nomencl_print "
745     i = 0
746     while True:
747       i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
748       if i == -1:
749         break
750       j = find_end_of_inset(document.body, i)
751       l = find_token(document.body, "set_width", i, j)
752       if l == -1:
753             document.warning("Can't find set_width option for nomencl_print!")
754             i = j
755             continue
756       del document.body[l]
757       i = i + 1
758
759
760 def revert_nomencl_cwidth(document):
761     " Remove width param from nomencl_print "
762     i = 0
763     while True:
764       i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
765       if i == -1:
766         break
767       j = find_end_of_inset(document.body, i)
768       l = find_token(document.body, "width", i, j)
769       if l == -1:
770             #Can't find width option for nomencl_print
771             i = j
772             continue
773       width = get_value(document.body, "width", i, j).strip('"')
774       del document.body[l]
775       add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
776       add_to_preamble(document, ["\\setlength{\\nomlabelwidth}{" + width + "}"])
777       i = i + 1
778
779
780 def revert_applemac(document):
781     " Revert applemac encoding to auto "
782     i = 0
783     if document.encoding == "applemac":
784         document.encoding = "auto"
785         i = find_token(document.header, "\\encoding", 0)
786         if i != -1:
787             document.header[i] = "\\encoding auto"
788
789
790 def revert_longtable_align(document):
791     " Remove longtable alignment setting "
792     i = 0
793     j = 0
794     while True:
795       i = find_token(document.body, "\\begin_inset Tabular", i)
796       if i == -1:
797           break
798       # the alignment is 2 lines below \\begin_inset Tabular
799       j = document.body[i+2].find("longtabularalignment")
800       if j == -1:
801           break
802       document.body[i+2] = document.body[i+2][:j-1]
803       document.body[i+2] = document.body[i+2] + '>'
804       i = i + 1
805
806
807 def revert_branch_filename(document):
808     " Remove \\filename_suffix parameter from branches "
809     i = 0
810     while True:
811         i = find_token(document.header, "\\filename_suffix", i)
812         if i == -1:
813             return
814         del document.header[i]
815
816
817 def revert_paragraph_indentation(document):
818     " Revert custom paragraph indentation to preamble code "
819     i = 0
820     while True:
821       i = find_token(document.header, "\\paragraph_indentation", i)
822       if i == -1:
823           break
824       # only remove the preamble line if default
825       # otherwise also write the value to the preamble
826       length = get_value(document.header, "\\paragraph_indentation", i)
827       if length == "default":
828           del document.header[i]
829           break
830       else:
831           # handle percent lengths
832           # latex_length returns "bool,length"
833           length = latex_length(length).split(",")[1]
834           add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
835           add_to_preamble(document, ["\\setlength{\\parindent}{" + length + "}"])
836           del document.header[i]
837       i = i + 1
838
839
840 def revert_percent_skip_lengths(document):
841     " Revert relative lengths for paragraph skip separation to preamble code "
842     i = 0
843     while True:
844       i = find_token(document.header, "\\defskip", i)
845       if i == -1:
846           break
847       length = get_value(document.header, "\\defskip", i)
848       # only revert when a custom length was set and when
849       # it used a percent length
850       if length not in ('smallskip', 'medskip', 'bigskip'):
851           # handle percent lengths
852           length = latex_length(length)
853           # latex_length returns "bool,length"
854           percent = length.split(",")[0]
855           length = length.split(",")[1]
856           if percent == "True":
857               add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
858               add_to_preamble(document, ["\\setlength{\\parskip}{" + length + "}"])
859               # set defskip to medskip as default
860               document.header[i] = "\\defskip medskip"
861       i = i + 1
862
863
864 def revert_percent_vspace_lengths(document):
865     " Revert relative VSpace lengths to ERT "
866     i = 0
867     while True:
868       i = find_token(document.body, "\\begin_inset VSpace", i)
869       if i == -1:
870           break
871       # only revert if a custom length was set and if
872       # it used a percent length
873       line = document.body[i]
874       r = re.compile(r'\\begin_inset VSpace (.*)$')
875       m = r.match(line)
876       length = m.group(1)
877       if length not in ('defskip', 'smallskip', 'medskip', 'bigskip', 'vfill'):
878           # check if the space has a star (protected space)
879           protected = (document.body[i].rfind("*") != -1)
880           if protected:
881               length = length.rstrip('*')
882           # handle percent lengths
883           length = latex_length(length)
884           # latex_length returns "bool,length"
885           percent = length.split(",")[0]
886           length = length.split(",")[1]
887           # revert the VSpace inset to ERT
888           if percent == "True":
889               if protected:
890                   subst = [put_cmd_in_ert("\\vspace*{" + length + "}")]
891               else:
892                   subst = [put_cmd_in_ert("\\vspace{" + length + "}")]
893               document.body[i:i+2] = subst
894       i = i + 1
895
896
897 def revert_percent_hspace_lengths(document):
898     " Revert relative HSpace lengths to ERT "
899     i = 0
900     while True:
901       i = find_token(document.body, "\\begin_inset space \\hspace", i)
902       if i == -1:
903           break
904       protected = (document.body[i].find("\\hspace*{}") != -1)
905       # only revert if a custom length was set and if
906       # it used a percent length
907       length = get_value(document.body, '\\length', i+1)
908       if length == '':
909           document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
910           return
911       # handle percent lengths
912       length = latex_length(length)
913       # latex_length returns "bool,length"
914       percent = length.split(",")[0]
915       length = length.split(",")[1]
916       # revert the HSpace inset to ERT
917       if percent == "True":
918           if protected:
919               subst = [put_cmd_in_ert("\\hspace*{" + length + "}")]
920           else:
921               subst = [put_cmd_in_ert("\\hspace{" + length + "}")]
922           document.body[i:i+3] = subst
923       i = i + 2
924
925
926 def revert_hspace_glue_lengths(document):
927     " Revert HSpace glue lengths to ERT "
928     i = 0
929     while True:
930       i = find_token(document.body, "\\begin_inset space \\hspace", i)
931       if i == -1:
932           break
933       protected = (document.body[i].find("\\hspace*{}") != -1)
934       length = get_value(document.body, '\\length', i+1)
935       if length == '':
936           document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
937           return
938       # only revert if the length contains a plus or minus at pos != 0
939       glue  = re.compile(r'.+[\+-]')
940       if glue.search(length):
941           # handle percent lengths
942           # latex_length returns "bool,length"
943           length = latex_length(length).split(",")[1]
944           # revert the HSpace inset to ERT
945           if protected:
946               subst = [put_cmd_in_ert("\\hspace*{" + length + "}")]
947           else:
948               subst = [put_cmd_in_ert("\\hspace{" + length + "}")]
949           document.body[i:i+3] = subst
950       i = i + 2
951
952 def convert_author_id(document):
953     " Add the author_id to the \\author definition and make sure 0 is not used"
954     i = 0
955     j = 1
956     while True:
957         i = find_token(document.header, "\\author", i)
958         if i == -1:
959             break
960         
961         r = re.compile(r'(\\author) (\".*\")\s?(.*)$')
962         m = r.match(document.header[i])
963         if m != None:
964             name = m.group(2)
965             
966             email = ''
967             if m.lastindex == 3:
968                 email = m.group(3)
969             document.header[i] = "\\author %i %s %s" % (j, name, email)
970         j = j + 1
971         i = i + 1
972         
973     k = 0
974     while True:
975         k = find_token(document.body, "\\change_", k)
976         if k == -1:
977             break
978
979         change = document.body[k].split(' ');
980         if len(change) == 3:
981             type = change[0]
982             author_id = int(change[1])
983             time = change[2]
984             document.body[k] = "%s %i %s" % (type, author_id + 1, time)
985         k = k + 1
986
987 def revert_author_id(document):
988     " Remove the author_id from the \\author definition "
989     i = 0
990     j = 0
991     idmap = dict()
992     while True:
993         i = find_token(document.header, "\\author", i)
994         if i == -1:
995             break
996         
997         r = re.compile(r'(\\author) (\d+) (\".*\")\s?(.*)$')
998         m = r.match(document.header[i])
999         if m != None:
1000             author_id = int(m.group(2))
1001             idmap[author_id] = j
1002             name = m.group(3)
1003             
1004             email = ''
1005             if m.lastindex == 4:
1006                 email = m.group(4)
1007             document.header[i] = "\\author %s %s" % (name, email)
1008         i = i + 1
1009         j = j + 1
1010
1011     k = 0
1012     while True:
1013         k = find_token(document.body, "\\change_", k)
1014         if k == -1:
1015             break
1016
1017         change = document.body[k].split(' ');
1018         if len(change) == 3:
1019             type = change[0]
1020             author_id = int(change[1])
1021             time = change[2]
1022             document.body[k] = "%s %i %s" % (type, idmap[author_id], time)
1023         k = k + 1
1024
1025
1026 def revert_suppress_date(document):
1027     " Revert suppressing of default document date to preamble code "
1028     i = 0
1029     while True:
1030       i = find_token(document.header, "\\suppress_date", i)
1031       if i == -1:
1032           break
1033       # remove the preamble line and write to the preamble
1034       # when suppress_date was true
1035       date = get_value(document.header, "\\suppress_date", i)
1036       if date == "true":
1037           add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
1038           add_to_preamble(document, ["\\date{}"])
1039       del document.header[i]
1040       i = i + 1
1041
1042
1043 def revert_mhchem(document):
1044     "Revert mhchem loading to preamble code"
1045     i = 0
1046     j = 0
1047     k = 0
1048     i = find_token(document.header, "\\use_mhchem 1", 0)
1049     if i != -1:
1050         mhchem = "auto"
1051     else:
1052         i = find_token(document.header, "\\use_mhchem 2", 0)
1053         if i != -1:
1054             mhchem = "on"
1055     if mhchem == "auto":
1056         j = find_token(document.body, "\\cf{", 0)
1057         if j != -1:
1058             mhchem = "on"
1059         else:
1060             j = find_token(document.body, "\\ce{", 0)
1061             if j != -1:
1062                 mhchem = "on"
1063     if mhchem == "on":
1064         add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
1065         add_to_preamble(document, ["\\PassOptionsToPackage{version=3}{mhchem}"])
1066         add_to_preamble(document, ["\\usepackage{mhchem}"])
1067     k = find_token(document.header, "\\use_mhchem", 0)
1068     if k == -1:
1069         document.warning("Malformed LyX document: Could not find mhchem setting.")
1070         return
1071     del document.header[k]
1072
1073
1074 def revert_fontenc(document):
1075     " Remove fontencoding param "
1076     i = find_token(document.header, '\\fontencoding', 0)
1077     if i == -1:
1078         document.warning("Malformed LyX document: Missing \\fontencoding.")
1079         return
1080     del document.header[i]
1081
1082
1083 def merge_gbrief(document):
1084     " Merge g-brief-en and g-brief-de to one class "
1085
1086     if document.textclass != "g-brief-de":
1087         if document.textclass == "g-brief-en":
1088             document.textclass = "g-brief"
1089             document.set_textclass()
1090         return
1091
1092     obsoletedby = { "Brieftext":       "Letter",
1093                     "Unterschrift":    "Signature",
1094                     "Strasse":         "Street",
1095                     "Zusatz":          "Addition",
1096                     "Ort":             "Town",
1097                     "Land":            "State",
1098                     "RetourAdresse":   "ReturnAddress",
1099                     "MeinZeichen":     "MyRef",
1100                     "IhrZeichen":      "YourRef",
1101                     "IhrSchreiben":    "YourMail",
1102                     "Telefon":         "Phone",
1103                     "BLZ":             "BankCode",
1104                     "Konto":           "BankAccount",
1105                     "Postvermerk":     "PostalComment",
1106                     "Adresse":         "Address",
1107                     "Datum":           "Date",
1108                     "Betreff":         "Reference",
1109                     "Anrede":          "Opening",
1110                     "Anlagen":         "Encl.",
1111                     "Verteiler":       "cc",
1112                     "Gruss":           "Closing"}
1113     i = 0
1114     while 1:
1115         i = find_token(document.body, "\\begin_layout", i)
1116         if i == -1:
1117             break
1118
1119         layout = document.body[i][14:]
1120         if layout in obsoletedby:
1121             document.body[i] = "\\begin_layout " + obsoletedby[layout]
1122
1123         i += 1
1124         
1125     document.textclass = "g-brief"
1126     document.set_textclass()
1127
1128
1129 def revert_gbrief(document):
1130     " Revert g-brief to g-brief-en "
1131     if document.textclass == "g-brief":
1132         document.textclass = "g-brief-en"
1133         document.set_textclass()
1134
1135
1136 def revert_html_options(document):
1137     " Remove html options "
1138     i = find_token(document.header, '\\html_use_mathml', 0)
1139     if i != -1:
1140         del document.header[i]
1141     i = find_token(document.header, '\\html_be_strict', 0)
1142     if i != -1:
1143         del document.header[i]
1144
1145
1146 def revert_includeonly(document):
1147     i = 0
1148     while True:
1149         i = find_token(document.header, "\\begin_includeonly", i)
1150         if i == -1:
1151             return
1152         j = find_end_of(document.header, i, "\\begin_includeonly", "\\end_includeonly")
1153         if j == -1:
1154             # this should not happen
1155             break
1156         document.header[i : j + 1] = []
1157
1158
1159 def revert_includeall(document):
1160     " Remove maintain_unincluded_children param "
1161     i = find_token(document.header, '\\maintain_unincluded_children', 0)
1162     if i != -1:
1163         del document.header[i]
1164
1165
1166 def revert_multirow(document):
1167     " Revert multirow cells in tables "
1168     i = 0
1169     multirow = False
1170     while True:
1171       # cell type 3 is multirow begin cell
1172       i = find_token(document.body, '<cell multirow="3"', i)
1173       if i == -1:
1174           break
1175       # a multirow cell was found
1176       multirow = True
1177       # remove the multirow tag, set the valignment to top
1178       # and remove the bottom line
1179       document.body[i] = document.body[i].replace(' multirow="3" ', ' ')
1180       document.body[i] = document.body[i].replace('valignment="middle"', 'valignment="top"')
1181       document.body[i] = document.body[i].replace(' bottomline="true" ', ' ')
1182       # write ERT to create the multirow cell
1183       # use 2 rows and 2cm as default with because the multirow span
1184       # and the column width is only hardly accessible
1185       subst = [put_cmd_in_ert("\\multirow{2}{2cm}{")]
1186       document.body[i + 4:i + 4] = subst
1187       i = find_token(document.body, "</cell>", i)
1188       if i == -1:
1189            document.warning("Malformed LyX document: Could not find end of tabular cell.")
1190            break
1191       subst = [put_cmd_in_ert("}")]
1192       document.body[i - 3:i - 3] = subst
1193       # cell type 4 is multirow part cell
1194       i = find_token(document.body, '<cell multirow="4"', i)
1195       if i == -1:
1196           break
1197       # remove the multirow tag, set the valignment to top
1198       # and remove the top line
1199       document.body[i] = document.body[i].replace(' multirow="4" ', ' ')
1200       document.body[i] = document.body[i].replace('valignment="middle"', 'valignment="top"')
1201       document.body[i] = document.body[i].replace(' topline="true" ', ' ')
1202       i = i + 1
1203     if multirow == True:
1204         add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
1205         add_to_preamble(document, ["\\usepackage{multirow}"])
1206
1207
1208 def convert_math_output(document):
1209     " Convert \html_use_mathml to \html_math_output "
1210     i = find_token(document.header, "\\html_use_mathml", 0)
1211     if i == -1:
1212         return
1213     rgx = re.compile(r'\\html_use_mathml\s+(\w+)')
1214     m = rgx.match(document.header[i])
1215     if rgx:
1216         newval = "0" # MathML
1217         val = m.group(1)
1218         if val != "true":
1219             newval = "2" # Images
1220         document.header[i] = "\\html_math_output " + newval
1221
1222
1223 def revert_math_output(document):
1224     " Revert \html_math_output to \html_use_mathml "
1225     i = find_token(document.header, "\\html_math_output", 0)
1226     if i == -1:
1227         return
1228     rgx = re.compile(r'\\html_math_output\s+(\d)')
1229     m = rgx.match(document.header[i])
1230     newval = "true"
1231     if rgx:
1232         val = m.group(1)
1233         if val == "1" or val == "2":
1234             newval = "false"
1235     else:
1236         document.warning("Unable to match " + document.header[i])
1237     document.header[i] = "\\html_use_mathml " + newval
1238                 
1239
1240
1241 def revert_inset_preview(document):
1242     " Dissolves the preview inset "
1243     i = 0
1244     j = 0
1245     k = 0
1246     while True:
1247       i = find_token(document.body, "\\begin_inset Preview", i)
1248       if i == -1:
1249           return
1250       j = find_end_of_inset(document.body, i)
1251       if j == -1:
1252           document.warning("Malformed LyX document: Could not find end of Preview inset.")
1253           return
1254       #If the layout is Standard we need to remove it, otherwise there
1255       #will be paragraph breaks that shouldn't be there.
1256       k = find_token(document.body, "\\begin_layout Standard", i)
1257       if k == i+2:
1258           del document.body[i : i+3]
1259           del document.body[j-5 : j-2]
1260           i -= 6
1261       else:
1262           del document.body[i]
1263           del document.body[j-1]
1264           i -= 2
1265                 
1266
1267 def revert_equalspacing_xymatrix(document):
1268     " Revert a Formula with xymatrix@! to an ERT inset "
1269     i = 0
1270     j = 0
1271     has_preamble = False
1272     has_equal_spacing = False
1273     while True:
1274       found = -1
1275       i = find_token(document.body, "\\begin_inset Formula", i)
1276       if i == -1:
1277           break
1278       j = find_end_of_inset(document.body, i)
1279       if j == -1:
1280           document.warning("Malformed LyX document: Could not find end of Formula inset.")
1281           break
1282           
1283       for curline in range(i,j):
1284           found = document.body[curline].find("\\xymatrix@!")
1285           if found != -1:
1286               break
1287  
1288       if found != -1:
1289           has_equal_spacing = True
1290           content = document.body[i][21:]
1291           content += '\n'.join(document.body[i+1:j])
1292           subst = [put_cmd_in_ert(content)]
1293           document.body[i:j+1] = subst
1294           i += 1
1295       else:
1296           for curline in range(i,j):
1297               l = document.body[curline].find("\\xymatrix")
1298               if l != -1:
1299                   has_preamble = True;
1300                   break;
1301           i = j + 1
1302     if has_equal_spacing and not has_preamble:
1303         add_to_preamble(document, ['\\usepackage[all]{xy}'])
1304
1305 ##
1306 # Conversion hub
1307 #
1308
1309 supported_versions = ["2.0.0","2.0"]
1310 convert = [[346, []],
1311            [347, []],
1312            [348, []],
1313            [349, []],
1314            [350, []],
1315            [351, []],
1316            [352, [convert_splitindex]],
1317            [353, []],
1318            [354, []],
1319            [355, []],
1320            [356, []],
1321            [357, []],
1322            [358, []],
1323            [359, [convert_nomencl_width]],
1324            [360, []],
1325            [361, []],
1326            [362, []],
1327            [363, []],
1328            [364, []],
1329            [365, []],
1330            [366, []],
1331            [367, []],
1332            [368, []],
1333            [369, [convert_author_id]],
1334            [370, []],
1335            [371, []],
1336            [372, []],
1337            [373, [merge_gbrief]],
1338            [374, []],
1339            [375, []],
1340            [376, []],
1341            [377, []],
1342            [378, []],
1343            [379, [convert_math_output]],
1344            [380, []],
1345            [381, []]
1346           ]
1347
1348 revert =  [[380, [revert_equalspacing_xymatrix]],
1349            [379, [revert_inset_preview]],
1350            [378, [revert_math_output]],
1351            [377, []],
1352            [376, [revert_multirow]],
1353            [375, [revert_includeall]],
1354            [374, [revert_includeonly]],
1355            [373, [revert_html_options]],
1356            [372, [revert_gbrief]],
1357            [371, [revert_fontenc]],
1358            [370, [revert_mhchem]],
1359            [369, [revert_suppress_date]],
1360            [368, [revert_author_id]],
1361            [367, [revert_hspace_glue_lengths]],
1362            [366, [revert_percent_vspace_lengths, revert_percent_hspace_lengths]],
1363            [365, [revert_percent_skip_lengths]],
1364            [364, [revert_paragraph_indentation]],
1365            [363, [revert_branch_filename]],
1366            [362, [revert_longtable_align]],
1367            [361, [revert_applemac]],
1368            [360, []],
1369            [359, [revert_nomencl_cwidth]],
1370            [358, [revert_nomencl_width]],
1371            [357, [revert_custom_processors]],
1372            [356, [revert_ulinelatex]],
1373            [355, [revert_uulinewave]],
1374            [354, [revert_strikeout]],
1375            [353, [revert_printindexall]],
1376            [352, [revert_subindex]],
1377            [351, [revert_splitindex]],
1378            [350, [revert_backgroundcolor]],
1379            [349, [revert_outputformat]],
1380            [348, [revert_xetex]],
1381            [347, [revert_phantom, revert_hphantom, revert_vphantom]],
1382            [346, [revert_tabularvalign]],
1383            [345, [revert_swiss]]
1384           ]
1385
1386
1387 if __name__ == "__main__":
1388     pass