]> git.lyx.org Git - lyx.git/blobdiff - lib/lyx2lyx/lyx_2_0.py
Simplify the get_value routines a bit.
[lyx.git] / lib / lyx2lyx / lyx_2_0.py
index 1a7a266193ebb3ee2835154bd0a02a6f9c05b836..e181d61ea0d02695c3beba32a46f45a9ef8cd4ad 100644 (file)
@@ -24,7 +24,8 @@ import unicodedata
 import sys, os
 
 from parser_tools import find_token, find_end_of, find_tokens, \
-  find_end_of_inset, find_end_of_layout, get_value, get_value_string
+  find_end_of_inset, find_end_of_layout, find_token_backwards, \
+  get_containing_inset, get_value, get_value_string
   
 from lyx2lyx_tools import add_to_preamble, insert_to_preamble, \
   put_cmd_in_ert, lyx2latex, latex_length, revert_flex_inset, \
@@ -33,13 +34,13 @@ from lyx2lyx_tools import add_to_preamble, insert_to_preamble, \
 ####################################################################
 # Private helper functions
 
-def remove_option(document, m, option):
+def remove_option(lines, m, option):
     ''' removes option from line m. returns whether we did anything '''
-    l = document.body[m].find(option)
+    l = lines[m].find(option)
     if l == -1:
         return False
-    val = document.body[m][l:].split('"')[1]
-    document.body[m] = document.body[m][:l - 1] + document.body[m][l+len(option + '="' + val + '"'):]
+    val = lines[m][l:].split('"')[1]
+    lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
     return True
 
 
@@ -832,6 +833,10 @@ def revert_mhchem(document):
             mhchem = "on"
         del document.header[i]
 
+    if mhchem == "off":
+      # don't load case
+      return 
+
     if mhchem == "auto":
         i = 0
         while True:
@@ -839,7 +844,7 @@ def revert_mhchem(document):
             if i == -1:
                break
             line = document.body[i]
-            if line.find("\\ce{") != -1 or line.find("\\cf{") != 1:
+            if line.find("\\ce{") != -1 or line.find("\\cf{") != -1:
               mhchem = "on"
               break
             i += 1
@@ -1300,7 +1305,6 @@ def revert_math_scale(document):
 
 
 def revert_pagesizes(document):
-  i = 0
   " Revert page sizes to default "
   i = find_token(document.header, '\\papersize', 0)
   if i != -1:
@@ -1314,7 +1318,6 @@ def revert_pagesizes(document):
 
 
 def revert_DIN_C_pagesizes(document):
-  i = 0
   " Revert DIN C page sizes to default "
   i = find_token(document.header, '\\papersize', 0)
   if i != -1:
@@ -1333,7 +1336,7 @@ def convert_html_quotes(document):
     line = document.header[i]
     l = re.compile(r'\\html_latex_start\s+"(.*)"')
     m = l.match(line)
-    if m != None:
+    if m:
       document.header[i] = "\\html_latex_start " + m.group(1)
       
   i = find_token(document.header, '\\html_latex_end', 0)
@@ -1341,7 +1344,7 @@ def convert_html_quotes(document):
     line = document.header[i]
     l = re.compile(r'\\html_latex_end\s+"(.*)"')
     m = l.match(line)
-    if m != None:
+    if m:
       document.header[i] = "\\html_latex_end " + m.group(1)
       
 
@@ -1353,14 +1356,22 @@ def revert_html_quotes(document):
     line = document.header[i]
     l = re.compile(r'\\html_latex_start\s+(.*)')
     m = l.match(line)
-    document.header[i] = "\\html_latex_start \"" + m.group(1) + "\""
+    if not m:
+        document.warning("Weird html_latex_start line: " + line)
+        del document.header[i]
+    else:
+        document.header[i] = "\\html_latex_start \"" + m.group(1) + "\""
       
   i = find_token(document.header, '\\html_latex_end', 0)
   if i != -1:
     line = document.header[i]
     l = re.compile(r'\\html_latex_end\s+(.*)')
     m = l.match(line)
-    document.header[i] = "\\html_latex_end \"" + m.group(1) + "\""
+    if not m:
+        document.warning("Weird html_latex_end line: " + line)
+        del document.header[i]
+    else:
+        document.header[i] = "\\html_latex_end \"" + m.group(1) + "\""
 
 
 def revert_output_sync(document):
