]> git.lyx.org Git - features.git/blob - lib/lyx2lyx/lyx_1_2.py
* LyX.py
[features.git] / lib / lyx2lyx / lyx_1_2.py
1 # This file is part of lyx2lyx
2 # -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2002 Dekel Tsur <dekel@lyx.org>
4 # Copyright (C) 2004 José Matos <jamatos@lyx.org>
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 string
21 import re
22
23 from parser_tools import find_token, find_token_backwards, \
24                          find_tokens,  find_tokens_backwards, find_beginning_of, find_end_of, find_re, \
25                          is_nonempty_line, find_nonempty_line, \
26                          get_value, check_token
27
28 ####################################################################
29 # Private helper functions
30
31 def get_layout(line, default_layout):
32     tokens = string.split(line)
33     if len(tokens) > 1:
34         return tokens[1]
35     return default_layout
36
37
38 # Finds the paragraph that contains line i.
39 def get_paragraph(lines, i, format):
40     begin_layout = "\\layout"
41
42     while i != -1:
43         i = find_tokens_backwards(lines, ["\\end_inset", begin_layout], i)
44         if i == -1: return -1
45         if check_token(lines[i], begin_layout):
46             return i
47         i = find_beginning_of_inset(lines, i)
48     return -1
49
50
51 # Finds the paragraph after the paragraph that contains line i.
52 def get_next_paragraph(lines, i, format):
53     tokens = ["\\begin_inset", "\\layout", "\\end_float", "\\the_end"]
54
55     while i != -1:
56         i = find_tokens(lines, tokens, i)
57         if not check_token(lines[i], "\\begin_inset"):
58             return i
59         i = find_end_of_inset(lines, i)
60     return -1
61
62
63 def find_beginning_of_inset(lines, i):
64     return find_beginning_of(lines, i, "\\begin_inset", "\\end_inset")
65
66
67 # Finds the matching \end_inset
68 def find_end_of_inset(lines, i):
69     return find_end_of(lines, i, "\\begin_inset", "\\end_inset")
70
71
72 def find_end_of_tabular(lines, i):
73     return find_end_of(lines, i, "<lyxtabular", "</lyxtabular")
74
75
76 def get_tabular_lines(lines, i):
77     result = []
78     i = i+1
79     j = find_end_of_tabular(lines, i)
80     if j == -1:
81         return []
82
83     while i <= j:
84         if check_token(lines[i], "\\begin_inset"):
85             i = find_end_of_inset(lines, i)+1
86         else:
87             result.append(i)
88             i = i+1
89     return result
90
91 # End of helper functions
92 ####################################################################
93
94
95 floats = {
96     "footnote": ["\\begin_inset Foot",
97                  "collapsed true"],
98     "margin":   ["\\begin_inset Marginal",
99                  "collapsed true"],
100     "fig":      ["\\begin_inset Float figure",
101                  "wide false",
102                  "collapsed false"],
103     "tab":      ["\\begin_inset Float table",
104                  "wide false",
105                  "collapsed false"],
106     "alg":      ["\\begin_inset Float algorithm",
107                  "wide false",
108                  "collapsed false"],
109     "wide-fig": ["\\begin_inset Float figure",
110                  "wide true",
111                  "collapsed false"],
112     "wide-tab": ["\\begin_inset Float table",
113                  "wide true",
114                  "collapsed false"]
115 }
116
117 font_tokens = ["\\family", "\\series", "\\shape", "\\size", "\\emph",
118                "\\bar", "\\noun", "\\color", "\\lang", "\\latex"]
119
120 pextra_type3_rexp = re.compile(r".*\\pextra_type\s+3")
121 pextra_rexp = re.compile(r"\\pextra_type\s+(\S+)"+\
122                          r"(\s+\\pextra_alignment\s+(\S+))?"+\
123                          r"(\s+\\pextra_hfill\s+(\S+))?"+\
124                          r"(\s+\\pextra_start_minipage\s+(\S+))?"+\
125                          r"(\s+(\\pextra_widthp?)\s+(\S*))?")
126
127
128 def get_width(mo):
129     if mo.group(10):
130         if mo.group(9) == "\\pextra_widthp":
131             return mo.group(10)+"col%"
132         else:
133             return mo.group(10)
134     else:
135         return "100col%"
136
137
138 #
139 # Change \begin_float .. \end_float into \begin_inset Float .. \end_inset
140 #
141 def remove_oldfloat(file):
142     lines = file.body
143     i = 0
144     while 1:
145         i = find_token(lines, "\\begin_float", i)
146         if i == -1:
147             break
148         # There are no nested floats, so finding the end of the float is simple
149         j = find_token(lines, "\\end_float", i+1)
150
151         floattype = string.split(lines[i])[1]
152         if not floats.has_key(floattype):
153             file.warning("Error! Unknown float type " + floattype)
154             floattype = "fig"
155
156         # skip \end_deeper tokens
157         i2 = i+1
158         while check_token(lines[i2], "\\end_deeper"):
159             i2 = i2+1
160         if i2 > i+1:
161             j2 = get_next_paragraph(lines, j + 1, file.format + 1)
162             lines[j2:j2] = ["\\end_deeper "]*(i2-(i+1))
163
164         new = floats[floattype]+[""]
165
166         # Check if the float is floatingfigure
167         k = find_re(lines, pextra_type3_rexp, i, j)
168         if k != -1:
169             mo = pextra_rexp.search(lines[k])
170             width = get_width(mo)
171             lines[k] = re.sub(pextra_rexp, "", lines[k])
172             new = ["\\begin_inset Wrap figure",
173                    'width "%s"' % width,
174                    "collapsed false",
175                    ""]
176
177         new = new+lines[i2:j]+["\\end_inset ", ""]
178
179         # After a float, all font attributes are reseted.
180         # We need to output '\foo default' for every attribute foo
181         # whose value is not default before the float.
182         # The check here is not accurate, but it doesn't matter
183         # as extra '\foo default' commands are ignored.
184         # In fact, it might be safer to output '\foo default' for all
185         # font attributes.
186         k = get_paragraph(lines, i, file.format + 1)
187         flag = 0
188         for token in font_tokens:
189             if find_token(lines, token, k, i) != -1:
190                 if not flag:
191                     # This is not necessary, but we want the output to be
192                     # as similar as posible to the lyx format
193                     flag = 1
194                     new.append("")
195                 if token == "\\lang":
196                     new.append(token+" "+ file.language)
197                 else:
198                     new.append(token+" default ")
199
200         lines[i:j+1] = new
201         i = i+1
202
203
204 pextra_type2_rexp = re.compile(r".*\\pextra_type\s+[12]")
205 pextra_type2_rexp2 = re.compile(r".*(\\layout|\\pextra_type\s+2)")
206 pextra_widthp = re.compile(r"\\pextra_widthp")
207
208 def remove_pextra(file):
209     lines = file.body
210     i = 0
211     flag = 0
212     while 1:
213         i = find_re(lines, pextra_type2_rexp, i)
214         if i == -1:
215             break
216
217         # Sometimes the \pextra_widthp argument comes in it own
218         # line. If that happens insert it back in this line.
219         if pextra_widthp.search(lines[i+1]):
220             lines[i] = lines[i] + ' ' + lines[i+1]
221             del lines[i+1]
222
223         mo = pextra_rexp.search(lines[i])
224         width = get_width(mo)
225
226         if mo.group(1) == "1":
227             # handle \pextra_type 1 (indented paragraph)
228             lines[i] = re.sub(pextra_rexp, "\\leftindent "+width+" ", lines[i])
229             i = i+1
230             continue
231
232         # handle \pextra_type 2 (minipage)
233         position = mo.group(3)
234         hfill = mo.group(5)
235         lines[i] = re.sub(pextra_rexp, "", lines[i])
236
237         start = ["\\begin_inset Minipage",
238                  "position " + position,
239                  "inner_position 0",
240                  'height "0pt"',
241                  'width "%s"' % width,
242                  "collapsed false"
243                  ]
244         if flag:
245             flag = 0
246             if hfill:
247                 start = ["","\hfill",""]+start
248         else:
249             start = ['\\layout %s' % file.default_layout,''] + start
250
251         j0 = find_token_backwards(lines,"\\layout", i-1)
252         j = get_next_paragraph(lines, i, file.format + 1)
253
254         count = 0
255         while 1:
256             # collect more paragraphs to the minipage
257             count = count+1
258             if j == -1 or not check_token(lines[j], "\\layout"):
259                 break
260             i = find_re(lines, pextra_type2_rexp2, j+1)
261             if i == -1:
262                 break
263             mo = pextra_rexp.search(lines[i])
264             if not mo:
265                 break
266             if mo.group(7) == "1":
267                 flag = 1
268                 break
269             lines[i] = re.sub(pextra_rexp, "", lines[i])
270             j = find_tokens(lines, ["\\layout", "\\end_float"], i+1)
271
272         mid = lines[j0:j]
273         end = ["\\end_inset "]
274
275         lines[j0:j] = start+mid+end
276         i = i+1
277
278
279 def is_empty(lines):
280     return filter(is_nonempty_line, lines) == []
281
282
283 move_rexp =  re.compile(r"\\(family|series|shape|size|emph|numeric|bar|noun|end_deeper)")
284 ert_rexp = re.compile(r"\\begin_inset|\\hfill|.*\\SpecialChar")
285 spchar_rexp = re.compile(r"(.*)(\\SpecialChar.*)")
286
287
288 def remove_oldert(file):
289     ert_begin = ["\\begin_inset ERT",
290                  "status Collapsed",
291                  "",
292                  '\\layout %s' % file.default_layout,
293                  ""]
294     lines = file.body
295     i = 0
296     while 1:
297         i = find_tokens(lines, ["\\latex latex", "\\layout LaTeX"], i)
298         if i == -1:
299             break
300         j = i+1
301         while 1:
302             # \end_inset is for ert inside a tabular cell. The other tokens
303             # are obvious.
304             j = find_tokens(lines, ["\\latex default", "\\layout", "\\begin_inset", "\\end_inset", "\\end_float", "\\the_end"],
305                             j)
306             if check_token(lines[j], "\\begin_inset"):
307                 j = find_end_of_inset(lines, j)+1
308             else:
309                 break
310
311         if check_token(lines[j], "\\layout"):
312             while j-1 >= 0 and check_token(lines[j-1], "\\begin_deeper"):
313                 j = j-1
314
315         # We need to remove insets, special chars & font commands from ERT text
316         new = []
317         new2 = []
318         if check_token(lines[i], "\\layout LaTeX"):
319             new = ['\layout %s' % file.default_layout, "", ""]
320
321         k = i+1
322         while 1:
323             k2 = find_re(lines, ert_rexp, k, j)
324             inset = hfill = specialchar = 0
325             if k2 == -1:
326                 k2 = j
327             elif check_token(lines[k2], "\\begin_inset"):
328                 inset = 1
329             elif check_token(lines[k2], "\\hfill"):
330                 hfill = 1
331                 del lines[k2]
332                 j = j-1
333             else:
334                 specialchar = 1
335                 mo = spchar_rexp.match(lines[k2])
336                 lines[k2] = mo.group(1)
337                 specialchar_str = mo.group(2)
338                 k2 = k2+1
339
340             tmp = []
341             for line in lines[k:k2]:
342                 # Move some lines outside the ERT inset:
343                 if move_rexp.match(line):
344                     if new2 == []:
345                         # This is not necessary, but we want the output to be
346                         # as similar as posible to the lyx format
347                         new2 = [""]
348                     new2.append(line)
349                 elif not check_token(line, "\\latex"):
350                     tmp.append(line)
351
352             if is_empty(tmp):
353                 if filter(lambda x:x != "", tmp) != []:
354                     if new == []:
355                         # This is not necessary, but we want the output to be
356                         # as similar as posible to the lyx format
357                         lines[i-1] = lines[i-1]+" "
358                     else:
359                         new = new+[" "]
360             else:
361                 new = new+ert_begin+tmp+["\\end_inset ", ""]
362
363             if inset:
364                 k3 = find_end_of_inset(lines, k2)
365                 new = new+[""]+lines[k2:k3+1]+[""] # Put an empty line after \end_inset
366                 k = k3+1
367                 # Skip the empty line after \end_inset
368                 if not is_nonempty_line(lines[k]):
369                     k = k+1
370                     new.append("")
371             elif hfill:
372                 new = new + ["\\hfill", ""]
373                 k = k2
374             elif specialchar:
375                 if new == []:
376                     # This is not necessary, but we want the output to be
377                     # as similar as posible to the lyx format
378                     lines[i-1] = lines[i-1]+specialchar_str
379                     new = [""]
380                 else:
381                     new = new+[specialchar_str, ""]
382                 k = k2
383             else:
384                 break
385
386         new = new+new2
387         if not check_token(lines[j], "\\latex "):
388             new = new+[""]+[lines[j]]
389         lines[i:j+1] = new
390         i = i+1
391
392     # Delete remaining "\latex xxx" tokens
393     i = 0
394     while 1:
395         i = find_token(lines, "\\latex ", i)
396         if i == -1:
397             break
398         del lines[i]
399
400
401 # ERT insert are hidden feature of lyx 1.1.6. This might be removed in the future.
402 def remove_oldertinset(file):
403     lines = file.body
404     i = 0
405     while 1:
406         i = find_token(lines, "\\begin_inset ERT", i)
407         if i == -1:
408             break
409         j = find_end_of_inset(lines, i)
410         k = find_token(lines, "\\layout", i+1)
411         l = get_paragraph(lines, i, file.format + 1)
412         if lines[k] == lines[l]: # same layout
413             k = k+1
414         new = lines[k:j]
415         lines[i:j+1] = new
416         i = i+1
417
418
419 def is_ert_paragraph(file, i):
420     lines = file.body
421     if not check_token(lines[i], "\\layout"):
422         return 0
423     if not file.is_default_layout(get_layout(lines[i], file.default_layout)):
424         return 0
425
426     i = find_nonempty_line(lines, i+1)
427     if not check_token(lines[i], "\\begin_inset ERT"):
428         return 0
429
430     j = find_end_of_inset(lines, i)
431     k = find_nonempty_line(lines, j+1)
432     return check_token(lines[k], "\\layout")
433
434
435 def combine_ert(file):
436     lines = file.body
437     i = 0
438     while 1:
439         i = find_token(lines, "\\begin_inset ERT", i)
440         if i == -1:
441             break
442         j = get_paragraph(lines, i, file.format + 1)
443         count = 0
444         text = []
445         while is_ert_paragraph(file, j):
446
447             count = count+1
448             i2 = find_token(lines, "\\layout", j+1)
449             k = find_token(lines, "\\end_inset", i2+1)
450             text = text+lines[i2:k]
451             j = find_token(lines, "\\layout", k+1)
452             if j == -1:
453                 break
454
455         if count >= 2:
456             j = find_token(lines, "\\layout", i+1)
457             lines[j:k] = text
458
459         i = i+1
460
461
462 oldunits = ["pt", "cm", "in", "text%", "col%"]
463
464 def get_length(lines, name, start, end):
465     i = find_token(lines, name, start, end)
466     if i == -1:
467         return ""
468     x = string.split(lines[i])
469     return x[2]+oldunits[int(x[1])]
470
471
472 def write_attribute(x, token, value):
473     if value != "":
474         x.append("\t"+token+" "+value)
475
476
477 def remove_figinset(file):
478     lines = file.body
479     i = 0
480     while 1:
481         i = find_token(lines, "\\begin_inset Figure", i)
482         if i == -1:
483             break
484         j = find_end_of_inset(lines, i)
485
486         if ( len(string.split(lines[i])) > 2 ):
487             lyxwidth = string.split(lines[i])[3]+"pt"
488             lyxheight = string.split(lines[i])[4]+"pt"
489         else:
490             lyxwidth = ""
491             lyxheight = ""
492
493         filename = get_value(lines, "file", i+1, j)
494
495         width = get_length(lines, "width", i+1, j)
496         # what does width=5 mean ?
497         height = get_length(lines, "height", i+1, j)
498         rotateAngle = get_value(lines, "angle", i+1, j)
499         if width == "" and height == "":
500             size_type = "0"
501         else:
502             size_type = "1"
503
504         flags = get_value(lines, "flags", i+1, j)
505         x = int(flags)%4
506         if x == 1:
507             display = "monochrome"
508         elif x == 2:
509             display = "gray"
510         else:
511             display = "color"
512
513         subcaptionText = ""
514         subcaptionLine = find_token(lines, "subcaption", i+1, j)
515         if subcaptionLine != -1:
516             subcaptionText = lines[subcaptionLine][11:]
517             if subcaptionText != "":
518                 subcaptionText = '"'+subcaptionText+'"'
519
520         k = find_token(lines, "subfigure", i+1,j)
521         if k == -1:
522             subcaption = 0
523         else:
524             subcaption = 1
525
526         new = ["\\begin_inset Graphics FormatVersion 1"]
527         write_attribute(new, "filename", filename)
528         write_attribute(new, "display", display)
529         if subcaption:
530             new.append("\tsubcaption")
531         write_attribute(new, "subcaptionText", subcaptionText)
532         write_attribute(new, "size_type", size_type)
533         write_attribute(new, "width", width)
534         write_attribute(new, "height", height)
535         if rotateAngle != "":
536             new.append("\trotate")
537             write_attribute(new, "rotateAngle", rotateAngle)
538         write_attribute(new, "rotateOrigin", "leftBaseline")
539         write_attribute(new, "lyxsize_type", "1")
540         write_attribute(new, "lyxwidth", lyxwidth)
541         write_attribute(new, "lyxheight", lyxheight)
542         new = new + ["\\end_inset"]
543         lines[i:j+1] = new
544
545
546 ##
547 # Convert tabular format 2 to 3
548 #
549 attr_re = re.compile(r' \w*="(false|0|)"')
550 line_re = re.compile(r'<(features|column|row|cell)')
551
552 def update_tabular(file):
553     regexp = re.compile(r'^\\begin_inset\s+Tabular')
554     lines = file.body
555     i = 0
556     while 1:
557         i = find_re(lines, regexp, i)
558         if i == -1:
559             break
560
561         for k in get_tabular_lines(lines, i):
562             if check_token(lines[k], "<lyxtabular"):
563                 lines[k] = string.replace(lines[k], 'version="2"', 'version="3"')
564             elif check_token(lines[k], "<column"):
565                 lines[k] = string.replace(lines[k], 'width=""', 'width="0pt"')
566
567             if line_re.match(lines[k]):
568                 lines[k] = re.sub(attr_re, "", lines[k])
569
570         i = i+1
571
572
573 ##
574 # Convert tabular format 2 to 3
575 #
576 # compatibility read for old longtable options. Now we can make any
577 # row part of the header/footer type we want before it was strict
578 # sequential from the first row down (as LaTeX does it!). So now when
579 # we find a header/footer line we have to go up the rows and set it
580 # on all preceding rows till the first or one with already a h/f option
581 # set. If we find a firstheader on the same line as a header or a
582 # lastfooter on the same line as a footer then this should be set empty.
583 # (Jug 20011220)
584
585 # just for compatibility with old python versions
586 # python >= 2.3 has real booleans (False and True)
587 false = 0
588 true = 1
589
590 # simple data structure to deal with long table info
591 class row:
592     def __init__(self):
593         self.endhead = false                # header row
594         self.endfirsthead = false        # first header row
595         self.endfoot = false                # footer row
596         self.endlastfoot = false        # last footer row
597
598
599 def haveLTFoot(row_info):
600     for row_ in row_info:
601         if row_.endfoot:
602             return true
603     return false
604
605
606 def setHeaderFooterRows(hr, fhr, fr, lfr, rows_, row_info):
607     endfirsthead_empty = false
608     endlastfoot_empty = false
609     # set header info
610     while (hr > 0):
611         hr = hr - 1
612         row_info[hr].endhead = true
613
614     # set firstheader info
615     if fhr and fhr < rows_:
616         if row_info[fhr].endhead:
617             while fhr > 0:
618                 fhr = fhr - 1
619                 row_info[fhr].endfirsthead = true
620                 row_info[fhr].endhead = false
621         elif row_info[fhr - 1].endhead:
622             endfirsthead_empty = true
623         else:
624             while fhr > 0 and not row_info[fhr - 1].endhead:
625                 fhr = fhr - 1
626                 row_info[fhr].endfirsthead = true
627
628     # set footer info
629     if fr and fr < rows_:
630         if row_info[fr].endhead and row_info[fr - 1].endhead:
631             while fr > 0 and not row_info[fr - 1].endhead:
632                 fr = fr - 1
633                 row_info[fr].endfoot = true
634                 row_info[fr].endhead = false
635         elif row_info[fr].endfirsthead and row_info[fr - 1].endfirsthead:
636             while fr > 0 and not row_info[fr - 1].endfirsthead:
637                 fr = fr - 1
638                 row_info[fr].endfoot = true
639                 row_info[fr].endfirsthead = false
640         elif not row_info[fr - 1].endhead and not row_info[fr - 1].endfirsthead:
641             while fr > 0 and not row_info[fr - 1].endhead and not row_info[fr - 1].endfirsthead:
642                 fr = fr - 1
643                 row_info[fr].endfoot = true
644
645     # set lastfooter info
646     if lfr and lfr < rows_:
647         if row_info[lfr].endhead and row_info[lfr - 1].endhead:
648             while lfr > 0 and not row_info[lfr - 1].endhead:
649                 lfr = lfr - 1
650                 row_info[lfr].endlastfoot = true
651                 row_info[lfr].endhead = false
652         elif row_info[lfr].endfirsthead and row_info[lfr - 1].endfirsthead:
653             while lfr > 0 and not row_info[lfr - 1].endfirsthead:
654                 lfr = lfr - 1
655                 row_info[lfr].endlastfoot = true
656                 row_info[lfr].endfirsthead = false
657         elif row_info[lfr].endfoot and row_info[lfr - 1].endfoot:
658             while lfr > 0 and not row_info[lfr - 1].endfoot:
659                 lfr = lfr - 1
660                 row_info[lfr].endlastfoot = true
661                 row_info[lfr].endfoot = false
662         elif not row_info[fr - 1].endhead and not row_info[fr - 1].endfirsthead and not row_info[fr - 1].endfoot:
663             while lfr > 0 and not row_info[lfr - 1].endhead and not row_info[lfr - 1].endfirsthead and not row_info[lfr - 1].endfoot:
664                 lfr = lfr - 1
665                 row_info[lfr].endlastfoot = true
666         elif haveLTFoot(row_info):
667             endlastfoot_empty = true
668
669     return endfirsthead_empty, endlastfoot_empty
670
671
672 def insert_attribute(lines, i, attribute):
673     last = string.find(lines[i],'>')
674     lines[i] = lines[i][:last] + ' ' + attribute + lines[i][last:]
675
676
677 rows_re = re.compile(r'rows="(\d*)"')
678 longtable_re = re.compile(r'islongtable="(\w)"')
679 ltvalues_re = re.compile(r'endhead="(-?\d*)" endfirsthead="(-?\d*)" endfoot="(-?\d*)" endlastfoot="(-?\d*)"')
680 lt_features_re = re.compile(r'(endhead="-?\d*" endfirsthead="-?\d*" endfoot="-?\d*" endlastfoot="-?\d*")')
681 def update_longtables(file):
682     regexp = re.compile(r'^\\begin_inset\s+Tabular')
683     body = file.body
684     i = 0
685     while 1:
686         i = find_re(body, regexp, i)
687         if i == -1:
688             break
689         i = i + 1
690         i = find_token(body, "<lyxtabular", i)
691         if i == -1:
692             break
693
694         # get number of rows in the table
695         rows = int(rows_re.search(body[i]).group(1))
696
697         i = i + 1
698         i = find_token(body, '<features', i)
699         if i == -1:
700             break
701
702         # is this a longtable?
703         longtable = longtable_re.search(body[i])
704
705         if not longtable:
706             # islongtable is missing add it
707             body[i] = body[i][:10] + 'islongtable="false" ' + body[i][10:]
708
709         if not longtable or longtable.group(1) != "true":
710             # remove longtable elements from features
711             features = lt_features_re.search(body[i])
712             if features:
713                 body[i] = string.replace(body[i], features.group(1), "")
714             continue
715
716         row_info = row() * rows
717         res = ltvalues_re.search(body[i])
718         if not res:
719             continue
720
721         endfirsthead_empty, endlastfoot_empty = setHeaderFooterRows(res.group(1), res.group(2), res.group(3), res.group(4), rows, row_info)
722
723         if endfirsthead_empty:
724             insert_attribute(body, i, 'firstHeadEmpty="true"')
725
726         if endfirsthead_empty:
727             insert_attribute(body, i, 'lastFootEmpty="true"')
728
729         i = i + 1
730         for j in range(rows):
731             i = find_token(body, '<row', i)
732
733             self.endfoot = false                # footer row
734             self.endlastfoot = false        # last footer row
735             if row_info[j].endhead:
736                 insert_attribute(body, i, 'endhead="true"')
737
738             if row_info[j].endfirsthead:
739                 insert_attribute(body, i, 'endfirsthead="true"')
740
741             if row_info[j].endfoot:
742                 insert_attribute(body, i, 'endfoot="true"')
743
744             if row_info[j].endlastfoot:
745                 insert_attribute(body, i, 'endlastfoot="true"')
746
747             i = i + 1
748
749
750 # Figure insert are hidden feature of lyx 1.1.6. This might be removed in the future.
751 def fix_oldfloatinset(file):
752     lines = file.body
753     i = 0
754     while 1:
755         i = find_token(lines, "\\begin_inset Float ", i)
756         if i == -1:
757             break
758         j = find_token(lines, "collapsed", i)
759         if j != -1:
760             lines[j:j] = ["wide false"]
761         i = i+1
762
763
764 def change_listof(file):
765     lines = file.body
766     i = 0
767     while 1:
768         i = find_token(lines, "\\begin_inset LatexCommand \\listof", i)
769         if i == -1:
770             break
771         type = re.search(r"listof(\w*)", lines[i]).group(1)[:-1]
772         lines[i] = "\\begin_inset FloatList "+type
773         i = i+1
774
775
776 def change_infoinset(file):
777     lines = file.body
778     i = 0
779     while 1:
780         i = find_token(lines, "\\begin_inset Info", i)
781         if i == -1:
782             break
783         txt = string.lstrip(lines[i][18:])
784         new = ["\\begin_inset Note", "collapsed true", ""]
785         j = find_token(lines, "\\end_inset", i)
786         if j == -1:
787             break
788
789         note_lines = lines[i+1:j]
790         if len(txt) > 0:
791             note_lines = [txt]+note_lines
792
793         for line in note_lines:
794             new = new + ['\layout %s' % file.default_layout, ""]
795             tmp = string.split(line, '\\')
796             new = new + [tmp[0]]
797             for x in tmp[1:]:
798                 new = new + ["\\backslash ", x]
799         lines[i:j] = new
800         i = i+5
801
802
803 def change_header(file):
804     lines = file.header
805     i = find_token(lines, "\\use_amsmath", 0)
806     if i == -1:
807         return
808     lines[i+1:i+1] = ["\\use_natbib 0",
809                       "\use_numerical_citations 0"]
810
811
812 convert = [[220, [change_header, change_listof, fix_oldfloatinset,
813                   update_tabular, update_longtables, remove_pextra,
814                   remove_oldfloat, remove_figinset, remove_oldertinset,
815                   remove_oldert, combine_ert, change_infoinset]]]
816 revert  = []
817
818
819 if __name__ == "__main__":
820     pass