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