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