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.
1124 if opt.input == stdin:
1127 dir = os.path.dirname(os.path.abspath(opt.input.name))
1130 i = find_token(lines, "\\begin_inset Graphics", i)
1134 j = find_token2(lines, "filename", i)
1138 filename = split(lines[j])[1]
1139 absname = os.path.normpath(os.path.join(dir, filename))
1140 if opt.input == stdin and not os.path.isabs(filename):
1141 # We don't know the directory and cannot check the file.
1142 # We could use a heuristic and take the current directory,
1143 # and we could try to find out if filename has an extension,
1144 # but that would be just guesses and could be wrong.
1145 opt.warning("""Warning: Can not determine wether file
1147 needs an extension when reading from standard input.
1148 You may need to correct the file manually or run
1149 lyx2lyx again with the .lyx file as commandline argument.""" % filename)
1151 # This needs to be the same algorithm as in pre 233 insetgraphics
1152 if access(absname, F_OK):
1154 if access(absname + ".ps", F_OK):
1155 lines[j] = replace(lines[j], filename, filename + ".ps")
1157 if access(absname + ".eps", F_OK):
1158 lines[j] = replace(lines[j], filename, filename + ".eps")
1165 def convert(header, body, opt):
1166 if opt.format < 223:
1167 add_end_header(header)
1168 convert_spaces(body)
1169 convert_bibtex(body)
1170 remove_insetparent(body)
1172 if opt.end == opt.format: return
1174 if opt.format < 224:
1175 convert_external(body)
1176 convert_comment(body)
1178 if opt.end == opt.format: return
1180 if opt.format < 225:
1181 add_end_layout(body)
1182 layout2begin_layout(body)
1183 convert_end_document(body)
1184 convert_table_valignment_middle(body)
1185 convert_breaks(body)
1187 if opt.end == opt.format: return
1189 if opt.format < 226:
1192 if opt.end == opt.format: return
1194 if opt.format < 227:
1197 if opt.end == opt.format: return
1199 if opt.format < 228:
1200 convert_collapsable(body, opt)
1201 convert_ert(body, opt)
1203 if opt.end == opt.format: return
1205 if opt.format < 229:
1206 convert_minipage(body)
1208 if opt.end == opt.format: return
1210 if opt.format < 230:
1211 convert_jurabib(header, opt)
1213 if opt.end == opt.format: return
1215 if opt.format < 231:
1216 convert_float(body, opt)
1218 if opt.end == opt.format: return
1220 if opt.format < 232:
1221 convert_bibtopic(header, opt)
1223 if opt.end == opt.format: return
1225 if opt.format < 233:
1226 convert_graphics(body, opt)
1229 def revert(header, body, opt):
1230 if opt.format > 232:
1232 if opt.end == opt.format: return
1234 if opt.format > 231:
1235 revert_bibtopic(header, opt)
1237 if opt.end == opt.format: return
1239 if opt.format > 230:
1240 revert_float(body, opt)
1242 if opt.end == opt.format: return
1244 if opt.format > 229:
1245 revert_jurabib(header, opt)
1247 if opt.end == opt.format: return
1249 if opt.format > 228:
1251 if opt.end == opt.format: return
1253 if opt.format > 227:
1254 revert_collapsable(body, opt)
1255 revert_ert(body, opt)
1257 if opt.end == opt.format: return
1259 if opt.format > 226:
1261 revert_external_2(body)
1263 if opt.end == opt.format: return
1265 if opt.format > 225:
1268 if opt.end == opt.format: return
1270 if opt.format > 224:
1272 begin_layout2layout(body)
1273 revert_end_document(body)
1274 revert_valignment_middle(body)
1275 convert_vspace(header, body, opt)
1276 convert_frameless_box(body, opt)
1277 if opt.end == opt.format: return
1279 if opt.format > 223:
1280 revert_external_2(body)
1281 revert_comment(body)
1283 if opt.end == opt.format: return
1285 if opt.format > 221:
1286 rm_end_header(header)
1289 rm_tracking_changes(header)
1290 rm_body_changes(body)
1294 if __name__ == "__main__":