]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/lyx_2_1.py
ff89312123f46cbd6fb558cf172a012ee9475ba6
[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             else:
963                 preamble += "[lining]"
964             preamble += "{libertine-type1}"
965             add_to_preamble(document, [preamble])
966             document.header[i] = "\\font_roman default"
967
968
969 def revert_txtt(document):
970     " Revert native txtt font definition to LaTeX " 
971
972     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
973         i = find_token(document.header, "\\font_typewriter txtt", 0)
974         if i != -1:
975             preamble = "\\renewcommand{\\ttdefault}{txtt}"
976             add_to_preamble(document, [preamble])
977             document.header[i] = "\\font_typewriter default"
978
979
980 def revert_mathdesign(document):
981     " Revert native mathdesign font definition to LaTeX " 
982
983     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
984         mathdesign_dict = {
985         "mdbch":  "charter",
986         "mdput":  "utopia",
987         "mdugm":  "garamond"
988         }
989         i = find_token(document.header, "\\font_roman", 0)
990         if i == -1:
991             return
992         val = get_value(document.header, "\\font_roman", i)
993         if val in mathdesign_dict.keys():
994             preamble = "\\usepackage[%s" % mathdesign_dict[val]
995             expert = False
996             j = find_token(document.header, "\\font_osf true", 0)
997             if j != -1:
998                 expert = True
999                 document.header[j] = "\\font_osf false"
1000             l = find_token(document.header, "\\font_sc true", 0)
1001             if l != -1:
1002                 expert = True
1003                 document.header[l] = "\\font_sc false"
1004             if expert:
1005                 preamble += ",expert"
1006             preamble += "]{mathdesign}"
1007             add_to_preamble(document, [preamble])
1008             document.header[i] = "\\font_roman default"
1009
1010
1011 def revert_texgyre(document):
1012     " Revert native TeXGyre font definition to LaTeX " 
1013
1014     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1015         texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1016                          "tgheros", "tgpagella", "tgschola", "tgtermes"]
1017         i = find_token(document.header, "\\font_roman", 0)
1018         if i != -1:
1019             val = get_value(document.header, "\\font_roman", i)
1020             if val in texgyre_fonts:
1021                 preamble = "\\usepackage{%s}" % val
1022                 add_to_preamble(document, [preamble])
1023                 document.header[i] = "\\font_roman default"
1024         i = find_token(document.header, "\\font_sans", 0)
1025         if i != -1:
1026             val = get_value(document.header, "\\font_sans", i)
1027             if val in texgyre_fonts:
1028                 preamble = "\\usepackage{%s}" % val
1029                 add_to_preamble(document, [preamble])
1030                 document.header[i] = "\\font_sans default"
1031         i = find_token(document.header, "\\font_typewriter", 0)
1032         if i != -1:
1033             val = get_value(document.header, "\\font_typewriter", i)
1034             if val in texgyre_fonts:
1035                 preamble = "\\usepackage{%s}" % val
1036                 add_to_preamble(document, [preamble])
1037                 document.header[i] = "\\font_typewriter default"
1038
1039
1040 def revert_ipadeco(document):
1041     " Revert IPA decorations to ERT "
1042     i = 0
1043     while True:
1044       i = find_token(document.body, "\\begin_inset IPADeco", i)
1045       if i == -1:
1046           return
1047       end = find_end_of_inset(document.body, i)
1048       if end == -1:
1049           document.warning("Can't find end of inset at line " + str(i))
1050           i += 1
1051           continue
1052       line = document.body[i]
1053       rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1054       m = rx.match(line)
1055       decotype = m.group(1)
1056       if decotype != "toptiebar" and decotype != "bottomtiebar":
1057           document.warning("Invalid IPADeco type: " + decotype)
1058           i = end
1059           continue
1060       blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1061       if blay == -1:
1062           document.warning("Can't find layout for inset at line " + str(i))
1063           i = end
1064           continue
1065       bend = find_end_of_layout(document.body, blay)
1066       if bend == -1:
1067           document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1068           i = end
1069           continue
1070       substi = ["\\begin_inset ERT", "status collapsed", "",
1071                 "\\begin_layout Plain Layout", "", "", "\\backslash", 
1072                 decotype + "{", "\\end_layout", "", "\\end_inset"]
1073       substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1074                 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1075       # do the later one first so as not to mess up the numbering
1076       document.body[bend:end + 1] = substj
1077       document.body[i:blay + 1] = substi
1078       i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1079       add_to_preamble(document, "\\usepackage{tipa}")
1080
1081
1082 def revert_ipachar(document):
1083     ' Revert \\IPAChar to ERT '
1084     i = 0
1085     found = False
1086     while i < len(document.body):
1087         m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1088         if m:
1089             found = True
1090             before = m.group(1)
1091             ipachar = m.group(2)
1092             after = m.group(3)
1093             subst = [before,
1094                      '\\begin_inset ERT',
1095                      'status collapsed', '',
1096                      '\\begin_layout Standard',
1097                      '', '', '\\backslash',
1098                      ipachar,
1099                      '\\end_layout', '',
1100                      '\\end_inset', '',
1101                      after]
1102             document.body[i: i+1] = subst
1103             i = i + len(subst)
1104         else:
1105             i = i + 1
1106     if found:
1107         add_to_preamble(document, "\\usepackage{tone}")
1108
1109
1110 def revert_minionpro(document):
1111     " Revert native MinionPro font definition to LaTeX " 
1112
1113     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1114         i = find_token(document.header, "\\font_roman minionpro", 0)
1115         if i != -1:
1116             osf = False
1117             j = find_token(document.header, "\\font_osf true", 0)
1118             if j != -1:
1119                 osf = True
1120             preamble = "\\usepackage"
1121             if osf:
1122                 document.header[j] = "\\font_osf false"
1123             else:
1124                 preamble += "[lf]"
1125             preamble += "{MinionPro}"
1126             add_to_preamble(document, [preamble])
1127             document.header[i] = "\\font_roman default"
1128
1129
1130 def revert_mathfonts(document):
1131     " Revert native math font definitions to LaTeX " 
1132
1133     i = find_token(document.header, "\\font_math", 0)
1134     if i == -1:
1135        return
1136     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1137         val = get_value(document.header, "\\font_math", i)
1138         if val == "eulervm":
1139             add_to_preamble(document, "\\usepackage{eulervm}")
1140         elif val == "default":
1141             mathfont_dict = {
1142             "lmodern":  "\\renewcommand{\\rmdefault}{lmr}",
1143             "minionpro":  "\\usepackage[onlytext,lf]{MinionPro}",
1144             "minionpro-osf":  "\\usepackage[onlytext]{MinionPro}",
1145             "palatino":  "\\renewcommand{\\rmdefault}{ppl}",
1146             "palatino-osf":  "\\renewcommand{\\rmdefault}{pplj}",
1147             "times":  "\\renewcommand{\\rmdefault}{ptm}",
1148             "utopia":  "\\renewcommand{\\rmdefault}{futs}",
1149             "utopia-osf":  "\\renewcommand{\\rmdefault}{futj}",
1150             }
1151             j = find_token(document.header, "\\font_roman", 0)
1152             if j != -1:
1153                 rm = get_value(document.header, "\\font_roman", j)
1154                 k = find_token(document.header, "\\font_osf true", 0)
1155                 if k != -1:
1156                     rm += "-osf"
1157                 if rm in mathfont_dict.keys():
1158                     add_to_preamble(document, mathfont_dict[rm])
1159                     document.header[j] = "\\font_roman default"
1160                     if k != -1:
1161                         document.header[k] = "\\font_osf false"
1162     del document.header[i]
1163
1164
1165 def revert_mdnomath(document):
1166     " Revert mathdesign and fourier without math " 
1167
1168     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1169         mathdesign_dict = {
1170         "md-charter": "mdbch",
1171         "md-utopia": "mdput",
1172         "md-garamond": "mdugm"
1173         }
1174         i = find_token(document.header, "\\font_roman", 0)
1175         if i == -1:
1176             return
1177         val = get_value(document.header, "\\font_roman", i)
1178         if val in mathdesign_dict.keys():
1179             j = find_token(document.header, "\\font_math", 0)
1180             if j == -1:
1181                 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1182             mval = get_value(document.header, "\\font_math", j)
1183             if mval == "default":
1184                 document.header[i] = "\\font_roman default"
1185                 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1186             else:
1187                 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1188
1189
1190 def convert_mdnomath(document):
1191     " Change mathdesign font name " 
1192
1193     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1194         mathdesign_dict = {
1195         "mdbch":  "md-charter",
1196         "mdput":  "md-utopia",
1197         "mdugm":  "md-garamond"
1198         }
1199         i = find_token(document.header, "\\font_roman", 0)
1200         if i == -1:
1201             return
1202         val = get_value(document.header, "\\font_roman", i)
1203         if val in mathdesign_dict.keys():
1204              document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1205
1206
1207 def revert_newtxmath(document):
1208     " Revert native newtxmath definitions to LaTeX " 
1209
1210     i = find_token(document.header, "\\font_math", 0)
1211     if i == -1:
1212        return
1213     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1214         val = get_value(document.header, "\\font_math", i)
1215         mathfont_dict = {
1216         "libertine-ntxm":  "\\usepackage[libertine]{newtxmath}",
1217         "minion-ntxm":  "\\usepackage[minion]{newtxmath}",
1218         "newtxmath":  "\\usepackage{newtxmath}",
1219         }
1220         if val in mathfont_dict.keys():
1221             add_to_preamble(document, mathfont_dict[val])
1222             document.header[i] = "\\font_math auto"
1223
1224
1225 def revert_biolinum(document):
1226     " Revert native biolinum font definition to LaTeX " 
1227
1228     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
1229         i = find_token(document.header, "\\font_sans biolinum", 0)
1230         if i != -1:
1231             osf = False
1232             j = find_token(document.header, "\\font_osf true", 0)
1233             if j != -1:
1234                 osf = True
1235             preamble = "\\usepackage"
1236             if not osf:
1237                 preamble += "[lf]"
1238             preamble += "{biolinum-type1}"
1239             add_to_preamble(document, [preamble])
1240             document.header[i] = "\\font_sans default"
1241
1242
1243 def revert_uop(document):
1244     " Revert native URW Classico (Optima) font definition to LaTeX "
1245
1246     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1247         i = find_token(document.header, "\\font_sans uop", 0)
1248         if i != -1:
1249                 preamble = "\\renewcommand{\\sfdefault}{uop}"
1250                 add_to_preamble(document, [preamble])
1251                 document.header[i] = "\\font_sans default"
1252
1253
1254 def convert_latexargs(document):
1255     " Convert InsetArgument to new syntax "
1256
1257     if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1258         # nothing to do.
1259         return
1260
1261     # A list of layouts (document classes) with only optional or no arguments.
1262     # These can be safely converted to the new syntax
1263     # (I took the liberty to add some of my personal layouts/modules here; JSP)
1264     safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1265                     "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1266                     "arab-article", "armenian-article", "article-beamer", "article",
1267                     "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1268                     "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1269                     "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1270                     "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1271                     "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1272                     "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1273                     "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1274                     "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1275                     "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1276                     "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1277                     "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1278                     "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1279                     "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1280                     "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1281                     "tbook", "treport", "tufte-book", "tufte-handout"]
1282     # A list of "safe" modules, same as above
1283     safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1284                     "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1285                     "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1286                     "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1287                     "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1288                     "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1289                     "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1290                     "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1291     # Modules we need to take care of
1292     caveat_modules = ["initials"]
1293     # information about the relevant styles in caveat_modules (number of opt and req args)
1294     # use this if we get more caveat_modules. For now, use hard coding (see below).
1295     # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1296
1297     # Is this a known safe layout?
1298     safe_layout = document.textclass in safe_layouts
1299     if not safe_layout:
1300         document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1301                          "Please check if short title insets have been converted correctly."
1302                          % document.textclass)
1303     # Do we use unsafe or unknown modules
1304     mods = document.get_module_list()
1305     unknown_modules = False
1306     used_caveat_modules = list()
1307     for mod in mods:
1308         if mod in safe_modules:
1309             continue
1310         if mod in caveat_modules:
1311             used_caveat_modules.append(mod)
1312             continue
1313         unknown_modules = True
1314         document.warning("Lyx2lyx knows nothing about module '%s'. "
1315                          "Please check if short title insets have been converted correctly."
1316                          % mod)
1317
1318     i = 0
1319     while True:
1320         i = find_token(document.body, "\\begin_inset Argument", i)
1321         if i == -1:
1322             return
1323
1324         if not safe_layout or unknown_modules:
1325             # We cannot do more here since we have no access to this layout.
1326             # InsetArgument itself will do the real work
1327             # (see InsetArgument::updateBuffer())
1328             document.body[i] = "\\begin_inset Argument 999"
1329             i = i + 1
1330             continue
1331         
1332         # Find containing paragraph layout
1333         parent = get_containing_layout(document.body, i)
1334         if parent == False:
1335             document.warning("Malformed lyx document: Can't find parent paragraph layout")
1336             i = i + 1
1337             continue
1338         parbeg = parent[1]
1339         parend = parent[2]
1340         allowed_opts = -1
1341         first_req = -1
1342         if len(used_caveat_modules) > 0:
1343             # We know for now that this must be the initials module with the Initial layout
1344             # If we get more such modules, we need some automating.
1345             if parent[0] == "Initial":
1346                 # Layout has 1 opt and 1 req arg.
1347                 # Count the actual arguments
1348                 actualargs = 0
1349                 for p in range(parbeg, parend):
1350                     if document.body[p] == "\\begin_inset Argument":
1351                         actualargs += 1
1352                 if actualargs == 1:
1353                     allowed_opts = 0
1354                     first_req = 2
1355         # Collect all arguments in this paragraph
1356         argnr = 0
1357         for p in range(parbeg, parend):
1358             if document.body[p] == "\\begin_inset Argument":
1359                 argnr += 1
1360                 if allowed_opts != -1:
1361                     # We have less arguments than opt + required.
1362                     # required must take precedence.
1363                     if argnr > allowed_opts and argnr < first_req:
1364                         argnr = first_req
1365                 document.body[p] = "\\begin_inset Argument %d" % argnr
1366         i = i + 1
1367
1368
1369 def revert_latexargs(document):
1370     " Revert InsetArgument to old syntax "
1371
1372     i = 0
1373     rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1374     args = dict()
1375     while True:
1376         # Search for Argument insets
1377         i = find_token(document.body, "\\begin_inset Argument", i)
1378         if i == -1:
1379             return
1380         m = rx.match(document.body[i])
1381         if not m:
1382             # No ID: inset already reverted
1383             i = i + 1
1384             continue
1385         # Find containing paragraph layout
1386         parent = get_containing_layout(document.body, i)
1387         if parent == False:
1388             document.warning("Malformed lyx document: Can't find parent paragraph layout")
1389             i = i + 1
1390             continue
1391         parbeg = parent[1]
1392         parend = parent[2]
1393         realparbeg = parent[3]
1394         # Collect all arguments in this paragraph 
1395         realparend = parend
1396         for p in range(parbeg, parend):
1397             m = rx.match(document.body[p])
1398             if m:
1399                 val = int(m.group(1))
1400                 j = find_end_of_inset(document.body, p)
1401                 # Revert to old syntax
1402                 document.body[p] = "\\begin_inset Argument"
1403                 if j == -1:
1404                     document.warning("Malformed lyx document: Can't find end of Argument inset")
1405                     continue
1406                 if val > 0:
1407                     args[val] = document.body[p : j + 1]
1408                 # Adjust range end
1409                 realparend = realparend - len(document.body[p : j + 1])
1410                 # Remove arg inset at this position
1411                 del document.body[p : j + 1]
1412             if p >= realparend:
1413                 break
1414         # Now sort the arg insets
1415         subst = [""]
1416         for f in sorted(args):
1417             subst += args[f]
1418             del args[f]
1419         # Insert the sorted arg insets at paragraph begin
1420         document.body[realparbeg : realparbeg] = subst
1421
1422         i = realparbeg + 1 + len(subst)
1423
1424
1425 def revert_Argument_to_TeX_brace(document, line, n, nmax, environment):
1426     '''
1427     Reverts an InsetArgument to TeX-code
1428     usage:
1429     revert_Argument_to_TeX_brace(document, LineOfBeginLayout, StartArgument, EndArgument, isEnvironment)
1430     LineOfBeginLayout is the line  of the \begin_layout statement
1431     StartArgument is the number of the first argument that needs to be converted
1432     EndArgument is the number of the last argument that needs to be converted or the last defined one
1433     isEnvironment must be true, if the layout id for a LaTeX environment
1434     '''
1435     lineArg = 0
1436     while lineArg != -1 and n < nmax + 1:
1437       lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
1438       if lineArg != -1:
1439         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
1440         # we have to assure that no other inset is in the Argument
1441         beginInset = find_token(document.body, "\\begin_inset", beginPlain)
1442         endInset = find_token(document.body, "\\end_inset", beginPlain)
1443         k = beginPlain + 1
1444         l = k
1445         while beginInset < endInset and beginInset != -1:
1446           beginInset = find_token(document.body, "\\begin_inset", k)
1447           endInset = find_token(document.body, "\\end_inset", l)
1448           k = beginInset + 1
1449           l = endInset + 1
1450         if environment == False:
1451           document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
1452           del(document.body[lineArg : beginPlain + 1])
1453         else:
1454           document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
1455           document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
1456         n = n + 1
1457
1458
1459 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment):
1460     '''
1461     Converts TeX code for mandatory arguments to an InsetArgument
1462     The conversion of TeX code for optional arguments must be done with another routine
1463     !!! Be careful if the braces are different in your case as expected here:
1464     - "}{" separates mandatory arguments of commands
1465     - "}" + "{" separates mandatory arguments of commands
1466     - "}" + " " + "{" separates mandatory arguments of commands
1467     - { and } surround a mandatory argument of an environment
1468     usage:
1469     convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment)
1470     LineOfBeginLayout/Inset is the line  of the \begin_layout or \begin_inset statement
1471     StartArgument is the number of the first ERT that needs to be converted
1472     EndArgument is the number of the last ERT that needs to be converted
1473     isInset must be true, if braces inside an InsetLayout needs to be converted
1474     isEnvironment must be true, if the layout is for a LaTeX environment
1475     
1476     Todo: this routine can currently handle only one mandatory argument of environments
1477     '''
1478     lineERT = line
1479     endn = line
1480     loop = 1
1481     while lineERT != -1 and n < nmax + 1:
1482       lineERT = find_token(document.body, "\\begin_inset ERT", lineERT)
1483       if environment == False and lineERT != -1:
1484         bracePair = find_token(document.body, "}{", lineERT)
1485         # assure that the "}{" is in this ERT
1486         if bracePair == lineERT + 5:
1487           end = find_token(document.body, "\\end_inset", bracePair)
1488           document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1489           if loop == 1:
1490             # in the case that n > 1 we have optional arguments before
1491             # therefore detect them if any
1492             if n > 1:
1493               # first check if there is an argument
1494               lineArg = find_token(document.body, "\\begin_inset Argument", line)
1495               if lineArg < lineERT and lineArg != -1:
1496                 # we have an argument, so now search backwards for its end
1497                 # we must now assure that we don't find other insets like e.g. a newline
1498                 endInsetArg = lineERT
1499                 endLayoutArg = endInsetArg
1500                 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1501                   endInsetArg = endInsetArg - 1
1502                   endLayoutArg = endInsetArg
1503                   endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1504                   endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1505                 line = endInsetArg + 1
1506             if inset == False:
1507               document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1508             else:
1509               document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1510           else:
1511             document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1512           n = n + 1
1513           endn = end
1514           loop = loop + 1
1515         # now check the case that we have "}" + "{" in two ERTs
1516         else:
1517           endBrace = find_token(document.body, "}", lineERT)
1518           if endBrace == lineERT + 5:
1519             beginBrace = find_token(document.body, "{", endBrace)
1520             # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
1521             if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
1522               end = find_token(document.body, "\\end_inset", beginBrace)
1523               document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1524               if loop == 1:
1525                 # in the case that n > 1 we have optional arguments before
1526                 # therefore detect them if any
1527                 if n > 1:
1528                   # first check if there is an argument
1529                   lineArg = find_token(document.body, "\\begin_inset Argument", line)
1530                   if lineArg < lineERT and lineArg != -1:
1531                     # we have an argument, so now search backwards for its end
1532                     # we must now assure that we don't find other insets like e.g. a newline
1533                     endInsetArg = lineERT
1534                     endLayoutArg = endInsetArg
1535                     while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1536                       endInsetArg = endInsetArg - 1
1537                       endLayoutArg = endInsetArg
1538                       endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1539                       endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1540                     line = endInsetArg + 1
1541                 if inset == False:
1542                   document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1543                 else:
1544                   document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1545               else:
1546                 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1547               n = n + 1
1548               loop = loop + 1
1549               # set the line where the next argument will be inserted
1550               if beginBrace == endBrace + 11:
1551                 endn = end - 11
1552               else:
1553                 endn = end - 12
1554           else:
1555             lineERT = lineERT + 1
1556       if environment == True and lineERT != -1:
1557         opening = find_token(document.body, "{", lineERT)
1558         if opening == lineERT + 5: # assure that the "{" is in this ERT
1559           end = find_token(document.body, "\\end_inset", opening)
1560           document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1561           n = n + 1
1562           lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT)
1563           closing = find_token(document.body, "}", lineERT2)
1564           if closing == lineERT2 + 5: # assure that the "}" is in this ERT
1565             end2 = find_token(document.body, "\\end_inset", closing)
1566             document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
1567         else:
1568           lineERT = lineERT + 1
1569
1570
1571 def revert_IEEEtran(document):
1572   '''
1573   Reverts InsetArgument of
1574   Page headings
1575   Biography
1576   Biography without photo
1577   to TeX-code
1578   '''
1579   if document.textclass == "IEEEtran":
1580     i = 0
1581     i2 = 0
1582     j = 0
1583     k = 0
1584     while True:
1585       if i != -1:
1586         i = find_token(document.body, "\\begin_layout Page headings", i)
1587       if i != -1:
1588         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1589         i = i + 1
1590       if i2 != -1:
1591         i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1592       if i2 != -1:
1593         revert_Argument_to_TeX_brace(document, i2, 1, 1, False)
1594         i2 = i2 + 1
1595       if j != -1:
1596         j = find_token(document.body, "\\begin_layout Biography without photo", j)
1597       if j != -1:
1598         revert_Argument_to_TeX_brace(document, j, 1, 1, True)
1599         j = j + 1
1600       if k != -1:
1601         k = find_token(document.body, "\\begin_layout Biography", k)
1602         kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1603         if k == kA and k != -1:
1604           k = k + 1
1605           continue
1606       if k != -1:
1607         # start with the second argument, therefore 2
1608         revert_Argument_to_TeX_brace(document, k, 2, 2, True)
1609         k = k + 1
1610       if i == -1 and i2 == -1 and j == -1 and k == -1:
1611         return
1612
1613
1614 def revert_IEEEtran_2(document):
1615   '''
1616   Reverts Flex Paragraph Start to TeX-code
1617   '''
1618   if document.textclass == "IEEEtran":
1619     begin = 0
1620     while True:
1621       if begin != -1:
1622         begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1623       if begin != -1:
1624         end1 = find_end_of_inset(document.body, begin)
1625         document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1626         document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1627         begin = begin + 5
1628       if begin == -1:
1629         return
1630
1631
1632 def convert_IEEEtran(document):
1633   '''
1634   Converts ERT of
1635   Page headings
1636   Biography
1637   Biography without photo
1638   to InsetArgument
1639   '''
1640   if document.textclass == "IEEEtran":
1641     i = 0
1642     j = 0
1643     k = 0
1644     while True:
1645       if i != -1:
1646         i = find_token(document.body, "\\begin_layout Page headings", i)
1647       if i != -1:
1648         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1649         i = i + 1
1650       if j != -1:
1651         j = find_token(document.body, "\\begin_layout Biography without photo", j)
1652       if j != -1:
1653         convert_TeX_brace_to_Argument(document, j, 1, 1, False, True)
1654         j = j + 1
1655       if k != -1:
1656         # assure that we don't handle Biography Biography without photo
1657         k = find_token(document.body, "\\begin_layout Biography", k)
1658         kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1659       if k == kA and k != -1:
1660         k = k + 1
1661         continue
1662       if k != -1:
1663         # the argument we want to convert is the second one
1664         convert_TeX_brace_to_Argument(document, k, 2, 2, False, True)
1665         k = k + 1
1666       if i == -1 and j == -1 and k == -1:
1667         return
1668
1669
1670 def revert_AASTeX(document):
1671   " Reverts InsetArgument of Altaffilation to TeX-code "
1672   if document.textclass == "aastex":
1673     i = 0
1674     while True:
1675       if i != -1:
1676         i = find_token(document.body, "\\begin_layout Altaffilation", i)
1677       if i != -1:
1678         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1679         i = i + 1
1680       if i == -1:
1681         return
1682
1683
1684 def convert_AASTeX(document):
1685   " Converts ERT of Altaffilation to InsetArgument "
1686   if document.textclass == "aastex":
1687     i = 0
1688     while True:
1689       if i != -1:
1690         i = find_token(document.body, "\\begin_layout Altaffilation", i)
1691       if i != -1:
1692         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1693         i = i + 1
1694       if i == -1:
1695         return
1696
1697
1698 def revert_AGUTeX(document):
1699   " Reverts InsetArgument of Author affiliation to TeX-code "
1700   if document.textclass == "agutex":
1701     i = 0
1702     while True:
1703       if i != -1:
1704         i = find_token(document.body, "\\begin_layout Author affiliation", i)
1705       if i != -1:
1706         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1707         i = i + 1
1708       if i == -1:
1709         return
1710
1711
1712 def convert_AGUTeX(document):
1713   " Converts ERT of Author affiliation to InsetArgument "
1714   if document.textclass == "agutex":
1715     i = 0
1716     while True:
1717       if i != -1:
1718         i = find_token(document.body, "\\begin_layout Author affiliation", i)
1719       if i != -1:
1720         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1721         i = i + 1
1722       if i == -1:
1723         return
1724
1725
1726 def revert_IJMP(document):
1727   " Reverts InsetArgument of MarkBoth to TeX-code "
1728   if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1729     i = 0
1730     while True:
1731       if i != -1:
1732         i = find_token(document.body, "\\begin_layout MarkBoth", i)
1733       if i != -1:
1734         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1735         i = i + 1
1736       if i == -1:
1737         return
1738
1739
1740 def convert_IJMP(document):
1741   " Converts ERT of MarkBoth to InsetArgument "
1742   if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1743     i = 0
1744     while True:
1745       if i != -1:
1746         i = find_token(document.body, "\\begin_layout MarkBoth", i)
1747       if i != -1:
1748         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1749         i = i + 1
1750       if i == -1:
1751         return
1752
1753
1754 def revert_SIGPLAN(document):
1755   " Reverts InsetArguments of SIGPLAN to TeX-code "
1756   if document.textclass == "sigplanconf":
1757     i = 0
1758     j = 0
1759     while True:
1760       if i != -1:
1761         i = find_token(document.body, "\\begin_layout Conference", i)
1762       if i != -1:
1763         revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1764         i = i + 1
1765       if j != -1:
1766         j = find_token(document.body, "\\begin_layout Author", j)
1767       if j != -1:
1768         revert_Argument_to_TeX_brace(document, j, 1, 2, False)
1769         j = j + 1
1770       if i == -1 and j == -1:
1771         return
1772
1773
1774 def convert_SIGPLAN(document):
1775   " Converts ERT of SIGPLAN to InsetArgument "
1776   if document.textclass == "sigplanconf":
1777     i = 0
1778     j = 0
1779     while True:
1780       if i != -1:
1781         i = find_token(document.body, "\\begin_layout Conference", i)
1782       if i != -1:
1783         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1784         i = i + 1
1785       if j != -1:
1786         j = find_token(document.body, "\\begin_layout Author", j)
1787       if j != -1:
1788         convert_TeX_brace_to_Argument(document, j, 1, 2, False, False)
1789         j = j + 1
1790       if i == -1 and j == -1:
1791         return
1792
1793
1794 def revert_SIGGRAPH(document):
1795   " Reverts InsetArgument of Flex CRcat to TeX-code "
1796   if document.textclass == "acmsiggraph":
1797     i = 0
1798     while True:
1799       if i != -1:
1800         i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1801       if i != -1:
1802         revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1803         i = i + 1
1804       if i == -1:
1805         return
1806
1807
1808 def convert_SIGGRAPH(document):
1809   " Converts ERT of Flex CRcat to InsetArgument "
1810   if document.textclass == "acmsiggraph":
1811     i = 0
1812     while True:
1813       if i != -1:
1814         i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1815       if i != -1:
1816         convert_TeX_brace_to_Argument(document, i, 1, 3, True, False)
1817         i = i + 1
1818       if i == -1:
1819         return
1820
1821
1822 def revert_EuropeCV(document):
1823   " Reverts InsetArguments of europeCV to TeX-code "
1824   if document.textclass == "europecv":
1825     i = 0
1826     j = 0
1827     k = 0
1828     m = 0
1829     while True:
1830       if i != -1:
1831         i = find_token(document.body, "\\begin_layout Item", i)
1832       if i != -1:
1833         revert_Argument_to_TeX_brace(document, i, 2, 2, False)
1834         i = i + 1
1835       if j != -1:
1836         j = find_token(document.body, "\\begin_layout BulletedItem", j)
1837       if j != -1:
1838         revert_Argument_to_TeX_brace(document, j, 2, 2, False)
1839         j = j + 1
1840       if k != -1:
1841         k = find_token(document.body, "\\begin_layout Language", k)
1842       if k != -1:
1843         revert_Argument_to_TeX_brace(document, k, 2, 6, False)
1844         k = k + 1
1845       if m != -1:
1846         m = find_token(document.body, "\\begin_layout LastLanguage", m)
1847       if m != -1:
1848         revert_Argument_to_TeX_brace(document, m, 2, 6, False)
1849         m = m + 1
1850       if i == -1 and j == -1 and k == -1 and m == -1:
1851         return
1852
1853
1854 def convert_EuropeCV(document):
1855   " Converts ERT of europeCV to InsetArgument "
1856   if document.textclass == "europecv":
1857     i = 0
1858     j = 0
1859     k = 0
1860     m = 0
1861     while True:
1862       if i != -1:
1863         i = find_token(document.body, "\\begin_layout Item", i)
1864       if i != -1:
1865         convert_TeX_brace_to_Argument(document, i, 2, 2, False, False)
1866         i = i + 1
1867       if j != -1:
1868         j = find_token(document.body, "\\begin_layout BulletedItem", j)
1869       if j != -1:
1870         convert_TeX_brace_to_Argument(document, j, 2, 2, False, False)
1871         j = j + 1
1872       if k != -1:
1873         k = find_token(document.body, "\\begin_layout Language", k)
1874       if k != -1:
1875         convert_TeX_brace_to_Argument(document, k, 2, 6, False, False)
1876         k = k + 1
1877       if m != -1:
1878         m = find_token(document.body, "\\begin_layout LastLanguage", m)
1879       if m != -1:
1880         convert_TeX_brace_to_Argument(document, m, 2, 6, False, False)
1881         m = m + 1
1882       if i == -1 and j == -1 and k == -1 and m == -1:
1883         return
1884
1885
1886 def revert_ModernCV(document):
1887   " Reverts InsetArguments of modernCV to TeX-code "
1888   if document.textclass == "moderncv":
1889     i = 0
1890     j = 0
1891     k = 0
1892     m = 0
1893     o = 0
1894     while True:
1895       if i != -1:
1896         i = find_token(document.body, "\\begin_layout DoubleItem", i)
1897       if i != -1:
1898         revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1899         i = i + 1
1900       if j != -1:
1901         j = find_token(document.body, "\\begin_layout Entry", j)
1902       if j != -1:
1903         revert_Argument_to_TeX_brace(document, j, 1, 5, False)
1904         j = j + 1
1905       if k != -1:
1906         k = find_token(document.body, "\\begin_layout Item", k)
1907       if k != -1:
1908         revert_Argument_to_TeX_brace(document, k, 1, 1, False)
1909         k = k + 1
1910       if m != -1:
1911         m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1912       if m != -1:
1913         revert_Argument_to_TeX_brace(document, m, 1, 2, False)
1914         document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1915         m = m + 1
1916       if o != -1:
1917         o = find_token(document.body, "\\begin_layout DoubleItem", o)
1918       if o != -1:
1919         revert_Argument_to_TeX_brace(document, o, 1, 3, False)
1920         document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
1921         o = o + 1
1922       if i == -1 and j == -1 and k == -1 and m == -1 and o == -1:
1923         return
1924
1925
1926 def convert_ModernCV(document):
1927   " Converts ERT of modernCV to InsetArgument "
1928   if document.textclass == "moderncv":
1929     i = 0
1930     j = 0
1931     k = 0
1932     m = 0
1933     o = 0
1934     while True:
1935       if i != -1:
1936         i = find_token(document.body, "\\begin_layout DoubleItem", i)
1937       if i != -1:
1938         convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1939         document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
1940         i = i + 1
1941       if j != -1:
1942         j = find_token(document.body, "\\begin_layout Entry", j)
1943       if j != -1:
1944         convert_TeX_brace_to_Argument(document, j, 1, 5, False, False)
1945         j = j + 1
1946       if k != -1:
1947         k = find_token(document.body, "\\begin_layout Item", k)
1948       if k != -1:
1949         convert_TeX_brace_to_Argument(document, k, 1, 1, False, False)
1950         k = k + 1
1951       if m != -1:
1952         m = find_token(document.body, "\\begin_layout Language", m)
1953       if m != -1:
1954         convert_TeX_brace_to_Argument(document, m, 1, 2, False, False)
1955         m = m + 1
1956       if i == -1 and j == -1 and k == -1 and m == -1:
1957         return
1958
1959
1960 def revert_Initials(document):
1961   " Reverts InsetArgument of Initial to TeX-code "
1962   i = 0
1963   while True:
1964     if i != -1:
1965       i = find_token(document.body, "\\begin_layout Initial", i)
1966     if i != -1:
1967       # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
1968       revert_Argument_to_TeX_brace(document, i, 3, 3, False)
1969       i = i + 1
1970     if i == -1:
1971       return
1972
1973
1974 def convert_Initials(document):
1975   " Converts ERT of Initial to InsetArgument "
1976   i = 0
1977   while True:
1978     if i != -1:
1979       i = find_token(document.body, "\\begin_layout Initial", i)
1980     if i != -1:
1981       convert_TeX_brace_to_Argument(document, i, 3, 3, False, False)
1982       i = i + 1
1983     if i == -1:
1984       return
1985
1986
1987 def revert_literate(document):
1988     " Revert Literate document to old format "
1989     if del_token(document.header, "noweb", 0):
1990       document.textclass = "literate-" + document.textclass
1991       i = 0
1992       while True:
1993         i = find_token(document.body, "\\begin_layout Chunk", i)
1994         if i == -1:
1995           break
1996         document.body[i] = "\\begin_layout Scrap"
1997         i = i + 1
1998
1999
2000 def convert_literate(document):
2001     " Convert Literate document to new format"
2002     i = find_token(document.header, "\\textclass", 0)    
2003     if (i != -1) and "literate-" in document.header[i]:
2004       document.textclass = document.header[i].replace("\\textclass literate-", "")
2005       j = find_token(document.header, "\\begin_modules", 0)
2006       if (j != -1):
2007         document.header.insert(j + 1, "noweb")
2008       else:
2009         document.header.insert(i + 1, "\\end_modules")
2010         document.header.insert(i + 1, "noweb")
2011         document.header.insert(i + 1, "\\begin_modules")
2012       i = 0
2013       while True:
2014         i = find_token(document.body, "\\begin_layout Scrap", i)
2015         if i == -1:
2016           break
2017         document.body[i] = "\\begin_layout Chunk"
2018         i = i + 1
2019
2020
2021 def revert_itemargs(document):
2022     " Reverts \\item arguments to TeX-code "
2023     i = 0
2024     while True:
2025         i = find_token(document.body, "\\begin_inset Argument item:", i)
2026         if i == -1:
2027             return
2028         j = find_end_of_inset(document.body, i)
2029         # Find containing paragraph layout
2030         parent = get_containing_layout(document.body, i)
2031         if parent == False:
2032             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2033             i = i + 1
2034             continue
2035         parbeg = parent[3]
2036         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2037         endPlain = find_end_of_layout(document.body, beginPlain)
2038         content = document.body[beginPlain + 1 : endPlain]
2039         del document.body[i:j+1]
2040         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2041         document.body[parbeg : parbeg] = subst
2042         i = i + 1
2043
2044
2045 def revert_garamondx_newtxmath(document):
2046     " Revert native garamond newtxmath definition to LaTeX " 
2047
2048     i = find_token(document.header, "\\font_math", 0)
2049     if i == -1:
2050        return
2051     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
2052         val = get_value(document.header, "\\font_math", i)
2053         if val == "garamondx-ntxm":
2054             add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2055             document.header[i] = "\\font_math auto"
2056
2057
2058 def revert_garamondx(document):
2059     " Revert native garamond font definition to LaTeX " 
2060
2061     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
2062         i = find_token(document.header, "\\font_roman garamondx", 0)
2063         if i != -1:
2064             osf = False
2065             j = find_token(document.header, "\\font_osf true", 0)
2066             if j != -1:
2067                 osf = True
2068             preamble = "\\usepackage"
2069             if osf:
2070                 preamble += "[osfI]"
2071             preamble += "{garamondx}"
2072             add_to_preamble(document, [preamble])
2073             document.header[i] = "\\font_roman default"
2074
2075
2076 def convert_beamerargs(document):
2077     " Converts beamer arguments to new layout "
2078     
2079     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2080     if document.textclass not in beamer_classes:
2081         return
2082
2083     shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2084     list_layouts = ["Itemize", "Enumerate", "Description"]
2085     rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2086
2087     i = 0
2088     while True:
2089         i = find_token(document.body, "\\begin_inset Argument", i)
2090         if i == -1:
2091             return
2092         # Find containing paragraph layout
2093         parent = get_containing_layout(document.body, i)
2094         if parent == False:
2095             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2096             i = i + 1
2097             continue
2098         parbeg = parent[1]
2099         parend = parent[2]
2100         layoutname = parent[0]
2101         for p in range(parbeg, parend):
2102             if layoutname in shifted_layouts:
2103                 m = rx.match(document.body[p])
2104                 if m:
2105                     argnr = int(m.group(1))
2106                     argnr += 1
2107                     document.body[p] = "\\begin_inset Argument %d" % argnr
2108             if layoutname == "AgainFrame":
2109                 m = rx.match(document.body[p])
2110                 if m:
2111                     document.body[p] = "\\begin_inset Argument 3"
2112                     if document.body[p + 4] == "\\begin_inset ERT":
2113                         if document.body[p + 9].startswith("<"):
2114                             # This is an overlay specification
2115                             # strip off the <
2116                             document.body[p + 9] = document.body[p + 9][1:]
2117                             if document.body[p + 9].endswith(">"):
2118                                 # strip off the >
2119                                 document.body[p + 9] = document.body[p + 9][:-1]
2120                                 # Shift this one
2121                                 document.body[p] = "\\begin_inset Argument 2"
2122             if layoutname in list_layouts:
2123                 m = rx.match(document.body[p])
2124                 if m:
2125                     if m.group(1) == "1":
2126                         if document.body[p + 4] == "\\begin_inset ERT":
2127                             if document.body[p + 9].startswith("<"):
2128                                 # This is an overlay specification
2129                                 # strip off the <
2130                                 document.body[p + 9] = document.body[p + 9][1:]
2131                                 if document.body[p + 9].endswith(">"):
2132                                     # strip off the >
2133                                     document.body[p + 9] = document.body[p + 9][:-1]
2134                         elif layoutname != "Itemize":
2135                             # Shift this one
2136                             document.body[p] = "\\begin_inset Argument 2"
2137         i = i + 1
2138
2139
2140 def convert_againframe_args(document):
2141     " Converts beamer AgainFrame to new layout "
2142
2143     # FIXME: This currently only works if the arguments are in one single ERT
2144     
2145     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2146     if document.textclass not in beamer_classes:
2147         return
2148    
2149     i = 0
2150     while True:
2151         i = find_token(document.body, "\\begin_layout AgainFrame", i)
2152         if i == -1:
2153             break
2154         parent = get_containing_layout(document.body, i)
2155         if parent[1] != i:
2156             document.warning("Wrong parent layout!")
2157         j = parent[2]
2158         parbeg = parent[3]
2159         if i != -1:
2160             if document.body[parbeg] == "\\begin_inset ERT":
2161                 ertcont = parbeg + 5
2162                 if document.body[ertcont].startswith("[<"):
2163                     # This is a default overlay specification
2164                     # strip off the [<
2165                     document.body[ertcont] = document.body[ertcont][2:]
2166                     if document.body[ertcont].endswith(">]"):
2167                         # strip off the >]
2168                         document.body[ertcont] = document.body[ertcont][:-2]
2169                     elif document.body[ertcont].endswith("]"):
2170                         # divide the args
2171                         tok = document.body[ertcont].find('>][')
2172                         if tok != -1:
2173                             subst = [document.body[ertcont][:tok],
2174                                      '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2175                                      'status collapsed', '', '\\begin_layout Plain Layout',
2176                                      document.body[ertcont][tok + 3:-1]]
2177                             document.body[ertcont : ertcont + 1] = subst
2178                      # Convert to ArgInset
2179                     document.body[parbeg] = "\\begin_inset Argument 2"
2180                     i = j
2181                     continue
2182                 elif document.body[ertcont].startswith("<"):
2183                     # This is an overlay specification
2184                     # strip off the <
2185                     document.body[ertcont] = document.body[ertcont][1:]
2186                     if document.body[ertcont].endswith(">"):
2187                         # strip off the >
2188                         document.body[ertcont] = document.body[ertcont][:-1]
2189                         # Convert to ArgInset
2190                         document.body[parbeg] = "\\begin_inset Argument 1"
2191                     elif document.body[ertcont].endswith(">]"):
2192                         # divide the args
2193                         tok = document.body[ertcont].find('>[<')
2194                         if tok != -1:
2195                            document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2196                                                            '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2197                                                            'status collapsed', '', '\\begin_layout Plain Layout',
2198                                                            document.body[ertcont][tok + 3:-2]]
2199                         # Convert to ArgInset
2200                         document.body[parbeg] = "\\begin_inset Argument 1"
2201                     elif document.body[ertcont].endswith("]"):
2202                         # divide the args
2203                         tok = document.body[ertcont].find('>[<')
2204                         if tok != -1:
2205                            # divide the args
2206                            tokk = document.body[ertcont].find('>][')
2207                            if tokk != -1:
2208                                document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2209                                                                '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2210                                                                'status collapsed', '', '\\begin_layout Plain Layout',
2211                                                                document.body[ertcont][tok + 3:tokk],
2212                                                                '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2213                                                                'status collapsed', '', '\\begin_layout Plain Layout',
2214                                                                document.body[ertcont][tokk + 3:-1]]
2215                         else:
2216                             tokk = document.body[ertcont].find('>[')
2217                             if tokk != -1:
2218                                 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2219                                                                 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2220                                                                 'status collapsed', '', '\\begin_layout Plain Layout',
2221                                                                 document.body[ertcont][tokk + 2:-1]]
2222                         # Convert to ArgInset
2223                         document.body[parbeg] = "\\begin_inset Argument 1"
2224                     i = j
2225                     continue
2226                 elif document.body[ertcont].startswith("["):
2227                     # This is an ERT option
2228                     # strip off the [
2229                     document.body[ertcont] = document.body[ertcont][1:]
2230                     if document.body[ertcont].endswith("]"):
2231                         # strip off the ]
2232                         document.body[ertcont] = document.body[ertcont][:-1]
2233                         # Convert to ArgInset
2234                         document.body[parbeg] = "\\begin_inset Argument 3"
2235                     i = j
2236                     continue
2237         i = j
2238
2239
2240 def convert_corollary_args(document):
2241     " Converts beamer corrolary-style ERT arguments native InsetArgs "
2242     
2243     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2244     if document.textclass not in beamer_classes:
2245         return
2246    
2247     corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2248     for lay in corollary_layouts:
2249         i = 0
2250         while True:
2251             i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2252             if i == -1:
2253                 break
2254             parent = get_containing_layout(document.body, i)
2255             if parent[1] != i:
2256                 document.warning("Wrong parent layout!")
2257             j = parent[2]
2258             parbeg = parent[3]
2259             if i != -1:
2260                 if document.body[parbeg] == "\\begin_inset ERT":
2261                     ertcont = parbeg + 5
2262                     if document.body[ertcont].startswith("<"):
2263                         # This is an overlay specification
2264                         # strip off the <
2265                         document.body[ertcont] = document.body[ertcont][1:]
2266                         if document.body[ertcont].endswith(">"):
2267                             # strip off the >
2268                             document.body[ertcont] = document.body[ertcont][:-1]
2269                         elif document.body[ertcont].endswith("]"):
2270                             # divide the args
2271                             tok = document.body[ertcont].find('>[')
2272                             if tok != -1:
2273                                 subst = [document.body[ertcont][:tok],
2274                                          '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2275                                          'status collapsed', '', '\\begin_layout Plain Layout',
2276                                          document.body[ertcont][tok + 2:-1]]
2277                                 document.body[ertcont : ertcont + 1] = subst
2278                         # Convert to ArgInset
2279                         document.body[parbeg] = "\\begin_inset Argument 1"
2280                         i = j
2281                         continue
2282                     elif document.body[ertcont].startswith("["):
2283                         # This is an ERT option
2284                         # strip off the [
2285                         document.body[ertcont] = document.body[ertcont][1:]
2286                         if document.body[ertcont].endswith("]"):
2287                             # strip off the ]
2288                             document.body[ertcont] = document.body[ertcont][:-1]
2289                         # Convert to ArgInset
2290                         document.body[parbeg] = "\\begin_inset Argument 2"
2291                     i = j
2292                     continue
2293             i = j
2294
2295
2296
2297 def convert_quote_args(document):
2298     " Converts beamer quote style ERT args to native InsetArgs "
2299     
2300     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2301     if document.textclass not in beamer_classes:
2302         return
2303    
2304     quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2305     for lay in quote_layouts:
2306         i = 0
2307         while True:
2308             i = find_token(document.body, "\\begin_layout " + lay, i)
2309             if i == -1:
2310                 break
2311             parent = get_containing_layout(document.body, i)
2312             if parent[1] != i:
2313                 document.warning("Wrong parent layout!")
2314             j = parent[2]
2315             parbeg = parent[3]
2316             if i != -1:
2317                 if document.body[parbeg] == "\\begin_inset ERT":
2318                     if document.body[i + 6].startswith("<"):
2319                         # This is an overlay specification
2320                         # strip off the <
2321                         document.body[i + 6] = document.body[i + 6][1:]
2322                         if document.body[i + 6].endswith(">"):
2323                             # strip off the >
2324                             document.body[i + 6] = document.body[i + 6][:-1]
2325                             # Convert to ArgInset
2326                             document.body[i + 1] = "\\begin_inset Argument 1"
2327             i = j
2328
2329
2330 def revert_beamerargs(document):
2331     " Reverts beamer arguments to old layout "
2332     
2333     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2334     if document.textclass not in beamer_classes:
2335         return
2336
2337     i = 0
2338     list_layouts = ["Itemize", "Enumerate", "Description"]
2339     headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2340                 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2341     quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2342     corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2343     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2344
2345     while True:
2346         i = find_token(document.body, "\\begin_inset Argument", i)
2347         if i == -1:
2348             return
2349         # Find containing paragraph layout
2350         parent = get_containing_layout(document.body, i)
2351         if parent == False:
2352             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2353             i = i + 1
2354             continue
2355         parbeg = parent[1]
2356         parend = parent[2]
2357         realparbeg = parent[3]
2358         layoutname = parent[0]
2359         realparend = parend
2360         for p in range(parbeg, parend):
2361             if p >= realparend:
2362                 i = realparend
2363                 break
2364             if layoutname in headings:
2365                 m = rx.match(document.body[p])
2366                 if m:
2367                     argnr = m.group(1)
2368                     if argnr == "1":
2369                         # Find containing paragraph layout
2370                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2371                         endPlain = find_end_of_layout(document.body, beginPlain)
2372                         endInset = find_end_of_inset(document.body, p)
2373                         argcontent = document.body[beginPlain + 1 : endPlain]
2374                         # Adjust range end
2375                         realparend = realparend - len(document.body[p : endInset + 1])
2376                         # Remove arg inset
2377                         del document.body[p : endInset + 1]
2378                         if layoutname == "FrameSubtitle":
2379                             pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2380                         elif layoutname == "NoteItem":
2381                             pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2382                         elif layoutname.endswith('*'):
2383                             pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2384                         else:
2385                             pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2386                         secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2387                         if secarg != -1:
2388                             # Find containing paragraph layout
2389                             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2390                             endPlain = find_end_of_layout(document.body, beginPlain)
2391                             endInset = find_end_of_inset(document.body, secarg)
2392                             argcontent = document.body[beginPlain + 1 : endPlain]
2393                             # Adjust range end
2394                             realparend = realparend - len(document.body[secarg : endInset + 1])
2395                             del document.body[secarg : endInset + 1]
2396                             pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2397                         pre += put_cmd_in_ert("{")
2398                         document.body[parbeg] = "\\begin_layout Standard"
2399                         document.body[realparbeg : realparbeg] = pre
2400                         pe = find_end_of_layout(document.body, parbeg)
2401                         post = put_cmd_in_ert("}")
2402                         document.body[pe : pe] = post
2403                         realparend += len(pre) + len(post)
2404             if layoutname == "AgainFrame":
2405                 m = rx.match(document.body[p])
2406                 if m:
2407                     argnr = m.group(1)
2408                     if argnr == "3":
2409                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2410                         endPlain = find_end_of_layout(document.body, beginPlain)
2411                         endInset = find_end_of_inset(document.body, p)
2412                         content = document.body[beginPlain + 1 : endPlain]
2413                         # Adjust range end
2414                         realparend = realparend - len(document.body[p : endInset + 1])
2415                         # Remove arg inset
2416                         del document.body[p : endInset + 1]
2417                         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2418                         document.body[realparbeg : realparbeg] = subst
2419             if layoutname == "Overprint":
2420                 m = rx.match(document.body[p])
2421                 if m:
2422                     argnr = m.group(1)
2423                     if argnr == "1":
2424                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2425                         endPlain = find_end_of_layout(document.body, beginPlain)
2426                         endInset = find_end_of_inset(document.body, p)
2427                         content = document.body[beginPlain + 1 : endPlain]
2428                         # Adjust range end
2429                         realparend = realparend - len(document.body[p : endInset + 1])
2430                         # Remove arg inset
2431                         del document.body[p : endInset + 1]
2432                         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2433                         document.body[realparbeg : realparbeg] = subst
2434             if layoutname == "OverlayArea":
2435                 m = rx.match(document.body[p])
2436                 if m:
2437                     argnr = m.group(1)
2438                     if argnr == "2":
2439                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2440                         endPlain = find_end_of_layout(document.body, beginPlain)
2441                         endInset = find_end_of_inset(document.body, p)
2442                         content = document.body[beginPlain + 1 : endPlain]
2443                         # Adjust range end
2444                         realparend = realparend - len(document.body[p : endInset + 1])
2445                         # Remove arg inset
2446                         del document.body[p : endInset + 1]
2447                         subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2448                         document.body[realparbeg : realparbeg] = subst
2449             if layoutname in list_layouts:
2450                 m = rx.match(document.body[p])
2451                 if m:
2452                     argnr = m.group(1)
2453                     if argnr == "1":
2454                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2455                         endPlain = find_end_of_layout(document.body, beginPlain)
2456                         endInset = find_end_of_inset(document.body, p)
2457                         content = document.body[beginPlain + 1 : endPlain]
2458                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2459                         realparend = realparend + len(subst) - len(content)
2460                         document.body[beginPlain + 1 : endPlain] = subst
2461                     elif argnr == "item:1":
2462                         j = find_end_of_inset(document.body, i)
2463                         # Find containing paragraph layout
2464                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2465                         endPlain = find_end_of_layout(document.body, beginPlain)
2466                         content = document.body[beginPlain + 1 : endPlain]
2467                         del document.body[i:j+1]
2468                         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2469                         document.body[realparbeg : realparbeg] = subst
2470                     elif argnr == "item:2":
2471                         j = find_end_of_inset(document.body, i)
2472                         # Find containing paragraph layout
2473                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2474                         endPlain = find_end_of_layout(document.body, beginPlain)
2475                         content = document.body[beginPlain + 1 : endPlain]
2476                         del document.body[i:j+1]
2477                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2478                         document.body[realparbeg : realparbeg] = subst
2479             if layoutname in quote_layouts:
2480                 m = rx.match(document.body[p])
2481                 if m:
2482                     argnr = m.group(1)
2483                     if argnr == "1":
2484                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2485                         endPlain = find_end_of_layout(document.body, beginPlain)
2486                         endInset = find_end_of_inset(document.body, p)
2487                         content = document.body[beginPlain + 1 : endPlain]
2488                         # Adjust range end
2489                         realparend = realparend - len(document.body[p : endInset + 1])
2490                         # Remove arg inset
2491                         del document.body[p : endInset + 1]
2492                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2493                         document.body[realparbeg : realparbeg] = subst
2494             if layoutname in corollary_layouts:
2495                 m = rx.match(document.body[p])
2496                 if m:
2497                     argnr = m.group(1)
2498                     if argnr == "2":
2499                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2500                         endPlain = find_end_of_layout(document.body, beginPlain)
2501                         endInset = find_end_of_inset(document.body, p)
2502                         content = document.body[beginPlain + 1 : endPlain]
2503                         # Adjust range end
2504                         realparend = realparend - len(document.body[p : endInset + 1])
2505                         # Remove arg inset
2506                         del document.body[p : endInset + 1]
2507                         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2508                         document.body[realparbeg : realparbeg] = subst
2509         
2510         i = realparend
2511
2512
2513 def revert_beamerargs2(document):
2514     " Reverts beamer arguments to old layout, step 2 "
2515     
2516     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2517     if document.textclass not in beamer_classes:
2518         return
2519
2520     i = 0
2521     shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2522     corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2523     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2524
2525     while True:
2526         i = find_token(document.body, "\\begin_inset Argument", i)
2527         if i == -1:
2528             return
2529         # Find containing paragraph layout
2530         parent = get_containing_layout(document.body, i)
2531         if parent == False:
2532             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2533             i = i + 1
2534             continue
2535         parbeg = parent[1]
2536         parend = parent[2]
2537         realparbeg = parent[3]
2538         layoutname = parent[0]
2539         realparend = parend
2540         for p in range(parbeg, parend):
2541             if p >= realparend:
2542                 i = realparend
2543                 break
2544             if layoutname in shifted_layouts:
2545                 m = rx.match(document.body[p])
2546                 if m:
2547                     argnr = m.group(1)
2548                     if argnr == "2":
2549                         document.body[p] = "\\begin_inset Argument 1"       
2550             if layoutname in corollary_layouts:
2551                 m = rx.match(document.body[p])
2552                 if m:
2553                     argnr = m.group(1)
2554                     if argnr == "1":
2555                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2556                         endPlain = find_end_of_layout(document.body, beginPlain)
2557                         endInset = find_end_of_inset(document.body, p)
2558                         content = document.body[beginPlain + 1 : endPlain]
2559                         # Adjust range end
2560                         realparend = realparend - len(document.body[p : endInset + 1])
2561                         # Remove arg inset
2562                         del document.body[p : endInset + 1]
2563                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2564                         document.body[realparbeg : realparbeg] = subst
2565             if layoutname == "OverlayArea":
2566                 m = rx.match(document.body[p])
2567                 if m:
2568                     argnr = m.group(1)
2569                     if argnr == "1":
2570                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2571                         endPlain = find_end_of_layout(document.body, beginPlain)
2572                         endInset = find_end_of_inset(document.body, p)
2573                         content = document.body[beginPlain + 1 : endPlain]
2574                         # Adjust range end
2575                         realparend = realparend - len(document.body[p : endInset + 1])
2576                         # Remove arg inset
2577                         del document.body[p : endInset + 1]
2578                         subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2579                         document.body[realparbeg : realparbeg] = subst
2580             if layoutname == "AgainFrame":
2581                 m = rx.match(document.body[p])
2582                 if m:
2583                     argnr = m.group(1)
2584                     if argnr == "2":
2585                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2586                         endPlain = find_end_of_layout(document.body, beginPlain)
2587                         endInset = find_end_of_inset(document.body, p)
2588                         content = document.body[beginPlain + 1 : endPlain]
2589                         # Adjust range end
2590                         realparend = realparend - len(document.body[p : endInset + 1])
2591                         # Remove arg inset
2592                         del document.body[p : endInset + 1]
2593                         subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2594                         document.body[realparbeg : realparbeg] = subst
2595         i = realparend
2596
2597
2598 def revert_beamerargs3(document):
2599     " Reverts beamer arguments to old layout, step 3 "
2600     
2601     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2602     if document.textclass not in beamer_classes:
2603         return
2604
2605     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2606     i = 0
2607     while True:
2608         i = find_token(document.body, "\\begin_inset Argument", i)
2609         if i == -1:
2610             return
2611         # Find containing paragraph layout
2612         parent = get_containing_layout(document.body, i)
2613         if parent == False:
2614             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2615             i = i + 1
2616             continue
2617         parbeg = parent[1]
2618         parend = parent[2]
2619         realparbeg = parent[3]
2620         layoutname = parent[0]
2621         realparend = parend
2622         for p in range(parbeg, parend):
2623             if p >= realparend:
2624                 i = realparend
2625                 break
2626             if layoutname == "AgainFrame":
2627                 m = rx.match(document.body[p])
2628                 if m:
2629                     argnr = m.group(1)
2630                     if argnr == "1":
2631                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2632                         endPlain = find_end_of_layout(document.body, beginPlain)
2633                         endInset = find_end_of_inset(document.body, p)
2634                         content = document.body[beginPlain + 1 : endPlain]
2635                         # Adjust range end
2636                         realparend = realparend - len(document.body[p : endInset + 1])
2637                         # Remove arg inset
2638                         del document.body[p : endInset + 1]
2639                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2640                         document.body[realparbeg : realparbeg] = subst
2641         i = realparend
2642
2643
2644 def revert_beamerflex(document):
2645     " Reverts beamer Flex insets "
2646     
2647     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2648     if document.textclass not in beamer_classes:
2649         return
2650
2651     new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2652                   "Uncover" : "\\uncover", "Visible" : "\\visible",
2653                   "Invisible" : "\\invisible", "Alternative" : "\\alt",
2654                   "Beamer_Note" : "\\note"}
2655     old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2656     rx = re.compile(r'^\\begin_inset Flex (.+)$')
2657
2658     i = 0
2659     while True:
2660         i = find_token(document.body, "\\begin_inset Flex", i)
2661         if i == -1:
2662             return
2663         m = rx.match(document.body[i])
2664         if m:
2665             flextype = m.group(1)
2666             z = find_end_of_inset(document.body, i)
2667             if z == -1:
2668                 document.warning("Can't find end of Flex " + flextype + " inset.")
2669                 i += 1
2670                 continue
2671             if flextype in new_flexes:
2672                 pre = put_cmd_in_ert(new_flexes[flextype])
2673                 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2674                 if arg != -1:
2675                     argend = find_end_of_inset(document.body, arg)
2676                     if argend == -1:
2677                         document.warning("Can't find end of Argument!")
2678                         i += 1
2679                         continue
2680                     # Find containing paragraph layout
2681                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2682                     endPlain = find_end_of_layout(document.body, beginPlain)
2683                     argcontent = document.body[beginPlain + 1 : endPlain]
2684                     # Adjust range end
2685                     z = z - len(document.body[arg : argend + 1])
2686                     # Remove arg inset
2687                     del document.body[arg : argend + 1]
2688                     pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2689                 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2690                 if arg != -1:
2691                     argend = find_end_of_inset(document.body, arg)
2692                     if argend == -1:
2693                         document.warning("Can't find end of Argument!")
2694                         i += 1
2695                         continue
2696                     # Find containing paragraph layout
2697                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2698                     endPlain = find_end_of_layout(document.body, beginPlain)
2699                     argcontent = document.body[beginPlain + 1 : endPlain]
2700                     # Adjust range end
2701                     z = z - len(document.body[arg : argend + 1])
2702                     # Remove arg inset
2703                     del document.body[arg : argend + 1]
2704                     if flextype == "Alternative":
2705                         pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2706                     else:
2707                         pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2708                 pre += put_cmd_in_ert("{")
2709                 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2710                 endPlain = find_end_of_layout(document.body, beginPlain)
2711                 # Adjust range end
2712                 z = z - len(document.body[i : beginPlain + 1])
2713                 z += len(pre)
2714                 document.body[i : beginPlain + 1] = pre
2715                 post = put_cmd_in_ert("}")
2716                 document.body[z - 2 : z + 1] = post
2717             elif flextype in old_flexes:
2718                 pre = put_cmd_in_ert(old_flexes[flextype])
2719                 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2720                 if arg == -1:
2721                     i += 1
2722                     continue
2723                 argend = find_end_of_inset(document.body, arg)
2724                 if argend == -1:
2725                     document.warning("Can't find end of Argument!")
2726                     i += 1
2727                     continue
2728                 # Find containing paragraph layout
2729                 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2730                 endPlain = find_end_of_layout(document.body, beginPlain)
2731                 argcontent = document.body[beginPlain + 1 : endPlain]
2732                 # Adjust range end
2733                 z = z - len(document.body[arg : argend + 1])
2734                 # Remove arg inset
2735                 del document.body[arg : argend + 1]
2736                 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2737                 pre += put_cmd_in_ert("{")
2738                 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2739                 endPlain = find_end_of_layout(document.body, beginPlain)
2740                 # Adjust range end
2741                 z = z - len(document.body[i : beginPlain + 1])
2742                 z += len(pre)
2743                 document.body[i : beginPlain + 1] = pre
2744                 post = put_cmd_in_ert("}")
2745                 document.body[z - 2 : z + 1] = post
2746         
2747         i += 1
2748
2749
2750 def revert_beamerblocks(document):
2751     " Reverts beamer block arguments to ERT "
2752     
2753     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2754     if document.textclass not in beamer_classes:
2755         return
2756
2757     blocks = ["Block", "ExampleBlock", "AlertBlock"]
2758
2759     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2760     i = 0
2761     while True:
2762         i = find_token(document.body, "\\begin_inset Argument", i)
2763         if i == -1:
2764             return
2765         # Find containing paragraph layout
2766         parent = get_containing_layout(document.body, i)
2767         if parent == False:
2768             document.warning("Malformed lyx document: Can't find parent paragraph layout")
2769             i = i + 1
2770             continue
2771         parbeg = parent[1]
2772         parend = parent[2]
2773         realparbeg = parent[3]
2774         layoutname = parent[0]
2775         realparend = parend
2776         for p in range(parbeg, parend):
2777             if p >= realparend:
2778                 i = realparend
2779                 break
2780             if layoutname in blocks:
2781                 m = rx.match(document.body[p])
2782                 if m:
2783                     argnr = m.group(1)
2784                     if argnr == "1":
2785                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2786                         endPlain = find_end_of_layout(document.body, beginPlain)
2787                         endInset = find_end_of_inset(document.body, p)
2788                         content = document.body[beginPlain + 1 : endPlain]
2789                         # Adjust range end
2790                         realparend = realparend - len(document.body[p : endInset + 1])
2791                         # Remove arg inset
2792                         del document.body[p : endInset + 1]
2793                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2794                         document.body[realparbeg : realparbeg] = subst
2795                     elif argnr == "2":
2796                         beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2797                         endPlain = find_end_of_layout(document.body, beginPlain)
2798                         endInset = find_end_of_inset(document.body, p)
2799                         content = document.body[beginPlain + 1 : endPlain]
2800                         # Adjust range end
2801                         realparend = realparend - len(document.body[p : endInset + 1])
2802                         # Remove arg inset
2803                         del document.body[p : endInset + 1]
2804                         subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2805                         document.body[realparbeg : realparbeg] = subst
2806         i = realparend
2807
2808
2809
2810 def convert_beamerblocks(document):
2811     " Converts beamer block ERT args to native InsetArgs "
2812     
2813     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2814     if document.textclass not in beamer_classes:
2815         return
2816    
2817     blocks = ["Block", "ExampleBlock", "AlertBlock"]
2818     for lay in blocks:
2819         i = 0
2820         while True:
2821             i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2822             if i == -1:
2823                 break
2824             parent = get_containing_layout(document.body, i)
2825             if parent == False or parent[1] != i:
2826                 document.warning("Wrong parent layout!")
2827                 i += 1
2828                 continue
2829             j = parent[2]
2830             parbeg = parent[3]
2831             if i != -1:
2832                 if document.body[parbeg] == "\\begin_inset ERT":
2833                     ertcont = parbeg + 5
2834                     while True:
2835                         if document.body[ertcont].startswith("<"):
2836                             # This is an overlay specification
2837                             # strip off the <
2838                             document.body[ertcont] = document.body[ertcont][1:]
2839                             if document.body[ertcont].endswith(">"):
2840                                 # strip off the >
2841                                 document.body[ertcont] = document.body[ertcont][:-1]
2842                                 # Convert to ArgInset
2843                                 document.body[parbeg] = "\\begin_inset Argument 1"
2844                             elif document.body[ertcont].endswith("}"):
2845                                 # divide the args
2846                                 tok = document.body[ertcont].find('>{')
2847                                 if tok != -1:
2848                                     document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2849                                                                             '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2850                                                                             'status collapsed', '', '\\begin_layout Plain Layout',
2851                                                                             document.body[ertcont][tok + 2:-1]]
2852                             # Convert to ArgInset
2853                             document.body[parbeg] = "\\begin_inset Argument 1"
2854                         elif document.body[ertcont].startswith("{"):
2855                             # This is the block title
2856                             if document.body[ertcont].endswith("}"):
2857                                 # strip off the braces
2858                                 document.body[ertcont] = document.body[ertcont][1:-1]
2859                                 # Convert to ArgInset
2860                                 document.body[parbeg] = "\\begin_inset Argument 2"
2861                             elif count_pars_in_inset(document.body, ertcont) > 1:
2862                                 # Multipar ERT. Skip this.
2863                                 break
2864                             else:
2865                                 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True)
2866                         else:
2867                             break
2868                         j = find_end_of_layout(document.body, i)
2869                         if j == -1:
2870                             document.warning("end of layout not found!")
2871                         k = find_token(document.body, "\\begin_inset Argument", i, j)
2872                         if k == -1:
2873                             document.warning("InsetArgument not found!")
2874                             break
2875                         l = find_end_of_inset(document.body, k)
2876                         m = find_token(document.body, "\\begin_inset ERT", l, j)
2877                         if m == -1:
2878                             break
2879                         ertcont = m + 5
2880                         parbeg = m
2881             i = j
2882
2883
2884 def convert_overprint(document):
2885     " Convert old beamer overprint layouts to ERT "
2886     
2887     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2888     if document.textclass not in beamer_classes:
2889         return
2890
2891     i = 0
2892     while True:
2893         i = find_token(document.body, "\\begin_layout Overprint", i)
2894         if i == -1:
2895             return
2896         # Find end of sequence
2897         j = find_end_of_sequence(document.body, i)
2898         if j == -1:
2899             document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2900             i = i + 1
2901             continue
2902         endseq = j
2903         subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2904         esubst = list()
2905         if document.body[j] == "\\end_deeper":
2906             esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2907         else:
2908             esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2909         endseq = endseq + len(esubst) - len(document.body[j : j])
2910         document.body[j : j] = esubst
2911         argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2912         if argbeg != -1:
2913             argend = find_end_of_layout(document.body, argbeg)
2914             if argend == -1:
2915                 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2916                 i = i + 1
2917                 continue
2918             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2919             endPlain = find_end_of_layout(document.body, beginPlain)
2920             content = document.body[beginPlain + 1 : endPlain]
2921             # Adjust range end
2922             endseq = endseq - len(document.body[argbeg : argend + 1])
2923             # Remove arg inset
2924             del document.body[argbeg : argend + 1]
2925             subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2926             
2927         endseq = endseq - len(document.body[i : i])
2928         document.body[i : i] = subst + ["\\end_layout"]
2929         endseq += len(subst)
2930         
2931         for p in range(i, endseq):
2932             if document.body[p] == "\\begin_layout Overprint":
2933                 document.body[p] = "\\begin_layout Standard"
2934
2935         i = endseq
2936
2937
2938 def revert_overprint(document):
2939     " Revert old beamer overprint layouts to ERT "
2940     
2941     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2942     if document.textclass not in beamer_classes:
2943         return
2944
2945     i = 0
2946     while True:
2947         i = find_token(document.body, "\\begin_layout Overprint", i)
2948         if i == -1:
2949             return
2950         # Find end of sequence
2951         j = find_end_of_sequence(document.body, i)
2952         if j == -1:
2953             document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2954             i = i + 1
2955             continue
2956         endseq = j
2957         subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2958         esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
2959         endseq = endseq + len(esubst) - len(document.body[j : j])
2960         if document.body[j] == "\\end_deeper":
2961             document.body[j : j] = ["\\end_deeper", ""] + esubst
2962         else:
2963             document.body[j : j] = esubst
2964         r = i
2965         while r < j:
2966             if document.body[r] == "\\begin_deeper":
2967                 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
2968                 if s != -1:
2969                     document.body[r] = ""
2970                     document.body[s] = ""
2971                     r = s
2972                     continue
2973             r = r + 1
2974         argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2975         if argbeg != -1:
2976             argend = find_end_of_inset(document.body, argbeg)
2977             if argend == -1:
2978                 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2979                 i = i + 1
2980                 continue
2981             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2982             endPlain = find_end_of_layout(document.body, beginPlain)
2983             content = document.body[beginPlain + 1 : endPlain]
2984             # Adjust range end
2985             endseq = endseq - len(document.body[argbeg : argend])
2986             # Remove arg inset
2987             del document.body[argbeg : argend + 1]
2988             subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2989             
2990         endseq = endseq - len(document.body[i : i])
2991         document.body[i : i] = subst + ["\\end_layout"]
2992         endseq += len(subst)
2993      
2994         p = i
2995         while True:
2996             if p >= endseq:
2997                 break
2998             if document.body[p] == "\\begin_layout Overprint":
2999                 q = find_end_of_layout(document.body, p)
3000                 if q == -1:
3001                     document.warning("Malformed lyx document. Cannot find end of Overprint layout!")
3002                     p += 1
3003                     continue
3004                 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3005                 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3006                 if argbeg != -1:
3007                     argend = find_end_of_inset(document.body, argbeg)
3008                     if argend == -1:
3009                         document.warning("Malformed lyx document. Cannot find end of Overprint item argument!")
3010                         p += 1
3011                         continue
3012                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3013                     endPlain = find_end_of_layout(document.body, beginPlain)
3014                     content = document.body[beginPlain + 1 : endPlain]
3015                     # Adjust range end
3016                     endseq = endseq - len(document.body[argbeg : argend + 1])
3017                     # Remove arg inset
3018                     del document.body[argbeg : argend + 1]
3019                     subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3020                 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3021                 document.body[p : p + 1] = subst
3022             p = p + 1
3023
3024         i = endseq
3025
3026
3027 def revert_frametitle(document):
3028     " Reverts beamer frametitle layout to ERT "
3029     
3030     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3031     if document.textclass not in beamer_classes:
3032         return
3033
3034     rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3035     i = 0
3036     while True:
3037         i = find_token(document.body, "\\begin_layout FrameTitle", i)
3038         if i == -1:
3039             return
3040         j = find_end_of_layout(document.body, i)
3041         if j == -1:
3042             document.warning("Malformed lyx document: Can't find end of FrameTitle layout")
3043             i = i + 1
3044             continue
3045         endlay = j
3046         document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3047         endlay += len(put_cmd_in_ert("}"))
3048         subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3049         for p in range(i, j):
3050             if p >= endlay:
3051                 break
3052             m = rx.match(document.body[p])
3053             if m:
3054                 argnr = m.group(1)
3055                 if argnr == "1":
3056                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3057                     endPlain = find_end_of_layout(document.body, beginPlain)
3058                     endInset = find_end_of_inset(document.body, p)
3059                     content = document.body[beginPlain + 1 : endPlain]
3060                     # Adjust range end
3061                     endlay = endlay - len(document.body[p : endInset + 1])
3062                     # Remove arg inset
3063                     del document.body[p : endInset + 1]
3064                     subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3065                 elif argnr == "2":
3066                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3067                     endPlain = find_end_of_layout(document.body, beginPlain)
3068                     endInset = find_end_of_inset(document.body, p)
3069                     content = document.body[beginPlain + 1 : endPlain]
3070                     # Adjust range end
3071                     endlay = endlay - len(document.body[p : endInset + 1])
3072                     # Remove arg inset
3073                     del document.body[p : endInset + 1]
3074                     subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3075                     
3076         subst += put_cmd_in_ert("{")
3077         document.body[i : i + 1] = subst
3078         i = endlay
3079
3080
3081 def convert_epigraph(document):
3082     " Converts memoir epigraph to new syntax "
3083     
3084     if document.textclass != "memoir":
3085         return
3086
3087     i = 0
3088     while True:
3089         i = find_token(document.body, "\\begin_layout Epigraph", i)
3090         if i == -1:
3091             return
3092         j = find_end_of_layout(document.body, i)
3093         if j == -1:
3094             document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3095             i = i + 1
3096             continue
3097         endlay = j
3098         subst = list()
3099         ert = find_token(document.body, "\\begin_inset ERT", i, j)
3100         if ert != -1:
3101             endInset = find_end_of_inset(document.body, ert)
3102             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3103             endPlain = find_end_of_layout(document.body, beginPlain)
3104             ertcont = beginPlain + 2
3105             if document.body[ertcont] == "}{":
3106                 # strip off the <
3107                 # Convert to ArgInset
3108                 endlay = endlay - 2 * len(document.body[j])
3109                 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3110                             '\\begin_layout Plain Layout']
3111                 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3112                 document.body[j : j + 1] = endsubst
3113                 document.body[endInset + 1 : endInset + 1] = begsubst
3114                 # Adjust range end
3115                 endlay += len(begsubst) + len(endsubst)
3116                 endlay = endlay - len(document.body[ert : endInset + 1])
3117                 del document.body[ert : endInset + 1]
3118                     
3119         i = endlay
3120
3121
3122 def revert_epigraph(document):
3123     " Reverts memoir epigraph argument to ERT "
3124     
3125     if document.textclass != "memoir":
3126         return
3127
3128     i = 0
3129     while True:
3130         i = find_token(document.body, "\\begin_layout Epigraph", i)
3131         if i == -1:
3132             return
3133         j = find_end_of_layout(document.body, i)
3134         if j == -1:
3135             document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3136             i = i + 1
3137             continue
3138         endlay = j
3139         subst = list()
3140         p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3141         if p != -1:
3142             beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3143             endPlain = find_end_of_layout(document.body, beginPlain)
3144             endInset = find_end_of_inset(document.body, p)
3145             content = document.body[beginPlain + 1 : endPlain]
3146             # Adjust range end
3147             endlay = endlay - len(document.body[p : endInset + 1])
3148             # Remove arg inset
3149             del document.body[p : endInset + 1]
3150             subst += put_cmd_in_ert("}{") + content
3151         else:
3152             subst += put_cmd_in_ert("}{")
3153                     
3154         document.body[j : j] = subst + document.body[j : j]
3155         i = endlay
3156
3157
3158 def convert_captioninsets(document):
3159     " Converts caption insets to new syntax "
3160     
3161     i = 0
3162     while True:
3163       i = find_token(document.body, "\\begin_inset Caption", i)
3164       if i == -1:
3165           return
3166       document.body[i] = "\\begin_inset Caption Standard"
3167       i = i + 1
3168         
3169
3170
3171 def revert_captioninsets(document):
3172     " Reverts caption insets to old syntax "
3173     
3174     i = 0
3175     while True:
3176       i = find_token(document.body, "\\begin_inset Caption Standard", i)
3177       if i == -1:
3178           return
3179       document.body[i] = "\\begin_inset Caption"
3180       i = i + 1
3181
3182
3183 def convert_captionlayouts(document):
3184     " Convert caption layouts to caption insets. "
3185     
3186     caption_dict = {
3187         "Captionabove":  "Above",
3188         "Captionbelow":  "Below",
3189         "FigCaption"  :  "FigCaption",
3190         "Table_Caption" :  "Table",
3191         "CenteredCaption" : "Centered",
3192         "Bicaption" : "Bicaption",
3193         }
3194     
3195     i = 0
3196     while True:
3197         i = find_token(document.body, "\\begin_layout", i)
3198         if i == -1:
3199             return
3200         val = get_value(document.body, "\\begin_layout", i)
3201         if val in caption_dict.keys():
3202             j = find_end_of_layout(document.body, i)
3203             if j == -1:
3204                 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3205                 return
3206
3207             document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3208             document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3209                                     "\\begin_inset Caption %s" % caption_dict[val], "",
3210                                     "\\begin_layout %s" % document.default_layout]
3211         i = i + 1
3212
3213
3214 def revert_captionlayouts(document):
3215     " Revert caption insets to caption layouts. "
3216     
3217     caption_dict = {
3218         "Above" : "Captionabove",
3219         "Below" : "Captionbelow",
3220         "FigCaption"  :  "FigCaption",
3221         "Table" : "Table_Caption",
3222         "Centered" : "CenteredCaption",
3223         "Bicaption" : "Bicaption",
3224         }
3225     
3226     i = 0
3227     rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3228     while True:
3229         i = find_token(document.body, "\\begin_inset Caption", i)
3230         if i == -1:
3231             return
3232
3233         m = rx.match(document.body[i])
3234         val = ""
3235         if m:
3236             val = m.group(1)
3237         if val not in caption_dict.keys():
3238             i = i + 1
3239             continue
3240         
3241         # We either need to delete the previous \begin_layout line, or we
3242         # need to end the previous layout if this inset is not in the first
3243         # position of the paragraph.
3244         layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3245         if layout_before == -1:
3246             document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3247             return
3248         layout_line = document.body[layout_before]
3249         del_layout_before = True
3250         l = layout_before + 1
3251         while l < i:
3252             if document.body[l] != "":
3253                 del_layout_before = False
3254                 break
3255             l = l + 1
3256         if del_layout_before:
3257             del document.body[layout_before:i]
3258             i = layout_before
3259         else:
3260             document.body[i:i] = ["\\end_layout", ""]
3261             i = i + 2
3262
3263         # Find start of layout in the inset and end of inset
3264         j = find_token(document.body, "\\begin_layout", i)
3265         if j == -1:
3266             document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3267             return
3268         k = find_end_of_inset(document.body, i)
3269         if k == -1:
3270             document.warning("Malformed LyX document: Missing `\\end_inset'.")
3271             return
3272
3273         # We either need to delete the following \end_layout line, or we need
3274         # to restart the old layout if this inset is not at the paragraph end.
3275         layout_after = find_token(document.body, "\\end_layout", k)
3276         if layout_after == -1:
3277             document.warning("Malformed LyX document: Missing `\\end_layout'.")
3278             return
3279         del_layout_after = True
3280         l = k + 1
3281         while l < layout_after:
3282             if document.body[l] != "":
3283                 del_layout_after = False
3284                 break
3285             l = l + 1
3286         if del_layout_after:
3287             del document.body[k+1:layout_after+1]
3288         else:
3289             document.body[k+1:k+1] = [layout_line, ""]
3290
3291         # delete \begin_layout and \end_inset and replace \begin_inset with
3292         # "\begin_layout XXX". This works because we can only have one
3293         # paragraph in the caption inset: The old \end_layout will be recycled.
3294         del document.body[k]
3295         if document.body[k] == "":
3296             del document.body[k]
3297         del document.body[j]
3298         if document.body[j] == "":
3299             del document.body[j]
3300         document.body[i] = "\\begin_layout %s" % caption_dict[val]
3301         if document.body[i+1] == "":
3302             del document.body[i+1]
3303         i = i + 1
3304
3305
3306 def revert_fragileframe(document):
3307     " Reverts beamer FragileFrame layout to ERT "
3308     
3309     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3310     if document.textclass not in beamer_classes:
3311         return
3312
3313     i = 0
3314     while True:
3315         i = find_token(document.body, "\\begin_layout FragileFrame", i)
3316         if i == -1:
3317             return
3318         # Find end of sequence
3319         j = find_end_of_sequence(document.body, i)
3320         if j == -1:
3321             document.warning("Malformed lyx document. Cannot find end of FragileFrame sequence!")
3322             i = i + 1
3323             continue
3324         endseq = j
3325         subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3326         esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3327         endseq = endseq + len(esubst) - len(document.body[j : j])
3328         if document.body[j] == "\\end_deeper":
3329             document.body[j : j] = ["\\end_deeper", ""] + esubst
3330         else:
3331             document.body[j : j] = esubst
3332         for q in range(i, j):
3333             if document.body[q] == "\\begin_layout FragileFrame":
3334                 document.body[q] = "\\begin_layout %s" % document.default_layout
3335         r = i
3336         while r < j:
3337             if document.body[r] == "\\begin_deeper":
3338                 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3339                 if s != -1:
3340                     document.body[r] = ""
3341                     document.body[s] = ""
3342                     r = s
3343                     continue
3344             r = r + 1
3345         for p in range(1, 5):
3346             arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3347             if arg != -1:
3348                 if p == 1:
3349                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3350                     endPlain = find_end_of_layout(document.body, beginPlain)
3351                     endInset = find_end_of_inset(document.body, arg)
3352                     content = document.body[beginPlain + 1 : endPlain]
3353                     # Adjust range end
3354                     j = j - len(document.body[arg : endInset + 1])
3355                     # Remove arg inset
3356                     del document.body[arg : endInset + 1]
3357                     subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3358                 elif p == 2:
3359                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3360                     endPlain = find_end_of_layout(document.body, beginPlain)
3361                     endInset = find_end_of_inset(document.body, arg)
3362                     content = document.body[beginPlain + 1 : endPlain]
3363                     # Adjust range end
3364                     j = j - len(document.body[arg : endInset + 1])
3365                     # Remove arg inset
3366                     del document.body[arg : endInset + 1]
3367                     subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3368                 elif p == 3:
3369                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3370                     endPlain = find_end_of_layout(document.body, beginPlain)
3371                     endInset = find_end_of_inset(document.body, arg)
3372                     content = document.body[beginPlain + 1 : endPlain]
3373                     # Adjust range end
3374                     j = j - len(document.body[arg : endInset + 1])
3375                     # Remove arg inset
3376                     del document.body[arg : endInset + 1]
3377                     subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3378                 elif p == 4:
3379                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3380                     endPlain = find_end_of_layout(document.body, beginPlain)
3381                     endInset = find_end_of_inset(document.body, arg)
3382                     content = document.body[beginPlain + 1 : endPlain]
3383                     # Adjust range end
3384                     j = j - len(document.body[arg : endInset + 1])
3385                     # Remove arg inset
3386                     del document.body[arg : endInset + 1]
3387                     subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3388             elif p == 3:
3389                 subst += put_cmd_in_ert("[fragile]")
3390                     
3391         document.body[i : i + 1] = subst
3392         i = j
3393
3394
3395 def revert_newframes(document):
3396     " Reverts beamer Frame and PlainFrame layouts to old forms "
3397     
3398     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3399     if document.textclass not in beamer_classes:
3400         return
3401
3402     frame_dict = {
3403         "Frame" : "BeginFrame",
3404         "PlainFrame" : "BeginPlainFrame",
3405         }
3406
3407     rx = re.compile(r'^\\begin_layout (\S+)$')
3408     i = 0
3409     while True:
3410         i = find_token(document.body, "\\begin_layout", i)
3411         if i == -1:
3412             return
3413
3414         m = rx.match(document.body[i])
3415         val = ""
3416         if m:
3417             val = m.group(1)
3418         if val not in frame_dict.keys():
3419             i = i + 1
3420             continue
3421         # Find end of sequence
3422         j = find_end_of_sequence(document.body, i)
3423         if j == -1:
3424             document.warning("Malformed lyx document. Cannot find end of Frame sequence!")
3425             i = i + 1
3426             continue
3427         endseq = j
3428         subst = ["\\begin_layout %s" % frame_dict[val]]
3429         esubst = ["\\end_layout", "", "\\begin_layout EndFrame", "", "\\end_layout"]
3430         endseq = endseq + len(esubst) - len(document.body[j : j])
3431         if document.body[j] == "\\end_deeper":
3432             document.body[j : j] = ["\\end_deeper", ""] + esubst
3433         else:
3434             document.body[j : j] = esubst
3435         for q in range(i, j):
3436             if document.body[q] == "\\begin_layout %s" % val:
3437                 document.body[q] = "\\begin_layout %s" % document.default_layout
3438         r = i
3439         while r < j:
3440             if document.body[r] == "\\begin_deeper":
3441                 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3442                 if s != -1:
3443                     document.body[r] = ""
3444                     document.body[s] = ""
3445                     r = s
3446                     continue
3447             r = r + 1
3448         l = find_end_of_layout(document.body, i)
3449         for p in range(1, 5):
3450             arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3451             if arg != -1:
3452                 if p == 1:
3453                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3454                     endPlain = find_end_of_layout(document.body, beginPlain)
3455                     endInset = find_end_of_inset(document.body, arg)
3456                     content = document.body[beginPlain + 1 : endPlain]
3457                     # Adjust range end
3458                     l = l - len(document.body[arg : endInset + 1])
3459                     # Remove arg inset
3460                     del document.body[arg : endInset + 1]
3461                     subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3462                 elif p == 2:
3463                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3464                     endPlain = find_end_of_layout(document.body, beginPlain)
3465                     endInset = find_end_of_inset(document.body, arg)
3466                     content = document.body[beginPlain + 1 : endPlain]
3467                     # Adjust range end
3468                     l = l - len(document.body[arg : endInset + 1])
3469                     # Remove arg inset
3470                     del document.body[arg : endInset + 1]
3471                     subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3472                 elif p == 3:
3473                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3474                     endPlain = find_end_of_layout(document.body, beginPlain)
3475                     endInset = find_end_of_inset(document.body, arg)
3476                     content = document.body[beginPlain + 1 : endPlain]
3477                     # Adjust range end
3478                     l = l - len(document.body[arg : endInset + 1])
3479                     # Remove arg inset
3480                     del document.body[arg : endInset + 1]
3481                     subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3482                 elif p == 4:
3483                     beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3484                     endPlain = find_end_of_layout(document.body, beginPlain)
3485                     endInset = find_end_of_inset(document.body, arg)
3486                     content = document.body[beginPlain + 1 : endPlain]
3487                     # Adjust range end
3488                     l = l - len(document.body[arg : endInset + 1])
3489                     # Remove arg inset
3490                     del document.body[arg : endInset + 1]
3491                     subst += content
3492                     
3493         document.body[i : i + 1] = subst
3494         i = j
3495
3496
3497 def revert_IEEEtran_3(document):
3498   '''
3499   Reverts Flex Insets to TeX-code
3500   '''
3501   if document.textclass == "IEEEtran":
3502     h = 0
3503     i = 0
3504     j = 0
3505     while True:
3506       if h != -1:
3507         h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3508       if h != -1:
3509         endh = find_end_of_inset(document.body, h)
3510         document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3511         document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3512         h = h + 5
3513       if i != -1:
3514         i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3515       if i != -1:
3516         endi = find_end_of_inset(document.body, i)
3517         document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3518         document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3519         i = i + 5
3520       if j != -1:
3521         j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3522       if j != -1:
3523         endj = find_end_of_inset(document.body, j)
3524         document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3525         document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3526         j = j + 5
3527       if i == -1 and j == -1 and h == -1:
3528         return
3529
3530
3531 def revert_kurier_fonts(document):
3532   " Revert kurier font definition to LaTeX "
3533   
3534   i = find_token(document.header, "\\font_math", 0)
3535   if i != -1:
3536     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
3537       val = get_value(document.header, "\\font_math", i)
3538       if val == "kurier-math":
3539         add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3540           "\\usepackage[math]{kurier}\n" \
3541           "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3542         document.header[i] = "\\font_math auto"
3543   
3544   if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
3545     k = find_token(document.header, "\\font_sans kurierl", 0)
3546     if k != -1:
3547       add_to_preamble(document, "\\renewcommand{\\sfdefault}{kurierl}\n" \
3548         "\\renewcommand{\\bfdefault}{b}")
3549       document.header[k] = "\\font_sans default"
3550     
3551   if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
3552     l = find_token(document.header, "\\font_sans kurier-condensed", 0)
3553     if l != -1:
3554       add_to_preamble(document, "\\renewcommand{\\sfdefault}{kurier}\n" \
3555         "\\edef\\sfdefault{\\sfdefault c}\n" \
3556         "\\renewcommand{\\bfdefault}{b}")
3557       document.header[l] = "\\font_sans default"
3558   
3559   if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
3560     m = find_token(document.header, "\\font_sans kurier-light-condensed", 0)
3561     if m != -1:
3562       add_to_preamble(document, "\\renewcommand{\\sfdefault}{kurierl}\n" \
3563         "\\edef\\sfdefault{\\sfdefault c}\n" \
3564         "\\renewcommand{\\bfdefault}{b}")
3565       document.header[m] = "\\font_sans default"
3566   
3567   if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
3568     j = find_token(document.header, "\\font_sans kurier", 0)
3569     if j != -1:
3570       add_to_preamble(document, "\\renewcommand{\\sfdefault}{kurier}\n" \
3571         "\\renewcommand{\\bfdefault}{b}")
3572       document.header[j] = "\\font_sans default"
3573
3574
3575 ##
3576 # Conversion hub
3577 #
3578
3579 supported_versions = ["2.1.0","2.1"]
3580 convert = [
3581            [414, []],
3582            [415, [convert_undertilde]],
3583            [416, []],
3584            [417, [convert_japanese_encodings]],
3585            [418, []],
3586            [419, []],
3587            [420, [convert_biblio_style]],
3588            [421, [convert_longtable_captions]],
3589            [422, [convert_use_packages]],
3590            [423, [convert_use_mathtools]],
3591            [424, [convert_cite_engine_type]],
3592            [425, []],
3593            [426, []],
3594            [427, []],
3595            [428, [convert_cell_rotation]],
3596            [429, [convert_table_rotation]],
3597            [430, [convert_listoflistings]],
3598            [431, [convert_use_amssymb]],
3599            [432, []],
3600            [433, [convert_armenian]],
3601            [434, []],
3602            [435, []],
3603            [436, []],
3604            [437, []],
3605            [438, []],
3606            [439, []],
3607            [440, []],
3608            [441, [convert_mdnomath]],
3609            [442, []],
3610            [443, []],
3611            [444, []],
3612            [445, []],
3613            [446, [convert_latexargs]],
3614            [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
3615            [448, [convert_literate]],
3616            [449, []],
3617            [450, []],
3618            [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
3619            [452, [convert_beamerblocks]],
3620            [453, [convert_use_stmaryrd]],
3621            [454, [convert_overprint]],
3622            [455, []],
3623            [456, [convert_epigraph]],
3624            [457, [convert_use_stackrel]],
3625            [458, [convert_captioninsets, convert_captionlayouts]],
3626            [459, []],
3627            [460, []],
3628            [461, []]
3629           ]
3630
3631 revert =  [
3632            [460, [revert_kurier_fonts]],
3633            [459, [revert_IEEEtran_3]],
3634            [458, [revert_fragileframe, revert_newframes]],
3635            [457, [revert_captioninsets, revert_captionlayouts]],
3636            [456, [revert_use_stackrel]],
3637            [455, [revert_epigraph]],
3638            [454, [revert_frametitle]],
3639            [453, [revert_overprint]],
3640            [452, [revert_use_stmaryrd]],
3641            [451, [revert_beamerblocks]],
3642            [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
3643            [449, [revert_garamondx, revert_garamondx_newtxmath]],
3644            [448, [revert_itemargs]],
3645            [447, [revert_literate]],
3646            [446, [revert_IEEEtran, revert_IEEEtran_2, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV, revert_Initials, revert_ModernCV]],
3647            [445, [revert_latexargs]],
3648            [444, [revert_uop]],
3649            [443, [revert_biolinum]],
3650            [442, []],
3651            [441, [revert_newtxmath]],
3652            [440, [revert_mdnomath]],
3653            [439, [revert_mathfonts]],
3654            [438, [revert_minionpro]],
3655            [437, [revert_ipadeco, revert_ipachar]],
3656            [436, [revert_texgyre]],
3657            [435, [revert_mathdesign]],
3658            [434, [revert_txtt]],
3659            [433, [revert_libertine]],
3660            [432, [revert_armenian]],
3661            [431, [revert_languages, revert_ancientgreek]],
3662            [430, [revert_use_amssymb]],
3663            [429, [revert_listoflistings]],
3664            [428, [revert_table_rotation]],
3665            [427, [revert_cell_rotation]],
3666            [426, [revert_tipa]],
3667            [425, [revert_verbatim]],
3668            [424, [revert_cancel]],
3669            [423, [revert_cite_engine_type]],
3670            [422, [revert_use_mathtools]],
3671            [421, [revert_use_packages]],
3672            [420, [revert_longtable_captions]],
3673            [419, [revert_biblio_style]],
3674            [418, [revert_australian]],
3675            [417, [revert_justification]],
3676            [416, [revert_japanese_encodings]],
3677            [415, [revert_negative_space, revert_math_spaces]],
3678            [414, [revert_undertilde]],
3679            [413, [revert_visible_space]]
3680           ]
3681
3682
3683 if __name__ == "__main__":
3684     pass