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