@@ -1373,106 +1384,34 @@ def revert_output_sync(document):
     del document.header[i]
 
 
-def convert_beamer_args(document):
-  " Convert ERT arguments in Beamer to InsetArguments "
-
-  if document.textclass != "beamer" and document.textclass != "article-beamer":
-    return
-  
-  layouts = ("Block", "ExampleBlock", "AlertBlock")
-  for layout in layouts:
-    blay = 0
-    while True:
-      blay = find_token(document.body, '\\begin_layout ' + layout, blay)
-      if blay == -1:
-        break
-      elay = find_end_of(document.body, blay, '\\begin_layout', '\\end_layout')
-      if elay == -1:
-        document.warning("Malformed LyX document: Can't find end of " + layout + " layout.")
-        blay += 1
-        continue
-      bert = find_token(document.body, '\\begin_inset ERT', blay)
-      if bert == -1:
-        document.warning("Malformed Beamer LyX document: Can't find argument of " + layout + " layout.")
-        blay = elay + 1
-        continue
-      eert = find_end_of_inset(document.body, bert)
-      if eert == -1:
-        document.warning("Malformed LyX document: Can't find end of ERT.")
-        blay = elay + 1
-        continue
-      
-      # So the ERT inset begins at line k and goes to line l. We now wrap it in 
-      # an argument inset.
-      # Do the end first, so as not to mess up the variables.
-      document.body[eert + 1:eert + 1] = ['', '\\end_layout', '', '\\end_inset', '']
-      document.body[bert:bert] = ['\\begin_inset OptArg', 'status open', '', 
-          '\\begin_layout Plain Layout']
-      blay = elay + 9
-
-
-def revert_beamer_args(document):
-  " Revert Beamer arguments to ERT "
-  
-  if document.textclass != "beamer" and document.textclass != "article-beamer":
-    return
-    
-  layouts = ("Block", "ExampleBlock", "AlertBlock")
-  for layout in layouts:
-    blay = 0
-    while True:
-      blay = find_token(document.body, '\\begin_layout ' + layout, blay)
-      if blay == -1:
-        break
-      elay = find_end_of(document.body, blay, '\\begin_layout', '\\end_layout')
-      if elay == -1:
-        document.warning("Malformed LyX document: Can't find end of " + layout + " layout.")
-        blay += 1
-        continue
-      bopt = find_token(document.body, '\\begin_inset OptArg', blay)
-      if bopt == -1:
-        # it is legal not to have one of these
-        blay = elay + 1
-        continue
-      eopt = find_end_of_inset(document.body, bopt)
-      if eopt == -1:
-        document.warning("Malformed LyX document: Can't find end of argument.")
-        blay = elay + 1
-        continue
-      bplay = find_token(document.body, '\\begin_layout Plain Layout', blay)
-      if bplay == -1:
-        document.warning("Malformed LyX document: Can't find plain layout.")
-        blay = elay + 1
-        continue
-      eplay = find_end_of(document.body, bplay, '\\begin_layout', '\\end_layout')
-      if eplay == -1:
-        document.warning("Malformed LyX document: Can't find end of plain layout.")
-        blay = elay + 1
-        continue
-      # So the content of the argument inset goes from bplay + 1 to eplay - 1
-      bcont = bplay + 1
-      if bcont >= eplay:
-        # Hmm.
-        document.warning(str(bcont) + " " + str(eplay))
-        blay = blay + 1
-        continue
-      # we convert the content of the argument into pure LaTeX...
-      content = lyx2latex(document, document.body[bcont:eplay])
-      strlist = put_cmd_in_ert(["{" + content + "}"])
-      
-      # now replace the optional argument with the ERT
-      document.body[bopt:eopt + 1] = strlist
-      blay = blay + 1
-
-
 def revert_align_decimal(document):
-  l = 0
+  i = 0
   while True:
