]> git.lyx.org Git - features.git/blob - lib/lyx2lyx/lyx_1_6.py
Check for Plain Layout as well as for Standard in these cases. We should always do...
[features.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("\\begin_layout Plain"):
718             line = line[22:]
719           if line.startswith("\\end_layout"):
720             line = line[11:]
721           if line.startswith("\\end_inset"):
722             line = line[10:]
723           if line.startswith("status collapsed"):
724             line = line[16:]
725           line = line.replace(u'ä', r'\\\"a').replace(u'ö', r'\\\"o').replace(u'ü', r'\\\"u')
726           content = content + line;
727         document.body[i + 3] = "name " + '"' + content + '"'
728         for k in range(i + 4, j - 2):
729           del document.body[i + 4]
730         document.body.insert(i + 4, "")
731         del document.body[i + 2] # \begin_layout standard
732         i = i + 5
733
734
735 def revert_wraptable(document):
736     "Revert wrap table to wrap figure."
737     i = 0
738     while True:
739         i = find_token(document.body, "\\begin_inset Wrap table", i)
740         if i == -1:
741             return
742         document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
743         i = i + 1
744
745
746 def revert_vietnamese(document):
747     "Set language Vietnamese to English"
748     # Set document language from Vietnamese to English
749     i = 0
750     if document.language == "vietnamese":
751         document.language = "english"
752         i = find_token(document.header, "\\language", 0)
753         if i != -1:
754             document.header[i] = "\\language english"
755     j = 0
756     while True:
757         j = find_token(document.body, "\\lang vietnamese", j)
758         if j == -1:
759             return
760         document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
761         j = j + 1
762
763
764 def revert_japanese(document):
765     "Set language japanese-plain to japanese"
766     # Set document language from japanese-plain to japanese
767     i = 0
768     if document.language == "japanese-plain":
769         document.language = "japanese"
770         i = find_token(document.header, "\\language", 0)
771         if i != -1:
772             document.header[i] = "\\language japanese"
773     j = 0
774     while True:
775         j = find_token(document.body, "\\lang japanese-plain", j)
776         if j == -1:
777             return
778         document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
779         j = j + 1
780
781
782 def revert_japanese_encoding(document):
783     "Set input encoding form EUC-JP-plain to EUC-JP etc."
784     # Set input encoding form EUC-JP-plain to EUC-JP etc.
785     i = 0
786     i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
787     if i != -1:
788         document.header[i] = "\\inputencoding EUC-JP"
789     j = 0
790     j = find_token(document.header, "\\inputencoding JIS-plain", 0)
791     if j != -1:
792         document.header[j] = "\\inputencoding JIS"
793     k = 0
794     k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
795     if k != -1: # convert to UTF8 since there is currently no SJIS encoding
796         document.header[k] = "\\inputencoding UTF8"
797
798
799 def revert_inset_info(document):
800     'Replace info inset with its content'
801     i = 0
802     while 1:
803         i = find_token(document.body, '\\begin_inset Info', i)
804         if i == -1:
805             return
806         j = find_end_of_inset(document.body, i + 1)
807         if j == -1:
808             # should not happen
809             document.warning("Malformed LyX document: Could not find end of Info inset.")
810         type = 'unknown'
811         arg = ''
812         for k in range(i, j+1):
813             if document.body[k].startswith("arg"):
814                 arg = document.body[k][3:].strip().strip('"')
815             if document.body[k].startswith("type"):
816                 type = document.body[k][4:].strip().strip('"')
817         # I think there is a newline after \\end_inset, which should be removed.
818         if document.body[j + 1].strip() == "":
819             document.body[i : (j + 2)] = [type + ':' + arg]
820         else:
821             document.body[i : (j + 1)] = [type + ':' + arg]
822
823
824 def convert_pdf_options(document):
825     # Set the pdfusetitle tag, delete the pdf_store_options,
826     # set quotes for bookmarksopenlevel"
827     has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
828     if has_hr == "1":
829         k = find_token(document.header, "\\use_hyperref", 0)
830         document.header.insert(k + 1, "\\pdf_pdfusetitle true")
831     k = find_token(document.header, "\\pdf_store_options", 0)
832     if k != -1:
833         del document.header[k]
834     i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
835     if i == -1: return
836     document.header[i] = document.header[i].replace('"', '')
837
838
839 def revert_pdf_options_2(document):
840     # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
841     k = find_token(document.header, "\\use_hyperref", 0)
842     i = find_token(document.header, "\\pdf_pdfusetitle", k)
843     if i != -1:
844         del document.header[i]
845     i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
846     if i == -1: return
847     values = document.header[i].split()
848     values[1] = ' "' + values[1] + '"'
849     document.header[i] = ''.join(values)
850
851
852 def convert_htmlurl(document):
853     'Convert "htmlurl" to "href" insets for docbook'
854     if document.backend != "docbook":
855       return
856     i = 0
857     while True:
858       i = find_token(document.body, "\\begin_inset CommandInset url", i)
859       if i == -1:
860         return
861       document.body[i] = "\\begin_inset CommandInset href"
862       document.body[i + 1] = "LatexCommand href"
863       i = i + 1
864
865
866 def convert_url(document):
867     'Convert url insets to url charstyles'
868     if document.backend == "docbook":
869       return
870     i = 0
871     while True:
872       i = find_token(document.body, "\\begin_inset CommandInset url", i)
873       if i == -1:
874         break
875       n = find_token(document.body, "name", i)
876       if n == i + 2:
877         # place the URL name in typewriter before the new URL insert
878         # grab the name 'bla' from the e.g. the line 'name "bla"',
879         # therefore start with the 6th character
880         name = document.body[n][6:-1]
881         newname = [name + " "]
882         document.body[i:i] = newname
883         i = i + 1
884       j = find_token(document.body, "target", i)
885       if j == -1:
886         document.warning("Malformed LyX document: Can't find target for url inset")
887         i = j
888         continue
889       target = document.body[j][8:-1]
890       k = find_token(document.body, "\\end_inset", j)
891       if k == -1:
892         document.warning("Malformed LyX document: Can't find end of url inset")
893         i = k
894         continue
895       newstuff = ["\\begin_inset Flex URL",
896         "status collapsed", "",
897         "\\begin_layout Standard",
898         "",
899         target,
900         "\\end_layout",
901         ""]
902       document.body[i:k] = newstuff
903       i = k
904
905 def convert_ams_classes(document):
906   tc = document.textclass
907   if (tc != "amsart" and tc != "amsart-plain" and
908       tc != "amsart-seq" and tc != "amsbook"):
909     return
910   if tc == "amsart-plain":
911     document.textclass = "amsart"
912     document.set_textclass()
913     document.add_module("Theorems (Starred)")
914     return
915   if tc == "amsart-seq":
916     document.textclass = "amsart"
917     document.set_textclass()
918   document.add_module("Theorems (AMS)")
919
920   #Now we want to see if any of the environments in the extended theorems
921   #module were used in this document. If so, we'll add that module, too.
922   layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note",  \
923     "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
924     "Assumption"]
925
926   r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
927   i = 0
928   while True:
929     i = find_token(document.body, "\\begin_layout", i)
930     if i == -1:
931       return
932     m = r.match(document.body[i])
933     if m == None:
934       document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
935       i += 1
936       continue
937     m = m.group(1)
938     if layouts.count(m) != 0:
939       document.add_module("Theorems (AMS-Extended)")
940       return
941     i += 1
942
943 def revert_href(document):
944     'Reverts hyperlink insets (href) to url insets (url)'
945     i = 0
946     while True:
947       i = find_token(document.body, "\\begin_inset CommandInset href", i)
948       if i == -1:
949           return
950       document.body[i : i + 2] = \
951         ["\\begin_inset CommandInset url", "LatexCommand url"]
952       i = i + 2
953
954
955 def convert_include(document):
956   'Converts include insets to new format.'
957   i = 0
958   r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
959   while True:
960     i = find_token(document.body, "\\begin_inset Include", i)
961     if i == -1:
962       return
963     line = document.body[i]
964     previewline = document.body[i + 1]
965     m = r.match(line)
966     if m == None:
967       document.warning("Unable to match line " + str(i) + " of body!")
968       i += 1
969       continue
970     cmd = m.group(1)
971     fn  = m.group(2)
972     opt = m.group(3)
973     insertion = ["\\begin_inset CommandInset include",
974        "LatexCommand " + cmd, previewline,
975        "filename \"" + fn + "\""]
976     newlines = 2
977     if opt:
978       insertion.append("lstparams " + '"' + opt + '"')
979       newlines += 1
980     document.body[i : i + 2] = insertion
981     i += newlines
982
983
984 def revert_include(document):
985   'Reverts include insets to old format.'
986   i = 0
987   r1 = re.compile('LatexCommand (.+)')
988   r2 = re.compile('filename (.+)')
989   r3 = re.compile('options (.*)')
990   while True:
991     i = find_token(document.body, "\\begin_inset CommandInset include", i)
992     if i == -1:
993       return
994     previewline = document.body[i + 1]
995     m = r1.match(document.body[i + 2])
996     if m == None:
997       document.warning("Malformed LyX document: No LatexCommand line for `" +
998         document.body[i] + "' on line " + str(i) + ".")
999       i += 1
1000       continue
1001     cmd = m.group(1)
1002     m = r2.match(document.body[i + 3])
1003     if m == None:
1004       document.warning("Malformed LyX document: No filename line for `" + \
1005         document.body[i] + "' on line " + str(i) + ".")
1006       i += 2
1007       continue
1008     fn = m.group(1)
1009     options = ""
1010     numlines = 4
1011     if (cmd == "lstinputlisting"):
1012       m = r3.match(document.body[i + 4])
1013       if m != None:
1014         options = m.group(1)
1015         numlines = 5
1016     newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1017     if options:
1018       newline += ("[" + options + "]")
1019     insertion = [newline, previewline]
1020     document.body[i : i + numlines] = insertion
1021     i += 2
1022
1023
1024 def revert_albanian(document):
1025     "Set language Albanian to English"
1026     i = 0
1027     if document.language == "albanian":
1028         document.language = "english"
1029         i = find_token(document.header, "\\language", 0)
1030         if i != -1:
1031             document.header[i] = "\\language english"
1032     j = 0
1033     while True:
1034         j = find_token(document.body, "\\lang albanian", j)
1035         if j == -1:
1036             return
1037         document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1038         j = j + 1
1039
1040
1041 def revert_lowersorbian(document):
1042     "Set language lower Sorbian to English"
1043     i = 0
1044     if document.language == "lowersorbian":
1045         document.language = "english"
1046         i = find_token(document.header, "\\language", 0)
1047         if i != -1:
1048             document.header[i] = "\\language english"
1049     j = 0
1050     while True:
1051         j = find_token(document.body, "\\lang lowersorbian", j)
1052         if j == -1:
1053             return
1054         document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1055         j = j + 1
1056
1057
1058 def revert_uppersorbian(document):
1059     "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1060     i = 0
1061     if document.language == "uppersorbian":
1062         document.language = "usorbian"
1063         i = find_token(document.header, "\\language", 0)
1064         if i != -1:
1065             document.header[i] = "\\language usorbian"
1066     j = 0
1067     while True:
1068         j = find_token(document.body, "\\lang uppersorbian", j)
1069         if j == -1:
1070             return
1071         document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1072         j = j + 1
1073
1074
1075 def convert_usorbian(document):
1076     "Set language usorbian to uppersorbian"
1077     i = 0
1078     if document.language == "usorbian":
1079         document.language = "uppersorbian"
1080         i = find_token(document.header, "\\language", 0)
1081         if i != -1:
1082             document.header[i] = "\\language uppersorbian"
1083     j = 0
1084     while True:
1085         j = find_token(document.body, "\\lang usorbian", j)
1086         if j == -1:
1087             return
1088         document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1089         j = j + 1
1090
1091
1092 def revert_macro_optional_params(document):
1093     "Convert macro definitions with optional parameters into ERTs"
1094     # Stub to convert macro definitions with one or more optional parameters
1095     # into uninterpreted ERT insets
1096
1097
1098 def revert_hyperlinktype(document):
1099     'Reverts hyperlink type'
1100     i = 0
1101     j = 0
1102     while True:
1103       i = find_token(document.body, "target", i)
1104       if i == -1:
1105           return
1106       j = find_token(document.body, "type", i)
1107       if j == -1:
1108           return
1109       if j == i + 1:
1110           del document.body[j]
1111       i = i + 1
1112
1113
1114 def revert_pagebreak(document):
1115     'Reverts pagebreak to ERT'
1116     i = 0
1117     while True:
1118       i = find_token(document.body, "\\pagebreak", i)
1119       if i == -1:
1120           return
1121       document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1122       '\\begin_layout Standard\n\n\n\\backslash\n' \
1123       'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1124       i = i + 1
1125
1126
1127 def revert_linebreak(document):
1128     'Reverts linebreak to ERT'
1129     i = 0
1130     while True:
1131       i = find_token(document.body, "\\linebreak", i)
1132       if i == -1:
1133           return
1134       document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1135       '\\begin_layout Standard\n\n\n\\backslash\n' \
1136       'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1137       i = i + 1
1138
1139
1140 def revert_latin(document):
1141     "Set language Latin to English"
1142     i = 0
1143     if document.language == "latin":
1144         document.language = "english"
1145         i = find_token(document.header, "\\language", 0)
1146         if i != -1:
1147             document.header[i] = "\\language english"
1148     j = 0
1149     while True:
1150         j = find_token(document.body, "\\lang latin", j)
1151         if j == -1:
1152             return
1153         document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1154         j = j + 1
1155
1156
1157 def revert_samin(document):
1158     "Set language North Sami to English"
1159     i = 0
1160     if document.language == "samin":
1161         document.language = "english"
1162         i = find_token(document.header, "\\language", 0)
1163         if i != -1:
1164             document.header[i] = "\\language english"
1165     j = 0
1166     while True:
1167         j = find_token(document.body, "\\lang samin", j)
1168         if j == -1:
1169             return
1170         document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1171         j = j + 1
1172
1173
1174 def convert_serbocroatian(document):
1175     "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1176     i = 0
1177     if document.language == "serbocroatian":
1178         document.language = "croatian"
1179         i = find_token(document.header, "\\language", 0)
1180         if i != -1:
1181             document.header[i] = "\\language croatian"
1182     j = 0
1183     while True:
1184         j = find_token(document.body, "\\lang serbocroatian", j)
1185         if j == -1:
1186             return
1187         document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1188         j = j + 1
1189
1190
1191 def convert_framed_notes(document):
1192     "Convert framed notes to boxes. "
1193     i = 0
1194     while 1:
1195         i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1196
1197         if i == -1:
1198             return
1199         document.body[i] = document.body[i].replace("\\begin_inset Note", "\\begin_inset Box")
1200         document.body.insert(i + 1, 'position "t"\nhor_pos "c"\nhas_inner_box 0\ninner_pos "t"\n' \
1201         'use_parbox 0\nwidth "100col%"\nspecial "none"\nheight "1in"\n' \
1202         'height_special "totalheight"')
1203         i = i + 1
1204
1205
1206 def convert_module_names(document):
1207   modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1208     'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1209     'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1210     'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1211     'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1212   modlist = document.get_module_list()
1213   if len(modlist) == 0:
1214     return
1215   newmodlist = []
1216   for mod in modlist:
1217     if modulemap.has_key(mod):
1218       newmodlist.append(modulemap[mod])
1219     else:
1220       document.warning("Can't find module %s in the module map!" % mod)
1221       newmodlist.append(mod)
1222   document.set_module_list(newmodlist)
1223
1224
1225 def revert_module_names(document):
1226   modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1227     'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1228     'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1229     'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1230     'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1231   modlist = document.get_module_list()
1232   if len(modlist) == 0:
1233     return
1234   newmodlist = []
1235   for mod in modlist:
1236     if modulemap.has_key(mod):
1237       newmodlist.append(modulemap[mod])
1238     else:
1239       document.warning("Can't find module %s in the module map!" % mod)
1240       newmodlist.append(mod)
1241   document.set_module_list(newmodlist)
1242
1243
1244 def revert_colsep(document):
1245     i = find_token(document.header, "\\columnsep", 0)
1246     if i == -1:
1247         return
1248     colsepline = document.header[i]
1249     r = re.compile(r'\\columnsep (.*)')
1250     m = r.match(colsepline)
1251     if not m:
1252         document.warning("Malformed column separation line!")
1253         return
1254     colsep = m.group(1)
1255     del document.header[i]
1256     #it seems to be safe to add the package even if it is already used
1257     pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1258
1259     add_to_preamble(document, pretext)
1260
1261
1262 def revert_framed_notes(document):
1263     "Revert framed boxes to notes. "
1264     i = 0
1265     while 1:
1266         i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1267
1268         if i == -1:
1269             return
1270         j = find_end_of_inset(document.body, i + 1)
1271         if j == -1:
1272             # should not happen
1273             document.warning("Malformed LyX document: Could not find end of Box inset.")
1274         k = find_token(document.body, "status", i + 1, j)
1275         if k == -1:
1276             document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1277             return
1278         status = document.body[k]
1279         l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1280         if l == -1:
1281             l = find_token(document.body, "\\begin_layout Plain", i + 1, j)
1282         if l == -1:
1283             document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1284             return
1285         m = find_token(document.body, "\\end_layout", i + 1, j)
1286         if m == -1:
1287             document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1288             return
1289         ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1290         pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1291         if ibox == -1 and pbox == -1:
1292             document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1293             del document.body[i+1:k]
1294         else:
1295             document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1296             document.body.insert(l + 1, "\\begin_inset Note Shaded\n" + status + "\n\\begin_layout Standard\n")
1297             document.body.insert(m + 1, "\\end_layout\n\\end_inset")
1298         i = i + 1
1299
1300
1301 def revert_slash(document):
1302     'Revert \\SpecialChar \\slash{} to ERT'
1303     for i in range(len(document.body)):
1304         document.body[i] = document.body[i].replace('\\SpecialChar \\slash{}', \
1305         '\\begin_inset ERT\nstatus collapsed\n\n' \
1306         '\\begin_layout Standard\n\n\n\\backslash\n' \
1307         'slash{}\n\\end_layout\n\n\\end_inset\n\n')
1308
1309
1310 def revert_nobreakdash(document):
1311     'Revert \\SpecialChar \\nobreakdash- to ERT'
1312     found = 0
1313     for i in range(len(document.body)):
1314         line = document.body[i]
1315         r = re.compile(r'\\SpecialChar \\nobreakdash-')
1316         m = r.match(line)
1317         if m:
1318             found = 1
1319         document.body[i] = document.body[i].replace('\\SpecialChar \\nobreakdash-', \
1320         '\\begin_inset ERT\nstatus collapsed\n\n' \
1321         '\\begin_layout Standard\n\n\n\\backslash\n' \
1322         'nobreakdash-\n\\end_layout\n\n\\end_inset\n\n')
1323     if not found:
1324         return
1325     j = find_token(document.header, "\\use_amsmath", 0)
1326     if j == -1:
1327         document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1328         return
1329     document.header[j] = "\\use_amsmath 2"
1330
1331
1332 def revert_nocite_key(body, start, end):
1333     'key "..." -> \nocite{...}'
1334     for i in range(start, end):
1335         if (body[i][0:5] == 'key "'):
1336             body[i] = body[i].replace('key "', "\\backslash\nnocite{")
1337             body[i] = body[i].replace('"', "}")
1338         else:
1339             body[i] = ""
1340
1341
1342 def revert_nocite(document):
1343     "Revert LatexCommand nocite to ERT"
1344     i = 0
1345     while 1:
1346         i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1347         if i == -1:
1348             return
1349         i = i + 1
1350         if (document.body[i] == "LatexCommand nocite"):
1351             j = find_end_of_inset(document.body, i + 1)
1352             if j == -1:
1353                 #this should not happen
1354                 document.warning("End of CommandInset citation not found in revert_nocite!")
1355                 revert_nocite_key(document.body, i + 1, len(document.body))
1356                 return
1357             revert_nocite_key(document.body, i + 1, j)
1358             document.body[i-1] = "\\begin_inset ERT"
1359             document.body[i] = "status collapsed\n\n" \
1360             "\\begin_layout Standard"
1361             document.body.insert(j, "\\end_layout\n");
1362             i = j
1363
1364
1365 def revert_btprintall(document):
1366     "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1367     i = find_token(document.header, '\\use_bibtopic', 0)
1368     if i == -1:
1369         document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1370         return
1371     if get_value(document.header, '\\use_bibtopic', 0) == "false":
1372         i = 0
1373         while i < len(document.body):
1374             i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1375             if i == -1:
1376                 return
1377             j = find_end_of_inset(document.body, i + 1)
1378             if j == -1:
1379                 #this should not happen
1380                 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1381                 j = len(document.body)
1382             for k in range(i, j):
1383                 if (document.body[k] == 'btprint "btPrintAll"'):
1384                     del document.body[k]
1385                     document.body.insert(i, "\\begin_inset ERT\n" \
1386                     "status collapsed\n\n\\begin_layout Standard\n\n" \
1387                     "\\backslash\nnocite{*}\n" \
1388                     "\\end_layout\n\\end_inset\n")
1389             i = j
1390
1391
1392 def revert_bahasam(document):
1393     "Set language Bahasa Malaysia to Bahasa Indonesia"
1394     i = 0
1395     if document.language == "bahasam":
1396         document.language = "bahasa"
1397         i = find_token(document.header, "\\language", 0)
1398         if i != -1:
1399             document.header[i] = "\\language bahasa"
1400     j = 0
1401     while True:
1402         j = find_token(document.body, "\\lang bahasam", j)
1403         if j == -1:
1404             return
1405         document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1406         j = j + 1
1407
1408
1409 def revert_interlingua(document):
1410     "Set language Interlingua to English"
1411     i = 0
1412     if document.language == "interlingua":
1413         document.language = "english"
1414         i = find_token(document.header, "\\language", 0)
1415         if i != -1:
1416             document.header[i] = "\\language english"
1417     j = 0
1418     while True:
1419         j = find_token(document.body, "\\lang interlingua", j)
1420         if j == -1:
1421             return
1422         document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1423         j = j + 1
1424
1425
1426 def revert_serbianlatin(document):
1427     "Set language Serbian-Latin to Croatian"
1428     i = 0
1429     if document.language == "serbian-latin":
1430         document.language = "croatian"
1431         i = find_token(document.header, "\\language", 0)
1432         if i != -1:
1433             document.header[i] = "\\language croatian"
1434     j = 0
1435     while True:
1436         j = find_token(document.body, "\\lang serbian-latin", j)
1437         if j == -1:
1438             return
1439         document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1440         j = j + 1
1441
1442
1443 def revert_rotfloat(document):
1444     " Revert sideways custom floats. "
1445     i = 0
1446     while 1:
1447         i = find_token(document.body, "\\begin_inset Float", i)
1448         if i == -1:
1449             return
1450         line = document.body[i]
1451         r = re.compile(r'\\begin_inset Float (.*)$')
1452         m = r.match(line)
1453         floattype = m.group(1)
1454         if floattype == "figure" or floattype == "table":
1455             i = i + 1
1456             continue
1457         j = find_end_of_inset(document.body, i)
1458         if j == -1:
1459             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1460             i = i + 1
1461             continue
1462         if get_value(document.body, 'sideways', i, j) != "false":
1463             l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1464             if l == -1:
1465                 l = find_token(document.body, "\\begin_layout Plain", i + 1, j)
1466             if l == -1:
1467                 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1468                 return
1469             document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1470             '\\begin_layout Standard\n\n\n\\backslash\n' \
1471             'end{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n'
1472             del document.body[i+1:l-1]
1473             document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1474             '\\begin_layout Standard\n\n\n\\backslash\n' \
1475             'begin{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1476             if floattype == "algorithm":
1477                 add_to_preamble(document,
1478                                 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1479                                  '\\usepackage{rotfloat}\n'
1480                                  '\\floatstyle{ruled}\n'
1481                                  '\\newfloat{algorithm}{tbp}{loa}\n'
1482                                  '\\floatname{algorithm}{Algorithm}\n'])
1483             else:
1484                 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1485             i = i + 1
1486             continue
1487         i = i + 1
1488
1489
1490 def revert_widesideways(document):
1491     " Revert wide sideways floats. "
1492     i = 0
1493     while 1:
1494         i = find_token(document.body, '\\begin_inset Float', i)
1495         if i == -1:
1496             return
1497         line = document.body[i]
1498         r = re.compile(r'\\begin_inset Float (.*)$')
1499         m = r.match(line)
1500         floattype = m.group(1)
1501         if floattype != "figure" and floattype != "table":
1502             i = i + 1
1503             continue
1504         j = find_end_of_inset(document.body, i)
1505         if j == -1:
1506             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1507             i = i + 1
1508             continue
1509         if get_value(document.body, 'sideways', i, j) != "false":
1510             if get_value(document.body, 'wide', i, j) != "false":
1511                 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1512                 if l == -1:
1513                     l = find_token(document.body, "\\begin_layout Plain", i + 1, j)
1514                 if l == -1:
1515                     document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1516                     return
1517                 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1518                 '\\begin_layout Standard\n\n\n\\backslash\n' \
1519                 'end{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n'
1520                 del document.body[i+1:l-1]
1521                 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1522                 '\\begin_layout Standard\n\n\n\\backslash\n' \
1523                 'begin{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1524                 add_to_preamble(document,
1525                                 ['\\usepackage{rotfloat}\n'])
1526                 i = i + 1
1527                 continue
1528         i = i + 1
1529
1530
1531 def revert_external_embedding(document):
1532     ' Remove embed tag from external inset '
1533     i = 0
1534     while 1:
1535         i = find_token(document.body, "\\begin_inset External", i)
1536         if i == -1:
1537             return
1538         j = find_end_of_inset(document.body, i)
1539         if j == -1:
1540             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1541             i = i + 1
1542             continue
1543         k = find_token(document.body, "\tembed", i, j)
1544         if k != -1:
1545             del document.body[k]
1546         i = i + 1
1547
1548
1549 def convert_subfig(document):
1550     " Convert subfigures to subfloats. "
1551     i = 0
1552     while 1:
1553         i = find_token(document.body, '\\begin_inset Graphics', i)
1554         if i == -1:
1555             return
1556         j = find_end_of_inset(document.body, i)
1557         if j == -1:
1558             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1559             i = i + 1
1560             continue
1561         k = find_token(document.body, '\tsubcaption', i, j)
1562         if k == -1:
1563             i = i + 1
1564             continue
1565         l = find_token(document.body, '\tsubcaptionText', i, j)
1566         caption = document.body[l][16:].strip('"')
1567         savestr = document.body[i]
1568         del document.body[l]
1569         del document.body[k]
1570         document.body[i] = '\\begin_inset Float figure\nwide false\nsideways false\n' \
1571         'status open\n\n\\begin_layout PlainLayout\n\\begin_inset Caption\n\n\\begin_layout PlainLayout\n' \
1572         + caption + '\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout PlainLayout\n' + savestr
1573         savestr = document.body[j]
1574         document.body[j] = '\n\\end_layout\n\n\\end_inset\n' + savestr
1575
1576
1577 def revert_subfig(document):
1578     " Revert subfloats. "
1579     i = 0
1580     while 1:
1581         i = find_token(document.body, '\\begin_inset Float', i)
1582         if i == -1:
1583             return
1584         while 1:
1585             j = find_end_of_inset(document.body, i)
1586             if j == -1:
1587                 document.warning("Malformed lyx document: Missing '\\end_inset' (float).")
1588                 i = i + 1
1589                 continue
1590             # look for embedded float (= subfloat)
1591             k = find_token(document.body, '\\begin_inset Float', i + 1, j)
1592             if k == -1:
1593                 break
1594             l = find_end_of_inset(document.body, k)
1595             if l == -1:
1596                 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
1597                 i = i + 1
1598                 continue
1599             m = find_token(document.body, "\\begin_layout PlainLayout", k + 1, l)
1600             # caption?
1601             cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
1602             caption = ''
1603             shortcap = ''
1604             if cap != -1:
1605                 capend = find_end_of_inset(document.body, cap)
1606                 if capend == -1:
1607                     document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
1608                     return
1609                 # label?
1610                 label = ''
1611                 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
1612                 if lbl != -1:
1613                     lblend = find_end_of_inset(document.body, lbl + 1)
1614                     if lblend == -1:
1615                         document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
1616                         return
1617                     for line in document.body[lbl:lblend + 1]:
1618                         if line.startswith('name '):
1619                             label = line.split()[1].strip('"')
1620                             break
1621                 else:
1622                     lbl = capend
1623                     lblend = capend
1624                     label = ''
1625                 # opt arg?
1626                 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
1627                 if opt != -1:
1628                     optend = find_end_of_inset(document.body, opt)
1629                     if optend == -1:
1630                         document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
1631                         return
1632                     optc = find_token(document.body, "\\begin_layout PlainLayout", opt, optend)
1633                     if optc == -1:
1634                         document.warning("Malformed LyX document: Missing `\\begin_layout PlainLayout' in Float inset.")
1635                         return
1636                     optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
1637                     for line in document.body[optc:optcend]:
1638                         if not line.startswith('\\'):
1639                             shortcap += line.strip()
1640                 else:
1641                     opt = capend
1642                     optend = capend
1643                 for line in document.body[cap:capend]:
1644                     if line in document.body[lbl:lblend]:
1645                         continue
1646                     elif line in document.body[opt:optend]:
1647                         continue
1648                     elif not line.startswith('\\'):
1649                         caption += line.strip()
1650                 if len(label) > 0:
1651                     caption += "\\backslash\nlabel{" + label + "}"
1652             document.body[l] = '\\begin_layout PlainLayout\n\\begin_inset ERT\nstatus collapsed\n\n' \
1653             '\\begin_layout PlainLayout\n\n}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout PlainLayout\n'
1654             del document.body[cap:capend+1]
1655             del document.body[k+1:m-1]
1656             insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
1657             '\\begin_layout PlainLayout\n\n\\backslash\n' \
1658             'subfloat'
1659             if len(shortcap) > 0:
1660                 insertion = insertion + "[" + shortcap + "]"
1661             if len(caption) > 0:
1662                 insertion = insertion + "[" + caption + "]"
1663             insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
1664             document.body[k] = insertion
1665             add_to_preamble(document,
1666                             ['\\usepackage{subfig}\n'])
1667         i = i + 1
1668
1669
1670 def revert_wrapplacement(document):
1671     " Revert placement options wrap floats (wrapfig). "
1672     i = 0
1673     while True:
1674         i = find_token(document.body, "lines", i)
1675         if i == -1:
1676             return
1677         j = find_token(document.body, "placement", i+1)
1678         if j != i + 1:
1679             document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
1680             return
1681         document.body[j] = document.body[j].replace("placement O", "placement o")
1682         document.body[j] = document.body[j].replace("placement I", "placement i")
1683         document.body[j] = document.body[j].replace("placement L", "placement l")
1684         document.body[j] = document.body[j].replace("placement R", "placement r")
1685         i = i + 1
1686
1687
1688 def remove_extra_embedded_files(document):
1689     " Remove \extra_embedded_files from buffer params "
1690     i = find_token(document.header, '\\extra_embedded_files', 0)
1691     if i == -1:
1692         document.warning("Malformed lyx document: Missing '\\extra_embedded_files'.")
1693         return
1694     document.header.pop(i)
1695
1696
1697 def convert_spaceinset(document):
1698     " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
1699     for i in range(len(document.body)):
1700         if re.search(r'\InsetSpace', document.body[i]):
1701             document.body[i] = document.body[i].replace('\\InsetSpace', '\n\\begin_inset Space')
1702             document.body[i] = document.body[i] + "\n\\end_inset"
1703
1704
1705 def revert_spaceinset(document):
1706     " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
1707     i = 0
1708     while True:
1709         i = find_token(document.body, "\\begin_inset Space", i)
1710         if i == -1:
1711             return
1712         j = find_end_of_inset(document.body, i)
1713         if j == -1:
1714             document.warning("Malformed LyX document: Could not find end of space inset.")
1715             continue
1716         document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
1717         del document.body[j]
1718
1719
1720 def convert_hfill(document):
1721     " Convert hfill to space inset "
1722     i = 0
1723     while True:
1724         i = find_token(document.body, "\\hfill", i)
1725         if i == -1:
1726             return
1727         document.body[i] = document.body[i].replace('\\hfill', '\n\\begin_inset Space \\hfill{}\n\\end_inset')
1728
1729
1730 def revert_hfills(document):
1731     ' Revert \\hfill commands '
1732     for i in range(len(document.body)):
1733         document.body[i] = document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
1734         document.body[i] = document.body[i].replace('\\InsetSpace \\dotfill{}', \
1735         '\\begin_inset ERT\nstatus collapsed\n\n' \
1736         '\\begin_layout Standard\n\n\n\\backslash\n' \
1737         'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
1738         document.body[i] = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
1739         '\\begin_inset ERT\nstatus collapsed\n\n' \
1740         '\\begin_layout Standard\n\n\n\\backslash\n' \
1741         'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
1742
1743
1744 def revert_hspace(document):
1745     ' Revert \\InsetSpace \\hspace{} to ERT '
1746     i = 0
1747     while True:
1748         i = find_token(document.body, "\\InsetSpace \\hspace", i)
1749         if i == -1:
1750             return
1751         length = get_value(document.body, '\\length', i+1)
1752         if length == '':
1753             document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
1754             return
1755         del document.body[i+1]
1756         document.body[i] = document.body[i].replace('\\InsetSpace \\hspace*{}', \
1757         '\\begin_inset ERT\nstatus collapsed\n\n' \
1758         '\\begin_layout Standard\n\n\n\\backslash\n' \
1759         'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
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
1765
1766 def revert_protected_hfill(document):
1767     ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
1768     i = 0
1769     while True:
1770         i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
1771         if i == -1:
1772             return
1773         j = find_end_of_inset(document.body, i)
1774         if j == -1:
1775             document.warning("Malformed LyX document: Could not find end of space inset.")
1776             continue
1777         del document.body[j]
1778         document.body[i] = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
1779         '\\begin_inset ERT\nstatus collapsed\n\n' \
1780         '\\begin_layout Standard\n\n\n\\backslash\n' \
1781         'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
1782
1783
1784 def revert_local_layout(document):
1785     ' Revert local layout headers.'
1786     i = 0
1787     while True:
1788         i = find_token(document.header, "\\begin_local_layout", i)
1789         if i == -1:
1790             return
1791         j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
1792         if j == -1:
1793             # this should not happen
1794             break
1795         document.header[i : j + 1] = []
1796
1797
1798 def convert_pagebreaks(document):
1799     ' Convert inline Newpage insets to new format '
1800     i = 0
1801     while True:
1802         i = find_token(document.body, '\\newpage', i)
1803         if i == -1:
1804             break
1805         document.body[i:i+1] = ['\\begin_inset Newpage newpage',
1806                              '\\end_inset']
1807     i = 0
1808     while True:
1809         i = find_token(document.body, '\\pagebreak', i)
1810         if i == -1:
1811             break
1812         document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
1813                              '\\end_inset']
1814     i = 0
1815     while True:
1816         i = find_token(document.body, '\\clearpage', i)
1817         if i == -1:
1818             break
1819         document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
1820                              '\\end_inset']
1821     i = 0
1822     while True:
1823         i = find_token(document.body, '\\cleardoublepage', i)
1824         if i == -1:
1825             break
1826         document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
1827                              '\\end_inset']
1828
1829
1830 def revert_pagebreaks(document):
1831     ' Revert \\begin_inset Newpage to previous inline format '
1832     i = 0
1833     while True:
1834         i = find_token(document.body, '\\begin_inset Newpage', i)
1835         if i == -1:
1836             return
1837         j = find_end_of_inset(document.body, i)
1838         if j == -1:
1839             document.warning("Malformed LyX document: Could not find end of Newpage inset.")
1840             continue
1841         del document.body[j]
1842         document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
1843         document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
1844         document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
1845         document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
1846
1847
1848 def convert_linebreaks(document):
1849     ' Convert inline Newline insets to new format '
1850     i = 0
1851     while True:
1852         i = find_token(document.body, '\\newline', i)
1853         if i == -1:
1854             break
1855         document.body[i:i+1] = ['\\begin_inset Newline newline',
1856                              '\\end_inset']
1857     i = 0
1858     while True:
1859         i = find_token(document.body, '\\linebreak', i)
1860         if i == -1:
1861             break
1862         document.body[i:i+1] = ['\\begin_inset Newline linebreak',
1863                              '\\end_inset']
1864
1865
1866 def revert_linebreaks(document):
1867     ' Revert \\begin_inset Newline to previous inline format '
1868     i = 0
1869     while True:
1870         i = find_token(document.body, '\\begin_inset Newline', i)
1871         if i == -1:
1872             return
1873         j = find_end_of_inset(document.body, i)
1874         if j == -1:
1875             document.warning("Malformed LyX document: Could not find end of Newline inset.")
1876             continue
1877         del document.body[j]
1878         document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
1879         document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
1880
1881
1882 def convert_japanese_plain(document):
1883     ' Set language japanese-plain to japanese '
1884     i = 0
1885     if document.language == "japanese-plain":
1886         document.language = "japanese"
1887         i = find_token(document.header, "\\language", 0)
1888         if i != -1:
1889             document.header[i] = "\\language japanese"
1890     j = 0
1891     while True:
1892         j = find_token(document.body, "\\lang japanese-plain", j)
1893         if j == -1:
1894             return
1895         document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
1896         j = j + 1
1897
1898
1899 def revert_pdfpages(document):
1900     ' Revert pdfpages external inset to ERT '
1901     i = 0
1902     while 1:
1903         i = find_token(document.body, "\\begin_inset External", i)
1904         if i == -1:
1905             return
1906         j = find_end_of_inset(document.body, i)
1907         if j == -1:
1908             document.warning("Malformed lyx document: Missing '\\end_inset'.")
1909             i = i + 1
1910             continue
1911         if get_value(document.body, 'template', i, j) == "PDFPages":
1912             filename = get_value(document.body, 'filename', i, j)
1913             extra = ''
1914             r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
1915             for k in range(i, j):
1916                 m = r.match(document.body[k])
1917                 if m:
1918                     extra = m.group(1)
1919             angle = get_value(document.body, 'rotateAngle', i, j)
1920             width = get_value(document.body, 'width', i, j)
1921             height = get_value(document.body, 'height', i, j)
1922             scale = get_value(document.body, 'scale', i, j)
1923             keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
1924             options = extra
1925             if angle != '':
1926                  if options != '':
1927                      options += ",angle=" + angle
1928                  else:
1929                      options += "angle=" + angle
1930             if width != '':
1931                  if options != '':
1932                      options += ",width=" + convert_len(width)
1933                  else:
1934                      options += "width=" + convert_len(width)
1935             if height != '':
1936                  if options != '':
1937                      options += ",height=" + convert_len(height)
1938                  else:
1939                      options += "height=" + convert_len(height)
1940             if scale != '':
1941                  if options != '':
1942                      options += ",scale=" + scale
1943                  else:
1944                      options += "scale=" + scale
1945             if keepAspectRatio != '':
1946                  if options != '':
1947                      options += ",keepaspectratio"
1948                  else:
1949                      options += "keepaspectratio"
1950             if options != '':
1951                      options = '[' + options + ']'
1952             del document.body[i+1:j+1]
1953             document.body[i:i+1] = ['\\begin_inset ERT',
1954                                 'status collapsed',
1955                                 '',
1956                                 '\\begin_layout Standard',
1957                                 '',
1958                                 '\\backslash',
1959                                 'includepdf' + options + '{' + filename + '}',
1960                                 '\\end_layout',
1961                                 '',
1962                                 '\\end_inset']
1963             add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
1964             i = i + 1
1965             continue
1966         i = i + 1
1967
1968
1969 ##
1970 # Conversion hub
1971 #
1972
1973 supported_versions = ["1.6.0","1.6"]
1974 convert = [[277, [fix_wrong_tables]],
1975            [278, [close_begin_deeper]],
1976            [279, [long_charstyle_names]],
1977            [280, [axe_show_label]],
1978            [281, []],
1979            [282, []],
1980            [283, [convert_flex]],
1981            [284, []],
1982            [285, []],
1983            [286, []],
1984            [287, [convert_wrapfig_options]],
1985            [288, [convert_inset_command]],
1986            [289, [convert_latexcommand_index]],
1987            [290, []],
1988            [291, []],
1989            [292, []],
1990            [293, []],
1991            [294, [convert_pdf_options]],
1992            [295, [convert_htmlurl, convert_url]],
1993            [296, [convert_include]],
1994            [297, [convert_usorbian]],
1995            [298, []],
1996            [299, []],
1997            [300, []],
1998            [301, []],
1999            [302, []],
2000            [303, [convert_serbocroatian]],
2001            [304, [convert_framed_notes]],
2002            [305, []],
2003            [306, []],
2004            [307, []],
2005            [308, []],
2006            [309, []],
2007            [310, []],
2008            [311, [convert_ams_classes]],
2009            [312, []],
2010            [313, [convert_module_names]],
2011            [314, []],
2012            [315, []],
2013            [316, [convert_subfig]],
2014            [317, []],
2015            [318, []],
2016            [319, [convert_spaceinset, convert_hfill]],
2017            [320, []],
2018            [321, [convert_tablines]],
2019            [322, []],
2020            [323, [convert_pagebreaks]],
2021            [324, [convert_linebreaks]],
2022            [325, [convert_japanese_plain]],
2023            [326, []]
2024           ]
2025
2026 revert =  [[325, [revert_pdfpages]],
2027            [324, []],
2028            [323, [revert_linebreaks]],
2029            [322, [revert_pagebreaks]],
2030            [321, [revert_local_layout]],
2031            [320, [revert_tablines]],
2032            [319, [revert_protected_hfill]],
2033            [318, [revert_spaceinset, revert_hfills, revert_hspace]],
2034            [317, [remove_extra_embedded_files]],
2035            [316, [revert_wrapplacement]],
2036            [315, [revert_subfig]],
2037            [314, [revert_colsep]],
2038            [313, []],
2039            [312, [revert_module_names]],
2040            [311, [revert_rotfloat, revert_widesideways]],
2041            [310, [revert_external_embedding]],
2042            [309, [revert_btprintall]],
2043            [308, [revert_nocite]],
2044            [307, [revert_serbianlatin]],
2045            [306, [revert_slash, revert_nobreakdash]],
2046            [305, [revert_interlingua]],
2047            [304, [revert_bahasam]],
2048            [303, [revert_framed_notes]],
2049            [302, []],
2050            [301, [revert_latin, revert_samin]],
2051            [300, [revert_linebreak]],
2052            [299, [revert_pagebreak]],
2053            [298, [revert_hyperlinktype]],
2054            [297, [revert_macro_optional_params]],
2055            [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
2056            [295, [revert_include]],
2057            [294, [revert_href]],
2058            [293, [revert_pdf_options_2]],
2059            [292, [revert_inset_info]],
2060            [291, [revert_japanese, revert_japanese_encoding]],
2061            [290, [revert_vietnamese]],
2062            [289, [revert_wraptable]],
2063            [288, [revert_latexcommand_index]],
2064            [287, [revert_inset_command]],
2065            [286, [revert_wrapfig_options]],
2066            [285, [revert_pdf_options]],
2067            [284, [remove_inzip_options]],
2068            [283, []],
2069            [282, [revert_flex]],
2070            [281, []],
2071            [280, [revert_begin_modules]],
2072            [279, [revert_show_label]],
2073            [278, [revert_long_charstyle_names]],
2074            [277, []],
2075            [276, []]
2076           ]
2077
2078
2079 if __name__ == "__main__":
2080     pass