Import SuperbChemistry version 2.2
[superbchemistry/superbchemistry.git] / extension / SuperbChemistry / Main.xba
... / ...
CommitLineData
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
3<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Main" script:language="StarBasic">&apos; SuperbChemistry version 2.2
4&apos; http://mattmccutchen.net/schem/
5&apos; Written and maintained by Matt McCutchen &lt;matt@mattmccutchen.net&gt;
6&apos;
7&apos; Applies superscript and subscript formatting to chemical formulas in
8&apos; OpenOffice.org Writer documents.
9&apos;
10&apos; Rules:
11&apos; - Quantities [0-9]+ and charges [0-9]*[-+−] are recognized after an element
12&apos; symbol [A-Z][a-z]? or a closing delimiter [\])}] . Hyphens are converted
13&apos; into real minus signs.
14&apos; - A charge sign [-+−] is ignored if it is followed by a letter, digit,
15&apos; opening delimiter, or [&lt;&gt;] . (Charges should appear only at the end of a
16&apos; formula, and we want to avoid matching ordinary hyphens in text.)
17&apos; - When digits followed by a charge sign are recognized, the last digit
18&apos; becomes part of the charge and the remaining digits become the quantity.
19&apos; (Charges rarely have absolute value more than 9.)
20&apos; - In cases like X2-, we have to guess whether the digit is an atom/group
21&apos; quantity or a charge amount. We guess atom/group quantity if X is H (NH4+),
22&apos; O (NO3-), a halogen (SbF6-, AlCl4-, etc.), or a closing parenthesis
23&apos; (Fe(OH)2+; the group likely would not have been parenthesized unless it had
24&apos; a quantity). Otherwise we guess charge amount (Fe3+). This heuristic
25&apos; should be right most of the time.
26&apos;
27&apos; Examples:
28&apos; C12345 ==&gt; C_{12345}
29&apos; H+ ==&gt; H^+
30&apos; Cl- ==&gt; Cl^-
31&apos; Fe3+ ==&gt; Fe^{3+}
32&apos; SO42- ==&gt; SO_4^{2-}
33&apos; C1232+ ==&gt; C_{123}^{2+}
34&apos; N3- ==&gt; N^{3-}
35&apos; N|_3^- not recognized (| represents &quot;no-width no break&quot;)
36&apos; NH4+ ==&gt; NH_4^+
37&apos; NO3- ==&gt; NO_3^-
38&apos; AlCl4- =&gt; AlCl_4^-
39&apos; Fe(OH)2+ ==&gt; Fe(OH)_2^+
40&apos; O12 ==&gt; O_{12}
41&apos; y4- not recognized
42&apos; x2 not recognized
43&apos; Foo2 not recognized
44&apos; TI-89 not recognized
45&apos;
46&apos; To format the current document, run the FormatDocument macro: go to Tools -&gt;
47&apos; Macros -&gt; Run Macro... -&gt; My Macros -&gt; SuperbChemistry -&gt; Main -&gt;
48&apos; FormatDocument -&gt; Run. I realize that this is ugly. I tried to make the
49&apos; package install a menu item to format the document, but the resulting package
50&apos; caused OpenOffice.org to crash regularly (I didn&apos;t investigate why), so I
51&apos; abandoned that idea. Note that you can add a menu item as a user
52&apos; customization (Tools -&gt; Customize), and I recommend it if you plan to use
53&apos; SuperbChemistry frequently.
54&apos;
55&apos; FormatDocument uses a sequence of regular expression find-and-replace
56&apos; operations since that was easy to implement and makes the rules easy to
57&apos; change. The operations appear in the undo history, so you can undo a
58&apos; formatting run by undoing the block of &quot;Replace&quot; entries at the top of the
59&apos; history.
60&apos;
61&apos; I would like to support formatting a selection, but the OpenOffice.org API
62&apos; does not appear to support replace-all within a selection. I could find
63&apos; within the selection and implement the replacing myself, but that is more
64&apos; work than I want to do.
65&apos;
66&apos; If SuperbChemistry makes a mistake (e.g., recognizes a &quot;formula&quot; that isn&apos;t
67&apos; or formats a formula incorrectly), you can correct the formatting yourself
68&apos; and prevent future runs of the macro from recognizing the offending text by
69&apos; inserting a &quot;No-width no break&quot; character in the middle of it. This character
70&apos; is available in the &quot;Insert -&gt; Formatting Mark&quot; menu when &quot;Tools -&gt; Options -&gt;
71&apos; Language Settings -&gt; Languages -&gt; Enhanced language support -&gt;
72&apos; Enabled for complex text layout (CTL)&quot; is enabled.
73
74&apos; ==============================================================================
75
76&apos; Regular expression replace in the document,
77&apos; creating superscripts if superb &gt; 0 or subscripts if superb &lt; 0.
78&apos; Used by FormatDocument.
79sub SuperbReplace(doc as object, searchStr as string, replaceStr as string, superb as integer)
80
81dim rd as object
82rd = doc.createReplaceDescriptor()
83
84rd.SearchCaseSensitive = true
85rd.SearchRegularExpression = true
86rd.setSearchString(searchStr)
87rd.setReplaceString(replaceStr)
88
89if superb &lt;&gt; 0 then
90 dim replaceAttrs(1) as new com.sun.star.beans.PropertyValue
91 replaceAttrs(0).Name = &quot;CharEscapement&quot;
92 if superb &gt; 0 then
93 replaceAttrs(0).Value = 33
94 else
95 replaceAttrs(0).Value = -9
96 end if
97 replaceAttrs(1).Name = &quot;CharEscapementHeight&quot;
98 replaceAttrs(1).Value = 58
99 rd.setReplaceAttributes(replaceAttrs)
100end if
101
102doc.replaceAll(rd)
103
104end sub
105
106&apos; Formats the current document
107sub FormatDocument
108
109&apos; Idiom: Match something and tag it on the left or right with @x@
110&apos; for further processing. If the replacement text could use
111&apos; backreferences, this would be easier. (I think backreferences were added
112&apos; since I originally wrote this code, but I see no need to rewrite it to take
113&apos; advantage of them. - Matt 2008-10-26)
114
115&apos; Tag candidate charges following symbols or ), but not in compound words, etc.
116&apos; Acceptable next character. (Has to be before end of line to avoid matching @g@ tag itself.)
117SuperbReplace(ThisComponent, &quot;([A-Z][a-z]?|[\])}])[0-9]*[-+−][^[({A-Za-z0-9&lt;&gt;]&quot;, &quot;&amp;@G@&quot;, 0)
118&apos; Retag in front.
119SuperbReplace(ThisComponent, &quot;.@G@&quot;, &quot;@g@&amp;&quot;, 0)
120&apos; End of line.
121SuperbReplace(ThisComponent, &quot;([A-Z][a-z]?|[\])}])[0-9]*[-+−]$&quot;, &quot;&amp;@g@&quot;, 0)
122
123&apos; Some groups grab a single following digit as a quantity rather than a charge amount.
124&apos; See detailed rationale above.
125SuperbReplace(ThisComponent, &quot;(H|O|F|Cl|Br|I|\))[0-9]&quot;, &quot;&amp;@n@&quot;, 0)
126
127&apos; Real minus signs in charges.
128SuperbReplace(ThisComponent, &quot;-@g@&quot;, &quot;−@g@&quot;, 0)
129
130&apos; Make charges: at most one digit.
131SuperbReplace(ThisComponent, &quot;[0-9]?[−+]@g@&quot;, &quot;@q@&amp;&quot;, 1)
132
133&apos; Remove the O and ) markers in case of O57.
134SuperbReplace(ThisComponent, &quot;@n@&quot;, &quot;&quot;, 0)
135
136&apos; Tag quantities: as many digits as we can still grab.
137SuperbReplace(ThisComponent, &quot;([A-Z][a-z]?|[\])}])[0-9]+&quot;, &quot;&amp;@n@&quot;, 0)
138
139&apos; Make quantities.
140SuperbReplace(ThisComponent, &quot;[0-9]+@n@&quot;, &quot;&amp;&quot;, -1)
141
142&apos; Clean up all markers.
143SuperbReplace(ThisComponent, &quot;@[gGnq]@&quot;, &quot;&quot;, 0)
144
145end sub
146
147</script:module>