-    l = document.body[l].find('alignment=decimal')
-    if l == -1:
-        break
-    remove_option(document, l, 'decimal_point')
-    document.body[l].replace('decimal', 'center')
+    i = find_token(document.body, "\\begin_inset Tabular", i)
+    if i == -1:
+      return
+    j = find_end_of_inset(document.body, i)
+    if j == -1:
+      document.warning("Unable to find end of Tabular inset at line " + str(i))
+      i += 1
+      continue
+    cell = find_token(document.body, "<cell", i, j)
+    if cell == -1:
+      document.warning("Can't find any cells in Tabular inset at line " + str(i))
+      i = j
+      continue
+    k = i + 1
+    while True:
+      k = find_token(document.body, "<column", k, cell)
+      if k == -1:
+        return
+      if document.body[k].find('alignment="decimal"') == -1:
+        k += 1
+        continue
+      remove_option(document.body, k, 'decimal_point')
+      document.body[k] = \
+        document.body[k].replace('alignment="decimal"', 'alignment="center"')
+      k += 1
 
 
 def convert_optarg(document):
@@ -1504,63 +1443,73 @@ def revert_makebox(document):
     # only revert frameless boxes without an inner box
     i = find_token(document.body, '\\begin_inset Box Frameless', i)
     if i == -1:
-      # remove the option use_makebox
-      revert_use_makebox(document)
       return
     z = find_end_of_inset(document.body, i)
     if z == -1:
       document.warning("Malformed LyX document: Can't find end of box inset.")
-      return
-    j = find_token(document.body, 'use_makebox 1', i)
-    # assure we found the makebox of the current box
-    if j < z and j != -1:
-      y = find_token(document.body, "\\begin_layout", i)
-      if y > z or y == -1:
-        document.warning("Malformed LyX document: Can't find layout in box.")
-        return
-      # remove the \end_layout \end_inset pair
-      document.body[z - 2:z + 1] = put_cmd_in_ert("}")
-      # determine the alignment
-      k = find_token(document.body, 'hor_pos', j - 4)
-      align = document.body[k][9]
-      # determine the width
-      l = find_token(document.body, 'width "', j + 1)
-      length = document.body[l][7:]
-      # remove trailing '"'
-      length = length[:-1]
-      length = latex_length(length)[1]
-      subst = "\\makebox[" + length + "][" \
-        + align + "]{"
-      document.body[i:y + 1] = put_cmd_in_ert(subst)
+      i += 1
+      continue
+    blay = find_token(document.body, "\\begin_layout", i, z)
+    if blay == -1:
+      document.warning("Malformed LyX document: Can't find layout in box.")
+      i = z
+      continue
+    # by looking before the layout we make sure we're actually finding
+    # an option, not text.
+    j = find_token(document.body, 'use_makebox', i, blay)
+    if j == -1:
+        i = z
+        continue
+    val = get_value(document.body, 'use_makebox', j)
+    if val != "1":
+        del document.body[j]
+        i = z
+        continue
+    bend = find_end_of_layout(document.body, blay)
+    if bend == -1 or bend > z:
+        document.warning("Malformed LyX document: Can't find end of layout in box.")
+        i = z
+        continue
+    # determine the alignment
+    align = get_value(document.body, 'hor_pos', i, blay, "c").strip('"')
+    # determine the width
+    length = get_value(document.body, 'width', i, blay, "50col%").strip('"')
+    length = latex_length(length)[1]
+    # remove the \end_layout \end_inset pair
+    document.body[bend:z + 1] = put_cmd_in_ert("}")
+    subst = "\\makebox[" + length + "][" \
+      + align + "]{"
+    document.body[i:blay + 1] = put_cmd_in_ert(subst)
     i += 1
 
 
-def revert_use_makebox(document):
-  " Deletes use_makebox option of boxes "
-  h = 0
-  while 1:
-    # remove the option use_makebox
-    h = find_token(document.body, 'use_makebox', 0)
-    if h == -1:
-      return
-    del document.body[h]
-    h += 1
-
-
 def convert_use_makebox(document):
   " Adds use_makebox option for boxes "
   i = 0
   while 1:
-    # remove the option use_makebox
     i = find_token(document.body, '\\begin_inset Box', i)
     if i == -1:
       return
-    k = find_token(document.body, 'use_parbox', i)
+    # all of this is to make sure we actually find the use_parbox
+    # that is an option for this box, not some text elsewhere.
+    z = find_end_of_inset(document.body, i)
+    if z == -1:
+      document.warning("Can't find end of box inset!!")
+      i += 1
+      continue
+    blay = find_token(document.body, "\\begin_layout", i, z)
+    if blay == -1:
+      document.warning("Can't find layout in box inset!!")
+      i = z
+      continue
+    # so now we are looking for use_parbox before the box's layout
+    k = find_token(document.body, 'use_parbox', i, blay)
     if k == -1:
       document.warning("Malformed LyX document: Can't find use_parbox statement in box.")
