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