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