]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/lyx_1_6.py
support for Serbian with Latin letters
[lyx.git] / lib / lyx2lyx / lyx_1_6.py
1 # This file is part of lyx2lyx
2 # -*- coding: utf-8 -*-
3 # Copyright (C) 2007 José Matos <jamatos@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
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
40 ####################################################################
41
42 def fix_wrong_tables(document):
43     i = 0
44     while True:
45         i = find_token(document.body, "\\begin_inset Tabular", i)
46         if i == -1:
47             return
48         j = find_end_of_inset(document.body, i + 1)
49         if j == -1:
50             document.warning("Malformed LyX document: Could not find end of tabular.")
51             continue
52
53         m = i + 1
54         nrows = int(document.body[i+1].split('"')[3])
55         ncols = int(document.body[i+1].split('"')[5])
56
57         for l in range(nrows):
58             prev_multicolumn = 0
59             for k in range(ncols):
60                 m = find_token(document.body, '<cell', m)
61
62                 if document.body[m].find('multicolumn') != -1:
63                     multicol_cont = int(document.body[m].split('"')[1])
64
65                     if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
66                         document.body[m] = document.body[m][:5] + document.body[m][21:]
67                         prev_multicolumn = 0
68                     else:
69                         prev_multicolumn = multicol_cont
70                 else:
71                     prev_multicolumn = 0
72
73         i = j + 1
74
75
76 def close_begin_deeper(document):
77     i = 0
78     depth = 0
79     while True:
80         i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
81
82         if i == -1:
83             break
84
85         if document.body[i][:13] == "\\begin_deeper":
86             depth += 1
87         else:
88             depth -= 1
89
90         i += 1
91
92     document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
93
94
95 def long_charstyle_names(document):
96     i = 0
97     while True:
98         i = find_token(document.body, "\\begin_inset CharStyle", i)
99         if i == -1:
100             return
101         document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
102         i += 1
103
104 def revert_long_charstyle_names(document):
105     i = 0
106     while True:
107         i = find_token(document.body, "\\begin_inset CharStyle", i)
108         if i == -1:
109             return
110         document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle")
111         i += 1
112
113
114 def axe_show_label(document):
115     i = 0
116     while True:
117         i = find_token(document.body, "\\begin_inset CharStyle", i)
118         if i == -1:
119             return
120         if document.body[i + 1].find("show_label") != -1:
121             if document.body[i + 1].find("true") != -1:
122                 document.body[i + 1] = "status open"
123                 del document.body[ i + 2]
124             else:
125                 if document.body[i + 1].find("false") != -1:
126                     document.body[i + 1] = "status collapsed"
127                     del document.body[ i + 2]
128                 else:
129                     document.warning("Malformed LyX document: show_label neither false nor true.")
130         else:
131             document.warning("Malformed LyX document: show_label missing in CharStyle.")
132             
133         i += 1
134
135
136 def revert_show_label(document):
137     i = 0
138     while True:
139         i = find_token(document.body, "\\begin_inset CharStyle", i)
140         if i == -1:
141             return
142         if document.body[i + 1].find("status open") != -1:
143             document.body.insert(i + 1, "show_label true")
144         else:
145             if document.body[i + 1].find("status collapsed") != -1:
146                 document.body.insert(i + 1, "show_label false")
147             else:
148                 document.warning("Malformed LyX document: no legal status line in CharStyle.")
149         i += 1
150
151 def revert_begin_modules(document):
152     i = 0
153     while True:
154         i = find_token(document.header, "\\begin_modules", i)
155         if i == -1:
156             return
157         j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
158         if j == -1:
159             # this should not happen
160             break
161         document.header[i : j + 1] = []
162
163 def convert_flex(document):
164     "Convert CharStyle to Flex"
165     i = 0
166     while True:
167         i = find_token(document.body, "\\begin_inset CharStyle", i)
168         if i == -1:
169             return
170         document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
171
172 def revert_flex(document):
173     "Convert Flex to CharStyle"
174     i = 0
175     while True:
176         i = find_token(document.body, "\\begin_inset Flex", i)
177         if i == -1:
178             return
179         document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
180
181
182 #  Discard PDF options for hyperref
183 def revert_pdf_options(document):
184         "Revert PDF options for hyperref."
185         i = 0
186         i = find_token(document.header, "\\use_hyperref", i)
187         if i != -1:
188             del document.header[i]
189         i = find_token(document.header, "\\pdf_store_options", i)
190         if i != -1:
191             del document.header[i]
192         i = find_token(document.header, "\\pdf_title", 0)
193         if i != -1:
194             del document.header[i]
195         i = find_token(document.header, "\\pdf_author", 0)
196         if i != -1:
197             del document.header[i]
198         i = find_token(document.header, "\\pdf_subject", 0)
199         if i != -1:
200             del document.header[i]
201         i = find_token(document.header, "\\pdf_keywords", 0)
202         if i != -1:
203             del document.header[i]
204         i = find_token(document.header, "\\pdf_bookmarks", 0)
205         if i != -1:
206             del document.header[i]
207         i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
208         if i != -1:
209             del document.header[i]
210         i = find_token(document.header, "\\pdf_bookmarksopen", i)
211         if i != -1:
212             del document.header[i]
213         i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
214         if i != -1:
215             del document.header[i]
216         i = find_token(document.header, "\\pdf_breaklinks", i)
217         if i != -1:
218             del document.header[i]
219         i = find_token(document.header, "\\pdf_pdfborder", i)
220         if i != -1:
221             del document.header[i]
222         i = find_token(document.header, "\\pdf_colorlinks", i)
223         if i != -1:
224             del document.header[i]
225         i = find_token(document.header, "\\pdf_backref", i)
226         if i != -1:
227             del document.header[i]
228         i = find_token(document.header, "\\pdf_pagebackref", i)
229         if i != -1:
230             del document.header[i]
231         i = find_token(document.header, "\\pdf_pagemode", 0)
232         if i != -1:
233             del document.header[i]
234         i = find_token(document.header, "\\pdf_quoted_options", 0)
235         if i != -1:
236             del document.header[i]
237
238
239 def remove_inzip_options(document):
240     "Remove inzipName and embed options from the Graphics inset"
241     i = 0
242     while 1:
243         i = find_token(document.body, "\\begin_inset Graphics", i)
244         if i == -1:
245             return
246         j = find_end_of_inset(document.body, i + 1)
247         if j == -1:
248             # should not happen
249             document.warning("Malformed LyX document: Could not find end of graphics inset.")
250         # If there's a inzip param, just remove that
251         k = find_token(document.body, "\tinzipName", i + 1, j)
252         if k != -1:
253             del document.body[k]
254             # embed option must follow the inzipName option
255             del document.body[k+1]
256         i = i + 1
257
258
259 def convert_inset_command(document):
260     """
261         Convert:
262             \begin_inset LatexCommand cmd 
263         to 
264             \begin_inset CommandInset InsetType
265             LatexCommand cmd
266     """
267     i = 0
268     while 1:
269         i = find_token(document.body, "\\begin_inset LatexCommand", i)
270         if i == -1:
271             return
272         line = document.body[i]
273         r = re.compile(r'\\begin_inset LatexCommand (.*)$')
274         m = r.match(line)
275         cmdName = m.group(1)
276         insetName = ""
277         #this is adapted from factory.cpp
278         if cmdName[0:4].lower() == "cite":
279             insetName = "citation"
280         elif cmdName == "url" or cmdName == "htmlurl":
281             insetName = "url"
282         elif cmdName[-3:] == "ref":
283             insetName = "ref"
284         elif cmdName == "tableofcontents":
285             insetName = "toc"
286         elif cmdName == "printnomenclature":
287             insetName = "nomencl_print"
288         elif cmdName == "printindex":
289             insetName = "index_print"
290         else:
291             insetName = cmdName
292         insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
293         document.body[i : i+1] = insertion
294
295
296 def revert_inset_command(document):
297     """
298         Convert:
299             \begin_inset CommandInset InsetType
300             LatexCommand cmd
301         to 
302             \begin_inset LatexCommand cmd 
303         Some insets may end up being converted to insets earlier versions of LyX
304         will not be able to recognize. Not sure what to do about that.
305     """
306     i = 0
307     while 1:
308         i = find_token(document.body, "\\begin_inset CommandInset", i)
309         if i == -1:
310             return
311         nextline = document.body[i+1]
312         r = re.compile(r'LatexCommand\s+(.*)$')
313         m = r.match(nextline)
314         if not m:
315             document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
316             continue
317         cmdName = m.group(1)
318         insertion = ["\\begin_inset LatexCommand " + cmdName]
319         document.body[i : i+2] = insertion
320
321
322 def convert_wrapfig_options(document):
323     "Convert optional options for wrap floats (wrapfig)."
324     # adds the tokens "lines", "placement", and "overhang"
325     i = 0
326     while True:
327         i = find_token(document.body, "\\begin_inset Wrap figure", i)
328         if i == -1:
329             return
330         document.body.insert(i + 1, "lines 0")
331         j = find_token(document.body, "placement", i)
332         # placement can be already set or not; if not, set it
333         if j == i+2:
334             document.body.insert(i + 3, "overhang 0col%")
335         else:
336            document.body.insert(i + 2, "placement o")
337            document.body.insert(i + 3, "overhang 0col%")
338         i = i + 1
339
340
341 def revert_wrapfig_options(document):
342     "Revert optional options for wrap floats (wrapfig)."
343     i = 0
344     while True:
345         i = find_token(document.body, "lines", i)
346         if i == -1:
347             return
348         j = find_token(document.body, "overhang", i+1)
349         if j != i + 2 and j != -1:
350             document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float.")
351         if j == -1:
352             return
353         del document.body[i]
354         del document.body[j-1]
355         i = i + 1
356
357
358 def convert_latexcommand_index(document):
359     "Convert from LatexCommand form to collapsable form."
360     i = 0 
361     while True:
362         i = find_token(document.body, "\\begin_inset CommandInset index", i)
363         if i == -1:
364             return
365         if document.body[i + 1] != "LatexCommand index": # Might also be index_print
366             return
367         fullcontent = document.body[i + 2][6:].strip('"')
368         document.body[i:i + 2] = ["\\begin_inset Index",
369           "status collapsed",
370           "\\begin_layout Standard"]
371         # Put here the conversions needed from LaTeX string to LyXText.
372         # Here we do a minimal conversion to prevent crashes and data loss.
373         # Manual patch-up may be needed.
374         # Umlauted characters (most common ones, can be extended):
375         fullcontent = fullcontent.replace(r'\\\"a', u'ä').replace(r'\\\"o', u'ö').replace(r'\\\"u', u'ü')
376         # Generic, \" -> ":
377         fullcontent = wrap_into_ert(fullcontent, r'\"', '"')
378         #fullcontent = fullcontent.replace(r'\"', '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout standard\n"\n\\end_layout\n\\end_inset\n')
379         # Math:
380         r = re.compile('^(.*?)(\$.*?\$)(.*)')
381         g = fullcontent
382         while r.match(g):
383           m = r.match(g)
384           s = m.group(1)
385           f = m.group(2).replace('\\\\', '\\')
386           g = m.group(3)
387           if s:
388             # this is non-math!
389             s = wrap_into_ert(s, r'\\', '\\backslash')
390             s = wrap_into_ert(s, '{', '{')
391             s = wrap_into_ert(s, '}', '}')
392             document.body.insert(i + 3, s)
393             i += 1
394           document.body.insert(i + 3, "\\begin_inset Formula " + f)
395           document.body.insert(i + 4, "\\end_inset")
396           i += 2
397         # Generic, \\ -> \backslash:
398         g = wrap_into_ert(g, r'\\', '\\backslash{}')
399         g = wrap_into_ert(g, '{', '{')
400         g = wrap_into_ert(g, '}', '}')
401         document.body.insert(i + 3, g)
402         document.body[i + 4] = "\\end_layout"
403         i = i + 5
404
405
406 def revert_latexcommand_index(document):
407     "Revert from collapsable form to LatexCommand form."
408     i = 0
409     while True:
410         i = find_token(document.body, "\\begin_inset Index", i)
411         if i == -1:
412           return
413         j = find_end_of_inset(document.body, i + 1)
414         if j == -1:
415           return
416         del document.body[j - 1]
417         del document.body[j - 2] # \end_layout
418         document.body[i] =  "\\begin_inset CommandInset index"
419         document.body[i + 1] =  "LatexCommand index"
420         # clean up multiline stuff
421         content = ""
422         for k in range(i + 3, j - 2):
423           line = document.body[k]
424           if line.startswith("\\begin_inset ERT"):
425             line = line[16:]
426           if line.startswith("\\begin_inset Formula"):
427             line = line[20:]
428           if line.startswith("\\begin_layout Standard"):
429             line = line[22:]
430           if line.startswith("\\end_layout"):
431             line = line[11:]
432           if line.startswith("\\end_inset"):
433             line = line[10:]
434           if line.startswith("status collapsed"):
435             line = line[16:]
436           line = line.replace(u'ä', r'\\\"a').replace(u'ö', r'\\\"o').replace(u'ü', r'\\\"u')
437           content = content + line;
438         document.body[i + 3] = "name " + '"' + content + '"'
439         for k in range(i + 4, j - 2):
440           del document.body[i + 4]
441         document.body.insert(i + 4, "")
442         del document.body[i + 2] # \begin_layout standard
443         i = i + 5
444
445
446 def revert_wraptable(document):
447     "Revert wrap table to wrap figure."
448     i = 0
449     while True:
450         i = find_token(document.body, "\\begin_inset Wrap table", i)
451         if i == -1:
452             return
453         document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
454         i = i + 1
455
456
457 def revert_vietnamese(document):
458     "Set language Vietnamese to English"
459     # Set document language from Vietnamese to English
460     i = 0
461     if document.language == "vietnamese":
462         document.language = "english"
463         i = find_token(document.header, "\\language", 0)
464         if i != -1:
465             document.header[i] = "\\language english"
466     j = 0
467     while True:
468         j = find_token(document.body, "\\lang vietnamese", j)
469         if j == -1:
470             return
471         document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
472         j = j + 1
473
474
475 def revert_japanese(document):
476     "Set language japanese-plain to japanese"
477     # Set document language from japanese-plain to japanese
478     i = 0
479     if document.language == "japanese-plain":
480         document.language = "japanese"
481         i = find_token(document.header, "\\language", 0)
482         if i != -1:
483             document.header[i] = "\\language japanese"
484     j = 0
485     while True:
486         j = find_token(document.body, "\\lang japanese-plain", j)
487         if j == -1:
488             return
489         document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
490         j = j + 1
491
492
493 def revert_japanese_encoding(document):
494     "Set input encoding form EUC-JP-plain to EUC-JP etc."
495     # Set input encoding form EUC-JP-plain to EUC-JP etc.
496     i = 0
497     i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
498     if i != -1:
499         document.header[i] = "\\inputencoding EUC-JP"
500     j = 0
501     j = find_token(document.header, "\\inputencoding JIS-plain", 0)
502     if j != -1:
503         document.header[j] = "\\inputencoding JIS"
504     k = 0
505     k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
506     if k != -1: # convert to UTF8 since there is currently no SJIS encoding 
507         document.header[k] = "\\inputencoding UTF8"
508
509
510 def revert_inset_info(document):
511     'Replace info inset with its content'
512     i = 0
513     while 1:
514         i = find_token(document.body, '\\begin_inset Info', i)
515         if i == -1:
516             return
517         j = find_end_of_inset(document.body, i + 1)
518         if j == -1:
519             # should not happen
520             document.warning("Malformed LyX document: Could not find end of Info inset.")
521         type = 'unknown'
522         arg = ''
523         for k in range(i, j+1):
524             if document.body[k].startswith("arg"):
525                 arg = document.body[k][3:].strip().strip('"')
526             if document.body[k].startswith("type"):
527                 type = document.body[k][4:].strip().strip('"')
528         # I think there is a newline after \\end_inset, which should be removed.
529         if document.body[j + 1].strip() == "":
530             document.body[i : (j + 2)] = [type + ':' + arg]
531         else:
532             document.body[i : (j + 1)] = [type + ':' + arg]
533
534
535 def convert_pdf_options(document):
536     # Set the pdfusetitle tag, delete the pdf_store_options,
537     # set quotes for bookmarksopenlevel"
538     has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
539     if has_hr == "1":
540         k = find_token(document.header, "\\use_hyperref", 0)
541         document.header.insert(k + 1, "\\pdf_pdfusetitle true")
542     k = find_token(document.header, "\\pdf_store_options", 0)
543     if k != -1:
544         del document.header[k]
545     i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
546     if i == -1: return
547     document.header[i] = document.header[i].replace('"', '')
548
549
550 def revert_pdf_options_2(document):
551     # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
552     k = find_token(document.header, "\\use_hyperref", 0)
553     i = find_token(document.header, "\\pdf_pdfusetitle", k)
554     if i != -1:
555         del document.header[i]
556     i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
557     if i == -1: return
558     values = document.header[i].split()
559     values[1] = ' "' + values[1] + '"'
560     document.header[i] = ''.join(values)
561
562
563 def convert_htmlurl(document):
564     'Convert "htmlurl" to "href" insets for docbook'
565     if document.backend != "docbook":
566       return
567     i = 0
568     while True:
569       i = find_token(document.body, "\\begin_inset CommandInset url", i)
570       if i == -1:
571         return
572       document.body[i] = "\\begin_inset CommandInset href"
573       document.body[i + 1] = "LatexCommand href"
574       i = i + 1
575
576
577 def convert_url(document):
578     'Convert url insets to url charstyles'
579     if document.backend == "docbook":
580       return
581     i = 0
582     while True:
583       i = find_token(document.body, "\\begin_inset CommandInset url", i)
584       if i == -1:
585         break
586       n = find_token(document.body, "name", i)
587       if n == i + 2:
588         # place the URL name in typewriter before the new URL insert
589         # grab the name 'bla' from the e.g. the line 'name "bla"',
590         # therefore start with the 6th character
591         name = document.body[n][6:-1]
592         newname = [name + " "]
593         document.body[i:i] = newname
594         i = i + 1
595       j = find_token(document.body, "target", i)
596       if j == -1:
597         document.warning("Malformed LyX document: Can't find target for url inset")
598         i = j
599         continue
600       target = document.body[j][8:-1]
601       k = find_token(document.body, "\\end_inset", j)
602       if k == -1:
603         document.warning("Malformed LyX document: Can't find end of url inset")
604         i = k
605         continue
606       newstuff = ["\\begin_inset Flex URL",
607         "status collapsed", "", 
608         "\\begin_layout Standard",
609         "",
610         target,
611         "\\end_layout",
612         ""]
613       document.body[i:k] = newstuff
614       i = k
615
616
617 def revert_href(document):
618     'Reverts hyperlink insets (href) to url insets (url)'
619     i = 0
620     while True:
621       i = find_token(document.body, "\\begin_inset CommandInset href", i)
622       if i == -1:
623           return
624       document.body[i : i + 2] = \
625         ["\\begin_inset CommandInset url", "LatexCommand url"]
626       i = i + 2
627
628
629 def convert_include(document):
630   'Converts include insets to new format.'
631   i = 0
632   r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
633   while True:
634     i = find_token(document.body, "\\begin_inset Include", i)
635     if i == -1:
636       return
637     line = document.body[i]
638     previewline = document.body[i + 1]
639     m = r.match(line)
640     if m == None:
641       document.warning("Unable to match line " + str(i) + " of body!")
642       i += 1
643       continue
644     cmd = m.group(1)
645     fn  = m.group(2)
646     opt = m.group(3)
647     insertion = ["\\begin_inset CommandInset include", 
648        "LatexCommand " + cmd, previewline,
649        "filename \"" + fn + "\""]
650     newlines = 2
651     if opt:
652       insertion.append("lstparams " + '"' + opt + '"')
653       newlines += 1
654     document.body[i : i + 2] = insertion
655     i += newlines
656
657
658 def revert_include(document):
659   'Reverts include insets to old format.'
660   i = 0
661   r1 = re.compile('LatexCommand (.+)')
662   r2 = re.compile('filename (.+)')
663   r3 = re.compile('options (.*)')
664   while True:
665     i = find_token(document.body, "\\begin_inset CommandInset include", i)
666     if i == -1:
667       return
668     previewline = document.body[i + 1]
669     m = r1.match(document.body[i + 2])
670     if m == None:
671       document.warning("Malformed LyX document: No LatexCommand line for `" +
672         document.body[i] + "' on line " + str(i) + ".")
673       i += 1
674       continue
675     cmd = m.group(1)
676     m = r2.match(document.body[i + 3])
677     if m == None:
678       document.warning("Malformed LyX document: No filename line for `" + \
679         document.body[i] + "' on line " + str(i) + ".")
680       i += 2
681       continue
682     fn = m.group(1)
683     options = ""
684     numlines = 4
685     if (cmd == "lstinputlisting"):
686       m = r3.match(document.body[i + 4])
687       if m != None:
688         options = m.group(1)
689         numlines = 5
690     newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
691     if options:
692       newline += ("[" + options + "]")
693     insertion = [newline, previewline]
694     document.body[i : i + numlines] = insertion
695     i += 2
696
697
698 def revert_albanian(document):
699     "Set language Albanian to English"
700     i = 0
701     if document.language == "albanian":
702         document.language = "english"
703         i = find_token(document.header, "\\language", 0)
704         if i != -1:
705             document.header[i] = "\\language english"
706     j = 0
707     while True:
708         j = find_token(document.body, "\\lang albanian", j)
709         if j == -1:
710             return
711         document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
712         j = j + 1
713
714
715 def revert_lowersorbian(document):
716     "Set language lower Sorbian to English"
717     i = 0
718     if document.language == "lowersorbian":
719         document.language = "english"
720         i = find_token(document.header, "\\language", 0)
721         if i != -1:
722             document.header[i] = "\\language english"
723     j = 0
724     while True:
725         j = find_token(document.body, "\\lang lowersorbian", j)
726         if j == -1:
727             return
728         document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
729         j = j + 1
730
731
732 def revert_uppersorbian(document):
733     "Set language uppersorbian to usorbian as this was used in LyX 1.5"
734     i = 0
735     if document.language == "uppersorbian":
736         document.language = "usorbian"
737         i = find_token(document.header, "\\language", 0)
738         if i != -1:
739             document.header[i] = "\\language usorbian"
740     j = 0
741     while True:
742         j = find_token(document.body, "\\lang uppersorbian", j)
743         if j == -1:
744             return
745         document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
746         j = j + 1
747
748
749 def convert_usorbian(document):
750     "Set language usorbian to uppersorbian"
751     i = 0
752     if document.language == "usorbian":
753         document.language = "uppersorbian"
754         i = find_token(document.header, "\\language", 0)
755         if i != -1:
756             document.header[i] = "\\language uppersorbian"
757     j = 0
758     while True:
759         j = find_token(document.body, "\\lang usorbian", j)
760         if j == -1:
761             return
762         document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
763         j = j + 1
764
765
766 def revert_macro_optional_params(document):
767     "Convert macro definitions with optional parameters into ERTs"
768     # Stub to convert macro definitions with one or more optional parameters
769     # into uninterpreted ERT insets
770
771
772 def revert_hyperlinktype(document):
773     'Reverts hyperlink type'
774     i = 0
775     j = 0
776     while True:
777       i = find_token(document.body, "target", i)
778       if i == -1:
779           return
780       j = find_token(document.body, "type", i)
781       if j == -1:
782           return
783       if j == i + 1:
784           del document.body[j]
785       i = i + 1
786
787
788 def revert_pagebreak(document):
789     'Reverts pagebreak to ERT'
790     i = 0
791     while True:
792       i = find_token(document.body, "\\pagebreak", i)
793       if i == -1:
794           return
795       document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
796       '\\begin_layout Standard\n\n\n\\backslash\n' \
797       'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
798       i = i + 1
799
800
801 def revert_linebreak(document):
802     'Reverts linebreak to ERT'
803     i = 0
804     while True:
805       i = find_token(document.body, "\\linebreak", i)
806       if i == -1:
807           return
808       document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
809       '\\begin_layout Standard\n\n\n\\backslash\n' \
810       'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
811       i = i + 1
812
813
814 def revert_latin(document):
815     "Set language Latin to English"
816     i = 0
817     if document.language == "latin":
818         document.language = "english"
819         i = find_token(document.header, "\\language", 0)
820         if i != -1:
821             document.header[i] = "\\language english"
822     j = 0
823     while True:
824         j = find_token(document.body, "\\lang latin", j)
825         if j == -1:
826             return
827         document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
828         j = j + 1
829
830
831 def revert_samin(document):
832     "Set language North Sami to English"
833     i = 0
834     if document.language == "samin":
835         document.language = "english"
836         i = find_token(document.header, "\\language", 0)
837         if i != -1:
838             document.header[i] = "\\language english"
839     j = 0
840     while True:
841         j = find_token(document.body, "\\lang samin", j)
842         if j == -1:
843             return
844         document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
845         j = j + 1
846
847
848 def convert_serbocroatian(document):
849     "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
850     i = 0
851     if document.language == "serbocroatian":
852         document.language = "croatian"
853         i = find_token(document.header, "\\language", 0)
854         if i != -1:
855             document.header[i] = "\\language croatian"
856     j = 0
857     while True:
858         j = find_token(document.body, "\\lang serbocroatian", j)
859         if j == -1:
860             return
861         document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
862         j = j + 1
863
864
865 def convert_framed_notes(document):
866     "Convert framed notes to boxes. "
867     i = 0
868     while 1:
869         i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
870
871         if i == -1:
872             return
873         document.body[i] = document.body[i].replace("\\begin_inset Note", "\\begin_inset Box")
874         document.body.insert(i + 1, 'position "t"\nhor_pos "c"\nhas_inner_box 0\ninner_pos "t"\n' \
875         'use_parbox 0\nwidth "100col%"\nspecial "none"\nheight "1in"\n' \
876         'height_special "totalheight"')
877         i = i + 1
878
879
880 def revert_framed_notes(document):
881     "Revert framed boxes to notes. "
882     i = 0
883     while 1:
884         i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
885
886         if i == -1:
887             return
888         j = find_end_of_inset(document.body, i + 1)
889         if j == -1:
890             # should not happen
891             document.warning("Malformed LyX document: Could not find end of Box inset.")
892         k = find_token(document.body, "status", i + 1, j)
893         if k == -1:
894             document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
895             return
896         status = document.body[k]
897         l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
898         if l == -1:
899             document.warning("Malformed LyX document: Missing `\\begin_layout Standard' in Box inset.")
900             return
901         m = find_token(document.body, "\\end_layout", i + 1, j)
902         if m == -1:
903             document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
904             return
905         ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
906         pbox = find_token(document.body, "use_parbox 1", i + 1, k)
907         if ibox == -1 and pbox == -1:
908             document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
909             del document.body[i+1:k]
910         else:
911             document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
912             document.body.insert(l + 1, "\\begin_inset Note Shaded\n" + status + "\n\\begin_layout Standard\n")
913             document.body.insert(m + 1, "\\end_layout\n\\end_inset")
914         i = i + 1
915
916
917 def revert_slash(document):
918     'Revert \\SpecialChar \\slash{} to ERT'
919     for i in range(len(document.body)):
920         document.body[i] = document.body[i].replace('\\SpecialChar \\slash{}', \
921         '\\begin_inset ERT\nstatus collapsed\n\n' \
922         '\\begin_layout Standard\n\n\n\\backslash\n' \
923         'slash{}\n\\end_layout\n\n\\end_inset\n\n')
924         
925
926 def revert_nobreakdash(document):
927     'Revert \\SpecialChar \\nobreakdash- to ERT'
928     found = 0
929     for i in range(len(document.body)):
930         line = document.body[i]
931         r = re.compile(r'\\SpecialChar \\nobreakdash-')
932         m = r.match(line)
933         if m:
934             found = 1
935         document.body[i] = document.body[i].replace('\\SpecialChar \\nobreakdash-', \
936         '\\begin_inset ERT\nstatus collapsed\n\n' \
937         '\\begin_layout Standard\n\n\n\\backslash\n' \
938         'nobreakdash-\n\\end_layout\n\n\\end_inset\n\n')
939     if not found:
940         return
941     j = find_token(document.header, "\\use_amsmath", 0)
942     if j == -1:
943         document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
944         return
945     document.header[j] = "\\use_amsmath 2"
946
947
948 def revert_bahasam(document):
949     "Set language Bahasa Malaysia to Bahasa Indonesia"
950     i = 0
951     if document.language == "bahasam":
952         document.language = "bahasa"
953         i = find_token(document.header, "\\language", 0)
954         if i != -1:
955             document.header[i] = "\\language bahasa"
956     j = 0
957     while True:
958         j = find_token(document.body, "\\lang bahasam", j)
959         if j == -1:
960             return
961         document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
962         j = j + 1
963
964
965 def revert_interlingua(document):
966     "Set language Interlingua to English"
967     i = 0
968     if document.language == "interlingua":
969         document.language = "english"
970         i = find_token(document.header, "\\language", 0)
971         if i != -1:
972             document.header[i] = "\\language english"
973     j = 0
974     while True:
975         j = find_token(document.body, "\\lang interlingua", j)
976         if j == -1:
977             return
978         document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
979         j = j + 1
980
981
982 def revert_serbianlatin(document):
983     "Set language Serbian-Latin to Croatian"
984     i = 0
985     if document.language == "serbian-latin":
986         document.language = "croatian"
987         i = find_token(document.header, "\\language", 0)
988         if i != -1:
989             document.header[i] = "\\language croatian"
990     j = 0
991     while True:
992         j = find_token(document.body, "\\lang serbian-latin", j)
993         if j == -1:
994             return
995         document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
996         j = j + 1
997
998
999 ##
1000 # Conversion hub
1001 #
1002
1003 supported_versions = ["1.6.0","1.6"]
1004 convert = [[277, [fix_wrong_tables]],
1005            [278, [close_begin_deeper]],
1006            [279, [long_charstyle_names]],
1007            [280, [axe_show_label]],
1008            [281, []],
1009            [282, []],
1010            [283, [convert_flex]],
1011            [284, []],
1012            [285, []],
1013            [286, []],
1014            [287, [convert_wrapfig_options]],
1015            [288, [convert_inset_command]],
1016            [289, [convert_latexcommand_index]],
1017            [290, []],
1018            [291, []],
1019            [292, []],
1020            [293, []],
1021            [294, [convert_pdf_options]],
1022            [295, [convert_htmlurl, convert_url]],
1023            [296, [convert_include]],
1024            [297, [convert_usorbian]],
1025            [298, []],
1026            [299, []],
1027            [300, []],
1028            [301, []],
1029            [302, []],
1030            [303, [convert_serbocroatian]],
1031            [304, [convert_framed_notes]],
1032            [305, []],
1033            [306, []],
1034            [307, []],
1035            [308, []]
1036           ]
1037
1038 revert =  [[307, [revert_serbianlatin]],
1039            [306, [revert_slash, revert_nobreakdash]],
1040            [305, [revert_interlingua]],
1041            [304, [revert_bahasam]],
1042            [303, [revert_framed_notes]],
1043            [302, []],
1044            [301, [revert_latin, revert_samin]],
1045            [300, [revert_linebreak]],
1046            [299, [revert_pagebreak]],
1047            [298, [revert_hyperlinktype]],
1048            [297, [revert_macro_optional_params]],
1049            [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
1050            [295, [revert_include]],
1051            [294, [revert_href]],
1052            [293, [revert_pdf_options_2]],
1053            [292, [revert_inset_info]],
1054            [291, [revert_japanese, revert_japanese_encoding]],
1055            [290, [revert_vietnamese]],
1056            [289, [revert_wraptable]],
1057            [288, [revert_latexcommand_index]],
1058            [287, [revert_inset_command]],
1059            [286, [revert_wrapfig_options]],
1060            [285, [revert_pdf_options]],
1061            [284, [remove_inzip_options]],
1062            [283, []],
1063            [282, [revert_flex]],
1064            [281, []],
1065            [280, [revert_begin_modules]],
1066            [279, [revert_show_label]],
1067            [278, [revert_long_charstyle_names]],
1068            [277, []],
1069            [276, []]
1070           ]
1071
1072
1073 if __name__ == "__main__":
1074     pass