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