-      return
+      i = z
+      continue
     document.body.insert(k + 1, "use_makebox 0")
-    i = k + 1
+    i = z + 1
 
 
 def revert_IEEEtran(document):
@@ -1582,7 +1531,7 @@ def revert_IEEEtran(document):
         i = find_token(document.body, '\\begin_layout ' + layout, i)
         if i == -1:
           break
-        j = find_end_of(document.body, i, '\\begin_layout', '\\end_layout')
+        j = find_end_of_layout(document.body, i)
         if j == -1:
           document.warning("Malformed LyX document: Can't find end of " + layout + " layout.")
           i += 1
@@ -1590,10 +1539,11 @@ def revert_IEEEtran(document):
         if layout in obsoletedby:
           document.body[i] = "\\begin_layout " + obsoletedby[layout]
           i = j
-        else:
-          content = lyx2latex(document, document.body[i:j + 1])
-          add_to_preamble(document, [latexcmd[layout] + "{" + content + "}"])
-          del document.body[i:j + 1]
+          continue
+        content = lyx2latex(document, document.body[i:j + 1])
+        add_to_preamble(document, [latexcmd[layout] + "{" + content + "}"])
+        del document.body[i:j + 1]
+        # no need to reset i
 
 
 def convert_prettyref(document):
@@ -1611,8 +1561,8 @@ def convert_prettyref(document):
                        document.warning("Malformed LyX document: No end of InsetRef!")
                        i += 1
                        continue
-               k = find_token(document.body, "LatexCommand prettyref", i)
-               if k != -1 and k < j:
+               k = find_token(document.body, "LatexCommand prettyref", i, j)
+               if k != -1:
                        document.body[k] = "LatexCommand formatted"
                i = j + 1
        document.header.insert(-1, "\\use_refstyle 0")
@@ -1633,8 +1583,8 @@ def revert_refstyle(document):
                        document.warning("Malformed LyX document: No end of InsetRef")
                        i += 1
                        continue
-               k = find_token(document.body, "LatexCommand formatted", i)
-               if k != -1 and k < j:
+               k = find_token(document.body, "LatexCommand formatted", i, j)
+               if k != -1:
                        document.body[k] = "LatexCommand prettyref"
                i = j + 1
        i = find_token(document.header, "\\use_refstyle", 0)
@@ -1659,23 +1609,15 @@ def revert_nameref(document):
       cmdloc = i
       i += 1
       # Make sure it is actually in an inset!
-      # We could just check document.lines[i-1], but that relies
-      # upon something that might easily change.
-      # We'll look back a few lines.
-      stins = cmdloc - 10
-      if stins < 0:
-        stins = 0
-      stins = find_token(document.body, "\\begin_inset CommandInset ref", stins)
-      if stins == -1 or stins > cmdloc:
-        continue
-      endins = find_end_of_inset(document.body, stins)
-      if endins == -1:
-        document.warning("Can't find end of inset at line " + stins + "!!")
-        continue
-      if endins < cmdloc:
+      # A normal line could begin with "LatexCommand nameref"!
+      stins, endins = get_containing_inset(document.body, cmdloc, \
+          "\\begin_inset CommandInset ref")
+      if stins == -1:
         continue
-      refline = find_token(document.body, "reference", stins)
-      if refline == -1 or refline > endins:
+
+      # ok, so it is in an InsetRef
+      refline = find_token(document.body, "reference", stins, endins)
+      if refline == -1:
         document.warning("Can't find reference for inset at line " + stinst + "!!")
         continue
       m = rx.match(document.body[refline])
@@ -1684,10 +1626,9 @@ def revert_nameref(document):
         continue
       foundone = True
       ref = m.group(1)
-      newcontent = ['\\begin_inset ERT', 'status collapsed', '', \
-        '\\begin_layout Plain Layout', '', '\\backslash', \
-        cmd + '{' + ref + '}', '\\end_layout', '', '\\end_inset']
+      newcontent = put_cmd_in_ert('\\' + cmd + '{' + ref + '}')
       document.body[stins:endins + 1] = newcontent
+
   if foundone:
     add_to_preamble(document, "\usepackage{nameref}")
 
