Import SuperbChemistry version 2.2
[superbchemistry/superbchemistry.git] / extension / SuperbChemistry / Main.xba
index e5a5a82..530cf8d 100644 (file)
@@ -1,28 +1,87 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
-<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Main" script:language="StarBasic">&apos; Matt McCutchen&apos;s SuperbChemistry for OpenOffice, version 1
+<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Main" script:language="StarBasic">&apos; SuperbChemistry version 2.2
+&apos; http://mattmccutchen.net/schem/
+&apos; Written and maintained by Matt McCutchen &lt;matt@mattmccutchen.net&gt;
 &apos;
-&apos; Applies superscript and subscript formatting to chemical formulas in text.
+&apos; Applies superscript and subscript formatting to chemical formulas in
+&apos; OpenOffice.org Writer documents.
+&apos;
+&apos; Rules:
+&apos; - Quantities [0-9]+ and charges [0-9]*[-+−] are recognized after an element
+&apos;   symbol [A-Z][a-z]? or a closing delimiter [\])}] .  Hyphens are converted
+&apos;   into real minus signs.
+&apos; - A charge sign [-+−] is ignored if it is followed by a letter, digit,
+&apos;   opening delimiter, or [&lt;&gt;] .  (Charges should appear only at the end of a
+&apos;   formula, and we want to avoid matching ordinary hyphens in text.)
+&apos; - When digits followed by a charge sign are recognized, the last digit
+&apos;   becomes part of the charge and the remaining digits become the quantity.
+&apos;   (Charges rarely have absolute value more than 9.)
+&apos; - In cases like X2-, we have to guess whether the digit is an atom/group
+&apos;   quantity or a charge amount.  We guess atom/group quantity if X is H (NH4+),
+&apos;   O (NO3-), a halogen (SbF6-, AlCl4-, etc.), or a closing parenthesis
+&apos;   (Fe(OH)2+; the group likely would not have been parenthesized unless it had
+&apos;   a quantity).  Otherwise we guess charge amount (Fe3+).  This heuristic
+&apos;   should be right most of the time.
 &apos;
 &apos; Examples:
 &apos; C12345 ==&gt; C_{12345}
 &apos; H+ ==&gt; H^+
 &apos; Cl- ==&gt; Cl^-
 &apos; Fe3+ ==&gt; Fe^{3+}
+&apos; SO42- ==&gt; SO_4^{2-}
 &apos; C1232+ ==&gt; C_{123}^{2+}
-&apos; N2- ==&gt; N^{2-}
-&apos; Exception for O and ): NO3- ==&gt; NO_3^-, Fe(OH)2- ==&gt; Fe(OH)_2^-
-&apos; But still O12 ==&gt; O_{12}
-&apos; 4+ ==&gt; 4+ (not a superscript by itself)
+&apos; N3- ==&gt; N^{3-}
+&apos; N|_3^- not recognized (| represents &quot;no-width no break&quot;)
+&apos; NH4+ ==&gt; NH_4^+
+&apos; NO3- ==&gt; NO_3^-
+&apos; AlCl4- =&gt; AlCl_4^-
+&apos; Fe(OH)2+ ==&gt; Fe(OH)_2^+
+&apos; O12 ==&gt; O_{12}
+&apos; y4- not recognized
+&apos; x2 not recognized
+&apos; Foo2 not recognized
+&apos; TI-89 not recognized
+&apos;
+&apos; To format the current document, run the FormatDocument macro: go to Tools -&gt;
+&apos; Macros -&gt;  Run Macro... -&gt; My Macros -&gt; SuperbChemistry -&gt; Main -&gt;
+&apos; FormatDocument -&gt; Run.  I realize that this is ugly.  I tried to make the
+&apos; package install a menu item to format the document, but the resulting package
+&apos; caused OpenOffice.org to crash regularly (I didn&apos;t investigate why), so I
+&apos; abandoned that idea.  Note that you can add a menu item as a user
+&apos; customization (Tools -&gt; Customize), and I recommend it if you plan to use
+&apos; SuperbChemistry frequently.
+&apos;
+&apos; FormatDocument uses a sequence of regular expression find-and-replace
+&apos; operations since that was easy to implement and makes the rules easy to
+&apos; change.  The operations appear in the undo history, so you can undo a
+&apos; formatting run by undoing the block of &quot;Replace&quot; entries at the top of the
+&apos; history.
+&apos;
+&apos; I would like to support formatting a selection, but the OpenOffice.org API
+&apos; does not appear to support replace-all within a selection.  I could find
+&apos; within the selection and implement the replacing myself, but that is more
+&apos; work than I want to do.
+&apos;
+&apos; If SuperbChemistry makes a mistake (e.g., recognizes a &quot;formula&quot; that isn&apos;t
+&apos; or formats a formula incorrectly), you can correct the formatting yourself
+&apos; and prevent future runs of the macro from recognizing the offending text by
+&apos; inserting a &quot;No-width no break&quot; character in the middle of it.  This character
+&apos; is available in the &quot;Insert -&gt; Formatting Mark&quot; menu when &quot;Tools -&gt; Options -&gt;
+&apos; Language Settings -&gt; Languages -&gt; Enhanced language support -&gt;
+&apos; Enabled for complex text layout (CTL)&quot; is enabled.
+
+&apos; ==============================================================================
 
 &apos; Regular expression replace in the document,
 &apos; creating superscripts if superb &gt; 0 or subscripts if superb &lt; 0.
