+def revert_frametitle(document):
+ " Reverts beamer frametitle layout to ERT "
+
+ beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
+ if document.textclass not in beamer_classes:
+ return
+
+ rx = re.compile(r'^\\begin_inset Argument (\S+)$')
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_layout FrameTitle", 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 FrameTitle layout")
+ i += 1
+ continue
+ endlay = j
+ document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
+ endlay += len(put_cmd_in_ert("}"))
+ subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
+ for p in range(i, j):
+ if p >= endlay:
+ break
+ m = rx.match(document.body[p])
+ if m:
+ argnr = m.group(1)
+ if argnr == "1":
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, p)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ endlay = endlay - len(document.body[p : endInset + 1])
+ # Remove arg inset
+ del document.body[p : endInset + 1]
+ subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
+ elif argnr == "2":
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, p)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ endlay = endlay - len(document.body[p : endInset + 1])
+ # Remove arg inset
+ del document.body[p : endInset + 1]
+ subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
+
+ subst += put_cmd_in_ert("{")
+ document.body[i : i + 1] = subst
+ i = endlay
+
+
+def convert_epigraph(document):
+ " Converts memoir epigraph to new syntax "
+
+ if document.textclass != "memoir":
+ return
+
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_layout Epigraph", 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 Epigraph layout")
+ i += 1
+ continue
+ endlay = j
+ subst = list()
+ ert = find_token(document.body, "\\begin_inset ERT", i, j)
+ if ert != -1:
+ endInset = find_end_of_inset(document.body, ert)
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ ertcont = beginPlain + 2
+ if document.body[ertcont] == "}{":
+ # strip off the <
+ # Convert to ArgInset
+ endlay = endlay - 2 * len(document.body[j])
+ begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
+ '\\begin_layout Plain Layout']
+ endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
+ document.body[j : j + 1] = endsubst
+ document.body[endInset + 1 : endInset + 1] = begsubst
+ # Adjust range end
+ endlay += len(begsubst) + len(endsubst)
+ endlay = endlay - len(document.body[ert : endInset + 1])
+ del document.body[ert : endInset + 1]
+
+ i = endlay
+
+
+def revert_epigraph(document):
+ " Reverts memoir epigraph argument to ERT "
+
+ if document.textclass != "memoir":
+ return
+
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_layout Epigraph", 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 Epigraph layout")
+ i += 1
+ continue
+ endlay = j
+ subst = list()
+ p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
+ if p != -1:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, p)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ endlay = endlay - len(document.body[p : endInset + 1])
+ # Remove arg inset
+ del document.body[p : endInset + 1]
+ subst += put_cmd_in_ert("}{") + content
+ else:
+ subst += put_cmd_in_ert("}{")
+
+ document.body[j : j] = subst + document.body[j : j]
+ i = endlay
+
+
+def convert_captioninsets(document):
+ " Converts caption insets to new syntax "
+
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Caption", i)
+ if i == -1:
+ return
+ document.body[i] = "\\begin_inset Caption Standard"
+ i += 1
+
+
+def revert_captioninsets(document):
+ " Reverts caption insets to old syntax "
+
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Caption Standard", i)
+ if i == -1:
+ return
+ document.body[i] = "\\begin_inset Caption"
+ i += 1
+
+
+def convert_captionlayouts(document):
+ " Convert caption layouts to caption insets. "
+
+ caption_dict = {
+ "Captionabove": "Above",
+ "Captionbelow": "Below",
+ "FigCaption" : "FigCaption",
+ "Table_Caption" : "Table",
+ "CenteredCaption" : "Centered",
+ "Bicaption" : "Bicaption",
+ }
+
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_layout", i)
+ if i == -1:
+ return
+ val = get_value(document.body, "\\begin_layout", i)
+ if val in list(caption_dict.keys()):
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Missing `\\end_layout'.")
+ return
+
+ document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
+ document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
+ "\\begin_inset Caption %s" % caption_dict[val], "",
+ "\\begin_layout %s" % document.default_layout]
+ i += 1
+
+
+def revert_captionlayouts(document):
+ " Revert caption insets to caption layouts. "
+
+ caption_dict = {
+ "Above" : "Captionabove",
+ "Below" : "Captionbelow",
+ "FigCaption" : "FigCaption",
+ "Table" : "Table_Caption",
+ "Centered" : "CenteredCaption",
+ "Bicaption" : "Bicaption",
+ }
+
+ i = 0
+ rx = re.compile(r'^\\begin_inset Caption (\S+)$')
+ while True:
+ i = find_token(document.body, "\\begin_inset Caption", i)
+ if i == -1:
+ return
+
+ m = rx.match(document.body[i])
+ val = ""
+ if m:
+ val = m.group(1)
+ if val not in list(caption_dict.keys()):
+ i += 1
+ continue
+
+ # We either need to delete the previous \begin_layout line, or we
+ # need to end the previous layout if this inset is not in the first
+ # position of the paragraph.
+ layout_before = find_token_backwards(document.body, "\\begin_layout", i)
+ if layout_before == -1:
+ document.warning("Malformed LyX document: Missing `\\begin_layout'.")
+ return
+ layout_line = document.body[layout_before]
+ del_layout_before = True
+ l = layout_before + 1
+ while l < i:
+ if document.body[l] != "":
+ del_layout_before = False
+ break
+ l = l + 1
+ if del_layout_before:
+ del document.body[layout_before:i]
+ i = layout_before
+ else:
+ document.body[i:i] = ["\\end_layout", ""]
+ i = i + 2
+
+ # Find start of layout in the inset and end of inset
+ j = find_token(document.body, "\\begin_layout", i)
+ if j == -1:
+ document.warning("Malformed LyX document: Missing `\\begin_layout'.")
+ return
+ k = find_end_of_inset(document.body, i)
+ if k == -1:
+ document.warning("Malformed LyX document: Missing `\\end_inset'.")
+ return
+
+ # We either need to delete the following \end_layout line, or we need
+ # to restart the old layout if this inset is not at the paragraph end.
+ layout_after = find_token(document.body, "\\end_layout", k)
+ if layout_after == -1:
+ document.warning("Malformed LyX document: Missing `\\end_layout'.")
+ return
+ del_layout_after = True
+ l = k + 1
+ while l < layout_after:
+ if document.body[l] != "":
+ del_layout_after = False
+ break
+ l = l + 1
+ if del_layout_after:
+ del document.body[k+1:layout_after+1]
+ else:
+ document.body[k+1:k+1] = [layout_line, ""]
+
+ # delete \begin_layout and \end_inset and replace \begin_inset with
+ # "\begin_layout XXX". This works because we can only have one
+ # paragraph in the caption inset: The old \end_layout will be recycled.
+ del document.body[k]
+ if document.body[k] == "":
+ del document.body[k]
+ del document.body[j]
+ if document.body[j] == "":
+ del document.body[j]
+ document.body[i] = "\\begin_layout %s" % caption_dict[val]
+ if document.body[i+1] == "":
+ del document.body[i+1]
+ i += 1
+
+
+def revert_fragileframe(document):
+ " Reverts beamer FragileFrame layout to ERT "
+
+ beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
+ if document.textclass not in beamer_classes:
+ return
+
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_layout FragileFrame", i)
+ if i == -1:
+ return
+ # Find end of sequence
+ j = find_end_of_sequence(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
+ i += 1
+ continue
+ endseq = j
+ subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
+ esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
+ endseq = endseq + len(esubst) - len(document.body[j : j])
+ if document.body[j] == "\\end_deeper":
+ document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
+ else:
+ document.body[j : j] = esubst
+ for q in range(i, j):
+ if document.body[q] == "\\begin_layout FragileFrame":
+ document.body[q] = "\\begin_layout %s" % document.default_layout
+ r = i
+ while r < j:
+ if document.body[r] == "\\begin_deeper":
+ s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
+ if s != -1:
+ document.body[r] = ""
+ document.body[s] = ""
+ r = s
+ continue
+ r = r + 1
+ for p in range(1, 5):
+ arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
+ if arg != -1:
+ if p == 1:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, arg)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ j = j - len(document.body[arg : endInset + 1])
+ # Remove arg inset
+ del document.body[arg : endInset + 1]
+ subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
+ elif p == 2:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, arg)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ j = j - len(document.body[arg : endInset + 1])
+ # Remove arg inset
+ del document.body[arg : endInset + 1]
+ subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
+ elif p == 3:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, arg)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ j = j - len(document.body[arg : endInset + 1])
+ # Remove arg inset
+ del document.body[arg : endInset + 1]
+ subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
+ elif p == 4:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, arg)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ j = j - len(document.body[arg : endInset + 1])
+ # Remove arg inset
+ del document.body[arg : endInset + 1]
+ subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
+ elif p == 3:
+ subst += put_cmd_in_ert("[fragile]")
+
+ document.body[i : i + 1] = subst
+ i = j
+
+
+def revert_newframes(document):
+ " Reverts beamer Frame and PlainFrame layouts to old forms "
+
+ beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
+ if document.textclass not in beamer_classes:
+ return
+
+ frame_dict = {
+ "Frame" : "BeginFrame",
+ "PlainFrame" : "BeginPlainFrame",
+ }
+
+ rx = re.compile(r'^\\begin_layout (\S+)$')
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_layout", i)
+ if i == -1:
+ return
+
+ m = rx.match(document.body[i])
+ val = ""
+ if m:
+ val = m.group(1)
+ if val not in list(frame_dict.keys()):
+ i += 1
+ continue
+ # Find end of sequence
+ j = find_end_of_sequence(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
+ i += 1
+ continue
+ endseq = j
+ subst = ["\\begin_layout %s" % frame_dict[val]]
+ esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
+ endseq = endseq + len(esubst) - len(document.body[j : j])
+ if document.body[j] == "\\end_deeper":
+ document.body[j : j] = esubst
+ else:
+ document.body[j+1 : j+1] = esubst
+ for q in range(i, j):
+ if document.body[q] == "\\begin_layout %s" % val:
+ document.body[q] = "\\begin_layout %s" % document.default_layout
+ r = i
+ while r < j:
+ if document.body[r] == "\\begin_deeper":
+ s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
+ if s != -1:
+ document.body[r] = ""
+ document.body[s] = ""
+ r = s
+ continue
+ r = r + 1
+ l = find_end_of_layout(document.body, i)
+ for p in range(1, 5):
+ arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
+ if arg != -1:
+ if p == 1:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, arg)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ l = l - len(document.body[arg : endInset + 1])
+ # Remove arg inset
+ del document.body[arg : endInset + 1]
+ subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
+ elif p == 2:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, arg)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ l = l - len(document.body[arg : endInset + 1])
+ # Remove arg inset
+ del document.body[arg : endInset + 1]
+ subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
+ elif p == 3:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, arg)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ l = l - len(document.body[arg : endInset + 1])
+ # Remove arg inset
+ del document.body[arg : endInset + 1]
+ subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
+ elif p == 4:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, arg)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ l = l - len(document.body[arg : endInset + 1])
+ # Remove arg inset
+ del document.body[arg : endInset + 1]
+ subst += content
+
+ document.body[i : i + 1] = subst
+ i = j
+
+# known encodings that do not change their names (same LyX and LaTeX names)
+known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
+ "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
+ "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
+ "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
+
+def convert_encodings(document):
+ "Use the LyX names of the encodings instead of the LaTeX names."
+ LaTeX2LyX_enc_dict = {
+ "8859-6": "iso8859-6",
+ "8859-8": "iso8859-8",
+ "Bg5": "big5",
+ "euc": "euc-jp-platex",
+ "EUC-JP": "euc-jp",
+ "EUC-TW": "euc-tw",
+ "GB": "euc-cn",
+ "GBK": "gbk",
+ "iso88595": "iso8859-5",
+ "iso-8859-7": "iso8859-7",
+ "JIS": "jis",
+ "jis": "jis-platex",
+ "KS": "euc-kr",
+ "l7xenc": "iso8859-13",
+ "latin1": "iso8859-1",
+ "latin2": "iso8859-2",
+ "latin3": "iso8859-3",
+ "latin4": "iso8859-4",
+ "latin5": "iso8859-9",
+ "latin9": "iso8859-15",
+ "latin10": "iso8859-16",
+ "SJIS": "shift-jis",
+ "sjis": "shift-jis-platex",
+ "UTF8": "utf8-cjk"
+ }
+ i = find_token(document.header, "\\inputencoding" , 0)
+ if i == -1:
+ return
+ val = get_value(document.header, "\\inputencoding", i)
+ if val in list(LaTeX2LyX_enc_dict.keys()):
+ document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
+ elif val not in known_enc_tuple:
+ document.warning("Ignoring unknown input encoding: `%s'" % val)
+
+
+def revert_encodings(document):
+ """Revert to using the LaTeX names of the encodings instead of the LyX names.
+ Also revert utf8-platex to sjis, the language default when using Japanese.
+ """
+ LyX2LaTeX_enc_dict = {
+ "big5": "Bg5",
+ "euc-cn": "GB",
+ "euc-kr": "KS",
+ "euc-jp": "EUC-JP",
+ "euc-jp-platex": "euc",
+ "euc-tw": "EUC-TW",
+ "gbk": "GBK",
+ "iso8859-1": "latin1",
+ "iso8859-2": "latin2",
+ "iso8859-3": "latin3",
+ "iso8859-4": "latin4",
+ "iso8859-5": "iso88595",
+ "iso8859-6": "8859-6",
+ "iso8859-7": "iso-8859-7",
+ "iso8859-8": "8859-8",
+ "iso8859-9": "latin5",
+ "iso8859-13": "l7xenc",
+ "iso8859-15": "latin9",
+ "iso8859-16": "latin10",
+ "jis": "JIS",
+ "jis-platex": "jis",
+ "shift-jis": "SJIS",
+ "shift-jis-platex": "sjis",
+ "utf8-cjk": "UTF8",
+ "utf8-platex": "sjis"
+ }
+ i = find_token(document.header, "\\inputencoding" , 0)
+ if i == -1:
+ return
+ val = get_value(document.header, "\\inputencoding", i)
+ if val in list(LyX2LaTeX_enc_dict.keys()):
+ document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
+ elif val not in known_enc_tuple:
+ document.warning("Ignoring unknown input encoding: `%s'" % val)
+
+
+def revert_IEEEtran_3(document):
+ '''
+ Reverts Flex Insets to TeX-code
+ '''
+ if document.textclass == "IEEEtran":
+ h = 0
+ i = 0
+ j = 0
+ while True:
+ if h != -1:
+ h = find_token(document.body, "\\begin_inset Flex Author Mark", 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("\\IEEEauthorrefmark{")
+ h = h + 5
+ if i != -1:
+ i = find_token(document.body, "\\begin_inset Flex Author Name", i)
+ if i != -1:
+ endi = find_end_of_inset(document.body, i)
+ document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
+ document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
+ i = i + 5
+ if j != -1:
+ j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
+ if j != -1:
+ 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("\\IEEEauthorblockA{")
+ j = j + 5
+ if i == -1 and j == -1 and h == -1:
+ return
+
+
+def revert_kurier_fonts(document):
+ " Revert kurier font definition to LaTeX "
+
+ i = find_token(document.header, "\\font_math", 0)
+ if i != -1:
+ if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
+ val = get_value(document.header, "\\font_math", i)
+ if val == "kurier-math":
+ add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
+ "\\usepackage[math]{kurier}\n" \
+ "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
+ document.header[i] = "\\font_math auto"
+
+ if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
+ kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
+ k = find_token(document.header, "\\font_sans kurier", 0)
+ if k != -1:
+ sf = get_value(document.header, "\\font_sans", k)
+ if sf in kurier_fonts:
+ add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
+ document.header[k] = "\\font_sans default"
+
+def revert_iwona_fonts(document):
+ " Revert iwona font definition to LaTeX "
+
+ i = find_token(document.header, "\\font_math", 0)
+ if i != -1:
+ if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
+ val = get_value(document.header, "\\font_math", i)
+ if val == "iwona-math":
+ add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
+ "\\usepackage[math]{iwona}\n" \
+ "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
+ document.header[i] = "\\font_math auto"
+
+ if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
+ iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
+ k = find_token(document.header, "\\font_sans iwona", 0)
+ if k != -1:
+ sf = get_value(document.header, "\\font_sans", k)
+ if sf in iwona_fonts:
+ add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
+ document.header[k] = "\\font_sans default"
+
+
+def revert_new_libertines(document):
+ " Revert new libertine font definition to LaTeX "
+
+ if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
+ return
+
+ i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
+ if i != -1:
+ preamble = "\\usepackage"
+ sc = find_token(document.header, "\\font_tt_scale", 0)
+ if sc != -1:
+ scval = get_value(document.header, "\\font_tt_scale", sc)
+ if scval != "100":
+ preamble += "[scale=%f]" % (float(scval) / 100)
+ document.header[sc] = "\\font_tt_scale 100"
+ preamble += "{libertineMono-type1}"
+ add_to_preamble(document, [preamble])
+ document.header[i] = "\\font_typewriter default"
+
+ k = find_token(document.header, "\\font_sans biolinum", 0)
+ if k != -1:
+ preamble = "\\usepackage"
+ options = ""
+ j = find_token(document.header, "\\font_osf true", 0)
+ if j != -1:
+ options += "osf"
+ else:
+ options += "lining"
+ sc = find_token(document.header, "\\font_sf_scale", 0)
+ if sc != -1:
+ scval = get_value(document.header, "\\font_sf_scale", sc)
+ if scval != "100":
+ options += ",scale=%f" % (float(scval) / 100)
+ document.header[sc] = "\\font_sf_scale 100"
+ if options != "":
+ preamble += "[" + options +"]"
+ preamble += "{biolinum-type1}"
+ add_to_preamble(document, [preamble])
+ document.header[k] = "\\font_sans default"
+
+
+def convert_lyxframes(document):
+ " Converts old beamer frames to new style "
+
+ beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
+ if document.textclass not in beamer_classes:
+ return
+
+ framebeg = ["BeginFrame", "BeginPlainFrame"]
+ frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
+ "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
+ for lay in framebeg:
+ i = 0
+ while True:
+ i = find_token_exact(document.body, "\\begin_layout " + lay, i)
+ if i == -1:
+ break
+ parent = get_containing_layout(document.body, i)
+ if parent == False or parent[1] != i:
+ document.warning("Wrong parent layout!")
+ i += 1
+ continue
+ frametype = parent[0]
+ j = parent[2]
+ parbeg = parent[3]
+ if i != -1:
+ # Step I: Convert ERT arguments
+ # FIXME: See restrictions in convert_beamerframeargs method
+ ertend = convert_beamerframeargs(document, i, parbeg)
+ if ertend == -1:
+ break
+ # Step II: Now rename the layout and convert the title to an argument
+ j = find_end_of_layout(document.body, i)
+ document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
+ if lay == "BeginFrame":
+ document.body[i] = "\\begin_layout Frame"
+ else:
+ document.body[i] = "\\begin_layout PlainFrame"
+ document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
+ 'status open', '', '\\begin_layout Plain Layout']
+ # Step III: find real frame end
+ j = j + 8
+ jj = j
+ inInset = get_containing_inset(document.body, i)
+ while True:
+ fend = find_token(document.body, "\\begin_layout", jj)
+ if fend == -1:
+ document.warning("Malformed LyX document: No real frame end!")
+ return
+ val = get_value(document.body, "\\begin_layout", fend)
+ if val not in frameend:
+ jj = fend + 1
+ continue
+ # is this frame nested in an inset (e.g., Note)?
+ if inInset != False:
+ # if so, end the frame inside the inset
+ if inInset[2] < fend:
+ fend = inInset[2]
+ if val == frametype:
+ document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
+ # consider explicit EndFrames between two identical frame types
+ elif val == "EndFrame":
+ nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
+ if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
+ document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
+ else:
+ document.body[fend : fend] = ['\\end_deeper']
+ else:
+ document.body[fend : fend] = ['\\end_deeper']
+ document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
+ break
+ i = j
+
+
+def remove_endframes(document):
+ " Remove deprecated beamer endframes "
+
+ beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
+ if document.textclass not in beamer_classes:
+ return
+
+ i = 0
+ while True:
+ i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
+ if i == -1:
+ break
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
+ i += 1
+ continue
+ del document.body[i : j + 1]
+
+
+def revert_powerdot_flexes(document):
+ " Reverts powerdot flex insets "
+
+ if document.textclass != "powerdot":
+ return
+
+ flexes = {"Onslide" : "\\onslide",
+ "Onslide*" : "\\onslide*",
+ "Onslide+" : "\\onslide+"}
+ rx = re.compile(r'^\\begin_inset Flex (.+)$')
+
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Flex", i)
+ if i == -1:
+ return
+ m = rx.match(document.body[i])
+ if m:
+ flextype = m.group(1)
+ z = find_end_of_inset(document.body, i)
+ if z == -1:
+ document.warning("Can't find end of Flex " + flextype + " inset.")
+ i += 1
+ continue
+ if flextype in flexes:
+ pre = put_cmd_in_ert(flexes[flextype])
+ arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
+ if arg != -1:
+ argend = find_end_of_inset(document.body, arg)
+ if argend == -1:
+ document.warning("Can't find end of Argument!")
+ i += 1
+ continue
+ # Find containing paragraph layout
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ argcontent = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ z = z - len(document.body[arg : argend + 1])
+ # Remove arg inset
+ del document.body[arg : argend + 1]
+ pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
+ pre += put_cmd_in_ert("{")
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ # Adjust range end
+ z = z - len(document.body[i : beginPlain + 1])
+ z += len(pre)
+ document.body[i : beginPlain + 1] = pre
+ post = put_cmd_in_ert("}")
+ document.body[z - 2 : z + 1] = post
+ i += 1
+
+
+def revert_powerdot_pause(document):
+ " Reverts powerdot pause layout to ERT "
+
+ if document.textclass != "powerdot":
+ return
+
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_layout Pause", 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 Pause layout")
+ i += 1
+ continue
+ endlay = j
+ subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
+ for p in range(i, j):
+ if p >= endlay:
+ break
+ arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
+ if arg != -1:
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, p)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ endlay = endlay - len(document.body[p : endInset + 1])
+ # Remove arg inset
+ del document.body[p : endInset + 1]
+ subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
+
+ document.body[i : i + 1] = subst
+ i = endlay
+
+
+def revert_powerdot_itemargs(document):
+ " Reverts powerdot item arguments to ERT "
+
+ if document.textclass != "powerdot":
+ return
+
+ i = 0
+ list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
+ rx = re.compile(r'^\\begin_inset Argument (\S+)$')
+
+ while True:
+ i = find_token(document.body, "\\begin_inset Argument", i)
+ if i == -1:
+ return
+ # Find containing paragraph layout
+ parent = get_containing_layout(document.body, i)
+ if parent == False:
+ document.warning("Malformed LyX document: Can't find parent paragraph layout")
+ i += 1
+ continue
+ parbeg = parent[1]
+ parend = parent[2]
+ realparbeg = parent[3]
+ layoutname = parent[0]
+ realparend = parend
+ for p in range(parbeg, parend):
+ if p >= realparend:
+ i = realparend
+ break
+ if layoutname in list_layouts:
+ m = rx.match(document.body[p])
+ if m:
+ argnr = m.group(1)
+ if argnr == "item:1":
+ j = find_end_of_inset(document.body, i)
+ # Find containing paragraph layout
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ content = document.body[beginPlain + 1 : endPlain]
+ del document.body[i:j+1]
+ subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
+ document.body[realparbeg : realparbeg] = subst
+ elif argnr == "item:2":
+ j = find_end_of_inset(document.body, i)
+ # Find containing paragraph layout
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ content = document.body[beginPlain + 1 : endPlain]
+ del document.body[i:j+1]
+ subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
+ document.body[realparbeg : realparbeg] = subst
+
+ i = realparend
+
+
+def revert_powerdot_columns(document):
+ " Reverts powerdot twocolumn to TeX-code "
+ if document.textclass != "powerdot":
+ return
+
+ rx = re.compile(r'^\\begin_inset Argument (\S+)$')
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_layout Twocolumn", 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 Twocolumn layout")
+ i += 1
+ continue
+ endlay = j
+ document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
+ endlay += len(put_cmd_in_ert("}"))
+ subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
+ for p in range(i, j):
+ if p >= endlay:
+ break
+ m = rx.match(document.body[p])
+ if m:
+ argnr = m.group(1)
+ if argnr == "1":
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, p)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ endlay = endlay - len(document.body[p : endInset + 1])
+ # Remove arg inset
+ del document.body[p : endInset + 1]
+ subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
+ elif argnr == "2":
+ beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
+ endPlain = find_end_of_layout(document.body, beginPlain)
+ endInset = find_end_of_inset(document.body, p)
+ content = document.body[beginPlain + 1 : endPlain]
+ # Adjust range end
+ endlay = endlay - len(document.body[p : endInset + 1])
+ # Remove arg inset
+ del document.body[p : endInset + 1]
+ subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
+
+ subst += put_cmd_in_ert("{")
+ document.body[i : i + 1] = subst
+ i = endlay
+
+
+def revert_mbox_fbox(document):
+ 'Convert revert mbox/fbox boxes to TeX-code'
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Box", i)
+ if i == -1:
+ return
+ j = find_token(document.body, "width", i)
+ if j != i + 7:
+ document.warning("Malformed LyX document: Can't find box width")
+ return
+ width = get_value(document.body, "width", j)
+ k = find_end_of_inset(document.body, j)
+ if k == -1:
+ document.warning("Malformed LyX document: Can't find end of box inset")
+ i += 1
+ continue
+ BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
+ EndLayout = find_end_of_layout(document.body, BeginLayout)
+ # replace if width is ""
+ if (width == '""'):
+ document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
+ if document.body[i] == "\\begin_inset Box Frameless":
+ document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
+ if document.body[i] == "\\begin_inset Box Boxed":
+ document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
+ i += 1
+
+
+def revert_starred_caption(document):
+ " Reverts unnumbered longtable caption insets "
+
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
+ if i == -1:
+ return
+ # This is not equivalent, but since the caption inset is a full blown
+ # text inset a true conversion to ERT is too difficult.
+ document.body[i] = "\\begin_inset Caption Standard"
+ i += 1
+
+
+def revert_forced_local_layout(document):
+ i = 0
+ while True:
+ i = find_token(document.header, "\\begin_forced_local_layout", i)
+ if i == -1:
+ return
+ j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
+ if j == -1:
+ # this should not happen
+ break
+ regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
+ k = find_re(document.header, regexp, i, j)
+ while k != -1:
+ del document.header[k]
+ j = j - 1
+ k = find_re(document.header, regexp, i, j)
+ k = find_token(document.header, "\\begin_local_layout", 0)
+ if k == -1:
+ document.header[i] = "\\begin_local_layout"
+ document.header[j] = "\\end_local_layout"
+ else:
+ l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
+ if j == -1:
+ # this should not happen
+ break
+ lines = document.header[i+1 : j]
+ if k > i:
+ document.header[k+1 : k+1] = lines
+ document.header[i : j ] = []
+ else:
+ document.header[i : j ] = []
+ document.header[k+1 : k+1] = lines
+
+
+def revert_aa1(document):
+ " Reverts InsetArguments of aa to TeX-code "
+ if document.textclass == "aa":
+ i = 0
+ while True:
+ if i != -1:
+ i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
+ if i != -1:
+ revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
+ i += 1
+ if i == -1:
+ return
+
+
+def revert_aa2(document):
+ " Reverts InsetArguments of aa to TeX-code "
+ if document.textclass == "aa":
+ i = 0
+ while True:
+ if i != -1:
+ i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
+ if i != -1:
+ document.body[i] = "\\begin_layout Abstract"
+ i += 1
+ if i == -1:
+ return
+
+
+def revert_tibetan(document):
+ "Set the document language for Tibetan to English"
+
+ if document.language == "tibetan":
+ document.language = "english"
+ i = find_token(document.header, "\\language", 0)
+ if i != -1:
+ document.header[i] = "\\language english"
+ j = 0
+ while j < len(document.body):
+ j = find_token(document.body, "\\lang tibetan", j)
+ if j != -1:
+ document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
+ j += 1
+ else:
+ j = len(document.body)
+
+
+#############
+#
+# Chunk stuff
+#
+#############
+
+# The idea here is that we will have a sequence of chunk paragraphs.
+# We want to convert them to paragraphs in one or several chunk insets.
+# Individual chunks are terminated by the character @ on the last line.
+# This line will be discarded, and following lines are treated as new
+# chunks, which go into their own insets.
+# The first line of a chunk should look like: <<CONTENT>>=
+# We will discard the delimiters, and put the CONTENT into the
+# optional argument of the inset, if the CONTENT is non-empty.
+def convert_chunks(document):
+ first_re = re.compile(r'<<(.*)>>=(.*)')
+ file_pos = 0
+ while True:
+ # find start of a block of chunks
+ i = find_token(document.body, "\\begin_layout Chunk", file_pos)
+ if i == -1:
+ return
+ start = i
+ end = -1
+ contents = []
+ chunk_started = False
+
+ while True:
+ # process the one we just found
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
+ # there is no point continuing, as we will run into the same error again.
+ return
+ this_chunk = "".join(document.body[i + 1:j])
+
+ # there may be empty lines between chunks
+ # we just skip them.
+ if not chunk_started:
+ if this_chunk != "":
+ # new chunk starts
+ chunk_started = True
+
+ if chunk_started:
+ contents.append(document.body[i + 1:j])
+
+ # look for potential chunk terminator
+ # on the last line of the chunk paragraph
+ if document.body[j - 1] == "@":
+ break
+
+ # look for subsequent chunk paragraph
+ i = find_token(document.body, "\\begin_layout", j)
+ if i == -1:
+ break
+
+ if get_value(document.body, "\\begin_layout", i) != "Chunk":
+ break
+
+ file_pos = end = j + 1
+
+ # The last chunk should simply have an "@" in it
+ # or at least end with "@" (can happen if @ is
+ # preceded by a newline)
+ lastpar = ''
+ if len(contents) > 0:
+ lastpar = ''.join(contents[-1])
+ if not lastpar.endswith("@"):
+ document.warning("Unexpected chunk content: chunk not terminated by '@'!")
+ if len(contents) == 0:
+ # convert empty chunk layouts to Standard
+ document.body[start] = "\\begin_layout Standard"
+ continue
+
+ if lastpar == "@":
+ # chunk par only contains "@". Just drop it.
+ contents.pop()
+ else:
+ # chunk par contains more. Only drop the "@".
+ contents[-1].pop()
+
+ # The first line should look like: <<CONTENT>>=
+ # We want the CONTENT
+ optarg = ' '.join(contents[0])
+ optarg.strip()
+ # We can already have real chunk content in
+ # the first par (separated from the options by a newline).
+ # We collect such stuff to re-insert it later.
+ postoptstuff = []
+
+ match = first_re.search(optarg)
+ if match:
+ optarg = match.groups()[0]
+ if match.groups()[1] != "":
+ postopt = False
+ for c in contents[0]:
+ if c.endswith(">>="):
+ postopt = True
+ continue
+ if postopt:
+ postoptstuff.append(c)
+ # We have stripped everything. This can be deleted.
+ contents.pop(0)
+
+ newstuff = ['\\begin_layout Standard']
+
+ # Maintain paragraph parameters
+ par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
+ "\\start_of_appendix", "\\paragraph_spacing", "\\align",
+ "\\labelwidthstring"]
+ parms = start + 1
+ while True:
+ if document.body[parms].split(' ', 1)[0] not in par_params:
+ break
+ newstuff.extend([document.body[parms]])
+ parms += 1
+
+ newstuff.extend(
+ ['\\begin_inset Flex Chunk',
+ 'status open', '',
+ '\\begin_layout Plain Layout', ''])
+
+ # If we have a non-empty optional argument, insert it.
+ if match and optarg != "":
+ newstuff.extend(
+ ['\\begin_inset Argument 1',
+ 'status open', '',
+ '\\begin_layout Plain Layout',
+ optarg,
+ '\\end_layout', '',
+ '\\end_inset', ''])
+
+ # Since we already opened a Plain layout, the first paragraph
+ # does not need to do that.
+ did_one_par = False
+ if postoptstuff:
+ # we need to replace newlines with new layouts
+ start_newline = -1
+ started_text = False
+ for lno in range(0,len(postoptstuff)):
+ if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
+ start_newline = lno
+ elif start_newline != -1:
+ if postoptstuff[lno].startswith("\\end_inset"):
+ # replace that bit, but only if we already have some text
+ # and we're not at the end except for a blank line
+ if started_text and \
+ (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
+ newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
+ start_newline = -1
+ started_text = True
+ else:
+ newstuff.extend([postoptstuff[lno]])
+ newstuff.append('\\end_layout')
+ did_one_par = True
+ for c in contents:
+ if did_one_par:
+ newstuff.extend(['', '\\begin_layout Plain Layout', ''])
+ else:
+ did_one_par = True
+ newstuff.extend(c)
+ newstuff.append('\\end_layout')
+
+ newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
+
+ document.body[start:end] = newstuff
+
+ file_pos += len(newstuff) - (end - start)
+
+
+def revert_chunks(document):
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Flex Chunk", i)
+ if i == -1:
+ return
+
+ iend = find_end_of_inset(document.body, i)
+ if iend == -1:
+ document.warning("Can't find end of Chunk!")
+ i += 1
+ continue
+
+ # Look for optional argument
+ optarg = ""
+ ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
+ if ostart != -1:
+ oend = find_end_of_inset(document.body, ostart)
+ k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
+ if k == -1:
+ document.warning("Malformed LyX document: Can't find argument contents!")
+ else:
+ m = find_end_of_layout(document.body, k)
+ optarg = "".join(document.body[k+1:m])
+
+ # We now remove the optional argument, so we have something
+ # uniform on which to work
+ document.body[ostart : oend + 1] = []
+ # iend is now invalid
+ iend = find_end_of_inset(document.body, i)
+
+ retval = get_containing_layout(document.body, i)
+ if not retval:
+ document.warning("Can't find containing layout for Chunk!")
+ i = iend
+ continue
+ (lname, lstart, lend, pstart) = retval
+ # we now want to work through the various paragraphs, and collect their contents
+ parlist = []
+ k = i
+ while True:
+ k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
+ if k == -1:
+ break
+ j = find_end_of_layout(document.body, k)
+ if j == -1:
+ document.warning("Can't find end of layout inside chunk!")
+ break
+ parlist.append(document.body[k+1:j])
+ k = j
+ # we now need to wrap all of these paragraphs in chunks
+ newlines = []
+ newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
+ for stuff in parlist:
+ newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
+ newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
+ # replace old content with new content
+ document.body[lstart : lend + 1] = newlines
+ i = lstart + len(newlines)
+
+