]> git.lyx.org Git - lyx.git/blobdiff - lib/lyx2lyx/lyx_2_1.py
Format and reversion code for new counter inset.
[lyx.git] / lib / lyx2lyx / lyx_2_1.py
index 2e53a6fd799e46e900084280eec37045e587d6d6..133d500f9ff31a26142586f6d8a6435504219c39 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, \
@@ -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
 
 
 ###############################################################################
@@ -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
@@ -838,7 +847,7 @@ def revert_verbatim(document, starred = False):
                    'begin{%s}' % (latex_name),
                    '\\end_layout', '', '\\begin_layout Plain Layout', '']
 
-    while 1:
+    while True:
         i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
         if i == -1:
             return
@@ -850,7 +859,7 @@ def revert_verbatim(document, starred = False):
             continue
         # delete all line breaks insets (there are no other insets)
         l = i
-        while 1:
+        while True:
             n = find_token(document.body, "\\begin_inset Newline newline", l, j)
             if n == -1:
                 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
@@ -898,7 +907,7 @@ def revert_verbatim(document, starred = False):
 def revert_tipa(document):
     " Revert native TIPA insets to mathed or ERT. "
     i = 0
-    while 1:
+    while True:
         i = find_token(document.body, "\\begin_inset IPA", i)
         if i == -1:
             return
@@ -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,7 +1055,7 @@ 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
 
 
@@ -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