# -*- coding: utf-8 -*-
# This file is part of lyx2lyx
# -*- coding: utf-8 -*-
-# Copyright (C) 2011 The LyX team
+# Copyright (C) 2015 The LyX team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# find_token_backwards, is_in_inset, get_value, get_quoted_value, \
# del_token, check_token, get_option_value
-from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, lyx2latex#, \
+from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, lyx2latex, \
+ length_in_bp#, \
# insert_to_preamble, latex_length, revert_flex_inset, \
# revert_font_attrs, hex2ratio, str2bool
find_end_of_inset, find_end_of_layout, find_nonempty_line, \
get_containing_layout, get_value, check_token
+####################################################################
+# Private helper functions
+
+def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt, nolastopt):
+ '''
+ Reverts an InsetArgument to TeX-code
+ usage:
+ revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt, notLastOpt)
+ LineOfBegin is the line of the \begin_layout or \begin_inset statement
+ LineOfEnd is the line of the \end_layout or \end_inset statement, if "0" is given, the end of the file is used instead
+ StartArgument is the number of the first argument that needs to be converted
+ EndArgument is the number of the last argument that needs to be converted or the last defined one
+ isEnvironment must be true, if the layout is for a LaTeX environment
+ isOpt must be true, if the argument is an optional one
+ notLastOpt must be true if the argument is mandatory and followed by optional ones
+ '''
+ lineArg = 0
+ wasOpt = False
+ while lineArg != -1 and n < nmax + 1:
+ lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
+ if lineArg > endline and endline != 0:
+ return wasOpt
+ if lineArg != -1:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
+ # we have to assure that no other inset is in the Argument
+ beginInset = find_token(document.body, "\\begin_inset", beginPlain)
+ endInset = find_token(document.body, "\\end_inset", beginPlain)
+ k = beginPlain + 1
+ l = k
+ while beginInset < endInset and beginInset != -1:
+ beginInset = find_token(document.body, "\\begin_inset", k)
+ endInset = find_token(document.body, "\\end_inset", l)
+ k = beginInset + 1
+ l = endInset + 1
+ if environment == False:
+ if opt == False:
+ if nolastopt == False:
+ document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
+ else:
+ document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
+ del(document.body[lineArg : beginPlain + 1])
+ wasOpt = False
+ else:
+ document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
+ document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
+ wasOpt = True
+ else:
+ if opt == False:
+ document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
+ document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
+ wasOpt = False
+ else:
+ document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
+ document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
+ wasOpt = True
+ n += 1
+ return wasOpt
+
+
###############################################################################
###
### Conversion and reversion routines
j = j + 1
-def revert_use_package(document, pkg, commands, oldauto):
+def revert_use_package(document, pkg, commands, oldauto, supported):
# oldauto defines how the version we are reverting to behaves:
# if it is true, the old version uses the package automatically.
# if it is false, the old version never uses the package.
+ # If "supported" is true, the target version also supports this
+ # package natively.
regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
- i = find_re(document.header, regexp, 0)
+ p = find_re(document.header, regexp, 0)
value = "1" # default is auto
- if i != -1:
- value = get_value(document.header, "\\use_package" , i).split()[1]
- del document.header[i]
- if value == "2": # on
+ if p != -1:
+ value = get_value(document.header, "\\use_package" , p).split()[1]
+ if not supported:
+ del document.header[p]
+ if value == "2" and not supported: # on
add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
elif value == "1" and not oldauto: # auto
i = 0
code = "\n".join(document.body[i:j])
for c in commands:
if code.find("\\%s" % c) != -1:
- add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
+ if supported:
+ document.header[p] = "\\use_package " + pkg + " 2"
+ else:
+ add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
return
i = j
def revert_xarrow(document):
"remove use_package mathtools"
- revert_use_package(document, "mathtools", mathtools_commands, False)
+ revert_use_package(document, "mathtools", mathtools_commands, False, True)
def revert_beamer_lemma(document):
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
endPlain = find_end_of_layout(document.body, beginPlain)
content = lyx2latex(document, document.body[beginPlain : endPlain])
- document.warning("content: %s" % content)
document.body[i:j + 1] = ["{", "", content, "", "}"]
# no need to reset i
i = find_token(document.body, "height_special", i)
if i == -1:
return
- document.body.insert(i + 1, 'thickness "0.4pt"\nseparation "3pt"\nshadowsize "4pt"')
- i = i + 1
+ document.body[i+1:i+1] = ['thickness "0.4pt"', 'separation "3pt"', 'shadowsize "4pt"']
+ i = i + 4
def revert_BoxFeatures(document):
if document.dir == "":
origin = "stdin"
else:
- origin = document.dir.replace('\\', '/')
+ relpath = ''
+ if document.systemlyxdir and document.systemlyxdir != '':
+ try:
+ if os.path.isabs(document.dir):
+ absdir = os.path.normpath(document.dir)
+ else:
+ absdir = os.path.normpath(os.path.abspath(document.dir))
+ if os.path.isabs(document.systemlyxdir):
+ abssys = os.path.normpath(document.systemlyxdir)
+ else:
+ abssys = os.path.normpath(os.path.abspath(document.systemlyxdir))
+ relpath = os.path.relpath(absdir, abssys)
+ if relpath.find('..') == 0:
+ relpath = ''
+ except:
+ relpath = ''
+ if relpath == '':
+ origin = document.dir.replace('\\', '/') + '/'
+ else:
+ origin = os.path.join("/systemlyxdir", relpath).replace('\\', '/') + '/'
+ if os.name != 'nt':
+ origin = unicode(origin, sys.getfilesystemencoding())
document.header[i:i] = ["\\origin " + origin]
"pink", "purple", "teal", "violet"]
def revert_textcolor(document):
- " revert new \texcolor colors to TeX code "
+ " revert new \\textcolor colors to TeX code "
i = 0
j = 0
xcolor = False
- add_to_preamble(document, ["\\@ifundefined{rangeHsb}{\\usepackage{xcolor}}"])
while True:
i = find_token(document.body, "\\color ", i)
if i == -1:
# register that xcolor must be loaded in the preamble
if xcolor == False:
xcolor = True
- add_to_preamble(document, ["\\@ifundefined{rangeHsb}{\usepackage{xcolor}}"])
+ add_to_preamble(document, ["\\@ifundefined{rangeHsb}{\usepackage{xcolor}}{}"])
# find the next \\color and/or the next \\end_layout
j = find_token(document.body, "\\color", i + 1)
k = find_token(document.body, "\\end_layout", i + 1)
i = 0
while True:
- i = find_token(document.body, "height_special", i)
+ i = find_token(document.body, "shadowsize", i)
if i == -1:
return
- document.body.insert(i + 2, 'framecolor "black"\nbackgroundcolor "none"')
- i = i + 2
+ document.body[i+1:i+1] = ['framecolor "black"', 'backgroundcolor "none"']
+ i = i + 3
def revert_colorbox(document):
" outputs color settings for boxes as TeX code "
- i = 0
+ binset = 0
defaultframecolor = "black"
- defaultbackcolor = "white"
+ defaultbackcolor = "none"
while True:
- i = find_token(document.body, "framecolor", i)
- if i == -1:
+ binset = find_token(document.body, "\\begin_inset Box", binset)
+ if binset == -1:
return
- # read out the values
- beg = document.body[i].find('"');
- end = document.body[i].rfind('"');
- framecolor = document.body[i][beg+1:end];
- beg = document.body[i+1].find('"');
- end = document.body[i+1].rfind('"');
- backcolor = document.body[i+1][beg+1:end];
- # delete the specification
- del document.body[i:i+2]
+
+ einset = find_end_of_inset(document.body, binset)
+ if einset == -1:
+ document.warning("Malformed LyX document: Can't find end of box inset!")
+ binset += 1
+ continue
+
+ blay = find_token(document.body, "\\begin_layout", binset, einset)
+ if blay == -1:
+ document.warning("Malformed LyX document: Can't find start of layout!")
+ binset = einset
+ continue
+
+ # doing it this way, we make sure only to find a framecolor option
+ frame = find_token(document.body, "framecolor", binset, blay)
+ if frame == -1:
+ binset = einset
+ continue
+
+ beg = document.body[frame].find('"')
+ end = document.body[frame].rfind('"')
+ framecolor = document.body[frame][beg + 1 : end]
+
+ # this should be on the next line
+ bgcolor = frame + 1
+ beg = document.body[bgcolor].find('"')
+ end = document.body[bgcolor].rfind('"')
+ backcolor = document.body[bgcolor][beg + 1 : end]
+
+ # delete those bits
+ del document.body[frame : frame + 2]
+ # adjust end of inset
+ einset -= 2
+
+ if document.body[binset] == "\\begin_inset Box Boxed" and \
+ framecolor != defaultframecolor:
+ document.body[binset] = "\\begin_inset Box Frameless"
+
# output TeX code
# first output the closing brace
- if framecolor != defaultframecolor or backcolor != defaultbackcolor:
- document.body[i + 9 : i + 9] = put_cmd_in_ert("}")
- # now output the box commands
- if framecolor != defaultframecolor or backcolor != defaultbackcolor:
- document.body[i - 14 : i - 14] = put_cmd_in_ert("{")
- if framecolor != defaultframecolor:
- document.body[i - 9 : i - 8] = ["\\backslash fboxcolor{" + framecolor + "}{" + backcolor + "}{"]
- if backcolor != defaultbackcolor and framecolor == defaultframecolor:
- document.body[i - 9 : i - 8] = ["\\backslash colorbox{" + backcolor + "}{"]
- i = i + 11
+ if framecolor == defaultframecolor and backcolor == defaultbackcolor:
+ # nothing needed
+ pass
+ else:
+ # we also neeed to load xcolor in the preamble but only once
+ add_to_preamble(document, ["\\@ifundefined{rangeHsb}{\usepackage{xcolor}}{}"])
+ document.body[einset + 1 : einset + 1] = put_cmd_in_ert("}")
+ if framecolor != defaultframecolor:
+ document.body[binset:binset] = put_cmd_in_ert("\\fcolorbox{" + framecolor + "}{" + backcolor + "}{")
+ else:
+ document.body[binset:binset] = put_cmd_in_ert("\\colorbox{" + backcolor + "}{")
+
+ binset = einset
+
+
+def revert_mathmulticol(document):
+ " Convert formulas to ERT if they contain multicolumns "
+
+ i = 0
+ while True:
+ i = find_token(document.body, '\\begin_inset Formula', i)
+ if i == -1:
+ return
+ j = find_end_of_inset(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
+ i += 1
+ continue
+ lines = document.body[i:j]
+ lines[0] = lines[0].replace('\\begin_inset Formula', '').lstrip()
+ code = "\n".join(lines)
+ converted = False
+ k = 0
+ n = 0
+ while n >= 0:
+ n = code.find("\\multicolumn", k)
+ # no need to convert degenerated multicolumn cells,
+ # they work in old LyX versions as "math ERT"
+ if n != -1 and code.find("\\multicolumn{1}", k) != n:
+ ert = put_cmd_in_ert(code)
+ document.body[i:j+1] = ert
+ converted = True
+ break
+ else:
+ k = n + 12
+ if converted:
+ i = find_end_of_inset(document.body, i)
+ else:
+ i = j
+
+
+def revert_jss(document):
+ " Reverts JSS In_Preamble commands to ERT in preamble "
+
+ if document.textclass != "jss":
+ return
+
+ h = 0
+ m = 0
+ j = 0
+ k = 0
+ n = 0
+ while True:
+ # at first revert the inset layouts because they can be part of the In_Preamble layouts
+ while m != -1 or j != -1 or h != -1 or k != -1 or n != -1:
+ # \pkg
+ if h != -1:
+ h = find_token(document.body, "\\begin_inset Flex Pkg", h)
+ if h != -1:
+ endh = find_end_of_inset(document.body, h)
+ document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
+ document.body[h : h + 4] = put_cmd_in_ert("\\pkg{")
+ h = h + 5
+ # \proglang
+ if m != -1:
+ m = find_token(document.body, "\\begin_inset Flex Proglang", m)
+ if m != -1:
+ endm = find_end_of_inset(document.body, m)
+ document.body[endm - 2 : endm + 1] = put_cmd_in_ert("}")
+ document.body[m : m + 4] = put_cmd_in_ert("\\proglang{")
+ m = m + 5
+ # \code
+ if j != -1:
+ j = find_token(document.body, "\\begin_inset Flex Code", j)
+ if j != -1:
+ # assure that we are not in a Code Chunk inset
+ if document.body[j][-1] == "e":
+ endj = find_end_of_inset(document.body, j)
+ document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
+ document.body[j : j + 4] = put_cmd_in_ert("\\code{")
+ j = j + 5
+ else:
+ j = j + 1
+ # \email
+ if k != -1:
+ k = find_token(document.body, "\\begin_inset Flex E-mail", k)
+ if k != -1:
+ endk = find_end_of_inset(document.body, k)
+ document.body[endk - 2 : endk + 1] = put_cmd_in_ert("}")
+ document.body[k : k + 4] = put_cmd_in_ert("\\email{")
+ k = k + 5
+ # \url
+ if n != -1:
+ n = find_token(document.body, "\\begin_inset Flex URL", n)
+ if n != -1:
+ endn = find_end_of_inset(document.body, n)
+ document.body[endn - 2 : endn + 1] = put_cmd_in_ert("}")
+ document.body[n : n + 4] = put_cmd_in_ert("\\url{")
+ n = n + 5
+ # now revert the In_Preamble layouts
+ # \title
+ i = find_token(document.body, "\\begin_layout Title", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Title layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\title{" + content + "}"])
+ del document.body[i:j + 1]
+ # \author
+ i = find_token(document.body, "\\begin_layout Author", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Author layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\author{" + content + "}"])
+ del document.body[i:j + 1]
+ # \Plainauthor
+ i = find_token(document.body, "\\begin_layout Plain Author", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Plain Author layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\Plainauthor{" + content + "}"])
+ del document.body[i:j + 1]
+ # \Plaintitle
+ i = find_token(document.body, "\\begin_layout Plain Title", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Plain Title layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\Plaintitle{" + content + "}"])
+ del document.body[i:j + 1]
+ # \Shorttitle
+ i = find_token(document.body, "\\begin_layout Short Title", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Short Title layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\Shorttitle{" + content + "}"])
+ del document.body[i:j + 1]
+ # \Abstract
+ i = find_token(document.body, "\\begin_layout Abstract", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Abstract layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\Abstract{" + content + "}"])
+ del document.body[i:j + 1]
+ # \Keywords
+ i = find_token(document.body, "\\begin_layout Keywords", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Keywords layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\Keywords{" + content + "}"])
+ del document.body[i:j + 1]
+ # \Plainkeywords
+ i = find_token(document.body, "\\begin_layout Plain Keywords", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Plain Keywords layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\Plainkeywords{" + content + "}"])
+ del document.body[i:j + 1]
+ # \Address
+ i = find_token(document.body, "\\begin_layout Address", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Address layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\Address{" + content + "}"])
+ del document.body[i:j + 1]
+ # finally handle the code layouts
+ h = 0
+ m = 0
+ j = 0
+ k = 0
+ while m != -1 or j != -1 or h != -1 or k != -1:
+ # \CodeChunk
+ if h != -1:
+ h = find_token(document.body, "\\begin_inset Flex Code Chunk", h)
+ if h != -1:
+ endh = find_end_of_inset(document.body, h)
+ document.body[endh + 1 : endh] = ["\\end_layout"]
+ document.body[endh : endh + 1] = put_cmd_in_ert("\\end{CodeChunk}")
+ document.body[h : h + 3] = put_cmd_in_ert("\\begin{CodeChunk}")
+ document.body[h - 1 : h] = ["\\begin_layout Standard"]
+ h = h + 1
+ # \CodeInput
+ if j != -1:
+ j = find_token(document.body, "\\begin_layout Code Input", j)
+ if j != -1:
+ endj = find_end_of_layout(document.body, j)
+ document.body[endj : endj + 1] = ["\\end_layout", "", "\\begin_layout Standard"]
+ document.body[endj + 3 : endj + 4] = put_cmd_in_ert("\\end{CodeInput}")
+ document.body[endj + 13 : endj + 13] = ["\\end_layout", "", "\\begin_layout Standard"]
+ document.body[j + 1 : j] = ["\\end_layout", "", "\\begin_layout Standard"]
+ document.body[j : j + 1] = put_cmd_in_ert("\\begin{CodeInput}")
+ j = j + 1
+ # \CodeOutput
+ if k != -1:
+ k = find_token(document.body, "\\begin_layout Code Output", k)
+ if k != -1:
+ endk = find_end_of_layout(document.body, k)
+ document.body[endk : endk + 1] = ["\\end_layout", "", "\\begin_layout Standard"]
+ document.body[endk + 3 : endk + 4] = put_cmd_in_ert("\\end{CodeOutput}")
+ document.body[endk + 13 : endk + 13] = ["\\end_layout", "", "\\begin_layout Standard"]
+ document.body[k + 1 : k] = ["\\end_layout", "", "\\begin_layout Standard"]
+ document.body[k : k + 1] = put_cmd_in_ert("\\begin{CodeOutput}")
+ k = k + 1
+ # \Code
+ if m != -1:
+ m = find_token(document.body, "\\begin_layout Code", m)
+ if m != -1:
+ endm = find_end_of_layout(document.body, m)
+ document.body[endm : endm + 1] = ["\\end_layout", "", "\\begin_layout Standard"]
+ document.body[endm + 3 : endm + 4] = put_cmd_in_ert("\\end{Code}")
+ document.body[endm + 13 : endm + 13] = ["\\end_layout", "", "\\begin_layout Standard"]
+ document.body[m + 1 : m] = ["\\end_layout", "", "\\begin_layout Standard"]
+ document.body[m : m + 1] = put_cmd_in_ert("\\begin{Code}")
+ m = m + 1
+
+
+def convert_subref(document):
+ " converts sub: ref prefixes to subref: "
+
+ # 1) label insets
+ rx = re.compile(r'^name \"sub:(.+)$')
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset CommandInset label", i)
+ if i == -1:
+ break
+ j = find_end_of_inset(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Label inset at line " + str(i))
+ i += 1
+ continue
+
+ for p in range(i, j):
+ m = rx.match(document.body[p])
+ if m:
+ label = m.group(1)
+ document.body[p] = "name \"subsec:" + label
+ i += 1
+
+ # 2) xref insets
+ rx = re.compile(r'^reference \"sub:(.+)$')
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset CommandInset ref", i)
+ if i == -1:
+ return
+ j = find_end_of_inset(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Ref inset at line " + str(i))
+ i += 1
+ continue
+
+ for p in range(i, j):
+ m = rx.match(document.body[p])
+ if m:
+ label = m.group(1)
+ document.body[p] = "reference \"subsec:" + label
+ break
+ i += 1
+
+
+
+def revert_subref(document):
+ " reverts subref: ref prefixes to sub: "
+
+ # 1) label insets
+ rx = re.compile(r'^name \"subsec:(.+)$')
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset CommandInset label", i)
+ if i == -1:
+ break
+ j = find_end_of_inset(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Label inset at line " + str(i))
+ i += 1
+ continue
+
+ for p in range(i, j):
+ m = rx.match(document.body[p])
+ if m:
+ label = m.group(1)
+ document.body[p] = "name \"sub:" + label
+ break
+ i += 1
+
+ # 2) xref insets
+ rx = re.compile(r'^reference \"subsec:(.+)$')
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset CommandInset ref", i)
+ if i == -1:
+ return
+ j = find_end_of_inset(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Ref inset at line " + str(i))
+ i += 1
+ continue
+
+ for p in range(i, j):
+ m = rx.match(document.body[p])
+ if m:
+ label = m.group(1)
+ document.body[p] = "reference \"sub:" + label
+ break
+ i += 1
+
+
+def convert_nounzip(document):
+ " remove the noUnzip parameter of graphics insets "
+
+ rx = re.compile(r'\s*noUnzip\s*$')
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Graphics", i)
+ if i == -1:
+ break
+ j = find_end_of_inset(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of graphics inset at line " + str(i))
+ i += 1
+ continue
+
+ k = find_re(document.body, rx, i, j)
+ if k != -1:
+ del document.body[k]
+ j = j - 1
+ i = j + 1
+
+
+def convert_revert_external_bbox(document, forward):
+ " add units to bounding box of external insets "
+
+ rx = re.compile(r'^\s*boundingBox\s+\S+\s+\S+\s+\S+\s+\S+\s*$')
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset External", i)
+ if i == -1:
+ break
+ j = find_end_of_inset(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of external inset at line " + str(i))
+ i += 1
+ continue
+ k = find_re(document.body, rx, i, j)
+ if k == -1:
+ i = j + 1
+ continue
+ tokens = document.body[k].split()
+ if forward:
+ for t in range(1, 5):
+ tokens[t] += "bp"
+ else:
+ for t in range(1, 5):
+ tokens[t] = length_in_bp(tokens[t])
+ document.body[k] = "\tboundingBox " + tokens[1] + " " + tokens[2] + " " + \
+ tokens[3] + " " + tokens[4]
+ i = j + 1
+
+
+def convert_external_bbox(document):
+ convert_revert_external_bbox(document, True)
+
+
+def revert_external_bbox(document):
+ convert_revert_external_bbox(document, False)
+
+
+def revert_tcolorbox_1(document):
+ " Reverts the Flex:Subtitle inset of tcolorbox to TeX-code "
+ i = -1
+ while True:
+ i = find_token(document.header, "tcolorbox", i)
+ if i == -1:
+ break
+ else:
+ flex = 0
+ flexEnd = -1
+ flex = find_token(document.body, "\\begin_inset Flex Subtitle", flex)
+ if flex == -1:
+ return flexEnd
+ flexEnd = find_end_of_inset(document.body, flex)
+ wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True, False)
+ revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False, False)
+ flexEnd = find_end_of_inset(document.body, flex)
+ if wasOpt == True:
+ document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\tcbsubtitle")
+ else:
+ document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\tcbsubtitle{")
+ document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
+ flex += 1
+
+
+def revert_tcolorbox_2(document):
+ " Reverts the Flex:Raster_Color_Box inset of tcolorbox to TeX-code "
+ i = -1
+ while True:
+ i = find_token(document.header, "tcolorbox", i)
+ if i == -1:
+ break
+ else:
+ flex = 0
+ flexEnd = -1
+ flex = find_token(document.body, "\\begin_inset Flex Raster Color Box", flex)
+ if flex == -1:
+ return flexEnd
+ flexEnd = find_end_of_inset(document.body, flex)
+ revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
+ flexEnd = find_end_of_inset(document.body, flex)
+ document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\begin{tcbraster}")
+ document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("\\end{tcbraster}")
+ flex += 1
+
+
+def revert_tcolorbox_3(document):
+ " Reverts the Flex:Custom_Color_Box_1 inset of tcolorbox to TeX-code "
+ i = -1
+ while True:
+ i = find_token(document.header, "tcolorbox", i)
+ if i == -1:
+ break
+ else:
+ flex = 0
+ flexEnd = -1
+ flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 1", flex)
+ if flex == -1:
+ return flexEnd
+ flexEnd = find_end_of_inset(document.body, flex)
+ revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
+ revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, True, False, False)
+ flexEnd = find_end_of_inset(document.body, flex)
+ document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\begin{cBoxA}")
+ document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("{}\\end{cBoxA}")
+ flex += 1
+
+
+def revert_tcolorbox_4(document):
+ " Reverts the Flex:Custom_Color_Box_2 inset of tcolorbox to TeX-code "
+ i = -1
+ while True:
+ i = find_token(document.header, "tcolorbox", i)
+ if i == -1:
+ break
+ else:
+ flex = 0
+ flexEnd = -1
+ flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 2", flex)
+ if flex == -1:
+ return flexEnd
+ flexEnd = find_end_of_inset(document.body, flex)
+ revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
+ revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, True, False, False)
+ flexEnd = find_end_of_inset(document.body, flex)
+ document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\begin{cBoxB}")
+ document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("{}\\end{cBoxB}")
+ flex += 1
+
+
+def revert_tcolorbox_5(document):
+ " Reverts the Flex:Custom_Color_Box_3 inset of tcolorbox to TeX-code "
+ i = -1
+ while True:
+ i = find_token(document.header, "tcolorbox", i)
+ if i == -1:
+ break
+ else:
+ flex = 0
+ flexEnd = -1
+ flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 3", flex)
+ if flex == -1:
+ return flexEnd
+ flexEnd = find_end_of_inset(document.body, flex)
+ revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
+ revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, True, False, False)
+ flexEnd = find_end_of_inset(document.body, flex)
+ document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\begin{cBoxC}")
+ document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("{}\\end{cBoxC}")
+ flex += 1
+
+
+def revert_tcolorbox_6(document):
+ " Reverts the Flex:Custom_Color_Box_4 inset of tcolorbox to TeX-code "
+ i = -1
+ while True:
+ i = find_token(document.header, "tcolorbox", i)
+ if i == -1:
+ break
+ else:
+ flex = 0
+ flexEnd = -1
+ flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 4", flex)
+ if flex == -1:
+ return flexEnd
+ flexEnd = find_end_of_inset(document.body, flex)
+ revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
+ revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, True, False, False)
+ flexEnd = find_end_of_inset(document.body, flex)
+ document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\begin{cBoxD}")
+ document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("{}\\end{cBoxD}")
+ flex += 1
+
+
+def revert_tcolorbox_7(document):
+ " Reverts the Flex:Custom_Color_Box_5 inset of tcolorbox to TeX-code "
+ i = -1
+ while True:
+ i = find_token(document.header, "tcolorbox", i)
+ if i == -1:
+ break
+ else:
+ flex = 0
+ flexEnd = -1
+ flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 5", flex)
+ if flex == -1:
+ return flexEnd
+ flexEnd = find_end_of_inset(document.body, flex)
+ revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
+ revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, True, False, False)
+ flexEnd = find_end_of_inset(document.body, flex)
+ document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\begin{cBoxE}")
+ document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("{}\\end{cBoxE}")
+ flex += 1
+
+
+def revert_tcolorbox_8(document):
+ " Reverts the layout New Color Box Type of tcolorbox to TeX-code "
+ i = 0
+ j = 0
+ k = 0
+ while True:
+ if i != -1:
+ i = find_token(document.body, "\\begin_layout New Color Box Type", i)
+ if i != -1:
+ j = find_end_of_layout(document.body, i)
+ wasOpt = revert_Argument_to_TeX_brace(document, i, j, 1, 1, False, True, False)
+ revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False, True)
+ revert_Argument_to_TeX_brace(document, i, 0, 3, 4, False, True, False)
+ document.body[i] = document.body[i].replace("\\begin_layout New Color Box Type", "\\begin_layout Standard")
+ if wasOpt == True:
+ document.body[i + 1 : i + 1] = put_cmd_in_ert("\\newtcolorbox")
+ else:
+ document.body[i + 1 : i + 1] = put_cmd_in_ert("\\newtcolorbox{")
+ k = find_end_of_inset(document.body, j)
+ k = find_token(document.body, "\\end_inset", k + 1)
+ k = find_token(document.body, "\\end_inset", k + 1)
+ if wasOpt == True:
+ k = find_token(document.body, "\\end_inset", k + 1)
+ document.body[k + 2 : j + 2] = put_cmd_in_ert("{")
+ j = find_token(document.body, "\\begin_layout Standard", j + 1)
+ document.body[j - 2 : j - 2] = put_cmd_in_ert("}")
+ i += 1
+ if i == -1:
+ return
+
+
+def revert_moderncv_1(document):
+ " Reverts the new inset of moderncv to TeX-code in preamble "
+
+ if document.textclass != "moderncv":
+ return
+ i = 0
+ j = 0
+ lineArg = 0
+ while True:
+ # at first revert the new styles
+ # \moderncvicons
+ i = find_token(document.body, "\\begin_layout CVIcons", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of CVIcons layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\moderncvicons{" + content + "}"])
+ del document.body[i:j + 1]
+ # \hintscolumnwidth
+ i = find_token(document.body, "\\begin_layout CVColumnWidth", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of CVColumnWidth layout")
+ i += 1
+ continue
+ content = lyx2latex(document, document.body[i:j + 1])
+ add_to_preamble(document, ["\\setlength{\hintscolumnwidth}{" + content + "}"])
+ del document.body[i:j + 1]
+ # now change the new styles to the obsolete ones
+ # \name
+ i = find_token(document.body, "\\begin_layout Name", 0)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Name layout")
+ i += 1
+ continue
+ lineArg = find_token(document.body, "\\begin_inset Argument 1", i)
+ if lineArg > j and j != 0:
+ return
+ if lineArg != -1:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
+ # we have to assure that no other inset is in the Argument
+ beginInset = find_token(document.body, "\\begin_inset", beginPlain)
+ endInset = find_token(document.body, "\\end_inset", beginPlain)
+ k = beginPlain + 1
+ l = k
+ while beginInset < endInset and beginInset != -1:
+ beginInset = find_token(document.body, "\\begin_inset", k)
+ endInset = find_token(document.body, "\\end_inset", l)
+ k = beginInset + 1
+ l = endInset + 1
+ Arg2 = document.body[l + 5 : l + 6]
+ # rename the style
+ document.body[i : i + 1]= ["\\begin_layout FirstName"]
+ # delete the Argument inset
+ del( document.body[endInset - 2 : endInset + 3])
+ del( document.body[lineArg : beginPlain + 1])
+ document.body[i + 4 : i + 4]= ["\\begin_layout FamilyName"] + Arg2 + ["\\end_layout"] + [""]
+
+
+def revert_moderncv_2(document):
+ " Reverts the phone inset of moderncv to the obsoleted mobile or fax "
+
+ if document.textclass != "moderncv":
+ return
+ i = 0
+ j = 0
+ lineArg = 0
+ while True:
+ # \phone
+ i = find_token(document.body, "\\begin_layout Phone", i)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Phone layout")
+ i += 1
+ return
+ lineArg = find_token(document.body, "\\begin_inset Argument 1", i)
+ if lineArg > j and j != 0:
+ i += 1
+ continue
+ if lineArg != -1:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
+ # we have to assure that no other inset is in the Argument
+ beginInset = find_token(document.body, "\\begin_inset", beginPlain)
+ endInset = find_token(document.body, "\\end_inset", beginPlain)
+ k = beginPlain + 1
+ l = k
+ while beginInset < endInset and beginInset != -1:
+ beginInset = find_token(document.body, "\\begin_inset", k)
+ endInset = find_token(document.body, "\\end_inset", l)
+ k = beginInset + 1
+ l = endInset + 1
+ Arg = document.body[beginPlain + 1 : beginPlain + 2]
+ # rename the style
+ if Arg[0] == "mobile":
+ document.body[i : i + 1]= ["\\begin_layout Mobile"]
+ if Arg[0] == "fax":
+ document.body[i : i + 1]= ["\\begin_layout Fax"]
+ # delete the Argument inset
+ del(document.body[endInset - 2 : endInset + 1])
+ del(document.body[lineArg : beginPlain + 3])
+ i += 1
+
+
+def convert_moderncv(document):
+ " Convert the Fax and Mobile inset of moderncv to the new phone inset "
+
+ if document.textclass != "moderncv":
+ return
+ i = 0
+ j = 0
+ lineArg = 0
+ while True:
+ # \mobile
+ i = find_token(document.body, "\\begin_layout Mobile", i)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Mobile layout")
+ i += 1
+ return
+ document.body[i + 1 : i + 1] = ["\\begin_inset Argument 1", "status open", "",
+ "\\begin_layout Plain Layout", "mobile", "\\end_layout", "",
+ "\\end_inset", ""]
+ # \fax
+ i = find_token(document.body, "\\begin_layout Fax", i)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of Fax layout")
+ i += 1
+ return
+ document.body[i + 1 : i + 1] = ["\\begin_inset Argument 1", "status open", "",
+ "\\begin_layout Plain Layout", "fax", "\\end_layout", "",
+ "\\end_inset", ""]
+ # \firstname and \familyname
+ i1 = find_token(document.body, "\\begin_layout FirstName", 0)
+ if i1 == -1:
+ return
+ j1 = find_end_of_layout(document.body, i1)
+ if j1 == -1:
+ document.warning("Malformed LyX document: Can't find end of FirstName layout")
+ i1 += 1
+ return
+ FirstName = document.body[i1 + 1 : i1 + 2]
+ i2 = find_token(document.body, "\\begin_layout FamilyName", 0)
+ if i2 == -1:
+ return
+ j2 = find_end_of_layout(document.body, i2)
+ if j2 == -1:
+ document.warning("Malformed LyX document: Can't find end of FamilyName layout")
+ i2 += 1
+ return
+ FamilyName = document.body[i2 + 1 : i2 + 2]
+ if j1 > j2:
+ k = j1
+ l = i2
+ else:
+ k = j2
+ l = i1
+ document.body[k + 1 : k + 1] = ["\\begin_layout Name", "\\begin_inset Argument 1", "status open", "",
+ "\\begin_layout Plain Layout", FirstName[0], "\\end_layout", "",
+ "\\end_inset", "", FamilyName[0], "\\end_layout", ""]
+ #document.body[i2 + 1 : i2 + 1] = ["hellok: ", str(k)]
+ del(document.body[l : k])
+ i += 1
+ i1 += 1
+ i2 += 1
+
+
+def revert_achemso(document):
+ " Reverts the flex inset Latin to TeX code "
+
+ if document.textclass != "achemso":
+ return
+ i = 0
+ j = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Flex Latin", i)
+ if i != -1:
+ j = find_end_of_inset(document.body, i)
+ else:
+ return
+ if j != -1:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ content = lyx2latex(document, document.body[beginPlain : endPlain])
+ document.body[i:j + 1] = put_cmd_in_ert("\\latin{" + content + "}")
+ else:
+ document.warning("Malformed LyX document: Can't find end of flex inset Latin")
+ return
+ i += 1
+
+
+fontsettings = ["\\font_roman", "\\font_sans", "\\font_typewriter", "\\font_math", \
+ "\\font_sf_scale", "\\font_tt_scale"]
+fontdefaults = ["default", "default", "default", "auto", "100", "100"]
+fontquotes = [True, True, True, True, False, False]
+
+def convert_fontsettings(document):
+ " Duplicate font settings "
+
+ i = find_token(document.header, "\\use_non_tex_fonts ", 0)
+ if i == -1:
+ document.warning("Malformed LyX document: No \\use_non_tex_fonts!")
+ use_non_tex_fonts = "false"
+ else:
+ use_non_tex_fonts = get_value(document.header, "\\use_non_tex_fonts", i)
+ j = 0
+ for f in fontsettings:
+ i = find_token(document.header, f + " ", 0)
+ if i == -1:
+ document.warning("Malformed LyX document: No " + f + "!")
+ j = j + 1
+ continue
+ value = document.header[i][len(f):].strip()
+ if fontquotes[j]:
+ if use_non_tex_fonts == "true":
+ document.header[i:i+1] = [f + ' "' + fontdefaults[j] + '" "' + value + '"']
+ else:
+ document.header[i:i+1] = [f + ' "' + value + '" "' + fontdefaults[j] + '"']
+ else:
+ if use_non_tex_fonts == "true":
+ document.header[i:i+1] = [f + ' ' + fontdefaults[j] + ' ' + value]
+ else:
+ document.header[i:i+1] = [f + ' ' + value + ' ' + fontdefaults[j]]
+ j = j + 1
+
+
+def revert_fontsettings(document):
+ " Merge font settings "
+
+ i = find_token(document.header, "\\use_non_tex_fonts ", 0)
+ if i == -1:
+ document.warning("Malformed LyX document: No \\use_non_tex_fonts!")
+ use_non_tex_fonts = "false"
+ else:
+ use_non_tex_fonts = get_value(document.header, "\\use_non_tex_fonts", i)
+ j = 0
+ for f in fontsettings:
+ i = find_token(document.header, f + " ", 0)
+ if i == -1:
+ document.warning("Malformed LyX document: No " + f + "!")
+ j = j + 1
+ continue
+ line = get_value(document.header, f, i)
+ if fontquotes[j]:
+ q1 = line.find('"')
+ q2 = line.find('"', q1+1)
+ q3 = line.find('"', q2+1)
+ q4 = line.find('"', q3+1)
+ if q1 == -1 or q2 == -1 or q3 == -1 or q4 == -1:
+ document.warning("Malformed LyX document: Missing quotes!")
+ j = j + 1
+ continue
+ if use_non_tex_fonts == "true":
+ document.header[i:i+1] = [f + ' ' + line[q3+1:q4]]
+ else:
+ document.header[i:i+1] = [f + ' ' + line[q1+1:q2]]
+ else:
+ if use_non_tex_fonts == "true":
+ document.header[i:i+1] = [f + ' ' + line.split()[2]]
+ else:
+ document.header[i:i+1] = [f + ' ' + line.split()[1]]
+ j = j + 1
##
[489, [convert_BoxFeatures]],
[490, [convert_origin]],
[491, []],
- [492, [convert_colorbox]]
+ [492, [convert_colorbox]],
+ [493, []],
+ [494, []],
+ [495, [convert_subref]],
+ [496, [convert_nounzip]],
+ [497, [convert_external_bbox]],
+ [498, []],
+ [499, [convert_moderncv]],
+ [500, []],
+ [501, [convert_fontsettings]]
]
revert = [
+ [500, [revert_fontsettings]],
+ [499, [revert_achemso]],
+ [498, [revert_moderncv_1, revert_moderncv_2]],
+ [497, [revert_tcolorbox_1, revert_tcolorbox_2,
+ revert_tcolorbox_3, revert_tcolorbox_4, revert_tcolorbox_5,
+ revert_tcolorbox_6, revert_tcolorbox_7, revert_tcolorbox_8]],
+ [496, [revert_external_bbox]],
+ [495, []], # nothing to do since the noUnzip parameter was optional
+ [494, [revert_subref]],
+ [493, [revert_jss]],
+ [492, [revert_mathmulticol]],
[491, [revert_colorbox]],
[490, [revert_textcolor]],
[489, [revert_origin]],