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