@@ -1705,20 +1646,9 @@ def remove_Nameref(document):
     i += 1
     
     # Make sure it is actually in an inset!
-    # We could just check document.lines[i-1], but that relies
-    # upon something that might easily change.
-    # We'll look back a few lines.
-    stins = cmdloc - 10
-    if stins < 0:
-      stins = 0
-    stins = find_token(document.body, "\\begin_inset CommandInset ref", stins)
-    if stins == -1 or stins > cmdloc:
-      continue
-    endins = find_end_of_inset(document.body, stins)
-    if endins == -1:
-      document.warning("Can't find end of inset at line " + stins + "!!")
-      continue
-    if endins < cmdloc:
+    stins, endins = get_containing_inset(document.body, \
+        cmdloc, "\\begin_inset CommandInset ref")
+    if stins == -1:
       continue
     document.body[cmdloc] = "LatexCommand nameref"
 
@@ -1726,16 +1656,10 @@ def remove_Nameref(document):
 def revert_mathrsfs(document):
     " Load mathrsfs if \mathrsfs us use in the document "
     i = 0
-    end = len(document.body) - 1
-    while True:
-      j = document.body[i].find("\\mathscr{")
-      if j != -1:
-        add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
-        add_to_preamble(document, ["\\usepackage{mathrsfs}"])
-        break
-      if i == end:
-        break
-      i += 1
+    for line in document.body:
+      if line.find("\\mathscr{") != -1:
+        add_to_preamble(document, ["% lyx2lyx mathrsfs addition", "\\usepackage{mathrsfs}"])
+        return
 
 
 def convert_flexnames(document):
@@ -1753,66 +1677,66 @@ def convert_flexnames(document):
       i += 1
 
 
