]> git.lyx.org Git - lyx.git/blobdiff - lib/lyx2lyx/lyx_2_1.py
Improved LYX_BUILD_TYPE detection for cmake - case insensitive AC_INIT processing
[lyx.git] / lib / lyx2lyx / lyx_2_1.py
index fa6a224ec28067f12a406215dd458b048e0cda4c..af9f1e6d76c2edf59dc51d9ba7673f46e1523b7b 100644 (file)
@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 # This file is part of lyx2lyx
-# -*- coding: utf-8 -*-
 # Copyright (C) 2011 The LyX team
 #
 # This program is free software; you can redistribute it and/or
@@ -25,7 +24,8 @@ import sys, os
 
 # Uncomment only what you need to import, please.
 
-from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
+from parser_tools import count_pars_in_inset, del_complete_lines, del_token, \
+    find_token, find_token_exact, \
     find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
     find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
     get_containing_inset, get_value, get_quoted_value, set_option_value
@@ -34,7 +34,7 @@ from parser_tools import count_pars_in_inset, del_token, find_token, find_token_
   #find_end_of_inset, find_end_of_layout, \
   #is_in_inset, del_token, check_token
 
-from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
+from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert, revert_language
 
 #from lyx2lyx_tools import insert_to_preamble, \
 #  lyx2latex, latex_length, revert_flex_inset, \
@@ -59,7 +59,7 @@ def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment,
     usage:
     revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt)
     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
+    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
@@ -117,7 +117,7 @@ def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, o
     isInset must be true, if braces inside an InsetLayout needs to be converted
     isEnvironment must be true, if the layout is for a LaTeX environment
     isOpt must be true, if the argument is an optional one