-&apos; Used by SuperbChemistry.
+&apos; Used by FormatDocument.
 sub SuperbReplace(doc as object, searchStr as string, replaceStr as string, superb as integer)
 
 dim rd as object
 rd = doc.createReplaceDescriptor()
 
+rd.SearchCaseSensitive = true
 rd.SearchRegularExpression = true
 rd.setSearchString(searchStr)
 rd.setReplaceString(replaceStr)
@@ -47,29 +106,41 @@ end sub
 &apos; Formats the current document
 sub FormatDocument
 
-&apos; Mark candidate superscripts so we know they follow letters or ).
-SuperbReplace(ThisComponent, &quot;[A-Za-z)][0-9]*[-+−]&quot;, &quot;&amp;@l@&quot;, 0)
+&apos; Idiom: Match something and tag it on the left or right with @x@
+&apos; for further processing.  If the replacement text could use
+&apos; backreferences, this would be easier.  (I think backreferences were added
+&apos; since I originally wrote this code, but I see no need to rewrite it to take
+&apos; advantage of them. - Matt 2008-10-26)
+
+&apos; Tag candidate charges following symbols or ), but not in compound words, etc.
+&apos; Acceptable next character.  (Has to be before end of line to avoid matching @g@ tag itself.)
+SuperbReplace(ThisComponent, &quot;([A-Z][a-z]?|[\])}])[0-9]*[-+−][^[({A-Za-z0-9&lt;&gt;]&quot;, &quot;&amp;@G@&quot;, 0)
+&apos; Retag in front.
+SuperbReplace(ThisComponent, &quot;.@G@&quot;, &quot;@g@&amp;&quot;, 0)
+&apos; End of line.
+SuperbReplace(ThisComponent, &quot;([A-Z][a-z]?|[\])}])[0-9]*[-+−]$&quot;, &quot;&amp;@g@&quot;, 0)
 
-&apos; O and ) grab a single digit.  Block it off from becoming a superscript.
-SuperbReplace(ThisComponent, &quot;[O)][0-9]&quot;, &quot;&amp;@n@&quot;, 0)
+&apos; Some groups grab a single following digit as a quantity rather than a charge amount.
+&apos; See detailed rationale above.
+SuperbReplace(ThisComponent, &quot;(H|O|F|Cl|Br|I|\))[0-9]&quot;, &quot;&amp;@n@&quot;, 0)
 
-&apos; Real minus signs in superscripts.
-SuperbReplace(ThisComponent, &quot;-@l@&quot;, &quot;−@l@&quot;, 0)
+&apos; Real minus signs in charges.
+SuperbReplace(ThisComponent, &quot;-@g@&quot;, &quot;−@g@&quot;, 0)
 
-&apos; Make superscripts: at most one digit.
-SuperbReplace(ThisComponent, &quot;[0-9]?[−+]@l@&quot;, &quot;@q@&amp;&quot;, 1)
+&apos; Make charges: at most one digit.
+SuperbReplace(ThisComponent, &quot;[0-9]?[−+]@g@&quot;, &quot;@q@&amp;&quot;, 1)
 
-&apos; Remove the O and ) markers.
+&apos; Remove the O and ) markers in case of O57.
 SuperbReplace(ThisComponent, &quot;@n@&quot;, &quot;&quot;, 0)
 
-&apos; Mark off subscripts: as many digits as we can still grab.
-SuperbReplace(ThisComponent, &quot;[A-Za-z)][0-9]+&quot;, &quot;&amp;@n@&quot;, 0)
+&apos; Tag quantities: as many digits as we can still grab.
+SuperbReplace(ThisComponent, &quot;([A-Z][a-z]?|[\])}])[0-9]+&quot;, &quot;&amp;@n@&quot;, 0)
 
-&apos; Make subscripts.
+&apos; Make quantities.
 SuperbReplace(ThisComponent, &quot;[0-9]+@n@&quot;, &quot;&amp;&quot;, -1)
 
 &apos; Clean up all markers.
-SuperbReplace(ThisComponent, &quot;@[lnq]@&quot;, &quot;&quot;, 0)
+SuperbReplace(ThisComponent, &quot;@[gGnq]@&quot;, &quot;&quot;, 0)
 
 end sub