-flex_insets = [
-  ["Alert", "CharStyle:Alert"],
-  ["Code", "CharStyle:Code"],
-  ["Concepts", "CharStyle:Concepts"],
-  ["E-Mail", "CharStyle:E-Mail"],
-  ["Emph", "CharStyle:Emph"],
-  ["Expression", "CharStyle:Expression"],
-  ["Initial", "CharStyle:Initial"],
-  ["Institute", "CharStyle:Institute"],
-  ["Meaning", "CharStyle:Meaning"],
-  ["Noun", "CharStyle:Noun"],
-  ["Strong", "CharStyle:Strong"],
-  ["Structure", "CharStyle:Structure"],
-  ["ArticleMode", "Custom:ArticleMode"],
-  ["Endnote", "Custom:Endnote"],
-  ["Glosse", "Custom:Glosse"],
-  ["PresentationMode", "Custom:PresentationMode"],
-  ["Tri-Glosse", "Custom:Tri-Glosse"]
-]
-
-flex_elements = [
-  ["Abbrev", "Element:Abbrev"],
-  ["CCC-Code", "Element:CCC-Code"],
-  ["Citation-number", "Element:Citation-number"],
-  ["City", "Element:City"],
-  ["Code", "Element:Code"],
-  ["CODEN", "Element:CODEN"],
-  ["Country", "Element:Country"],
-  ["Day", "Element:Day"],
-  ["Directory", "Element:Directory"],
-  ["Dscr", "Element:Dscr"],
-  ["Email", "Element:Email"],
-  ["Emph", "Element:Emph"],
-  ["Filename", "Element:Filename"],
-  ["Firstname", "Element:Firstname"],
-  ["Fname", "Element:Fname"],
-  ["GuiButton", "Element:GuiButton"],
-  ["GuiMenu", "Element:GuiMenu"],
-  ["GuiMenuItem", "Element:GuiMenuItem"],
-  ["ISSN", "Element:ISSN"],
-  ["Issue-day", "Element:Issue-day"],
-  ["Issue-months", "Element:Issue-months"],
-  ["Issue-number", "Element:Issue-number"],
-  ["KeyCap", "Element:KeyCap"],
-  ["KeyCombo", "Element:KeyCombo"],
-  ["Keyword", "Element:Keyword"],
-  ["Literal", "Element:Literal"],
-  ["MenuChoice", "Element:MenuChoice"],
-  ["Month", "Element:Month"],
-  ["Orgdiv", "Element:Orgdiv"],
-  ["Orgname", "Element:Orgname"],
-  ["Postcode", "Element:Postcode"],
-  ["SS-Code", "Element:SS-Code"],
-  ["SS-Title", "Element:SS-Title"],
-  ["State", "Element:State"],
-  ["Street", "Element:Street"],
-  ["Surname", "Element:Surname"],
-  ["Volume", "Element:Volume"],
-  ["Year", "Element:Year"]
-]
+flex_insets = {
+  "Alert" : "CharStyle:Alert",
+  "Code" : "CharStyle:Code",
+  "Concepts" : "CharStyle:Concepts",
+  "E-Mail" : "CharStyle:E-Mail",
+  "Emph" : "CharStyle:Emph",
+  "Expression" : "CharStyle:Expression",
+  "Initial" : "CharStyle:Initial",
+  "Institute" : "CharStyle:Institute",
+  "Meaning" : "CharStyle:Meaning",
+  "Noun" : "CharStyle:Noun",
+  "Strong" : "CharStyle:Strong",
+  "Structure" : "CharStyle:Structure",
+  "ArticleMode" : "Custom:ArticleMode",
+  "Endnote" : "Custom:Endnote",
+  "Glosse" : "Custom:Glosse",
+  "PresentationMode" : "Custom:PresentationMode",
+  "Tri-Glosse" : "Custom:Tri-Glosse"
+}
+
+flex_elements = {
+  "Abbrev" : "Element:Abbrev",
+  "CCC-Code" : "Element:CCC-Code",
+  "Citation-number" : "Element:Citation-number",
+  "City" : "Element:City",
+  "Code" : "Element:Code",
+  "CODEN" : "Element:CODEN",
+  "Country" : "Element:Country",
+  "Day" : "Element:Day",
+  "Directory" : "Element:Directory",
+  "Dscr" : "Element:Dscr",
+  "Email" : "Element:Email",
+  "Emph" : "Element:Emph",
+  "Filename" : "Element:Filename",
+  "Firstname" : "Element:Firstname",
+  "Fname" : "Element:Fname",
+  "GuiButton" : "Element:GuiButton",
+  "GuiMenu" : "Element:GuiMenu",
+  "GuiMenuItem" : "Element:GuiMenuItem",
+  "ISSN" : "Element:ISSN",
+  "Issue-day" : "Element:Issue-day",
+  "Issue-months" : "Element:Issue-months",
+  "Issue-number" : "Element:Issue-number",
+  "KeyCap" : "Element:KeyCap",
+  "KeyCombo" : "Element:KeyCombo",
+  "Keyword" : "Element:Keyword",
+  "Literal" : "Element:Literal",
+  "MenuChoice" : "Element:MenuChoice",
+  "Month" : "Element:Month",
+  "Orgdiv" : "Element:Orgdiv",
+  "Orgname" : "Element:Orgname",
+  "Postcode" : "Element:Postcode",
+  "SS-Code" : "Element:SS-Code",
+  "SS-Title" : "Element:SS-Title",
+  "State" : "Element:State",
+  "Street" : "Element:Street",
+  "Surname" : "Element:Surname",
+  "Volume" : "Element:Volume",
+  "Year" : "Element:Year"
+}
 
 
 def revert_flexnames(document):
@@ -1832,100 +1756,115 @@ def revert_flexnames(document):
       document.warning("Illegal flex inset: " + document.body[i])
       i += 1
       continue
-    
     style = m.group(1)
-    for f in flexlist:
-      if f[0] == style:
-        document.body[i] = "\\begin_inset Flex " + f[1]
-        break
-
+    if style in flexlist:
+      document.body[i] = "\\begin_inset Flex " + flexlist[style]
     i += 1
 
 
 def convert_mathdots(document):
     " Load mathdots automatically "
-    while True:
-      i = find_token(document.header, "\\use_esint" , 0)
-      if i != -1:
-        document.header.insert(i + 1, "\\use_mathdots 1")
-      break
+    i = find_token(document.header, "\\use_esint" , 0)
+    if i != -1:
+      document.header.insert(i + 1, "\\use_mathdots 1")
 
 
 def revert_mathdots(document):
     " Load mathdots if used in the document "
-    i = 0
-    ddots = re.compile(r'\\begin_inset Formula .*\\ddots', re.DOTALL)
-    vdots = re.compile(r'\\begin_inset Formula .*\\vdots', re.DOTALL)
-    iddots = re.compile(r'\\begin_inset Formula .*\\iddots', re.DOTALL)
+
     mathdots = find_token(document.header, "\\use_mathdots" , 0)