-    
+
     Todo: this routine can currently handle only one mandatory argument of environments
     '''
 
@@ -168,7 +168,7 @@ def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, o
           n += 1
           endn = end
           loop += 1
-        else: 
+        else:
           # no brace pair found
           # now check the case that we have "}" + "{" in two ERTs
           if opt:
@@ -181,7 +181,7 @@ def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, o
             else:
               beginBrace = find_token(document.body, "{", endBrace, end_layout)
             # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
-            if beginBrance != -1 and (beginBrace == endBrace + 11 or beginBrace == endBrace + 12):
+            if beginBrace != -1 and (beginBrace == endBrace + 11 or beginBrace == endBrace + 12):
               end = find_token(document.body, "\\end_inset", beginBrace)
               document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
               if loop == 1:
@@ -219,6 +219,13 @@ def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, o
           else:
             lineERT += 1
       if environment == True:
+        # FIXME This version of the routine does not check for and pass over
+        # arguments before n. So it attempts to process the argument in the
+        # document, no matter what has been specified.
+        #
+        # The other branch does do that, but probably that code would be better
+        # in a single location: Skip all those arguments, then process the ones
+        # we want.
         end_ERT = find_end_of_inset(document.body, lineERT)
         if end_ERT == -1:
           document.warning("Can't find end of ERT!!")
@@ -254,6 +261,9 @@ def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, o
               document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
             document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
           n += 1
+        else:
+          document.warning("Unable to process argument!")
+          n += 1
 
 
 ###############################################################################
@@ -343,7 +353,7 @@ def revert_undertilde(document):
 
 
 def revert_negative_space(document):
-    "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
+    "Revert InsetSpace negmedspace and negthickspace into their TeX-code counterparts"
     i = 0
     j = 0
     reverted = False
@@ -356,7 +366,7 @@ def revert_negative_space(document):
           if reverted == True:
             i = find_token(document.header, "\\use_amsmath 2", 0)
             if i == -1:
-              add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
+              add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}{}"])
           return
       if i == -1:
         return
@@ -439,16 +449,16 @@ def revert_justification(document):
 
 
 def revert_australian(document):
-    "Set English language variants Australian and Newzealand to English" 
+    "Set English language variants Australian and Newzealand to English"
 
-    if document.language == "australian" or document.language == "newzealand": 
+    if document.language == "australian" or document.language == "newzealand":
         document.language = "english"
-        i = find_token(document.header, "\\language", 0) 
-        if i != -1: 
-            document.header[i] = "\\language english" 
-    j = 0 
-    while True: 
-        j = find_token(document.body, "\\lang australian", j) 
+        i = find_token(document.header, "\\language", 0)
+        if i != -1:
+            document.header[i] = "\\language english"
+    j = 0
+    while True:
+        j = find_token(document.body, "\\lang australian", j)
         if j == -1:
             j = find_token(document.body, "\\lang newzealand", 0)
             if j == -1:
@@ -456,7 +466,7 @@ def revert_australian(document):
             else:
                 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
         else:
-            document.body[j] = document.body[j].replace("\\lang australian", "\\lang english") 
+            document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
         j += 1
 
 
@@ -546,8 +556,6 @@ def handle_longtable_captions(document, forward):
                     get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
                     document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
             elif get_option_value(document.body[begin_row], 'caption') == 'true':
-                if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
-                    document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
                 if get_option_value(document.body[begin_row], 'endhead') == 'true':
                     document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
                 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
@@ -555,7 +563,7 @@ def handle_longtable_captions(document, forward):
                 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
                     document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
             begin_row = end_row
-        # since there could be a tabular inside this one, we 
+        # since there could be a tabular inside this one, we
         # cannot jump to end.
         begin_table += 1
 
@@ -609,15 +617,16 @@ def convert_use_package(document, pkg, commands, oldauto):
     # oldauto defines how the version we are converting from behaves:
     # if it is true, the old version uses the package automatically.
     # if it is false, the old version never uses the package.
-    i = find_token(document.header, "\\use_package", 0)
+    i = find_token(document.header, "\\use_package")
     if i == -1:
         document.warning("Malformed LyX document: Can't find \\use_package.")
         return;
-    j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
-    if j != -1:
-        # package was loaded in the preamble, convert this to header setting for round trip
+    packageline = "\\usepackage{%s}" % pkg
+    if (del_complete_lines(document.preamble,
+                           ['% Added by lyx2lyx', packageline]) or
+        del_complete_lines(document.preamble, [packageline])):
+        # package was loaded in the preamble, convert this to header setting
         document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
-        del document.preamble[j]
     # If oldauto is true we have two options:
     # We can either set the package to auto - this is correct for files in
     # format 425 to 463, and may create a conflict for older files which use
@@ -965,9 +974,9 @@ def revert_cell_rotation(document):
             put_cmd_in_ert("\\end{turn}")
           document.body[i + 4 : i + 4] = \
             put_cmd_in_ert("\\begin{turn}{" + value + "}")
-        
+
       i += 1
-        
+
   finally:
     if load_rotating:
       add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
@@ -987,7 +996,7 @@ def convert_cell_rotation(document):
         rgx = re.compile(r'rotate="[^"]+?"')
         # convert "true" to "90"
         document.body[i] = rgx.sub('rotate="90"', document.body[i])
-        
+
       i += 1
 
 
@@ -1024,9 +1033,9 @@ def revert_table_rotation(document):
             put_cmd_in_ert("\\end{turn}")
           document.body[i - 2 : i - 2] = \
             put_cmd_in_ert("\\begin{turn}{" + value + "}")
-        
+
       i += 1
-        
+
   finally:
     if load_rotating:
       add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
@@ -1046,12 +1055,12 @@ def convert_table_rotation(document):
         rgx = re.compile(r'rotate="[^"]+?"')
         # convert "true" to "90"
         document.body[i] = rgx.sub('rotate="90"', document.body[i])
-        
+
       i += 1
 
 
 def convert_listoflistings(document):
-    'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
+    r'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
     # We can support roundtrip because the command is so simple
     i = 0
     while True:
@@ -1140,68 +1149,60 @@ def revert_use_cancel(document):
 
 
 def revert_ancientgreek(document):
-    "Set the document language for ancientgreek to greek" 
+    "Set the document language for ancientgreek to greek"
 
-    if document.language == "ancientgreek": 
+    if document.language == "ancientgreek":
         document.language = "greek"
-        i = find_token(document.header, "\\language", 0) 
-        if i != -1: 
-            document.header[i] = "\\language greek" 
-    j = 0 
-    while True: 
-        j = find_token(document.body, "\\lang ancientgreek", j) 
+        i = find_token(document.header, "\\language", 0)
+        if i != -1:
+            document.header[i] = "\\language greek"
+    j = 0
+    while True:
+        j = find_token(document.body, "\\lang ancientgreek", j)
         if j == -1:
             return
         else:
-            document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek") 
+            document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
         j += 1
 
 
 def revert_languages(document):
-    "Set the document language for new supported languages to English" 
-
-    languages = [
-                 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
-                 "syriac", "tamil", "telugu", "urdu"
-                ]
-    for n in range(len(languages)):
-        if document.language == languages[n]:
-            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 " + languages[n], j)
-            if j != -1:
-                document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
-                j += 1
-            else:
-                j = len(document.body)
+    "Set the document language for new supported languages to English"
+
+    # polyglossia-only
+    polyglossia_languages = ["coptic", "divehi", "hindi", "lao", "marathi",
+                             "occitan", "sanskrit", "syriac", "tamil",
+                             "telugu", "urdu"]
+    # babel-only
+    babel_languages = ["kurmanji"]
+    for lang in polyglossia_languages:
+        revert_language(document, lang, "", lang)
+    for lang in babel_languages:
+        revert_language(document, lang, lang, "")
 
 
 def convert_armenian(document):
-    "Use polyglossia and thus non-TeX fonts for Armenian" 
+    "Use polyglossia and thus non-TeX fonts for Armenian"
 
-    if document.language == "armenian": 
-        i = find_token(document.header, "\\use_non_tex_fonts", 0) 
-        if i != -1: 
-            document.header[i] = "\\use_non_tex_fonts true" 
+    if document.language == "armenian":
+        i = find_token(document.header, "\\use_non_tex_fonts", 0)
+        if i != -1:
+            document.header[i] = "\\use_non_tex_fonts true"
 
 
 def revert_armenian(document):
-    "Use ArmTeX and thus TeX fonts for Armenian" 
+    "Use ArmTeX and thus TeX fonts for Armenian"
 
-    if document.language == "armenian": 
-        i = find_token(document.header, "\\use_non_tex_fonts", 0) 
-        if i != -1: 
-            document.header[i] = "\\use_non_tex_fonts false" 
+    if document.language == "armenian":
+        i = find_token(document.header, "\\use_non_tex_fonts", 0)
+        if i != -1:
+            document.header[i] = "\\use_non_tex_fonts false"
 
 
 def revert_libertine(document):
-    " Revert native libertine font definition to LaTeX " 
+    " Revert native libertine font definition to LaTeX "
 
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         i = find_token(document.header, "\\font_roman libertine", 0)
         if i != -1:
             osf = False
@@ -1220,9 +1221,9 @@ def revert_libertine(document):
 
 
 def revert_txtt(document):
-    " Revert native txtt font definition to LaTeX " 
+    " Revert native txtt font definition to LaTeX "
 
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         i = find_token(document.header, "\\font_typewriter txtt", 0)
         if i != -1:
             preamble = "\\renewcommand{\\ttdefault}{txtt}"
@@ -1231,9 +1232,9 @@ def revert_txtt(document):
 
 
 def revert_mathdesign(document):
-    " Revert native mathdesign font definition to LaTeX " 
+    " Revert native mathdesign font definition to LaTeX "
 
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         mathdesign_dict = {
         "mdbch":  "charter",
         "mdput":  "utopia",
@@ -1262,9 +1263,9 @@ def revert_mathdesign(document):
 
 
 def revert_texgyre(document):
-    " Revert native TeXGyre font definition to LaTeX " 
+    " Revert native TeXGyre font definition to LaTeX "
 
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
                          "tgheros", "tgpagella", "tgschola", "tgtermes"]
         i = find_token(document.header, "\\font_roman", 0)
@@ -1321,7 +1322,7 @@ def revert_ipadeco(document):
           i = end
           continue
       substi = ["\\begin_inset ERT", "status collapsed", "",
-                "\\begin_layout Plain Layout", "", "", "\\backslash", 
+                "\\begin_layout Plain Layout", "", "", "\\backslash",
                 decotype + "{", "\\end_layout", "", "\\end_inset"]
       substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
                 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
@@ -1361,9 +1362,9 @@ def revert_ipachar(document):
 
 
 def revert_minionpro(document):
-    " Revert native MinionPro font definition to LaTeX " 
+    " Revert native MinionPro font definition to LaTeX "
 
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         i = find_token(document.header, "\\font_roman minionpro", 0)
         if i != -1:
             osf = False
@@ -1381,12 +1382,12 @@ def revert_minionpro(document):
 
 
 def revert_mathfonts(document):
-    " Revert native math font definitions to LaTeX " 
+    " Revert native math font definitions to LaTeX "
 
     i = find_token(document.header, "\\font_math", 0)
     if i == -1:
        return
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         val = get_value(document.header, "\\font_math", i)
         if val == "eulervm":
             add_to_preamble(document, "\\usepackage{eulervm}")
@@ -1416,9 +1417,9 @@ def revert_mathfonts(document):
 
 
 def revert_mdnomath(document):
-    " Revert mathdesign and fourier without math " 
+    " Revert mathdesign and fourier without math "
 
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         mathdesign_dict = {
         "md-charter": "mdbch",
         "md-utopia": "mdput",
@@ -1445,9 +1446,9 @@ def convert_mathfonts(document):
 
 
 def convert_mdnomath(document):
-    " Change mathdesign font name " 
+    " Change mathdesign font name "
 
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         mathdesign_dict = {
         "mdbch":  "md-charter",
         "mdput":  "md-utopia",
@@ -1462,12 +1463,12 @@ def convert_mdnomath(document):
 
 
 def revert_newtxmath(document):
-    " Revert native newtxmath definitions to LaTeX " 
+    " Revert native newtxmath definitions to LaTeX "
 
     i = find_token(document.header, "\\font_math", 0)
     if i == -1:
        return
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         val = get_value(document.header, "\\font_math", i)
         mathfont_dict = {
         "libertine-ntxm":  "\\usepackage[libertine]{newtxmath}",
@@ -1480,9 +1481,9 @@ def revert_newtxmath(document):
 
 
 def revert_biolinum(document):
-    " Revert native biolinum font definition to LaTeX " 
+    " Revert native biolinum font definition to LaTeX "
 
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         i = find_token(document.header, "\\font_sans biolinum", 0)
         if i != -1:
             osf = False
@@ -1546,10 +1547,11 @@ def convert_latexargs(document):
                     "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
                     "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
     # Modules we need to take care of
-    caveat_modules = ["initials"]
+    caveat_modules = ["initials"] # TODO: , "graphicboxes", "bicaption"]
     # information about the relevant styles in caveat_modules (number of opt and req args)
     # use this if we get more caveat_modules. For now, use hard coding (see below).
     # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
+    # graphicboxes = { ... }
 
     # Is this a known safe layout?
     safe_layout = document.textclass in safe_layouts
@@ -1585,7 +1587,7 @@ def convert_latexargs(document):
             document.body[i] = "\\begin_inset Argument 999"
             i += 1
             continue
-        
+
         # Find containing paragraph layout
         parent = get_containing_layout(document.body, i)
         if parent == False:
@@ -2164,7 +2166,7 @@ def revert_literate(document):
 
 def convert_literate(document):
     " Convert Literate document to new format"
-    i = find_token(document.header, "\\textclass", 0)    
+    i = find_token(document.header, "\\textclass", 0)
     if (i != -1) and "literate-" in document.header[i]:
       document.textclass = document.header[i].replace("\\textclass literate-", "")
       j = find_token(document.header, "\\begin_modules", 0)
@@ -2208,12 +2210,12 @@ def revert_itemargs(document):
 
 
 def revert_garamondx_newtxmath(document):
-    " Revert native garamond newtxmath definition to LaTeX " 
+    " Revert native garamond newtxmath definition to LaTeX "
 
     i = find_token(document.header, "\\font_math", 0)
     if i == -1:
        return
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         val = get_value(document.header, "\\font_math", i)
         if val == "garamondx-ntxm":
             add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
@@ -2221,9 +2223,9 @@ def revert_garamondx_newtxmath(document):
 
 
 def revert_garamondx(document):
-    " Revert native garamond font definition to LaTeX " 
+    " Revert native garamond font definition to LaTeX "
 
-    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: 
+    if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
         i = find_token(document.header, "\\font_roman garamondx", 0)
         if i != -1:
             osf = False
@@ -2240,7 +2242,7 @@ def revert_garamondx(document):
 
 def convert_beamerargs(document):
     " Converts beamer arguments to new layout "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
@@ -2411,7 +2413,7 @@ def convert_againframe_args(document):
     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 AgainFrame", i)
@@ -2433,11 +2435,11 @@ def convert_againframe_args(document):
 
 def convert_corollary_args(document):
     " Converts beamer corrolary-style ERT arguments native InsetArgs "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
-   
+
     corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
     for lay in corollary_layouts:
         i = 0
@@ -2523,11 +2525,11 @@ def convert_corollary_args(document):
 
 def convert_quote_args(document):
     " Converts beamer quote style ERT args to native InsetArgs "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
-   
+
     quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
     for lay in quote_layouts:
         i = 0
@@ -2592,7 +2594,7 @@ def cleanup_beamerargs(document):
 
 def revert_beamerargs(document):
     " Reverts beamer arguments to old layout "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
@@ -2783,13 +2785,13 @@ def revert_beamerargs(document):
                         del document.body[p : endInset + 1]
                         subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
                         document.body[realparbeg : realparbeg] = subst
-        
+
         i = realparend
 
 
 def revert_beamerargs2(document):
     " Reverts beamer arguments to old layout, step 2 "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
@@ -2823,7 +2825,7 @@ def revert_beamerargs2(document):
                 if m:
                     argnr = m.group(1)
                     if argnr == "2":
-                        document.body[p] = "\\begin_inset Argument 1"       
+                        document.body[p] = "\\begin_inset Argument 1"
             if layoutname in corollary_layouts:
                 m = rx.match(document.body[p])
                 if m:
@@ -2874,7 +2876,7 @@ def revert_beamerargs2(document):
 
 def revert_beamerargs3(document):
     " Reverts beamer arguments to old layout, step 3 "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
@@ -2920,7 +2922,7 @@ def revert_beamerargs3(document):
 
 def revert_beamerflex(document):
     " Reverts beamer Flex insets "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
@@ -3020,13 +3022,13 @@ def revert_beamerflex(document):
                 document.body[i : beginPlain + 1] = pre
                 post = put_cmd_in_ert("}")
                 document.body[z - 2 : z + 1] = post
-        
+
         i += 1
 
 
 def revert_beamerblocks(document):
     " Reverts beamer block arguments to ERT "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
@@ -3086,11 +3088,11 @@ def revert_beamerblocks(document):
 
 def convert_beamerblocks(document):
     " Converts beamer block ERT args to native InsetArgs "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
-   
+
     blocks = ["Block", "ExampleBlock", "AlertBlock"]
     for lay in blocks:
         i = 0
@@ -3201,7 +3203,7 @@ def convert_beamerblocks(document):
                                                 document.body[ertcontlastline : ertcontlastline + 1] = [
                                                                                     document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
                                                 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
-                                                                                    '\\end_layout', '', '\\end_inset', '', '\\end_layout', '', 
+                                                                                    '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
                                                                                     '\\end_inset', '', '', '\\begin_inset Argument 2',
                                                                                     'status collapsed', '', '\\begin_layout Plain Layout',
                                                                                     '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
@@ -3290,7 +3292,7 @@ def convert_beamerblocks(document):
                                                         document.body[ertcontlastline : ertcontlastline + 1] = [
                                                                                             document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
                                                         document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
-                                                                                            '\\end_layout', '', '\\end_inset', '', '\\end_layout', '', 
+                                                                                            '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
                                                                                             '\\end_inset', '', '', '\\begin_inset Argument 1',
                                                                                             'status collapsed', '', '\\begin_layout Plain Layout',
                                                                                             '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
@@ -3336,7 +3338,7 @@ def convert_beamerblocks(document):
 
 def convert_overprint(document):
     " Convert old beamer overprint layouts to ERT "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
@@ -3376,11 +3378,11 @@ def convert_overprint(document):
             # Remove arg inset
             del document.body[argbeg : argend + 1]
             subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
-            
+
         endseq = endseq - len(document.body[i : i])
         document.body[i : i] = subst + ["\\end_layout"]
         endseq += len(subst)
-        
+
         for p in range(i, endseq):
             if document.body[p] == "\\begin_layout Overprint":
                 document.body[p] = "\\begin_layout Standard"
@@ -3390,7 +3392,7 @@ def convert_overprint(document):
 
 def revert_overprint(document):
     " Revert old beamer overprint layouts to ERT "
-    
+
     beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
     if document.textclass not in beamer_classes:
         return
@@ -3442,11 +3444,11 @@ def revert_overprint(document):
                 # Remove arg inset
                 del document.body[argbeg : argend + 1]
                 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
-            
+
         endseq = endseq - len(document.body[i : i])
         document.body[i : i] = subst + ["\\end_layout"]
         endseq += len(subst)
-     
+
         p = i
         while True:
             if p >= endseq:
@@ -3482,7 +3484,7 @@ def revert_overprint(document):
 
 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
@@ -3528,7 +3530,7 @@ def revert_frametitle(document):
                     # 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
@@ -3536,7 +3538,7 @@ def revert_frametitle(document):
 
 def convert_epigraph(document):
     " Converts memoir epigraph to new syntax "
-    
+
     if document.textclass != "memoir":
         return
 
@@ -3571,13 +3573,13 @@ def convert_epigraph(document):
                 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
 
@@ -3606,14 +3608,14 @@ def revert_epigraph(document):
             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)
@@ -3625,7 +3627,7 @@ def convert_captioninsets(document):
 
 def revert_captioninsets(document):
     " Reverts caption insets to old syntax "
-    
+
     i = 0
     while True:
       i = find_token(document.body, "\\begin_inset Caption Standard", i)
@@ -3647,28 +3649,27 @@ def convert_captionlayouts(document):
         "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()):
+    for captype in caption_dict.keys():
+        i = 0
+        while True:
+            i = find_token(document.body, "\\begin_layout " + captype, i)
+            if i == -1:
+                break
             j = find_end_of_layout(document.body, i)
             if j == -1:
                 document.warning("Malformed LyX document: Missing `\\end_layout'.")
-                return
+                break
 
             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_inset Caption %s" % caption_dict[captype], "",
                                     "\\begin_layout %s" % document.default_layout]
-        i += 1
+            i = j + 1
 
 
 def revert_captionlayouts(document):
     " Revert caption insets to caption layouts. "
-    
+
     caption_dict = {
         "Above" : "Captionabove",
         "Below" : "Captionbelow",
@@ -3677,7 +3678,7 @@ def revert_captionlayouts(document):
         "Centered" : "CenteredCaption",
         "Bicaption" : "Bicaption",
         }
-    
+
     i = 0
     rx = re.compile(r'^\\begin_inset Caption (\S+)$')
     while True:
@@ -3692,7 +3693,7 @@ def revert_captionlayouts(document):
         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.
@@ -3760,7 +3761,7 @@ def revert_captionlayouts(document):
 
 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
@@ -3842,14 +3843,14 @@ def revert_fragileframe(document):
                     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
@@ -3944,7 +3945,7 @@ def revert_newframes(document):
                     # Remove arg inset
                     del document.body[arg : endInset + 1]
                     subst += content
-                    
+
         document.body[i : i + 1] = subst
         i = j
 
@@ -4069,18 +4070,18 @@ def revert_IEEEtran_3(document):
 
 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: 
+    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: 
+
+  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:
@@ -4091,18 +4092,18 @@ def revert_kurier_fonts(document):
 
 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: 
+    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: 
+
+  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:
@@ -4114,7 +4115,7 @@ def revert_iwona_fonts(document):
 
 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
 
@@ -4130,7 +4131,7 @@ def revert_new_libertines(document):
         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"
@@ -4155,11 +4156,11 @@ def revert_new_libertines(document):
 
 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*"]
@@ -4228,11 +4229,11 @@ def convert_lyxframes(document):
 
 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)
@@ -4248,7 +4249,7 @@ def remove_endframes(document):
 
 def revert_powerdot_flexes(document):
     " Reverts powerdot flex insets "
-    
+
     if document.textclass != "powerdot":
         return
 
@@ -4296,13 +4297,13 @@ def revert_powerdot_flexes(document):
                 z += len(pre)
                 document.body[i : beginPlain + 1] = pre
                 post = put_cmd_in_ert("}")
-                document.body[z - 2 : z + 1] = post     
+                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
 
@@ -4332,14 +4333,14 @@ def revert_powerdot_pause(document):
                 # 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
 
@@ -4388,7 +4389,7 @@ def revert_powerdot_itemargs(document):
                         del document.body[i:j+1]
                         subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
                         document.body[realparbeg : realparbeg] = subst
-        
+
         i = realparend
 
 
@@ -4438,7 +4439,7 @@ def revert_powerdot_columns(document):
                     # 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
@@ -4475,7 +4476,7 @@ def revert_mbox_fbox(document):
 
 def revert_starred_caption(document):
     " Reverts unnumbered longtable caption insets "
-    
+
     i = 0
     while True:
       i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
@@ -4550,21 +4551,9 @@ def revert_aa2(document):
 
 
 def revert_tibetan(document):
-    "Set the document language for Tibetan to English" 
+    "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)
+    revert_language(document, "tibetan", "", "tibetan")
 
 
 #############
@@ -4602,14 +4591,14 @@ def convert_chunks(document):
                 # 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])
 
@@ -4656,7 +4645,7 @@ def convert_chunks(document):
         # 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]
@@ -4796,7 +4785,7 @@ def revert_chunks(document):
         # replace old content with new content
         document.body[lstart : lend + 1] = newlines
         i = lstart + len(newlines)
-        
+
 
 ##
 # Conversion hub