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