]> git.lyx.org Git - features.git/blob - lib/lyx2lyx/lyx_1_6.py
Fix include reversion routine.
[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 # WARNING!
35 # DO NOT do this:
36 #   document.body[i] = wrap_insert_ert(...)
37 # wrap_into_ert may returns a multiline string, which should NOT appear
38 # in document.body. Insetad, do something like this:
39 #   subst = wrap_inset_ert(...)
40 #   subst = subst.split('\n')
41 #   document.body[i:i+1] = subst
42 #   i+= len(subst) - 1
43 # where the last statement resets the counter to accord with the added
44 # lines.
45 def wrap_into_ert(string, src, dst):
46     " Wrap a something into an ERT"
47     return string.replace(src, '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n'
48       + dst + '\n\\end_layout\n\\end_inset\n')
49
50 def add_to_preamble(document, text):
51     """ Add text to the preamble if it is not already there.
52     Only the first line is checked!"""
53
54     if find_token(document.preamble, text[0], 0) != -1:
55         return
56
57     document.preamble.extend(text)
58
59 # Convert a LyX length into a LaTeX length
60 def convert_len(len):
61     units = {"text%":"\\backslash\ntextwidth", "col%":"\\backslash\ncolumnwidth",
62              "page%":"\\backslash\npagewidth", "line%":"\\backslash\nlinewidth",
63              "theight%":"\\backslash\ntextheight", "pheight%":"\\backslash\npageheight"}
64
65     # Convert LyX units to LaTeX units
66     for unit in units.keys():
67         if len.find(unit) != -1:
68             len = '%f' % (len2value(len) / 100)
69             len = len.strip('0') + units[unit]
70             break
71
72     return len
73
74 # Return the value of len without the unit in numerical form.
75 def len2value(len):
76     result = re.search('([+-]?[0-9.]+)', len)
77     if result:
78         return float(result.group(1))
79     # No number means 1.0
80     return 1.0
81
82 # Unfortunately, this doesn't really work, since Standard isn't always default.
83 # But it's as good as we can do right now.
84 def find_default_layout(document, start, end):
85     l = find_token(document.body, "\\begin_layout Standard", start, end)
86     if l == -1:
87         l = find_token(document.body, "\\begin_layout PlainLayout", start, end)
88     if l == -1:
89         l = find_token(document.body, "\\begin_layout Plain Layout", start, end)
90     return l
91
92 def get_option(document, m, option, default):
93     l = document.body[m].find(option)
94     val = default
95     if l != -1:
96         val = document.body[m][l:].split('"')[1]
97     return val
98
99 def remove_option(document, m, option):
100     l = document.body[m].find(option)
101     if l != -1:
102         val = document.body[m][l:].split('"')[1]
103         document.body[m] = document.body[m][:l-1] + document.body[m][l+len(option + '="' + val + '"'):]
104     return l
105
106 def set_option(document, m, option, value):
107     l = document.body[m].find(option)
108     if l != -1:
109         oldval = document.body[m][l:].split('"')[1]
110         l = l + len(option + '="')
111         document.body[m] = document.body[m][:l] + value + document.body[m][l+len(oldval):]
112     else:
113         document.body[m] = document.body[m][:-1] + ' ' + option + '="' + value + '">'
114     return l
115
116
117 ####################################################################
118
119 def convert_ltcaption(document):
120     i = 0
121     while True:
122         i = find_token(document.body, "\\begin_inset Tabular", i)
123         if i == -1:
124             return
125         j = find_end_of_inset(document.body, i + 1)
126         if j == -1:
127             document.warning("Malformed LyX document: Could not find end of tabular.")
128             continue
129
130         nrows = int(document.body[i+1].split('"')[3])
131         ncols = int(document.body[i+1].split('"')[5])
132
133         m = i + 1
134         for k in range(nrows):
135             m = find_token(document.body, "<row", m)
136             r = m
137             caption = 'false'
138             for k in range(ncols):
139                 m = find_token(document.body, "<cell", m)
140                 if (k == 0):
141                     mend = find_token(document.body, "</cell>", m + 1)
142                     # first look for caption insets
143                     mcap = find_token(document.body, "\\begin_inset Caption", m + 1, mend)
144                     # then look for ERT captions
145                     if mcap == -1:
146                         mcap = find_token(document.body, "caption", m + 1, mend)
147                         if mcap > -1:
148                             mcap = find_token(document.body, "\\backslash", mcap - 1, mcap)
149                     if mcap > -1:
150                         caption = 'true'
151                 if caption == 'true':
152                     if (k == 0):
153                         set_option(document, r, 'caption', 'true')
154                         set_option(document, m, 'multicolumn', '1')
155                         set_option(document, m, 'bottomline', 'false')
156                         set_option(document, m, 'topline', 'false')
157                         set_option(document, m, 'rightline', 'false')
158                         set_option(document, m, 'leftline', 'false')
159                         #j = find_end_of_inset(document.body, j + 1)
160                     else:
161                         set_option(document, m, 'multicolumn', '2')
162                 m = m + 1
163             m = m + 1
164
165         i = j + 1
166
167
168 #FIXME Use of wrap_into_ert can confuse lyx2lyx
169 def revert_ltcaption(document):
170     i = 0
171     while True:
172         i = find_token(document.body, "\\begin_inset Tabular", i)
173         if i == -1:
174             return
175         j = find_end_of_inset(document.body, i + 1)
176         if j == -1:
177             document.warning("Malformed LyX document: Could not find end of tabular.")
178             continue
179
180         m = i + 1
181         nrows = int(document.body[i+1].split('"')[3])
182         ncols = int(document.body[i+1].split('"')[5])
183
184         for k in range(nrows):
185             m = find_token(document.body, "<row", m)
186             caption = get_option(document, m, 'caption', 'false')
187             if caption == 'true':
188                 remove_option(document, m, 'caption')
189                 for k in range(ncols):
190                     m = find_token(document.body, "<cell", m)
191                     remove_option(document, m, 'multicolumn')
192                     if k == 0:
193                         m = find_token(document.body, "\\begin_inset Caption", m)
194                         if m == -1:
195                             return
196                         m = find_end_of_inset(document.body, m + 1)
197                         document.body[m] += wrap_into_ert("","","\\backslash\n\\backslash\n%")
198                     m = m + 1
199             m = m + 1
200         i = j + 1
201
202
203 def convert_tablines(document):
204     i = 0
205     while True:
206         i = find_token(document.body, "\\begin_inset Tabular", i)
207         if i == -1:
208             # LyX 1.3 inserted an extra space between \begin_inset
209             # and Tabular so let us try if this is the case and fix it.
210             i = find_token(document.body, "\\begin_inset  Tabular", i)
211             if i == -1:
212                 return
213             else:
214                 document.body[i] = "\\begin_inset Tabular"
215         j = find_end_of_inset(document.body, i + 1)
216         if j == -1:
217             document.warning("Malformed LyX document: Could not find end of tabular.")
218             continue
219
220         m = i + 1
221         nrows = int(document.body[i+1].split('"')[3])
222         ncols = int(document.body[i+1].split('"')[5])
223
224         col_info = []
225         for k in range(ncols):
226             m = find_token(document.body, "<column", m)
227             left = get_option(document, m, 'leftline', 'false')
228             right = get_option(document, m, 'rightline', 'false')
229             col_info.append([left, right])
230             remove_option(document, m, 'leftline')
231             remove_option(document, m, 'rightline')
232             m = m + 1
233
234         row_info = []
235         for k in range(nrows):
236             m = find_token(document.body, "<row", m)
237             top = get_option(document, m, 'topline', 'false')
238             bottom = get_option(document, m, 'bottomline', 'false')
239             row_info.append([top, bottom])
240             remove_option(document, m, 'topline')
241             remove_option(document, m, 'bottomline')
242             m = m + 1
243
244         m = i + 1
245         mc_info = []
246         for k in range(nrows*ncols):
247             m = find_token(document.body, "<cell", m)
248             mc_info.append(get_option(document, m, 'multicolumn', '0'))
249             m = m + 1
250         m = i + 1
251         for l in range(nrows):
252             for k in range(ncols):
253                 m = find_token(document.body, '<cell', m)
254                 if mc_info[l*ncols + k] == '0':
255                     r = set_option(document, m, 'topline', row_info[l][0])
256                     r = set_option(document, m, 'bottomline', row_info[l][1])
257                     r = set_option(document, m, 'leftline', col_info[k][0])
258                     r = set_option(document, m, 'rightline', col_info[k][1])
259                 elif mc_info[l*ncols + k] == '1':
260                     s = k + 1
261                     while s < ncols and mc_info[l*ncols + s] == '2':
262                         s = s + 1
263                     if s < ncols and mc_info[l*ncols + s] != '1':
264                         r = set_option(document, m, 'rightline', col_info[k][1])
265                     if k > 0 and mc_info[l*ncols + k - 1] == '0':
266                         r = set_option(document, m, 'leftline', col_info[k][0])
267                 m = m + 1
268         i = j + 1
269
270
271 def revert_tablines(document):
272     i = 0
273     while True:
274         i = find_token(document.body, "\\begin_inset Tabular", i)
275         if i == -1:
276             return
277         j = find_end_of_inset(document.body, i + 1)
278         if j == -1:
279             document.warning("Malformed LyX document: Could not find end of tabular.")
280             continue
281
282         m = i + 1
283         nrows = int(document.body[i+1].split('"')[3])
284         ncols = int(document.body[i+1].split('"')[5])
285
286         lines = []
287         for k in range(nrows*ncols):
288             m = find_token(document.body, "<cell", m)
289             top = get_option(document, m, 'topline', 'false')
290             bottom = get_option(document, m, 'bottomline', 'false')
291             left = get_option(document, m, 'leftline', 'false')
292             right = get_option(document, m, 'rightline', 'false')
293             lines.append([top, bottom, left, right])
294             m = m + 1
295
296         # we will want to ignore longtable captions
297         m = i + 1
298         caption_info = []
299         for k in range(nrows):
300             m = find_token(document.body, "<row", m)
301             caption = get_option(document, m, 'caption', 'false')
302             caption_info.append([caption])
303             m = m + 1
304
305         m = i + 1
306         col_info = []
307         for k in range(ncols):
308             m = find_token(document.body, "<column", m)
309             left = 'true'
310             for l in range(nrows):
311                 left = lines[l*ncols + k][2]
312                 if left == 'false' and caption_info[l] == 'false':
313                     break
314             set_option(document, m, 'leftline', left)
315             right = 'true'
316             for l in range(nrows):
317                 right = lines[l*ncols + k][3]
318                 if right == 'false' and caption_info[l] == 'false':
319                     break
320             set_option(document, m, 'rightline', right)
321             m = m + 1
322
323         row_info = []
324         for k in range(nrows):
325             m = find_token(document.body, "<row", m)
326             top = 'true'
327             for l in range(ncols):
328                 top = lines[k*ncols + l][0]
329                 if top == 'false':
330                     break
331             if caption_info[k] == 'false':
332                 top = 'false'
333             set_option(document, m, 'topline', top)
334             bottom = 'true'
335             for l in range(ncols):
336                 bottom = lines[k*ncols + l][1]
337                 if bottom == 'false':
338                     break
339             if caption_info[k] == 'false':
340                 bottom = 'false'
341             set_option(document, m, 'bottomline', bottom)
342             m = m + 1
343
344         i = j + 1
345
346
347 def fix_wrong_tables(document):
348     i = 0
349     while True:
350         i = find_token(document.body, "\\begin_inset Tabular", i)
351         if i == -1:
352             return
353         j = find_end_of_inset(document.body, i + 1)
354         if j == -1:
355             document.warning("Malformed LyX document: Could not find end of tabular.")
356             continue
357
358         m = i + 1
359         nrows = int(document.body[i+1].split('"')[3])
360         ncols = int(document.body[i+1].split('"')[5])
361
362         for l in range(nrows):
363             prev_multicolumn = 0
364             for k in range(ncols):
365                 m = find_token(document.body, '<cell', m)
366
367                 if document.body[m].find('multicolumn') != -1:
368                     multicol_cont = int(document.body[m].split('"')[1])
369
370                     if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
371                         document.body[m] = document.body[m][:5] + document.body[m][21:]
372                         prev_multicolumn = 0
373                     else:
374                         prev_multicolumn = multicol_cont
375                 else:
376                     prev_multicolumn = 0
377
378         i = j + 1
379
380
381 def close_begin_deeper(document):
382     i = 0
383     depth = 0
384     while True:
385         i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
386
387         if i == -1:
388             break
389
390         if document.body[i][:13] == "\\begin_deeper":
391             depth += 1
392         else:
393             depth -= 1
394
395         i += 1
396
397     document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
398
399
400 def long_charstyle_names(document):
401     i = 0
402     while True:
403         i = find_token(document.body, "\\begin_inset CharStyle", i)
404         if i == -1:
405             return
406         document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
407         i += 1
408
409 def revert_long_charstyle_names(document):
410     i = 0
411     while True:
412         i = find_token(document.body, "\\begin_inset CharStyle", i)
413         if i == -1:
414             return
415         document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle")
416         i += 1
417
418
419 def axe_show_label(document):
420     i = 0
421     while True:
422         i = find_token(document.body, "\\begin_inset CharStyle", i)
423         if i == -1:
424             return
425         if document.body[i + 1].find("show_label") != -1:
426             if document.body[i + 1].find("true") != -1:
427                 document.body[i + 1] = "status open"
428                 del document.body[ i + 2]
429             else:
430                 if document.body[i + 1].find("false") != -1:
431                     document.body[i + 1] = "status collapsed"
432                     del document.body[ i + 2]
433                 else:
434                     document.warning("Malformed LyX document: show_label neither false nor true.")
435         else:
436             document.warning("Malformed LyX document: show_label missing in CharStyle.")
437
438         i += 1
439
440
441 def revert_show_label(document):
442     i = 0
443     while True:
444         i = find_token(document.body, "\\begin_inset CharStyle", i)
445         if i == -1:
446             return
447         if document.body[i + 1].find("status open") != -1:
448             document.body.insert(i + 1, "show_label true")
449         else:
450             if document.body[i + 1].find("status collapsed") != -1:
451                 document.body.insert(i + 1, "show_label false")
452             else:
453                 document.warning("Malformed LyX document: no legal status line in CharStyle.")
454         i += 1
455
456 def revert_begin_modules(document):
457     i = 0
458     while True:
459         i = find_token(document.header, "\\begin_modules", i)
460         if i == -1:
461             return
462         j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
463         if j == -1:
464             # this should not happen
465             break
466         document.header[i : j + 1] = []
467
468 def convert_flex(document):
469     "Convert CharStyle to Flex"
470     i = 0
471     while True:
472         i = find_token(document.body, "\\begin_inset CharStyle", i)
473         if i == -1:
474             return
475         document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
476
477 def revert_flex(document):
478     "Convert Flex to CharStyle"
479     i = 0
480     while True:
481         i = find_token(document.body, "\\begin_inset Flex", i)
482         if i == -1:
483             return
484         document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
485
486
487 #  Discard PDF options for hyperref
488 def revert_pdf_options(document):
489         "Revert PDF options for hyperref."
490         # store the PDF options and delete the entries from the Lyx file
491         i = 0
492         hyperref = False
493         title = ""
494         author = ""
495         subject = ""
496         keywords = ""
497         bookmarks = ""
498         bookmarksnumbered = ""
499         bookmarksopen = ""
500         bookmarksopenlevel = ""
501         breaklinks = ""
502         pdfborder = ""
503         colorlinks = ""
504         backref = ""
505         pagebackref = ""
506         pagemode = ""
507         otheroptions = ""
508         i = find_token(document.header, "\\use_hyperref", i)
509         if i != -1:
510             hyperref = get_value(document.header, "\\use_hyperref", i) == 'true'
511             del document.header[i]
512         i = find_token(document.header, "\\pdf_store_options", i)
513         if i != -1:
514             del document.header[i]
515         i = find_token(document.header, "\\pdf_title", 0)
516         if i != -1:
517             title = get_value_string(document.header, '\\pdf_title', 0, 0, True)
518             title = ' pdftitle={' + title + '}'
519             del document.header[i]
520         i = find_token(document.header, "\\pdf_author", 0)
521         if i != -1:
522             author = get_value_string(document.header, '\\pdf_author', 0, 0, True)
523             if title == "":
524                 author = ' pdfauthor={' + author + '}'
525             else:
526                 author = ',\n pdfauthor={' + author + '}'
527             del document.header[i]
528         i = find_token(document.header, "\\pdf_subject", 0)
529         if i != -1:
530             subject = get_value_string(document.header, '\\pdf_subject', 0, 0, True)
531             if title == "" and author == "":
532                 subject = ' pdfsubject={' + subject + '}'
533             else:
534                 subject = ',\n pdfsubject={' + subject + '}'
535             del document.header[i]
536         i = find_token(document.header, "\\pdf_keywords", 0)
537         if i != -1:
538             keywords = get_value_string(document.header, '\\pdf_keywords', 0, 0, True)
539             if title == "" and author == "" and subject == "":
540                 keywords = ' pdfkeywords={' + keywords + '}'
541             else:
542                 keywords = ',\n pdfkeywords={' + keywords + '}'
543             del document.header[i]
544         i = find_token(document.header, "\\pdf_bookmarks", 0)
545         if i != -1:
546             bookmarks = get_value_string(document.header, '\\pdf_bookmarks', 0)
547             bookmarks = ',\n bookmarks=' + bookmarks
548             del document.header[i]
549         i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
550         if i != -1:
551             bookmarksnumbered = get_value_string(document.header, '\\pdf_bookmarksnumbered', 0)
552             bookmarksnumbered = ',\n bookmarksnumbered=' + bookmarksnumbered
553             del document.header[i]
554         i = find_token(document.header, "\\pdf_bookmarksopen", i)
555         if i != -1:
556             bookmarksopen = get_value_string(document.header, '\\pdf_bookmarksopen', 0)
557             bookmarksopen = ',\n bookmarksopen=' + bookmarksopen
558             del document.header[i]
559         i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
560         if i != -1:
561             bookmarksopenlevel = get_value_string(document.header, '\\pdf_bookmarksopenlevel', 0, 0, True)
562             bookmarksopenlevel = ',\n bookmarksopenlevel=' + bookmarksopenlevel
563             del document.header[i]
564         i = find_token(document.header, "\\pdf_breaklinks", i)
565         if i != -1:
566             breaklinks = get_value_string(document.header, '\\pdf_breaklinks', 0)
567             breaklinks = ',\n breaklinks=' + breaklinks
568             del document.header[i]
569         i = find_token(document.header, "\\pdf_pdfborder", i)
570         if i != -1:
571             pdfborder = get_value_string(document.header, '\\pdf_pdfborder', 0)
572             if pdfborder == 'true':
573                 pdfborder = ',\n pdfborder={0 0 0}'
574             else:
575                 pdfborder = ',\n pdfborder={0 0 1}'
576             del document.header[i]
577         i = find_token(document.header, "\\pdf_colorlinks", i)
578         if i != -1:
579             colorlinks = get_value_string(document.header, '\\pdf_colorlinks', 0)
580             colorlinks = ',\n colorlinks=' + colorlinks
581             del document.header[i]
582         i = find_token(document.header, "\\pdf_backref", i)
583         if i != -1:
584             backref = get_value_string(document.header, '\\pdf_backref', 0)
585             backref = ',\n backref=' + backref
586             del document.header[i]
587         i = find_token(document.header, "\\pdf_pagebackref", i)
588         if i != -1:
589             pagebackref = get_value_string(document.header, '\\pdf_pagebackref', 0)
590             pagebackref = ',\n pagebackref=' + pagebackref
591             del document.header[i]
592         i = find_token(document.header, "\\pdf_pagemode", 0)
593         if i != -1:
594             pagemode = get_value_string(document.header, '\\pdf_pagemode', 0)
595             pagemode = ',\n pdfpagemode=' + pagemode
596             del document.header[i]
597         i = find_token(document.header, "\\pdf_quoted_options", 0)
598         if i != -1:
599             otheroptions = get_value_string(document.header, '\\pdf_quoted_options', 0, 0, True)
600             if title == "" and author == "" and subject == "" and keywords == "":
601                 otheroptions = ' ' + otheroptions
602             else:
603                 otheroptions = ',\n ' + otheroptions
604             del document.header[i]
605
606         # write to the preamble when hyperref was used
607         if hyperref == True:
608             # preamble write preparations
609             # bookmark numbers are only output when they are turned on
610             if bookmarksopen == ',\n bookmarksopen=true':
611                 bookmarksopen = bookmarksopen + bookmarksopenlevel
612             if bookmarks == ',\n bookmarks=true':
613                 bookmarks = bookmarks + bookmarksnumbered + bookmarksopen
614             else:
615                 bookmarks = bookmarks
616             # hypersetup is only output when there are things to be set up
617             setupstart = '\\hypersetup{%\n'
618             setupend = ' }\n'
619             if otheroptions == "" and title == "" and  author == ""\
620                and  subject == "" and keywords == "":
621                 setupstart = ""
622                 setupend = ""
623             # write the preamble
624             add_to_preamble(document,
625                                 ['% Commands inserted by lyx2lyx for PDF properties',
626                                  '\\usepackage[unicode=true'
627                                  + bookmarks
628                                  + breaklinks
629                                  + pdfborder
630                                  + backref
631                                  + pagebackref
632                                  + colorlinks
633                                  + pagemode
634                                  + ']\n'
635                                  ' {hyperref}\n'
636                                  + setupstart
637                                  + title
638                                  + author
639                                  + subject
640                                  + keywords
641                                  + otheroptions
642                                  + setupend])
643
644
645 def remove_inzip_options(document):
646     "Remove inzipName and embed options from the Graphics inset"
647     i = 0
648     while 1:
649         i = find_token(document.body, "\\begin_inset Graphics", i)
650         if i == -1:
651             return
652         j = find_end_of_inset(document.body, i + 1)
653         if j == -1:
654             # should not happen
655             document.warning("Malformed LyX document: Could not find end of graphics inset.")
656         # If there's a inzip param, just remove that
657         k = find_token(document.body, "\tinzipName", i + 1, j)
658         if k != -1:
659             del document.body[k]
660             # embed option must follow the inzipName option
661             del document.body[k+1]
662         i = i + 1
663
664
665 def convert_inset_command(document):
666     """
667         Convert:
668             \begin_inset LatexCommand cmd
669         to
670             \begin_inset CommandInset InsetType
671             LatexCommand cmd
672     """
673     i = 0
674     while 1:
675         i = find_token(document.body, "\\begin_inset LatexCommand", i)
676         if i == -1:
677             return
678         line = document.body[i]
679         r = re.compile(r'\\begin_inset LatexCommand (.*)$')
680         m = r.match(line)
681         cmdName = m.group(1)
682         insetName = ""
683         #this is adapted from factory.cpp
684         if cmdName[0:4].lower() == "cite":
685             insetName = "citation"
686         elif cmdName == "url" or cmdName == "htmlurl":
687             insetName = "url"
688         elif cmdName[-3:] == "ref":
689             insetName = "ref"
690         elif cmdName == "tableofcontents":
691             insetName = "toc"
692         elif cmdName == "printnomenclature":
693             insetName = "nomencl_print"
694         elif cmdName == "printindex":
695             insetName = "index_print"
696         else:
697             insetName = cmdName
698         insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
699         document.body[i : i+1] = insertion
700
701
702 def revert_inset_command(document):
703     """
704         Convert:
705             \begin_inset CommandInset InsetType
706             LatexCommand cmd
707         to
708             \begin_inset LatexCommand cmd
709         Some insets may end up being converted to insets earlier versions of LyX
710         will not be able to recognize. Not sure what to do about that.
711     """
712     i = 0
713     while 1:
714         i = find_token(document.body, "\\begin_inset CommandInset", i)
715         if i == -1:
716             return
717         nextline = document.body[i+1]
718         r = re.compile(r'LatexCommand\s+(.*)$')
719         m = r.match(nextline)
720         if not m:
721             document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
722             continue
723         cmdName = m.group(1)
724         insertion = ["\\begin_inset LatexCommand " + cmdName]
725         document.body[i : i+2] = insertion
726
727
728 def convert_wrapfig_options(document):
729     "Convert optional options for wrap floats (wrapfig)."
730     # adds the tokens "lines", "placement", and "overhang"
731     i = 0
732     while True:
733         i = find_token(document.body, "\\begin_inset Wrap figure", i)
734         if i == -1:
735             return
736         document.body.insert(i + 1, "lines 0")
737         j = find_token(document.body, "placement", i)
738         # placement can be already set or not; if not, set it
739         if j == i+2:
740             document.body.insert(i + 3, "overhang 0col%")
741         else:
742            document.body.insert(i + 2, "placement o")
743            document.body.insert(i + 3, "overhang 0col%")
744         i = i + 1
745
746
747 def revert_wrapfig_options(document):
748     "Revert optional options for wrap floats (wrapfig)."
749     i = 0
750     while True:
751         i = find_token(document.body, "lines", i)
752         if i == -1:
753             return
754         j = find_token(document.body, "overhang", i+1)
755         if j != i + 2 and j != -1:
756             document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float.")
757         if j == -1:
758             return
759         del document.body[i]
760         del document.body[j-1]
761         i = i + 1
762
763
764 # To convert and revert indices, we need to convert between LaTeX 
765 # strings and LyXText. Here we do a minimal conversion to prevent 
766 # crashes and data loss. Manual patch-up may be needed.
767 replacements = [
768   [r'\\\"a', u'ä'], 
769   [r'\\\"o', u'ö'], 
770   [r'\\\"u', u'ü'],
771   [r'\\\'a', u'á'],
772   [r'\\\'e', u'é'],
773   [r'\\\'i', u'í'],
774   [r'\\\'o', u'ó'],
775   [r'\\\'u', u'ú']
776 ]
777
778 def convert_latexcommand_index(document):
779     "Convert from LatexCommand form to collapsable form."
780     i = 0
781     while True:
782         i = find_token(document.body, "\\begin_inset CommandInset index", i)
783         if i == -1:
784             return
785         if document.body[i + 1] != "LatexCommand index": # Might also be index_print
786             return
787         fullcontent = document.body[i + 2][5:]
788         fullcontent.strip()
789         fullcontent = fullcontent[1:-1]
790         document.body[i:i + 3] = ["\\begin_inset Index",
791           "status collapsed",
792           "\\begin_layout Standard"]
793         i += 3
794         # We are now on the blank line preceding "\end_inset"
795         # We will write the content here, into the inset.
796
797         # Do the LaTeX --> LyX text conversion
798         for rep in replacements:
799             fullcontent = fullcontent.replace(rep[0], rep[1])
800         # Generic, \" -> ":
801         fullcontent = wrap_into_ert(fullcontent, r'\"', '"')
802         # Math:
803         r = re.compile('^(.*?)(\$.*?\$)(.*)')
804         lines = fullcontent.split('\n')
805         for line in lines:
806             #document.warning("LINE: " + line)
807             #document.warning(str(i) + ":" + document.body[i])
808             #document.warning("LAST: " + document.body[-1])
809             g = line
810             while r.match(g):
811                 m = r.match(g)
812                 s = m.group(1)
813                 f = m.group(2).replace('\\\\', '\\')
814                 g = m.group(3)
815                 if s:
816                   # this is non-math!
817                   s = wrap_into_ert(s, r'\\', '\\backslash')
818                   s = wrap_into_ert(s, '{', '{')
819                   s = wrap_into_ert(s, '}', '}')
820                   subst = s.split('\n')
821                   document.body[i:i] = subst
822                   i += len(subst)
823                 document.body.insert(i + 1, "\\begin_inset Formula " + f)
824                 document.body.insert(i + 2, "\\end_inset")
825                 i += 2
826             # Generic, \\ -> \backslash:
827             g = wrap_into_ert(g, r'\\', '\\backslash')
828             g = wrap_into_ert(g, '{', '{')
829             g = wrap_into_ert(g, '}', '}')
830             subst = g.split('\n')
831             document.body[i+1:i+1] = subst
832             i += len(subst)
833         document.body.insert(i + 1, "\\end_layout")
834
835
836 def revert_latexcommand_index(document):
837     "Revert from collapsable form to LatexCommand form."
838     i = 0
839     while True:
840         i = find_token(document.body, "\\begin_inset Index", i)
841         if i == -1:
842           return
843         j = find_end_of_inset(document.body, i + 1)
844         if j == -1:
845           return
846         del document.body[j - 1]
847         del document.body[j - 2] # \end_layout
848         document.body[i] =  "\\begin_inset CommandInset index"
849         document.body[i + 1] =  "LatexCommand index"
850         # clean up multiline stuff
851         content = ""
852         ert_end = 0
853         for k in range(i + 3, j - 2):
854           line = document.body[k]
855           if line.startswith("\\begin_inset ERT"):
856               ert_end = find_end_of_inset(document.body, k + 1)
857               line = line[16:]
858           if line.startswith("\\begin_inset Formula"):
859             line = line[20:]
860           if line.startswith("\\begin_layout Standard"):
861             line = line[22:]
862           if line.startswith("\\begin_layout Plain Layout"):
863             line = line[26:]
864           if line.startswith("\\end_layout"):
865             line = line[11:]
866           if line.startswith("\\end_inset"):
867             line = line[10:]
868           if line.startswith("status collapsed"):
869             line = line[16:]
870           if line.startswith("status open"):
871             line = line[11:]
872           # a lossless reversion is not possible
873           # try at least to handle some common insets and settings
874           # do not replace inside ERTs
875           if ert_end < k:
876               # Do the LyX text --> LaTeX conversion
877               for rep in replacements:
878                 line = line.replace(rep[1], rep[0])
879               line = line.replace(r'\backslash', r'\textbackslash{}')
880               line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}')
881               line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}')
882               line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}')
883               line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}')
884               line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}')
885               line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}')
886               line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}')
887               line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}')
888               line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'')
889           else:
890               line = line.replace(r'\backslash', r'\\')
891           content = content + line;
892         document.body[i + 3] = "name " + '"' + content + '"'
893         for k in range(i + 4, j - 2):
894           del document.body[i + 4]
895         document.body.insert(i + 4, "")
896         del document.body[i + 2] # \begin_layout standard
897         i = i + 5
898
899
900 def revert_wraptable(document):
901     "Revert wrap table to wrap figure."
902     i = 0
903     while True:
904         i = find_token(document.body, "\\begin_inset Wrap table", i)
905         if i == -1:
906             return
907         document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
908         i = i + 1
909
910
911 def revert_vietnamese(document):
912     "Set language Vietnamese to English"
913     # Set document language from Vietnamese to English
914     i = 0
915     if document.language == "vietnamese":
916         document.language = "english"
917         i = find_token(document.header, "\\language", 0)
918         if i != -1:
919             document.header[i] = "\\language english"
920     j = 0
921     while True:
922         j = find_token(document.body, "\\lang vietnamese", j)
923         if j == -1:
924             return
925         document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
926         j = j + 1
927
928
929 def revert_japanese(document):
930     "Set language japanese-plain to japanese"
931     # Set document language from japanese-plain to japanese
932     i = 0
933     if document.language == "japanese-plain":
934         document.language = "japanese"
935         i = find_token(document.header, "\\language", 0)
936         if i != -1:
937             document.header[i] = "\\language japanese"
938     j = 0
939     while True:
940         j = find_token(document.body, "\\lang japanese-plain", j)
941         if j == -1:
942             return
943         document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
944         j = j + 1
945
946
947 def revert_japanese_encoding(document):
948     "Set input encoding form EUC-JP-plain to EUC-JP etc."
949     # Set input encoding form EUC-JP-plain to EUC-JP etc.
950     i = 0
951     i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
952     if i != -1:
953         document.header[i] = "\\inputencoding EUC-JP"
954     j = 0
955     j = find_token(document.header, "\\inputencoding JIS-plain", 0)
956     if j != -1:
957         document.header[j] = "\\inputencoding JIS"
958     k = 0
959     k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
960     if k != -1: # convert to UTF8 since there is currently no SJIS encoding
961         document.header[k] = "\\inputencoding UTF8"
962
963
964 def revert_inset_info(document):
965     'Replace info inset with its content'
966     i = 0
967     while 1:
968         i = find_token(document.body, '\\begin_inset Info', i)
969         if i == -1:
970             return
971         j = find_end_of_inset(document.body, i + 1)
972         if j == -1:
973             # should not happen
974             document.warning("Malformed LyX document: Could not find end of Info inset.")
975         type = 'unknown'
976         arg = ''
977         for k in range(i, j+1):
978             if document.body[k].startswith("arg"):
979                 arg = document.body[k][3:].strip().strip('"')
980             if document.body[k].startswith("type"):
981                 type = document.body[k][4:].strip().strip('"')
982         # I think there is a newline after \\end_inset, which should be removed.
983         if document.body[j + 1].strip() == "":
984             document.body[i : (j + 2)] = [type + ':' + arg]
985         else:
986             document.body[i : (j + 1)] = [type + ':' + arg]
987
988
989 def convert_pdf_options(document):
990     # Set the pdfusetitle tag, delete the pdf_store_options,
991     # set quotes for bookmarksopenlevel"
992     has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
993     if has_hr == "1":
994         k = find_token(document.header, "\\use_hyperref", 0)
995         document.header.insert(k + 1, "\\pdf_pdfusetitle true")
996     k = find_token(document.header, "\\pdf_store_options", 0)
997     if k != -1:
998         del document.header[k]
999     i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1000     if i == -1: return
1001     document.header[i] = document.header[i].replace('"', '')
1002
1003
1004 def revert_pdf_options_2(document):
1005     # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
1006     k = find_token(document.header, "\\use_hyperref", 0)
1007     i = find_token(document.header, "\\pdf_pdfusetitle", k)
1008     if i != -1:
1009         del document.header[i]
1010     i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1011     if i == -1: return
1012     values = document.header[i].split()
1013     values[1] = ' "' + values[1] + '"'
1014     document.header[i] = ''.join(values)
1015
1016
1017 def convert_htmlurl(document):
1018     'Convert "htmlurl" to "href" insets for docbook'
1019     if document.backend != "docbook":
1020       return
1021     i = 0
1022     while True:
1023       i = find_token(document.body, "\\begin_inset CommandInset url", i)
1024       if i == -1:
1025         return
1026       document.body[i] = "\\begin_inset CommandInset href"
1027       document.body[i + 1] = "LatexCommand href"
1028       i = i + 1
1029
1030
1031 def convert_url(document):
1032     'Convert url insets to url charstyles'
1033     if document.backend == "docbook":
1034       return
1035     i = 0
1036     while True:
1037       i = find_token(document.body, "\\begin_inset CommandInset url", i)
1038       if i == -1:
1039         break
1040       n = find_token(document.body, "name", i)
1041       if n == i + 2:
1042         # place the URL name in typewriter before the new URL insert
1043         # grab the name 'bla' from the e.g. the line 'name "bla"',
1044         # therefore start with the 6th character
1045         name = document.body[n][6:-1]
1046         newname = [name + " "]
1047         document.body[i:i] = newname
1048         i = i + 1
1049       j = find_token(document.body, "target", i)
1050       if j == -1:
1051         document.warning("Malformed LyX document: Can't find target for url inset")
1052         i = j
1053         continue
1054       target = document.body[j][8:-1]
1055       k = find_token(document.body, "\\end_inset", j)
1056       if k == -1:
1057         document.warning("Malformed LyX document: Can't find end of url inset")
1058         i = k
1059         continue
1060       newstuff = ["\\begin_inset Flex URL",
1061         "status collapsed", "",
1062         "\\begin_layout Standard",
1063         "",
1064         target,
1065         "\\end_layout",
1066         ""]
1067       document.body[i:k] = newstuff
1068       i = k
1069
1070 def convert_ams_classes(document):
1071   tc = document.textclass
1072   if (tc != "amsart" and tc != "amsart-plain" and
1073       tc != "amsart-seq" and tc != "amsbook"):
1074     return
1075   if tc == "amsart-plain":
1076     document.textclass = "amsart"
1077     document.set_textclass()
1078     document.add_module("Theorems (Starred)")
1079     return
1080   if tc == "amsart-seq":
1081     document.textclass = "amsart"
1082     document.set_textclass()
1083   document.add_module("Theorems (AMS)")
1084
1085   #Now we want to see if any of the environments in the extended theorems
1086   #module were used in this document. If so, we'll add that module, too.
1087   layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note",  \
1088     "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
1089     "Assumption"]
1090
1091   r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
1092   i = 0
1093   while True:
1094     i = find_token(document.body, "\\begin_layout", i)
1095     if i == -1:
1096       return
1097     m = r.match(document.body[i])
1098     if m == None:
1099       document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
1100       i += 1
1101       continue
1102     m = m.group(1)
1103     if layouts.count(m) != 0:
1104       document.add_module("Theorems (AMS-Extended)")
1105       return
1106     i += 1
1107
1108 def revert_href(document):
1109     'Reverts hyperlink insets (href) to url insets (url)'
1110     i = 0
1111     while True:
1112       i = find_token(document.body, "\\begin_inset CommandInset href", i)
1113       if i == -1:
1114           return
1115       document.body[i : i + 2] = \
1116         ["\\begin_inset CommandInset url", "LatexCommand url"]
1117       i = i + 2
1118
1119 def revert_url(document):
1120     'Reverts Flex URL insets to old-style URL insets'
1121     i = 0
1122     while True:
1123         i = find_token(document.body, "\\begin_inset Flex URL", i)
1124         if i == -1:
1125             return
1126         j = find_end_of_inset(document.body, i)
1127         if j == -1:
1128             document.warning("Can't find end of inset in revert_url!")
1129             return
1130         k = find_default_layout(document, i, j)
1131         if k == -1:
1132             document.warning("Can't find default layout in revert_url!")
1133             i = j
1134             continue
1135         l = find_end_of(document.body, k, "\\begin_layout", "\\end_layout")
1136         if l == -1 or l >= j:
1137             document.warning("Can't find end of default layout in revert_url!")
1138             i = j
1139             continue
1140         # OK, so the inset's data is between lines k and l.
1141         data =  " ".join(document.body[k+1:l])
1142         data = data.strip()
1143         newinset = ["\\begin_inset LatexCommand url", "target \"" + data + "\"",\
1144                     "", "\\end_inset"]
1145         document.body[i:j+1] = newinset
1146         i = i + len(newinset)
1147
1148
1149 def convert_include(document):
1150   'Converts include insets to new format.'
1151   i = 0
1152   r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
1153   while True:
1154     i = find_token(document.body, "\\begin_inset Include", i)
1155     if i == -1:
1156       return
1157     line = document.body[i]
1158     previewline = document.body[i + 1]
1159     m = r.match(line)
1160     if m == None:
1161       document.warning("Unable to match line " + str(i) + " of body!")
1162       i += 1
1163       continue
1164     cmd = m.group(1)
1165     fn  = m.group(2)
1166     opt = m.group(3)
1167     insertion = ["\\begin_inset CommandInset include",
1168        "LatexCommand " + cmd, previewline,
1169        "filename \"" + fn + "\""]
1170     newlines = 2
1171     if opt:
1172       insertion.append("lstparams " + '"' + opt + '"')
1173       newlines += 1
1174     document.body[i : i + 2] = insertion
1175     i += newlines
1176
1177
1178 def revert_include(document):
1179   'Reverts include insets to old format.'
1180   i = 0
1181   r0 = re.compile('preview.*')
1182   r1 = re.compile('LatexCommand (.+)')
1183   r2 = re.compile('filename (.+)')
1184   r3 = re.compile('options (.*)')
1185   while True:
1186     i = find_token(document.body, "\\begin_inset CommandInset include", i)
1187     if i == -1:
1188       return
1189     nextline = i + 1
1190     if r0.match(document.body[nextline]):
1191       previewline = document.body[nextline]
1192       nextline += 1
1193     else:
1194       previewline = ""
1195     m = r1.match(document.body[nextline])
1196     if m == None:
1197       document.warning("Malformed LyX document: No LatexCommand line for `" +
1198         document.body[i] + "' on line " + str(i) + ".")
1199       i += 1
1200       continue
1201     cmd = m.group(1)
1202     nextline += 1
1203     m = r2.match(document.body[nextline])
1204     if m == None:
1205       document.warning("Malformed LyX document: No filename line for `" + \
1206         document.body[i] + "' on line " + str(i) + ".")
1207       i += 2
1208       continue
1209     fn = m.group(1)
1210     nextline += 1
1211     options = ""
1212     if (cmd == "lstinputlisting"):
1213       m = r3.match(document.body[nextline])
1214       if m != None:
1215         options = m.group(1)
1216         numlines = 5
1217         nextline += 1
1218     newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1219     if options:
1220       newline += ("[" + options + "]")
1221     insertion = [newline]
1222     if previewline != "":
1223       insertion.append(previewline)
1224     document.body[i : nextline] = insertion
1225     i += 2
1226
1227
1228 def revert_albanian(document):
1229     "Set language Albanian to English"
1230     i = 0
1231     if document.language == "albanian":
1232         document.language = "english"
1233         i = find_token(document.header, "\\language", 0)
1234         if i != -1:
1235             document.header[i] = "\\language english"
1236     j = 0
1237     while True:
1238         j = find_token(document.body, "\\lang albanian", j)
1239         if j == -1:
1240             return
1241         document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1242         j = j + 1
1243
1244
1245 def revert_lowersorbian(document):
1246     "Set language lower Sorbian to English"
1247     i = 0
1248     if document.language == "lowersorbian":
1249         document.language = "english"
1250         i = find_token(document.header, "\\language", 0)
1251         if i != -1:
1252             document.header[i] = "\\language english"
1253     j = 0
1254     while True:
1255         j = find_token(document.body, "\\lang lowersorbian", j)
1256         if j == -1:
1257             return
1258         document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1259         j = j + 1
1260
1261
1262 def revert_uppersorbian(document):
1263     "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1264     i = 0
1265     if document.language == "uppersorbian":
1266         document.language = "usorbian"
1267         i = find_token(document.header, "\\language", 0)
1268         if i != -1:
1269             document.header[i] = "\\language usorbian"
1270     j = 0
1271     while True:
1272         j = find_token(document.body, "\\lang uppersorbian", j)
1273         if j == -1:
1274             return
1275         document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1276         j = j + 1
1277
1278
1279 def convert_usorbian(document):
1280     "Set language usorbian to uppersorbian"
1281     i = 0
1282     if document.language == "usorbian":
1283         document.language = "uppersorbian"
1284         i = find_token(document.header, "\\language", 0)
1285         if i != -1:
1286             document.header[i] = "\\language uppersorbian"
1287     j = 0
1288     while True:
1289         j = find_token(document.body, "\\lang usorbian", j)
1290         if j == -1:
1291             return
1292         document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1293         j = j + 1
1294
1295
1296 def revert_macro_optional_params(document):
1297     "Convert macro definitions with optional parameters into ERTs"
1298     # Stub to convert macro definitions with one or more optional parameters
1299     # into uninterpreted ERT insets
1300
1301
1302 def revert_hyperlinktype(document):
1303     'Reverts hyperlink type'
1304     i = 0
1305     j = 0
1306     while True:
1307       i = find_token(document.body, "target", i)
1308       if i == -1:
1309           return
1310       j = find_token(document.body, "type", i)
1311       if j == -1:
1312           return
1313       if j == i + 1:
1314           del document.body[j]
1315       i = i + 1
1316
1317
1318 def revert_pagebreak(document):
1319     'Reverts pagebreak to ERT'
1320     i = 0
1321     while True:
1322       i = find_token(document.body, "\\pagebreak", i)
1323       if i == -1:
1324           return
1325       document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1326       '\\begin_layout Standard\n\n\n\\backslash\n' \
1327       'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1328       i = i + 1
1329
1330
1331 def revert_linebreak(document):
1332     'Reverts linebreak to ERT'
1333     i = 0
1334     while True:
1335       i = find_token(document.body, "\\linebreak", i)
1336       if i == -1:
1337           return
1338       document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1339       '\\begin_layout Standard\n\n\n\\backslash\n' \
1340       'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1341       i = i + 1
1342
1343
1344 def revert_latin(document):
1345     "Set language Latin to English"
1346     i = 0
1347     if document.language == "latin":
1348         document.language = "english"
1349         i = find_token(document.header, "\\language", 0)
1350         if i != -1:
1351             document.header[i] = "\\language english"
1352     j = 0
1353     while True:
1354         j = find_token(document.body, "\\lang latin", j)
1355         if j == -1:
1356             return
1357         document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1358         j = j + 1
1359
1360
1361 def revert_samin(document):
1362     "Set language North Sami to English"
1363     i = 0
1364     if document.language == "samin":
1365         document.language = "english"
1366         i = find_token(document.header, "\\language", 0)
1367         if i != -1:
1368             document.header[i] = "\\language english"
1369     j = 0
1370     while True:
1371         j = find_token(document.body, "\\lang samin", j)
1372         if j == -1:
1373             return
1374         document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1375         j = j + 1
1376
1377
1378 def convert_serbocroatian(document):
1379     "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1380     i = 0
1381     if document.language == "serbocroatian":
1382         document.language = "croatian"
1383         i = find_token(document.header, "\\language", 0)
1384         if i != -1:
1385             document.header[i] = "\\language croatian"
1386     j = 0
1387     while True:
1388         j = find_token(document.body, "\\lang serbocroatian", j)
1389         if j == -1:
1390             return
1391         document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1392         j = j + 1
1393
1394
1395 def convert_framed_notes(document):
1396     "Convert framed notes to boxes. "
1397     i = 0
1398     while 1:
1399         i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1400         if i == -1:
1401             return
1402         subst = [document.body[i].replace("\\begin_inset Note", "\\begin_inset Box"),
1403                  'position "t"',
1404                  'hor_pos "c"',
1405                  'has_inner_box 0',
1406                  'inner_pos "t"', 
1407                  'use_parbox 0',
1408                  'width "100col%"',
1409                  'special "none"',
1410                  'height "1in"',
1411                  'height_special "totalheight"']
1412         document.body[i:i+1] = subst
1413         i = i + 9
1414
1415
1416 def convert_module_names(document):
1417   modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1418     'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1419     'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1420     'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1421     'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1422   modlist = document.get_module_list()
1423   if len(modlist) == 0:
1424     return
1425   newmodlist = []
1426   for mod in modlist:
1427     if modulemap.has_key(mod):
1428       newmodlist.append(modulemap[mod])
1429     else:
1430       document.warning("Can't find module %s in the module map!" % mod)
1431       newmodlist.append(mod)
1432   document.set_module_list(newmodlist)
1433
1434
1435 def revert_module_names(document):
1436   modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1437     'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1438     'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1439     'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1440     'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1441   modlist = document.get_module_list()
1442   if len(modlist) == 0:
1443     return
1444   newmodlist = []
1445   for mod in modlist:
1446     if modulemap.has_key(mod):
1447       newmodlist.append(modulemap[mod])
1448     else:
1449       document.warning("Can't find module %s in the module map!" % mod)
1450       newmodlist.append(mod)
1451   document.set_module_list(newmodlist)
1452
1453
1454 def revert_colsep(document):
1455     i = find_token(document.header, "\\columnsep", 0)
1456     if i == -1:
1457         return
1458     colsepline = document.header[i]
1459     r = re.compile(r'\\columnsep (.*)')
1460     m = r.match(colsepline)
1461     if not m:
1462         document.warning("Malformed column separation line!")
1463         return
1464     colsep = m.group(1)
1465     del document.header[i]
1466     #it seems to be safe to add the package even if it is already used
1467     pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1468
1469     add_to_preamble(document, pretext)
1470
1471
1472 def revert_framed_notes(document):
1473     "Revert framed boxes to notes. "
1474     i = 0
1475     while 1:
1476         i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1477
1478         if i == -1:
1479             return
1480         j = find_end_of_inset(document.body, i + 1)
1481         if j == -1:
1482             # should not happen
1483             document.warning("Malformed LyX document: Could not find end of Box inset.")
1484         k = find_token(document.body, "status", i + 1, j)
1485         if k == -1:
1486             document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1487             return
1488         status = document.body[k]
1489         l = find_default_layout(document, i + 1, j)
1490         if l == -1:
1491             document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1492             return
1493         m = find_token(document.body, "\\end_layout", i + 1, j)
1494         if m == -1:
1495             document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1496             return
1497         ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1498         pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1499         if ibox == -1 and pbox == -1:
1500             document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1501             del document.body[i+1:k]
1502         else:
1503             document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1504             subst1 = [document.body[l],
1505                       "\\begin_inset Note Shaded",
1506                       status,
1507                       '\\begin_layout Standard']
1508             document.body[l:l + 1] = subst1
1509             subst2 = [document.body[m], "\\end_layout", "\\end_inset"]
1510             document.body[m:m + 1] = subst2
1511         i = i + 1
1512
1513
1514 def revert_slash(document):
1515     'Revert \\SpecialChar \\slash{} to ERT'
1516     r = re.compile(r'\\SpecialChar \\slash{}')
1517     i = 0
1518     while i < len(document.body):
1519         m = r.match(document.body[i])
1520         if m:
1521           subst = ['\\begin_inset ERT',
1522                    'status collapsed', '',
1523                    '\\begin_layout Standard',
1524                    '', '', '\\backslash',
1525                    'slash{}',
1526                    '\\end_layout', '',
1527                    '\\end_inset', '']
1528           document.body[i: i+1] = subst
1529           i = i + len(subst)
1530         else:
1531           i = i + 1
1532
1533
1534 def revert_nobreakdash(document):
1535     'Revert \\SpecialChar \\nobreakdash- to ERT'
1536     i = 0
1537     while i < len(document.body):
1538         line = document.body[i]
1539         r = re.compile(r'\\SpecialChar \\nobreakdash-')
1540         m = r.match(line)
1541         if m:
1542             subst = ['\\begin_inset ERT',
1543                     'status collapsed', '',
1544                     '\\begin_layout Standard', '', '',
1545                     '\\backslash',
1546                     'nobreakdash-',
1547                     '\\end_layout', '',
1548                     '\\end_inset', '']
1549             document.body[i:i+1] = subst
1550             i = i + len(subst)
1551             j = find_token(document.header, "\\use_amsmath", 0)
1552             if j == -1:
1553                 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1554                 return
1555             document.header[j] = "\\use_amsmath 2"
1556         else:
1557             i = i + 1
1558
1559
1560 #Returns number of lines added/removed
1561 def revert_nocite_key(body, start, end):
1562     'key "..." -> \nocite{...}' 
1563     r = re.compile(r'^key "(.*)"')
1564     i = start
1565     j = end
1566     while i < j:
1567         m = r.match(body[i])
1568         if m:
1569             body[i:i+1] = ["\\backslash", "nocite{" + m.group(1) + "}"]
1570             j += 1     # because we added a line
1571             i += 2     # skip that line
1572         else:
1573             del body[i]
1574             j -= 1     # because we deleted a line
1575             # no need to change i, since it now points to the next line
1576     return j - end
1577
1578
1579 def revert_nocite(document):
1580     "Revert LatexCommand nocite to ERT"
1581     i = 0
1582     while 1:
1583         i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1584         if i == -1:
1585             return
1586         if (document.body[i+1] != "LatexCommand nocite"):
1587             # note that we already incremented i
1588             i = i + 1
1589             continue
1590         insetEnd = find_end_of_inset(document.body, i)
1591         if insetEnd == -1:
1592             #this should not happen
1593             document.warning("End of CommandInset citation not found in revert_nocite!")
1594             return
1595
1596         paramLocation = i + 2 #start of the inset's parameters
1597         addedLines = 0
1598         document.body[i:i+2] = \
1599             ["\\begin_inset ERT", "status collapsed", "", "\\begin_layout Standard"]
1600         # that added two lines
1601         paramLocation += 2
1602         insetEnd += 2
1603         #print insetEnd, document.body[i: insetEnd + 1]
1604         insetEnd += revert_nocite_key(document.body, paramLocation, insetEnd)
1605         #print insetEnd, document.body[i: insetEnd + 1]
1606         document.body.insert(insetEnd, "\\end_layout")
1607         document.body.insert(insetEnd + 1, "")
1608         i = insetEnd + 1
1609
1610
1611 def revert_btprintall(document):
1612     "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1613     i = find_token(document.header, '\\use_bibtopic', 0)
1614     if i == -1:
1615         document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1616         return
1617     if get_value(document.header, '\\use_bibtopic', 0) == "false":
1618         i = 0
1619         while i < len(document.body):
1620             i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1621             if i == -1:
1622                 return
1623             j = find_end_of_inset(document.body, i + 1)
1624             if j == -1:
1625                 #this should not happen
1626                 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1627                 j = len(document.body)
1628             # this range isn't really right, but it should be OK, since we shouldn't
1629             # see more than one matching line in each inset
1630             addedlines = 0
1631             for k in range(i, j):
1632                 if (document.body[k] == 'btprint "btPrintAll"'):
1633                     del document.body[k]
1634                     subst = ["\\begin_inset ERT",
1635                              "status collapsed", "",
1636                              "\\begin_layout Standard", "",
1637                              "\\backslash",
1638                              "nocite{*}",
1639                              "\\end_layout",
1640                              "\\end_inset"]
1641                     document.body[i:i] = subst
1642                     addlines = addedlines + len(subst) - 1
1643             i = j + addedlines
1644
1645
1646 def revert_bahasam(document):
1647     "Set language Bahasa Malaysia to Bahasa Indonesia"
1648     i = 0
1649     if document.language == "bahasam":
1650         document.language = "bahasa"
1651         i = find_token(document.header, "\\language", 0)
1652         if i != -1:
1653             document.header[i] = "\\language bahasa"
1654     j = 0
1655     while True:
1656         j = find_token(document.body, "\\lang bahasam", j)
1657         if j == -1:
1658             return
1659         document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1660         j = j + 1
1661
1662
1663 def revert_interlingua(document):
1664     "Set language Interlingua to English"
1665     i = 0
1666     if document.language == "interlingua":
1667         document.language = "english"
1668         i = find_token(document.header, "\\language", 0)
1669         if i != -1:
1670             document.header[i] = "\\language english"
1671     j = 0
1672     while True:
1673         j = find_token(document.body, "\\lang interlingua", j)
1674         if j == -1:
1675             return
1676         document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1677         j = j + 1
1678
1679
1680 def revert_serbianlatin(document):
1681     "Set language Serbian-Latin to Croatian"
1682     i = 0
1683     if document.language == "serbian-latin":
1684         document.language = "croatian"
1685         i = find_token(document.header, "\\language", 0)
1686         if i != -1:
1687             document.header[i] = "\\language croatian"
1688     j = 0
1689     while True:
1690         j = find_token(document.body, "\\lang serbian-latin", j)
1691         if j == -1:
1692             return
1693         document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1694         j = j + 1
1695
1696
1697 def revert_rotfloat(document):
1698     " Revert sideways custom floats. "
1699     i = 0
1700     while 1:
1701         # whitespace intended (exclude \\begin_inset FloatList)
1702         i = find_token(document.body, "\\begin_inset Float ", i)
1703         if i == -1:
1704             return
1705         line = document.body[i]
1706         r = re.compile(r'\\begin_inset Float (.*)$')
1707         m = r.match(line)
1708         if m == None:
1709             document.warning("Unable to match line " + str(i) + " of body!")
1710             i += 1
1711             continue
1712         floattype = m.group(1)
1713         if floattype == "figure" or floattype == "table":
1714             i += 1
1715             continue
1716         j = find_end_of_inset(document.body, i)
1717         if j == -1:
1718             document.warning("Malformed lyx document: Missing '\\end_inset' in revert_rotfloat.")
1719             i += 1
1720             continue
1721         addedLines = 0
1722         if get_value(document.body, 'sideways', i, j) == "false":
1723             i += 1
1724             continue
1725         l = find_default_layout(document, i + 1, j)
1726         if l == -1:
1727             document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1728             return
1729         subst = ['\\begin_layout Standard',
1730                   '\\begin_inset ERT',
1731                   'status collapsed', '',
1732                   '\\begin_layout Standard', '', '', 
1733                   '\\backslash', '',
1734                   'end{sideways' + floattype + '}',
1735                   '\\end_layout', '', '\\end_inset']
1736         document.body[j : j+1] = subst
1737         addedLines = len(subst) - 1
1738         del document.body[i+1 : l]
1739         addedLines -= (l-1) - (i+1) 
1740         subst = ['\\begin_inset ERT', 'status collapsed', '',
1741                   '\\begin_layout Standard', '', '', '\\backslash', 
1742                   'begin{sideways' + floattype + '}', 
1743                   '\\end_layout', '', '\\end_inset', '',
1744                   '\\end_layout', '']
1745         document.body[i : i+1] = subst
1746         addedLines += len(subst) - 1
1747         if floattype == "algorithm":
1748             add_to_preamble(document,
1749                             ['% Commands inserted by lyx2lyx for sideways algorithm float',
1750                               '\\usepackage{rotfloat}',
1751                               '\\floatstyle{ruled}',
1752                               '\\newfloat{algorithm}{tbp}{loa}',
1753                               '\\floatname{algorithm}{Algorithm}'])
1754         else:
1755             document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1756         i += addedLines + 1
1757
1758
1759 def revert_widesideways(document):
1760     " Revert wide sideways floats. "
1761     i = 0
1762     while 1:
1763         # whitespace intended (exclude \\begin_inset FloatList)
1764         i = find_token(document.body, '\\begin_inset Float ', i)
1765         if i == -1:
1766             return
1767         line = document.body[i]
1768         r = re.compile(r'\\begin_inset Float (.*)$')
1769         m = r.match(line)
1770         if m == None:
1771             document.warning("Unable to match line " + str(i) + " of body!")
1772             i += 1
1773             continue
1774         floattype = m.group(1)
1775         if floattype != "figure" and floattype != "table":
1776             i += 1
1777             continue
1778         j = find_end_of_inset(document.body, i)
1779         if j == -1:
1780             document.warning("Malformed lyx document: Missing '\\end_inset' in revert_widesideways.")
1781             i += 1
1782             continue
1783         if get_value(document.body, 'sideways', i, j) == "false" or \
1784            get_value(document.body, 'wide', i, j) == "false":
1785              i += 1
1786              continue
1787         l = find_default_layout(document, i + 1, j)
1788         if l == -1:
1789             document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1790             return
1791         subst = ['\\begin_layout Standard', '\\begin_inset ERT', 
1792                   'status collapsed', '', 
1793                   '\\begin_layout Standard', '', '', '\\backslash',
1794                   'end{sideways' + floattype + '*}', 
1795                   '\\end_layout', '', '\\end_inset']
1796         document.body[j : j+1] = subst
1797         addedLines = len(subst) - 1
1798         del document.body[i+1:l-1]
1799         addedLines -= (l-1) - (i+1)
1800         subst = ['\\begin_inset ERT', 'status collapsed', '',
1801                  '\\begin_layout Standard', '', '', '\\backslash',
1802                  'begin{sideways' + floattype + '*}', '\\end_layout', '',
1803                  '\\end_inset', '', '\\end_layout', '']
1804         document.body[i : i+1] = subst
1805         addedLines += len(subst) - 1
1806         add_to_preamble(document, ['\\usepackage{rotfloat}\n'])
1807         i += addedLines + 1
1808
1809
1810 def revert_inset_embedding(document, type):
1811     ' Remove embed tag from certain type of insets'
1812     i = 0
1813     while 1:
1814         i = find_token(document.body, "\\begin_inset %s" % type, i)
1815         if i == -1:
1816             return
1817         j = find_end_of_inset(document.body, i)
1818         if j == -1:
1819             document.warning("Malformed lyx document: Missing '\\end_inset' in revert_inset_embedding.")
1820             i = i + 1
1821             continue
1822         k = find_token(document.body, "\tembed", i, j)
1823         if k == -1:
1824             k = find_token(document.body, "embed", i, j)
1825         if k != -1:
1826             del document.body[k]
1827         i = i + 1
1828
1829
1830 def revert_external_embedding(document):
1831     ' Remove embed tag from external inset '
1832     revert_inset_embedding(document, 'External')
1833
1834
1835 # FIXME This code can still be cleaned up a fair bit.
1836 def convert_subfig(document):
1837     " Convert subfigures to subfloats. "
1838     i = 0
1839     while 1:
1840         i = find_token(document.body, '\\begin_inset Graphics', i)
1841         if i == -1:
1842             return
1843         endInset = find_end_of_inset(document.body, i)
1844         if endInset == -1:
1845             document.warning("Malformed lyx document: Missing '\\end_inset' in convert_subfig.")
1846             i += 1
1847             continue
1848         k = find_token(document.body, '\tsubcaption', i, endInset)
1849         if k == -1:
1850             i += 1
1851             continue
1852         l = find_token(document.body, '\tsubcaptionText', i, endInset)
1853         caption = document.body[l][16:].strip('"')
1854         savestr = document.body[i]
1855         laststr = document.body[endInset]
1856         del document.body[l]
1857         del document.body[k]
1858         addedLines = -2
1859         # savestr should no longer be needed here.
1860         subst = ['\\begin_inset Float figure', 'wide false', 'sideways false', 
1861                  'status open', '', '\\begin_layout Plain Layout', '\\begin_inset Caption', 
1862                  '', '\\begin_layout Plain Layout',
1863                  caption, '\\end_layout', '', '\\end_inset', '', 
1864                  '\\end_layout', '', '\\begin_layout Plain Layout', savestr]
1865         document.body[i : i+1] = subst
1866         addedLines += len(subst) - 1
1867         endInset += addedLines
1868         # There should be an easier way to do this.
1869         subst = ['', '\\end_inset', '', '\\end_layout', laststr]
1870         document.body[endInset : endInset+1] = subst
1871         addedLines += len(subst) - 1
1872         i += addedLines + 1
1873
1874
1875 def revert_subfig(document):
1876     " Revert subfloats. "
1877     i = 0
1878     while 1:
1879         # whitespace intended (exclude \\begin_inset FloatList)
1880         i = find_tokens(document.body, ['\\begin_inset Float ', '\\begin_inset Wrap'], i)
1881         if i == -1:
1882             return
1883         j = 0
1884         addedLines = 0
1885         while j != -1:
1886             j = find_end_of_inset(document.body, i)
1887             if j == -1:
1888                 document.warning("Malformed lyx document: Missing '\\end_inset' (float) at line " + str(i + len(document.header)) + ".\n\t" + document.body[i])
1889                 # document.warning(document.body[i-1] + "\n" + document.body[i+1])
1890                 i += 1
1891                 continue # this will get us back to the outer loop, since j == -1
1892             # look for embedded float (= subfloat)
1893             # whitespace intended (exclude \\begin_inset FloatList)
1894             k = find_token(document.body, '\\begin_inset Float ', i + 1, j)
1895             if k == -1:
1896                 break
1897             l = find_end_of_inset(document.body, k)
1898             if l == -1:
1899                 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
1900                 i += 1
1901                 j == -1
1902                 continue # escape to the outer loop
1903             m = find_default_layout(document, k + 1, l)
1904             # caption?
1905             cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
1906             caption = ''
1907             shortcap = ''
1908             capend = cap
1909             if cap != -1:
1910                 capend = find_end_of_inset(document.body, cap)
1911                 if capend == -1:
1912                     document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
1913                     return
1914                 # label?
1915                 label = ''
1916                 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
1917                 if lbl != -1:
1918                     lblend = find_end_of_inset(document.body, lbl + 1)
1919                     if lblend == -1:
1920                         document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
1921                         return
1922                     for line in document.body[lbl:lblend + 1]:
1923                         if line.startswith('name '):
1924                             label = line.split()[1].strip('"')
1925                             break
1926                 else:
1927                     lbl = capend
1928                     lblend = capend
1929                     label = ''
1930                 # opt arg?
1931                 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
1932                 if opt != -1:
1933                     optend = find_end_of_inset(document.body, opt)
1934                     if optend == -1:
1935                         document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
1936                         return
1937                     optc = find_default_layout(document, opt, optend)
1938                     if optc == -1:
1939                         document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1940                         return
1941                     optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
1942                     for line in document.body[optc:optcend]:
1943                         if not line.startswith('\\'):
1944                             shortcap += line.strip()
1945                 else:
1946                     opt = capend
1947                     optend = capend
1948                 for line in document.body[cap:capend]:
1949                     if line in document.body[lbl:lblend]:
1950                         continue
1951                     elif line in document.body[opt:optend]:
1952                         continue
1953                     elif not line.startswith('\\'):
1954                         caption += line.strip()
1955                 if len(label) > 0:
1956                     caption += "\\backslash\nlabel{" + label + "}"
1957             subst = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
1958                       '\\begin_layout Plain Layout\n\n}\n\\end_layout\n\n\\end_inset\n\n' \
1959                       '\\end_layout\n\n\\begin_layout Plain Layout\n'
1960             subst = subst.split('\n')
1961             document.body[l : l+1] = subst
1962             addedLines = len(subst) - 1
1963             # this is before l and so is unchanged by the multiline insertion
1964             if cap != capend:
1965                 del document.body[cap:capend+1]
1966                 addedLines -= (capend + 1 - cap)
1967             del document.body[k+1:m-1]
1968             addedLines -= (m - 1 - (k + 1))
1969             insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
1970                         '\\begin_layout Plain Layout\n\n\\backslash\n' \
1971                         'subfloat'
1972             if len(shortcap) > 0:
1973                 insertion = insertion + "[" + shortcap + "]"
1974             if len(caption) > 0:
1975                 insertion = insertion + "[" + caption + "]"
1976             insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
1977             insertion = insertion.split('\n')
1978             document.body[k : k + 1] = insertion
1979             addedLines += len(insertion) - 1
1980             add_to_preamble(document,
1981                             ['\\usepackage{subfig}\n'])
1982         i += addedLines + 1
1983
1984
1985 def revert_wrapplacement(document):
1986     " Revert placement options wrap floats (wrapfig). "
1987     i = 0
1988     while True:
1989         i = find_token(document.body, "lines", i)
1990         if i == -1:
1991             return
1992         j = find_token(document.body, "placement", i+1)
1993         if j != i + 1:
1994             document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
1995             return
1996         document.body[j] = document.body[j].replace("placement O", "placement o")
1997         document.body[j] = document.body[j].replace("placement I", "placement i")
1998         document.body[j] = document.body[j].replace("placement L", "placement l")
1999         document.body[j] = document.body[j].replace("placement R", "placement r")
2000         i = i + 1
2001
2002
2003 def remove_extra_embedded_files(document):
2004     " Remove \extra_embedded_files from buffer params "
2005     i = find_token(document.header, '\\extra_embedded_files', 0)
2006     if i == -1:
2007         return
2008     document.header.pop(i)
2009
2010
2011 def convert_spaceinset(document):
2012     " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
2013     i = 0
2014     while i < len(document.body):
2015         m = re.match(r'(.*)\\InsetSpace (.*)', document.body[i])
2016         if m:
2017             before = m.group(1)
2018             after = m.group(2)
2019             subst = [before, "\\begin_inset Space " + after, "\\end_inset"]
2020             document.body[i: i+1] = subst
2021             i = i + len(subst)
2022         else:
2023             i = i + 1
2024
2025
2026 def revert_spaceinset(document):
2027     " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
2028     i = 0
2029     while True:
2030         i = find_token(document.body, "\\begin_inset Space", i)
2031         if i == -1:
2032             return
2033         j = find_end_of_inset(document.body, i)
2034         if j == -1:
2035             document.warning("Malformed LyX document: Could not find end of space inset.")
2036             continue
2037         document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
2038         del document.body[j]
2039
2040
2041 def convert_hfill(document):
2042     " Convert hfill to space inset "
2043     i = 0
2044     while True:
2045         i = find_token(document.body, "\\hfill", i)
2046         if i == -1:
2047             return
2048         subst = document.body[i].replace('\\hfill', \
2049                   '\n\\begin_inset Space \\hfill{}\n\\end_inset')
2050         subst = subst.split('\n')
2051         document.body[i : i+1] = subst
2052         i += len(subst)
2053
2054
2055 def revert_hfills(document):
2056     ' Revert \\hfill commands '
2057     hfill = re.compile(r'\\hfill')
2058     dotfill = re.compile(r'\\dotfill')
2059     hrulefill = re.compile(r'\\hrulefill')
2060     i = 0
2061     while True:
2062         i = find_token(document.body, "\\InsetSpace", i)
2063         if i == -1:
2064             return
2065         if hfill.search(document.body[i]):
2066             document.body[i] = \
2067               document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
2068             i += 1
2069             continue
2070         if dotfill.search(document.body[i]):
2071             subst = document.body[i].replace('\\InsetSpace \\dotfill{}', \
2072               '\\begin_inset ERT\nstatus collapsed\n\n' \
2073               '\\begin_layout Standard\n\n\n\\backslash\n' \
2074               'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
2075             subst = subst.split('\n')
2076             document.body[i : i+1] = subst
2077             i += len(subst)
2078             continue
2079         if hrulefill.search(document.body[i]):
2080             subst = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
2081               '\\begin_inset ERT\nstatus collapsed\n\n' \
2082               '\\begin_layout Standard\n\n\n\\backslash\n' \
2083               'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
2084             subst = subst.split('\n')
2085             document.body[i : i+1] = subst
2086             i += len(subst)
2087             continue
2088         i += 1
2089
2090 def revert_hspace(document):
2091     ' Revert \\InsetSpace \\hspace{} to ERT '
2092     i = 0
2093     hspace = re.compile(r'\\hspace{}')
2094     hstar  = re.compile(r'\\hspace\*{}')
2095     while True:
2096         i = find_token(document.body, "\\InsetSpace \\hspace", i)
2097         if i == -1:
2098             return
2099         length = get_value(document.body, '\\length', i+1)
2100         if length == '':
2101             document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
2102             return
2103         del document.body[i+1]
2104         addedLines = -1
2105         if hstar.search(document.body[i]):
2106             subst = document.body[i].replace('\\InsetSpace \\hspace*{}', \
2107               '\\begin_inset ERT\nstatus collapsed\n\n' \
2108               '\\begin_layout Standard\n\n\n\\backslash\n' \
2109               'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2110             subst = subst.split('\n')
2111             document.body[i : i+1] = subst
2112             addedLines += len(subst) - 1
2113             i += addedLines + 1
2114             continue
2115         if hspace.search(document.body[i]):
2116             subst = document.body[i].replace('\\InsetSpace \\hspace{}', \
2117               '\\begin_inset ERT\nstatus collapsed\n\n' \
2118               '\\begin_layout Standard\n\n\n\\backslash\n' \
2119               'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2120             subst = subst.split('\n')
2121             document.body[i : i+1] = subst
2122             addedLines += len(subst) - 1
2123             i += addedLines + 1
2124             continue
2125         i += 1
2126
2127
2128 def revert_protected_hfill(document):
2129     ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
2130     i = 0
2131     while True:
2132         i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
2133         if i == -1:
2134             return
2135         j = find_end_of_inset(document.body, i)
2136         if j == -1:
2137             document.warning("Malformed LyX document: Could not find end of space inset.")
2138             continue
2139         del document.body[j]
2140         subst = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
2141           '\\begin_inset ERT\nstatus collapsed\n\n' \
2142           '\\begin_layout Standard\n\n\n\\backslash\n' \
2143           'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
2144         subst = subst.split('\n')
2145         document.body[i : i+1] = subst
2146         i += len(subst)
2147
2148
2149 def revert_leftarrowfill(document):
2150     ' Revert \\begin_inset Space \\leftarrowfill{} to ERT '
2151     i = 0
2152     while True:
2153         i = find_token(document.body, '\\begin_inset Space \\leftarrowfill{}', i)
2154         if i == -1:
2155             return
2156         j = find_end_of_inset(document.body, i)
2157         if j == -1:
2158             document.warning("Malformed LyX document: Could not find end of space inset.")
2159             continue
2160         del document.body[j]
2161         subst = document.body[i].replace('\\begin_inset Space \\leftarrowfill{}', \
2162           '\\begin_inset ERT\nstatus collapsed\n\n' \
2163           '\\begin_layout Standard\n\n\n\\backslash\n' \
2164           'leftarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2165         subst = subst.split('\n')
2166         document.body[i : i+1] = subst
2167         i += len(subst)
2168
2169
2170 def revert_rightarrowfill(document):
2171     ' Revert \\begin_inset Space \\rightarrowfill{} to ERT '
2172     i = 0
2173     while True:
2174         i = find_token(document.body, '\\begin_inset Space \\rightarrowfill{}', i)
2175         if i == -1:
2176             return
2177         j = find_end_of_inset(document.body, i)
2178         if j == -1:
2179             document.warning("Malformed LyX document: Could not find end of space inset.")
2180             continue
2181         del document.body[j]
2182         subst = document.body[i].replace('\\begin_inset Space \\rightarrowfill{}', \
2183           '\\begin_inset ERT\nstatus collapsed\n\n' \
2184           '\\begin_layout Standard\n\n\n\\backslash\n' \
2185           'rightarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2186         subst = subst.split('\n')
2187         document.body[i : i+1] = subst
2188         i += len(subst)
2189
2190
2191 def revert_upbracefill(document):
2192     ' Revert \\begin_inset Space \\upbracefill{} to ERT '
2193     i = 0
2194     while True:
2195         i = find_token(document.body, '\\begin_inset Space \\upbracefill{}', i)
2196         if i == -1:
2197             return
2198         j = find_end_of_inset(document.body, i)
2199         if j == -1:
2200             document.warning("Malformed LyX document: Could not find end of space inset.")
2201             continue
2202         del document.body[j]
2203         subst = document.body[i].replace('\\begin_inset Space \\upbracefill{}', \
2204           '\\begin_inset ERT\nstatus collapsed\n\n' \
2205           '\\begin_layout Standard\n\n\n\\backslash\n' \
2206           'upbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2207         subst = subst.split('\n')
2208         document.body[i : i+1] = subst
2209         i += len(subst)
2210
2211
2212 def revert_downbracefill(document):
2213     ' Revert \\begin_inset Space \\downbracefill{} to ERT '
2214     i = 0
2215     while True:
2216         i = find_token(document.body, '\\begin_inset Space \\downbracefill{}', i)
2217         if i == -1:
2218             return
2219         j = find_end_of_inset(document.body, i)
2220         if j == -1:
2221             document.warning("Malformed LyX document: Could not find end of space inset.")
2222             continue
2223         del document.body[j]
2224         subst = document.body[i].replace('\\begin_inset Space \\downbracefill{}', \
2225           '\\begin_inset ERT\nstatus collapsed\n\n' \
2226           '\\begin_layout Standard\n\n\n\\backslash\n' \
2227           'downbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2228         subst = subst.split('\n')
2229         document.body[i : i+1] = subst
2230         i += len(subst)
2231
2232
2233 def revert_local_layout(document):
2234     ' Revert local layout headers.'
2235     i = 0
2236     while True:
2237         i = find_token(document.header, "\\begin_local_layout", i)
2238         if i == -1:
2239             return
2240         j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
2241         if j == -1:
2242             # this should not happen
2243             break
2244         document.header[i : j + 1] = []
2245
2246
2247 def convert_pagebreaks(document):
2248     ' Convert inline Newpage insets to new format '
2249     i = 0
2250     while True:
2251         i = find_token(document.body, '\\newpage', i)
2252         if i == -1:
2253             break
2254         document.body[i:i+1] = ['\\begin_inset Newpage newpage',
2255                                 '\\end_inset']
2256     i = 0
2257     while True:
2258         i = find_token(document.body, '\\pagebreak', i)
2259         if i == -1:
2260             break
2261         document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
2262                                 '\\end_inset']
2263     i = 0
2264     while True:
2265         i = find_token(document.body, '\\clearpage', i)
2266         if i == -1:
2267             break
2268         document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
2269                                 '\\end_inset']
2270     i = 0
2271     while True:
2272         i = find_token(document.body, '\\cleardoublepage', i)
2273         if i == -1:
2274             break
2275         document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
2276                                 '\\end_inset']
2277
2278
2279 def revert_pagebreaks(document):
2280     ' Revert \\begin_inset Newpage to previous inline format '
2281     i = 0
2282     while True:
2283         i = find_token(document.body, '\\begin_inset Newpage', i)
2284         if i == -1:
2285             return
2286         j = find_end_of_inset(document.body, i)
2287         if j == -1:
2288             document.warning("Malformed LyX document: Could not find end of Newpage inset.")
2289             continue
2290         del document.body[j]
2291         document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
2292         document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
2293         document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
2294         document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
2295
2296
2297 def convert_linebreaks(document):
2298     ' Convert inline Newline insets to new format '
2299     i = 0
2300     while True:
2301         i = find_token(document.body, '\\newline', i)
2302         if i == -1:
2303             break
2304         document.body[i:i+1] = ['\\begin_inset Newline newline',
2305                                 '\\end_inset']
2306     i = 0
2307     while True:
2308         i = find_token(document.body, '\\linebreak', i)
2309         if i == -1:
2310             break
2311         document.body[i:i+1] = ['\\begin_inset Newline linebreak',
2312                                 '\\end_inset']
2313
2314
2315 def revert_linebreaks(document):
2316     ' Revert \\begin_inset Newline to previous inline format '
2317     i = 0
2318     while True:
2319         i = find_token(document.body, '\\begin_inset Newline', i)
2320         if i == -1:
2321             return
2322         j = find_end_of_inset(document.body, i)
2323         if j == -1:
2324             document.warning("Malformed LyX document: Could not find end of Newline inset.")
2325             continue
2326         del document.body[j]
2327         document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
2328         document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
2329
2330
2331 def convert_japanese_plain(document):
2332     ' Set language japanese-plain to japanese '
2333     i = 0
2334     if document.language == "japanese-plain":
2335         document.language = "japanese"
2336         i = find_token(document.header, "\\language", 0)
2337         if i != -1:
2338             document.header[i] = "\\language japanese"
2339     j = 0
2340     while True:
2341         j = find_token(document.body, "\\lang japanese-plain", j)
2342         if j == -1:
2343             return
2344         document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
2345         j = j + 1
2346
2347
2348 def revert_pdfpages(document):
2349     ' Revert pdfpages external inset to ERT '
2350     i = 0
2351     while 1:
2352         i = find_token(document.body, "\\begin_inset External", i)
2353         if i == -1:
2354             return
2355         j = find_end_of_inset(document.body, i)
2356         if j == -1:
2357             document.warning("Malformed lyx document: Missing '\\end_inset' in revert_pdfpages.")
2358             i = i + 1
2359             continue
2360         if get_value(document.body, 'template', i, j) == "PDFPages":
2361             filename = get_value(document.body, 'filename', i, j)
2362             extra = ''
2363             r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
2364             for k in range(i, j):
2365                 m = r.match(document.body[k])
2366                 if m:
2367                     extra = m.group(1)
2368             angle = get_value(document.body, 'rotateAngle', i, j)
2369             width = get_value(document.body, 'width', i, j)
2370             height = get_value(document.body, 'height', i, j)
2371             scale = get_value(document.body, 'scale', i, j)
2372             keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
2373             options = extra
2374             if angle != '':
2375                  if options != '':
2376                      options += ",angle=" + angle
2377                  else:
2378                      options += "angle=" + angle
2379             if width != '':
2380                  if options != '':
2381                      options += ",width=" + convert_len(width)
2382                  else:
2383                      options += "width=" + convert_len(width)
2384             if height != '':
2385                  if options != '':
2386                      options += ",height=" + convert_len(height)
2387                  else:
2388                      options += "height=" + convert_len(height)
2389             if scale != '':
2390                  if options != '':
2391                      options += ",scale=" + scale
2392                  else:
2393                      options += "scale=" + scale
2394             if keepAspectRatio != '':
2395                  if options != '':
2396                      options += ",keepaspectratio"
2397                  else:
2398                      options += "keepaspectratio"
2399             if options != '':
2400                      options = '[' + options + ']'
2401             del document.body[i+1:j+1]
2402             document.body[i:i+1] = ['\\begin_inset ERT',
2403                                 'status collapsed',
2404                                 '',
2405                                 '\\begin_layout Standard',
2406                                 '',
2407                                 '\\backslash',
2408                                 'includepdf' + options + '{' + filename + '}',
2409                                 '\\end_layout',
2410                                 '',
2411                                 '\\end_inset']
2412             add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
2413             i = i + 1
2414             continue
2415         i = i + 1
2416
2417
2418 def revert_mexican(document):
2419     ' Set language Spanish(Mexico) to Spanish '
2420     i = 0
2421     if document.language == "spanish-mexico":
2422         document.language = "spanish"
2423         i = find_token(document.header, "\\language", 0)
2424         if i != -1:
2425             document.header[i] = "\\language spanish"
2426     j = 0
2427     while True:
2428         j = find_token(document.body, "\\lang spanish-mexico", j)
2429         if j == -1:
2430             return
2431         document.body[j] = document.body[j].replace("\\lang spanish-mexico", "\\lang spanish")
2432         j = j + 1
2433
2434
2435 def remove_embedding(document):
2436     ' Remove embed tag from all insets '
2437     revert_inset_embedding(document, 'Graphics')
2438     revert_inset_embedding(document, 'External')
2439     revert_inset_embedding(document, 'CommandInset include')
2440     revert_inset_embedding(document, 'CommandInset bibtex')
2441
2442
2443 def revert_master(document):
2444     ' Remove master param '
2445     i = find_token(document.header, "\\master", 0)
2446     if i != -1:
2447         del document.header[i]
2448
2449
2450 def revert_graphics_group(document):
2451     ' Revert group information from graphics insets '
2452     i = 0
2453     while 1:
2454         i = find_token(document.body, "\\begin_inset Graphics", i)
2455         if i == -1:
2456             return
2457         j = find_end_of_inset(document.body, i)
2458         if j == -1:
2459             document.warning("Malformed lyx document: Missing '\\end_inset' in revert_graphics_group.")
2460             i = i + 1
2461             continue
2462         k = find_token(document.body, " groupId", i, j)
2463         if k == -1:
2464             i = i + 1
2465             continue
2466         del document.body[k]
2467         i = i + 1
2468
2469
2470 def update_apa_styles(document):
2471     ' Replace obsolete styles '
2472
2473     if document.textclass != "apa":
2474         return
2475
2476     obsoletedby = { "Acknowledgments": "Acknowledgements",
2477                     "Section*":        "Section",
2478                     "Subsection*":     "Subsection",
2479                     "Subsubsection*":  "Subsubsection",
2480                     "Paragraph*":      "Paragraph",
2481                     "Subparagraph*":   "Subparagraph"}
2482     i = 0
2483     while 1:
2484         i = find_token(document.body, "\\begin_layout", i)
2485         if i == -1:
2486             return
2487
2488         layout = document.body[i][14:]
2489         if layout in obsoletedby:
2490             document.body[i] = "\\begin_layout " + obsoletedby[layout]
2491
2492         i += 1
2493
2494
2495 def convert_paper_sizes(document):
2496     ' exchange size options legalpaper and executivepaper to correct order '
2497     # routine is needed to fix http://bugzilla.lyx.org/show_bug.cgi?id=4868
2498     i = 0
2499     j = 0
2500     i = find_token(document.header, "\\papersize executivepaper", 0)
2501     if i != -1:
2502         document.header[i] = "\\papersize legalpaper"
2503         return
2504     j = find_token(document.header, "\\papersize legalpaper", 0)
2505     if j != -1:
2506         document.header[j] = "\\papersize executivepaper"
2507
2508
2509 def revert_paper_sizes(document):
2510     ' exchange size options legalpaper and executivepaper to correct order '
2511     i = 0
2512     j = 0
2513     i = find_token(document.header, "\\papersize executivepaper", 0)
2514     if i != -1:
2515         document.header[i] = "\\papersize legalpaper"
2516         return
2517     j = find_token(document.header, "\\papersize legalpaper", 0)
2518     if j != -1:
2519         document.header[j] = "\\papersize executivepaper"
2520
2521
2522 def convert_InsetSpace(document):
2523     " Convert '\\begin_inset Space foo' to '\\begin_inset space foo'"
2524     i = 0
2525     while True:
2526         i = find_token(document.body, "\\begin_inset Space", i)
2527         if i == -1:
2528             return
2529         document.body[i] = document.body[i].replace('\\begin_inset Space', '\\begin_inset space')
2530
2531
2532 def revert_InsetSpace(document):
2533     " Revert '\\begin_inset space foo' to '\\begin_inset Space foo'"
2534     i = 0
2535     while True:
2536         i = find_token(document.body, "\\begin_inset space", i)
2537         if i == -1:
2538             return
2539         document.body[i] = document.body[i].replace('\\begin_inset space', '\\begin_inset Space')
2540
2541
2542 def convert_display_enum(document):
2543     " Convert 'display foo' to 'display false/true'"
2544     i = 0
2545     while True:
2546         i = find_token(document.body, "\tdisplay", i)
2547         if i == -1:
2548             return
2549         val = get_value(document.body, 'display', i)
2550         if val == "none":
2551             document.body[i] = document.body[i].replace('none', 'false')
2552         if val == "default":
2553             document.body[i] = document.body[i].replace('default', 'true')
2554         if val == "monochrome":
2555             document.body[i] = document.body[i].replace('monochrome', 'true')
2556         if val == "grayscale":
2557             document.body[i] = document.body[i].replace('grayscale', 'true')
2558         if val == "color":
2559             document.body[i] = document.body[i].replace('color', 'true')
2560         if val == "preview":
2561             document.body[i] = document.body[i].replace('preview', 'true')
2562         i += 1
2563
2564
2565 def revert_display_enum(document):
2566     " Revert 'display false/true' to 'display none/color'"
2567     i = 0
2568     while True:
2569         i = find_token(document.body, "\tdisplay", i)
2570         if i == -1:
2571             return
2572         val = get_value(document.body, 'display', i)
2573         if val == "false":
2574             document.body[i] = document.body[i].replace('false', 'none')
2575         if val == "true":
2576             document.body[i] = document.body[i].replace('true', 'default')
2577         i += 1
2578
2579
2580 def remove_fontsCJK(document):
2581     ' Remove font_cjk param '
2582     i = find_token(document.header, "\\font_cjk", 0)
2583     if i != -1:
2584         del document.header[i]
2585
2586
2587 def convert_plain_layout(document):
2588     " Convert 'PlainLayout' to 'Plain Layout'" 
2589     i = 0
2590     while True:
2591         i = find_token(document.body, '\\begin_layout PlainLayout', i)
2592         if i == -1:
2593             return
2594         document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2595           '\\begin_layout Plain Layout')
2596         i += 1
2597
2598
2599 def revert_plain_layout(document):
2600     " Convert 'PlainLayout' to 'Plain Layout'" 
2601     i = 0
2602     while True:
2603         i = find_token(document.body, '\\begin_layout Plain Layout', i)
2604         if i == -1:
2605             return
2606         document.body[i] = document.body[i].replace('\\begin_layout Plain Layout', \
2607           '\\begin_layout PlainLayout')
2608         i += 1
2609
2610
2611 def revert_plainlayout(document):
2612     " Convert 'PlainLayout' to 'Plain Layout'" 
2613     i = 0
2614     while True:
2615         i = find_token(document.body, '\\begin_layout PlainLayout', i)
2616         if i == -1:
2617             return
2618         # This will be incorrect for some document classes, since Standard is not always
2619         # the default. But (a) it is probably the best we can do and (b) it will actually
2620         # work, in fact, since an unknown layout will be converted to default.
2621         document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2622           '\\begin_layout Standard')
2623         i += 1
2624
2625
2626 def revert_polytonicgreek(document):
2627     "Set language polytonic Greek to Greek"
2628     i = 0
2629     if document.language == "polutonikogreek":
2630         document.language = "greek"
2631         i = find_token(document.header, "\\language", 0)
2632         if i != -1:
2633             document.header[i] = "\\language greek"
2634     j = 0
2635     while True:
2636         j = find_token(document.body, "\\lang polutonikogreek", j)
2637         if j == -1:
2638             return
2639         document.body[j] = document.body[j].replace("\\lang polutonikogreek", "\\lang greek")
2640         j = j + 1
2641
2642
2643 ##
2644 # Conversion hub
2645 #
2646
2647 supported_versions = ["1.6.0","1.6"]
2648 convert = [[277, [fix_wrong_tables]],
2649            [278, [close_begin_deeper]],
2650            [279, [long_charstyle_names]],
2651            [280, [axe_show_label]],
2652            [281, []],
2653            [282, []],
2654            [283, [convert_flex]],
2655            [284, []],
2656            [285, []],
2657            [286, []],
2658            [287, [convert_wrapfig_options]],
2659            [288, [convert_inset_command]],
2660            [289, [convert_latexcommand_index]],
2661            [290, []],
2662            [291, []],
2663            [292, []],
2664            [293, []],
2665            [294, [convert_pdf_options]],
2666            [295, [convert_htmlurl, convert_url]],
2667            [296, [convert_include]],
2668            [297, [convert_usorbian]],
2669            [298, []],
2670            [299, []],
2671            [300, []],
2672            [301, []],
2673            [302, []],
2674            [303, [convert_serbocroatian]],
2675            [304, [convert_framed_notes]],
2676            [305, []],
2677            [306, []],
2678            [307, []],
2679            [308, []],
2680            [309, []],
2681            [310, []],
2682            [311, [convert_ams_classes]],
2683            [312, []],
2684            [313, [convert_module_names]],
2685            [314, []],
2686            [315, []],
2687            [316, [convert_subfig]],
2688            [317, []],
2689            [318, []],
2690            [319, [convert_spaceinset, convert_hfill]],
2691            [320, []],
2692            [321, [convert_tablines]],
2693            [322, [convert_plain_layout]],
2694            [323, [convert_pagebreaks]],
2695            [324, [convert_linebreaks]],
2696            [325, [convert_japanese_plain]],
2697            [326, []],
2698            [327, []],
2699            [328, [remove_embedding, remove_extra_embedded_files, remove_inzip_options]],
2700            [329, []],
2701            [330, []],
2702            [331, [convert_ltcaption]],
2703            [332, []],
2704            [333, [update_apa_styles]],
2705            [334, [convert_paper_sizes]],
2706            [335, [convert_InsetSpace]],
2707            [336, []],
2708            [337, [convert_display_enum]],
2709            [338, []],
2710           ]
2711
2712 revert =  [[337, [revert_polytonicgreek]],
2713            [336, [revert_display_enum]],
2714            [335, [remove_fontsCJK]],
2715            [334, [revert_InsetSpace]],
2716            [333, [revert_paper_sizes]],
2717            [332, []],
2718            [331, [revert_graphics_group]],
2719            [330, [revert_ltcaption]],
2720            [329, [revert_leftarrowfill, revert_rightarrowfill, revert_upbracefill, revert_downbracefill]],
2721            [328, [revert_master]],
2722            [327, []],
2723            [326, [revert_mexican]],
2724            [325, [revert_pdfpages]],
2725            [324, []],
2726            [323, [revert_linebreaks]],
2727            [322, [revert_pagebreaks]],
2728            [321, [revert_local_layout, revert_plain_layout]],
2729            [320, [revert_tablines]],
2730            [319, [revert_protected_hfill]],
2731            [318, [revert_spaceinset, revert_hfills, revert_hspace]],
2732            [317, [remove_extra_embedded_files]],
2733            [316, [revert_wrapplacement]],
2734            [315, [revert_subfig]],
2735            [314, [revert_colsep, revert_plainlayout]],
2736            [313, []],
2737            [312, [revert_module_names]],
2738            [311, [revert_rotfloat, revert_widesideways]],
2739            [310, [revert_external_embedding]],
2740            [309, [revert_btprintall]],
2741            [308, [revert_nocite]],
2742            [307, [revert_serbianlatin]],
2743            [306, [revert_slash, revert_nobreakdash]],
2744            [305, [revert_interlingua]],
2745            [304, [revert_bahasam]],
2746            [303, [revert_framed_notes]],
2747            [302, []],
2748            [301, [revert_latin, revert_samin]],
2749            [300, [revert_linebreak]],
2750            [299, [revert_pagebreak]],
2751            [298, [revert_hyperlinktype]],
2752            [297, [revert_macro_optional_params]],
2753            [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
2754            [295, [revert_include]],
2755            [294, [revert_href, revert_url]],
2756            [293, [revert_pdf_options_2]],
2757            [292, [revert_inset_info]],
2758            [291, [revert_japanese, revert_japanese_encoding]],
2759            [290, [revert_vietnamese]],
2760            [289, [revert_wraptable]],
2761            [288, [revert_latexcommand_index]],
2762            [287, [revert_inset_command]],
2763            [286, [revert_wrapfig_options]],
2764            [285, [revert_pdf_options]],
2765            [284, [remove_inzip_options]],
2766            [283, []],
2767            [282, [revert_flex]],
2768            [281, []],
2769            [280, [revert_begin_modules]],
2770            [279, [revert_show_label]],
2771            [278, [revert_long_charstyle_names]],
2772            [277, []],
2773            [276, []]
2774           ]
2775
2776
2777 if __name__ == "__main__":
2778     pass