-    no = find_token(document.header, "\\use_mathdots 0" , 0)
-    auto = find_token(document.header, "\\use_mathdots 1" , 0)
-    yes = find_token(document.header, "\\use_mathdots 2" , 0)
-    if mathdots != -1:
+    if mathdots == -1:
+      document.warning("No \\usemathdots line. Assuming auto.")
+    else:
+      val = get_value(document.header, "\\use_mathdots", mathdots)
       del document.header[mathdots]
+      try:
+        usedots = int(val)
+      except:
+        document.warning("Invalid \\use_mathdots value: " + val + ". Assuming auto.")
+        # probably usedots has not been changed, but be safe.
+        usedots = 1
+
+      if usedots == 0:
+        # do not load case
+        return
+      if usedots == 2:
+        # force load case
+        add_to_preamble(["% lyx2lyx mathdots addition", "\\usepackage{mathdots}"])
+        return
+    
+    # so we are in the auto case. we want to load mathdots if \iddots is used.
+    i = 0
     while True:
       i = find_token(document.body, '\\begin_inset Formula', i)
       if i == -1:
         return
       j = find_end_of_inset(document.body, i)
       if j == -1:
-        document.warning("Malformed LyX document: Can't find end of Formula inset.")
-        return 
-      k = ddots.search("\n".join(document.body[i:j]))
-      l = vdots.search("\n".join(document.body[i:j]))
-      m = iddots.search("\n".join(document.body[i:j]))
-      if (yes == -1) and ((no != -1) or (not k and not l and not m) or (auto != -1 and not m)):
+        document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
         i += 1
         continue
-      # use \@ifundefined to catch also the "auto" case
-      add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
-      add_to_preamble(document, ["\\@ifundefined{iddots}{\\usepackage{mathdots}}\n"])
-      return
+      code = "\n".join(document.body[i:j])
+      if code.find("\\iddots") != -1:
+        add_to_preamble(document, ["% lyx2lyx mathdots addition", 
+        "\\@ifundefined{iddots}{\\usepackage{mathdots}}"])
+        return
+      i = j
 
 
 def convert_rule(document):
-    " Convert \\lyxline to CommandInset line "
+    " Convert \\lyxline to CommandInset line. "
     i = 0
+    
+    inset = ['\\begin_inset CommandInset line',
+      'LatexCommand rule',
+      'offset "0.5ex"',
+      'width "100line%"',
+      'height "1pt"', '',
+      '\\end_inset', '', '']
+
+    # if paragraphs are indented, we may have to unindent to get the
+    # line to be full-width.
+    indent = get_value(document.header, "\\paragraph_separation", 0)
+    have_indent = (indent == "indent")
+
     while True:
       i = find_token(document.body, "\\lyxline" , i)
       if i == -1:
         return
-        
-      j = find_token(document.body, "\\color" , i - 2)
-      if j == i - 2:
-        color = document.body[j] + '\n'
-      else:
-        color = ''
-      k = find_token(document.body, "\\begin_layout Standard" , i - 4)
-      # we need to handle the case that \lyxline is in a separate paragraph and that it is colored
-      # the result is then an extra empty paragraph which we get by adding an empty ERT inset
-      if k == i - 4 and j == i - 2 and document.body[i - 1] == '':
-        layout = '\\begin_inset ERT\nstatus collapsed\n\n\\begin_layout Plain Layout\n\n\n\\end_layout\n\n\\end_inset\n' \
-          + '\\end_layout\n\n' \
-          + '\\begin_layout Standard\n'
-      elif k == i - 2 and document.body[i - 1] == '':
-        layout = ''
-      else:
-        layout = '\\end_layout\n\n' \
-          + '\\begin_layout Standard\n'
-      l = find_token(document.body, "\\begin_layout Standard" , i + 4)
-      if l == i + 4 and document.body[i + 1] == '':
-        layout2 = ''
+
+      # we need to find out if this line follows other content
+      # in its paragraph. find its layout....
+      lastlay = find_token_backwards(document.body, "\\begin_layout", i)
+      if lastlay == -1:
+        document.warning("Can't find layout for line at " + str(i))
+        # do the best we can.
+        document.body[i:i+1] = inset
+        i += len(inset)
+        continue
+
+      # ...and look for other content before it.
+      lineisfirst = True
+      for line in document.body[lastlay + 1:i]:
+        # is it empty or a paragraph option?
+        if not line or line[0] == '\\':
+          continue
+        lineisfirst = False
+        break
+
+      if lineisfirst:
+        document.body[i:i+1] = inset
+        if indent:
+          # we need to unindent, lest the line be too long
+          document.body.insert(lastlay + 1, "\\noindent")
+        i += len(inset)
       else:
