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"]
252 i = find_tokens(lines, ["\\begin_inset", "\\end_inset", "\\layout",
253 "\\begin_deeper", "\\end_deeper", "\\the_end"], i)
255 token = split(lines[i])[0]
257 if token == "\\begin_inset":
258 struct_stack.append(token)
262 if token == "\\end_inset":
263 tail = struct_stack.pop()
264 if tail == "\\layout":
265 lines.insert(i,"\\end_layout")
267 #Check if it is the correct tag
272 if token == "\\layout":
273 tail = struct_stack.pop()
275 lines.insert(i,"\\end_layout")
278 struct_stack.append(tail)
280 struct_stack.append(token)
283 if token == "\\begin_deeper" or token == "\\end_deeper":
284 lines.insert(i,"\\end_layout")
289 lines.insert(i, "\\end_layout")
293 def rm_end_layout(lines):
296 i = find_token(lines, '\\end_layout', i)
305 # Remove change tracking keywords
307 def rm_tracking_changes(lines):
308 i = find_token(lines, "\\author", 0)
312 i = find_token(lines, "\\tracking_changes", 0)
318 def rm_body_changes(lines):
321 i = find_token(lines, "\\change_", i)
329 # \layout -> \begin_layout
331 def layout2begin_layout(lines):
334 i = find_token(lines, '\\layout', i)
338 lines[i] = replace(lines[i], '\\layout', '\\begin_layout')
342 def begin_layout2layout(lines):
345 i = find_token(lines, '\\begin_layout', i)
349 lines[i] = replace(lines[i], '\\begin_layout', '\\layout')
354 # valignment="center" -> valignment="middle"
356 def convert_valignment_middle(lines, start, end):
357 for i in range(start, end):
358 if re.search('^<(column|cell) .*valignment="center".*>$', lines[i]):
359 lines[i] = replace(lines[i], 'valignment="center"', 'valignment="middle"')
362 def convert_table_valignment_middle(lines):
365 i = find_token(lines, '\\begin_inset Tabular', i)
368 j = find_end_of_inset(lines, i + 1)
370 #this should not happen
371 convert_valignment_middle(lines, i + 1, len(lines))
373 convert_valignment_middle(lines, i + 1, j)
377 def revert_table_valignment_middle(lines, start, end):
378 for i in range(start, end):
379 if re.search('^<(column|cell) .*valignment="middle".*>$', lines[i]):
380 lines[i] = replace(lines[i], 'valignment="middle"', 'valignment="center"')
383 def revert_valignment_middle(lines):
386 i = find_token(lines, '\\begin_inset Tabular', i)
389 j = find_end_of_inset(lines, i + 1)
391 #this should not happen
392 revert_table_valignment_middle(lines, i + 1, len(lines))
394 revert_table_valignment_middle(lines, i + 1, j)
399 # \the_end -> \end_document
401 def convert_end_document(lines):
402 i = find_token(lines, "\\the_end", 0)
404 lines.append("\\end_document")
406 lines[i] = "\\end_document"
409 def revert_end_document(lines):
410 i = find_token(lines, "\\end_document", 0)
412 lines.append("\\the_end")
414 lines[i] = "\\the_end"
418 # Convert line and page breaks
421 #\line_top \line_bottom \pagebreak_top \pagebreak_bottom \added_space_top xxx \added_space_bottom yyy
425 #\begin layout Standard
430 #\begin_inset VSpace xxx
434 #\begin_layout Standard
438 #\begin_layout Standard
440 #\begin_inset VSpace xxx
447 def convert_breaks(lines):
450 i = find_token(lines, "\\begin_layout", i)
454 line_top = find(lines[i],"\\line_top")
455 line_bot = find(lines[i],"\\line_bottom")
456 pb_top = find(lines[i],"\\pagebreak_top")
457 pb_bot = find(lines[i],"\\pagebreak_bottom")
458 vspace_top = find(lines[i],"\\added_space_top")
459 vspace_bot = find(lines[i],"\\added_space_bottom")
461 if line_top == -1 and line_bot == -1 and pb_bot == -1 and pb_top == -1 and vspace_top == -1 and vspace_bot == -1:
464 for tag in "\\line_top", "\\line_bottom", "\\pagebreak_top", "\\pagebreak_bottom":
465 lines[i] = replace(lines[i], tag, "")
468 # the position could be change because of the removal of other
469 # paragraph properties above
470 vspace_top = find(lines[i],"\\added_space_top")
471 tmp_list = split(lines[i][vspace_top:])
472 vspace_top_value = tmp_list[1]
473 lines[i] = lines[i][:vspace_top] + join(tmp_list[2:])
476 # the position could be change because of the removal of other
477 # paragraph properties above
478 vspace_bot = find(lines[i],"\\added_space_bottom")
479 tmp_list = split(lines[i][vspace_bot:])
480 vspace_bot_value = tmp_list[1]
481 lines[i] = lines[i][:vspace_bot] + join(tmp_list[2:])
483 lines[i] = strip(lines[i])
486 # Create an empty paragraph for line and page break that belong
487 # above the paragraph
488 if pb_top !=-1 or line_top != -1 or vspace_bot != -1:
490 paragraph_above = ['','\\begin_layout Standard','','']
493 paragraph_above.extend(['\\newpage ',''])
496 paragraph_above.extend(['\\begin_inset VSpace ' + vspace_top_value,'\\end_inset ','',''])
499 paragraph_above.extend(['\\lyxline ',''])
501 paragraph_above.extend(['\\end_layout',''])
503 #inset new paragraph above the current paragraph
504 lines[i-2:i-2] = paragraph_above
505 i = i + len(paragraph_above)
507 # Ensure that nested style are converted later.
508 k = find_end_of(lines, i, "\\begin_layout", "\\end_layout")
513 if pb_top !=-1 or line_top != -1 or vspace_bot != -1:
515 paragraph_bellow = ['','\\begin_layout Standard','','']
518 paragraph_bellow.extend(['\\lyxline ',''])
521 paragraph_bellow.extend(['\\begin_inset VSpace ' + vspace_bot_value,'\\end_inset ','',''])
524 paragraph_bellow.extend(['\\newpage ',''])
526 paragraph_bellow.extend(['\\end_layout',''])
528 #inset new paragraph above the current paragraph
529 lines[k + 1: k + 1] = paragraph_bellow
535 def convert_note(lines):
538 i = find_tokens(lines, ["\\begin_inset Note",
539 "\\begin_inset Comment",
540 "\\begin_inset Greyedout"], i)
544 lines[i] = lines[i][0:13] + 'Note ' + lines[i][13:]
548 def revert_note(lines):
549 note_header = "\\begin_inset Note "
552 i = find_token(lines, note_header, i)
556 lines[i] = "\\begin_inset " + lines[i][len(note_header):]
563 def convert_box(lines):
566 i = find_tokens(lines, ["\\begin_inset Boxed",
567 "\\begin_inset Doublebox",
568 "\\begin_inset Frameless",
569 "\\begin_inset ovalbox",
570 "\\begin_inset Ovalbox",
571 "\\begin_inset Shadowbox"], i)
575 lines[i] = lines[i][0:13] + 'Box ' + lines[i][13:]
579 def revert_box(lines):
580 box_header = "\\begin_inset Box "
583 i = find_token(lines, box_header, i)
587 lines[i] = "\\begin_inset " + lines[i][len(box_header):]
594 def convert_collapsable(lines, opt):
597 i = find_tokens(lines, ["\\begin_inset Box",
598 "\\begin_inset Branch",
599 "\\begin_inset CharStyle",
600 "\\begin_inset Float",
601 "\\begin_inset Foot",
602 "\\begin_inset Marginal",
603 "\\begin_inset Note",
604 "\\begin_inset OptArg",
605 "\\begin_inset Wrap"], i)
609 # Seach for a line starting 'collapsed'
610 # If, however, we find a line starting '\begin_layout'
611 # (_always_ present) then break with a warning message
614 if (lines[i] == "collapsed false"):
615 lines[i] = "status open"
617 elif (lines[i] == "collapsed true"):
618 lines[i] = "status collapsed"
620 elif (lines[i][:13] == "\\begin_layout"):
621 opt.warning("Malformed LyX file.")
628 def revert_collapsable(lines, opt):
631 i = find_tokens(lines, ["\\begin_inset Box",
632 "\\begin_inset Branch",
633 "\\begin_inset CharStyle",
634 "\\begin_inset Float",
635 "\\begin_inset Foot",
636 "\\begin_inset Marginal",
637 "\\begin_inset Note",
638 "\\begin_inset OptArg",
639 "\\begin_inset Wrap"], i)
643 # Seach for a line starting 'status'
644 # If, however, we find a line starting '\begin_layout'
645 # (_always_ present) then break with a warning message
648 if (lines[i] == "status open"):
649 lines[i] = "collapsed false"
651 elif (lines[i] == "status collapsed" or
652 lines[i] == "status inlined"):
653 lines[i] = "collapsed true"
655 elif (lines[i][:13] == "\\begin_layout"):
656 opt.warning("Malformed LyX file.")
666 def convert_ert(lines, opt):
669 i = find_token(lines, "\\begin_inset ERT", i)
673 # Seach for a line starting 'status'
674 # If, however, we find a line starting '\begin_layout'
675 # (_always_ present) then break with a warning message
678 if (lines[i] == "status Open"):
679 lines[i] = "status open"
681 elif (lines[i] == "status Collapsed"):
682 lines[i] = "status collapsed"
684 elif (lines[i] == "status Inlined"):
685 lines[i] = "status inlined"
687 elif (lines[i][:13] == "\\begin_layout"):
688 opt.warning("Malformed LyX file.")
695 def revert_ert(lines, opt):
698 i = find_token(lines, "\\begin_inset ERT", i)
702 # Seach for a line starting 'status'
703 # If, however, we find a line starting '\begin_layout'
704 # (_always_ present) then break with a warning message
707 if (lines[i] == "status open"):
708 lines[i] = "status Open"
710 elif (lines[i] == "status collapsed"):
711 lines[i] = "status Collapsed"
713 elif (lines[i] == "status inlined"):
714 lines[i] = "status Inlined"
716 elif (lines[i][:13] == "\\begin_layout"):
717 opt.warning("Malformed LyX file.")
727 def convert_minipage(lines):
728 """ Convert minipages to the box inset.
729 We try to use the same order of arguments as lyx does.
732 inner_pos = ["c","t","b","s"]
736 i = find_token(lines, "\\begin_inset Minipage", i)
740 lines[i] = "\\begin_inset Box Frameless"
743 # convert old to new position using the pos list
744 if lines[i][:8] == "position":
745 lines[i] = 'position "%s"' % pos[int(lines[i][9])]
747 lines.insert(i, 'position "%s"' % pos[0])
750 lines.insert(i, 'hor_pos "c"')
752 lines.insert(i, 'has_inner_box 1')
755 # convert the inner_position
756 if lines[i][:14] == "inner_position":
757 lines[i] = 'inner_pos "%s"' % inner_pos[int(lines[i][15])]
759 lines.insert('inner_pos "%s"' % inner_pos[0])
762 # We need this since the new file format has a height and width
763 # in a different order.
764 if lines[i][:6] == "height":
765 height = lines[i][6:]
766 # test for default value of 221 and convert it accordingly
767 if height == ' "0pt"':
773 if lines[i][:5] == "width":
779 if lines[i][:9] == "collapsed":
780 if lines[i][9:] == "true":
788 lines.insert(i, 'use_parbox 0')
790 lines.insert(i, 'width' + width)
792 lines.insert(i, 'special "none"')
794 lines.insert(i, 'height' + height)
796 lines.insert(i, 'height_special "totalheight"')
798 lines.insert(i, 'status ' + status)
802 # -------------------------------------------------------------------------------------------
803 # Convert backslashes into valid ERT code, append the converted text to
804 # lines[i] and return the (maybe incremented) line index i
805 def convert_ertbackslash(lines, i, ert):
808 lines[i] = lines[i] + '\\backslash '
812 lines[i] = lines[i] + c
816 def convert_vspace(header, lines, opt):
818 # Get default spaceamount
819 i = find_token(header, '\\defskip', 0)
821 defskipamount = 'medskip'
823 defskipamount = split(header[i])[1]
828 i = find_token(lines, '\\begin_inset VSpace', i)
831 spaceamount = split(lines[i])[2]
833 # Are we at the beginning or end of a paragraph?
835 start = get_paragraph(lines, i) + 1
836 for k in range(start, i):
837 if is_nonempty_line(lines[k]):
841 j = find_end_of_inset(lines, i)
843 opt.warning("Malformed LyX file: Missing '\\end_inset'.")
846 end = get_next_paragraph(lines, i)
847 for k in range(j + 1, end):
848 if is_nonempty_line(lines[k]):
852 # Convert to paragraph formatting if we are at the beginning or end
853 # of a paragraph and the resulting paragraph would not be empty
854 if ((paragraph_start and not paragraph_end) or
855 (paragraph_end and not paragraph_start)):
856 # The order is important: del and insert invalidate some indices
860 lines.insert(start, '\\added_space_top ' + spaceamount + ' ')
862 lines.insert(start, '\\added_space_bottom ' + spaceamount + ' ')
866 lines[i:i+1] = ['\\begin_inset ERT', 'status Collapsed', '',
867 '\\layout Standard', '', '\\backslash ']
869 if spaceamount[-1] == '*':
870 spaceamount = spaceamount[:-1]
875 # Replace defskip by the actual value
876 if spaceamount == 'defskip':
877 spaceamount = defskipamount
879 # LaTeX does not know \\smallskip* etc
881 if spaceamount == 'smallskip':
882 spaceamount = '\\smallskipamount'
883 elif spaceamount == 'medskip':
884 spaceamount = '\\medskipamount'
885 elif spaceamount == 'bigskip':
886 spaceamount = '\\bigskipamount'
887 elif spaceamount == 'vfill':
888 spaceamount = '\\fill'
890 # Finally output the LaTeX code
891 if (spaceamount == 'smallskip' or spaceamount == 'medskip' or
892 spaceamount == 'bigskip' or spaceamount == 'vfill'):
893 lines.insert(i, spaceamount)
896 lines.insert(i, 'vspace*{')
898 lines.insert(i, 'vspace{')
899 i = convert_ertbackslash(lines, i, spaceamount)
900 lines[i] = lines[i] + '}'
904 # Convert a LyX length into valid ERT code and append it to lines[i]
905 # Return the (maybe incremented) line index i
906 def convert_ertlen(lines, i, len, special):
907 units = {"text%":"\\textwidth", "col%":"\\columnwidth",
908 "page%":"\\pagewidth", "line%":"\\linewidth",
909 "theight%":"\\textheight", "pheight%":"\\pageheight"}
911 # Convert special lengths
912 if special != 'none':
913 len = '%f\\' % len2value(len) + special
915 # Convert LyX units to LaTeX units
916 for unit in units.keys():
917 if find(len, unit) != -1:
918 len = '%f' % (len2value(len) / 100) + units[unit]
921 # Convert backslashes and insert the converted length into lines
922 return convert_ertbackslash(lines, i, len)
925 # Return the value of len without the unit in numerical form
927 result = re.search('([+-]?[0-9.]+)', len)
929 return float(result.group(1))
930 # No number means 1.0
934 def convert_frameless_box(lines, opt):
935 pos = ['t', 'c', 'b']
936 inner_pos = ['c', 't', 'b', 's']
939 i = find_token(lines, '\\begin_inset Frameless', i)
942 j = find_end_of_inset(lines, i)
944 opt.warning("Malformed LyX file: Missing '\\end_inset'\n")
950 params = {'position':'0', 'hor_pos':'c', 'has_inner_box':'1',
951 'inner_pos':'1', 'use_parbox':'0', 'width':'100col%',
952 'special':'none', 'height':'1in',
953 'height_special':'totalheight', 'collapsed':'false'}
954 for key in params.keys():
955 value = replace(get_value(lines, key, i, j), '"', '')
957 if key == 'position':
958 # convert new to old position: 'position "t"' -> 0
959 value = find_token(pos, value, 0)
962 elif key == 'inner_pos':
963 # convert inner position
964 value = find_token(inner_pos, value, 0)
969 j = del_token(lines, key, i, j)
972 # Convert to minipage or ERT?
973 # Note that the inner_position and height parameters of a minipage
974 # inset are ignored and not accessible for the user, although they
975 # are present in the file format and correctly read in and written.
976 # Therefore we convert to ERT if they do not have their LaTeX
977 # defaults. These are:
978 # - the value of "position" for "inner_pos"
979 # - "\totalheight" for "height"
980 if (params['use_parbox'] != '0' or
981 params['has_inner_box'] != '1' or
982 params['special'] != 'none' or
983 inner_pos[params['inner_pos']] != pos[params['position']] or
984 params['height_special'] != 'totalheight' or
985 len2value(params['height']) != 1.0):
988 if params['collapsed'] == 'true':
989 params['collapsed'] = 'Collapsed'
991 params['collapsed'] = 'Open'
992 lines[i : i] = ['\\begin_inset ERT', 'status ' + params['collapsed'],
993 '', '\\layout Standard', '', '\\backslash ']
995 if params['use_parbox'] == '1':
996 lines.insert(i, 'parbox')
998 lines.insert(i, 'begin{minipage}')
999 lines[i] = lines[i] + '[' + pos[params['position']] + ']['
1000 i = convert_ertlen(lines, i, params['height'], params['height_special'])
1001 lines[i] = lines[i] + '][' + inner_pos[params['inner_pos']] + ']{'
1002 i = convert_ertlen(lines, i, params['width'], params['special'])
1003 if params['use_parbox'] == '1':
1004 lines[i] = lines[i] + '}{'
1006 lines[i] = lines[i] + '}'
1008 lines[i:i] = ['', '\\end_inset ']
1010 j = find_end_of_inset(lines, i)
1012 opt.warning("Malformed LyX file: Missing '\\end_inset'.")
1014 lines[j-1:j-1] = ['\\begin_inset ERT', 'status ' + params['collapsed'],
1015 '', '\\layout Standard', '']
1017 if params['use_parbox'] == '1':
1018 lines.insert(j, '}')
1020 lines[j:j] = ['\\backslash ', 'end{minipage}']
1023 # Convert to minipage
1024 lines[i:i] = ['\\begin_inset Minipage',
1025 'position %d' % params['position'],
1026 'inner_position %d' % params['inner_pos'],
1027 'height "' + params['height'] + '"',
1028 'width "' + params['width'] + '"',
1029 'collapsed ' + params['collapsed']]
1036 def convert_jurabib(header, opt):
1037 i = find_token(header, '\\use_numerical_citations', 0)
1039 opt.warning("Malformed lyx file: Missing '\\use_numerical_citations'")
1041 header.insert(i + 1, '\\use_jurabib 0')
1044 def revert_jurabib(header, opt):
1045 i = find_token(header, '\\use_jurabib', 0)
1047 opt.warning("Malformed lyx file: Missing '\\use_jurabib'")
1049 if get_value(header, '\\use_jurabib', 0) != "0":
1050 opt.warning("Conversion of '\\use_jurabib = 1' not yet implemented.")
1051 # Don't remove '\\use_jurabib' so that people will get warnings by lyx
1059 def convert_bibtopic(header, opt):
1060 i = find_token(header, '\\use_jurabib', 0)
1062 opt.warning("Malformed lyx file: Missing '\\use_jurabib'")
1064 header.insert(i + 1, '\\use_bibtopic 0')
1067 def revert_bibtopic(header, opt):
1068 i = find_token(header, '\\use_bibtopic', 0)
1070 opt.warning("Malformed lyx file: Missing '\\use_bibtopic'")
1072 if get_value(header, '\\use_bibtopic', 0) != "0":
1073 opt.warning("Conversion of '\\use_bibtopic = 1' not yet implemented.")
1074 # Don't remove '\\use_jurabib' so that people will get warnings by lyx
1081 def convert_float(lines, opt):
1084 i = find_token(lines, '\\begin_inset Float', i)
1087 # Seach for a line starting 'wide'
1088 # If, however, we find a line starting '\begin_layout'
1089 # (_always_ present) then break with a warning message
1092 if (lines[i][:4] == "wide"):
1093 lines.insert(i + 1, 'sideways false')
1095 elif (lines[i][:13] == "\\begin_layout"):
1096 opt.warning("Malformed lyx file")
1102 def revert_float(lines, opt):
1105 i = find_token(lines, '\\begin_inset Float', i)
1108 j = find_end_of_inset(lines, i)
1110 opt.warning("Malformed lyx file: Missing '\\end_inset'")
1113 if get_value(lines, 'sideways', i, j) != "false":
1114 opt.warning("Conversion of 'sideways true' not yet implemented.")
1115 # Don't remove 'sideways' so that people will get warnings by lyx
1118 del_token(lines, 'sideways', i, j)
1121 def convert_graphics(lines, opt):
1122 """ Add extension to filenames of insetgraphics if necessary.
1126 i = find_token(lines, "\\begin_inset Graphics", i)
1130 j = find_token2(lines, "filename", i)
1134 filename = split(lines[j])[1]
1135 absname = os.path.normpath(os.path.join(opt.dir, filename))
1136 if opt.input == stdin and not os.path.isabs(filename):
1137 # We don't know the directory and cannot check the file.
1138 # We could use a heuristic and take the current directory,
1139 # and we could try to find out if filename has an extension,
1140 # but that would be just guesses and could be wrong.
1141 opt.warning("""Warning: Can not determine wether file
1143 needs an extension when reading from standard input.
1144 You may need to correct the file manually or run
1145 lyx2lyx again with the .lyx file as commandline argument.""" % filename)
1147 # This needs to be the same algorithm as in pre 233 insetgraphics
1148 if access(absname, F_OK):
1150 if access(absname + ".ps", F_OK):
1151 lines[j] = replace(lines[j], filename, filename + ".ps")
1153 if access(absname + ".eps", F_OK):
1154 lines[j] = replace(lines[j], filename, filename + ".eps")
1161 def convert(header, body, opt):
1162 if opt.format < 223:
1163 add_end_header(header)
1164 convert_spaces(body)
1165 convert_bibtex(body)
1166 remove_insetparent(body)
1168 if opt.end == opt.format: return
1170 if opt.format < 224:
1171 convert_external(body)
1172 convert_comment(body)
1174 if opt.end == opt.format: return
1176 if opt.format < 225:
1177 add_end_layout(body)
1178 layout2begin_layout(body)
1179 convert_end_document(body)
1180 convert_table_valignment_middle(body)
1181 convert_breaks(body)
1183 if opt.end == opt.format: return
1185 if opt.format < 226:
1188 if opt.end == opt.format: return
1190 if opt.format < 227:
1193 if opt.end == opt.format: return
1195 if opt.format < 228:
1196 convert_collapsable(body, opt)
1197 convert_ert(body, opt)
1199 if opt.end == opt.format: return
1201 if opt.format < 229:
1202 convert_minipage(body)
1204 if opt.end == opt.format: return
1206 if opt.format < 230:
1207 convert_jurabib(header, opt)
1209 if opt.end == opt.format: return
1211 if opt.format < 231:
1212 convert_float(body, opt)
1214 if opt.end == opt.format: return
1216 if opt.format < 232:
1217 convert_bibtopic(header, opt)
1219 if opt.end == opt.format: return
1221 if opt.format < 233:
1222 convert_graphics(body, opt)
1225 def revert(header, body, opt):
1226 if opt.format > 232:
1228 if opt.end == opt.format: return
1230 if opt.format > 231:
1231 revert_bibtopic(header, opt)
1233 if opt.end == opt.format: return
1235 if opt.format > 230:
1236 revert_float(body, opt)
1238 if opt.end == opt.format: return
1240 if opt.format > 229:
1241 revert_jurabib(header, opt)
1243 if opt.end == opt.format: return
1245 if opt.format > 228:
1247 if opt.end == opt.format: return
1249 if opt.format > 227:
1250 revert_collapsable(body, opt)
1251 revert_ert(body, opt)
1253 if opt.end == opt.format: return
1255 if opt.format > 226:
1257 revert_external_2(body)
1259 if opt.end == opt.format: return
1261 if opt.format > 225:
1264 if opt.end == opt.format: return
1266 if opt.format > 224:
1268 begin_layout2layout(body)
1269 revert_end_document(body)
1270 revert_valignment_middle(body)
1271 convert_vspace(header, body, opt)
1272 convert_frameless_box(body, opt)
1273 if opt.end == opt.format: return
1275 if opt.format > 223:
1276 revert_external_2(body)
1277 revert_comment(body)
1279 if opt.end == opt.format: return
1281 if opt.format > 221:
1282 rm_end_header(header)
1285 rm_tracking_changes(header)
1286 rm_body_changes(body)
1290 if __name__ == "__main__":