]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/lyx_1_6.py
b1d5597bdfca6a50483750bd7cec688b5558aae6
[lyx.git] / lib / lyx2lyx / lyx_1_6.py
1 # This file is part of lyx2lyx
2 # -*- coding: utf-8 -*-
3 # Copyright (C) 2007-2008 The LyX Team <lyx-devel@lists.lyx.org>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 """ Convert files to the file format generated by lyx 1.6"""
20
21 import re
22 import unicodedata
23 import sys, os
24
25 from parser_tools import find_token, find_end_of, find_tokens, get_value, get_value_string
26
27 ####################################################################
28 # Private helper functions
29
30 def find_end_of_inset(lines, i):
31     " Find end of inset, where lines[i] is included."
32     return find_end_of(lines, i, "\\begin_inset", "\\end_inset")
33
34 def wrap_into_ert(string, src, dst):
35     " Wrap a something into an ERT"
36     return string.replace(src, '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n'
37       + dst + '\n\\end_layout\n\\end_inset\n')
38
39 def add_to_preamble(document, text):
40     """ Add text to the preamble if it is not already there.
41     Only the first line is checked!"""
42
43     if find_token(document.preamble, text[0], 0) != -1:
44         return
45
46     document.preamble.extend(text)
47
48 # Convert a LyX length into a LaTeX length
49 def convert_len(len):
50     units = {"text%":"\\backslash\ntextwidth", "col%":"\\backslash\ncolumnwidth",
51              "page%":"\\backslash\npagewidth", "line%":"\\backslash\nlinewidth",
52              "theight%":"\\backslash\ntextheight", "pheight%":"\\backslash\npageheight"}
53
54     # Convert LyX units to LaTeX units
55     for unit in units.keys():
56         if len.find(unit) != -1:
57             len = '%f' % (len2value(len) / 100)
58             len = len.strip('0') + units[unit]
59             break
60
61     return len
62
63 # Return the value of len without the unit in numerical form.
64 def len2value(len):
65     result = re.search('([+-]?[0-9.]+)', len)
66     if result:
67         return float(result.group(1))
68     # No number means 1.0
69     return 1.0
70
71 # Unfortunately, this doesn't really work, since Standard isn't always default.
72 # But it's as good as we can do right now.
73 def find_default_layout(doc, start, end):
74     l = find_token(document.body, "\\begin_layout Standard", start, end)
75     if l == -1:
76         l = find_token(document.body, "\\begin_layout PlainLayout", start, end)
77     if l == -1:
78         l = find_token(document.body, "\\begin_layout Plain Layout", start, end)
79     return l
80
81 ####################################################################
82
83 def get_option(document, m, option, default):
84     l = document.body[m].find(option)
85     val = default
86     if l != -1:
87         val = document.body[m][l:].split('"')[1]
88     return val
89
90 def remove_option(document, m, option):
91     l = document.body[m].find(option)
92     if l != -1:
93         val = document.body[m][l:].split('"')[1]
94         document.body[m] = document.body[m][:l-1] + document.body[m][l+len(option + '="' + val + '"'):]
95     return l
96
97 def set_option(document, m, option, value):
98     l = document.body[m].find(option)
99     if l != -1:
100         oldval = document.body[m][l:].split('"')[1]
101         l = l + len(option + '="')
102         document.body[m] = document.body[m][:l] + value + document.body[m][l+len(oldval):]
103     else:
104         document.body[m] = document.body[m][:-1] + ' ' + option + '="' + value + '">'
105     return l
106
107 def convert_tablines(document):
108     i = 0
109     while True:
110         i = find_token(document.body, "\\begin_inset Tabular", i)
111         if i == -1:
112             # LyX 1.3 inserted an extra space between \begin_inset
113             # and Tabular so let us try if this is the case and fix it.
114             i = find_token(document.body, "\\begin_inset  Tabular", i)
115             if i == -1:
116                 return
117             else:
118                 document.body[i] = "\\begin_inset Tabular"
119         j = find_end_of_inset(document.body, i + 1)
120         if j == -1:
121             document.warning("Malformed LyX document: Could not find end of tabular.")
122             continue
123
124         m = i + 1
125         nrows = int(document.body[i+1].split('"')[3])
126         ncols = int(document.body[i+1].split('"')[5])
127
128         col_info = []
129         for k in range(ncols):
130             m = find_token(document.body, "<column", m)
131             left = get_option(document, m, 'leftline', 'false')
132             right = get_option(document, m, 'rightline', 'false')
133             col_info.append([left, right])
134             remove_option(document, m, 'leftline')
135             remove_option(document, m, 'rightline')
136             m = m + 1
137
138         row_info = []
139         for k in range(nrows):
140             m = find_token(document.body, "<row", m)
141             top = get_option(document, m, 'topline', 'false')
142             bottom = get_option(document, m, 'bottomline', 'false')
143             row_info.append([top, bottom])
144             remove_option(document, m, 'topline')
145             remove_option(document, m, 'bottomline')
146             m = m + 1
147
148         m = i + 1
149         mc_info = []
150         for k in range(nrows*ncols):
151             m = find_token(document.body, "<cell", m)
152             mc_info.append(get_option(document, m, 'multicolumn', '0'))
153             m = m + 1
154         m = i + 1
155         for l in range(nrows):
156             for k in range(ncols):
157                 m = find_token(document.body, '<cell', m)
158                 if mc_info[l*ncols + k] == '0':
159                     r = set_option(document, m, 'topline', row_info[l][0])
160                     r = set_option(document, m, 'bottomline', row_info[l][1])
161                     r = set_option(document, m, 'leftline', col_info[k][0])
162                     r = set_option(document, m, 'rightline', col_info[k][1])
163                 elif mc_info[l*ncols + k] == '1':
164                     s = k + 1
165                     while s < ncols and mc_info[l*ncols + s] == '2':
166                         s = s + 1
167                     if s < ncols and mc_info[l*ncols + s] != '1':
168                         r = set_option(document, m, 'rightline', col_info[k][1])
169                     if k > 0 and mc_info[l*ncols + k - 1] == '0':
170                         r = set_option(document, m, 'leftline', col_info[k][0])
171                 m = m + 1
172         i = j + 1
173
174
175 def revert_tablines(document):
176     i = 0
177     while True:
178         i = find_token(document.body, "\\begin_inset Tabular", i)
179         if i == -1:
180             return
181         j = find_end_of_inset(document.body, i + 1)
182         if j == -1:
183             document.warning("Malformed LyX document: Could not find end of tabular.")
184             continue
185
186         m = i + 1
187         nrows = int(document.body[i+1].split('"')[3])
188         ncols = int(document.body[i+1].split('"')[5])
189
190         lines = []
191         for k in range(nrows*ncols):
192             m = find_token(document.body, "<cell", m)
193             top = get_option(document, m, 'topline', 'false')
194             bottom = get_option(document, m, 'bottomline', 'false')
195             left = get_option(document, m, 'leftline', 'false')
196             right = get_option(document, m, 'rightline', 'false')
197             lines.append([top, bottom, left, right])
198             m = m + 1
199
200         m = i + 1
201         col_info = []
202         for k in range(ncols):
203             m = find_token(document.body, "<column", m)
204             left = 'true'
205             for l in range(nrows):
206                 left = lines[k*ncols + k][2]
207                 if left == 'false':
208                     break
209             set_option(document, m, 'leftline', left)
210             right = 'true'
211             for l in range(nrows):
212                 right = lines[k*ncols + k][3]
213                 if right == 'false':
214                     break
215             set_option(document, m, 'rightline', right)
216             m = m + 1
217
218         row_info = []
219         for k in range(nrows):
220             m = find_token(document.body, "<row", m)
221             top = 'true'
222             for l in range(ncols):
223                 top = lines[k*ncols + l][0]
224                 if top == 'false':
225                     break
226             set_option(document, m, 'topline', top)
227             bottom = 'true'
228             for l in range(ncols):
229                 bottom = lines[k*ncols + l][1]
230                 if bottom == 'false':
231                     break
232             set_option(document, m, 'bottomline', bottom)
233             m = m + 1
234
235         i = j + 1
236
237
238 def fix_wrong_tables(document):
239     i = 0
240     while True:
241         i = find_token(document.body, "\\begin_inset Tabular", i)
242         if i == -1:
243             return
244         j = find_end_of_inset(document.body, i + 1)
245         if j == -1:
246             document.warning("Malformed LyX document: Could not find end of tabular.")
247             continue
248
249         m = i + 1
250         nrows = int(document.body[i+1].split('"')[3])
251         ncols = int(document.body[i+1].split('"')[5])
252
253         for l in range(nrows):
254             prev_multicolumn = 0
255             for k in range(ncols):
256                 m = find_token(document.body, '<cell', m)
257
258                 if document.body[m].find('multicolumn') != -1:
259                     multicol_cont = int(document.body[m].split('"')[1])
260
261                     if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
262                         document.body[m] = document.body[m][:5] + document.body[m][21:]
263                         prev_multicolumn = 0
264                     else:
265                         prev_multicolumn = multicol_cont
266                 else:
267                     prev_multicolumn = 0
268
269         i = j + 1
270
271
272 def close_begin_deeper(document):
273     i = 0
274     depth = 0
275     while True:
276         i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
277
278         if i == -1:
279             break
280
281         if document.body[i][:13] == "\\begin_deeper":
282             depth += 1
283         else:
284             depth -= 1
285
286         i += 1
287
288     document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
289
290
291 def long_charstyle_names(document):
292     i = 0
293     while True:
294         i = find_token(document.body, "\\begin_inset CharStyle", i)
295         if i == -1:
296             return
297         document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
298         i += 1
299
300 def revert_long_charstyle_names(document):
301     i = 0
302     while True:
303         i = find_token(document.body, "\\begin_inset CharStyle", i)
304         if i == -1:
305             return
306         document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle")
307         i += 1
308
309
310 def axe_show_label(document):
311     i = 0
312     while True:
313         i = find_token(document.body, "\\begin_inset CharStyle", i)
314         if i == -1:
315             return
316         if document.body[i + 1].find("show_label") != -1:
317             if document.body[i + 1].find("true") != -1:
318                 document.body[i + 1] = "status open"
319                 del document.body[ i + 2]
320             else:
321                 if document.body[i + 1].find("false") != -1:
322                     document.body[i + 1] = "status collapsed"
323                     del document.body[ i + 2]
324                 else:
325                     document.warning("Malformed LyX document: show_label neither false nor true.")
326         else:
327             document.warning("Malformed LyX document: show_label missing in CharStyle.")
328
329         i += 1
330
331
332 def revert_show_label(document):
333     i = 0
334     while True:
335         i = find_token(document.body, "\\begin_inset CharStyle", i)
336         if i == -1:
337             return
338         if document.body[i + 1].find("status open") != -1:
339             document.body.insert(i + 1, "show_label true")
340         else:
341             if document.body[i + 1].find("status collapsed") != -1:
342                 document.body.insert(i + 1, "show_label false")
343             else:
344                 document.warning("Malformed LyX document: no legal status line in CharStyle.")
345         i += 1
346
347 def revert_begin_modules(document):
348     i = 0
349     while True:
350         i = find_token(document.header, "\\begin_modules", i)
351         if i == -1:
352             return
353         j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
354         if j == -1:
355             # this should not happen
356             break
357         document.header[i : j + 1] = []
358
359 def convert_flex(document):
360     "Convert CharStyle to Flex"
361     i = 0
362     while True:
363         i = find_token(document.body, "\\begin_inset CharStyle", i)
364         if i == -1:
365             return
366         document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
367
368 def revert_flex(document):
369     "Convert Flex to CharStyle"
370     i = 0
371     while True:
372         i = find_token(document.body, "\\begin_inset Flex", i)
373         if i == -1:
374             return
375         document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
376
377
378 #  Discard PDF options for hyperref
379 def revert_pdf_options(document):
380         "Revert PDF options for hyperref."
381         # store the PDF options and delete the entries from the Lyx file        
382         i = 0
383         hyperref = False
384         title = ""
385         author = ""
386         subject = ""
387         keywords = ""
388         bookmarks = ""
389         bookmarksnumbered = ""
390         bookmarksopen = ""
391         bookmarksopenlevel = ""
392         breaklinks = ""
393         pdfborder = ""
394         colorlinks = ""
395         backref = ""
396         pagebackref = ""
397         pagemode = ""
398         otheroptions = ""
399         i = find_token(document.header, "\\use_hyperref", i)
400         if i != -1:
401             hyperref = get_value(document.header, "\\use_hyperref", i) == 'true'
402             del document.header[i]
403         i = find_token(document.header, "\\pdf_store_options", i)
404         if i != -1:
405             del document.header[i]
406         i = find_token(document.header, "\\pdf_title", 0)
407         if i != -1:
408             title = get_value_string(document.header, '\\pdf_title', 0, 0, True)
409             title = ' pdftitle={' + title + '}'
410             del document.header[i]
411         i = find_token(document.header, "\\pdf_author", 0)
412         if i != -1:
413             author = get_value_string(document.header, '\\pdf_author', 0, 0, True)
414             if title == "":
415                 author = ' pdfauthor={' + author + '}'
416             else:
417                 author = ',\n pdfauthor={' + author + '}'
418             del document.header[i]
419         i = find_token(document.header, "\\pdf_subject", 0)
420         if i != -1:
421             subject = get_value_string(document.header, '\\pdf_subject', 0, 0, True)
422             if title == "" and author == "":
423                 subject = ' pdfsubject={' + subject + '}'
424             else:
425                 subject = ',\n pdfsubject={' + subject + '}'
426             del document.header[i]
427         i = find_token(document.header, "\\pdf_keywords", 0)
428         if i != -1:
429             keywords = get_value_string(document.header, '\\pdf_keywords', 0, 0, True)
430             if title == "" and author == "" and subject == "":
431                 keywords = ' pdfkeywords={' + keywords + '}'
432             else:
433                 keywords = ',\n pdfkeywords={' + keywords + '}'
434             del document.header[i]
435         i = find_token(document.header, "\\pdf_bookmarks", 0)
436         if i != -1:
437             bookmarks = get_value_string(document.header, '\\pdf_bookmarks', 0)
438             bookmarks = ',\n bookmarks=' + bookmarks
439             del document.header[i]
440         i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
441         if i != -1:
442             bookmarksnumbered = get_value_string(document.header, '\\pdf_bookmarksnumbered', 0)
443             bookmarksnumbered = ',\n bookmarksnumbered=' + bookmarksnumbered
444             del document.header[i]
445         i = find_token(document.header, "\\pdf_bookmarksopen", i)
446         if i != -1:
447             bookmarksopen = get_value_string(document.header, '\\pdf_bookmarksopen', 0)
448             bookmarksopen = ',\n bookmarksopen=' + bookmarksopen
449             del document.header[i]
450         i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
451         if i != -1:
452             bookmarksopenlevel = get_value_string(document.header, '\\pdf_bookmarksopenlevel', 0, 0, True)
453             bookmarksopenlevel = ',\n bookmarksopenlevel=' + bookmarksopenlevel
454             del document.header[i]
455         i = find_token(document.header, "\\pdf_breaklinks", i)
456         if i != -1:
457             breaklinks = get_value_string(document.header, '\\pdf_breaklinks', 0)
458             breaklinks = ',\n breaklinks=' + breaklinks
459             del document.header[i]
460         i = find_token(document.header, "\\pdf_pdfborder", i)
461         if i != -1:
462             pdfborder = get_value_string(document.header, '\\pdf_pdfborder', 0)
463             if pdfborder == 'true':
464                 pdfborder = ',\n pdfborder={0 0 0}'
465             else:
466                 pdfborder = ',\n pdfborder={0 0 1}'
467             del document.header[i]
468         i = find_token(document.header, "\\pdf_colorlinks", i)
469         if i != -1:
470             colorlinks = get_value_string(document.header, '\\pdf_colorlinks', 0)
471             colorlinks = ',\n colorlinks=' + colorlinks
472             del document.header[i]
473         i = find_token(document.header, "\\pdf_backref", i)
474         if i != -1:
475             backref = get_value_string(document.header, '\\pdf_backref', 0)
476             backref = ',\n backref=' + backref
477             del document.header[i]
478         i = find_token(document.header, "\\pdf_pagebackref", i)
479         if i != -1:
480             pagebackref = get_value_string(document.header, '\\pdf_pagebackref', 0)
481             pagebackref = ',\n pagebackref=' + pagebackref
482             del document.header[i]
483         i = find_token(document.header, "\\pdf_pagemode", 0)
484         if i != -1:
485             pagemode = get_value_string(document.header, '\\pdf_pagemode', 0)
486             pagemode = ',\n pdfpagemode=' + pagemode
487             del document.header[i]
488         i = find_token(document.header, "\\pdf_quoted_options", 0)
489         if i != -1:
490             otheroptions = get_value_string(document.header, '\\pdf_quoted_options', 0, 0, True)
491             if title == "" and author == "" and subject == "" and keywords == "":
492                 otheroptions = ' ' + otheroptions
493             else:
494                 otheroptions = ',\n ' + otheroptions
495             del document.header[i]
496
497         # write to the preamble when hyperref was used
498         if hyperref == True:
499             # preamble write preparations
500             # bookmark numbers are only output when they are turned on
501             if bookmarksopen == ',\n bookmarksopen=true':
502                 bookmarksopen = bookmarksopen + bookmarksopenlevel
503             if bookmarks == ',\n bookmarks=true':
504                 bookmarks = bookmarks + bookmarksnumbered + bookmarksopen
505             else:
506                 bookmarks = bookmarks
507             # hypersetup is only output when there are things to be set up
508             setupstart = '\\hypersetup{%\n'
509             setupend = ' }\n'
510             if otheroptions == "" and title == "" and  author == ""\
511                and  subject == "" and keywords == "":
512                 setupstart = ""
513                 setupend = ""
514             # write the preamble
515             add_to_preamble(document,
516                                 ['% Commands inserted by lyx2lyx for PDF properties',
517                                  '\\usepackage[unicode=true'
518                                  + bookmarks
519                                  + breaklinks
520                                  + pdfborder
521                                  + backref
522                                  + pagebackref
523                                  + colorlinks
524                                  + pagemode
525                                  + ']\n'
526                                  ' {hyperref}\n'
527                                  + setupstart
528                                  + title
529                                  + author
530                                  + subject
531                                  + keywords
532                                  + otheroptions
533                                  + setupend])
534
535
536 def remove_inzip_options(document):
537     "Remove inzipName and embed options from the Graphics inset"
538     i = 0
539     while 1:
540         i = find_token(document.body, "\\begin_inset Graphics", i)
541         if i == -1:
542             return
543         j = find_end_of_inset(document.body, i + 1)
544         if j == -1:
545             # should not happen
546             document.warning("Malformed LyX document: Could not find end of graphics inset.")
547         # If there's a inzip param, just remove that
548         k = find_token(document.body, "\tinzipName", i + 1, j)
549         if k != -1:
550             del document.body[k]
551             # embed option must follow the inzipName option
552             del document.body[k+1]
553         i = i + 1
554
555
556 def convert_inset_command(document):
557     """
558         Convert:
559             \begin_inset LatexCommand cmd
560         to
561             \begin_inset CommandInset InsetType
562             LatexCommand cmd
563     """
564     i = 0
565     while 1:
566         i = find_token(document.body, "\\begin_inset LatexCommand", i)
567         if i == -1:
568             return
569         line = document.body[i]
570         r = re.compile(r'\\begin_inset LatexCommand (.*)$')
571         m = r.match(line)
572         cmdName = m.group(1)
573         insetName = ""
574         #this is adapted from factory.cpp
575         if cmdName[0:4].lower() == "cite":
576             insetName = "citation"
577         elif cmdName == "url" or cmdName == "htmlurl":
578             insetName = "url"
579         elif cmdName[-3:] == "ref":
580             insetName = "ref"
581         elif cmdName == "tableofcontents":
582             insetName = "toc"
583         elif cmdName == "printnomenclature":
584             insetName = "nomencl_print"
585         elif cmdName == "printindex":
586             insetName = "index_print"
587         else:
588             insetName = cmdName
589         insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
590         document.body[i : i+1] = insertion
591
592
593 def revert_inset_command(document):
594     """
595         Convert:
596             \begin_inset CommandInset InsetType
597             LatexCommand cmd
598         to
599             \begin_inset LatexCommand cmd
600         Some insets may end up being converted to insets earlier versions of LyX
601         will not be able to recognize. Not sure what to do about that.
602     """
603     i = 0
604     while 1:
605         i = find_token(document.body, "\\begin_inset CommandInset", i)
606         if i == -1:
607             return
608         nextline = document.body[i+1]
609         r = re.compile(r'LatexCommand\s+(.*)$')
610         m = r.match(nextline)
611         if not m:
612             document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
613             continue
614         cmdName = m.group(1)
615         insertion = ["\\begin_inset LatexCommand " + cmdName]
616         document.body[i : i+2] = insertion
617
618
619 def convert_wrapfig_options(document):
620     "Convert optional options for wrap floats (wrapfig)."
621     # adds the tokens "lines", "placement", and "overhang"
622     i = 0
623     while True:
624         i = find_token(document.body, "\\begin_inset Wrap figure", i)
625         if i == -1:
626             return
627         document.body.insert(i + 1, "lines 0")
628         j = find_token(document.body, "placement", i)
629         # placement can be already set or not; if not, set it
630         if j == i+2:
631             document.body.insert(i + 3, "overhang 0col%")
632         else:
633            document.body.insert(i + 2, "placement o")
634            document.body.insert(i + 3, "overhang 0col%")
635         i = i + 1
636
637
638 def revert_wrapfig_options(document):
639     "Revert optional options for wrap floats (wrapfig)."
640     i = 0
641     while True:
642         i = find_token(document.body, "lines", i)
643         if i == -1:
644             return
645         j = find_token(document.body, "overhang", i+1)
646         if j != i + 2 and j != -1:
647             document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float.")
648         if j == -1:
649             return
650         del document.body[i]
651         del document.body[j-1]
652         i = i + 1
653
654
655 def convert_latexcommand_index(document):
656     "Convert from LatexCommand form to collapsable form."
657     i = 0
658     while True:
659         i = find_token(document.body, "\\begin_inset CommandInset index", i)
660         if i == -1:
661             return
662         if document.body[i + 1] != "LatexCommand index": # Might also be index_print
663             return
664         fullcontent = document.body[i + 2][6:].strip('"')
665         document.body[i:i + 2] = ["\\begin_inset Index",
666           "status collapsed",
667           "\\begin_layout Standard"]
668         # Put here the conversions needed from LaTeX string to LyXText.
669         # Here we do a minimal conversion to prevent crashes and data loss.
670         # Manual patch-up may be needed.
671         # Umlauted characters (most common ones, can be extended):
672         fullcontent = fullcontent.replace(r'\\\"a', u'ä').replace(r'\\\"o', u'ö').replace(r'\\\"u', u'ü')
673         # Generic, \" -> ":
674         fullcontent = wrap_into_ert(fullcontent, r'\"', '"')
675         #fullcontent = fullcontent.replace(r'\"', '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout standard\n"\n\\end_layout\n\\end_inset\n')
676         # Math:
677         r = re.compile('^(.*?)(\$.*?\$)(.*)')
678         g = fullcontent
679         while r.match(g):
680           m = r.match(g)
681           s = m.group(1)
682           f = m.group(2).replace('\\\\', '\\')
683           g = m.group(3)
684           if s:
685             # this is non-math!
686             s = wrap_into_ert(s, r'\\', '\\backslash')
687             s = wrap_into_ert(s, '{', '{')
688             s = wrap_into_ert(s, '}', '}')
689             document.body.insert(i + 3, s)
690             i += 1
691           document.body.insert(i + 3, "\\begin_inset Formula " + f)
692           document.body.insert(i + 4, "\\end_inset")
693           i += 2
694         # Generic, \\ -> \backslash:
695         g = wrap_into_ert(g, r'\\', '\\backslash{}')
696         g = wrap_into_ert(g, '{', '{')
697         g = wrap_into_ert(g, '}', '}')
698         document.body.insert(i + 3, g)
699         document.body[i + 4] = "\\end_layout"
700         i = i + 5
701
702
703 def revert_latexcommand_index(document):
704     "Revert from collapsable form to LatexCommand form."
705     i = 0
706     while True:
707         i = find_token(document.body, "\\begin_inset Index", i)
708         if i == -1:
709           return
710         j = find_end_of_inset(document.body, i + 1)
711         if j == -1:
712           return
713         del document.body[j - 1]
714         del document.body[j - 2] # \end_layout
715         document.body[i] =  "\\begin_inset CommandInset index"
716         document.body[i + 1] =  "LatexCommand index"
717         # clean up multiline stuff
718         content = ""
719         for k in range(i + 3, j - 2):
720           line = document.body[k]
721           if line.startswith("\\begin_inset ERT"):
722             line = line[16:]
723           if line.startswith("\\begin_inset Formula"):
724             line = line[20:]
725           if line.startswith("\\begin_layout Standard"):
726             line = line[22:]
727           if line.startswith("\\begin_layout Plain"):
728             line = line[22:]
729           if line.startswith("\\end_layout"):
730             line = line[11:]
731           if line.startswith("\\end_inset"):
732             line = line[10:]
733           if line.startswith("status collapsed"):
734             line = line[16:]
735           line = line.replace(u'ä', r'\\\"a').replace(u'ö', r'\\\"o').replace(u'ü', r'\\\"u')
736           content = content + line;
737         document.body[i + 3] = "name " + '"' + content + '"'
738         for k in range(i + 4, j - 2):
739           del document.body[i + 4]
740         document.body.insert(i + 4, "")
741         del document.body[i + 2] # \begin_layout standard
742         i = i + 5
743
744
745 def revert_wraptable(document):
746     "Revert wrap table to wrap figure."
747     i = 0
748     while True:
749         i = find_token(document.body, "\\begin_inset Wrap table", i)
750         if i == -1:
751             return
752         document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
753         i = i + 1
754
755
756 def revert_vietnamese(document):
757     "Set language Vietnamese to English"
758     # Set document language from Vietnamese to English
759     i = 0
760     if document.language == "vietnamese":
761         document.language = "english"
762         i = find_token(document.header, "\\language", 0)
763         if i != -1:
764             document.header[i] = "\\language english"
765     j = 0
766     while True:
767         j = find_token(document.body, "\\lang vietnamese", j)
768         if j == -1:
769             return
770         document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
771         j = j + 1
772
773
774 def revert_japanese(document):
775     "Set language japanese-plain to japanese"
776     # Set document language from japanese-plain to japanese
777     i = 0
778     if document.language == "japanese-plain":
779         document.language = "japanese"
780         i = find_token(document.header, "\\language", 0)
781         if i != -1:
782             document.header[i] = "\\language japanese"
783     j = 0
784     while True:
785         j = find_token(document.body, "\\lang japanese-plain", j)
786         if j == -1:
787             return
788         document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
789         j = j + 1
790
791
792 def revert_japanese_encoding(document):
793     "Set input encoding form EUC-JP-plain to EUC-JP etc."
794     # Set input encoding form EUC-JP-plain to EUC-JP etc.
795     i = 0
796     i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
797     if i != -1:
798         document.header[i] = "\\inputencoding EUC-JP"
799     j = 0
800     j = find_token(document.header, "\\inputencoding JIS-plain", 0)
801     if j != -1:
802         document.header[j] = "\\inputencoding JIS"
803     k = 0
804     k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
805     if k != -1: # convert to UTF8 since there is currently no SJIS encoding
806         document.header[k] = "\\inputencoding UTF8"
807
808
809 def revert_inset_info(document):
810     'Replace info inset with its content'
811     i = 0
812     while 1:
813         i = find_token(document.body, '\\begin_inset Info', i)
814         if i == -1:
815             return
816         j = find_end_of_inset(document.body, i + 1)
817         if j == -1:
818             # should not happen
819             document.warning("Malformed LyX document: Could not find end of Info inset.")
820         type = 'unknown'
821         arg = ''
822         for k in range(i, j+1):
823             if document.body[k].startswith("arg"):
824                 arg = document.body[k][3:].strip().strip('"')
825             if document.body[k].startswith("type"):
826                 type = document.body[k][4:].strip().strip('"')
827         # I think there is a newline after \\end_inset, which should be removed.
828         if document.body[j + 1].strip() == "":
829             document.body[i : (j + 2)] = [type + ':' + arg]
830         else:
831             document.body[i : (j + 1)] = [type + ':' + arg]
832
833
834 def convert_pdf_options(document):
835     # Set the pdfusetitle tag, delete the pdf_store_options,
836     # set quotes for bookmarksopenlevel"
837     has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
838     if has_hr == "1":
839         k = find_token(document.header, "\\use_hyperref", 0)
840         document.header.insert(k + 1, "\\pdf_pdfusetitle true")
841     k = find_token(document.header, "\\pdf_store_options", 0)
842     if k != -1:
843         del document.header[k]
844     i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
845     if i == -1: return
846     document.header[i] = document.header[i].replace('"', '')
847
848
849 def revert_pdf_options_2(document):
850     # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
851     k = find_token(document.header, "\\use_hyperref", 0)
852     i = find_token(document.header, "\\pdf_pdfusetitle", k)
853     if i != -1:
854         del document.header[i]
855     i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
856     if i == -1: return
857     values = document.header[i].split()
858     values[1] = ' "' + values[1] + '"'
859     document.header[i] = ''.join(values)
860
861
862 def convert_htmlurl(document):
863     'Convert "htmlurl" to "href" insets for docbook'
864     if document.backend != "docbook":
865       return
866     i = 0
867     while True:
868       i = find_token(document.body, "\\begin_inset CommandInset url", i)
869       if i == -1:
870         return
871       document.body[i] = "\\begin_inset CommandInset href"
872       document.body[i + 1] = "LatexCommand href"
873       i = i + 1
874
875
876 def convert_url(document):
877     'Convert url insets to url charstyles'
878     if document.backend == "docbook":
879       return
880     i = 0
881     while True:
882       i = find_token(document.body, "\\begin_inset CommandInset url", i)
883       if i == -1:
884         break
885       n = find_token(document.body, "name", i)
886       if n == i + 2:
887         # place the URL name in typewriter before the new URL insert
888         # grab the name 'bla' from the e.g. the line 'name "bla"',
889         # therefore start with the 6th character
890         name = document.body[n][6:-1]
891         newname = [name + " "]
892         document.body[i:i] = newname
893         i = i + 1
894       j = find_token(document.body, "target", i)
895       if j == -1:
896         document.warning("Malformed LyX document: Can't find target for url inset")
897         i = j
898         continue
899       target = document.body[j][8:-1]
900       k = find_token(document.body, "\\end_inset", j)
901       if k == -1:
902         document.warning("Malformed LyX document: Can't find end of url inset")
903         i = k
904         continue
905       newstuff = ["\\begin_inset Flex URL",
906         "status collapsed", "",
907         "\\begin_layout Standard",
908         "",
909         target,
910         "\\end_layout",
911         ""]
912       document.body[i:k] = newstuff
913       i = k
914
915 def convert_ams_classes(document):
916   tc = document.textclass
917   if (tc != "amsart" and tc != "amsart-plain" and
918       tc != "amsart-seq" and tc != "amsbook"):
919     return
920   if tc == "amsart-plain":
921     document.textclass = "amsart"
922     document.set_textclass()
923     document.add_module("Theorems (Starred)")
924     return
925   if tc == "amsart-seq":
926     document.textclass = "amsart"
927     document.set_textclass()
928   document.add_module("Theorems (AMS)")
929
930   #Now we want to see if any of the environments in the extended theorems
931   #module were used in this document. If so, we'll add that module, too.
932   layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note",  \
933     "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
934     "Assumption"]
935
936   r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
937   i = 0
938   while True:
939     i = find_token(document.body, "\\begin_layout", i)
940     if i == -1:
941       return
942     m = r.match(document.body[i])
943     if m == None:
944       document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
945       i += 1
946       continue
947     m = m.group(1)
948     if layouts.count(m) != 0:
949       document.add_module("Theorems (AMS-Extended)")
950       return
951     i += 1
952
953 def revert_href(document):
954     'Reverts hyperlink insets (href) to url insets (url)'
955     i = 0
956     while True:
957       i = find_token(document.body, "\\begin_inset CommandInset href", i)
958       if i == -1:
959           return
960       document.body[i : i + 2] = \
961         ["\\begin_inset CommandInset url", "LatexCommand url"]
962       i = i + 2
963
964
965 def convert_include(document):
966   'Converts include insets to new format.'
967   i = 0
968   r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
969   while True:
970     i = find_token(document.body, "\\begin_inset Include", i)
971     if i == -1:
972       return
973     line = document.body[i]
974     previewline = document.body[i + 1]
975     m = r.match(line)
976     if m == None:
977       document.warning("Unable to match line " + str(i) + " of body!")
978       i += 1
979       continue
980     cmd = m.group(1)
981     fn  = m.group(2)
982     opt = m.group(3)
983     insertion = ["\\begin_inset CommandInset include",
984        "LatexCommand " + cmd, previewline,
985        "filename \"" + fn + "\""]
986     newlines = 2
987     if opt:
988       insertion.append("lstparams " + '"' + opt + '"')
989       newlines += 1
990     document.body[i : i + 2] = insertion
991     i += newlines
992
993
994 def revert_include(document):
995   'Reverts include insets to old format.'
996   i = 0
997   r1 = re.compile('LatexCommand (.+)')
998   r2 = re.compile('filename (.+)')
999   r3 = re.compile('options (.*)')
1000   while True:
1001     i = find_token(document.body, "\\begin_inset CommandInset include", i)
1002     if i == -1:
1003       return
1004     previewline = document.body[i + 1]
1005     m = r1.match(document.body[i + 2])
1006     if m == None:
1007       document.warning("Malformed LyX document: No LatexCommand line for `" +
1008         document.body[i] + "' on line " + str(i) + ".")
1009       i += 1
1010       continue
1011     cmd = m.group(1)
1012     m = r2.match(document.body[i + 3])
1013     if m == None:
1014       document.warning("Malformed LyX document: No filename line for `" + \
1015         document.body[i] + "' on line " + str(i) + ".")
1016       i += 2
1017       continue
1018     fn = m.group(1)
1019     options = ""
1020     numlines = 4
1021     if (cmd == "lstinputlisting"):
1022       m = r3.match(document.body[i + 4])
1023       if m != None:
1024         options = m.group(1)
1025         numlines = 5
1026     newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1027     if options:
1028       newline += ("[" + options + "]")
1029     insertion = [newline, previewline]
1030     document.body[i : i + numlines] = insertion
1031     i += 2
1032
1033
1034 def revert_albanian(document):
1035     "Set language Albanian to English"
1036     i = 0
1037     if document.language == "albanian":
1038         document.language = "english"
1039         i = find_token(document.header, "\\language", 0)
1040         if i != -1:
1041             document.header[i] = "\\language english"
1042     j = 0
1043     while True:
1044         j = find_token(document.body, "\\lang albanian", j)
1045         if j == -1:
1046             return
1047         document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1048         j = j + 1
1049
1050
1051 def revert_lowersorbian(document):
1052     "Set language lower Sorbian to English"
1053     i = 0
1054     if document.language == "lowersorbian":
1055         document.language = "english"
1056         i = find_token(document.header, "\\language", 0)
1057         if i != -1:
1058             document.header[i] = "\\language english"
1059     j = 0
1060     while True:
1061         j = find_token(document.body, "\\lang lowersorbian", j)
1062         if j == -1:
1063             return
1064         document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1065         j = j + 1
1066
1067
1068 def revert_uppersorbian(document):
1069     "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1070     i = 0
1071     if document.language == "uppersorbian":
1072         document.language = "usorbian"
1073         i = find_token(document.header, "\\language", 0)
1074         if i != -1:
1075             document.header[i] = "\\language usorbian"
1076     j = 0
1077     while True:
1078         j = find_token(document.body, "\\lang uppersorbian", j)
1079         if j == -1:
1080             return
1081         document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1082         j = j + 1
1083
1084
1085 def convert_usorbian(document):
1086     "Set language usorbian to uppersorbian"
1087     i = 0
1088     if document.language == "usorbian":
1089         document.language = "uppersorbian"
1090         i = find_token(document.header, "\\language", 0)
1091         if i != -1:
1092             document.header[i] = "\\language uppersorbian"
1093     j = 0
1094     while True:
1095         j = find_token(document.body, "\\lang usorbian", j)
1096         if j == -1:
1097             return
1098         document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1099         j = j + 1
1100
1101
1102 def revert_macro_optional_params(document):
1103     "Convert macro definitions with optional parameters into ERTs"
1104     # Stub to convert macro definitions with one or more optional parameters
1105     # into uninterpreted ERT insets
1106
1107
1108 def revert_hyperlinktype(document):
1109     'Reverts hyperlink type'
1110     i = 0
1111     j = 0
1112     while True:
1113       i = find_token(document.body, "target", i)
1114       if i == -1:
1115           return
1116       j = find_token(document.body, "type", i)
1117       if j == -1:
1118           return
1119       if j == i + 1:
1120           del document.body[j]
1121       i = i + 1
1122
1123
1124 def revert_pagebreak(document):
1125     'Reverts pagebreak to ERT'
1126     i = 0
1127     while True:
1128       i = find_token(document.body, "\\pagebreak", i)
1129       if i == -1:
1130           return
1131       document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1132       '\\begin_layout Standard\n\n\n\\backslash\n' \
1133       'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1134       i = i + 1
1135
1136
1137 def revert_linebreak(document):
1138     'Reverts linebreak to ERT'
1139     i = 0
1140     while True:
1141       i = find_token(document.body, "\\linebreak", i)
1142       if i == -1:
1143           return
1144       document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1145       '\\begin_layout Standard\n\n\n\\backslash\n' \
1146       'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1147       i = i + 1
1148
1149
1150 def revert_latin(document):
1151     "Set language Latin to English"
1152     i = 0
1153     if document.language == "latin":
1154         document.language = "english"
1155         i = find_token(document.header, "\\language", 0)
1156         if i != -1:
1157             document.header[i] = "\\language english"
1158     j = 0
1159     while True:
1160         j = find_token(document.body, "\\lang latin", j)
1161         if j == -1:
1162             return
1163         document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1164         j = j + 1
1165
1166
1167 def revert_samin(document):
1168     "Set language North Sami to English"
1169     i = 0
1170     if document.language == "samin":
1171         document.language = "english"
1172         i = find_token(document.header, "\\language", 0)
1173         if i != -1:
1174             document.header[i] = "\\language english"
1175     j = 0
1176     while True:
1177         j = find_token(document.body, "\\lang samin", j)
1178         if j == -1:
1179             return
1180         document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1181         j = j + 1
1182
1183
1184 def convert_serbocroatian(document):
1185     "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1186     i = 0
1187     if document.language == "serbocroatian":
1188         document.language = "croatian"
1189         i = find_token(document.header, "\\language", 0)
1190         if i != -1:
1191             document.header[i] = "\\language croatian"
1192     j = 0
1193     while True:
1194         j = find_token(document.body, "\\lang serbocroatian", j)
1195         if j == -1:
1196             return
1197         document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1198         j = j + 1
1199
1200
1201 def convert_framed_notes(document):
1202     "Convert framed notes to boxes. "
1203     i = 0
1204     while 1:
1205         i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1206
1207         if i == -1:
1208             return
1209         document.body[i] = document.body[i].replace("\\begin_inset Note", "\\begin_inset Box")
1210         document.body.insert(i + 1, 'position "t"\nhor_pos "c"\nhas_inner_box 0\ninner_pos "t"\n' \
1211         'use_parbox 0\nwidth "100col%"\nspecial "none"\nheight "1in"\n' \
1212         'height_special "totalheight"')
1213         i = i + 1
1214
1215
1216 def convert_module_names(document):
1217   modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1218     'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1219     'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1220     'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1221     'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1222   modlist = document.get_module_list()
1223   if len(modlist) == 0:
1224     return
1225   newmodlist = []
1226   for mod in modlist:
1227     if modulemap.has_key(mod):
1228       newmodlist.append(modulemap[mod])
1229     else:
1230       document.warning("Can't find module %s in the module map!" % mod)
1231       newmodlist.append(mod)
1232   document.set_module_list(newmodlist)
1233
1234
1235 def revert_module_names(document):
1236   modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1237     'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1238     'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1239     'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1240     'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1241   modlist = document.get_module_list()
1242   if len(modlist) == 0:
1243     return
1244   newmodlist = []
1245   for mod in modlist:
1246     if modulemap.has_key(mod):
1247       newmodlist.append(modulemap[mod])
1248     else:
1249       document.warning("Can't find module %s in the module map!" % mod)
1250       newmodlist.append(mod)
1251   document.set_module_list(newmodlist)
1252
1253
1254 def revert_colsep(document):
1255     i = find_token(document.header, "\\columnsep", 0)
1256     if i == -1:
1257         return
1258     colsepline = document.header[i]
1259     r = re.compile(r'\\columnsep (.*)')
1260     m = r.match(colsepline)
1261     if not m:
1262         document.warning("Malformed column separation line!")
1263         return
1264     colsep = m.group(1)
1265     del document.header[i]
1266     #it seems to be safe to add the package even if it is already used
1267     pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1268
1269     add_to_preamble(document, pretext)
1270
1271
1272 def revert_framed_notes(document):
1273     "Revert framed boxes to notes. "
1274     i = 0
1275     while 1:
1276         i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1277
1278         if i == -1:
1279             return
1280         j = find_end_of_inset(document.body, i + 1)
1281         if j == -1:
1282             # should not happen
1283             document.warning("Malformed LyX document: Could not find end of Box inset.")
1284         k = find_token(document.body, "status", i + 1, j)
1285         if k == -1:
1286             document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1287             return
1288         status = document.body[k]
1289         l = find_default_layout(document, i + 1, j)
1290         if l == -1:
1291             document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1292             return
1293         m = find_token(document.body, "\\end_layout", i + 1, j)
1294         if m == -1:
1295             document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1296             return
1297         ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1298         pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1299         if ibox == -1 and pbox == -1:
1300             document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1301             del document.body[i+1:k]
1302         else:
1303             document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1304             document.body.insert(l + 1, "\\begin_inset Note Shaded\n" + status + "\n\\begin_layout Standard\n")
1305             document.body.insert(m + 1, "\\end_layout\n\\end_inset")
1306         i = i + 1
1307
1308
1309 def revert_slash(document):
1310     'Revert \\SpecialChar \\slash{} to ERT'
1311     for i in range(len(document.body)):
1312         document.body[i] = document.body[i].replace('\\SpecialChar \\slash{}', \
1313         '\\begin_inset ERT\nstatus collapsed\n\n' \
1314         '\\begin_layout Standard\n\n\n\\backslash\n' \
1315         'slash{}\n\\end_layout\n\n\\end_inset\n\n')
1316
1317
1318 def revert_nobreakdash(document):
1319     'Revert \\SpecialChar \\nobreakdash- to ERT'
1320     found = 0
1321     for i in range(len(document.body)):
1322         line = document.body[i]
1323         r = re.compile(r'\\SpecialChar \\nobreakdash-')
1324         m = r.match(line)
1325         if m:
1326             found = 1
1327         document.body[i] = document.body[i].replace('\\SpecialChar \\nobreakdash-', \
1328         '\\begin_inset ERT\nstatus collapsed\n\n' \
1329         '\\begin_layout Standard\n\n\n\\backslash\n' \
1330         'nobreakdash-\n\\end_layout\n\n\\end_inset\n\n')
1331     if not found:
1332         return
1333     j = find_token(document.header, "\\use_amsmath", 0)
1334     if j == -1:
1335         document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1336         return
1337     document.header[j] = "\\use_amsmath 2"
1338
1339
1340 def revert_nocite_key(body, start, end):
1341     'key "..." -> \nocite{...}'
1342     for i in range(start, end):
1343         if (body[i][0:5] == 'key "'):
1344             body[i] = body[i].replace('key "', "\\backslash\nnocite{")
1345             body[i] = body[i].replace('"', "}")
1346         else:
1347             body[i] = ""
1348
1349
1350 def revert_nocite(document):
1351     "Revert LatexCommand nocite to ERT"
1352     i = 0
1353     while 1:
1354         i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1355         if i == -1:
1356             return
1357         i = i + 1
1358         if (document.body[i] == "LatexCommand nocite"):
1359             j = find_end_of_inset(document.body, i + 1)
1360             if j == -1:
1361                 #this should not happen
1362                 document.warning("End of CommandInset citation not found in revert_nocite!")
1363                 revert_nocite_key(document.body, i + 1, len(document.body))
1364                 return
1365             revert_nocite_key(document.body, i + 1, j)
1366             document.body[i-1] = "\\begin_inset ERT"
1367             document.body[i] = "status collapsed\n\n" \
1368             "\\begin_layout Standard"
1369             document.body.insert(j, "\\end_layout\n");
1370             i = j
1371
1372
1373 def revert_btprintall(document):
1374     "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1375     i = find_token(document.header, '\\use_bibtopic', 0)
1376     if i == -1:
1377         document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1378         return
1379     if get_value(document.header, '\\use_bibtopic', 0) == "false":
1380         i = 0
1381         while i < len(document.body):
1382             i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1383             if i == -1:
1384                 return
1385             j = find_end_of_inset(document.body, i + 1)
1386             if j == -1:
1387                 #this should not happen
1388                 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1389                 j = len(document.body)
1390             for k in range(i, j):
1391                 if (document.body[k] == 'btprint "btPrintAll"'):
1392                     del document.body[k]
1393                     document.body.insert(i, "\\begin_inset ERT\n" \
1394                     "status collapsed\n\n\\begin_layout Standard\n\n" \
1395                     "\\backslash\nnocite{*}\n" \
1396                     "\\end_layout\n\\end_inset\n")
1397             i = j
1398
1399
1400 def revert_bahasam(document):
1401     "Set language Bahasa Malaysia to Bahasa Indonesia"
1402     i = 0
1403     if document.language == "bahasam":
1404         document.language = "bahasa"
1405         i = find_token(document.header, "\\language", 0)
1406         if i != -1:
1407             document.header[i] = "\\language bahasa"
1408     j = 0
1409     while True:
1410         j = find_token(document.body, "\\lang bahasam", j)
1411         if j == -1:
1412             return
1413         document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1414         j = j + 1
1415
1416
1417 def revert_interlingua(document):
1418     "Set language Interlingua to English"
1419     i = 0
1420     if document.language == "interlingua":
1421         document.language = "english"
1422         i = find_token(document.header, "\\language", 0)
1423         if i != -1:
1424             document.header[i] = "\\language english"
1425     j = 0
1426     while True:
1427         j = find_token(document.body, "\\lang interlingua", j)
1428         if j == -1:
1429             return
1430         document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1431         j = j + 1
1432
1433
1434 def revert_serbianlatin(document):
1435     "Set language Serbian-Latin to Croatian"
1436     i = 0
1437     if document.language == "serbian-latin":
1438         document.language = "croatian"
1439         i = find_token(document.header, "\\language", 0)
1440         if i != -1:
1441             document.header[i] = "\\language croatian"
1442     j = 0
1443     while True:
1444         j = find_token(document.body, "\\lang serbian-latin", j)
1445         if j == -1:
1446             return
1447         document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1448         j = j + 1
1449
1450
1451 def revert_rotfloat(document):
1452     " Revert sideways custom floats. "
1453     i = 0
1454     while 1:
1455         i = find_token(document.body, "\\begin_inset Float", i)
1456         if i == -1:
1457             return
1458         line = document.body[i]
1459         r = re.compile(r'\\begin_inset Float (.*)$')
1460         m = r.match(line)
1461         floattype = m.group(1)
1462         if floattype == "figure" or floattype == "table":
1463             i = i + 1
1464             continue
1465         j = find_end_of_inset(document.body, i)
1466         if j == -1:
1467             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1468             i = i + 1
1469             continue
1470         if get_value(document.body, 'sideways', i, j) != "false":
1471             l = find_default_layout(doc, i + 1, j)
1472             if l == -1:
1473                 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1474                 return
1475             document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1476             '\\begin_layout Standard\n\n\n\\backslash\n' \
1477             'end{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n'
1478             del document.body[i+1:l-1]
1479             document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1480             '\\begin_layout Standard\n\n\n\\backslash\n' \
1481             'begin{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1482             if floattype == "algorithm":
1483                 add_to_preamble(document,
1484                                 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1485                                  '\\usepackage{rotfloat}\n'
1486                                  '\\floatstyle{ruled}\n'
1487                                  '\\newfloat{algorithm}{tbp}{loa}\n'
1488                                  '\\floatname{algorithm}{Algorithm}\n'])
1489             else:
1490                 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1491             i = i + 1
1492             continue
1493         i = i + 1
1494
1495
1496 def revert_widesideways(document):
1497     " Revert wide sideways floats. "
1498     i = 0
1499     while 1:
1500         i = find_token(document.body, '\\begin_inset Float', i)
1501         if i == -1:
1502             return
1503         line = document.body[i]
1504         r = re.compile(r'\\begin_inset Float (.*)$')
1505         m = r.match(line)
1506         floattype = m.group(1)
1507         if floattype != "figure" and floattype != "table":
1508             i = i + 1
1509             continue
1510         j = find_end_of_inset(document.body, i)
1511         if j == -1:
1512             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1513             i = i + 1
1514             continue
1515         if get_value(document.body, 'sideways', i, j) != "false":
1516             if get_value(document.body, 'wide', i, j) != "false":
1517                 l = find_default_layout(document, i + 1, j)
1518                 if l == -1:
1519                     document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1520                     return
1521                 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1522                 '\\begin_layout Standard\n\n\n\\backslash\n' \
1523                 'end{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n'
1524                 del document.body[i+1:l-1]
1525                 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1526                 '\\begin_layout Standard\n\n\n\\backslash\n' \
1527                 'begin{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1528                 add_to_preamble(document,
1529                                 ['\\usepackage{rotfloat}\n'])
1530                 i = i + 1
1531                 continue
1532         i = i + 1
1533
1534
1535 def revert_external_embedding(document):
1536     ' Remove embed tag from external inset '
1537     i = 0
1538     while 1:
1539         i = find_token(document.body, "\\begin_inset External", i)
1540         if i == -1:
1541             return
1542         j = find_end_of_inset(document.body, i)
1543         if j == -1:
1544             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1545             i = i + 1
1546             continue
1547         k = find_token(document.body, "\tembed", i, j)
1548         if k != -1:
1549             del document.body[k]
1550         i = i + 1
1551
1552
1553 def convert_subfig(document):
1554     " Convert subfigures to subfloats. "
1555     i = 0
1556     while 1:
1557         i = find_token(document.body, '\\begin_inset Graphics', i)
1558         if i == -1:
1559             return
1560         j = find_end_of_inset(document.body, i)
1561         if j == -1:
1562             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1563             i = i + 1
1564             continue
1565         k = find_token(document.body, '\tsubcaption', i, j)
1566         if k == -1:
1567             i = i + 1
1568             continue
1569         l = find_token(document.body, '\tsubcaptionText', i, j)
1570         caption = document.body[l][16:].strip('"')
1571         savestr = document.body[i]
1572         del document.body[l]
1573         del document.body[k]
1574         document.body[i] = '\\begin_inset Float figure\nwide false\nsideways false\n' \
1575         'status open\n\n\\begin_layout Plain Layout\n\\begin_inset Caption\n\n\\begin_layout Plain Layout\n' \
1576         + caption + '\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout Plain Layout\n' + savestr
1577         savestr = document.body[j]
1578         document.body[j] = '\n\\end_layout\n\n\\end_inset\n' + savestr
1579
1580
1581 def revert_subfig(document):
1582     " Revert subfloats. "
1583     i = 0
1584     while 1:
1585         i = find_token(document.body, '\\begin_inset Float', i)
1586         if i == -1:
1587             return
1588         while 1:
1589             j = find_end_of_inset(document.body, i)
1590             if j == -1:
1591                 document.warning("Malformed lyx document: Missing '\\end_inset' (float).")
1592                 i = i + 1
1593                 continue
1594             # look for embedded float (= subfloat)
1595             k = find_token(document.body, '\\begin_inset Float', i + 1, j)
1596             if k == -1:
1597                 break
1598             l = find_end_of_inset(document.body, k)
1599             if l == -1:
1600                 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
1601                 i = i + 1
1602                 continue
1603             m = find_default_layout(document.body, k + 1, l)
1604             # caption?
1605             cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
1606             caption = ''
1607             shortcap = ''
1608             if cap != -1:
1609                 capend = find_end_of_inset(document.body, cap)
1610                 if capend == -1:
1611                     document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
1612                     return
1613                 # label?
1614                 label = ''
1615                 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
1616                 if lbl != -1:
1617                     lblend = find_end_of_inset(document.body, lbl + 1)
1618                     if lblend == -1:
1619                         document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
1620                         return
1621                     for line in document.body[lbl:lblend + 1]:
1622                         if line.startswith('name '):
1623                             label = line.split()[1].strip('"')
1624                             break
1625                 else:
1626                     lbl = capend
1627                     lblend = capend
1628                     label = ''
1629                 # opt arg?
1630                 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
1631                 if opt != -1:
1632                     optend = find_end_of_inset(document.body, opt)
1633                     if optend == -1:
1634                         document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
1635                         return
1636                     optc = find_default_layout(document.body, opt, optend)
1637                     if optc == -1:
1638                         document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1639                         return
1640                     optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
1641                     for line in document.body[optc:optcend]:
1642                         if not line.startswith('\\'):
1643                             shortcap += line.strip()
1644                 else:
1645                     opt = capend
1646                     optend = capend
1647                 for line in document.body[cap:capend]:
1648                     if line in document.body[lbl:lblend]:
1649                         continue
1650                     elif line in document.body[opt:optend]:
1651                         continue
1652                     elif not line.startswith('\\'):
1653                         caption += line.strip()
1654                 if len(label) > 0:
1655                     caption += "\\backslash\nlabel{" + label + "}"
1656             document.body[l] = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
1657             '\\begin_layout Plain Layout\n\n}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout Plain Layout\n'
1658             del document.body[cap:capend+1]
1659             del document.body[k+1:m-1]
1660             insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
1661             '\\begin_layout Plain Layout\n\n\\backslash\n' \
1662             'subfloat'
1663             if len(shortcap) > 0:
1664                 insertion = insertion + "[" + shortcap + "]"
1665             if len(caption) > 0:
1666                 insertion = insertion + "[" + caption + "]"
1667             insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
1668             document.body[k] = insertion
1669             add_to_preamble(document,
1670                             ['\\usepackage{subfig}\n'])
1671         i = i + 1
1672
1673
1674 def revert_wrapplacement(document):
1675     " Revert placement options wrap floats (wrapfig). "
1676     i = 0
1677     while True:
1678         i = find_token(document.body, "lines", i)
1679         if i == -1:
1680             return
1681         j = find_token(document.body, "placement", i+1)
1682         if j != i + 1:
1683             document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
1684             return
1685         document.body[j] = document.body[j].replace("placement O", "placement o")
1686         document.body[j] = document.body[j].replace("placement I", "placement i")
1687         document.body[j] = document.body[j].replace("placement L", "placement l")
1688         document.body[j] = document.body[j].replace("placement R", "placement r")
1689         i = i + 1
1690
1691
1692 def remove_extra_embedded_files(document):
1693     " Remove \extra_embedded_files from buffer params "
1694     i = find_token(document.header, '\\extra_embedded_files', 0)
1695     if i == -1:
1696         document.warning("Malformed lyx document: Missing '\\extra_embedded_files'.")
1697         return
1698     document.header.pop(i)
1699
1700
1701 def convert_spaceinset(document):
1702     " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
1703     for i in range(len(document.body)):
1704         if re.search(r'\InsetSpace', document.body[i]):
1705             document.body[i] = document.body[i].replace('\\InsetSpace', '\n\\begin_inset Space')
1706             document.body[i] = document.body[i] + "\n\\end_inset"
1707
1708
1709 def revert_spaceinset(document):
1710     " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
1711     i = 0
1712     while True:
1713         i = find_token(document.body, "\\begin_inset Space", i)
1714         if i == -1:
1715             return
1716         j = find_end_of_inset(document.body, i)
1717         if j == -1:
1718             document.warning("Malformed LyX document: Could not find end of space inset.")
1719             continue
1720         document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
1721         del document.body[j]
1722
1723
1724 def convert_hfill(document):
1725     " Convert hfill to space inset "
1726     i = 0
1727     while True:
1728         i = find_token(document.body, "\\hfill", i)
1729         if i == -1:
1730             return
1731         document.body[i] = document.body[i].replace('\\hfill', '\n\\begin_inset Space \\hfill{}\n\\end_inset')
1732
1733
1734 def revert_hfills(document):
1735     ' Revert \\hfill commands '
1736     for i in range(len(document.body)):
1737         document.body[i] = document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
1738         document.body[i] = document.body[i].replace('\\InsetSpace \\dotfill{}', \
1739         '\\begin_inset ERT\nstatus collapsed\n\n' \
1740         '\\begin_layout Standard\n\n\n\\backslash\n' \
1741         'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
1742         document.body[i] = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
1743         '\\begin_inset ERT\nstatus collapsed\n\n' \
1744         '\\begin_layout Standard\n\n\n\\backslash\n' \
1745         'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
1746
1747
1748 def revert_hspace(document):
1749     ' Revert \\InsetSpace \\hspace{} to ERT '
1750     i = 0
1751     while True:
1752         i = find_token(document.body, "\\InsetSpace \\hspace", i)
1753         if i == -1:
1754             return
1755         length = get_value(document.body, '\\length', i+1)
1756         if length == '':
1757             document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
1758             return
1759         del document.body[i+1]
1760         document.body[i] = document.body[i].replace('\\InsetSpace \\hspace*{}', \
1761         '\\begin_inset ERT\nstatus collapsed\n\n' \
1762         '\\begin_layout Standard\n\n\n\\backslash\n' \
1763         'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
1764         document.body[i] = document.body[i].replace('\\InsetSpace \\hspace{}', \
1765         '\\begin_inset ERT\nstatus collapsed\n\n' \
1766         '\\begin_layout Standard\n\n\n\\backslash\n' \
1767         'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
1768
1769
1770 def revert_protected_hfill(document):
1771     ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
1772     i = 0
1773     while True:
1774         i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
1775         if i == -1:
1776             return
1777         j = find_end_of_inset(document.body, i)
1778         if j == -1:
1779             document.warning("Malformed LyX document: Could not find end of space inset.")
1780             continue
1781         del document.body[j]
1782         document.body[i] = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
1783         '\\begin_inset ERT\nstatus collapsed\n\n' \
1784         '\\begin_layout Standard\n\n\n\\backslash\n' \
1785         'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
1786
1787
1788 def revert_local_layout(document):
1789     ' Revert local layout headers.'
1790     i = 0
1791     while True:
1792         i = find_token(document.header, "\\begin_local_layout", i)
1793         if i == -1:
1794             return
1795         j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
1796         if j == -1:
1797             # this should not happen
1798             break
1799         document.header[i : j + 1] = []
1800
1801
1802 def convert_pagebreaks(document):
1803     ' Convert inline Newpage insets to new format '
1804     i = 0
1805     while True:
1806         i = find_token(document.body, '\\newpage', i)
1807         if i == -1:
1808             break
1809         document.body[i:i+1] = ['\\begin_inset Newpage newpage',
1810                              '\\end_inset']
1811     i = 0
1812     while True:
1813         i = find_token(document.body, '\\pagebreak', i)
1814         if i == -1:
1815             break
1816         document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
1817                              '\\end_inset']
1818     i = 0
1819     while True:
1820         i = find_token(document.body, '\\clearpage', i)
1821         if i == -1:
1822             break
1823         document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
1824                              '\\end_inset']
1825     i = 0
1826     while True:
1827         i = find_token(document.body, '\\cleardoublepage', i)
1828         if i == -1:
1829             break
1830         document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
1831                              '\\end_inset']
1832
1833
1834 def revert_pagebreaks(document):
1835     ' Revert \\begin_inset Newpage to previous inline format '
1836     i = 0
1837     while True:
1838         i = find_token(document.body, '\\begin_inset Newpage', i)
1839         if i == -1:
1840             return
1841         j = find_end_of_inset(document.body, i)
1842         if j == -1:
1843             document.warning("Malformed LyX document: Could not find end of Newpage inset.")
1844             continue
1845         del document.body[j]
1846         document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
1847         document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
1848         document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
1849         document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
1850
1851
1852 def convert_linebreaks(document):
1853     ' Convert inline Newline insets to new format '
1854     i = 0
1855     while True:
1856         i = find_token(document.body, '\\newline', i)
1857         if i == -1:
1858             break
1859         document.body[i:i+1] = ['\\begin_inset Newline newline',
1860                              '\\end_inset']
1861     i = 0
1862     while True:
1863         i = find_token(document.body, '\\linebreak', i)
1864         if i == -1:
1865             break
1866         document.body[i:i+1] = ['\\begin_inset Newline linebreak',
1867                              '\\end_inset']
1868
1869
1870 def revert_linebreaks(document):
1871     ' Revert \\begin_inset Newline to previous inline format '
1872     i = 0
1873     while True:
1874         i = find_token(document.body, '\\begin_inset Newline', i)
1875         if i == -1:
1876             return
1877         j = find_end_of_inset(document.body, i)
1878         if j == -1:
1879             document.warning("Malformed LyX document: Could not find end of Newline inset.")
1880             continue
1881         del document.body[j]
1882         document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
1883         document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
1884
1885
1886 def convert_japanese_plain(document):
1887     ' Set language japanese-plain to japanese '
1888     i = 0
1889     if document.language == "japanese-plain":
1890         document.language = "japanese"
1891         i = find_token(document.header, "\\language", 0)
1892         if i != -1:
1893             document.header[i] = "\\language japanese"
1894     j = 0
1895     while True:
1896         j = find_token(document.body, "\\lang japanese-plain", j)
1897         if j == -1:
1898             return
1899         document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
1900         j = j + 1
1901
1902
1903 def revert_pdfpages(document):
1904     ' Revert pdfpages external inset to ERT '
1905     i = 0
1906     while 1:
1907         i = find_token(document.body, "\\begin_inset External", i)
1908         if i == -1:
1909             return
1910         j = find_end_of_inset(document.body, i)
1911         if j == -1:
1912             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1913             i = i + 1
1914             continue
1915         if get_value(document.body, 'template', i, j) == "PDFPages":
1916             filename = get_value(document.body, 'filename', i, j)
1917             extra = ''
1918             r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
1919             for k in range(i, j):
1920                 m = r.match(document.body[k])
1921                 if m:
1922                     extra = m.group(1)
1923             angle = get_value(document.body, 'rotateAngle', i, j)
1924             width = get_value(document.body, 'width', i, j)
1925             height = get_value(document.body, 'height', i, j)
1926             scale = get_value(document.body, 'scale', i, j)
1927             keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
1928             options = extra
1929             if angle != '':
1930                  if options != '':
1931                      options += ",angle=" + angle
1932                  else:
1933                      options += "angle=" + angle
1934             if width != '':
1935                  if options != '':
1936                      options += ",width=" + convert_len(width)
1937                  else:
1938                      options += "width=" + convert_len(width)
1939             if height != '':
1940                  if options != '':
1941                      options += ",height=" + convert_len(height)
1942                  else:
1943                      options += "height=" + convert_len(height)
1944             if scale != '':
1945                  if options != '':
1946                      options += ",scale=" + scale
1947                  else:
1948                      options += "scale=" + scale
1949             if keepAspectRatio != '':
1950                  if options != '':
1951                      options += ",keepaspectratio"
1952                  else:
1953                      options += "keepaspectratio"
1954             if options != '':
1955                      options = '[' + options + ']'
1956             del document.body[i+1:j+1]
1957             document.body[i:i+1] = ['\\begin_inset ERT',
1958                                 'status collapsed',
1959                                 '',
1960                                 '\\begin_layout Standard',
1961                                 '',
1962                                 '\\backslash',
1963                                 'includepdf' + options + '{' + filename + '}',
1964                                 '\\end_layout',
1965                                 '',
1966                                 '\\end_inset']
1967             add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
1968             i = i + 1
1969             continue
1970         i = i + 1
1971
1972
1973 ##
1974 # Conversion hub
1975 #
1976
1977 supported_versions = ["1.6.0","1.6"]
1978 convert = [[277, [fix_wrong_tables]],
1979            [278, [close_begin_deeper]],
1980            [279, [long_charstyle_names]],
1981            [280, [axe_show_label]],
1982            [281, []],
1983            [282, []],
1984            [283, [convert_flex]],
1985            [284, []],
1986            [285, []],
1987            [286, []],
1988            [287, [convert_wrapfig_options]],
1989            [288, [convert_inset_command]],
1990            [289, [convert_latexcommand_index]],
1991            [290, []],
1992            [291, []],
1993            [292, []],
1994            [293, []],
1995            [294, [convert_pdf_options]],
1996            [295, [convert_htmlurl, convert_url]],
1997            [296, [convert_include]],
1998            [297, [convert_usorbian]],
1999            [298, []],
2000            [299, []],
2001            [300, []],
2002            [301, []],
2003            [302, []],
2004            [303, [convert_serbocroatian]],
2005            [304, [convert_framed_notes]],
2006            [305, []],
2007            [306, []],
2008            [307, []],
2009            [308, []],
2010            [309, []],
2011            [310, []],
2012            [311, [convert_ams_classes]],
2013            [312, []],
2014            [313, [convert_module_names]],
2015            [314, []],
2016            [315, []],
2017            [316, [convert_subfig]],
2018            [317, []],
2019            [318, []],
2020            [319, [convert_spaceinset, convert_hfill]],
2021            [320, []],
2022            [321, [convert_tablines]],
2023            [322, []],
2024            [323, [convert_pagebreaks]],
2025            [324, [convert_linebreaks]],
2026            [325, [convert_japanese_plain]],
2027            [326, []]
2028           ]
2029
2030 revert =  [[325, [revert_pdfpages]],
2031            [324, []],
2032            [323, [revert_linebreaks]],
2033            [322, [revert_pagebreaks]],
2034            [321, [revert_local_layout]],
2035            [320, [revert_tablines]],
2036            [319, [revert_protected_hfill]],
2037            [318, [revert_spaceinset, revert_hfills, revert_hspace]],
2038            [317, [remove_extra_embedded_files]],
2039            [316, [revert_wrapplacement]],
2040            [315, [revert_subfig]],
2041            [314, [revert_colsep]],
2042            [313, []],
2043            [312, [revert_module_names]],
2044            [311, [revert_rotfloat, revert_widesideways]],
2045            [310, [revert_external_embedding]],
2046            [309, [revert_btprintall]],
2047            [308, [revert_nocite]],
2048            [307, [revert_serbianlatin]],
2049            [306, [revert_slash, revert_nobreakdash]],
2050            [305, [revert_interlingua]],
2051            [304, [revert_bahasam]],
2052            [303, [revert_framed_notes]],
2053            [302, []],
2054            [301, [revert_latin, revert_samin]],
2055            [300, [revert_linebreak]],
2056            [299, [revert_pagebreak]],
2057            [298, [revert_hyperlinktype]],
2058            [297, [revert_macro_optional_params]],
2059            [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
2060            [295, [revert_include]],
2061            [294, [revert_href]],
2062            [293, [revert_pdf_options_2]],
2063            [292, [revert_inset_info]],
2064            [291, [revert_japanese, revert_japanese_encoding]],
2065            [290, [revert_vietnamese]],
2066            [289, [revert_wraptable]],
2067            [288, [revert_latexcommand_index]],
2068            [287, [revert_inset_command]],
2069            [286, [revert_wrapfig_options]],
2070            [285, [revert_pdf_options]],
2071            [284, [remove_inzip_options]],
2072            [283, []],
2073            [282, [revert_flex]],
2074            [281, []],
2075            [280, [revert_begin_modules]],
2076            [279, [revert_show_label]],
2077            [278, [revert_long_charstyle_names]],
2078            [277, []],
2079            [276, []]
2080           ]
2081
2082
2083 if __name__ == "__main__":
2084     pass