-        layout2 = '\\end_layout\n' \
-          + '\n\\begin_layout Standard\n'
-      subst = layout \
-        + '\\noindent\n\n' \
-        + color \
-        + '\\begin_inset CommandInset line\n' \
-        + 'LatexCommand rule\n' \
-        + 'offset "0.5ex"\n' \
-        + 'width "100line%"\n' \
-        + 'height "1pt"\n' \
-        + '\n\\end_inset\n\n\n' \
-        + layout2
-      document.body[i] = subst
-      i += 1
+        # so our line is in the middle of a paragraph
+        # we need to add a new line, lest this line follow the
+        # other content on that line and run off the side of the page
+        document.body[i:i+1] = inset
+        document.body[i:i] = ["\\begin_inset Newline newline", "\\end_inset", ""]
+      i += len(inset)
 
 
 def revert_rule(document):
@@ -1937,41 +1876,28 @@ def revert_rule(document):
         return
       # find end of inset
       j = find_token(document.body, "\\end_inset" , i)
-      # assure we found the end_inset of the current inset
-      if j > i + 6 or j == -1:
+      if j == -1:
         document.warning("Malformed LyX document: Can't find end of line inset.")
         return
       # determine the optional offset
-      k = find_token(document.body, 'offset', i, j)
-      if k != -1:
-        offset = document.body[k][8:-1]
-      else:
-        offset = ""
+      offset = get_value(document.body, 'offset', i, j).strip('"')
+      if offset:
+        offset = '[' + offset + ']'
       # determine the width
-      l = find_token(document.body, 'width', i, j)
-      if l != -1:
-        width = document.body[l][7:-1]
-      else:
-        width = "100col%"
+      width = get_value(document.body, 'width', i, j, "100col%").strip('"')
+      width = latex_length(width)[1]
       # determine the height
-      m = find_token(document.body, 'height', i, j)
-      if m != -1:
-        height = document.body[m][8:-1]
-      else:
-        height = "1pt"
+      height = get_value(document.body, 'height', i, j, "1pt").strip('"')
+      height = latex_length(height)[1]
       # output the \rule command
-      if offset:
-        subst = "\\rule[" + offset + "]{" + width + "}{" + height + "}"
-      else:
-        subst = "\\rule{" + width + "}{" + height + "}"
+      subst = "\\rule[" + offset + "]{" + width + "}{" + height + "}"
       document.body[i:j + 1] = put_cmd_in_ert(subst)
-      i += 1
+      i += len(subst) - (j - i)
 
 
 def revert_diagram(document):
   " Add the feyn package if \\Diagram is used in math "
   i = 0
-  re_diagram = re.compile(r'\\begin_inset Formula .*\\Diagram', re.DOTALL)
   while True:
     i = find_token(document.body, '\\begin_inset Formula', i)
     if i == -1:
@@ -1980,12 +1906,11 @@ def revert_diagram(document):
     if j == -1:
         document.warning("Malformed LyX document: Can't find end of Formula inset.")
         return 
-    m = re_diagram.search("\n".join(document.body[i:j]))
-    if not m:
-      i += 1
+    lines = "\n".join(document.body[i:j])
+    if lines.find("\\Diagram") == -1:
+      i = j
       continue
-    add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
-    add_to_preamble(document, "\\usepackage{feyn}")
+    add_to_preamble(document, ["% lyx2lyx feyn package insertion ", "\\usepackage{feyn}"])
     # only need to do it once!
     return
 
@@ -2133,7 +2058,7 @@ revert =  [[403, [revert_refstyle]],
            [394, [revert_DIN_C_pagesizes]],
            [393, [revert_makebox]],
            [392, [revert_argument]],
-           [391, [revert_beamer_args]],
+           [391, []],
            [390, [revert_align_decimal, revert_IEEEtran]],
            [389, [revert_output_sync]],
            [388, [revert_html_quotes]],