]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/lyx_2_1.py
1d159d94dcb52293d19e080b92c0eb546f93ef24
[lyx.git] / lib / lyx2lyx / lyx_2_1.py
1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
20 """ Convert files to the file format generated by lyx 2.1"""
21
22 import re, string
23 import unicodedata
24 import sys, os
25
26 # Uncomment only what you need to import, please.
27
28 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
29     find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30     find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31     get_value, get_quoted_value, set_option_value
32
33 #from parser_tools import find_token, find_end_of, find_tokens, \
34   #find_end_of_inset, find_end_of_layout, \
35   #is_in_inset, del_token, check_token
36
37 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
38
39 #from lyx2lyx_tools import insert_to_preamble, \
40 #  lyx2latex, latex_length, revert_flex_inset, \
41 #  revert_font_attrs, hex2ratio, str2bool
42
43 ####################################################################
44 # Private helper functions
45
46 #def remove_option(lines, m, option):
47     #''' removes option from line m. returns whether we did anything '''
48     #l = lines[m].find(option)
49     #if l == -1:
50         #return False
51     #val = lines[m][l:].split('"')[1]
52     #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
53     #return True
54
55
56 ###############################################################################
57 ###
58 ### Conversion and reversion routines
59 ###
60 ###############################################################################
61
62 def revert_visible_space(document):
63     "Revert InsetSpace visible into its ERT counterpart"
64     i = 0
65     while True:
66       i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
67       if i == -1:
68         return
69       end = find_end_of_inset(document.body, i)
70       subst = put_cmd_in_ert("\\textvisiblespace{}")
71       document.body[i:end + 1] = subst
72
73
74 def convert_undertilde(document):
75     " Load undertilde automatically "
76     i = find_token(document.header, "\\use_mathdots" , 0)
77     if i == -1:
78         i = find_token(document.header, "\\use_mhchem" , 0)
79     if i == -1:
80         i = find_token(document.header, "\\use_esint" , 0)
81     if i == -1:
82         document.warning("Malformed LyX document: Can't find \\use_mathdots.")
83         return;
84     j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
85     if j == -1:
86         document.header.insert(i + 1, "\\use_undertilde 0")
87     else:
88         document.header.insert(i + 1, "\\use_undertilde 2")
89         del document.preamble[j]
90
91
92 def revert_undertilde(document):
93     " Load undertilde if used in the document "
94     undertilde = find_token(document.header, "\\use_undertilde" , 0)
95     if undertilde == -1:
96       document.warning("No \\use_undertilde line. Assuming auto.")
97     else:
98       val = get_value(document.header, "\\use_undertilde", undertilde)
99       del document.header[undertilde]
100       try:
101         usetilde = int(val)
102       except:
103         document.warning("Invalid \\use_undertilde value: " + val + ". Assuming auto.")
104         # probably usedots has not been changed, but be safe.
105         usetilde = 1
106
107       if usetilde == 0:
108         # do not load case
109         return
110       if usetilde == 2:
111         # force load case
112         add_to_preamble(document, ["\\usepackage{undertilde}"])
113         return
114
115     # so we are in the auto case. we want to load undertilde if \utilde is used.
116     i = 0
117     while True:
118       i = find_token(document.body, '\\begin_inset Formula', i)
119       if i == -1:
120         return
121       j = find_end_of_inset(document.body, i)
122       if j == -1:
123         document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
124         i += 1
125         continue
126       code = "\n".join(document.body[i:j])
127       if code.find("\\utilde") != -1:
128         add_to_preamble(document, ["\\@ifundefined{utilde}{\\usepackage{undertilde}}"])
129         return
130       i = j
131
132
133 def revert_negative_space(document):
134     "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
135     i = 0
136     j = 0
137     reverted = False
138     while True:
139       i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
140       if i == -1:
141         j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
142         if j == -1:
143           # load amsmath in the preamble if not already loaded if we are at the end of checking
144           if reverted == True:
145             i = find_token(document.header, "\\use_amsmath 2", 0)
146             if i == -1:
147               add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
148           return
149       if i == -1:
150         return
151       end = find_end_of_inset(document.body, i)
152       subst = put_cmd_in_ert("\\negmedspace{}")
153       document.body[i:end + 1] = subst
154       j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
155       if j == -1:
156         return
157       end = find_end_of_inset(document.body, j)
158       subst = put_cmd_in_ert("\\negthickspace{}")
159       document.body[j:end + 1] = subst
160       reverted = True
161
162
163 def revert_math_spaces(document):
164     "Revert formulas with protected custom space and protected hfills to TeX-code"
165     i = 0
166     while True:
167       i = find_token(document.body, "\\begin_inset Formula", i)
168       if i == -1:
169         return
170       j = document.body[i].find("\\hspace*")
171       if j != -1:
172         end = find_end_of_inset(document.body, i)
173         subst = put_cmd_in_ert(document.body[i][21:])
174         document.body[i:end + 1] = subst
175       i = i + 1
176
177
178 def convert_japanese_encodings(document):
179     " Rename the japanese encodings to names understood by platex "
180     jap_enc_dict = {
181         "EUC-JP-pLaTeX": "euc",
182         "JIS-pLaTeX":    "jis",
183         "SJIS-pLaTeX":   "sjis"
184     }
185     i = find_token(document.header, "\\inputencoding" , 0)
186     if i == -1:
187         return
188     val = get_value(document.header, "\\inputencoding", i)
189     if val in jap_enc_dict.keys():
190         document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
191
192
193 def revert_japanese_encodings(document):
194     " Revert the japanese encodings name changes "
195     jap_enc_dict = {
196         "euc":  "EUC-JP-pLaTeX",
197         "jis":  "JIS-pLaTeX",
198         "sjis": "SJIS-pLaTeX"
199     }
200     i = find_token(document.header, "\\inputencoding" , 0)
201     if i == -1:
202         return
203     val = get_value(document.header, "\\inputencoding", i)
204     if val in jap_enc_dict.keys():
205         document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
206
207
208 def revert_justification(document):
209     " Revert the \\justification buffer param"
210     if not del_token(document.header, '\\justification', 0):
211         document.warning("Malformed LyX document: Missing \\justification.")
212
213
214 def revert_australian(document):
215     "Set English language variants Australian and Newzealand to English" 
216
217     if document.language == "australian" or document.language == "newzealand": 
218         document.language = "english"
219         i = find_token(document.header, "\\language", 0) 
220         if i != -1: 
221             document.header[i] = "\\language english" 
222     j = 0 
223     while True: 
224         j = find_token(document.body, "\\lang australian", j) 
225         if j == -1:
226             j = find_token(document.body, "\\lang newzealand", 0)
227             if j == -1:
228                 return
229             else:
230                 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
231         else:
232             document.body[j] = document.body[j].replace("\\lang australian", "\\lang english") 
233         j += 1
234
235
236 def convert_biblio_style(document):
237     "Add a sensible default for \\biblio_style based on the citation engine."
238     i = find_token(document.header, "\\cite_engine", 0)
239     if i != -1:
240         engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
241         style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
242         document.header.insert(i + 1, "\\biblio_style " + style[engine])
243
244
245 def revert_biblio_style(document):
246     "BibTeX insets with default option use the style defined by \\biblio_style."
247     i = find_token(document.header, "\\biblio_style" , 0)
248     if i == -1:
249         document.warning("No \\biblio_style line. Nothing to do.")
250         return
251
252     default_style = get_value(document.header, "\\biblio_style", i)
253     del document.header[i]
254
255     # We are looking for bibtex insets having the default option
256     i = 0
257     while True:
258         i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
259         if i == -1:
260             return
261         j = find_end_of_inset(document.body, i)
262         if j == -1:
263             document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
264             i += 1
265             return
266         k = find_token(document.body, "options", i, j)
267         if k != -1:
268             options = get_quoted_value(document.body, "options", k)
269             if "default" in options.split(","):
270                 document.body[k] = 'options "%s"' \
271                     % options.replace("default", default_style)
272         i = j
273
274
275 def handle_longtable_captions(document, forward):
276     begin_table = 0
277     while True:
278         begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
279         if begin_table == -1:
280             break
281         end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
282         if end_table == -1:
283             document.warning("Malformed LyX document: Could not find end of table.")
284             begin_table += 1
285             continue
286         fline = find_token(document.body, "<features", begin_table, end_table)
287         if fline == -1:
288             document.warning("Can't find features for inset at line " + str(begin_table))
289             begin_table += 1
290             continue
291         p = document.body[fline].find("islongtable")
292         if p == -1:
293             # no longtable
294             begin_table += 1
295             continue
296         numrows = get_option_value(document.body[begin_table], "rows")
297         try:
298             numrows = int(numrows)
299         except:
300             document.warning(document.body[begin_table])
301             document.warning("Unable to determine rows!")
302             begin_table = end_table
303             continue
304         begin_row = begin_table
305         for row in range(numrows):
306             begin_row = find_token(document.body, '<row', begin_row, end_table)
307             if begin_row == -1:
308                 document.warning("Can't find row " + str(row + 1))
309                 break
310             end_row = find_end_of(document.body, begin_row, '<row', '</row>')
311             if end_row == -1:
312                 document.warning("Can't find end of row " + str(row + 1))
313                 break
314             if forward:
315                 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
316                     get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
317                     get_option_value(document.body[begin_row], 'endhead') != 'true' and
318                     get_option_value(document.body[begin_row], 'endfoot') != 'true' and
319                     get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
320                     document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
321             elif get_option_value(document.body[begin_row], 'caption') == 'true':
322                 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
323                     document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
324                 if get_option_value(document.body[begin_row], 'endhead') == 'true':
325                     document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
326                 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
327                     document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
328                 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
329                     document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
330             begin_row = end_row
331         # since there could be a tabular inside this one, we 
332         # cannot jump to end.
333         begin_table += 1
334
335
336 def convert_longtable_captions(document):
337     "Add a firsthead flag to caption rows"
338     handle_longtable_captions(document, True)
339
340
341 def revert_longtable_captions(document):
342     "remove head/foot flag from caption rows"
343     handle_longtable_captions(document, False)
344
345
346 def convert_use_packages(document):
347     "use_xxx yyy => use_package xxx yyy"
348     packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
349     for p in packages:
350         i = find_token(document.header, "\\use_%s" % p, 0)
351         if i != -1:
352             value = get_value(document.header, "\\use_%s" % p, i)
353             document.header[i] = "\\use_package %s %s" % (p, value)
354
355
356 def revert_use_packages(document):
357     "use_package xxx yyy => use_xxx yyy"
358     packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
359     # the order is arbitrary for the use_package version, and not all packages need to be given.
360     # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
361     j = 0
362     for p in packages:
363         regexp = re.compile(r'(\\use_package\s+%s)' % p)
364         i = find_re(document.header, regexp, j)
365         if i != -1:
366             value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
367             del document.header[i]
368             j = i
369             document.header.insert(j, "\\use_%s %s"  % (p, value))
370         j = j + 1
371
372
373 def convert_use_mathtools(document):
374     "insert use_package mathtools"
375     i = find_token(document.header, "\\use_package", 0)
376     if i == -1:
377         document.warning("Malformed LyX document: Can't find \\use_package.")
378         return;
379     j = find_token(document.preamble, "\\usepackage{mathtools}", 0)
380     if j == -1:
381         document.header.insert(i + 1, "\\use_package mathtools 0")
382     else:
383         document.header.insert(i + 1, "\\use_package mathtools 2")
384         del document.preamble[j]
385
386
387 def revert_use_mathtools(document):
388     "remove use_package mathtools"
389     regexp = re.compile(r'(\\use_package\s+mathtools)')
390     i = find_re(document.header, regexp, 0)
391     value = "1" # default is auto
392     if i != -1:
393         value = get_value(document.header, "\\use_package" , i).split()[1]
394         del document.header[i]
395     if value == "2": # on
396         add_to_preamble(document, ["\\usepackage{mathtools}"])
397     elif value == "1": # auto
398         commands = ["mathclap", "mathllap", "mathrlap", \
399                     "lgathered", "rgathered", "vcentcolon", "dblcolon", \
400                     "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
401                     "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
402                     "Colonapprox", "colonsim", "Colonsim"]
403         i = 0
404         while True:
405             i = find_token(document.body, '\\begin_inset Formula', i)
406             if i == -1:
407                 return
408             j = find_end_of_inset(document.body, i)
409             if j == -1:
410                 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
411                 i += 1
412                 continue
413             code = "\n".join(document.body[i:j])
414             for c in commands:
415                 if code.find("\\%s" % c) != -1:
416                     add_to_preamble(document, ["\\usepackage{mathtools}"])
417                     return
418             i = j
419
420
421 def convert_use_stmaryrd(document):
422     "insert use_package stmaryrd"
423     i = find_token(document.header, "\\use_package", 0)
424     if i == -1:
425         document.warning("Malformed LyX document: Can't find \\use_package.")
426         return;
427     j = find_token(document.preamble, "\\usepackage{stmaryrd}", 0)
428     if j == -1:
429         document.header.insert(i + 1, "\\use_package stmaryrd 0")
430     else:
431         document.header.insert(i + 1, "\\use_package stmaryrd 2")
432         del document.preamble[j]
433
434
435 def revert_use_stmaryrd(document):
436     "remove use_package stmaryrd"
437     regexp = re.compile(r'(\\use_package\s+stmaryrd)')
438     i = find_re(document.header, regexp, 0)
439     value = "1" # default is auto
440     if i != -1:
441         value = get_value(document.header, "\\use_package" , i).split()[1]
442         del document.header[i]
443     if value == "2": # on
444         add_to_preamble(document, ["\\usepackage{stmaryrd}"])
445     elif value == "1": # auto
446         commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
447                     "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
448                     "varcurlyvee", "varcurlywedge", "minuso", "baro", \
449                     "sslash", "bbslash", "moo", "varotimes", "varoast", \
450                     "varobar", "varodot", "varoslash", "varobslash", \
451                     "varocircle", "varoplus", "varominus", "boxast", \
452                     "boxbar", "boxslash", "boxbslash", "boxcircle", \
453                     "boxbox", "boxempty", "merge", "vartimes", \
454                     "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
455                     "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
456                     "rbag", "varbigcirc", "leftrightarroweq", \
457                     "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
458                     "nnearrow", "leftslice", "rightslice", "varolessthan", \
459                     "varogreaterthan", "varovee", "varowedge", "talloblong", \
460                     "interleave", "obar", "obslash", "olessthan", \
461                     "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
462                     "niplus", "nplus", "subsetplus", "supsetplus", \
463                     "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
464                     "llbracket", "rrbracket", "llparenthesis", \
465                     "rrparenthesis", "binampersand", "bindnasrepma", \
466                     "trianglelefteqslant", "trianglerighteqslant", \
467                     "ntrianglelefteqslant", "ntrianglerighteqslant", \
468                     "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
469                     "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
470                     "leftrightarrowtriangle", "leftarrowtriangle", \
471                     "rightarrowtriangle", \
472                     "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
473                     "bigparallel", "biginterleave", "bignplus", \
474                     "varcopyright", "longarrownot", "Longarrownot", \
475                     "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
476                     "longmapsfrom", "Longmapsfrom"]
477         # commands provided by stmaryrd.sty but LyX uses other packages:
478         # boxdot lightning, bigtriangledown, bigtriangleup
479
480         i = 0
481         while True:
482             i = find_token(document.body, '\\begin_inset Formula', i)
483             if i == -1:
484                 return
485             j = find_end_of_inset(document.body, i)
486             if j == -1:
487                 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
488                 i += 1
489                 continue
490             code = "\n".join(document.body[i:j])
491             for c in commands:
492                 if code.find("\\%s" % c) != -1:
493                     add_to_preamble(document, ["\\usepackage{stmaryrd}"])
494                     return
495             i = j
496
497
498 def convert_use_stackrel(document):
499     "insert use_package stackrel"
500     i = find_token(document.header, "\\use_package", 0)
501     if i == -1:
502         document.warning("Malformed LyX document: Can't find \\use_package.")
503         return;
504     j = find_token(document.preamble, "\\usepackage{stackrel}", 0)
505     if j == -1:
506         document.header.insert(i + 1, "\\use_package stackrel 0")
507     else:
508         document.header.insert(i + 1, "\\use_package stackrel 2")
509         del document.preamble[j]
510
511
512 def revert_use_stackrel(document):
513     "remove use_package stackrel"
514     regexp = re.compile(r'(\\use_package\s+stackrel)')
515     i = find_re(document.header, regexp, 0)
516     value = "1" # default is auto
517     if i != -1:
518         value = get_value(document.header, "\\use_package" , i).split()[1]
519         del document.header[i]
520     if value == "2": # on
521         add_to_preamble(document, ["\\usepackage{stackrel}"])
522     elif value == "1": # auto
523         regcmd = re.compile(r'.*\\stackrel\s*\[')
524         i = 0
525         while True:
526             i = find_token(document.body, '\\begin_inset Formula', i)
527             if i == -1:
528                 return
529             j = find_end_of_inset(document.body, i)
530             if j == -1:
531                 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
532                 i += 1
533                 continue
534             code = "\n".join(document.body[i:j])
535             if regcmd.match(code):
536                 add_to_preamble(document, ["\\usepackage{stackrel}"])
537                 return
538             i = j
539
540
541 def convert_cite_engine_type(document):
542     "Determine the \\cite_engine_type from the citation engine."
543     i = find_token(document.header, "\\cite_engine", 0)
544     if i == -1:
545         return
546     engine = get_value(document.header, "\\cite_engine", i)
547     if "_" in engine:
548         engine, type = engine.split("_")
549     else:
550         type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
551     document.header[i] = "\\cite_engine " + engine
552     document.header.insert(i + 1, "\\cite_engine_type " + type)
553
554
555 def revert_cite_engine_type(document):
556     "Natbib had the type appended with an underscore."
557     engine_type = "numerical"
558     i = find_token(document.header, "\\cite_engine_type" , 0)
559     if i == -1:
560         document.warning("No \\cite_engine_type line. Assuming numerical.")
561     else:
562         engine_type = get_value(document.header, "\\cite_engine_type", i)
563         del document.header[i]
564
565     # We are looking for the natbib citation engine
566     i = find_token(document.header, "\\cite_engine natbib", 0)
567     if i == -1:
568         return
569     document.header[i] = "\\cite_engine natbib_" + engine_type
570
571
572 def revert_cancel(document):
573     "add cancel to the preamble if necessary"
574     commands = ["cancelto", "cancel", "bcancel", "xcancel"]
575     i = 0
576     while True:
577         i = find_token(document.body, '\\begin_inset Formula', i)
578         if i == -1:
579             return
580         j = find_end_of_inset(document.body, i)
581         if j == -1:
582             document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
583             i += 1
584             continue
585         code = "\n".join(document.body[i:j])
586         for c in commands:
587             if code.find("\\%s" % c) != -1:
588                 add_to_preamble(document, ["\\usepackage{cancel}"])
589                 return
590         i = j
591
592
593 def revert_verbatim(document):
594     " Revert verbatim einvironments completely to TeX-code. "
595     i = 0
596     consecutive = False
597     subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
598                  '\end_layout', '',
599                  '\\begin_layout Plain Layout', '', '',
600                  '\\backslash', '',
601                  'end{verbatim}',
602                  '\\end_layout', '', '\\end_inset',
603                  '', '', '\\end_layout']
604     subst_begin = ['\\begin_layout Standard', '\\noindent',
605                    '\\begin_inset ERT', 'status collapsed', '',
606                    '\\begin_layout Plain Layout', '', '', '\\backslash',
607                    'begin{verbatim}',
608                    '\\end_layout', '', '\\begin_layout Plain Layout', '']
609     while 1:
610         i = find_token(document.body, "\\begin_layout Verbatim", i)
611         if i == -1:
612             return
613         j = find_end_of_layout(document.body, i)
614         if j == -1:
615             document.warning("Malformed lyx document: Can't find end of Verbatim layout")
616             i += 1
617             continue
618         # delete all line breaks insets (there are no other insets)
619         l = i
620         while 1:
621             n = find_token(document.body, "\\begin_inset Newline newline", l)
622             if n == -1:
623                 n = find_token(document.body, "\\begin_inset Newline linebreak", l)
624                 if n == -1:
625                     break
626             m = find_end_of_inset(document.body, n)
627             del(document.body[m:m+1])
628             document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
629             l += 1
630             j += 1
631         # consecutive verbatim environments need to be connected
632         k = find_token(document.body, "\\begin_layout Verbatim", j)
633         if k == j + 2 and consecutive == False:
634             consecutive = True
635             document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
636             document.body[i:i+1] = subst_begin
637             continue
638         if k == j + 2 and consecutive == True:
639             document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
640             del(document.body[i:i+1])
641             continue
642         if k != j + 2 and consecutive == True:
643             document.body[j:j+1] = subst_end
644             # the next paragraph must not be indented
645             document.body[j+19:j+19] = ['\\noindent']
646             del(document.body[i:i+1])
647             consecutive = False
648             continue
649         else:
650             document.body[j:j+1] = subst_end
651             # the next paragraph must not be indented
652             document.body[j+19:j+19] = ['\\noindent']
653             document.body[i:i+1] = subst_begin
654
655
656 def revert_tipa(document):
657     " Revert native TIPA insets to mathed or ERT. "
658     i = 0
659     while 1:
660         i = find_token(document.body, "\\begin_inset IPA", i)
661         if i == -1:
662             return
663         j = find_end_of_inset(document.body, i)
664         if j == -1:
665             document.warning("Malformed lyx document: Can't find end of IPA inset")
666             i += 1
667             continue
668         Multipar = False
669         n = find_token(document.body, "\\begin_layout", i, j)
670         if n == -1:
671             document.warning("Malformed lyx document: IPA inset has no embedded layout")
672             i += 1
673             continue
674         m = find_end_of_layout(document.body, n)
675         if m == -1:
676             document.warning("Malformed lyx document: Can't find end of embedded layout")
677             i += 1
678             continue
679         content = document.body[n+1:m]
680         p = find_token(document.body, "\\begin_layout", m, j)
681         if p != -1 or len(content) > 1:
682             Multipar = True
683             content = document.body[i+1:j]
684         if Multipar:
685             # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
686             document.body[i:j+1] = ['\\end_layout', '', '\\begin_layout Standard'] + put_cmd_in_ert("\\begin{IPA}") + ['\\end_layout'] + content + ['\\begin_layout Standard'] + put_cmd_in_ert("\\end{IPA}")
687             add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
688         else:
689             # single-par IPA insets can be reverted to mathed
690             document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
691         i = j
692
693
694 def revert_cell_rotation(document):
695   "Revert cell rotations to TeX-code"
696
697   load_rotating = False
698   i = 0
699   try:
700     while True:
701       # first, let's find out if we need to do anything
702       i = find_token(document.body, '<cell ', i)
703       if i == -1:
704         return
705       j = document.body[i].find('rotate="')
706       if j != -1:
707         k = document.body[i].find('"', j + 8)
708         value = document.body[i][j + 8 : k]
709         if value == "0":
710           rgx = re.compile(r' rotate="[^"]+?"')
711           # remove rotate option
712           document.body[i] = rgx.sub('', document.body[i])
713         elif value == "90":
714           rgx = re.compile(r' rotate="[^"]+?"')
715           document.body[i] = rgx.sub('rotate="true"', document.body[i])
716         else:
717           rgx = re.compile(r' rotate="[^"]+?"')
718           load_rotating = True
719           # remove rotate option
720           document.body[i] = rgx.sub('', document.body[i])
721           # write ERT
722           document.body[i + 5 : i + 5] = \
723             put_cmd_in_ert("\\end{turn}")
724           document.body[i + 4 : i + 4] = \
725             put_cmd_in_ert("\\begin{turn}{" + value + "}")
726         
727       i += 1
728         
729   finally:
730     if load_rotating:
731       add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
732
733
734 def convert_cell_rotation(document):
735     'Convert cell rotation statements from "true" to "90"'
736
737     i = 0
738     while True:
739       # first, let's find out if we need to do anything
740       i = find_token(document.body, '<cell ', i)
741       if i == -1:
742         return
743       j = document.body[i].find('rotate="true"')
744       if j != -1:
745         rgx = re.compile(r'rotate="[^"]+?"')
746         # convert "true" to "90"
747         document.body[i] = rgx.sub('rotate="90"', document.body[i])
748         
749       i += 1
750
751
752 def revert_table_rotation(document):
753   "Revert table rotations to TeX-code"
754
755   load_rotating = False
756   i = 0
757   try:
758     while True:
759       # first, let's find out if we need to do anything
760       i = find_token(document.body, '<features ', i)
761       if i == -1:
762         return
763       j = document.body[i].find('rotate="')
764       if j != -1:
765         end_table = find_token(document.body, '</lyxtabular>', j)
766         k = document.body[i].find('"', j + 8)
767         value = document.body[i][j + 8 : k]
768         if value == "0":
769           rgx = re.compile(r' rotate="[^"]+?"')
770           # remove rotate option
771           document.body[i] = rgx.sub('', document.body[i])
772         elif value == "90":
773           rgx = re.compile(r'rotate="[^"]+?"')
774           document.body[i] = rgx.sub('rotate="true"', document.body[i])
775         else:
776           rgx = re.compile(r' rotate="[^"]+?"')
777           load_rotating = True
778           # remove rotate option
779           document.body[i] = rgx.sub('', document.body[i])
780           # write ERT
781           document.body[end_table + 3 : end_table + 3] = \
782             put_cmd_in_ert("\\end{turn}")
783           document.body[i - 2 : i - 2] = \
784             put_cmd_in_ert("\\begin{turn}{" + value + "}")
785         
786       i += 1
787         
788   finally:
789     if load_rotating:
790       add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
791
792
793 def convert_table_rotation(document):
794     'Convert table rotation statements from "true" to "90"'
795
796     i = 0
797     while True:
798       # first, let's find out if we need to do anything
799       i = find_token(document.body, '<features ', i)
800       if i == -1:
801         return
802       j = document.body[i].find('rotate="true"')
803       if j != -1:
804         rgx = re.compile(r'rotate="[^"]+?"')
805         # convert "true" to "90"
806         document.body[i] = rgx.sub('rotate="90"', document.body[i])
807         
808       i += 1
809
810
811 def convert_listoflistings(document):
812     'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
813     # We can support roundtrip because the command is so simple
814     i = 0
815     while True:
816         i = find_token(document.body, "\\begin_inset ERT", i)
817         if i == -1:
818             return
819         j = find_end_of_inset(document.body, i)
820         if j == -1:
821             document.warning("Malformed lyx document: Can't find end of ERT inset")
822             i += 1
823             continue
824         ert = get_ert(document.body, i)
825         if ert == "\\lstlistoflistings{}":
826             document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
827             i = i + 4
828         else:
829             i = j + 1
830
831
832 def revert_listoflistings(document):
833     'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
834     i = 0
835     while True:
836         i = find_token(document.body, "\\begin_inset CommandInset toc", i)
837         if i == -1:
838             return
839         if document.body[i+1] == "LatexCommand lstlistoflistings":
840             j = find_end_of_inset(document.body, i)
841             if j == -1:
842                 document.warning("Malformed lyx document: Can't find end of TOC inset")
843                 i += 1
844                 continue
845             subst = put_cmd_in_ert("\\lstlistoflistings{}")
846             document.body[i:j+1] = subst
847             add_to_preamble(document, ["\\usepackage{listings}"])
848         i = i + 1
849
850
851 def convert_use_amssymb(document):
852     "insert use_package amssymb"
853     regexp = re.compile(r'(\\use_package\s+amsmath)')
854     i = find_re(document.header, regexp, 0)
855     if i == -1:
856         document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
857         return;
858     value = get_value(document.header, "\\use_package" , i).split()[1]
859     useamsmath = 0
860     try:
861         useamsmath = int(value)
862     except:
863         document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
864         useamsmath = 1
865     j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
866     if j == -1:
867         document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
868     else:
869         document.header.insert(i + 1, "\\use_package amssymb 2")
870         del document.preamble[j]
871
872
873 def revert_use_amssymb(document):
874     "remove use_package amssymb"
875     regexp1 = re.compile(r'(\\use_package\s+amsmath)')
876     regexp2 = re.compile(r'(\\use_package\s+amssymb)')
877     i = find_re(document.header, regexp1, 0)
878     j = find_re(document.header, regexp2, 0)
879     value1 = "1" # default is auto
880     value2 = "1" # default is auto
881     if i != -1:
882         value1 = get_value(document.header, "\\use_package" , i).split()[1]
883     if j != -1:
884         value2 = get_value(document.header, "\\use_package" , j).split()[1]
885         del document.header[j]
886     if value1 != value2 and value2 == "2": # on
887         add_to_preamble(document, ["\\usepackage{amssymb}"])
888
889
890 def revert_ancientgreek(document):
891     "Set the document language for ancientgreek to greek" 
892
893     if document.language == "ancientgreek": 
894         document.language = "greek"
895         i = find_token(document.header, "\\language", 0) 
896         if i != -1: 
897             document.header[i] = "\\language greek" 
898     j = 0 
899     while True: 
900         j = find_token(document.body, "\\lang ancientgreek", j) 
901         if j == -1:
902             return
903         else:
904             document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek") 
905         j += 1
906
907
908 def revert_languages(document):
909     "Set the document language for new supported languages to English" 
910
911     languages = [
912                  "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
913                  "syriac", "tamil", "telugu", "urdu"
914                 ]
915     for n in range(len(languages)):
916         if document.language == languages[n]:
917             document.language = "english"
918             i = find_token(document.header, "\\language", 0) 
919             if i != -1: 
920                 document.header[i] = "\\language english" 
921         j = 0
922         while j < len(document.body): 
923             j = find_token(document.body, "\\lang " + languages[n], j)
924             if j != -1:
925                 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
926                 j += 1
927             else:
928                 j = len(document.body)
929
930
931 def convert_armenian(document):
932     "Use polyglossia and thus non-TeX fonts for Armenian" 
933
934     if document.language == "armenian": 
935         i = find_token(document.header, "\\use_non_tex_fonts", 0) 
936         if i != -1: 
937             document.header[i] = "\\use_non_tex_fonts true" 
938
939
940 def revert_armenian(document):
941     "Use ArmTeX and thus TeX fonts for Armenian" 
942
943     if document.language == "armenian": 
944         i = find_token(document.header, "\\use_non_tex_fonts", 0) 
945         if i != -1: 
946             document.header[i] = "\\use_non_tex_fonts false" 
947
948
949 def revert_libertine(document):
950     " Revert native libertine font definition to LaTeX " 
951
952     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
953         i = find_token(document.header, "\\font_roman libertine", 0)
954         if i != -1:
955             osf = False
956             j = find_token(document.header, "\\font_osf true", 0)
957             if j != -1:
958                 osf = True
959             preamble = "\\usepackage"
960             if osf:
961                 document.header[j] = "\\font_osf false"
962                 preamble += "[osf]"
963             else:
964                 preamble += "[lining]"
965             preamble += "{libertine-type1}"
966             add_to_preamble(document, [preamble])
967             document.header[i] = "\\font_roman default"
968
969
970 def revert_txtt(document):
971     " Revert native txtt font definition to LaTeX " 
972
973     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
974         i = find_token(document.header, "\\font_typewriter txtt", 0)
975         if i != -1:
976             preamble = "\\renewcommand{\\ttdefault}{txtt}"
977             add_to_preamble(document, [preamble])
978             document.header[i] = "\\font_typewriter default"
979
980
981 def revert_mathdesign(document):
982     " Revert native mathdesign font definition to LaTeX " 
983
984     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
985         mathdesign_dict = {
986         "mdbch":  "charter",
987         "mdput":  "utopia",
988         "mdugm":  "garamond"
989         }
990         i = find_token(document.header, "\\font_roman", 0)
991         if i == -1:
992             return
993         val = get_value(document.header, "\\font_roman", i)
994         if val in mathdesign_dict.keys():
995             preamble = "\\usepackage[%s" % mathdesign_dict[val]
996             expert = False
997             j = find_token(document.header, "\\font_osf true", 0)
998             if j != -1:
999                 expert = True
1000                 document.header[j] = "\\font_osf false"
1001             l = find_token(document.header, "\\font_sc true", 0)
1002             if l != -1:
1003                 expert = True
1004                 document.header[l] = "\\font_sc false"
1005             if expert:
1006                 preamble += ",expert"
1007             preamble += "]{mathdesign}"
1008             add_to_preamble(document, [preamble])
1009             document.header[i] = "\\font_roman default"
1010
1011
1012 def revert_texgyre(document):
1013     " Revert native TeXGyre font definition to LaTeX " 
1014
1015     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1016         texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1017                          "tgheros", "tgpagella", "tgschola", "tgtermes"]
1018         i = find_token(document.header, "\\font_roman", 0)
1019         if i != -1:
1020             val = get_value(document.header, "\\font_roman", i)
1021             if val in texgyre_fonts:
1022                 preamble = "\\usepackage{%s}" % val
1023                 add_to_preamble(document, [preamble])
1024                 document.header[i] = "\\font_roman default"
1025         i = find_token(document.header, "\\font_sans", 0)
1026         if i != -1:
1027             val = get_value(document.header, "\\font_sans", i)
1028             if val in texgyre_fonts:
1029                 preamble = "\\usepackage{%s}" % val
1030                 add_to_preamble(document, [preamble])
1031                 document.header[i] = "\\font_sans default"
1032         i = find_token(document.header, "\\font_typewriter", 0)
1033         if i != -1:
1034             val = get_value(document.header, "\\font_typewriter", i)
1035             if val in texgyre_fonts:
1036                 preamble = "\\usepackage{%s}" % val
1037                 add_to_preamble(document, [preamble])
1038                 document.header[i] = "\\font_typewriter default"
1039
1040
1041 def revert_ipadeco(document):
1042     " Revert IPA decorations to ERT "
1043     i = 0
1044     while True:
1045       i = find_token(document.body, "\\begin_inset IPADeco", i)
1046       if i == -1:
1047           return
1048       end = find_end_of_inset(document.body, i)
1049       if end == -1:
1050           document.warning("Can't find end of inset at line " + str(i))
1051           i += 1
1052           continue
1053       line = document.body[i]
1054       rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1055       m = rx.match(line)
1056       decotype = m.group(1)
1057       if decotype != "toptiebar" and decotype != "bottomtiebar":
1058           document.warning("Invalid IPADeco type: " + decotype)
1059           i = end
1060           continue
1061       blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1062       if blay == -1:
1063           document.warning("Can't find layout for inset at line " + str(i))
1064           i = end
1065           continue
1066       bend = find_end_of_layout(document.body, blay)
1067       if bend == -1:
1068           document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1069           i = end
1070           continue
1071       substi = ["\\begin_inset ERT", "status collapsed", "",
1072                 "\\begin_layout Plain Layout", "", "", "\\backslash", 
1073                 decotype + "{", "\\end_layout", "", "\\end_inset"]
1074       substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1075                 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1076       # do the later one first so as not to mess up the numbering
1077       document.body[bend:end + 1] = substj
1078       document.body[i:blay + 1] = substi
1079       i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1080       add_to_preamble(document, "\\usepackage{tipa}")
1081
1082
1083 def revert_ipachar(document):
1084     ' Revert \\IPAChar to ERT '
1085     i = 0
1086     found = False
1087     while i < len(document.body):
1088         m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1089         if m:
1090             found = True
1091             before = m.group(1)
1092             ipachar = m.group(2)
1093             after = m.group(3)
1094             subst = [before,
1095                      '\\begin_inset ERT',
1096                      'status collapsed', '',
1097                      '\\begin_layout Standard',
1098                      '', '', '\\backslash',
1099                      ipachar,
1100                      '\\end_layout', '',
1101                      '\\end_inset', '',
1102                      after]
1103             document.body[i: i+1] = subst
1104             i = i + len(subst)
1105         else:
1106             i = i + 1
1107     if found:
1108         add_to_preamble(document, "\\usepackage{tone}")
1109
1110
1111 def revert_minionpro(document):
1112     " Revert native MinionPro font definition to LaTeX " 
1113
1114     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1115         i = find_token(document.header, "\\font_roman minionpro", 0)
1116         if i != -1:
1117             osf = False
1118             j = find_token(document.header, "\\font_osf true", 0)
1119             if j != -1:
1120                 osf = True
1121             preamble = "\\usepackage"
1122             if osf:
1123                 document.header[j] = "\\font_osf false"
1124             else:
1125                 preamble += "[lf]"
1126             preamble += "{MinionPro}"
1127             add_to_preamble(document, [preamble])
1128             document.header[i] = "\\font_roman default"
1129
1130
1131 def revert_mathfonts(document):
1132     " Revert native math font definitions to LaTeX " 
1133
1134     i = find_token(document.header, "\\font_math", 0)
1135     if i == -1:
1136        return
1137     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1138         val = get_value(document.header, "\\font_math", i)
1139         if val == "eulervm":
1140             add_to_preamble(document, "\\usepackage{eulervm}")
1141         elif val == "default":
1142             mathfont_dict = {
1143             "lmodern":  "\\renewcommand{\\rmdefault}{lmr}",
1144             "minionpro":  "\\usepackage[onlytext,lf]{MinionPro}",
1145             "minionpro-osf":  "\\usepackage[onlytext]{MinionPro}",
1146             "palatino":  "\\renewcommand{\\rmdefault}{ppl}",
1147             "palatino-osf":  "\\renewcommand{\\rmdefault}{pplj}",
1148             "times":  "\\renewcommand{\\rmdefault}{ptm}",
1149             "utopia":  "\\renewcommand{\\rmdefault}{futs}",
1150             "utopia-osf":  "\\renewcommand{\\rmdefault}{futj}",
1151             }
1152             j = find_token(document.header, "\\font_roman", 0)
1153             if j != -1:
1154                 rm = get_value(document.header, "\\font_roman", j)
1155                 k = find_token(document.header, "\\font_osf true", 0)
1156                 if k != -1:
1157                     rm += "-osf"
1158                 if rm in mathfont_dict.keys():
1159                     add_to_preamble(document, mathfont_dict[rm])
1160                     document.header[j] = "\\font_roman default"
1161                     if k != -1:
1162                         document.header[k] = "\\font_osf false"
1163     del document.header[i]
1164
1165
1166 def revert_mdnomath(document):
1167     " Revert mathdesign and fourier without math " 
1168
1169     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1170         mathdesign_dict = {
1171         "md-charter": "mdbch",
1172         "md-utopia": "mdput",
1173         "md-garamond": "mdugm"
1174         }
1175         i = find_token(document.header, "\\font_roman", 0)
1176         if i == -1:
1177             return
1178         val = get_value(document.header, "\\font_roman", i)
1179         if val in mathdesign_dict.keys():
1180             j = find_token(document.header, "\\font_math", 0)
1181             if j == -1:
1182                 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1183             mval = get_value(document.header, "\\font_math", j)
1184             if mval == "default":
1185                 document.header[i] = "\\font_roman default"
1186                 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1187             else:
1188                 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1189
1190
1191 def convert_mdnomath(document):
1192     " Change mathdesign font name " 
1193
1194     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1195         mathdesign_dict = {
1196         "mdbch":  "md-charter",
1197         "mdput":  "md-utopia",
1198         "mdugm":  "md-garamond"
1199         }
1200         i = find_token(document.header, "\\font_roman", 0)
1201         if i == -1:
1202             return
1203         val = get_value(document.header, "\\font_roman", i)
1204         if val in mathdesign_dict.keys():
1205              document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1206
1207
1208 def revert_newtxmath(document):
1209     " Revert native newtxmath definitions to LaTeX " 
1210
1211     i = find_token(document.header, "\\font_math", 0)
1212     if i == -1:
1213        return
1214     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1215         val = get_value(document.header, "\\font_math", i)
1216         mathfont_dict = {
1217         "libertine-ntxm":  "\\usepackage[libertine]{newtxmath}",
1218         "minion-ntxm":  "\\usepackage[minion]{newtxmath}",
1219         "newtxmath":  "\\usepackage{newtxmath}",
1220         }
1221         if val in mathfont_dict.keys():
1222             add_to_preamble(document, mathfont_dict[val])
1223             document.header[i] = "\\font_math auto"
1224
1225
1226 def revert_biolinum(document):
1227     " Revert native biolinum font definition to LaTeX " 
1228
1229     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1230         i = find_token(document.header, "\\font_sans biolinum", 0)
1231         if i != -1:
1232             osf = False
1233             j = find_token(document.header, "\\font_osf true", 0)
1234             if j != -1:
1235                 osf = True
1236             preamble = "\\usepackage"
1237             if not osf:
1238                 preamble += "[lf]"
1239             preamble += "{biolinum-type1}"
1240             add_to_preamble(document, [preamble])
1241             document.header[i] = "\\font_sans default"
1242
1243
1244 def revert_uop(document):
1245     " Revert native URW Classico (Optima) font definition to LaTeX "
1246
1247     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1248         i = find_token(document.header, "\\font_sans uop", 0)
1249         if i != -1:
1250                 preamble = "\\renewcommand{\\sfdefault}{uop}"
1251                 add_to_preamble(document, [preamble])
1252                 document.header[i] = "\\font_sans default"
1253
1254
1255 def convert_latexargs(document):
1256     " Convert InsetArgument to new syntax "
1257
1258     if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1259         # nothing to do.
1260         return
1261
1262     # A list of layouts (document classes) with only optional or no arguments.
1263     # These can be safely converted to the new syntax
1264     # (I took the liberty to add some of my personal layouts/modules here; JSP)
1265     safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1266                     "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1267                     "arab-article", "armenian-article", "article-beamer", "article",
1268                     "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1269                     "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1270                     "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1271                     "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1272                     "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1273                     "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1274                     "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1275                     "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1276                     "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1277                     "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1278                     "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1279                     "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1280                     "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1281                     "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1282                     "tbook", "treport", "tufte-book", "tufte-handout"]
1283     # A list of "safe" modules, same as above
1284     safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1285                     "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1286                     "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1287                     "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1288                     "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1289                     "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1290                     "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1291                     "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1292     # Modules we need to take care of
1293     caveat_modules = ["initials"]
1294     # information about the relevant styles in caveat_modules (number of opt and req args)
1295     # use this if we get more caveat_modules. For now, use hard coding (see below).
1296     # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1297
1298     # Is this a known safe layout?
1299     safe_layout = document.textclass in safe_layouts
1300     if not safe_layout:
1301         document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1302                          "Please check if short title insets have been converted correctly."
1303                          % document.textclass)
1304     # Do we use unsafe or unknown modules
1305     mods = document.get_module_list()
1306     unknown_modules = False
1307     used_caveat_modules = list()
1308     for mod in mods:
1309         if mod in safe_modules:
1310             continue
1311         if mod in caveat_modules:
1312             used_caveat_modules.append(mod)
1313             continue
1314         unknown_modules = True
1315         document.warning("Lyx2lyx knows nothing about module '%s'. "
1316                          "Please check if short title insets have been converted correctly."
1317                          % mod)
1318
1319     i = 0
1320     while True:
1321         i = find_token(document.body, "\\begin_inset Argument", i)
1322         if i == -1:
1323             return
1324
1325         if not safe_layout or unknown_modules:
1326             # We cannot do more here since we have no access to this layout.
1327             # InsetArgument itself will do the real work
1328             # (see InsetArgument::updateBuffer())
1329             document.body[i] = "\\begin_inset Argument 999"
1330             i = i + 1
1331             continue
1332         
1333         # Find containing paragraph layout
1334         parent = get_containing_layout(document.body, i)
1335         if parent == False:
1336             document.warning("Malformed lyx document: Can't find parent paragraph layout")
1337             i = i + 1
1338             continue
1339         parbeg = parent[1]
1340         parend = parent[2]
1341         allowed_opts = -1
1342         first_req = -1
1343         if len(used_caveat_modules) > 0:
1344             # We know for now that this must be the initials module with the Initial layout
1345             # If we get more such modules, we need some automating.
1346             if parent[0] == "Initial":
1347                 # Layout has 1 opt and 1 req arg.
1348                 # Count the actual arguments
1349                 actualargs = 0
1350                 for p in range(parbeg, parend):
1351                     if document.body[p] == "\\begin_inset Argument":
1352                         actualargs += 1
1353                 if actualargs == 1:
1354                     allowed_opts = 0
1355                     first_req = 2
1356         # Collect all arguments in this paragraph
1357         argnr = 0
1358         for p in range(parbeg, parend):
1359             if document.body[p] == "\\begin_inset Argument":
1360                 argnr += 1
1361                 if allowed_opts != -1:
1362                     # We have less arguments than opt + required.
1363                     # required must take precedence.
1364                     if argnr > allowed_opts and argnr < first_req:
1365                         argnr = first_req
1366                 document.body[p] = "\\begin_inset Argument %d" % argnr
1367         i = i + 1
1368
1369
1370 def revert_latexargs(document):
1371     " Revert InsetArgument to old syntax "
1372
1373     i = 0
1374     rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1375     args = dict()
1376     while True:
1377         # Search for Argument insets
1378         i = find_token(document.body, "\\begin_inset Argument", i)
1379         if i == -1:
1380             return
1381         m = rx.match(document.body[i])
1382         if not m:
1383             # No ID: inset already reverted
1384             i = i + 1
1385             continue
1386         # Find containing paragraph layout
1387         parent = get_containing_layout(document.body, i)
1388         if parent == False:
1389             document.warning("Malformed lyx document: Can't find parent paragraph layout")
1390             i = i + 1
1391             continue
1392         parbeg = parent[1]
1393         parend = parent[2]
1394         realparbeg = parent[3]
1395         # Collect all arguments in this paragraph 
1396         realparend = parend
1397         for p in range(parbeg, parend):
1398             m = rx.match(document.body[p])
1399             if m:
1400                 val = int(m.group(1))
1401                 j = find_end_of_inset(document.body, p)
1402                 # Revert to old syntax
1403                 document.body[p] = "\\begin_inset Argument"
1404                 if j == -1:
1405                     document.warning("Malformed lyx document: Can't find end of Argument inset")
1406                     continue
1407                 if val > 0:
1408                     args[val] = document.body[p : j + 1]
1409                 # Adjust range end
1410                 realparend = realparend - len(document.body[p : j + 1])
1411                 # Remove arg inset at this position
1412                 del document.body[p : j + 1]
1413             if p >= realparend:
1414                 break
1415         # Now sort the arg insets
1416         subst = [""]
1417         for f in sorted(args):
1418             subst += args[f]
1419             del args[f]
1420         # Insert the sorted arg insets at paragraph begin
1421         document.body[realparbeg : realparbeg] = subst
1422
1423         i = realparbeg + 1 + len(subst)
1424
1425
1426 def revert_Argument_to_TeX_brace(document, line, n, nmax, environment):
1427     '''
1428     Reverts an InsetArgument to TeX-code
1429     usage:
1430     revert_Argument_to_TeX_brace(document, LineOfBeginLayout, StartArgument, EndArgument, isEnvironment)
1431     LineOfBeginLayout is the line  of the \begin_layout statement
1432     StartArgument is the number of the first argument that needs to be converted
1433     EndArgument is the number of the last argument that needs to be converted or the last defined one
1434     isEnvironment must be true, if the layout id for a LaTeX environment
1435     '''
1436     lineArg = 0
1437     while lineArg != -1 and n < nmax + 1:
1438       lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
1439       if lineArg != -1:
1440         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
1441         # we have to assure that no other inset is in the Argument
1442         beginInset = find_token(document.body, "\\begin_inset", beginPlain)
1443         endInset = find_token(document.body, "\\end_inset", beginPlain)
1444         k = beginPlain + 1
1445         l = k
1446         while beginInset < endInset and beginInset != -1:
1447           beginInset = find_token(document.body, "\\begin_inset", k)
1448           endInset = find_token(document.body, "\\end_inset", l)
1449           k = beginInset + 1
1450           l = endInset + 1
1451         if environment == False:
1452           document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
1453           del(document.body[lineArg : beginPlain + 1])
1454         else:
1455           document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
1456           document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
1457         n = n + 1
1458
1459
1460 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment):
1461     '''
1462     Converts TeX code for mandatory arguments to an InsetArgument
1463     The conversion of TeX code for optional arguments must be done with another routine
1464     !!! Be careful if the braces are different in your case as expected here:
1465     - "}{" separates mandatory arguments of commands
1466     - "}" + "{" separates mandatory arguments of commands
1467     - "}" + " " + "{" separates mandatory arguments of commands
1468     - { and } surround a mandatory argument of an environment
1469     usage:
1470     convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment)
1471     LineOfBeginLayout/Inset is the line  of the \begin_layout or \begin_inset statement
1472     StartArgument is the number of the first ERT that needs to be converted
1473     EndArgument is the number of the last ERT that needs to be converted
1474     isInset must be true, if braces inside an InsetLayout needs to be converted
1475     isEnvironment must be true, if the layout is for a LaTeX environment
1476     
1477     Todo: this routine can currently handle only one mandatory argument of environments
1478     '''
1479     lineERT = line
1480     endn = line
1481     loop = 1
1482     while lineERT != -1 and n < nmax + 1:
1483       lineERT = find_token(document.body, "\\begin_inset ERT", lineERT)
1484       if environment == False and lineERT != -1:
1485         bracePair = find_token(document.body, "}{", lineERT)
1486         # assure that the "}{" is in this ERT
1487         if bracePair == lineERT + 5:
1488           end = find_token(document.body, "\\end_inset", bracePair)
1489           document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1490           if loop == 1:
1491             # in the case that n > 1 we have optional arguments before
1492             # therefore detect them if any
1493             if n > 1:
1494               # first check if there is an argument
1495               lineArg = find_token(document.body, "\\begin_inset Argument", line)
1496               if lineArg < lineERT and lineArg != -1:
1497                 # we have an argument, so now search backwards for its end
1498                 # we must now assure that we don't find other insets like e.g. a newline
1499                 endInsetArg = lineERT
1500                 endLayoutArg = endInsetArg
1501                 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1502                   endInsetArg = endInsetArg - 1
1503                   endLayoutArg = endInsetArg
1504                   endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1505                   endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1506                 line = endInsetArg + 1
1507             if inset == False:
1508               document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1509             else:
1510               document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1511           else:
1512             document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1513           n = n + 1
1514           endn = end
1515           loop = loop + 1
1516         # now check the case that we have "}" + "{" in two ERTs
1517         else:
1518           endBrace = find_token(document.body, "}", lineERT)
1519           if endBrace == lineERT + 5:
1520             beginBrace = find_token(document.body, "{", endBrace)
1521             # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
1522             if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
1523               end = find_token(document.body, "\\end_inset", beginBrace)
1524               document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1525               if loop == 1:
1526                 # in the case that n > 1 we have optional arguments before
1527                 # therefore detect them if any
1528                 if n > 1:
1529                   # first check if there is an argument
1530                   lineArg = find_token(document.body, "\\begin_inset Argument", line)
1531                   if lineArg < lineERT and lineArg != -1:
1532                     # we have an argument, so now search backwards for its end
1533                     # we must now assure that we don't find other insets like e.g. a newline
1534                     endInsetArg = lineERT
1535                     endLayoutArg = endInsetArg
1536                     while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1537                       endInsetArg = endInsetArg - 1
1538                       endLayoutArg = endInsetArg
1539                       endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1540                       endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1541                     line = endInsetArg + 1
1542                 if inset == False:
1543                   document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1544                 else:
1545                   document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1546               else:
1547                 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1548               n = n + 1
1549               loop = loop + 1
1550               # set the line where the next argument will be inserted
1551               if beginBrace == endBrace + 11:
1552                 endn = end - 11
1553               else:
1554                 endn = end - 12
1555           else:
1556             lineERT = lineERT + 1
1557       if environment == True and lineERT != -1:
1558         opening = find_token(document.body, "{", lineERT)
1559         if opening == lineERT + 5: # assure that the "{" is in this ERT
1560           end = find_token(document.body, "\\end_inset", opening)
1561           document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1562           n = n + 1
1563           lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT)
1564           closing = find_token(document.body, "}", lineERT2)
1565           if closing == lineERT2 + 5: # assure that the "}" is in this ERT
1566             end2 = find_token(document.body, "\\end_inset", closing)
1567             document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
1568         else:
1569           lineERT = lineERT + 1
1570
1571
1572 def revert_IEEEtran(document):
1573   '''
1574   Reverts InsetArgument of
1575   Page headings
1576   Biography
1577   Biography without photo
1578   to TeX-code
1579   '''
1580   if document.textclass == "IEEEtran":
1581     i = 0
1582     i2 = 0
1583     j = 0
1584     k = 0
1585     while True:
1586       if i != -1:
1587         i = find_token(document.body, "\\begin_layout Page headings", i)
1588       if i != -1:
1589         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1590         i = i + 1
1591       if i2 != -1:
1592         i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1593       if i2 != -1:
1594         revert_Argument_to_TeX_brace(document, i2, 1, 1, False)
1595         i2 = i2 + 1
1596       if j != -1:
1597         j = find_token(document.body, "\\begin_layout Biography without photo", j)
1598       if j != -1:
1599         revert_Argument_to_TeX_brace(document, j, 1, 1, True)
1600         j = j + 1
1601       if k != -1:
1602         k = find_token(document.body, "\\begin_layout Biography", k)
1603         kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1604         if k == kA and k != -1:
1605           k = k + 1
1606           continue
1607       if k != -1:
1608         # start with the second argument, therefore 2
1609         revert_Argument_to_TeX_brace(document, k, 2, 2, True)
1610         k = k + 1
1611       if i == -1 and i2 == -1 and j == -1 and k == -1:
1612         return
1613
1614
1615 def revert_IEEEtran_2(document):
1616   '''
1617   Reverts Flex Paragraph Start to TeX-code
1618   '''
1619   if document.textclass == "IEEEtran":
1620     begin = 0
1621     while True:
1622       if begin != -1:
1623         begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1624       if begin != -1:
1625         end1 = find_end_of_inset(document.body, begin)
1626         document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1627         document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1628         begin = begin + 5
1629       if begin == -1:
1630         return
1631
1632
1633 def convert_IEEEtran(document):
1634   '''
1635   Converts ERT of
1636   Page headings
1637   Biography
1638   Biography without photo
1639   to InsetArgument
1640   '''
1641   if document.textclass == "IEEEtran":
1642     i = 0
1643     j = 0
1644     k = 0
1645     while True:
1646       if i != -1:
1647         i = find_token(document.body, "\\begin_layout Page headings", i)
1648       if i != -1:
1649         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1650         i = i + 1
1651       if j != -1:
1652         j = find_token(document.body, "\\begin_layout Biography without photo", j)
1653       if j != -1:
1654         convert_TeX_brace_to_Argument(document, j, 1, 1, False, True)
1655         j = j + 1
1656       if k != -1:
1657         # assure that we don't handle Biography Biography without photo
1658         k = find_token(document.body, "\\begin_layout Biography", k)
1659         kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1660       if k == kA and k != -1:
1661         k = k + 1
1662         continue
1663       if k != -1:
1664         # the argument we want to convert is the second one
1665         convert_TeX_brace_to_Argument(document, k, 2, 2, False, True)
1666         k = k + 1
1667       if i == -1 and j == -1 and k == -1:
1668         return
1669
1670
1671 def revert_AASTeX(document):
1672   " Reverts InsetArgument of Altaffilation to TeX-code "
1673   if document.textclass == "aastex":
1674     i = 0
1675     while True:
1676       if i != -1:
1677         i = find_token(document.body, "\\begin_layout Altaffilation", i)
1678       if i != -1:
1679         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1680         i = i + 1
1681       if i == -1:
1682         return
1683
1684
1685 def convert_AASTeX(document):
1686   " Converts ERT of Altaffilation to InsetArgument "
1687   if document.textclass == "aastex":
1688     i = 0
1689     while True:
1690       if i != -1:
1691         i = find_token(document.body, "\\begin_layout Altaffilation", i)
1692       if i != -1:
1693         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1694         i = i + 1
1695       if i == -1:
1696         return
1697
1698
1699 def revert_AGUTeX(document):
1700   " Reverts InsetArgument of Author affiliation to TeX-code "
1701   if document.textclass == "agutex":
1702     i = 0
1703     while True:
1704       if i != -1:
1705         i = find_token(document.body, "\\begin_layout Author affiliation", i)
1706       if i != -1:
1707         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1708         i = i + 1
1709       if i == -1:
1710         return
1711
1712
1713 def convert_AGUTeX(document):
1714   " Converts ERT of Author affiliation to InsetArgument "
1715   if document.textclass == "agutex":
1716     i = 0
1717     while True:
1718       if i != -1:
1719         i = find_token(document.body, "\\begin_layout Author affiliation", i)
1720       if i != -1:
1721         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1722         i = i + 1
1723       if i == -1:
1724         return
1725
1726
1727 def revert_IJMP(document):
1728   " Reverts InsetArgument of MarkBoth to TeX-code "
1729   if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1730     i = 0
1731     while True:
1732       if i != -1:
1733         i = find_token(document.body, "\\begin_layout MarkBoth", i)
1734       if i != -1:
1735         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1736         i = i + 1
1737       if i == -1:
1738         return
1739
1740
1741 def convert_IJMP(document):
1742   " Converts ERT of MarkBoth to InsetArgument "
1743   if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1744     i = 0
1745     while True:
1746       if i != -1:
1747         i = find_token(document.body, "\\begin_layout MarkBoth", i)
1748       if i != -1:
1749         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1750         i = i + 1
1751       if i == -1:
1752         return
1753
1754
1755 def revert_SIGPLAN(document):
1756   " Reverts InsetArguments of SIGPLAN to TeX-code "
1757   if document.textclass == "sigplanconf":
1758     i = 0
1759     j = 0
1760     while True:
1761       if i != -1:
1762         i = find_token(document.body, "\\begin_layout Conference", i)
1763       if i != -1:
1764         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1765         i = i + 1
1766       if j != -1:
1767         j = find_token(document.body, "\\begin_layout Author", j)
1768       if j != -1:
1769         revert_Argument_to_TeX_brace(document, j, 1, 2, False)
1770         j = j + 1
1771       if i == -1 and j == -1:
1772         return
1773
1774
1775 def convert_SIGPLAN(document):
1776   " Converts ERT of SIGPLAN to InsetArgument "
1777   if document.textclass == "sigplanconf":
1778     i = 0
1779     j = 0
1780     while True:
1781       if i != -1:
1782         i = find_token(document.body, "\\begin_layout Conference", i)
1783       if i != -1:
1784         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1785         i = i + 1
1786       if j != -1:
1787         j = find_token(document.body, "\\begin_layout Author", j)
1788       if j != -1:
1789         convert_TeX_brace_to_Argument(document, j, 1, 2, False, False)
1790         j = j + 1
1791       if i == -1 and j == -1:
1792         return
1793
1794
1795 def revert_SIGGRAPH(document):
1796   " Reverts InsetArgument of Flex CRcat to TeX-code "
1797   if document.textclass == "acmsiggraph":
1798     i = 0
1799     while True:
1800       if i != -1:
1801         i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1802       if i != -1:
1803         revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1804         i = i + 1
1805       if i == -1:
1806         return
1807
1808
1809 def convert_SIGGRAPH(document):
1810   " Converts ERT of Flex CRcat to InsetArgument "
1811   if document.textclass == "acmsiggraph":
1812     i = 0
1813     while True:
1814       if i != -1:
1815         i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1816       if i != -1:
1817         convert_TeX_brace_to_Argument(document, i, 1, 3, True, False)
1818         i = i + 1
1819       if i == -1:
1820         return
1821
1822
1823 def revert_EuropeCV(document):
1824   " Reverts InsetArguments of europeCV to TeX-code "
1825   if document.textclass == "europecv":
1826     i = 0
1827     j = 0
1828     k = 0
1829     m = 0
1830     while True:
1831       if i != -1:
1832         i = find_token(document.body, "\\begin_layout Item", i)
1833       if i != -1:
1834         revert_Argument_to_TeX_brace(document, i, 2, 2, False)
1835         i = i + 1
1836       if j != -1:
1837         j = find_token(document.body, "\\begin_layout BulletedItem", j)
1838       if j != -1:
1839         revert_Argument_to_TeX_brace(document, j, 2, 2, False)
1840         j = j + 1
1841       if k != -1:
1842         k = find_token(document.body, "\\begin_layout Language", k)
1843       if k != -1:
1844         revert_Argument_to_TeX_brace(document, k, 2, 6, False)
1845         k = k + 1
1846       if m != -1:
1847         m = find_token(document.body, "\\begin_layout LastLanguage", m)
1848       if m != -1:
1849         revert_Argument_to_TeX_brace(document, m, 2, 6, False)
1850         m = m + 1
1851       if i == -1 and j == -1 and k == -1 and m == -1:
1852         return
1853
1854
1855 def convert_EuropeCV(document):
1856   " Converts ERT of europeCV to InsetArgument "
1857   if document.textclass == "europecv":
1858     i = 0
1859     j = 0
1860     k = 0
1861     m = 0
1862     while True:
1863       if i != -1:
1864         i = find_token(document.body, "\\begin_layout Item", i)
1865       if i != -1:
1866         convert_TeX_brace_to_Argument(document, i, 2, 2, False, False)
1867         i = i + 1
1868       if j != -1:
1869         j = find_token(document.body, "\\begin_layout BulletedItem", j)
1870       if j != -1:
1871         convert_TeX_brace_to_Argument(document, j, 2, 2, False, False)
1872         j = j + 1
1873       if k != -1:
1874         k = find_token(document.body, "\\begin_layout Language", k)
1875       if k != -1:
1876         convert_TeX_brace_to_Argument(document, k, 2, 6, False, False)
1877         k = k + 1
1878       if m != -1:
1879         m = find_token(document.body, "\\begin_layout LastLanguage", m)
1880       if m != -1:
1881         convert_TeX_brace_to_Argument(document, m, 2, 6, False, False)
1882         m = m + 1
1883       if i == -1 and j == -1 and k == -1 and m == -1:
1884         return
1885
1886
1887 def revert_ModernCV(document):
1888   " Reverts InsetArguments of modernCV to TeX-code "
1889   if document.textclass == "moderncv":
1890     i = 0
1891     j = 0
1892     k = 0
1893     m = 0
1894     o = 0
1895     while True:
1896       if i != -1:
1897         i = find_token(document.body, "\\begin_layout DoubleItem", i)
1898       if i != -1:
1899         revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1900         i = i + 1
1901       if j != -1:
1902         j = find_token(document.body, "\\begin_layout Entry", j)
1903       if j != -1:
1904         revert_Argument_to_TeX_brace(document, j, 1, 5, False)
1905         j = j + 1
1906       if k != -1:
1907         k = find_token(document.body, "\\begin_layout Item", k)
1908       if k != -1:
1909         revert_Argument_to_TeX_brace(document, k, 1, 1, False)
1910         k = k + 1
1911       if m != -1:
1912         m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1913       if m != -1:
1914         revert_Argument_to_TeX_brace(document, m, 1, 2, False)
1915         document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1916         m = m + 1
1917       if o != -1:
1918         o = find_token(document.body, "\\begin_layout DoubleItem", o)
1919       if o != -1:
1920         revert_Argument_to_TeX_brace(document, o, 1, 3, False)
1921         document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
1922         o = o + 1
1923       if i == -1 and j == -1 and k == -1 and m == -1 and o == -1:
1924         return
1925
1926
1927 def convert_ModernCV(document):
1928   " Converts ERT of modernCV to InsetArgument "
1929   if document.textclass == "moderncv":
1930     i = 0
1931     j = 0
1932     k = 0
1933     m = 0
1934     o = 0
1935     while True:
1936       if i != -1:
1937         i = find_token(document.body, "\\begin_layout DoubleItem", i)
1938       if i != -1:
1939         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1940         document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
1941         i = i + 1
1942       if j != -1:
1943         j = find_token(document.body, "\\begin_layout Entry", j)
1944       if j != -1:
1945         convert_TeX_brace_to_Argument(document, j, 1, 5, False, False)
1946         j = j + 1
1947       if k != -1:
1948         k = find_token(document.body, "\\begin_layout Item", k)
1949       if k != -1:
1950         convert_TeX_brace_to_Argument(document, k, 1, 1, False, False)
1951         k = k + 1
1952       if m != -1:
1953         m = find_token(document.body, "\\begin_layout Language", m)
1954       if m != -1:
1955         convert_TeX_brace_to_Argument(document, m, 1, 2, False, False)
1956         m = m + 1
1957       if i == -1 and j == -1 and k == -1 and m == -1:
1958         return
1959
1960
1961 def revert_Initials(document):
1962   " Reverts InsetArgument of Initial to TeX-code "
1963   i = 0
1964   while True:
1965     if i != -1:
1966       i = find_token(document.body, "\\begin_layout Initial", i)
1967     if i != -1:
1968       # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
1969       revert_Argument_to_TeX_brace(document, i, 3, 3, False)
1970       i = i + 1
1971     if i == -1:
1972       return
1973
1974
1975 def convert_Initials(document):
1976   " Converts ERT of Initial to InsetArgument "
1977   i = 0
1978   while True:
1979     if i != -1:
1980       i = find_token(document.body, "\\begin_layout Initial", i)
1981     if i != -1:
1982       convert_TeX_brace_to_Argument(document, i, 3, 3, False, False)
1983       i = i + 1
1984     if i == -1:
1985       return
1986
1987
1988 def revert_literate(document):
1989     " Revert Literate document to old format "
1990     if del_token(document.header, "noweb", 0):
1991       document.textclass = "literate-" + document.textclass
1992       i = 0
1993       while True:
1994         i = find_token(document.body, "\\begin_layout Chunk", i)
1995         if i == -1:
1996           break
1997         document.body[i] = "\\begin_layout Scrap"
1998         i = i + 1
1999
2000
2001 def convert_literate(document):
2002     " Convert Literate document to new format"
2003     i = find_token(document.header, "\\textclass", 0)    
2004     if (i != -1) and "literate-" in document.header[i]:
2005       document.textclass = document.header[i].replace("\\textclass literate-", "")
2006       j = find_token(document.header, "\\begin_modules", 0)
2007       if (j != -1):
2008         document.header.insert(j + 1, "noweb")
2009       else:
2010         document.header.insert(i + 1, "\\end_modules")
2011         document.header.insert(i + 1, "noweb")
2012         document.header.insert(i + 1, "\\begin_modules")
2013       i = 0
2014       while True:
2015         i = find_token(document.body, "\\begin_layout Scrap", i)
2016         if i == -1:
2017           break
2018         document.body[i] = "\\begin_layout Chunk"
2019         i = i + 1
2020
2021
2022 def revert_itemargs(document):
2023     " Reverts \\item arguments to TeX-code "
2024     i = 0
2025     while True:
2026         i = find_token(document.body, "\\begin_inset Argument item:", i)
2027         if i == -1:
2028             return
2029         j = find_end_of_inset(document.body, i)
2030         # Find containing paragraph layout
2031         parent = get_containing_layout(document.body, i)
2032         if parent == False:
2033             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2034             i = i + 1
2035             continue
2036         parbeg = parent[3]
2037         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2038         endPlain = find_end_of_layout(document.body, beginPlain)
2039         content = document.body[beginPlain + 1 : endPlain]
2040         del document.body[i:j+1]
2041         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2042         document.body[parbeg : parbeg] = subst
2043         i = i + 1
2044
2045
2046 def revert_garamondx_newtxmath(document):
2047     " Revert native garamond newtxmath definition to LaTeX " 
2048
2049     i = find_token(document.header, "\\font_math", 0)
2050     if i == -1:
2051        return
2052     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
2053         val = get_value(document.header, "\\font_math", i)
2054         if val == "garamondx-ntxm":
2055             add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2056             document.header[i] = "\\font_math auto"
2057
2058
2059 def revert_garamondx(document):
2060     " Revert native garamond font definition to LaTeX " 
2061
2062     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
2063         i = find_token(document.header, "\\font_roman garamondx", 0)
2064         if i != -1:
2065             osf = False
2066             j = find_token(document.header, "\\font_osf true", 0)
2067             if j != -1:
2068                 osf = True
2069             preamble = "\\usepackage"
2070             if osf:
2071                 preamble += "[osfI]"
2072             preamble += "{garamondx}"
2073             add_to_preamble(document, [preamble])
2074             document.header[i] = "\\font_roman default"
2075
2076
2077 def convert_beamerargs(document):
2078     " Converts beamer arguments to new layout "
2079     
2080     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2081     if document.textclass not in beamer_classes:
2082         return
2083
2084     shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2085     list_layouts = ["Itemize", "Enumerate", "Description"]
2086     rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2087
2088     i = 0
2089     while True:
2090         i = find_token(document.body, "\\begin_inset Argument", i)
2091         if i == -1:
2092             return
2093         # Find containing paragraph layout
2094         parent = get_containing_layout(document.body, i)
2095         if parent == False:
2096             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2097             i = i + 1
2098             continue
2099         parbeg = parent[1]
2100         parend = parent[2]
2101         layoutname = parent[0]
2102         for p in range(parbeg, parend):
2103             if layoutname in shifted_layouts:
2104                 m = rx.match(document.body[p])
2105                 if m:
2106                     argnr = int(m.group(1))
2107                     argnr += 1
2108                     document.body[p] = "\\begin_inset Argument %d" % argnr
2109             if layoutname == "AgainFrame":
2110                 m = rx.match(document.body[p])
2111                 if m:
2112                     document.body[p] = "\\begin_inset Argument 3"
2113                     if document.body[p + 4] == "\\begin_inset ERT":
2114                         if document.body[p + 9].startswith("<"):
2115                             # This is an overlay specification
2116                             # strip off the <
2117                             document.body[p + 9] = document.body[p + 9][1:]
2118                             if document.body[p + 9].endswith(">"):
2119                                 # strip off the >
2120                                 document.body[p + 9] = document.body[p + 9][:-1]
2121                                 # Shift this one
2122                                 document.body[p] = "\\begin_inset Argument 2"
2123             if layoutname in list_layouts:
2124                 m = rx.match(document.body[p])
2125                 if m:
2126                     if m.group(1) == "1":
2127                         if document.body[p + 4] == "\\begin_inset ERT":
2128                             if document.body[p + 9].startswith("<"):
2129                                 # This is an overlay specification
2130                                 # strip off the <
2131                                 document.body[p + 9] = document.body[p + 9][1:]
2132                                 if document.body[p + 9].endswith(">"):
2133                                     # strip off the >
2134                                     document.body[p + 9] = document.body[p + 9][:-1]
2135                         elif layoutname != "Itemize":
2136                             # Shift this one
2137                             document.body[p] = "\\begin_inset Argument 2"
2138         i = i + 1
2139
2140
2141 def convert_againframe_args(document):
2142     " Converts beamer AgainFrame to new layout "
2143
2144     # FIXME: This currently only works if the arguments are in one single ERT
2145     
2146     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2147     if document.textclass not in beamer_classes:
2148         return
2149    
2150     i = 0
2151     while True:
2152         i = find_token(document.body, "\\begin_layout AgainFrame", i)
2153         if i == -1:
2154             break
2155         parent = get_containing_layout(document.body, i)
2156         if parent[1] != i:
2157             document.warning("Wrong parent layout!")
2158         j = parent[2]
2159         parbeg = parent[3]
2160         if i != -1:
2161             if document.body[parbeg] == "\\begin_inset ERT":
2162                 ertcont = parbeg + 5
2163                 if document.body[ertcont].startswith("[<"):
2164                     # This is a default overlay specification
2165                     # strip off the [<
2166                     document.body[ertcont] = document.body[ertcont][2:]
2167                     if document.body[ertcont].endswith(">]"):
2168                         # strip off the >]
2169                         document.body[ertcont] = document.body[ertcont][:-2]
2170                     elif document.body[ertcont].endswith("]"):
2171                         # divide the args
2172                         tok = document.body[ertcont].find('>][')
2173                         if tok != -1:
2174                             subst = [document.body[ertcont][:tok],
2175                                      '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2176                                      'status collapsed', '', '\\begin_layout Plain Layout',
2177                                      document.body[ertcont][tok + 3:-1]]
2178                             document.body[ertcont : ertcont + 1] = subst
2179                      # Convert to ArgInset
2180                     document.body[parbeg] = "\\begin_inset Argument 2"
2181                     i = j
2182                     continue
2183                 elif document.body[ertcont].startswith("<"):
2184                     # This is an overlay specification
2185                     # strip off the <
2186                     document.body[ertcont] = document.body[ertcont][1:]
2187                     if document.body[ertcont].endswith(">"):
2188                         # strip off the >
2189                         document.body[ertcont] = document.body[ertcont][:-1]
2190                         # Convert to ArgInset
2191                         document.body[parbeg] = "\\begin_inset Argument 1"
2192                     elif document.body[ertcont].endswith(">]"):
2193                         # divide the args
2194                         tok = document.body[ertcont].find('>[<')
2195                         if tok != -1:
2196                            document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2197                                                            '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2198                                                            'status collapsed', '', '\\begin_layout Plain Layout',
2199                                                            document.body[ertcont][tok + 3:-2]]
2200                         # Convert to ArgInset
2201                         document.body[parbeg] = "\\begin_inset Argument 1"
2202                     elif document.body[ertcont].endswith("]"):
2203                         # divide the args
2204                         tok = document.body[ertcont].find('>[<')
2205                         if tok != -1:
2206                            # divide the args
2207                            tokk = document.body[ertcont].find('>][')
2208                            if tokk != -1:
2209                                document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2210                                                                '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2211                                                                'status collapsed', '', '\\begin_layout Plain Layout',
2212                                                                document.body[ertcont][tok + 3:tokk],
2213                                                                '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2214                                                                'status collapsed', '', '\\begin_layout Plain Layout',
2215                                                                document.body[ertcont][tokk + 3:-1]]
2216                         else:
2217                             tokk = document.body[ertcont].find('>[')
2218                             if tokk != -1:
2219                                 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2220                                                                 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2221                                                                 'status collapsed', '', '\\begin_layout Plain Layout',
2222                                                                 document.body[ertcont][tokk + 2:-1]]
2223                         # Convert to ArgInset
2224                         document.body[parbeg] = "\\begin_inset Argument 1"
2225                     i = j
2226                     continue
2227                 elif document.body[ertcont].startswith("["):
2228                     # This is an ERT option
2229                     # strip off the [
2230                     document.body[ertcont] = document.body[ertcont][1:]
2231                     if document.body[ertcont].endswith("]"):
2232                         # strip off the ]
2233                         document.body[ertcont] = document.body[ertcont][:-1]
2234                         # Convert to ArgInset
2235                         document.body[parbeg] = "\\begin_inset Argument 3"
2236                     i = j
2237                     continue
2238         i = j
2239
2240
2241 def convert_corollary_args(document):
2242     " Converts beamer corrolary-style ERT arguments native InsetArgs "
2243     
2244     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2245     if document.textclass not in beamer_classes:
2246         return
2247    
2248     corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2249     for lay in corollary_layouts:
2250         i = 0
2251         while True:
2252             i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2253             if i == -1:
2254                 break
2255             parent = get_containing_layout(document.body, i)
2256             if parent[1] != i:
2257                 document.warning("Wrong parent layout!")
2258             j = parent[2]
2259             parbeg = parent[3]
2260             if i != -1:
2261                 if document.body[parbeg] == "\\begin_inset ERT":
2262                     ertcont = parbeg + 5
2263                     if document.body[ertcont].startswith("<"):
2264                         # This is an overlay specification
2265                         # strip off the <
2266                         document.body[ertcont] = document.body[ertcont][1:]
2267                         if document.body[ertcont].endswith(">"):
2268                             # strip off the >
2269                             document.body[ertcont] = document.body[ertcont][:-1]
2270                         elif document.body[ertcont].endswith("]"):
2271                             # divide the args
2272                             tok = document.body[ertcont].find('>[')
2273                             if tok != -1:
2274                                 subst = [document.body[ertcont][:tok],
2275                                          '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2276                                          'status collapsed', '', '\\begin_layout Plain Layout',
2277                                          document.body[ertcont][tok + 2:-1]]
2278                                 document.body[ertcont : ertcont + 1] = subst
2279                         # Convert to ArgInset
2280                         document.body[parbeg] = "\\begin_inset Argument 1"
2281                         i = j
2282                         continue
2283                     elif document.body[ertcont].startswith("["):
2284                         # This is an ERT option
2285                         # strip off the [
2286                         document.body[ertcont] = document.body[ertcont][1:]
2287                         if document.body[ertcont].endswith("]"):
2288                             # strip off the ]
2289                             document.body[ertcont] = document.body[ertcont][:-1]
2290                         # Convert to ArgInset
2291                         document.body[parbeg] = "\\begin_inset Argument 2"
2292                     i = j
2293                     continue
2294             i = j
2295
2296
2297
2298 def convert_quote_args(document):
2299     " Converts beamer quote style ERT args to native InsetArgs "
2300     
2301     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2302     if document.textclass not in beamer_classes:
2303         return
2304    
2305     quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2306     for lay in quote_layouts:
2307         i = 0
2308         while True:
2309             i = find_token(document.body, "\\begin_layout " + lay, i)
2310             if i == -1:
2311                 break
2312             parent = get_containing_layout(document.body, i)
2313             if parent[1] != i:
2314                 document.warning("Wrong parent layout!")
2315             j = parent[2]
2316             parbeg = parent[3]
2317             if i != -1:
2318                 if document.body[parbeg] == "\\begin_inset ERT":
2319                     if document.body[i + 6].startswith("<"):
2320                         # This is an overlay specification
2321                         # strip off the <
2322                         document.body[i + 6] = document.body[i + 6][1:]
2323                         if document.body[i + 6].endswith(">"):
2324                             # strip off the >
2325                             document.body[i + 6] = document.body[i + 6][:-1]
2326                             # Convert to ArgInset
2327                             document.body[i + 1] = "\\begin_inset Argument 1"
2328             i = j
2329
2330
2331 def revert_beamerargs(document):
2332     " Reverts beamer arguments to old layout "
2333     
2334     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2335     if document.textclass not in beamer_classes:
2336         return
2337
2338     i = 0
2339     list_layouts = ["Itemize", "Enumerate", "Description"]
2340     headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2341                 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2342     quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2343     corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2344     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2345
2346     while True:
2347         i = find_token(document.body, "\\begin_inset Argument", i)
2348         if i == -1:
2349             return
2350         # Find containing paragraph layout
2351         parent = get_containing_layout(document.body, i)
2352         if parent == False:
2353             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2354             i = i + 1
2355             continue
2356         parbeg = parent[1]
2357         parend = parent[2]
2358         realparbeg = parent[3]
2359         layoutname = parent[0]
2360         realparend = parend
2361         for p in range(parbeg, parend):
2362             if p >= realparend:
2363                 i = realparend
2364                 break
2365             if layoutname in headings:
2366                 m = rx.match(document.body[p])
2367                 if m:
2368                     argnr = m.group(1)
2369                     if argnr == "1":
2370                         # Find containing paragraph layout
2371                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2372                         endPlain = find_end_of_layout(document.body, beginPlain)
2373                         endInset = find_end_of_inset(document.body, p)
2374                         argcontent = document.body[beginPlain + 1 : endPlain]
2375                         # Adjust range end
2376                         realparend = realparend - len(document.body[p : endInset + 1])
2377                         # Remove arg inset
2378                         del document.body[p : endInset + 1]
2379                         if layoutname == "FrameSubtitle":
2380                             pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2381                         elif layoutname == "NoteItem":
2382                             pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2383                         elif layoutname.endswith('*'):
2384                             pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2385                         else:
2386                             pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2387                         secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2388                         if secarg != -1:
2389                             # Find containing paragraph layout
2390                             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2391                             endPlain = find_end_of_layout(document.body, beginPlain)
2392                             endInset = find_end_of_inset(document.body, secarg)
2393                             argcontent = document.body[beginPlain + 1 : endPlain]
2394                             # Adjust range end
2395                             realparend = realparend - len(document.body[secarg : endInset + 1])
2396                             del document.body[secarg : endInset + 1]
2397                             pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2398                         pre += put_cmd_in_ert("{")
2399                         document.body[parbeg] = "\\begin_layout Standard"
2400                         document.body[realparbeg : realparbeg] = pre
2401                         pe = find_end_of_layout(document.body, parbeg)
2402                         post = put_cmd_in_ert("}")
2403                         document.body[pe : pe] = post
2404                         realparend += len(pre) + len(post)
2405             if layoutname == "AgainFrame":
2406                 m = rx.match(document.body[p])
2407                 if m:
2408                     argnr = m.group(1)
2409                     if argnr == "3":
2410                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2411                         endPlain = find_end_of_layout(document.body, beginPlain)
2412                         endInset = find_end_of_inset(document.body, p)
2413                         content = document.body[beginPlain + 1 : endPlain]
2414                         # Adjust range end
2415                         realparend = realparend - len(document.body[p : endInset + 1])
2416                         # Remove arg inset
2417                         del document.body[p : endInset + 1]
2418                         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2419                         document.body[realparbeg : realparbeg] = subst
2420             if layoutname == "Overprint":
2421                 m = rx.match(document.body[p])
2422                 if m:
2423                     argnr = m.group(1)
2424                     if argnr == "1":
2425                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2426                         endPlain = find_end_of_layout(document.body, beginPlain)
2427                         endInset = find_end_of_inset(document.body, p)
2428                         content = document.body[beginPlain + 1 : endPlain]
2429                         # Adjust range end
2430                         realparend = realparend - len(document.body[p : endInset + 1])
2431                         # Remove arg inset
2432                         del document.body[p : endInset + 1]
2433                         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2434                         document.body[realparbeg : realparbeg] = subst
2435             if layoutname == "OverlayArea":
2436                 m = rx.match(document.body[p])
2437                 if m:
2438                     argnr = m.group(1)
2439                     if argnr == "2":
2440                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2441                         endPlain = find_end_of_layout(document.body, beginPlain)
2442                         endInset = find_end_of_inset(document.body, p)
2443                         content = document.body[beginPlain + 1 : endPlain]
2444                         # Adjust range end
2445                         realparend = realparend - len(document.body[p : endInset + 1])
2446                         # Remove arg inset
2447                         del document.body[p : endInset + 1]
2448                         subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2449                         document.body[realparbeg : realparbeg] = subst
2450             if layoutname in list_layouts:
2451                 m = rx.match(document.body[p])
2452                 if m:
2453                     argnr = m.group(1)
2454                     if argnr == "1":
2455                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2456                         endPlain = find_end_of_layout(document.body, beginPlain)
2457                         endInset = find_end_of_inset(document.body, p)
2458                         content = document.body[beginPlain + 1 : endPlain]
2459                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2460                         realparend = realparend + len(subst) - len(content)
2461                         document.body[beginPlain + 1 : endPlain] = subst
2462                     elif argnr == "item:1":
2463                         j = find_end_of_inset(document.body, i)
2464                         # Find containing paragraph layout
2465                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2466                         endPlain = find_end_of_layout(document.body, beginPlain)
2467                         content = document.body[beginPlain + 1 : endPlain]
2468                         del document.body[i:j+1]
2469                         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2470                         document.body[realparbeg : realparbeg] = subst
2471                     elif argnr == "item:2":
2472                         j = find_end_of_inset(document.body, i)
2473                         # Find containing paragraph layout
2474                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2475                         endPlain = find_end_of_layout(document.body, beginPlain)
2476                         content = document.body[beginPlain + 1 : endPlain]
2477                         del document.body[i:j+1]
2478                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2479                         document.body[realparbeg : realparbeg] = subst
2480             if layoutname in quote_layouts:
2481                 m = rx.match(document.body[p])
2482                 if m:
2483                     argnr = m.group(1)
2484                     if argnr == "1":
2485                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2486                         endPlain = find_end_of_layout(document.body, beginPlain)
2487                         endInset = find_end_of_inset(document.body, p)
2488                         content = document.body[beginPlain + 1 : endPlain]
2489                         # Adjust range end
2490                         realparend = realparend - len(document.body[p : endInset + 1])
2491                         # Remove arg inset
2492                         del document.body[p : endInset + 1]
2493                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2494                         document.body[realparbeg : realparbeg] = subst
2495             if layoutname in corollary_layouts:
2496                 m = rx.match(document.body[p])
2497                 if m:
2498                     argnr = m.group(1)
2499                     if argnr == "2":
2500                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2501                         endPlain = find_end_of_layout(document.body, beginPlain)
2502                         endInset = find_end_of_inset(document.body, p)
2503                         content = document.body[beginPlain + 1 : endPlain]
2504                         # Adjust range end
2505                         realparend = realparend - len(document.body[p : endInset + 1])
2506                         # Remove arg inset
2507                         del document.body[p : endInset + 1]
2508                         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2509                         document.body[realparbeg : realparbeg] = subst
2510         
2511         i = realparend
2512
2513
2514 def revert_beamerargs2(document):
2515     " Reverts beamer arguments to old layout, step 2 "
2516     
2517     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2518     if document.textclass not in beamer_classes:
2519         return
2520
2521     i = 0
2522     shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2523     corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2524     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2525
2526     while True:
2527         i = find_token(document.body, "\\begin_inset Argument", i)
2528         if i == -1:
2529             return
2530         # Find containing paragraph layout
2531         parent = get_containing_layout(document.body, i)
2532         if parent == False:
2533             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2534             i = i + 1
2535             continue
2536         parbeg = parent[1]
2537         parend = parent[2]
2538         realparbeg = parent[3]
2539         layoutname = parent[0]
2540         realparend = parend
2541         for p in range(parbeg, parend):
2542             if p >= realparend:
2543                 i = realparend
2544                 break
2545             if layoutname in shifted_layouts:
2546                 m = rx.match(document.body[p])
2547                 if m:
2548                     argnr = m.group(1)
2549                     if argnr == "2":
2550                         document.body[p] = "\\begin_inset Argument 1"       
2551             if layoutname in corollary_layouts:
2552                 m = rx.match(document.body[p])
2553                 if m:
2554                     argnr = m.group(1)
2555                     if argnr == "1":
2556                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2557                         endPlain = find_end_of_layout(document.body, beginPlain)
2558                         endInset = find_end_of_inset(document.body, p)
2559                         content = document.body[beginPlain + 1 : endPlain]
2560                         # Adjust range end
2561                         realparend = realparend - len(document.body[p : endInset + 1])
2562                         # Remove arg inset
2563                         del document.body[p : endInset + 1]
2564                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2565                         document.body[realparbeg : realparbeg] = subst
2566             if layoutname == "OverlayArea":
2567                 m = rx.match(document.body[p])
2568                 if m:
2569                     argnr = m.group(1)
2570                     if argnr == "1":
2571                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2572                         endPlain = find_end_of_layout(document.body, beginPlain)
2573                         endInset = find_end_of_inset(document.body, p)
2574                         content = document.body[beginPlain + 1 : endPlain]
2575                         # Adjust range end
2576                         realparend = realparend - len(document.body[p : endInset + 1])
2577                         # Remove arg inset
2578                         del document.body[p : endInset + 1]
2579                         subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2580                         document.body[realparbeg : realparbeg] = subst
2581             if layoutname == "AgainFrame":
2582                 m = rx.match(document.body[p])
2583                 if m:
2584                     argnr = m.group(1)
2585                     if argnr == "2":
2586                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2587                         endPlain = find_end_of_layout(document.body, beginPlain)
2588                         endInset = find_end_of_inset(document.body, p)
2589                         content = document.body[beginPlain + 1 : endPlain]
2590                         # Adjust range end
2591                         realparend = realparend - len(document.body[p : endInset + 1])
2592                         # Remove arg inset
2593                         del document.body[p : endInset + 1]
2594                         subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2595                         document.body[realparbeg : realparbeg] = subst
2596         i = realparend
2597
2598
2599 def revert_beamerargs3(document):
2600     " Reverts beamer arguments to old layout, step 3 "
2601     
2602     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2603     if document.textclass not in beamer_classes:
2604         return
2605
2606     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2607     i = 0
2608     while True:
2609         i = find_token(document.body, "\\begin_inset Argument", i)
2610         if i == -1:
2611             return
2612         # Find containing paragraph layout
2613         parent = get_containing_layout(document.body, i)
2614         if parent == False:
2615             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2616             i = i + 1
2617             continue
2618         parbeg = parent[1]
2619         parend = parent[2]
2620         realparbeg = parent[3]
2621         layoutname = parent[0]
2622         realparend = parend
2623         for p in range(parbeg, parend):
2624             if p >= realparend:
2625                 i = realparend
2626                 break
2627             if layoutname == "AgainFrame":
2628                 m = rx.match(document.body[p])
2629                 if m:
2630                     argnr = m.group(1)
2631                     if argnr == "1":
2632                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2633                         endPlain = find_end_of_layout(document.body, beginPlain)
2634                         endInset = find_end_of_inset(document.body, p)
2635                         content = document.body[beginPlain + 1 : endPlain]
2636                         # Adjust range end
2637                         realparend = realparend - len(document.body[p : endInset + 1])
2638                         # Remove arg inset
2639                         del document.body[p : endInset + 1]
2640                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2641                         document.body[realparbeg : realparbeg] = subst
2642         i = realparend
2643
2644
2645 def revert_beamerflex(document):
2646     " Reverts beamer Flex insets "
2647     
2648     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2649     if document.textclass not in beamer_classes:
2650         return
2651
2652     new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2653                   "Uncover" : "\\uncover", "Visible" : "\\visible",
2654                   "Invisible" : "\\invisible", "Alternative" : "\\alt",
2655                   "Beamer_Note" : "\\note"}
2656     old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2657     rx = re.compile(r'^\\begin_inset Flex (.+)$')
2658
2659     i = 0
2660     while True:
2661         i = find_token(document.body, "\\begin_inset Flex", i)
2662         if i == -1:
2663             return
2664         m = rx.match(document.body[i])
2665         if m:
2666             flextype = m.group(1)
2667             z = find_end_of_inset(document.body, i)
2668             if z == -1:
2669                 document.warning("Can't find end of Flex " + flextype + " inset.")
2670                 i += 1
2671                 continue
2672             if flextype in new_flexes:
2673                 pre = put_cmd_in_ert(new_flexes[flextype])
2674                 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2675                 if arg != -1:
2676                     argend = find_end_of_inset(document.body, arg)
2677                     if argend == -1:
2678                         document.warning("Can't find end of Argument!")
2679                         i += 1
2680                         continue
2681                     # Find containing paragraph layout
2682                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2683                     endPlain = find_end_of_layout(document.body, beginPlain)
2684                     argcontent = document.body[beginPlain + 1 : endPlain]
2685                     # Adjust range end
2686                     z = z - len(document.body[arg : argend + 1])
2687                     # Remove arg inset
2688                     del document.body[arg : argend + 1]
2689                     pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2690                 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2691                 if arg != -1:
2692                     argend = find_end_of_inset(document.body, arg)
2693                     if argend == -1:
2694                         document.warning("Can't find end of Argument!")
2695                         i += 1
2696                         continue
2697                     # Find containing paragraph layout
2698                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2699                     endPlain = find_end_of_layout(document.body, beginPlain)
2700                     argcontent = document.body[beginPlain + 1 : endPlain]
2701                     # Adjust range end
2702                     z = z - len(document.body[arg : argend + 1])
2703                     # Remove arg inset
2704                     del document.body[arg : argend + 1]
2705                     if flextype == "Alternative":
2706                         pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2707                     else:
2708                         pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2709                 pre += put_cmd_in_ert("{")
2710                 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2711                 endPlain = find_end_of_layout(document.body, beginPlain)
2712                 # Adjust range end
2713                 z = z - len(document.body[i : beginPlain + 1])
2714                 z += len(pre)
2715                 document.body[i : beginPlain + 1] = pre
2716                 post = put_cmd_in_ert("}")
2717                 document.body[z - 2 : z + 1] = post
2718             elif flextype in old_flexes:
2719                 pre = put_cmd_in_ert(old_flexes[flextype])
2720                 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2721                 if arg == -1:
2722                     i += 1
2723                     continue
2724                 argend = find_end_of_inset(document.body, arg)
2725                 if argend == -1:
2726                     document.warning("Can't find end of Argument!")
2727                     i += 1
2728                     continue
2729                 # Find containing paragraph layout
2730                 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2731                 endPlain = find_end_of_layout(document.body, beginPlain)
2732                 argcontent = document.body[beginPlain + 1 : endPlain]
2733                 # Adjust range end
2734                 z = z - len(document.body[arg : argend + 1])
2735                 # Remove arg inset
2736                 del document.body[arg : argend + 1]
2737                 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2738                 pre += put_cmd_in_ert("{")
2739                 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2740                 endPlain = find_end_of_layout(document.body, beginPlain)
2741                 # Adjust range end
2742                 z = z - len(document.body[i : beginPlain + 1])
2743                 z += len(pre)
2744                 document.body[i : beginPlain + 1] = pre
2745                 post = put_cmd_in_ert("}")
2746                 document.body[z - 2 : z + 1] = post
2747         
2748         i += 1
2749
2750
2751 def revert_beamerblocks(document):
2752     " Reverts beamer block arguments to ERT "
2753     
2754     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2755     if document.textclass not in beamer_classes:
2756         return
2757
2758     blocks = ["Block", "ExampleBlock", "AlertBlock"]
2759
2760     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2761     i = 0
2762     while True:
2763         i = find_token(document.body, "\\begin_inset Argument", i)
2764         if i == -1:
2765             return
2766         # Find containing paragraph layout
2767         parent = get_containing_layout(document.body, i)
2768         if parent == False:
2769             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2770             i = i + 1
2771             continue
2772         parbeg = parent[1]
2773         parend = parent[2]
2774         realparbeg = parent[3]
2775         layoutname = parent[0]
2776         realparend = parend
2777         for p in range(parbeg, parend):
2778             if p >= realparend:
2779                 i = realparend
2780                 break
2781             if layoutname in blocks:
2782                 m = rx.match(document.body[p])
2783                 if m:
2784                     argnr = m.group(1)
2785                     if argnr == "1":
2786                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2787                         endPlain = find_end_of_layout(document.body, beginPlain)
2788                         endInset = find_end_of_inset(document.body, p)
2789                         content = document.body[beginPlain + 1 : endPlain]
2790                         # Adjust range end
2791                         realparend = realparend - len(document.body[p : endInset + 1])
2792                         # Remove arg inset
2793                         del document.body[p : endInset + 1]
2794                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2795                         document.body[realparbeg : realparbeg] = subst
2796                     elif argnr == "2":
2797                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2798                         endPlain = find_end_of_layout(document.body, beginPlain)
2799                         endInset = find_end_of_inset(document.body, p)
2800                         content = document.body[beginPlain + 1 : endPlain]
2801                         # Adjust range end
2802                         realparend = realparend - len(document.body[p : endInset + 1])
2803                         # Remove arg inset
2804                         del document.body[p : endInset + 1]
2805                         subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2806                         document.body[realparbeg : realparbeg] = subst
2807         i = realparend
2808
2809
2810
2811 def convert_beamerblocks(document):
2812     " Converts beamer block ERT args to native InsetArgs "
2813     
2814     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2815     if document.textclass not in beamer_classes:
2816         return
2817    
2818     blocks = ["Block", "ExampleBlock", "AlertBlock"]
2819     for lay in blocks:
2820         i = 0
2821         while True:
2822             i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2823             if i == -1:
2824                 break
2825             parent = get_containing_layout(document.body, i)
2826             if parent == False or parent[1] != i:
2827                 document.warning("Wrong parent layout!")
2828                 i += 1
2829                 continue
2830             j = parent[2]
2831             parbeg = parent[3]
2832             if i != -1:
2833                 if document.body[parbeg] == "\\begin_inset ERT":
2834                     ertcont = parbeg + 5
2835                     while True:
2836                         if document.body[ertcont].startswith("<"):
2837                             # This is an overlay specification
2838                             # strip off the <
2839                             document.body[ertcont] = document.body[ertcont][1:]
2840                             if document.body[ertcont].endswith(">"):
2841                                 # strip off the >
2842                                 document.body[ertcont] = document.body[ertcont][:-1]
2843                                 # Convert to ArgInset
2844                                 document.body[parbeg] = "\\begin_inset Argument 1"
2845                             elif document.body[ertcont].endswith("}"):
2846                                 # divide the args
2847                                 tok = document.body[ertcont].find('>{')
2848                                 if tok != -1:
2849                                     document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2850                                                                             '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2851                                                                             'status collapsed', '', '\\begin_layout Plain Layout',
2852                                                                             document.body[ertcont][tok + 2:-1]]
2853                             # Convert to ArgInset
2854                             document.body[parbeg] = "\\begin_inset Argument 1"
2855                         elif document.body[ertcont].startswith("{"):
2856                             # This is the block title
2857                             if document.body[ertcont].endswith("}"):
2858                                 # strip off the braces
2859                                 document.body[ertcont] = document.body[ertcont][1:-1]
2860                                 # Convert to ArgInset
2861                                 document.body[parbeg] = "\\begin_inset Argument 2"
2862                             elif count_pars_in_inset(document.body, ertcont) > 1:
2863                                 # Multipar ERT. Skip this.
2864                                 break
2865                             else:
2866                                 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True)
2867                         else:
2868                             break
2869                         j = find_end_of_layout(document.body, i)
2870                         if j == -1:
2871                             document.warning("end of layout not found!")
2872                         k = find_token(document.body, "\\begin_inset Argument", i, j)
2873                         if k == -1:
2874                             document.warning("InsetArgument not found!")
2875                             break
2876                         l = find_end_of_inset(document.body, k)
2877                         m = find_token(document.body, "\\begin_inset ERT", l, j)
2878                         if m == -1:
2879                             break
2880                         ertcont = m + 5
2881                         parbeg = m
2882             i = j
2883
2884
2885 def convert_overprint(document):
2886     " Convert old beamer overprint layouts to ERT "
2887     
2888     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2889     if document.textclass not in beamer_classes:
2890         return
2891
2892     i = 0
2893     while True:
2894         i = find_token(document.body, "\\begin_layout Overprint", i)
2895         if i == -1:
2896             return
2897         # Find end of sequence
2898         j = find_end_of_sequence(document.body, i)
2899         if j == -1:
2900             document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2901             i = i + 1
2902             continue
2903         endseq = j
2904         subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2905         esubst = list()
2906         if document.body[j] == "\\end_deeper":
2907             esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2908         else:
2909             esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2910         endseq = endseq + len(esubst) - len(document.body[j : j])
2911         document.body[j : j] = esubst
2912         argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2913         if argbeg != -1:
2914             argend = find_end_of_layout(document.body, argbeg)
2915             if argend == -1:
2916                 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2917                 i = i + 1
2918                 continue
2919             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2920             endPlain = find_end_of_layout(document.body, beginPlain)
2921             content = document.body[beginPlain + 1 : endPlain]
2922             # Adjust range end
2923             endseq = endseq - len(document.body[argbeg : argend + 1])
2924             # Remove arg inset
2925             del document.body[argbeg : argend + 1]
2926             subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2927             
2928         endseq = endseq - len(document.body[i : i])
2929         document.body[i : i] = subst + ["\\end_layout"]
2930         endseq += len(subst)
2931         
2932         for p in range(i, endseq):
2933             if document.body[p] == "\\begin_layout Overprint":
2934                 document.body[p] = "\\begin_layout Standard"
2935
2936         i = endseq
2937
2938
2939 def revert_overprint(document):
2940     " Revert old beamer overprint layouts to ERT "
2941     
2942     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2943     if document.textclass not in beamer_classes:
2944         return
2945
2946     i = 0
2947     while True:
2948         i = find_token(document.body, "\\begin_layout Overprint", i)
2949         if i == -1:
2950             return
2951         # Find end of sequence
2952         j = find_end_of_sequence(document.body, i)
2953         if j == -1:
2954             document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2955             i = i + 1
2956             continue
2957         endseq = j
2958         subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2959         esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
2960         endseq = endseq + len(esubst) - len(document.body[j : j])
2961         if document.body[j] == "\\end_deeper":
2962             document.body[j : j] = ["\\end_deeper", ""] + esubst
2963         else:
2964             document.body[j : j] = esubst
2965         r = i
2966         while r < j:
2967             if document.body[r] == "\\begin_deeper":
2968                 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
2969                 if s != -1:
2970                     document.body[r] = ""
2971                     document.body[s] = ""
2972                     r = s
2973                     continue
2974             r = r + 1
2975         argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2976         if argbeg != -1:
2977             argend = find_end_of_inset(document.body, argbeg)
2978             if argend == -1:
2979                 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2980                 i = i + 1
2981                 continue
2982             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2983             endPlain = find_end_of_layout(document.body, beginPlain)
2984             content = document.body[beginPlain + 1 : endPlain]
2985             # Adjust range end
2986             endseq = endseq - len(document.body[argbeg : argend])
2987             # Remove arg inset
2988             del document.body[argbeg : argend + 1]
2989             subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2990             
2991         endseq = endseq - len(document.body[i : i])
2992         document.body[i : i] = subst + ["\\end_layout"]
2993         endseq += len(subst)
2994      
2995         p = i
2996         while True:
2997             if p >= endseq:
2998                 break
2999             if document.body[p] == "\\begin_layout Overprint":
3000                 q = find_end_of_layout(document.body, p)
3001                 if q == -1:
3002                     document.warning("Malformed lyx document. Cannot find end of Overprint layout!")
3003                     p += 1
3004                     continue
3005                 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3006                 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3007                 if argbeg != -1:
3008                     argend = find_end_of_inset(document.body, argbeg)
3009                     if argend == -1:
3010                         document.warning("Malformed lyx document. Cannot find end of Overprint item argument!")
3011                         p += 1
3012                         continue
3013                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3014                     endPlain = find_end_of_layout(document.body, beginPlain)
3015                     content = document.body[beginPlain + 1 : endPlain]
3016                     # Adjust range end
3017                     endseq = endseq - len(document.body[argbeg : argend + 1])
3018                     # Remove arg inset
3019                     del document.body[argbeg : argend + 1]
3020                     subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3021                 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3022                 document.body[p : p + 1] = subst
3023             p = p + 1
3024
3025         i = endseq
3026
3027
3028 def revert_frametitle(document):
3029     " Reverts beamer frametitle layout to ERT "
3030     
3031     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3032     if document.textclass not in beamer_classes:
3033         return
3034
3035     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3036     i = 0
3037     while True:
3038         i = find_token(document.body, "\\begin_layout FrameTitle", i)
3039         if i == -1:
3040             return
3041         j = find_end_of_layout(document.body, i)
3042         if j == -1:
3043             document.warning("Malformed lyx document: Can't find end of FrameTitle layout")
3044             i = i + 1
3045             continue
3046         endlay = j
3047         document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3048         endlay += len(put_cmd_in_ert("}"))
3049         subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3050         for p in range(i, j):
3051             if p >= endlay:
3052                 break
3053             m = rx.match(document.body[p])
3054             if m:
3055                 argnr = m.group(1)
3056                 if argnr == "1":
3057                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3058                     endPlain = find_end_of_layout(document.body, beginPlain)
3059                     endInset = find_end_of_inset(document.body, p)
3060                     content = document.body[beginPlain + 1 : endPlain]
3061                     # Adjust range end
3062                     endlay = endlay - len(document.body[p : endInset + 1])
3063                     # Remove arg inset
3064                     del document.body[p : endInset + 1]
3065                     subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3066                 elif argnr == "2":
3067                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3068                     endPlain = find_end_of_layout(document.body, beginPlain)
3069                     endInset = find_end_of_inset(document.body, p)
3070                     content = document.body[beginPlain + 1 : endPlain]
3071                     # Adjust range end
3072                     endlay = endlay - len(document.body[p : endInset + 1])
3073                     # Remove arg inset
3074                     del document.body[p : endInset + 1]
3075                     subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3076                     
3077         subst += put_cmd_in_ert("{")
3078         document.body[i : i + 1] = subst
3079         i = endlay
3080
3081
3082 def convert_epigraph(document):
3083     " Converts memoir epigraph to new syntax "
3084     
3085     if document.textclass != "memoir":
3086         return
3087
3088     i = 0
3089     while True:
3090         i = find_token(document.body, "\\begin_layout Epigraph", i)
3091         if i == -1:
3092             return
3093         j = find_end_of_layout(document.body, i)
3094         if j == -1:
3095             document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3096             i = i + 1
3097             continue
3098         endlay = j
3099         subst = list()
3100         ert = find_token(document.body, "\\begin_inset ERT", i, j)
3101         if ert != -1:
3102             endInset = find_end_of_inset(document.body, ert)
3103             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3104             endPlain = find_end_of_layout(document.body, beginPlain)
3105             ertcont = beginPlain + 2
3106             if document.body[ertcont] == "}{":
3107                 # strip off the <
3108                 # Convert to ArgInset
3109                 endlay = endlay - 2 * len(document.body[j])
3110                 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3111                             '\\begin_layout Plain Layout']
3112                 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3113                 document.body[j : j + 1] = endsubst
3114                 document.body[endInset + 1 : endInset + 1] = begsubst
3115                 # Adjust range end
3116                 endlay += len(begsubst) + len(endsubst)
3117                 endlay = endlay - len(document.body[ert : endInset + 1])
3118                 del document.body[ert : endInset + 1]
3119                     
3120         i = endlay
3121
3122
3123 def revert_epigraph(document):
3124     " Reverts memoir epigraph argument to ERT "
3125     
3126     if document.textclass != "memoir":
3127         return
3128
3129     i = 0
3130     while True:
3131         i = find_token(document.body, "\\begin_layout Epigraph", i)
3132         if i == -1:
3133             return
3134         j = find_end_of_layout(document.body, i)
3135         if j == -1:
3136             document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3137             i = i + 1
3138             continue
3139         endlay = j
3140         subst = list()
3141         p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3142         if p != -1:
3143             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3144             endPlain = find_end_of_layout(document.body, beginPlain)
3145             endInset = find_end_of_inset(document.body, p)
3146             content = document.body[beginPlain + 1 : endPlain]
3147             # Adjust range end
3148             endlay = endlay - len(document.body[p : endInset + 1])
3149             # Remove arg inset
3150             del document.body[p : endInset + 1]
3151             subst += put_cmd_in_ert("}{") + content
3152         else:
3153             subst += put_cmd_in_ert("}{")
3154                     
3155         document.body[j : j] = subst + document.body[j : j]
3156         i = endlay
3157
3158
3159 def convert_captioninsets(document):
3160     " Converts caption insets to new syntax "
3161     
3162     i = 0
3163     while True:
3164       i = find_token(document.body, "\\begin_inset Caption", i)
3165       if i == -1:
3166           return
3167       document.body[i] = "\\begin_inset Caption Standard"
3168       i = i + 1
3169         
3170
3171
3172 def revert_captioninsets(document):
3173     " Reverts caption insets to old syntax "
3174     
3175     i = 0
3176     while True:
3177       i = find_token(document.body, "\\begin_inset Caption Standard", i)
3178       if i == -1:
3179           return
3180       document.body[i] = "\\begin_inset Caption"
3181       i = i + 1
3182
3183
3184 def convert_captionlayouts(document):
3185     " Convert caption layouts to caption insets. "
3186     
3187     caption_dict = {
3188         "Captionabove":  "Above",
3189         "Captionbelow":  "Below",
3190         "FigCaption"  :  "FigCaption",
3191         "Table_Caption" :  "Table",
3192         "CenteredCaption" : "Centered",
3193         "Bicaption" : "Bicaption",
3194         }
3195     
3196     i = 0
3197     while True:
3198         i = find_token(document.body, "\\begin_layout", i)
3199         if i == -1:
3200             return
3201         val = get_value(document.body, "\\begin_layout", i)
3202         if val in caption_dict.keys():
3203             j = find_end_of_layout(document.body, i)
3204             if j == -1:
3205                 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3206                 return
3207
3208             document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3209             document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3210                                     "\\begin_inset Caption %s" % caption_dict[val], "",
3211                                     "\\begin_layout %s" % document.default_layout]
3212         i = i + 1
3213
3214
3215 def revert_captionlayouts(document):
3216     " Revert caption insets to caption layouts. "
3217     
3218     caption_dict = {
3219         "Above" : "Captionabove",
3220         "Below" : "Captionbelow",
3221         "FigCaption"  :  "FigCaption",
3222         "Table" : "Table_Caption",
3223         "Centered" : "CenteredCaption",
3224         "Bicaption" : "Bicaption",
3225         }
3226     
3227     i = 0
3228     rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3229     while True:
3230         i = find_token(document.body, "\\begin_inset Caption", i)
3231         if i == -1:
3232             return
3233
3234         m = rx.match(document.body[i])
3235         val = ""
3236         if m:
3237             val = m.group(1)
3238         if val not in caption_dict.keys():
3239             i = i + 1
3240             continue
3241         
3242         # We either need to delete the previous \begin_layout line, or we
3243         # need to end the previous layout if this inset is not in the first
3244         # position of the paragraph.
3245         layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3246         if layout_before == -1:
3247             document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3248             return
3249         layout_line = document.body[layout_before]
3250         del_layout_before = True
3251         l = layout_before + 1
3252         while l < i:
3253             if document.body[l] != "":
3254                 del_layout_before = False
3255                 break
3256             l = l + 1
3257         if del_layout_before:
3258             del document.body[layout_before:i]
3259             i = layout_before
3260         else:
3261             document.body[i:i] = ["\\end_layout", ""]
3262             i = i + 2
3263
3264         # Find start of layout in the inset and end of inset
3265         j = find_token(document.body, "\\begin_layout", i)
3266         if j == -1:
3267             document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3268             return
3269         k = find_end_of_inset(document.body, i)
3270         if k == -1:
3271             document.warning("Malformed LyX document: Missing `\\end_inset'.")
3272             return
3273
3274         # We either need to delete the following \end_layout line, or we need
3275         # to restart the old layout if this inset is not at the paragraph end.
3276         layout_after = find_token(document.body, "\\end_layout", k)
3277         if layout_after == -1:
3278             document.warning("Malformed LyX document: Missing `\\end_layout'.")
3279             return
3280         del_layout_after = True
3281         l = k + 1
3282         while l < layout_after:
3283             if document.body[l] != "":
3284                 del_layout_after = False
3285                 break
3286             l = l + 1
3287         if del_layout_after:
3288             del document.body[k+1:layout_after+1]
3289         else:
3290             document.body[k+1:k+1] = [layout_line, ""]
3291
3292         # delete \begin_layout and \end_inset and replace \begin_inset with
3293         # "\begin_layout XXX". This works because we can only have one
3294         # paragraph in the caption inset: The old \end_layout will be recycled.
3295         del document.body[k]
3296         if document.body[k] == "":
3297             del document.body[k]
3298         del document.body[j]
3299         if document.body[j] == "":
3300             del document.body[j]
3301         document.body[i] = "\\begin_layout %s" % caption_dict[val]
3302         if document.body[i+1] == "":
3303             del document.body[i+1]
3304         i = i + 1
3305
3306
3307 def revert_fragileframe(document):
3308     " Reverts beamer FragileFrame layout to ERT "
3309     
3310     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3311     if document.textclass not in beamer_classes:
3312         return
3313
3314     i = 0
3315     while True:
3316         i = find_token(document.body, "\\begin_layout FragileFrame", i)
3317         if i == -1:
3318             return
3319         # Find end of sequence
3320         j = find_end_of_sequence(document.body, i)
3321         if j == -1:
3322             document.warning("Malformed lyx document. Cannot find end of FragileFrame sequence!")
3323             i = i + 1
3324             continue
3325         endseq = j
3326         subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3327         esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3328         endseq = endseq + len(esubst) - len(document.body[j : j])
3329         if document.body[j] == "\\end_deeper":
3330             document.body[j : j] = ["\\end_deeper", ""] + esubst
3331         else:
3332             document.body[j : j] = esubst
3333         for q in range(i, j):
3334             if document.body[q] == "\\begin_layout FragileFrame":
3335                 document.body[q] = "\\begin_layout %s" % document.default_layout
3336         r = i
3337         while r < j:
3338             if document.body[r] == "\\begin_deeper":
3339                 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3340                 if s != -1:
3341                     document.body[r] = ""
3342                     document.body[s] = ""
3343                     r = s
3344                     continue
3345             r = r + 1
3346         for p in range(1, 5):
3347             arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3348             if arg != -1:
3349                 if p == 1:
3350                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3351                     endPlain = find_end_of_layout(document.body, beginPlain)
3352                     endInset = find_end_of_inset(document.body, arg)
3353                     content = document.body[beginPlain + 1 : endPlain]
3354                     # Adjust range end
3355                     j = j - len(document.body[arg : endInset + 1])
3356                     # Remove arg inset
3357                     del document.body[arg : endInset + 1]
3358                     subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3359                 elif p == 2:
3360                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3361                     endPlain = find_end_of_layout(document.body, beginPlain)
3362                     endInset = find_end_of_inset(document.body, arg)
3363                     content = document.body[beginPlain + 1 : endPlain]
3364                     # Adjust range end
3365                     j = j - len(document.body[arg : endInset + 1])
3366                     # Remove arg inset
3367                     del document.body[arg : endInset + 1]
3368                     subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3369                 elif p == 3:
3370                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3371                     endPlain = find_end_of_layout(document.body, beginPlain)
3372                     endInset = find_end_of_inset(document.body, arg)
3373                     content = document.body[beginPlain + 1 : endPlain]
3374                     # Adjust range end
3375                     j = j - len(document.body[arg : endInset + 1])
3376                     # Remove arg inset
3377                     del document.body[arg : endInset + 1]
3378                     subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3379                 elif p == 4:
3380                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3381                     endPlain = find_end_of_layout(document.body, beginPlain)
3382                     endInset = find_end_of_inset(document.body, arg)
3383                     content = document.body[beginPlain + 1 : endPlain]
3384                     # Adjust range end
3385                     j = j - len(document.body[arg : endInset + 1])
3386                     # Remove arg inset
3387                     del document.body[arg : endInset + 1]
3388                     subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3389             elif p == 3:
3390                 subst += put_cmd_in_ert("[fragile]")
3391                     
3392         document.body[i : i + 1] = subst
3393         i = j
3394
3395
3396 def revert_newframes(document):
3397     " Reverts beamer Frame and PlainFrame layouts to old forms "
3398     
3399     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3400     if document.textclass not in beamer_classes:
3401         return
3402
3403     frame_dict = {
3404         "Frame" : "BeginFrame",
3405         "PlainFrame" : "BeginPlainFrame",
3406         }
3407
3408     rx = re.compile(r'^\\begin_layout (\S+)$')
3409     i = 0
3410     while True:
3411         i = find_token(document.body, "\\begin_layout", i)
3412         if i == -1:
3413             return
3414
3415         m = rx.match(document.body[i])
3416         val = ""
3417         if m:
3418             val = m.group(1)
3419         if val not in frame_dict.keys():
3420             i = i + 1
3421             continue
3422         # Find end of sequence
3423         j = find_end_of_sequence(document.body, i)
3424         if j == -1:
3425             document.warning("Malformed lyx document. Cannot find end of Frame sequence!")
3426             i = i + 1
3427             continue
3428         endseq = j
3429         subst = ["\\begin_layout %s" % frame_dict[val]]
3430         esubst = ["\\end_layout", "", "\\begin_layout EndFrame", "", "\\end_layout"]
3431         endseq = endseq + len(esubst) - len(document.body[j : j])
3432         if document.body[j] == "\\end_deeper":
3433             document.body[j : j] = ["\\end_deeper", ""] + esubst
3434         else:
3435             document.body[j : j] = esubst
3436         for q in range(i, j):
3437             if document.body[q] == "\\begin_layout %s" % val:
3438                 document.body[q] = "\\begin_layout %s" % document.default_layout
3439         r = i
3440         while r < j:
3441             if document.body[r] == "\\begin_deeper":
3442                 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3443                 if s != -1:
3444                     document.body[r] = ""
3445                     document.body[s] = ""
3446                     r = s
3447                     continue
3448             r = r + 1
3449         l = find_end_of_layout(document.body, i)
3450         for p in range(1, 5):
3451             arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3452             if arg != -1:
3453                 if p == 1:
3454                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3455                     endPlain = find_end_of_layout(document.body, beginPlain)
3456                     endInset = find_end_of_inset(document.body, arg)
3457                     content = document.body[beginPlain + 1 : endPlain]
3458                     # Adjust range end
3459                     l = l - len(document.body[arg : endInset + 1])
3460                     # Remove arg inset
3461                     del document.body[arg : endInset + 1]
3462                     subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3463                 elif p == 2:
3464                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3465                     endPlain = find_end_of_layout(document.body, beginPlain)
3466                     endInset = find_end_of_inset(document.body, arg)
3467                     content = document.body[beginPlain + 1 : endPlain]
3468                     # Adjust range end
3469                     l = l - len(document.body[arg : endInset + 1])
3470                     # Remove arg inset
3471                     del document.body[arg : endInset + 1]
3472                     subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3473                 elif p == 3:
3474                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3475                     endPlain = find_end_of_layout(document.body, beginPlain)
3476                     endInset = find_end_of_inset(document.body, arg)
3477                     content = document.body[beginPlain + 1 : endPlain]
3478                     # Adjust range end
3479                     l = l - len(document.body[arg : endInset + 1])
3480                     # Remove arg inset
3481                     del document.body[arg : endInset + 1]
3482                     subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3483                 elif p == 4:
3484                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3485                     endPlain = find_end_of_layout(document.body, beginPlain)
3486                     endInset = find_end_of_inset(document.body, arg)
3487                     content = document.body[beginPlain + 1 : endPlain]
3488                     # Adjust range end
3489                     l = l - len(document.body[arg : endInset + 1])
3490                     # Remove arg inset
3491                     del document.body[arg : endInset + 1]
3492                     subst += content
3493                     
3494         document.body[i : i + 1] = subst
3495         i = j
3496
3497
3498 def revert_IEEEtran_3(document):
3499   '''
3500   Reverts Flex Insets to TeX-code
3501   '''
3502   if document.textclass == "IEEEtran":
3503     h = 0
3504     i = 0
3505     j = 0
3506     while True:
3507       if h != -1:
3508         h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3509       if h != -1:
3510         endh = find_end_of_inset(document.body, h)
3511         document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3512         document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3513         h = h + 5
3514       if i != -1:
3515         i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3516       if i != -1:
3517         endi = find_end_of_inset(document.body, i)
3518         document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3519         document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3520         i = i + 5
3521       if j != -1:
3522         j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3523       if j != -1:
3524         endj = find_end_of_inset(document.body, j)
3525         document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3526         document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3527         j = j + 5
3528       if i == -1 and j == -1 and h == -1:
3529         return
3530
3531
3532 def revert_kurier_fonts(document):
3533   " Revert kurier font definition to LaTeX "
3534   
3535   i = find_token(document.header, "\\font_math", 0)
3536   if i != -1:
3537     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
3538       val = get_value(document.header, "\\font_math", i)
3539       if val == "kurier-math":
3540         add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3541           "\\usepackage[math]{kurier}\n" \
3542           "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3543         document.header[i] = "\\font_math auto"
3544   
3545   if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
3546     kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
3547     k = find_token(document.header, "\\font_sans kurier", 0)
3548     if k != -1:
3549       sf = get_value(document.header, "\\font_sans", k)
3550       if sf in kurier_fonts:
3551         add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3552         document.header[k] = "\\font_sans default"
3553
3554
3555 def revert_new_libertines(document):
3556     " Revert new libertine font definition to LaTeX "
3557   
3558     if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
3559         return
3560
3561     i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
3562     if i != -1:
3563         preamble = "\\usepackage"
3564         sc = find_token(document.header, "\\font_tt_scale", 0)
3565         if sc != -1:
3566             scval = get_value(document.header, "\\font_tt_scale", sc)
3567             if scval != "100":
3568                 preamble += "[scale=%f]" % (float(scval) / 100)
3569                 document.header[sc] = "\\font_tt_scale 100"
3570         preamble += "{libertineMono-type1}"
3571         add_to_preamble(document, [preamble])
3572         document.header[i] = "\\font_typewriter default"
3573    
3574     k = find_token(document.header, "\\font_sans biolinum", 0)
3575     if k != -1:
3576         preamble = "\\usepackage"
3577         options = ""
3578         j = find_token(document.header, "\\font_osf true", 0)
3579         if j != -1:
3580             options += "osf"
3581         else:
3582             options += "lining"
3583         sc = find_token(document.header, "\\font_sf_scale", 0)
3584         if sc != -1:
3585             scval = get_value(document.header, "\\font_sf_scale", sc)
3586             if scval != "100":
3587                 options += ",scale=%f" % (float(scval) / 100)
3588                 document.header[sc] = "\\font_sf_scale 100"
3589         if options != "":
3590             preamble += "[" + options +"]"
3591         preamble += "{biolinum-type1}"
3592         add_to_preamble(document, [preamble])
3593         document.header[k] = "\\font_sans default"
3594
3595
3596 ##
3597 # Conversion hub
3598 #
3599
3600 supported_versions = ["2.1.0","2.1"]
3601 convert = [
3602            [414, []],
3603            [415, [convert_undertilde]],
3604            [416, []],
3605            [417, [convert_japanese_encodings]],
3606            [418, []],
3607            [419, []],
3608            [420, [convert_biblio_style]],
3609            [421, [convert_longtable_captions]],
3610            [422, [convert_use_packages]],
3611            [423, [convert_use_mathtools]],
3612            [424, [convert_cite_engine_type]],
3613            [425, []],
3614            [426, []],
3615            [427, []],
3616            [428, [convert_cell_rotation]],
3617            [429, [convert_table_rotation]],
3618            [430, [convert_listoflistings]],
3619            [431, [convert_use_amssymb]],
3620            [432, []],
3621            [433, [convert_armenian]],
3622            [434, []],
3623            [435, []],
3624            [436, []],
3625            [437, []],
3626            [438, []],
3627            [439, []],
3628            [440, []],
3629            [441, [convert_mdnomath]],
3630            [442, []],
3631            [443, []],
3632            [444, []],
3633            [445, []],
3634            [446, [convert_latexargs]],
3635            [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
3636            [448, [convert_literate]],
3637            [449, []],
3638            [450, []],
3639            [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
3640            [452, [convert_beamerblocks]],
3641            [453, [convert_use_stmaryrd]],
3642            [454, [convert_overprint]],
3643            [455, []],
3644            [456, [convert_epigraph]],
3645            [457, [convert_use_stackrel]],
3646            [458, [convert_captioninsets, convert_captionlayouts]],
3647            [459, []],
3648            [460, []],
3649            [461, []],
3650            [462, []]
3651           ]
3652
3653 revert =  [
3654            [461, [revert_new_libertines]],
3655            [460, [revert_kurier_fonts]],
3656            [459, [revert_IEEEtran_3]],
3657            [458, [revert_fragileframe, revert_newframes]],
3658            [457, [revert_captioninsets, revert_captionlayouts]],
3659            [456, [revert_use_stackrel]],
3660            [455, [revert_epigraph]],
3661            [454, [revert_frametitle]],
3662            [453, [revert_overprint]],
3663            [452, [revert_use_stmaryrd]],
3664            [451, [revert_beamerblocks]],
3665            [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
3666            [449, [revert_garamondx, revert_garamondx_newtxmath]],
3667            [448, [revert_itemargs]],
3668            [447, [revert_literate]],
3669            [446, [revert_IEEEtran, revert_IEEEtran_2, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV, revert_Initials, revert_ModernCV]],
3670            [445, [revert_latexargs]],
3671            [444, [revert_uop]],
3672            [443, [revert_biolinum]],
3673            [442, []],
3674            [441, [revert_newtxmath]],
3675            [440, [revert_mdnomath]],
3676            [439, [revert_mathfonts]],
3677            [438, [revert_minionpro]],
3678            [437, [revert_ipadeco, revert_ipachar]],
3679            [436, [revert_texgyre]],
3680            [435, [revert_mathdesign]],
3681            [434, [revert_txtt]],
3682            [433, [revert_libertine]],
3683            [432, [revert_armenian]],
3684            [431, [revert_languages, revert_ancientgreek]],
3685            [430, [revert_use_amssymb]],
3686            [429, [revert_listoflistings]],
3687            [428, [revert_table_rotation]],
3688            [427, [revert_cell_rotation]],
3689            [426, [revert_tipa]],
3690            [425, [revert_verbatim]],
3691            [424, [revert_cancel]],
3692            [423, [revert_cite_engine_type]],
3693            [422, [revert_use_mathtools]],
3694            [421, [revert_use_packages]],
3695            [420, [revert_longtable_captions]],
3696            [419, [revert_biblio_style]],
3697            [418, [revert_australian]],
3698            [417, [revert_justification]],
3699            [416, [revert_japanese_encodings]],
3700            [415, [revert_negative_space, revert_math_spaces]],
3701            [414, [revert_undertilde]],
3702            [413, [revert_visible_space]]
3703           ]
3704
3705
3706 if __name__ == "__main__":
3707     pass