]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/lyx_1_1_6.py
fix bug 2026 and bug 2088
[lyx.git] / lib / lyx2lyx / lyx_1_1_6.py
1 # This file is part of lyx2lyx
2 # -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2002-2004 José Matos <jamatos@lyx.org>
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 import string
21 from parser_tools import find_re, find_tokens, find_token, check_token
22
23
24 lyxtable_re = re.compile(r".*\\LyXTable$")
25 def update_tabular(file):
26     lines = file.body
27     i=0
28     while 1:
29         i = find_re(lines, lyxtable_re, i)
30         if i == -1:
31             break
32         prop_dict = {"family" : "default", "series" : "default",
33                       "shape" : "default", "size" : "default",
34                       "emph" : "default", "bar" : "default",
35                       "noun" : "default", "latex" : "default", "color" : "default"}
36
37         # remove \LyXTable
38         lines[i] = lines[i][:-9]
39         i = i + 1
40         lines.insert(i,'')
41         i = i + 1
42         lines[i] = "\\begin_inset  Tabular"
43         i = i + 1
44         head = string.split(lines[i])
45         rows = int(head[0])
46         columns = int(head[1])
47
48         tabular_line = i
49         i = i +1
50         lines.insert(i, '<Features rotate="%s" islongtable="%s" endhead="%s" endfirsthead="%s" endfoot="%s" endlastfoot="%s">' % (head[2],head[3],head[4],head[5],head[6],head[7]))
51
52         i = i +1
53
54         row_info = []
55         cont_row = []
56         for j in range(rows):
57             row_info.append(string.split(lines[i]))
58             if string.split(lines[i])[2] == '1':
59                 cont_row.append(j)
60             del lines[i]
61
62         column_info = []
63         col_info_re = re.compile(r'(\d) (\d) (\d) (".*") (".*")')
64         for j in range(columns):
65             column_info.append(col_info_re.match(lines[i]).groups())
66             del lines[i]
67
68         cell_info = []
69         cell_col = []
70         ncells = 0
71         cell_re = re.compile(r'(\d) (\d) (\d) (\d) (\d) (\d) (\d) (".*") (".*")')
72         for j in range(rows):
73             for k in range(columns):
74                 #add column location to read properties
75                 cell_info.append(cell_re.match(lines[i]).groups())
76                 cell_col.append(k)
77                 if lines[i][0] != "2":
78                     ncells = ncells + 1
79                 del lines[i]
80
81         lines[tabular_line] = '<LyXTabular version="1" rows="%s" columns="%s">' % (rows-len(cont_row),columns)
82         del lines[i]
83         if not lines[i]:
84             del lines[i]
85
86         # Read cells
87         l = 0
88         cell_content = []
89         for j in range(rows):
90             cell_content.append([])
91
92         for j in range(rows):
93             for k in range(columns):
94                 cell_content[j].append([])
95
96         for j in range(rows):
97             for k in range(columns):
98                 m = j*columns + k
99                 if cell_info[m][0] == '2':
100                     continue
101
102                 if l == ncells -1:
103                     # the end variable refers to cell end, not to file end.
104                     end = find_tokens(lines, ['\\layout','\\the_end','\\end_deeper','\\end_float'], i)
105                 else:
106                     end = find_token(lines, '\\newline', i)
107
108                 if end == -1:
109                     file.error("Malformed LyX file.")
110
111                 end = end - i
112                 while end > 0:
113                     cell_content[j][k].append(lines[i])
114                     del lines[i]
115                     end = end -1
116
117                 if string.find(lines[i],'\\newline') != -1:
118                     del lines[i]
119                 l = l + 1
120
121         tmp = []
122         tmp.append("")
123
124         for j in range(rows):
125             if j in cont_row:
126                 continue
127             tmp.append('<Row topline="%s" bottomline="%s" newpage="%s">' % (row_info[j][0],row_info[j][1],row_info[j][3]))
128
129             for k in range(columns):
130                 if j:
131                     tmp.append('<Column>')
132                 else:
133                     tmp.append('<Column alignment="%s" valignment="0" leftline="%s" rightline="%s" width=%s special=%s>' % (column_info[k][0],column_info[k][1], column_info[k][2], column_info[k][3], column_info[k][4]))
134                 m = j*columns + k
135
136                 leftline = int(column_info[k][1])
137                 if cell_info[m][0] == '1':
138                     n = m + 1
139                     while n < rows * columns - 1 and cell_info[n][0] == '2':
140                         n = n + 1
141                     rightline = int(column_info[cell_col[n-1]][2])
142                 else:
143                     # not a multicolumn main cell
144                     rightline = int(column_info[k][2])
145
146                 tmp.append('<Cell multicolumn="%s" alignment="%s" valignment="0" topline="%s" bottomline="%s" leftline="%d" rightline="%d" rotate="%s" usebox="%s" width=%s special=%s>' % (cell_info[m][0],cell_info[m][1],cell_info[m][2],cell_info[m][3],leftline,rightline,cell_info[m][5],cell_info[m][6],cell_info[m][7],cell_info[m][8]))
147                 tmp.append('\\begin_inset Text')
148                 tmp.append('')
149                 tmp.append('\\layout %s' % file.default_layout)
150                 tmp.append('')
151
152                 if cell_info[m][0] != '2':
153                     paragraph = []
154                     if cell_info[m][4] == '1':
155                         l = j
156                         paragraph = paragraph + cell_content[j][k]
157                         while cell_info[m][4] == '1':
158                             m = m + columns
159                             l = l + 1
160                             if l >= rows: break
161                             paragraph = paragraph + cell_content[l][k]
162                     else:
163                         paragraph = cell_content[j][k]
164                     tmp = tmp + set_paragraph_properties(paragraph, prop_dict)
165
166                 tmp.append('\\end_inset ')
167                 tmp.append('</Cell>')
168                 tmp.append('</Column>')
169             tmp.append('</Row>')
170
171         tmp.append('</LyXTabular>')
172         tmp.append('')
173         tmp.append('\\end_inset ')
174         tmp.append('')
175         tmp.append('')
176         lines[i:i] = tmp
177
178         i = i + len(tmp)
179
180
181 prop_exp = re.compile(r"\\(\S*)\s*(\S*)")
182
183 def set_paragraph_properties(lines, prop_dict):
184     # we need to preserve the order of options
185     properties = ["family","series","shape","size",
186                   "emph","bar","noun","latex","color"]
187     prop_value = {"family" : "default", "series" : "medium",
188                    "shape" : "up", "size" : "normal",
189                    "emph" : "off", "bar" : "no",
190                    "noun" : "off", "latex" : "no_latex", "color" : "none"}
191
192     start = 0
193     end = 0
194     i = 0
195     n = len(lines)
196
197     #skip empty lines
198     while i<n and lines[i] == "":
199         i = i + 1
200     start = i
201
202     #catch open char properties
203     while i<n and lines[i][:1] == "\\":
204         result = prop_exp.match(lines[i])
205         # sys.stderr.write(lines[i]+"\n")
206         prop = result.group(1)
207         if prop not in properties:
208             break
209         else:
210             prop_dict[prop] = result.group(2)
211         i = i + 1
212     end = i
213
214     aux = []
215     insert = 0
216     for prop in properties:
217         if prop_dict[prop] != 'default':
218             insert = 1
219             if prop == "color":
220                 aux.append("\\%s %s" % (prop, prop_dict[prop]))
221             elif prop != "family" or prop_dict[prop] != "roman":
222                     aux.append("\\%s %s " % (prop, prop_dict[prop]))
223
224     # remove final char properties
225     n = len(lines)
226     changed_prop = []
227
228     while n:
229         n = n - 1
230         if not lines[n]:
231             del lines[n]
232             continue
233
234         if lines[n][:1] == '\\':
235             result = prop_exp.match(lines[n])
236             prop = result.group(1)
237             if prop in properties:
238                 changed_prop.append(prop)
239                 prop_dict[prop] = result.group(2)
240                 del lines[n]
241                 continue
242
243             if check_token(lines[n],'\\end_inset'):
244                 # ensure proper newlines after inset end
245                 lines.append('')
246                 lines.append('')
247         break
248
249     for line in lines[end:]:
250         if line[:1] == '\\':
251             result = prop_exp.match(line)
252             prop = result.group(1)
253             if prop in properties and prop not in changed_prop:
254                 prop_dict[prop] = result.group(2)
255
256     if not lines[start:] and not lines[end:]:
257         return []
258
259     result = lines[:start] + aux[:] + lines[end:]
260     if insert and result[0] != '':
261         return [''] + result[:]
262
263     return result[:]
264
265
266 def update_language(file):
267     header = file.header
268     i = find_token(header, "\\language", 0)
269     if i == -1:
270         # no language, should emit a warning
271         header.append('\\language english')
272         return
273     # This is the lyx behaviour: defaults to english
274     if string.split(header[i])[1] == 'default':
275         header[i] = '\\language english'
276     return
277
278
279 convert = [[217, [update_tabular, update_language]]]
280 revert  = []
281
282
283 if __name__ == "__main__":
284     pass