1 # This file is part of lyx2lyx
2 # -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2002 Dekel Tsur <dekel@lyx.org>
4 # Copyright (C) 2002-2004 José Matos <jamatos@lyx.org>
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 from os import access, F_OK
23 from parser_tools import find_token, find_end_of_inset, get_next_paragraph, \
24 get_paragraph, get_value, del_token, is_nonempty_line,\
25 find_tokens, find_end_of, find_token2
27 from string import replace, split, find, strip, join
32 def add_end_header(header):
33 header.append("\\end_header");
36 def rm_end_header(lines):
37 i = find_token(lines, "\\end_header", 0)
44 # \SpecialChar ~ -> \InsetSpace ~
46 def convert_spaces(lines):
47 for i in range(len(lines)):
48 lines[i] = replace(lines[i],"\\SpecialChar ~","\\InsetSpace ~")
51 def revert_spaces(lines):
52 for i in range(len(lines)):
53 lines[i] = replace(lines[i],"\\InsetSpace ~", "\\SpecialChar ~")
59 def convert_bibtex(lines):
60 for i in range(len(lines)):
61 lines[i] = replace(lines[i],"\\begin_inset LatexCommand \\BibTeX",
62 "\\begin_inset LatexCommand \\bibtex")
65 def revert_bibtex(lines):
66 for i in range(len(lines)):
67 lines[i] = replace(lines[i], "\\begin_inset LatexCommand \\bibtex",
68 "\\begin_inset LatexCommand \\BibTeX")
74 def remove_insetparent(lines):
77 i = find_token(lines, "\\begin_inset LatexCommand \\lyxparent", i)
86 def convert_external(lines):
87 external_rexp = re.compile(r'\\begin_inset External ([^,]*),"([^"]*)",')
88 external_header = "\\begin_inset External"
91 i = find_token(lines, external_header, i)
94 look = external_rexp.search(lines[i])
97 args[0] = look.group(1)
98 args[1] = look.group(2)
99 #FIXME: if the previous search fails then warn
101 if args[0] == "RasterImage":
102 # Convert a RasterImage External Inset to a Graphics Inset.
103 top = "\\begin_inset Graphics"
105 filename = "\tfilename " + args[1]
106 lines[i:i+1] = [top, filename]
109 # Convert the old External Inset format to the new.
110 top = external_header
111 template = "\ttemplate " + args[0]
113 filename = "\tfilename " + args[1]
114 lines[i:i+1] = [top, template, filename]
117 lines[i:i+1] = [top, template]
121 def revert_external_1(lines):
122 external_header = "\\begin_inset External"
125 i = find_token(lines, external_header, i)
129 template = split(lines[i+1])
133 filename = split(lines[i+1])
137 params = split(lines[i+1])
139 if lines[i+1]: del lines[i+1]
141 lines[i] = lines[i] + " " + template[0]+ ', "' + filename[0] + '", " '+ join(params[1:]) + '"'
145 def revert_external_2(lines):
146 draft_token = '\tdraft'
149 i = find_token(lines, '\\begin_inset External', i)
152 j = find_end_of_inset(lines, i + 1)
154 #this should not happen
156 k = find_token(lines, draft_token, i+1, j-1)
157 if (k != -1 and len(draft_token) == len(lines[k])):
165 def convert_comment(lines):
167 comment = "\\layout Comment"
169 i = find_token(lines, comment, i)
173 lines[i:i+1] = ["\\layout Standard","","",
174 "\\begin_inset Comment",
181 i = find_token(lines, "\\layout", i)
184 lines[i:i] = ["\\end_inset ","",""]
187 j = find_token(lines, '\\begin_deeper', old_i, i)
188 if j == -1: j = i + 1
189 k = find_token(lines, '\\begin_inset', old_i, i)
190 if k == -1: k = i + 1
195 i = find_end_of( lines, i, "\\begin_deeper","\\end_deeper")
197 #This case should not happen
198 #but if this happens deal with it greacefully adding
199 #the missing \end_deeper.
201 lines[i:i] = ["\end_deeper","","","\\end_inset ","",""]
209 i = find_end_of( lines, i, "\\begin_inset","\\end_inset")
211 #This case should not happen
212 #but if this happens deal with it greacefully adding
213 #the missing \end_inset.
215 lines[i:i] = ["\\end_inset ","","","\\end_inset ","",""]
221 if find(lines[i], comment) == -1:
222 lines[i:i] = ["\\end_inset"]
225 lines[i:i+1] = ["\\layout Standard"]
229 def revert_comment(lines):
232 i = find_tokens(lines, ["\\begin_inset Comment", "\\begin_inset Greyedout"], i)
236 lines[i] = "\\begin_inset Note"
243 def add_end_layout(lines):
244 i = find_token(lines, '\\layout', 0)
250 struct_stack = ["\\layout"]
253 i = find_tokens(lines, ["\\begin_inset", "\\end_inset", "\\layout",
254 "\\begin_deeper", "\\end_deeper", "\\the_end"], i)
256 token = split(lines[i])[0]
258 if token == "\\begin_inset":
259 struct_stack.append(token)
263 if token == "\\end_inset":
264 tail = struct_stack.pop()
265 if tail == "\\layout":
267 lines.insert(i,"\\end_layout")
269 #Check if it is the correct tag
274 if token == "\\layout":
275 tail = struct_stack.pop()
278 lines.insert(i,"\\end_layout")
281 struct_stack.append(tail)
283 struct_stack.append(token)
286 if token == "\\begin_deeper":
288 lines.insert(i,"\\end_layout")
290 struct_stack.append(token)
293 if token == "\\end_deeper":
295 lines.insert(i,"\\end_layout")
297 while struct_stack[-1] != "\\begin_deeper":
303 lines.insert(i, "\\end_layout")
307 def rm_end_layout(lines):
310 i = find_token(lines, '\\end_layout', i)
319 # Handle change tracking keywords
321 def insert_tracking_changes(lines):
322 i = find_token(lines, "\\tracking_changes", 0)
324 lines.append("\\tracking_changes 0")
326 def rm_tracking_changes(lines):
327 i = find_token(lines, "\\author", 0)
331 i = find_token(lines, "\\tracking_changes", 0)
337 def rm_body_changes(lines):
340 i = find_token(lines, "\\change_", i)
348 # \layout -> \begin_layout
350 def layout2begin_layout(lines):
353 i = find_token(lines, '\\layout', i)
357 lines[i] = replace(lines[i], '\\layout', '\\begin_layout')
361 def begin_layout2layout(lines):
364 i = find_token(lines, '\\begin_layout', i)
368 lines[i] = replace(lines[i], '\\begin_layout', '\\layout')
373 # valignment="center" -> valignment="middle"
375 def convert_valignment_middle(lines, start, end):
376 for i in range(start, end):
377 if re.search('^<(column|cell) .*valignment="center".*>$', lines[i]):
378 lines[i] = replace(lines[i], 'valignment="center"', 'valignment="middle"')
381 def convert_table_valignment_middle(lines):
384 i = find_token(lines, '\\begin_inset Tabular', i)
387 j = find_end_of_inset(lines, i + 1)
389 #this should not happen
390 convert_valignment_middle(lines, i + 1, len(lines))
392 convert_valignment_middle(lines, i + 1, j)
396 def revert_table_valignment_middle(lines, start, end):
397 for i in range(start, end):
398 if re.search('^<(column|cell) .*valignment="middle".*>$', lines[i]):
399 lines[i] = replace(lines[i], 'valignment="middle"', 'valignment="center"')
402 def revert_valignment_middle(lines):
405 i = find_token(lines, '\\begin_inset Tabular', i)
408 j = find_end_of_inset(lines, i + 1)
410 #this should not happen
411 revert_table_valignment_middle(lines, i + 1, len(lines))
413 revert_table_valignment_middle(lines, i + 1, j)
418 # \the_end -> \end_document
420 def convert_end_document(lines):
421 i = find_token(lines, "\\the_end", 0)
423 lines.append("\\end_document")
425 lines[i] = "\\end_document"
428 def revert_end_document(lines):
429 i = find_token(lines, "\\end_document", 0)
431 lines.append("\\the_end")
433 lines[i] = "\\the_end"
437 # Convert line and page breaks
440 #\line_top \line_bottom \pagebreak_top \pagebreak_bottom \added_space_top xxx \added_space_bottom yyy
444 #\begin layout Standard
449 #\begin_inset VSpace xxx
453 #\begin_layout Standard
457 #\begin_layout Standard
459 #\begin_inset VSpace xxx
466 def convert_breaks(lines):
469 i = find_token(lines, "\\begin_layout", i)
473 line_top = find(lines[i],"\\line_top")
474 line_bot = find(lines[i],"\\line_bottom")
475 pb_top = find(lines[i],"\\pagebreak_top")
476 pb_bot = find(lines[i],"\\pagebreak_bottom")
477 vspace_top = find(lines[i],"\\added_space_top")
478 vspace_bot = find(lines[i],"\\added_space_bottom")
480 if line_top == -1 and line_bot == -1 and pb_bot == -1 and pb_top == -1 and vspace_top == -1 and vspace_bot == -1:
483 for tag in "\\line_top", "\\line_bottom", "\\pagebreak_top", "\\pagebreak_bottom":
484 lines[i] = replace(lines[i], tag, "")
487 # the position could be change because of the removal of other
488 # paragraph properties above
489 vspace_top = find(lines[i],"\\added_space_top")
490 tmp_list = split(lines[i][vspace_top:])
491 vspace_top_value = tmp_list[1]
492 lines[i] = lines[i][:vspace_top] + join(tmp_list[2:])
495 # the position could be change because of the removal of other
496 # paragraph properties above
497 vspace_bot = find(lines[i],"\\added_space_bottom")
498 tmp_list = split(lines[i][vspace_bot:])
499 vspace_bot_value = tmp_list[1]
500 lines[i] = lines[i][:vspace_bot] + join(tmp_list[2:])
502 lines[i] = strip(lines[i])
505 # Create an empty paragraph for line and page break that belong
506 # above the paragraph
507 if pb_top !=-1 or line_top != -1 or vspace_bot != -1:
509 paragraph_above = ['','\\begin_layout Standard','','']
512 paragraph_above.extend(['\\newpage ',''])
515 paragraph_above.extend(['\\begin_inset VSpace ' + vspace_top_value,'\\end_inset ','',''])
518 paragraph_above.extend(['\\lyxline ',''])
520 paragraph_above.extend(['\\end_layout',''])
522 #inset new paragraph above the current paragraph
523 lines[i-2:i-2] = paragraph_above
524 i = i + len(paragraph_above)
526 # Ensure that nested style are converted later.
527 k = find_end_of(lines, i, "\\begin_layout", "\\end_layout")
532 if pb_top !=-1 or line_top != -1 or vspace_bot != -1:
534 paragraph_bellow = ['','\\begin_layout Standard','','']
537 paragraph_bellow.extend(['\\lyxline ',''])
540 paragraph_bellow.extend(['\\begin_inset VSpace ' + vspace_bot_value,'\\end_inset ','',''])
543 paragraph_bellow.extend(['\\newpage ',''])
545 paragraph_bellow.extend(['\\end_layout',''])
547 #inset new paragraph above the current paragraph
548 lines[k + 1: k + 1] = paragraph_bellow
554 def convert_note(lines):
557 i = find_tokens(lines, ["\\begin_inset Note",
558 "\\begin_inset Comment",
559 "\\begin_inset Greyedout"], i)
563 lines[i] = lines[i][0:13] + 'Note ' + lines[i][13:]
567 def revert_note(lines):
568 note_header = "\\begin_inset Note "
571 i = find_token(lines, note_header, i)
575 lines[i] = "\\begin_inset " + lines[i][len(note_header):]
582 def convert_box(lines):
585 i = find_tokens(lines, ["\\begin_inset Boxed",
586 "\\begin_inset Doublebox",
587 "\\begin_inset Frameless",
588 "\\begin_inset ovalbox",
589 "\\begin_inset Ovalbox",
590 "\\begin_inset Shadowbox"], i)
594 lines[i] = lines[i][0:13] + 'Box ' + lines[i][13:]
598 def revert_box(lines):
599 box_header = "\\begin_inset Box "
602 i = find_token(lines, box_header, i)
606 lines[i] = "\\begin_inset " + lines[i][len(box_header):]
613 def convert_collapsable(lines, opt):
616 i = find_tokens(lines, ["\\begin_inset Box",
617 "\\begin_inset Branch",
618 "\\begin_inset CharStyle",
619 "\\begin_inset Float",
620 "\\begin_inset Foot",
621 "\\begin_inset Marginal",
622 "\\begin_inset Note",
623 "\\begin_inset OptArg",
624 "\\begin_inset Wrap"], i)
628 # Seach for a line starting 'collapsed'
629 # If, however, we find a line starting '\begin_layout'
630 # (_always_ present) then break with a warning message
633 if (lines[i] == "collapsed false"):
634 lines[i] = "status open"
636 elif (lines[i] == "collapsed true"):
637 lines[i] = "status collapsed"
639 elif (lines[i][:13] == "\\begin_layout"):
640 opt.warning("Malformed LyX file.")
647 def revert_collapsable(lines, opt):
650 i = find_tokens(lines, ["\\begin_inset Box",
651 "\\begin_inset Branch",
652 "\\begin_inset CharStyle",
653 "\\begin_inset Float",
654 "\\begin_inset Foot",
655 "\\begin_inset Marginal",
656 "\\begin_inset Note",
657 "\\begin_inset OptArg",
658 "\\begin_inset Wrap"], i)
662 # Seach for a line starting 'status'
663 # If, however, we find a line starting '\begin_layout'
664 # (_always_ present) then break with a warning message
667 if (lines[i] == "status open"):
668 lines[i] = "collapsed false"
670 elif (lines[i] == "status collapsed" or
671 lines[i] == "status inlined"):
672 lines[i] = "collapsed true"
674 elif (lines[i][:13] == "\\begin_layout"):
675 opt.warning("Malformed LyX file.")
685 def convert_ert(lines, opt):
688 i = find_token(lines, "\\begin_inset ERT", i)
692 # Seach for a line starting 'status'
693 # If, however, we find a line starting '\begin_layout'
694 # (_always_ present) then break with a warning message
697 if (lines[i] == "status Open"):
698 lines[i] = "status open"
700 elif (lines[i] == "status Collapsed"):
701 lines[i] = "status collapsed"
703 elif (lines[i] == "status Inlined"):
704 lines[i] = "status inlined"
706 elif (lines[i][:13] == "\\begin_layout"):
707 opt.warning("Malformed LyX file.")
714 def revert_ert(lines, opt):
717 i = find_token(lines, "\\begin_inset ERT", i)
721 # Seach for a line starting 'status'
722 # If, however, we find a line starting '\begin_layout'
723 # (_always_ present) then break with a warning message
726 if (lines[i] == "status open"):
727 lines[i] = "status Open"
729 elif (lines[i] == "status collapsed"):
730 lines[i] = "status Collapsed"
732 elif (lines[i] == "status inlined"):
733 lines[i] = "status Inlined"
735 elif (lines[i][:13] == "\\begin_layout"):
736 opt.warning("Malformed LyX file.")
746 def convert_minipage(lines):
747 """ Convert minipages to the box inset.
748 We try to use the same order of arguments as lyx does.
751 inner_pos = ["c","t","b","s"]
755 i = find_token(lines, "\\begin_inset Minipage", i)
759 lines[i] = "\\begin_inset Box Frameless"
762 # convert old to new position using the pos list
763 if lines[i][:8] == "position":
764 lines[i] = 'position "%s"' % pos[int(lines[i][9])]
766 lines.insert(i, 'position "%s"' % pos[0])
769 lines.insert(i, 'hor_pos "c"')
771 lines.insert(i, 'has_inner_box 1')
774 # convert the inner_position
775 if lines[i][:14] == "inner_position":
776 lines[i] = 'inner_pos "%s"' % inner_pos[int(lines[i][15])]
778 lines.insert('inner_pos "%s"' % inner_pos[0])
781 # We need this since the new file format has a height and width
782 # in a different order.
783 if lines[i][:6] == "height":
784 height = lines[i][6:]
785 # test for default value of 221 and convert it accordingly
786 if height == ' "0pt"':
792 if lines[i][:5] == "width":
798 if lines[i][:9] == "collapsed":
799 if lines[i][9:] == "true":
807 lines.insert(i, 'use_parbox 0')
809 lines.insert(i, 'width' + width)
811 lines.insert(i, 'special "none"')
813 lines.insert(i, 'height' + height)
815 lines.insert(i, 'height_special "totalheight"')
817 lines.insert(i, 'status ' + status)
821 # -------------------------------------------------------------------------------------------
822 # Convert backslashes into valid ERT code, append the converted text to
823 # lines[i] and return the (maybe incremented) line index i
824 def convert_ertbackslash(lines, i, ert):
827 lines[i] = lines[i] + '\\backslash '
831 lines[i] = lines[i] + c
835 def convert_vspace(header, lines, opt):
837 # Get default spaceamount
838 i = find_token(header, '\\defskip', 0)
840 defskipamount = 'medskip'
842 defskipamount = split(header[i])[1]
847 i = find_token(lines, '\\begin_inset VSpace', i)
850 spaceamount = split(lines[i])[2]
852 # Are we at the beginning or end of a paragraph?
854 start = get_paragraph(lines, i) + 1
855 for k in range(start, i):
856 if is_nonempty_line(lines[k]):
860 j = find_end_of_inset(lines, i)
862 opt.warning("Malformed LyX file: Missing '\\end_inset'.")
865 end = get_next_paragraph(lines, i)
866 for k in range(j + 1, end):
867 if is_nonempty_line(lines[k]):
871 # Convert to paragraph formatting if we are at the beginning or end
872 # of a paragraph and the resulting paragraph would not be empty
873 if ((paragraph_start and not paragraph_end) or
874 (paragraph_end and not paragraph_start)):
875 # The order is important: del and insert invalidate some indices
879 lines.insert(start, '\\added_space_top ' + spaceamount + ' ')
881 lines.insert(start, '\\added_space_bottom ' + spaceamount + ' ')
885 lines[i:i+1] = ['\\begin_inset ERT', 'status Collapsed', '',
886 '\\layout Standard', '', '\\backslash ']
888 if spaceamount[-1] == '*':
889 spaceamount = spaceamount[:-1]
894 # Replace defskip by the actual value
895 if spaceamount == 'defskip':
896 spaceamount = defskipamount
898 # LaTeX does not know \\smallskip* etc
900 if spaceamount == 'smallskip':
901 spaceamount = '\\smallskipamount'
902 elif spaceamount == 'medskip':
903 spaceamount = '\\medskipamount'
904 elif spaceamount == 'bigskip':
905 spaceamount = '\\bigskipamount'
906 elif spaceamount == 'vfill':
907 spaceamount = '\\fill'
909 # Finally output the LaTeX code
910 if (spaceamount == 'smallskip' or spaceamount == 'medskip' or
911 spaceamount == 'bigskip' or spaceamount == 'vfill'):
912 lines.insert(i, spaceamount)
915 lines.insert(i, 'vspace*{')
917 lines.insert(i, 'vspace{')
918 i = convert_ertbackslash(lines, i, spaceamount)
919 lines[i] = lines[i] + '}'
923 # Convert a LyX length into valid ERT code and append it to lines[i]
924 # Return the (maybe incremented) line index i
925 def convert_ertlen(lines, i, len, special):
926 units = {"text%":"\\textwidth", "col%":"\\columnwidth",
927 "page%":"\\pagewidth", "line%":"\\linewidth",
928 "theight%":"\\textheight", "pheight%":"\\pageheight"}
930 # Convert special lengths
931 if special != 'none':
932 len = '%f\\' % len2value(len) + special
934 # Convert LyX units to LaTeX units
935 for unit in units.keys():
936 if find(len, unit) != -1:
937 len = '%f' % (len2value(len) / 100) + units[unit]
940 # Convert backslashes and insert the converted length into lines
941 return convert_ertbackslash(lines, i, len)
944 # Return the value of len without the unit in numerical form
946 result = re.search('([+-]?[0-9.]+)', len)
948 return float(result.group(1))
949 # No number means 1.0
953 def convert_frameless_box(lines, opt):
954 pos = ['t', 'c', 'b']
955 inner_pos = ['c', 't', 'b', 's']
958 i = find_token(lines, '\\begin_inset Frameless', i)
961 j = find_end_of_inset(lines, i)
963 opt.warning("Malformed LyX file: Missing '\\end_inset'\n")
969 params = {'position':'0', 'hor_pos':'c', 'has_inner_box':'1',
970 'inner_pos':'1', 'use_parbox':'0', 'width':'100col%',
971 'special':'none', 'height':'1in',
972 'height_special':'totalheight', 'collapsed':'false'}
973 for key in params.keys():
974 value = replace(get_value(lines, key, i, j), '"', '')
976 if key == 'position':
977 # convert new to old position: 'position "t"' -> 0
978 value = find_token(pos, value, 0)
981 elif key == 'inner_pos':
982 # convert inner position
983 value = find_token(inner_pos, value, 0)
988 j = del_token(lines, key, i, j)
991 # Convert to minipage or ERT?
992 # Note that the inner_position and height parameters of a minipage
993 # inset are ignored and not accessible for the user, although they
994 # are present in the file format and correctly read in and written.
995 # Therefore we convert to ERT if they do not have their LaTeX
996 # defaults. These are:
997 # - the value of "position" for "inner_pos"
998 # - "\totalheight" for "height"
999 if (params['use_parbox'] != '0' or
1000 params['has_inner_box'] != '1' or
1001 params['special'] != 'none' or
1002 inner_pos[params['inner_pos']] != pos[params['position']] or
1003 params['height_special'] != 'totalheight' or
1004 len2value(params['height']) != 1.0):
1007 if params['collapsed'] == 'true':
1008 params['collapsed'] = 'Collapsed'
1010 params['collapsed'] = 'Open'
1011 lines[i : i] = ['\\begin_inset ERT', 'status ' + params['collapsed'],
1012 '', '\\layout Standard', '', '\\backslash ']
1014 if params['use_parbox'] == '1':
1015 lines.insert(i, 'parbox')
1017 lines.insert(i, 'begin{minipage}')
1018 lines[i] = lines[i] + '[' + pos[params['position']] + ']['
1019 i = convert_ertlen(lines, i, params['height'], params['height_special'])
1020 lines[i] = lines[i] + '][' + inner_pos[params['inner_pos']] + ']{'
1021 i = convert_ertlen(lines, i, params['width'], params['special'])
1022 if params['use_parbox'] == '1':
1023 lines[i] = lines[i] + '}{'
1025 lines[i] = lines[i] + '}'
1027 lines[i:i] = ['', '\\end_inset ']
1029 j = find_end_of_inset(lines, i)
1031 opt.warning("Malformed LyX file: Missing '\\end_inset'.")
1033 lines[j-1:j-1] = ['\\begin_inset ERT', 'status ' + params['collapsed'],
1034 '', '\\layout Standard', '']
1036 if params['use_parbox'] == '1':
1037 lines.insert(j, '}')
1039 lines[j:j] = ['\\backslash ', 'end{minipage}']
1042 # Convert to minipage
1043 lines[i:i] = ['\\begin_inset Minipage',
1044 'position %d' % params['position'],
1045 'inner_position %d' % params['inner_pos'],
1046 'height "' + params['height'] + '"',
1047 'width "' + params['width'] + '"',
1048 'collapsed ' + params['collapsed']]
1055 def convert_jurabib(header, opt):
1056 i = find_token(header, '\\use_numerical_citations', 0)
1058 opt.warning("Malformed lyx file: Missing '\\use_numerical_citations'")
1060 header.insert(i + 1, '\\use_jurabib 0')
1063 def revert_jurabib(header, opt):
1064 i = find_token(header, '\\use_jurabib', 0)
1066 opt.warning("Malformed lyx file: Missing '\\use_jurabib'")
1068 if get_value(header, '\\use_jurabib', 0) != "0":
1069 opt.warning("Conversion of '\\use_jurabib = 1' not yet implemented.")
1070 # Don't remove '\\use_jurabib' so that people will get warnings by lyx
1078 def convert_bibtopic(header, opt):
1079 i = find_token(header, '\\use_jurabib', 0)
1081 opt.warning("Malformed lyx file: Missing '\\use_jurabib'")
1083 header.insert(i + 1, '\\use_bibtopic 0')
1086 def revert_bibtopic(header, opt):
1087 i = find_token(header, '\\use_bibtopic', 0)
1089 opt.warning("Malformed lyx file: Missing '\\use_bibtopic'")
1091 if get_value(header, '\\use_bibtopic', 0) != "0":
1092 opt.warning("Conversion of '\\use_bibtopic = 1' not yet implemented.")
1093 # Don't remove '\\use_jurabib' so that people will get warnings by lyx
1100 def convert_float(lines, opt):
1103 i = find_token(lines, '\\begin_inset Float', i)
1106 # Seach for a line starting 'wide'
1107 # If, however, we find a line starting '\begin_layout'
1108 # (_always_ present) then break with a warning message
1111 if (lines[i][:4] == "wide"):
1112 lines.insert(i + 1, 'sideways false')
1114 elif (lines[i][:13] == "\\begin_layout"):
1115 opt.warning("Malformed lyx file")
1121 def revert_float(lines, opt):
1124 i = find_token(lines, '\\begin_inset Float', i)
1127 j = find_end_of_inset(lines, i)
1129 opt.warning("Malformed lyx file: Missing '\\end_inset'")
1132 if get_value(lines, 'sideways', i, j) != "false":
1133 opt.warning("Conversion of 'sideways true' not yet implemented.")
1134 # Don't remove 'sideways' so that people will get warnings by lyx
1137 del_token(lines, 'sideways', i, j)
1141 def convert_graphics(lines, opt):
1142 """ Add extension to filenames of insetgraphics if necessary.
1146 i = find_token(lines, "\\begin_inset Graphics", i)
1150 j = find_token2(lines, "filename", i)
1154 filename = split(lines[j])[1]
1155 absname = os.path.normpath(os.path.join(opt.dir, filename))
1156 if opt.input == stdin and not os.path.isabs(filename):
1157 # We don't know the directory and cannot check the file.
1158 # We could use a heuristic and take the current directory,
1159 # and we could try to find out if filename has an extension,
1160 # but that would be just guesses and could be wrong.
1161 opt.warning("""Warning: Can not determine whether file
1163 needs an extension when reading from standard input.
1164 You may need to correct the file manually or run
1165 lyx2lyx again with the .lyx file as commandline argument.""" % filename)
1167 # This needs to be the same algorithm as in pre 233 insetgraphics
1168 if access(absname, F_OK):
1170 if access(absname + ".ps", F_OK):
1171 lines[j] = replace(lines[j], filename, filename + ".ps")
1173 if access(absname + ".eps", F_OK):
1174 lines[j] = replace(lines[j], filename, filename + ".eps")
1178 # Convert firstname and surname from styles -> char styles
1180 def convert_names(lines, opt):
1181 """ Convert in the docbook backend from firstname and surname style
1184 if opt.backend != "docbook":
1190 i = find_token(lines, "\\begin_layout Author", i)
1195 while lines[i] == "":
1198 if lines[i][:11] != "\\end_layout" or lines[i+2][:13] != "\\begin_deeper":
1203 i = find_end_of( lines, i+3, "\\begin_deeper","\\end_deeper")
1205 # something is really wrong, abort
1206 opt.warning("Missing \\end_deeper,after style Author")
1207 opt.warning("Aborted attempt to parse FirstName and Surname")
1209 firstname, surname = "", ""
1213 j = find_token(name, "\\begin_layout FirstName", 0)
1216 while(name[j] != "\\end_layout"):
1217 firstname = firstname + name[j]
1220 j = find_token(name, "\\begin_layout Surname", 0)
1223 while(name[j] != "\\end_layout"):
1224 surname = surname + name[j]
1230 lines[k-1:k-1] = ["", "",
1231 "\\begin_inset CharStyle Firstname",
1234 "\\begin_layout Standard",
1242 "\\begin_inset CharStyle Surname",
1245 "\\begin_layout Standard",
1254 def revert_names(lines, opt):
1255 """ Revert in the docbook backend from firstname and surname char style
1258 if opt.backend != "docbook":
1266 def convert(header, body, opt):
1267 if opt.format < 223:
1268 insert_tracking_changes(header)
1269 add_end_header(header)
1270 convert_spaces(body)
1271 convert_bibtex(body)
1272 remove_insetparent(body)
1274 if opt.end == opt.format: return
1276 if opt.format < 224:
1277 convert_external(body)
1278 convert_comment(body)
1280 if opt.end == opt.format: return
1282 if opt.format < 225:
1283 add_end_layout(body)
1284 layout2begin_layout(body)
1285 convert_end_document(body)
1286 convert_table_valignment_middle(body)
1287 convert_breaks(body)
1289 if opt.end == opt.format: return
1291 if opt.format < 226:
1294 if opt.end == opt.format: return
1296 if opt.format < 227:
1299 if opt.end == opt.format: return
1301 if opt.format < 228:
1302 convert_collapsable(body, opt)
1303 convert_ert(body, opt)
1305 if opt.end == opt.format: return
1307 if opt.format < 229:
1308 convert_minipage(body)
1310 if opt.end == opt.format: return
1312 if opt.format < 230:
1313 convert_jurabib(header, opt)
1315 if opt.end == opt.format: return
1317 if opt.format < 231:
1318 convert_float(body, opt)
1320 if opt.end == opt.format: return
1322 if opt.format < 232:
1323 convert_bibtopic(header, opt)
1325 if opt.end == opt.format: return
1327 if opt.format < 233:
1328 convert_graphics(body, opt)
1329 convert_names(body, opt)
1332 def revert(header, body, opt):
1333 if opt.format > 232:
1334 revert_names(body, opt)
1336 if opt.end == opt.format: return
1338 if opt.format > 231:
1339 revert_bibtopic(header, opt)
1341 if opt.end == opt.format: return
1343 if opt.format > 230:
1344 revert_float(body, opt)
1346 if opt.end == opt.format: return
1348 if opt.format > 229:
1349 revert_jurabib(header, opt)
1351 if opt.end == opt.format: return
1353 if opt.format > 228:
1355 if opt.end == opt.format: return
1357 if opt.format > 227:
1358 revert_collapsable(body, opt)
1359 revert_ert(body, opt)
1361 if opt.end == opt.format: return
1363 if opt.format > 226:
1365 revert_external_2(body)
1367 if opt.end == opt.format: return
1369 if opt.format > 225:
1372 if opt.end == opt.format: return
1374 if opt.format > 224:
1376 begin_layout2layout(body)
1377 revert_end_document(body)
1378 revert_valignment_middle(body)
1379 convert_vspace(header, body, opt)
1380 convert_frameless_box(body, opt)
1381 if opt.end == opt.format: return
1383 if opt.format > 223:
1384 revert_external_2(body)
1385 revert_comment(body)
1387 if opt.end == opt.format: return
1389 if opt.format > 221:
1390 rm_end_header(header)
1393 rm_tracking_changes(header)
1394 rm_body_changes(body)
1398 if __name__ == "__main__":