]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/lyxrevert_225.py
add bibtopic support (bug 870).
[lyx.git] / lib / lyx2lyx / lyxrevert_225.py
1 # This file is part of lyx2lyx
2 # -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2003 José Matos <jamatos@fep.up.pt>
4 # Copyright (C) 2003 Georg Baum <Georg.Baum@post.rwth-aachen.de>
5 #
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.
10 #
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.
15 #
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.
19
20 import re
21 from parser_tools import find_token, find_end_of_inset, get_next_paragraph, \
22                          get_paragraph, get_value, del_token, is_nonempty_line
23 from string import find, replace, split
24 import sys
25
26 def rm_end_layout(lines):
27     i = 0
28     while 1:
29         i = find_token(lines, '\\end_layout', i)
30
31         if i == -1:
32             return
33
34         del lines[i]
35
36 def begin_layout2layout(lines):
37     i = 0
38     while 1:
39         i = find_token(lines, '\\begin_layout', i)
40         if i == -1:
41             return
42
43         lines[i] = replace(lines[i], '\\begin_layout', '\\layout')
44         i = i + 1
45
46 def table_valignment_middle(lines, start, end):
47     for i in range(start, end):
48         if re.search('^<(column|cell) .*valignment="middle".*>$', lines[i]):
49             lines[i] = replace(lines[i], 'valignment="middle"', 'valignment="center"')
50
51 def valignment_middle(lines):
52     i = 0
53     while 1:
54         i = find_token(lines, '\\begin_inset  Tabular', i)
55         if i == -1:
56             return
57         j = find_end_of_inset(lines, i + 1)
58         if j == -1:
59             #this should not happen
60             valignment_middle(lines, i + 1, len(lines))
61             return
62         valignment_middle(lines, i + 1, j)
63         i = j + 1
64
65 def end_document(lines):
66     i = find_token(lines, "\\end_document", 0)
67     if i == -1:
68         lines.append("\\the_end")
69         return
70     lines[i] = "\\the_end"
71
72 # Convert backslashes into valid ERT code, append the converted text to
73 # lines[i] and return the (maybe incremented) line index i
74 def convert_ertbackslash(lines, i, ert):
75     for c in ert:
76         if c == '\\':
77             lines[i] = lines[i] + '\\backslash '
78             lines.insert(i, '')
79             i = i + 1
80         else:
81             lines[i] = lines[i] + c
82     return i
83
84 def convert_vspace(header, lines):
85
86     # Get default spaceamount
87     i = find_token(header, '\\defskip', 0)
88     if i == -1:
89         defskipamount = 'medskip'
90     else:
91         defskipamount = split(header[i])[1]
92
93     # Convert the insets
94     i = 0
95     while 1:
96         i = find_token(lines, '\\begin_inset VSpace', i)
97         if i == -1:
98             return
99         spaceamount = split(lines[i])[2]
100
101         # Are we at the beginning or end of a paragraph?
102         paragraph_start = 1
103         start = get_paragraph(lines, i) + 1
104         for k in range(start, i):
105             if is_nonempty_line(lines[k]):
106                 paragraph_start = 0
107                 break
108         paragraph_end = 1
109         j = find_end_of_inset(lines, i)
110         if j == -1:
111             sys.stderr.write("Malformed lyx file: Missing '\\end_inset'\n")
112             i = i + 1
113             continue
114         end = get_next_paragraph(lines, i)
115         for k in range(j + 1, end):
116             if is_nonempty_line(lines[k]):
117                 paragraph_end = 0
118                 break
119
120         # Convert to paragraph formatting if we are at the beginning or end
121         # of a paragraph and the resulting paragraph would not be empty
122         if ((paragraph_start and not paragraph_end) or
123             (paragraph_end   and not paragraph_start)):
124             # The order is important: del and insert invalidate some indices
125             del lines[j]
126             del lines[i]
127             if paragraph_start:
128                 lines.insert(start, '\\added_space_top ' + spaceamount + ' ')
129             else:
130                 lines.insert(start, '\\added_space_bottom ' + spaceamount + ' ')
131             continue
132
133         # Convert to ERT
134         lines[i:i+1] = ['\\begin_inset ERT', 'status Collapsed', '',
135                         '\\layout Standard', '', '\\backslash ']
136         i = i + 6
137         if spaceamount[-1] == '*':
138             spaceamount = spaceamount[:-1]
139             keep = 1
140         else:
141             keep = 0
142
143         # Replace defskip by the actual value
144         if spaceamount == 'defskip':
145             spaceamount = defskipamount
146
147         # LaTeX does not know \\smallskip* etc
148         if keep:
149             if spaceamount == 'smallskip':
150                 spaceamount = '\\smallskipamount'
151             elif spaceamount == 'medskip':
152                 spaceamount = '\\medskipamount'
153             elif spaceamount == 'bigskip':
154                 spaceamount = '\\bigskipamount'
155             elif spaceamount == 'vfill':
156                 spaceamount = '\\fill'
157
158         # Finally output the LaTeX code
159         if (spaceamount == 'smallskip' or spaceamount == 'medskip' or
160             spaceamount == 'bigskip'   or spaceamount == 'vfill'):
161             lines.insert(i, spaceamount)
162         else :
163             if keep:
164                 lines.insert(i, 'vspace*{')
165             else:
166                 lines.insert(i, 'vspace{')
167             i = convert_ertbackslash(lines, i, spaceamount)
168             lines[i] =  lines[i] + '}'
169         i = i + 1
170
171 # Convert a LyX length into valid ERT code and append it to lines[i]
172 # Return the (maybe incremented) line index i
173 def convert_ertlen(lines, i, len, special):
174     units = {"text%":"\\textwidth", "col%":"\\columnwidth",
175              "page%":"\\pagewidth", "line%":"\\linewidth",
176              "theight%":"\\textheight", "pheight%":"\\pageheight"}
177
178     # Convert special lengths
179     if special != 'none':
180         len = '%f\\' % len2value(len) + special
181
182     # Convert LyX units to LaTeX units
183     for unit in units.keys():
184         if find(len, unit) != -1:
185             len = '%f' % (len2value(len) / 100) + units[unit]
186             break
187
188     # Convert backslashes and insert the converted length into lines
189     return convert_ertbackslash(lines, i, len)
190
191 # Return the value of len without the unit in numerical form
192 def len2value(len):
193     result = re.search('([+-]?[0-9.]+)', len)
194     if result:
195         return float(result.group(1))
196     # No number means 1.0
197     return 1.0
198
199 def convert_frameless_box(lines):
200     pos = ['t', 'c', 'b']
201     inner_pos = ['c', 't', 'b', 's']
202     i = 0
203     while 1:
204         i = find_token(lines, '\\begin_inset Frameless', i)
205         if i == -1:
206             return
207         j = find_end_of_inset(lines, i)
208         if j == -1:
209             sys.stderr.write("Malformed lyx file: Missing '\\end_inset'\n")
210             i = i + 1
211             continue
212         del lines[i]
213
214         # Gather parameters
215         params = {'position':'0', 'hor_pos':'c', 'has_inner_box':'1',
216                   'inner_pos':'1', 'use_parbox':'0', 'width':'100col%',
217                   'special':'none', 'height':'1in',
218                   'height_special':'totalheight', 'collapsed':'false'}
219         for key in params.keys():
220             value = replace(get_value(lines, key, i, j), '"', '')
221             if value != "":
222                 if key == 'position':
223                     # convert new to old position: 'position "t"' -> 0
224                     value = find_token(pos, value, 0)
225                     if value != -1:
226                         params[key] = value
227                 elif key == 'inner_pos':
228                     # convert inner position
229                     value = find_token(inner_pos, value, 0)
230                     if value != -1:
231                         params[key] = value
232                 else:
233                     params[key] = value
234                 j = del_token(lines, key, i, j)
235         i = i + 1
236
237         # Convert to minipage or ERT?
238         # Note that the inner_position and height parameters of a minipage
239         # inset are ignored and not accessible for the user, although they
240         # are present in the file format and correctly read in and written.
241         # Therefore we convert to ERT if they do not have their LaTeX
242         # defaults. These are:
243         # - the value of "position" for "inner_pos"
244         # - "\totalheight"          for "height"
245         if (params['use_parbox'] != '0' or
246             params['has_inner_box'] != '1' or
247             params['special'] != 'none' or
248             inner_pos[params['inner_pos']] != pos[params['position']] or
249             params['height_special'] != 'totalheight' or
250             len2value(params['height']) != 1.0):
251
252             # Convert to ERT
253             if params['collapsed'] == 'true':
254                 params['collapsed'] = 'Collapsed'
255             else:
256                 params['collapsed'] = 'Open'
257             lines[i : i] = ['\\begin_inset ERT', 'status ' + params['collapsed'],
258                             '', '\\layout Standard', '', '\\backslash ']
259             i = i + 6
260             if params['use_parbox'] == '1':
261                 lines.insert(i, 'parbox')
262             else:
263                 lines.insert(i, 'begin{minipage}')
264             lines[i] = lines[i] + '[' + pos[params['position']] + ']['
265             i = convert_ertlen(lines, i, params['height'], params['height_special'])
266             lines[i] = lines[i] + '][' + inner_pos[params['inner_pos']] + ']{'
267             i = convert_ertlen(lines, i, params['width'], params['special'])
268             if params['use_parbox'] == '1':
269                 lines[i] = lines[i] + '}{'
270             else:
271                 lines[i] = lines[i] + '}'
272             i = i + 1
273             lines[i:i] = ['', '\\end_inset ']
274             i = i + 2
275             j = find_end_of_inset(lines, i)
276             if j == -1:
277                 sys.stderr.write("Malformed lyx file: Missing '\\end_inset'\n")
278                 break
279             lines[j-1:j-1] += ['\\begin_inset ERT', 'status ' + params['collapsed'],
280                                '', '\\layout Standard', '']
281             j = j + 4
282             if params['use_parbox'] == '1':
283                 lines.insert(j, '}')
284             else:
285                 lines[j:j] = ['\\backslash ', 'end{minipage}']
286         else:
287
288             # Convert to minipage
289             lines[i:i] = ['\\begin_inset Minipage',
290                           'position %d' % params['position'],
291                           'inner_position %d' % params['inner_pos'],
292                           'height "' + params['height'] + '"',
293                           'width "' + params['width'] + '"',
294                           'collapsed ' + params['collapsed']]
295             i = i + 6
296
297 def convert(header, body):
298     rm_end_layout(body)
299     begin_layout2layout(body)
300     end_document(body)
301     valignment_middle(body)
302     convert_vspace(header, body)
303     convert_frameless_box(body)
304
305 if __name__ == "__main__":
306     pass