lyx_mirror/lib/lyx2lyx/lyxrevert_225.py
Alfredo Braunstein 20198582f1 Georg Baum's patch
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8384 a592a061-630c-0410-9148-cb99ea01b6c8
2004-02-02 21:39:17 +00:00

304 lines
9.4 KiB
Python

# This file is part of lyx2lyx
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2003 José Matos <jamatos@fep.up.pt>
# Copyright (C) 2003 Georg Baum <Georg.Baum@post.rwth-aachen.de>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import re
from parser_tools import find_token, find_end_of_inset, get_next_paragraph, \
get_paragraph, get_value, del_token, is_nonempty_line
from string import find, replace, split
import sys
def rm_end_layout(lines):
i = 0
while 1:
i = find_token(lines, '\\end_layout', i)
if i == -1:
return
del lines[i]
def begin_layout2layout(lines):
i = 0
while 1:
i = find_token(lines, '\\begin_layout', i)
if i == -1:
return
lines[i] = replace(lines[i], '\\begin_layout', '\\layout')
i = i + 1
def table_valignment_middle(lines, start, end):
for i in range(start, end):
if re.search('^<(column|cell) .*valignment="middle".*>$', lines[i]):
lines[i] = replace(lines[i], 'valignment="middle"', 'valignment="center"')
def valignment_middle(lines):
i = 0
while 1:
i = find_token(lines, '\\begin_inset Tabular', i)
if i == -1:
return
j = find_end_of_inset(lines, i + 1)
if j == -1:
#this should not happen
valignment_middle(lines, i + 1, len(lines))
return
valignment_middle(lines, i + 1, j)
i = j + 1
def end_document(lines):
i = find_token(lines, "\\end_document", 0)
if i == -1:
lines.append("\\the_end")
return
lines[i] = "\\the_end"
# Convert backslashes into valid ERT code, append the converted text to
# lines[i] and return the (maybe incremented) line index i
def convert_ertbackslash(lines, i, ert):
for c in ert:
if c == '\\':
lines[i] = lines[i] + '\\backslash '
lines.insert(i, '')
i = i + 1
else:
lines[i] = lines[i] + c
return i
def convert_vspace(header, lines):
# Get default spaceamount
i = find_token(header, '\\defskip', 0)
if i == -1:
defskipamount = 'medskip'
else:
defskipamount = split(header[i])[1]
# Convert the insets
i = 0
while 1:
i = find_token(lines, '\\begin_inset VSpace', i)
if i == -1:
return
spaceamount = split(lines[i])[2]
# Are we at the beginning or end of a paragraph?
paragraph_start = 1
start = get_paragraph(lines, i) + 1
for k in range(start, i):
if is_nonempty_line(lines[k]):
paragraph_start = 0
break
paragraph_end = 1
j = find_end_of_inset(lines, i)
if j == -1:
sys.stderr.write("Malformed lyx file: Missing '\\end_inset'\n")
i = i + 1
continue
end = get_next_paragraph(lines, i)
for k in range(j + 1, end):
if is_nonempty_line(lines[k]):
paragraph_end = 0
break
# Convert to paragraph formatting if we are at the beginning or end
# of a paragraph and the resulting paragraph would not be empty
if ((paragraph_start and not paragraph_end) or
(paragraph_end and not paragraph_start)):
# The order is important: del and insert invalidate some indices
del lines[j]
del lines[i]
if paragraph_start:
lines.insert(start, '\\added_space_top ' + spaceamount + ' ')
else:
lines.insert(start, '\\added_space_bottom ' + spaceamount + ' ')
continue
# Convert to ERT
lines[i:i+1] = ['\\begin_inset ERT', 'status Collapsed', '',
'\\layout Standard', '', '\\backslash ']
i = i + 6
if spaceamount[-1] == '*':
spaceamount = spaceamount[:-1]
keep = 1
else:
keep = 0
# Replace defskip by the actual value
if spaceamount == 'defskip':
spaceamount = defskipamount
# LaTeX does not know \\smallskip* etc
if keep:
if spaceamount == 'smallskip':
spaceamount = '\\smallskipamount'
elif spaceamount == 'medskip':
spaceamount = '\\medskipamount'
elif spaceamount == 'bigskip':
spaceamount = '\\bigskipamount'
elif spaceamount == 'vfill':
spaceamount = '\\fill'
# Finally output the LaTeX code
if (spaceamount == 'smallskip' or spaceamount == 'medskip' or
spaceamount == 'bigskip' or spaceamount == 'vfill'):
lines.insert(i, spaceamount)
else :
if keep:
lines.insert(i, 'vspace*{')
else:
lines.insert(i, 'vspace{')
i = convert_ertbackslash(lines, i, spaceamount)
lines[i] = lines[i] + '}'
i = i + 1
# Convert a LyX length into valid ERT code and append it to lines[i]
# Return the (maybe incremented) line index i
def convert_ertlen(lines, i, len, special):
units = {"text%":"\\textwidth", "col%":"\\columnwidth",
"page%":"\\pagewidth", "line%":"\\linewidth",
"theight%":"\\textheight", "pheight%":"\\pageheight"}
# Convert special lengths
if special != 'none':
len = '%f\\' % len2value(len) + special
# Convert LyX units to LaTeX units
for unit in units.keys():
if find(len, unit) != -1:
len = '%f' % (len2value(len) / 100) + units[unit]
break
# Convert backslashes and insert the converted length into lines
return convert_ertbackslash(lines, i, len)
# Return the value of len without the unit in numerical form
def len2value(len):
result = re.search('([+-]?[0-9.]+)', len)
if result:
return float(result.group(1))
# No number means 1.0
return 1.0
def convert_frameless_box(lines):
pos = ['t', 'c', 'b']
inner_pos = ['c', 't', 'b', 's']
i = 0
while 1:
i = find_token(lines, '\\begin_inset Frameless', i)
if i == -1:
return
j = find_end_of_inset(lines, i)
if j == -1:
sys.stderr.write("Malformed lyx file: Missing '\\end_inset'\n")
i = i + 1
continue
del lines[i]
# Gather parameters
params = {'position':'0', 'hor_pos':'c', 'has_inner_box':'1',
'inner_pos':'1', 'use_parbox':'0', 'width':'100col%',
'special':'none', 'height':'1in',
'height_special':'totalheight', 'collapsed':'false'}
for key in params.keys():
value = replace(get_value(lines, key, i, j), '"', '')
if value != "":
if key == 'position':
# convert new to old position: 'position "t"' -> 0
value = find_token(pos, value, 0)
if value != -1:
params[key] = value
elif key == 'inner_pos':
# convert inner position
value = find_token(inner_pos, value, 0)
if value != -1:
params[key] = value
else:
params[key] = value
j = del_token(lines, key, i, j)
i = i + 1
# Convert to minipage or ERT?
# Note that the inner_position and height parameters of a minipage
# inset are ignored and not accessible for the user, although they
# are present in the file format and correctly read in and written.
# Therefore we convert to ERT if they do not have their LaTeX
# defaults. These are:
# - the value of "position" for "inner_pos"
# - "\totalheight" for "height"
if (params['use_parbox'] != '0' or
params['has_inner_box'] != '1' or
params['special'] != 'none' or
inner_pos[params['inner_pos']] != pos[params['position']] or
params['height_special'] != 'totalheight' or
len2value(params['height']) != 1.0):
# Convert to ERT
if params['collapsed'] == 'true':
params['collapsed'] = 'Collapsed'
else:
params['collapsed'] = 'Open'
lines[i : i] = ['\\begin_inset ERT', 'status ' + params['collapsed'],
'', '\\layout Standard', '', '\\backslash ']
i = i + 6
if params['use_parbox'] == '1':
lines.insert(i, 'parbox')
else:
lines.insert(i, 'begin{minipage}')
lines[i] = lines[i] + '[' + pos[params['position']] + ']['
i = convert_ertlen(lines, i, params['height'], params['height_special'])
lines[i] = lines[i] + '][' + inner_pos[params['inner_pos']] + ']{'
i = convert_ertlen(lines, i, params['width'], params['special'])
lines[i] = lines[i] + '}{'
i = i + 1
lines[i:i] = ['', '\\end_inset ']
i = i + 2
j = find_end_of_inset(lines, i)
if j == -1:
sys.stderr.write("Malformed lyx file: Missing '\\end_inset'\n")
break
lines[j-1:j-1] += ['\\begin_inset ERT', 'status ' + params['collapsed'],
'', '\\layout Standard', '']
j = j + 4
if params['use_parbox'] == '1':
lines.insert(j, '}')
else:
lines[j:j] = ['\\backslash ', 'end{minipage}']
else:
# Convert to minipage
lines[i:i] = ['\\begin_inset Minipage',
'position %d' % params['position'],
'inner_position %d' % params['inner_pos'],
'height "' + params['height'] + '"',
'width "' + params['width'] + '"',
'collapsed ' + params['collapsed']]
i = i + 6
def convert(header, body):
rm_end_layout(body)
begin_layout2layout(body)
end_document(body)
valignment_middle(body)
convert_vspace(header, body)
convert_frameless_box(body)
if __name__ == "__main__":
pass