1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2010 The LyX team
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.
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.
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.
20 """ Convert files to the file format generated by lyx 2.0"""
26 from parser_tools import find_token, find_end_of, find_tokens, \
27 find_end_of_inset, find_end_of_layout, find_token_backwards, \
28 get_containing_inset, get_value, get_value_string
30 from lyx2lyx_tools import add_to_preamble, insert_to_preamble, \
31 put_cmd_in_ert, lyx2latex, latex_length, revert_flex_inset, \
32 revert_font_attrs, revert_layout_command, hex2ratio, str2bool
34 ####################################################################
35 # Private helper functions
37 def remove_option(lines, m, option):
38 ''' removes option from line m. returns whether we did anything '''
39 l = lines[m].find(option)
42 val = lines[m][l:].split('"')[1]
43 lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
47 # DO NOT USE THIS ROUTINE ANY MORE. Better yet, replace the uses that
48 # have been made of it with uses of put_cmd_in_ert.
49 def old_put_cmd_in_ert(string):
50 for rep in unicode_reps:
51 string = string.replace(rep[1], rep[0].replace('\\\\', '\\'))
52 string = string.replace('\\', "\\backslash\n")
53 string = "\\begin_inset ERT\nstatus collapsed\n\\begin_layout Plain Layout\n" \
54 + string + "\n\\end_layout\n\\end_inset"
58 ###############################################################################
60 ### Conversion and reversion routines
62 ###############################################################################
64 def revert_swiss(document):
65 " Set language german-ch to ngerman "
67 if document.language == "german-ch":
68 document.language = "ngerman"
69 i = find_token(document.header, "\\language", 0)
71 document.header[i] = "\\language ngerman"
74 j = find_token(document.body, "\\lang german-ch", j)
77 document.body[j] = document.body[j].replace("\\lang german-ch", "\\lang ngerman")
81 def revert_tabularvalign(document):
82 " Revert the tabular valign option "
85 i = find_token(document.body, "\\begin_inset Tabular", i)
88 end = find_end_of_inset(document.body, i)
90 document.warning("Can't find end of inset at line " + str(i))
93 fline = find_token(document.body, "<features", i, end)
95 document.warning("Can't find features for inset at line " + str(i))
98 p = document.body[fline].find("islongtable")
100 q = document.body[fline].find("tabularvalignment")
103 # This seems wrong: It removes everything after
104 # tabularvalignment, too.
105 document.body[fline] = document.body[fline][:q - 1] + '>'
110 tabularvalignment = 'c'
111 # which valignment is specified?
112 m = document.body[fline].find('tabularvalignment="top"')
114 tabularvalignment = 't'
115 m = document.body[fline].find('tabularvalignment="bottom"')
117 tabularvalignment = 'b'
118 # delete tabularvalignment
119 q = document.body[fline].find("tabularvalignment")
122 # This seems wrong: It removes everything after
123 # tabularvalignment, too.
124 document.body[fline] = document.body[fline][:q - 1] + '>'
126 # don't add a box when centered
127 if tabularvalignment == 'c':
130 subst = ['\\end_layout', '\\end_inset']
131 document.body[end:end] = subst # just inserts those lines
132 subst = ['\\begin_inset Box Frameless',
133 'position "' + tabularvalignment +'"',
138 # we don't know the width, assume 50%
142 'height_special "totalheight"',
145 '\\begin_layout Plain Layout']
146 document.body[i:i] = subst # this just inserts the array at i
147 # since there could be a tabular inside a tabular, we cannot
152 def revert_phantom_types(document, ptype, cmd):
153 " Reverts phantom to ERT "
156 i = find_token(document.body, "\\begin_inset Phantom " + ptype, i)
159 end = find_end_of_inset(document.body, i)
161 document.warning("Can't find end of inset at line " + str(i))
164 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
166 document.warning("Can't find layout for inset at line " + str(i))
169 bend = find_token(document.body, "\\end_layout", blay, end)
171 document.warning("Malformed LyX document: Could not find end of Phantom inset's layout.")
174 substi = ["\\begin_inset ERT", "status collapsed", "",
175 "\\begin_layout Plain Layout", "", "", "\\backslash",
176 cmd + "{", "\\end_layout", "", "\\end_inset"]
177 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
178 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
179 # do the later one first so as not to mess up the numbering
180 document.body[bend:end + 1] = substj
181 document.body[i:blay + 1] = substi
182 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
185 def revert_phantom(document):
186 revert_phantom_types(document, "Phantom", "phantom")
188 def revert_hphantom(document):
189 revert_phantom_types(document, "HPhantom", "hphantom")
191 def revert_vphantom(document):
192 revert_phantom_types(document, "VPhantom", "vphantom")
195 def revert_xetex(document):
196 " Reverts documents that use XeTeX "
198 i = find_token(document.header, '\\use_xetex', 0)
200 document.warning("Malformed LyX document: Missing \\use_xetex.")
202 if not str2bool(get_value(document.header, "\\use_xetex", i)):
203 del document.header[i]
205 del document.header[i]
207 # 1.) set doc encoding to utf8-plain
208 i = find_token(document.header, "\\inputencoding", 0)
210 document.warning("Malformed LyX document: Missing \\inputencoding.")
212 document.header[i] = "\\inputencoding utf8-plain"
214 # 2.) check font settings
216 roman = sans = typew = default
218 sf_scale = tt_scale = 100.0
220 i = find_token(document.header, "\\font_roman", 0)
222 document.warning("Malformed LyX document: Missing \\font_roman.")
224 roman = get_value(document.header, "\\font_roman", i)
225 document.header[i] = "\\font_roman default"
227 i = find_token(document.header, "\\font_sans", 0)
229 document.warning("Malformed LyX document: Missing \\font_sans.")
231 sans = get_value(document.header, "\\font_sans", i)
232 document.header[i] = "\\font_sans default"
234 i = find_token(document.header, "\\font_typewriter", 0)
236 document.warning("Malformed LyX document: Missing \\font_typewriter.")
238 typew = get_value(document.header, "\\font_typewriter", i)
239 document.header[i] = "\\font_typewriter default"
241 i = find_token(document.header, "\\font_osf", 0)
243 document.warning("Malformed LyX document: Missing \\font_osf.")
245 osf = str2bool(get_value(document.header, "\\font_osf", i))
246 document.header[i] = "\\font_osf false"
248 i = find_token(document.header, "\\font_sc", 0)
250 document.warning("Malformed LyX document: Missing \\font_sc.")
252 # FIXME Do we want this value? and want to do something with it?
253 document.header[i] = "\\font_sc false"
255 i = find_token(document.header, "\\font_sf_scale", 0)
257 document.warning("Malformed LyX document: Missing \\font_sf_scale.")
259 val = get_value(document.header, '\\font_sf_scale', i)
262 sf_scale = float(val)
264 document.warning("Invalid font_sf_scale value: " + val)
265 document.header[i] = "\\font_sf_scale 100"
267 i = find_token(document.header, "\\font_tt_scale", 0)
269 document.warning("Malformed LyX document: Missing \\font_tt_scale.")
271 val = get_value(document.header, '\\font_tt_scale', i)
274 tt_scale = float(val)
276 document.warning("Invalid font_tt_scale value: " + val)
277 document.header[i] = "\\font_tt_scale 100"
279 # 3.) set preamble stuff
280 pretext = ['%% This document must be processed with xelatex!']
281 pretext.append('\\usepackage{fontspec}')
282 if roman != "default":
283 pretext.append('\\setmainfont[Mapping=tex-text]{' + roman + '}')
284 if sans != "default":
285 sf = '\\setsansfont['
286 if sf_scale != 100.0:
287 sf += 'Scale=' + str(sf_scale / 100.0) + ','
288 sf += 'Mapping=tex-text]{' + sans + '}'
290 if typewriter != "default":
292 if tt_scale != 100.0:
293 tw += '[Scale=' + str(tt_scale / 100.0) + ']'
294 tw += '{' + typewriter + '}'
297 pretext.append('\\defaultfontfeatures{Numbers=OldStyle}')
298 pretext.append('\usepackage{xunicode}')
299 pretext.append('\usepackage{xltxtra}')
300 insert_to_preamble(0, document, pretext)
303 def revert_outputformat(document):
304 " Remove default output format param "
305 i = find_token(document.header, '\\default_output_format', 0)
307 document.warning("Malformed LyX document: Missing \\default_output_format.")
309 del document.header[i]
312 def revert_backgroundcolor(document):
313 " Reverts background color to preamble code "
314 i = find_token(document.header, "\\backgroundcolor", 0)
317 colorcode = get_value(document.header, '\\backgroundcolor', i)
318 del document.header[i]
319 # don't clutter the preamble if backgroundcolor is not set
320 if colorcode == "#ffffff":
322 red = hex2ratio(colorcode[1:3])
323 green = hex2ratio(colorcode[3:5])
324 blue = hex2ratio(colorcode[5:7])
325 insert_to_preamble(0, document,
326 '% Commands inserted by lyx2lyx to set the background color\n'
327 + '\\@ifundefined{definecolor}{\\usepackage{color}}{}\n'
328 + '\\definecolor{page_backgroundcolor}{rgb}{'
329 + red + ',' + green + ',' + blue + '}\n'
330 + '\\pagecolor{page_backgroundcolor}\n')
333 def revert_splitindex(document):
334 " Reverts splitindex-aware documents "
335 i = find_token(document.header, '\\use_indices', 0)
337 document.warning("Malformed LyX document: Missing \\use_indices.")
339 useindices = str2bool(get_value(document.header, "\\use_indices", i))
340 del document.header[i]
343 preamble.append("\\usepackage{splitidx})")
345 # deal with index declarations in the preamble
348 i = find_token(document.header, "\\index", i)
351 k = find_token(document.header, "\\end_index", i)
353 document.warning("Malformed LyX document: Missing \\end_index.")
356 line = document.header[i]
357 l = re.compile(r'\\index (.*)$')
360 ishortcut = get_value(document.header, '\\shortcut', i, k)
362 preamble.append("\\newindex[" + iname + "]{" + ishortcut + "}")
363 del document.header[i:k + 1]
365 insert_to_preamble(0, document, preamble)
367 # deal with index insets
368 # these need to have the argument removed
371 i = find_token(document.body, "\\begin_inset Index", i)
374 line = document.body[i]
375 l = re.compile(r'\\begin_inset Index (.*)$')
378 if itype == "idx" or indices == "false":
379 document.body[i] = "\\begin_inset Index"
381 k = find_end_of_inset(document.body, i)
383 document.warning("Can't find end of index inset!")
386 content = lyx2latex(document, document.body[i:k])
388 content = content.replace('"', r'\"')
389 subst = put_cmd_in_ert("\\sindex[" + itype + "]{" + content + "}")
390 document.body[i:k + 1] = subst
393 # deal with index_print insets
396 i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
399 k = find_end_of_inset(document.body, i)
400 ptype = get_value(document.body, 'type', i, k).strip('"')
402 j = find_token(document.body, "type", i, k)
405 del document.body[i:k + 1]
407 subst = put_cmd_in_ert("\\printindex[" + ptype + "]{}")
408 document.body[i:k + 1] = subst
412 def convert_splitindex(document):
413 " Converts index and printindex insets to splitindex-aware format "
416 i = find_token(document.body, "\\begin_inset Index", i)
419 document.body[i] = document.body[i].replace("\\begin_inset Index",
420 "\\begin_inset Index idx")
424 i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
427 if document.body[i + 1].find('LatexCommand printindex') == -1:
428 document.warning("Malformed LyX document: Incomplete printindex inset.")
430 subst = ["LatexCommand printindex",
432 document.body[i + 1:i + 2] = subst
436 def revert_subindex(document):
437 " Reverts \\printsubindex CommandInset types "
438 i = find_token(document.header, '\\use_indices', 0)
440 document.warning("Malformed LyX document: Missing \\use_indices.")
442 indices = get_value(document.header, "\\use_indices", i)
443 useindices = (indices == "true")
446 i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
449 k = find_end_of_inset(document.body, i)
450 ctype = get_value(document.body, 'LatexCommand', i, k)
451 if ctype != "printsubindex":
454 ptype = get_value(document.body, 'type', i, k).strip('"')
456 del document.body[i:k + 1]
458 subst = put_cmd_in_ert("\\printsubindex[" + ptype + "]{}")
459 document.body[i:k + 1] = subst
463 def revert_printindexall(document):
464 " Reverts \\print[sub]index* CommandInset types "
465 i = find_token(document.header, '\\use_indices', 0)
467 document.warning("Malformed LyX document: Missing \\use_indices.")
469 indices = get_value(document.header, "\\use_indices", i)
470 useindices = (indices == "true")
473 i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
476 k = find_end_of_inset(document.body, i)
477 ctype = get_value(document.body, 'LatexCommand', i, k)
478 if ctype != "printindex*" and ctype != "printsubindex*":
482 del document.body[i:k + 1]
484 subst = put_cmd_in_ert("\\" + ctype + "{}")
485 document.body[i:k + 1] = subst
489 def revert_strikeout(document):
490 " Reverts \\strikeout font attribute "
491 changed = revert_font_attrs(document, "\\uuline", "\\uuline")
492 changed = revert_font_attrs(document, "\\uwave", "\\uwave") or changed
493 changed = revert_font_attrs(document, "\\strikeout", "\\sout") or changed
495 insert_to_preamble(0, document,
496 '% Commands inserted by lyx2lyx for proper underlining\n'
497 + '\\PassOptionsToPackage{normalem}{ulem}\n'
498 + '\\usepackage{ulem}\n')
501 def revert_ulinelatex(document):
502 " Reverts \\uline font attribute "
503 i = find_token(document.body, '\\bar under', 0)
506 insert_to_preamble(0, document,
507 '% Commands inserted by lyx2lyx for proper underlining\n'
508 + '\\PassOptionsToPackage{normalem}{ulem}\n'
509 + '\\usepackage{ulem}\n'
510 + '\\let\\cite@rig\\cite\n'
511 + '\\newcommand{\\b@xcite}[2][\\%]{\\def\\def@pt{\\%}\\def\\pas@pt{#1}\n'
512 + ' \\mbox{\\ifx\\def@pt\\pas@pt\\cite@rig{#2}\\else\\cite@rig[#1]{#2}\\fi}}\n'
513 + '\\renewcommand{\\underbar}[1]{{\\let\\cite\\b@xcite\\uline{#1}}}\n')
516 def revert_custom_processors(document):
517 " Remove bibtex_command and index_command params "
518 i = find_token(document.header, '\\bibtex_command', 0)
520 document.warning("Malformed LyX document: Missing \\bibtex_command.")
522 del document.header[i]
523 i = find_token(document.header, '\\index_command', 0)
525 document.warning("Malformed LyX document: Missing \\index_command.")
527 del document.header[i]
530 def convert_nomencl_width(document):
531 " Add set_width param to nomencl_print "
534 i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
537 document.body.insert(i + 2, "set_width \"none\"")
541 def revert_nomencl_width(document):
542 " Remove set_width param from nomencl_print "
545 i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
548 j = find_end_of_inset(document.body, i)
549 l = find_token(document.body, "set_width", i, j)
551 document.warning("Can't find set_width option for nomencl_print!")
558 def revert_nomencl_cwidth(document):
559 " Remove width param from nomencl_print "
562 i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
565 j = find_end_of_inset(document.body, i)
566 l = find_token(document.body, "width", i, j)
568 document.warning("Can't find width option for nomencl_print!")
571 width = get_value(document.body, "width", i, j).strip('"')
573 add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
574 add_to_preamble(document, ["\\setlength{\\nomlabelwidth}{" + width + "}"])
578 def revert_applemac(document):
579 " Revert applemac encoding to auto "
580 if document.encoding != "applemac":
582 document.encoding = "auto"
583 i = find_token(document.header, "\\encoding", 0)
585 document.header[i] = "\\encoding auto"
588 def revert_longtable_align(document):
589 " Remove longtable alignment setting "
592 i = find_token(document.body, "\\begin_inset Tabular", i)
595 end = find_end_of_inset(document.body, i)
597 document.warning("Can't find end of inset at line " + str(i))
600 fline = find_token(document.body, "<features", i, end)
602 document.warning("Can't find features for inset at line " + str(i))
605 j = document.body[fline].find("longtabularalignment")
609 # FIXME Is this correct? It wipes out everything after the
611 document.body[fline] = document.body[fline][:j - 1] + '>'
612 # since there could be a tabular inside this one, we
613 # cannot jump to end.
617 def revert_branch_filename(document):
618 " Remove \\filename_suffix parameter from branches "
621 i = find_token(document.header, "\\filename_suffix", i)
624 del document.header[i]
627 def revert_paragraph_indentation(document):
628 " Revert custom paragraph indentation to preamble code "
629 i = find_token(document.header, "\\paragraph_indentation", 0)
632 length = get_value(document.header, "\\paragraph_indentation", i)
633 # we need only remove the line if indentation is default
634 if length != "default":
635 # handle percent lengths
636 length = latex_length(length)[1]
637 add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
638 add_to_preamble(document, ["\\setlength{\\parindent}{" + length + "}"])
639 del document.header[i]
642 def revert_percent_skip_lengths(document):
643 " Revert relative lengths for paragraph skip separation to preamble code "
644 i = find_token(document.header, "\\defskip", 0)
647 length = get_value(document.header, "\\defskip", i)
648 # only revert when a custom length was set and when
649 # it used a percent length
650 if length in ('smallskip', 'medskip', 'bigskip'):
652 # handle percent lengths
653 percent, length = latex_length(length)
655 add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
656 add_to_preamble(document, ["\\setlength{\\parskip}{" + length + "}"])
657 # set defskip to medskip as default
658 document.header[i] = "\\defskip medskip"
661 def revert_percent_vspace_lengths(document):
662 " Revert relative VSpace lengths to ERT "
665 i = find_token(document.body, "\\begin_inset VSpace", i)
668 # only revert if a custom length was set and if
669 # it used a percent length
670 r = re.compile(r'\\begin_inset VSpace (.*)$')
671 m = r.match(document.body[i])
673 if length in ('defskip', 'smallskip', 'medskip', 'bigskip', 'vfill'):
676 # check if the space has a star (protected space)
677 protected = (document.body[i].rfind("*") != -1)
679 length = length.rstrip('*')
680 # handle percent lengths
681 percent, length = latex_length(length)
682 # revert the VSpace inset to ERT
685 subst = put_cmd_in_ert("\\vspace*{" + length + "}")
687 subst = put_cmd_in_ert("\\vspace{" + length + "}")
688 document.body[i:i + 2] = subst
692 def revert_percent_hspace_lengths(document):
693 " Revert relative HSpace lengths to ERT "
696 i = find_token(document.body, "\\begin_inset space \\hspace", i)
699 j = find_end_of_inset(document.body, i)
701 document.warning("Can't find end of inset at line " + str(i))
704 # only revert if a custom length was set...
705 length = get_value(document.body, '\\length', i + 1, j)
707 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
711 if document.body[i].find("\\hspace*{}") != -1:
713 # ...and if it used a percent length
714 percent, length = latex_length(length)
715 # revert the HSpace inset to ERT
717 subst = put_cmd_in_ert("\\hspace" + protected + "{" + length + "}")
718 document.body[i:j + 1] = subst
719 # if we did a substitution, this will still be ok
723 def revert_hspace_glue_lengths(document):
724 " Revert HSpace glue lengths to ERT "
727 i = find_token(document.body, "\\begin_inset space \\hspace", i)
730 j = find_end_of_inset(document.body, i)
732 document.warning("Can't find end of inset at line " + str(i))
735 length = get_value(document.body, '\\length', i + 1, j)
737 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
741 if document.body[i].find("\\hspace*{}") != -1:
743 # only revert if the length contains a plus or minus at pos != 0
744 if length.find('-',1) != -1 or length.find('+',1) != -1:
745 # handle percent lengths
746 length = latex_length(length)[1]
747 # revert the HSpace inset to ERT
748 subst = put_cmd_in_ert("\\hspace" + protected + "{" + length + "}")
749 document.body[i:j+1] = subst
753 def convert_author_id(document):
754 " Add the author_id to the \\author definition and make sure 0 is not used"
757 re_author = re.compile(r'(\\author) (\".*\")\s*(.*)$')
760 i = find_token(document.header, "\\author", i)
763 m = re_author.match(document.header[i])
767 document.header[i] = "\\author %i %s %s" % (anum, name, email)
768 # FIXME Should this really be incremented if we didn't match?
774 i = find_token(document.body, "\\change_", i)
777 change = document.body[i].split(' ');
780 author_id = int(change[1])
782 document.body[i] = "%s %i %s" % (type, author_id + 1, time)
786 def revert_author_id(document):
787 " Remove the author_id from the \\author definition "
790 rx = re.compile(r'(\\author)\s+(\d+)\s+(\".*\")\s*(.*)$')
794 i = find_token(document.header, "\\author", i)
797 m = rx.match(document.header[i])
799 author_id = int(m.group(2))
800 idmap[author_id] = anum
803 document.header[i] = "\\author %s %s" % (name, email)
805 # FIXME Should this be incremented if we didn't match?
810 i = find_token(document.body, "\\change_", i)
813 change = document.body[i].split(' ');
816 author_id = int(change[1])
818 document.body[i] = "%s %i %s" % (type, idmap[author_id], time)
822 def revert_suppress_date(document):
823 " Revert suppressing of default document date to preamble code "
824 i = find_token(document.header, "\\suppress_date", 0)
827 # remove the preamble line and write to the preamble
828 # when suppress_date was true
829 date = get_value(document.header, "\\suppress_date", i)
831 add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
832 add_to_preamble(document, ["\\date{}"])
833 del document.header[i]
836 def revert_mhchem(document):
837 "Revert mhchem loading to preamble code"
840 i = find_token(document.header, "\\use_mhchem", 0)
842 document.warning("Malformed LyX document: Could not find mhchem setting.")
845 val = get_value(document.header, "\\use_mhchem", i)
850 del document.header[i]
859 i = find_token(document.body, "\\begin_inset Formula", i)
862 line = document.body[i]
863 if line.find("\\ce{") != -1 or line.find("\\cf{") != -1:
869 pre = ["% lyx2lyx mhchem commands",
870 "\\PassOptionsToPackage{version=3}{mhchem}",
871 "\\usepackage{mhchem}"]
872 add_to_preamble(document, pre)
875 def revert_fontenc(document):
876 " Remove fontencoding param "
877 i = find_token(document.header, '\\fontencoding', 0)
879 document.warning("Malformed LyX document: Missing \\fontencoding.")
881 del document.header[i]
884 def merge_gbrief(document):
885 " Merge g-brief-en and g-brief-de to one class "
887 if document.textclass != "g-brief-de":
888 if document.textclass == "g-brief-en":
889 document.textclass = "g-brief"
890 document.set_textclass()
893 obsoletedby = { "Brieftext": "Letter",
894 "Unterschrift": "Signature",
896 "Zusatz": "Addition",
899 "RetourAdresse": "ReturnAddress",
900 "MeinZeichen": "MyRef",
901 "IhrZeichen": "YourRef",
902 "IhrSchreiben": "YourMail",
905 "Konto": "BankAccount",
906 "Postvermerk": "PostalComment",
907 "Adresse": "Address",
909 "Betreff": "Reference",
916 i = find_token(document.body, "\\begin_layout", i)
920 layout = document.body[i][14:]
921 if layout in obsoletedby:
922 document.body[i] = "\\begin_layout " + obsoletedby[layout]
926 document.textclass = "g-brief"
927 document.set_textclass()
930 def revert_gbrief(document):
931 " Revert g-brief to g-brief-en "
932 if document.textclass == "g-brief":
933 document.textclass = "g-brief-en"
934 document.set_textclass()
937 def revert_html_options(document):
938 " Remove html options "
939 i = find_token(document.header, '\\html_use_mathml', 0)
941 del document.header[i]
942 i = find_token(document.header, '\\html_be_strict', 0)
944 del document.header[i]
947 def revert_includeonly(document):
950 i = find_token(document.header, "\\begin_includeonly", i)
953 j = find_end_of(document.header, i, "\\begin_includeonly", "\\end_includeonly")
955 document.warning("Unable to find end of includeonly section!!")
957 document.header[i : j + 1] = []
960 def revert_includeall(document):
961 " Remove maintain_unincluded_children param "
962 i = find_token(document.header, '\\maintain_unincluded_children', 0)
964 del document.header[i]
967 def revert_multirow(document):
968 " Revert multirow cells in tables to TeX-code"
972 # cell type 3 is multirow begin cell
973 i = find_token(document.body, '<cell multirow="3"', i)
976 # a multirow cell was found
978 # remove the multirow tag, set the valignment to top
979 # and remove the bottom line
980 # FIXME Are we sure these always have space around them?
981 document.body[i] = document.body[i].replace(' multirow="3" ', ' ')
982 document.body[i] = document.body[i].replace('valignment="middle"', 'valignment="top"')
983 document.body[i] = document.body[i].replace(' bottomline="true" ', ' ')
984 # write ERT to create the multirow cell
985 # use 2 rows and 2cm as default with because the multirow span
986 # and the column width is only hardly accessible
987 cend = find_token(document.body, "</cell>", i)
989 document.warning("Malformed LyX document: Could not find end of tabular cell.")
992 blay = find_token(document.body, "\\begin_layout", i, cend)
994 document.warning("Can't find layout for cell!")
997 bend = find_end_of_layout(document.body, blay)
999 document.warning("Can't find end of layout for cell!")
1003 # do the later one first, so as not to mess up the numbering
1004 # we are wrapping the whole cell in this ert
1005 # so before the end of the layout...
1006 document.body[bend:bend] = put_cmd_in_ert("}")
1007 # ...and after the beginning
1008 document.body[blay+1:blay+1] = put_cmd_in_ert("\\multirow{2}{2cm}{")
1011 # cell type 4 is multirow part cell
1012 k = find_token(document.body, '<cell multirow="4"', cend)
1015 # remove the multirow tag, set the valignment to top
1016 # and remove the top line
1017 # FIXME Are we sure these always have space around them?
1018 document.body[k] = document.body[k].replace(' multirow="4" ', ' ')
1019 document.body[k] = document.body[k].replace('valignment="middle"', 'valignment="top"')
1020 document.body[k] = document.body[k].replace(' topline="true" ', ' ')
1022 # this will always be ok
1025 if multirow == True:
1026 add_to_preamble(document,
1027 ["% lyx2lyx multirow additions ", "\\usepackage{multirow}"])
1030 def convert_math_output(document):
1031 " Convert \html_use_mathml to \html_math_output "
1032 i = find_token(document.header, "\\html_use_mathml", 0)
1035 rgx = re.compile(r'\\html_use_mathml\s+(\w+)')
1036 m = rgx.match(document.header[i])
1037 newval = "0" # MathML
1041 newval = "2" # Images
1043 document.warning("Can't match " + document.header[i])
1044 document.header[i] = "\\html_math_output " + newval
1047 def revert_math_output(document):
1048 " Revert \html_math_output to \html_use_mathml "
1049 i = find_token(document.header, "\\html_math_output", 0)
1052 rgx = re.compile(r'\\html_math_output\s+(\d)')
1053 m = rgx.match(document.header[i])
1057 if val == "1" or val == "2":
1060 document.warning("Unable to match " + document.header[i])
1061 document.header[i] = "\\html_use_mathml " + newval
1065 def revert_inset_preview(document):
1066 " Dissolves the preview inset "
1069 i = find_token(document.body, "\\begin_inset Preview", i)
1072 iend = find_end_of_inset(document.body, i)
1074 document.warning("Malformed LyX document: Could not find end of Preview inset.")
1078 # This has several issues.
1079 # We need to do something about the layouts inside InsetPreview.
1080 # If we just leave the first one, then we have something like:
1081 # \begin_layout Standard
1083 # \begin_layout Standard
1084 # and we get a "no \end_layout" error. So something has to be done.
1085 # Ideally, we would check if it is the same as the layout we are in.
1086 # If so, we just remove it; if not, we end the active one. But it is
1087 # not easy to know what layout we are in, due to depth changes, etc,
1088 # and it is not clear to me how much work it is worth doing. In most
1089 # cases, the layout will probably be the same.
1091 # For the same reason, we have to remove the \end_layout tag at the
1092 # end of the last layout in the inset. Again, that will sometimes be
1093 # wrong, but it will usually be right. To know what to do, we would
1094 # again have to know what layout the inset is in.
1096 blay = find_token(document.body, "\\begin_layout", i, iend)
1098 document.warning("Can't find layout for preview inset!")
1099 # always do the later one first...
1100 del document.body[iend]
1101 del document.body[i]
1102 # deletions mean we do not need to reset i
1105 # This is where we would check what layout we are in.
1106 # The check for Standard is definitely wrong.
1108 # lay = document.body[blay].split(None, 1)[1]
1109 # if lay != oldlayout:
1110 # # record a boolean to tell us what to do later....
1111 # # better to do it later, since (a) it won't mess up
1112 # # the numbering and (b) we only modify at the end.
1114 # we want to delete the last \\end_layout in this inset, too.
1115 # note that this may not be the \\end_layout that goes with blay!!
1116 bend = find_end_of_layout(document.body, blay)
1118 tmp = find_token(document.body, "\\end_layout", bend + 1, iend)
1123 document.warning("Unable to find last layout in preview inset!")
1124 del document.body[iend]
1125 del document.body[i]
1126 # deletions mean we do not need to reset i
1128 # always do the later one first...
1129 del document.body[iend]
1130 del document.body[bend]
1131 del document.body[i:blay + 1]
1132 # we do not need to reset i
1135 def revert_equalspacing_xymatrix(document):
1136 " Revert a Formula with xymatrix@! to an ERT inset "
1138 has_preamble = False
1139 has_equal_spacing = False
1142 i = find_token(document.body, "\\begin_inset Formula", i)
1145 j = find_end_of_inset(document.body, i)
1147 document.warning("Malformed LyX document: Could not find end of Formula inset.")
1151 for curline in range(i,j):
1152 found = document.body[curline].find("\\xymatrix@!")
1157 has_equal_spacing = True
1158 content = [document.body[i][21:]]
1159 content += document.body[i + 1:j]
1160 subst = put_cmd_in_ert(content)
1161 document.body[i:j + 1] = subst
1162 i += len(subst) - (j - i) + 1
1164 for curline in range(i,j):
1165 l = document.body[curline].find("\\xymatrix")
1167 has_preamble = True;
1171 if has_equal_spacing and not has_preamble:
1172 add_to_preamble(document, ['% lyx2lyx xymatrix addition', '\\usepackage[all]{xy}'])
1175 def revert_notefontcolor(document):
1176 " Reverts greyed-out note font color to preamble code "
1178 i = find_token(document.header, "\\notefontcolor", 0)
1182 # are there any grey notes?
1183 if find_token(document.body, "\\begin_inset Note Greyedout", 0) == -1:
1184 # no need to do anything, and \renewcommand will throw an error
1185 # since lyxgreyedout will not exist.
1188 colorcode = get_value(document.header, '\\notefontcolor', i)
1189 del document.header[i]
1190 # the color code is in the form #rrggbb where every character denotes a hex number
1191 red = hex2ratio(colorcode[1:3])
1192 green = hex2ratio(colorcode[3:5])
1193 blue = hex2ratio(colorcode[5:7])
1194 # write the preamble
1195 insert_to_preamble(0, document,
1196 ['% Commands inserted by lyx2lyx to set the font color',
1197 '% for greyed-out notes',
1198 '\\@ifundefined{definecolor}{\\usepackage{color}}{}'
1199 '\\definecolor{note_fontcolor}{rgb}{%s,%s,%s}' % (red, green, blue),
1200 '\\renewenvironment{lyxgreyedout}',
1201 ' {\\textcolor{note_fontcolor}\\bgroup}{\\egroup}'])
1204 def revert_turkmen(document):
1205 "Set language Turkmen to English"
1207 if document.language == "turkmen":
1208 document.language = "english"
1209 i = find_token(document.header, "\\language", 0)
1211 document.header[i] = "\\language english"
1215 j = find_token(document.body, "\\lang turkmen", j)
1218 document.body[j] = document.body[j].replace("\\lang turkmen", "\\lang english")
1222 def revert_fontcolor(document):
1223 " Reverts font color to preamble code "
1224 i = find_token(document.header, "\\fontcolor", 0)
1227 colorcode = get_value(document.header, '\\fontcolor', i)
1228 del document.header[i]
1229 # don't clutter the preamble if font color is not set
1230 if colorcode == "#000000":
1232 # the color code is in the form #rrggbb where every character denotes a hex number
1233 red = hex2ratio(colorcode[1:3])
1234 green = hex2ratio(colorcode[3:5])
1235 blue = hex2ratio(colorcode[5:7])
1236 # write the preamble
1237 insert_to_preamble(0, document,
1238 ['% Commands inserted by lyx2lyx to set the font color',
1239 '\\@ifundefined{definecolor}{\\usepackage{color}}{}',
1240 '\\definecolor{document_fontcolor}{rgb}{%s,%s,%s}' % (red, green, blue),
1241 '\\color{document_fontcolor}'])
1244 def revert_shadedboxcolor(document):
1245 " Reverts shaded box color to preamble code "
1246 i = find_token(document.header, "\\boxbgcolor", 0)
1249 colorcode = get_value(document.header, '\\boxbgcolor', i)
1250 del document.header[i]
1251 # the color code is in the form #rrggbb
1252 red = hex2ratio(colorcode[1:3])
1253 green = hex2ratio(colorcode[3:5])
1254 blue = hex2ratio(colorcode[5:7])
1255 # write the preamble
1256 insert_to_preamble(0, document,
1257 ['% Commands inserted by lyx2lyx to set the color of boxes with shaded background',
1258 '\\@ifundefined{definecolor}{\\usepackage{color}}{}',
1259 "\\definecolor{shadecolor}{rgb}{%s,%s,%s}" % (red, green, blue)])
1262 def revert_lyx_version(document):
1263 " Reverts LyX Version information from Inset Info "
1264 version = "LyX version"
1266 import lyx2lyx_version
1267 version = lyx2lyx_version.version
1273 i = find_token(document.body, '\\begin_inset Info', i)
1276 j = find_end_of_inset(document.body, i + 1)
1278 document.warning("Malformed LyX document: Could not find end of Info inset.")
1287 # but we shall try to be forgiving.
1289 for k in range(i, j):
1290 if document.body[k].startswith("arg"):
1291 arg = document.body[k][3:].strip().strip('"')
1292 if document.body[k].startswith("type"):
1293 typ = document.body[k][4:].strip().strip('"')
1294 if arg != "version" or typ != "lyxinfo":
1298 # We do not actually know the version of LyX used to produce the document.
1299 # But we can use our version, since we are reverting.
1301 # Now we want to check if the line after "\end_inset" is empty. It normally
1302 # is, so we want to remove it, too.
1304 if document.body[j + 1].strip() == "":
1306 document.body[i: lastline] = s
1310 def revert_math_scale(document):
1311 " Remove math scaling and LaTeX options "
1312 i = find_token(document.header, '\\html_math_img_scale', 0)
1314 del document.header[i]
1315 i = find_token(document.header, '\\html_latex_start', 0)
1317 del document.header[i]
1318 i = find_token(document.header, '\\html_latex_end', 0)
1320 del document.header[i]
1323 def revert_pagesizes(document):
1324 " Revert page sizes to default "
1325 i = find_token(document.header, '\\papersize', 0)
1327 size = document.header[i][11:]
1328 if size == "a0paper" or size == "a1paper" or size == "a2paper" \
1329 or size == "a6paper" or size == "b0paper" or size == "b1paper" \
1330 or size == "b2paper" or size == "b6paper" or size == "b0j" \
1331 or size == "b1j" or size == "b2j" or size == "b3j" or size == "b4j" \
1332 or size == "b5j" or size == "b6j":
1333 del document.header[i]
1336 def revert_DIN_C_pagesizes(document):
1337 " Revert DIN C page sizes to default "
1338 i = find_token(document.header, '\\papersize', 0)
1340 size = document.header[i][11:]
1341 if size == "c0paper" or size == "c1paper" or size == "c2paper" \
1342 or size == "c3paper" or size == "c4paper" or size == "c5paper" \
1343 or size == "c6paper":
1344 del document.header[i]
1347 def convert_html_quotes(document):
1348 " Remove quotes around html_latex_start and html_latex_end "
1350 i = find_token(document.header, '\\html_latex_start', 0)
1352 line = document.header[i]
1353 l = re.compile(r'\\html_latex_start\s+"(.*)"')
1356 document.header[i] = "\\html_latex_start " + m.group(1)
1358 i = find_token(document.header, '\\html_latex_end', 0)
1360 line = document.header[i]
1361 l = re.compile(r'\\html_latex_end\s+"(.*)"')
1364 document.header[i] = "\\html_latex_end " + m.group(1)
1367 def revert_html_quotes(document):
1368 " Remove quotes around html_latex_start and html_latex_end "
1370 i = find_token(document.header, '\\html_latex_start', 0)
1372 line = document.header[i]
1373 l = re.compile(r'\\html_latex_start\s+(.*)')
1376 document.warning("Weird html_latex_start line: " + line)
1377 del document.header[i]
1379 document.header[i] = "\\html_latex_start \"" + m.group(1) + "\""
1381 i = find_token(document.header, '\\html_latex_end', 0)
1383 line = document.header[i]
1384 l = re.compile(r'\\html_latex_end\s+(.*)')
1387 document.warning("Weird html_latex_end line: " + line)
1388 del document.header[i]
1390 document.header[i] = "\\html_latex_end \"" + m.group(1) + "\""
1393 def revert_output_sync(document):
1394 " Remove forward search options "
1395 i = find_token(document.header, '\\output_sync_macro', 0)
1397 del document.header[i]
1398 i = find_token(document.header, '\\output_sync', 0)
1400 del document.header[i]
1403 def revert_align_decimal(document):
1406 i = find_token(document.body, "\\begin_inset Tabular", i)
1409 j = find_end_of_inset(document.body, i)
1411 document.warning("Unable to find end of Tabular inset at line " + str(i))
1414 cell = find_token(document.body, "<cell", i, j)
1416 document.warning("Can't find any cells in Tabular inset at line " + str(i))
1421 k = find_token(document.body, "<column", k, cell)
1424 if document.body[k].find('alignment="decimal"') == -1:
1427 remove_option(document.body, k, 'decimal_point')
1428 document.body[k] = \
1429 document.body[k].replace('alignment="decimal"', 'alignment="center"')
1433 def convert_optarg(document):
1434 " Convert \\begin_inset OptArg to \\begin_inset Argument "
1437 i = find_token(document.body, '\\begin_inset OptArg', i)
1440 document.body[i] = "\\begin_inset Argument"
1444 def revert_argument(document):
1445 " Convert \\begin_inset Argument to \\begin_inset OptArg "
1448 i = find_token(document.body, '\\begin_inset Argument', i)
1451 document.body[i] = "\\begin_inset OptArg"
1455 def revert_makebox(document):
1456 " Convert \\makebox to TeX code "
1459 # only revert frameless boxes without an inner box
1460 i = find_token(document.body, '\\begin_inset Box Frameless', i)
1463 z = find_end_of_inset(document.body, i)
1465 document.warning("Malformed LyX document: Can't find end of box inset.")
1468 blay = find_token(document.body, "\\begin_layout", i, z)
1470 document.warning("Malformed LyX document: Can't find layout in box.")
1473 # by looking before the layout we make sure we're actually finding
1474 # an option, not text.
1475 j = find_token(document.body, 'use_makebox', i, blay)
1479 val = get_value(document.body, 'use_makebox', j)
1481 del document.body[j]
1484 bend = find_end_of_layout(document.body, blay)
1485 if bend == -1 or bend > z:
1486 document.warning("Malformed LyX document: Can't find end of layout in box.")
1489 # determine the alignment
1490 align = get_value(document.body, 'hor_pos', i, blay, "c").strip('"')
1491 # determine the width
1492 length = get_value(document.body, 'width', i, blay, "50col%").strip('"')
1493 length = latex_length(length)[1]
1494 # remove the \end_layout \end_inset pair
1495 document.body[bend:z + 1] = put_cmd_in_ert("}")
1496 subst = "\\makebox[" + length + "][" \
1498 document.body[i:blay + 1] = put_cmd_in_ert(subst)
1502 def convert_use_makebox(document):
1503 " Adds use_makebox option for boxes "
1506 i = find_token(document.body, '\\begin_inset Box', i)
1509 # all of this is to make sure we actually find the use_parbox
1510 # that is an option for this box, not some text elsewhere.
1511 z = find_end_of_inset(document.body, i)
1513 document.warning("Can't find end of box inset!!")
1516 blay = find_token(document.body, "\\begin_layout", i, z)
1518 document.warning("Can't find layout in box inset!!")
1521 # so now we are looking for use_parbox before the box's layout
1522 k = find_token(document.body, 'use_parbox', i, blay)
1524 document.warning("Malformed LyX document: Can't find use_parbox statement in box.")
1527 document.body.insert(k + 1, "use_makebox 0")
1531 def revert_IEEEtran(document):
1532 " Convert IEEEtran layouts and styles to TeX code "
1533 if document.textclass != "IEEEtran":
1535 revert_flex_inset(document, "IEEE membership", "\\IEEEmembership", 0)
1536 revert_flex_inset(document, "Lowercase", "\\MakeLowercase", 0)
1537 layouts = ("Special Paper Notice", "After Title Text", "Publication ID",
1538 "Page headings", "Biography without photo")
1539 latexcmd = {"Special Paper Notice": "\\IEEEspecialpapernotice",
1540 "After Title Text": "\\IEEEaftertitletext",
1541 "Publication ID": "\\IEEEpubid"}
1542 obsoletedby = {"Page headings": "MarkBoth",
1543 "Biography without photo": "BiographyNoPhoto"}
1544 for layout in layouts:
1547 i = find_token(document.body, '\\begin_layout ' + layout, i)
1550 j = find_end_of_layout(document.body, i)
1552 document.warning("Malformed LyX document: Can't find end of " + layout + " layout.")
1555 if layout in obsoletedby:
1556 document.body[i] = "\\begin_layout " + obsoletedby[layout]
1559 content = lyx2latex(document, document.body[i:j + 1])
1560 add_to_preamble(document, [latexcmd[layout] + "{" + content + "}"])
1561 del document.body[i:j + 1]
1562 # no need to reset i
1565 def convert_prettyref(document):
1566 " Converts prettyref references to neutral formatted refs "
1567 re_ref = re.compile("^\s*reference\s+\"(\w+):(\S+)\"")
1568 nm_ref = re.compile("^\s*name\s+\"(\w+):(\S+)\"")
1572 i = find_token(document.body, "\\begin_inset CommandInset ref", i)
1575 j = find_end_of_inset(document.body, i)
1577 document.warning("Malformed LyX document: No end of InsetRef!")
1580 k = find_token(document.body, "LatexCommand prettyref", i, j)
1582 document.body[k] = "LatexCommand formatted"
1584 document.header.insert(-1, "\\use_refstyle 0")
1587 def revert_refstyle(document):
1588 " Reverts neutral formatted refs to prettyref "
1589 re_ref = re.compile("^reference\s+\"(\w+):(\S+)\"")
1590 nm_ref = re.compile("^\s*name\s+\"(\w+):(\S+)\"")
1594 i = find_token(document.body, "\\begin_inset CommandInset ref", i)
1597 j = find_end_of_inset(document.body, i)
1599 document.warning("Malformed LyX document: No end of InsetRef")
1602 k = find_token(document.body, "LatexCommand formatted", i, j)
1604 document.body[k] = "LatexCommand prettyref"
1606 i = find_token(document.header, "\\use_refstyle", 0)
1608 document.header.pop(i)
1611 def revert_nameref(document):
1612 " Convert namerefs to regular references "
1613 cmds = ["Nameref", "nameref"]
1615 rx = re.compile(r'reference "(.*)"')
1618 oldcmd = "LatexCommand " + cmd
1620 # It seems better to look for this, as most of the reference
1621 # insets won't be ones we care about.
1622 i = find_token(document.body, oldcmd, i)
1627 # Make sure it is actually in an inset!
1628 # A normal line could begin with "LatexCommand nameref"!
1629 stins, endins = get_containing_inset(document.body, cmdloc, \
1630 "\\begin_inset CommandInset ref")
1634 # ok, so it is in an InsetRef
1635 refline = find_token(document.body, "reference", stins, endins)
1637 document.warning("Can't find reference for inset at line " + stinst + "!!")
1639 m = rx.match(document.body[refline])
1641 document.warning("Can't match reference line: " + document.body[ref])
1645 newcontent = put_cmd_in_ert('\\' + cmd + '{' + ref + '}')
1646 document.body[stins:endins + 1] = newcontent
1649 add_to_preamble(document, "\usepackage{nameref}")
1652 def remove_Nameref(document):
1653 " Convert Nameref commands to nameref commands "
1656 # It seems better to look for this, as most of the reference
1657 # insets won't be ones we care about.
1658 i = find_token(document.body, "LatexCommand Nameref" , i)
1664 # Make sure it is actually in an inset!
1665 stins, endins = get_containing_inset(document.body, \
1666 cmdloc, "\\begin_inset CommandInset ref")
1669 document.body[cmdloc] = "LatexCommand nameref"
1672 def revert_mathrsfs(document):
1673 " Load mathrsfs if \mathrsfs us use in the document "
1675 for line in document.body:
1676 if line.find("\\mathscr{") != -1:
1677 add_to_preamble(document, ["% lyx2lyx mathrsfs addition", "\\usepackage{mathrsfs}"])
1681 def convert_flexnames(document):
1682 "Convert \\begin_inset Flex Custom:Style to \\begin_inset Flex Style and similarly for CharStyle and Element."
1685 rx = re.compile(r'^\\begin_inset Flex (?:Custom|CharStyle|Element):(.+)$')
1687 i = find_token(document.body, "\\begin_inset Flex", i)
1690 m = rx.match(document.body[i])
1692 document.body[i] = "\\begin_inset Flex " + m.group(1)
1697 "Alert" : "CharStyle:Alert",
1698 "Code" : "CharStyle:Code",
1699 "Concepts" : "CharStyle:Concepts",
1700 "E-Mail" : "CharStyle:E-Mail",
1701 "Emph" : "CharStyle:Emph",
1702 "Expression" : "CharStyle:Expression",
1703 "Initial" : "CharStyle:Initial",
1704 "Institute" : "CharStyle:Institute",
1705 "Meaning" : "CharStyle:Meaning",
1706 "Noun" : "CharStyle:Noun",
1707 "Strong" : "CharStyle:Strong",
1708 "Structure" : "CharStyle:Structure",
1709 "ArticleMode" : "Custom:ArticleMode",
1710 "Endnote" : "Custom:Endnote",
1711 "Glosse" : "Custom:Glosse",
1712 "PresentationMode" : "Custom:PresentationMode",
1713 "Tri-Glosse" : "Custom:Tri-Glosse"
1717 "Abbrev" : "Element:Abbrev",
1718 "CCC-Code" : "Element:CCC-Code",
1719 "Citation-number" : "Element:Citation-number",
1720 "City" : "Element:City",
1721 "Code" : "Element:Code",
1722 "CODEN" : "Element:CODEN",
1723 "Country" : "Element:Country",
1724 "Day" : "Element:Day",
1725 "Directory" : "Element:Directory",
1726 "Dscr" : "Element:Dscr",
1727 "Email" : "Element:Email",
1728 "Emph" : "Element:Emph",
1729 "Filename" : "Element:Filename",
1730 "Firstname" : "Element:Firstname",
1731 "Fname" : "Element:Fname",
1732 "GuiButton" : "Element:GuiButton",
1733 "GuiMenu" : "Element:GuiMenu",
1734 "GuiMenuItem" : "Element:GuiMenuItem",
1735 "ISSN" : "Element:ISSN",
1736 "Issue-day" : "Element:Issue-day",
1737 "Issue-months" : "Element:Issue-months",
1738 "Issue-number" : "Element:Issue-number",
1739 "KeyCap" : "Element:KeyCap",
1740 "KeyCombo" : "Element:KeyCombo",
1741 "Keyword" : "Element:Keyword",
1742 "Literal" : "Element:Literal",
1743 "MenuChoice" : "Element:MenuChoice",
1744 "Month" : "Element:Month",
1745 "Orgdiv" : "Element:Orgdiv",
1746 "Orgname" : "Element:Orgname",
1747 "Postcode" : "Element:Postcode",
1748 "SS-Code" : "Element:SS-Code",
1749 "SS-Title" : "Element:SS-Title",
1750 "State" : "Element:State",
1751 "Street" : "Element:Street",
1752 "Surname" : "Element:Surname",
1753 "Volume" : "Element:Volume",
1754 "Year" : "Element:Year"
1758 def revert_flexnames(document):
1759 if document.backend == "latex":
1760 flexlist = flex_insets
1762 flexlist = flex_elements
1764 rx = re.compile(r'^\\begin_inset Flex\s+(.+)$')
1767 i = find_token(document.body, "\\begin_inset Flex", i)
1770 m = rx.match(document.body[i])
1772 document.warning("Illegal flex inset: " + document.body[i])
1776 if style in flexlist:
1777 document.body[i] = "\\begin_inset Flex " + flexlist[style]
1781 def convert_mathdots(document):
1782 " Load mathdots automatically "
1783 i = find_token(document.header, "\\use_esint" , 0)
1785 document.header.insert(i + 1, "\\use_mathdots 1")
1788 def revert_mathdots(document):
1789 " Load mathdots if used in the document "
1791 mathdots = find_token(document.header, "\\use_mathdots" , 0)
1793 document.warning("No \\usemathdots line. Assuming auto.")
1795 val = get_value(document.header, "\\use_mathdots", mathdots)
1796 del document.header[mathdots]
1800 document.warning("Invalid \\use_mathdots value: " + val + ". Assuming auto.")
1801 # probably usedots has not been changed, but be safe.
1809 add_to_preamble(["% lyx2lyx mathdots addition", "\\usepackage{mathdots}"])
1812 # so we are in the auto case. we want to load mathdots if \iddots is used.
1815 i = find_token(document.body, '\\begin_inset Formula', i)
1818 j = find_end_of_inset(document.body, i)
1820 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
1823 code = "\n".join(document.body[i:j])
1824 if code.find("\\iddots") != -1:
1825 add_to_preamble(document, ["% lyx2lyx mathdots addition",
1826 "\\@ifundefined{iddots}{\\usepackage{mathdots}}"])
1831 def convert_rule(document):
1832 " Convert \\lyxline to CommandInset line. "
1835 inset = ['\\begin_inset CommandInset line',
1836 'LatexCommand rule',
1840 '\\end_inset', '', '']
1842 # if paragraphs are indented, we may have to unindent to get the
1843 # line to be full-width.
1844 indent = get_value(document.header, "\\paragraph_separation", 0)
1845 have_indent = (indent == "indent")
1848 i = find_token(document.body, "\\lyxline" , i)
1852 # we need to find out if this line follows other content
1853 # in its paragraph. find its layout....
1854 lastlay = find_token_backwards(document.body, "\\begin_layout", i)
1856 document.warning("Can't find layout for line at " + str(i))
1857 # do the best we can.
1858 document.body[i:i+1] = inset
1862 # ...and look for other content before it.
1864 for line in document.body[lastlay + 1:i]:
1865 # is it empty or a paragraph option?
1866 if not line or line[0] == '\\':
1872 document.body[i:i+1] = inset
1874 # we need to unindent, lest the line be too long
1875 document.body.insert(lastlay + 1, "\\noindent")
1878 # so our line is in the middle of a paragraph
1879 # we need to add a new line, lest this line follow the
1880 # other content on that line and run off the side of the page
1881 document.body[i:i+1] = inset
1882 document.body[i:i] = ["\\begin_inset Newline newline", "\\end_inset", ""]
1886 def revert_rule(document):
1887 " Revert line insets to Tex code "
1890 i = find_token(document.body, "\\begin_inset CommandInset line" , i)
1894 j = find_token(document.body, "\\end_inset" , i)
1896 document.warning("Malformed LyX document: Can't find end of line inset.")
1898 # determine the optional offset
1899 offset = get_value(document.body, 'offset', i, j).strip('"')
1901 offset = '[' + offset + ']'
1902 # determine the width
1903 width = get_value(document.body, 'width', i, j, "100col%").strip('"')
1904 width = latex_length(width)[1]
1905 # determine the height
1906 height = get_value(document.body, 'height', i, j, "1pt").strip('"')
1907 height = latex_length(height)[1]
1908 # output the \rule command
1909 subst = "\\rule[" + offset + "]{" + width + "}{" + height + "}"
1910 document.body[i:j + 1] = put_cmd_in_ert(subst)
1911 i += len(subst) - (j - i)
1914 def revert_diagram(document):
1915 " Add the feyn package if \\Diagram is used in math "
1918 i = find_token(document.body, '\\begin_inset Formula', i)
1921 j = find_end_of_inset(document.body, i)
1923 document.warning("Malformed LyX document: Can't find end of Formula inset.")
1925 lines = "\n".join(document.body[i:j])
1926 if lines.find("\\Diagram") == -1:
1929 add_to_preamble(document, ["% lyx2lyx feyn package insertion ", "\\usepackage{feyn}"])
1930 # only need to do it once!
1934 def convert_bibtex_clearpage(document):
1935 " insert a clear(double)page bibliographystyle if bibtotoc option is used "
1937 i = find_token(document.header, '\\papersides', 0)
1940 document.warning("Malformed LyX document: Can't find papersides definition.")
1941 document.warning("Assuming single sided.")
1944 val = get_value(document.header, "\\papersides", i)
1949 if sides != 1 and sides != 2:
1950 document.warning("Invalid papersides value: " + val)
1951 document.warning("Assuming single sided.")
1956 j = find_token(document.body, "\\begin_inset CommandInset bibtex", j)
1960 k = find_end_of_inset(document.body, j)
1962 document.warning("Can't find end of Bibliography inset at line " + str(j))
1966 # only act if there is the option "bibtotoc"
1967 val = get_value(document.body, 'options', j, k)
1969 document.warning("Can't find options for bibliography inset at line " + str(j))
1973 if val.find("bibtotoc") == -1:
1977 # so we want to insert a new page right before the paragraph that
1978 # this bibliography thing is in.
1979 lay = find_token_backwards(document.body, "\\begin_layout", j)
1981 document.warning("Can't find layout containing bibliography inset at line " + str(j))
1988 cmd = "cleardoublepage"
1989 subst = ['\\begin_layout Standard',
1990 '\\begin_inset Newpage ' + cmd,
1991 '\\end_inset', '', '',
1993 document.body[lay:lay] = subst
2001 supported_versions = ["2.0.0","2.0"]
2002 convert = [[346, []],
2008 [352, [convert_splitindex]],
2015 [359, [convert_nomencl_width]],
2025 [369, [convert_author_id]],
2029 [373, [merge_gbrief]],
2035 [379, [convert_math_output]],
2045 [389, [convert_html_quotes]],
2049 [393, [convert_optarg]],
2050 [394, [convert_use_makebox]],
2053 [397, [remove_Nameref]],
2055 [399, [convert_mathdots]],
2056 [400, [convert_rule]],
2058 [402, [convert_bibtex_clearpage]],
2059 [403, [convert_flexnames]],
2060 [404, [convert_prettyref]]
2063 revert = [[403, [revert_refstyle]],
2064 [402, [revert_flexnames]],
2066 [400, [revert_diagram]],
2067 [399, [revert_rule]],
2068 [398, [revert_mathdots]],
2069 [397, [revert_mathrsfs]],
2071 [395, [revert_nameref]],
2072 [394, [revert_DIN_C_pagesizes]],
2073 [393, [revert_makebox]],
2074 [392, [revert_argument]],
2076 [390, [revert_align_decimal, revert_IEEEtran]],
2077 [389, [revert_output_sync]],
2078 [388, [revert_html_quotes]],
2079 [387, [revert_pagesizes]],
2080 [386, [revert_math_scale]],
2081 [385, [revert_lyx_version]],
2082 [384, [revert_shadedboxcolor]],
2083 [383, [revert_fontcolor]],
2084 [382, [revert_turkmen]],
2085 [381, [revert_notefontcolor]],
2086 [380, [revert_equalspacing_xymatrix]],
2087 [379, [revert_inset_preview]],
2088 [378, [revert_math_output]],
2090 [376, [revert_multirow]],
2091 [375, [revert_includeall]],
2092 [374, [revert_includeonly]],
2093 [373, [revert_html_options]],
2094 [372, [revert_gbrief]],
2095 [371, [revert_fontenc]],
2096 [370, [revert_mhchem]],
2097 [369, [revert_suppress_date]],
2098 [368, [revert_author_id]],
2099 [367, [revert_hspace_glue_lengths]],
2100 [366, [revert_percent_vspace_lengths, revert_percent_hspace_lengths]],
2101 [365, [revert_percent_skip_lengths]],
2102 [364, [revert_paragraph_indentation]],
2103 [363, [revert_branch_filename]],
2104 [362, [revert_longtable_align]],
2105 [361, [revert_applemac]],
2107 [359, [revert_nomencl_cwidth]],
2108 [358, [revert_nomencl_width]],
2109 [357, [revert_custom_processors]],
2110 [356, [revert_ulinelatex]],
2112 [354, [revert_strikeout]],
2113 [353, [revert_printindexall]],
2114 [352, [revert_subindex]],
2115 [351, [revert_splitindex]],
2116 [350, [revert_backgroundcolor]],
2117 [349, [revert_outputformat]],
2118 [348, [revert_xetex]],
2119 [347, [revert_phantom, revert_hphantom, revert_vphantom]],
2120 [346, [revert_tabularvalign]],
2121 [345, [revert_swiss]]
2125 if __name__ == "__main__":