| 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">' Matt McCutchen's SuperbChemistry for OpenOffice, version 2.1 |
| 4 | ' |
| 5 | ' Applies superscript and subscript formatting to chemical formulas in text. |
| 6 | ' |
| 7 | ' Rules: |
| 8 | ' - Quantities [0-9]+ and charges [0-9]*[-+−] are recognized after an element |
| 9 | ' symbol [A-Z][a-z]? or a closing delimiter [])}] . Hyphens are converted |
| 10 | ' into real minus signs. |
| 11 | ' - A charge sign [-+−] is ignored if it is followed by a letter, digit, |
| 12 | ' opening delimiter, or [<>] . (Charges should appear only at the end of a |
| 13 | ' formula, and we want to avoid matching ordinary hyphens in text.) |
| 14 | ' - When digits followed by a charge sign are recognized, the last digit |
| 15 | ' becomes part of the charge and the remaining digits become the quantity. |
| 16 | ' (Charges rarely have absolute value more than 9.) |
| 17 | ' - Exception: If a single digit follows O or a closing delimiter, that digit |
| 18 | ' is always the quantity. (Handle NO3- and Fe(OH)2+. I think oxygen is the |
| 19 | ' only element that frequently has a quantity as part of a +/-1 ion. A group |
| 20 | ' is rarely parenthesized unless it has a quantity.) |
| 21 | ' |
| 22 | ' Examples: |
| 23 | ' C12345 ==> C_{12345} |
| 24 | ' H+ ==> H^+ |
| 25 | ' Cl- ==> Cl^- |
| 26 | ' Fe3+ ==> Fe^{3+} |
| 27 | ' SO42- ==> SO_4^{2-} |
| 28 | ' C1232+ ==> C_{123}^{2+} |
| 29 | ' N2- ==> N^{2-} |
| 30 | ' NO3- ==> NO_3^- |
| 31 | ' Fe(OH)2- ==> Fe(OH)_2^- |
| 32 | ' O12 ==> O_{12} |
| 33 | ' y4- ==> y4- |
| 34 | ' x2 ==> x2 |
| 35 | ' Foo2 ==> Foo2 |
| 36 | ' TI-89 ==> TI-89 |
| 37 | |
| 38 | ' Regular expression replace in the document, |
| 39 | ' creating superscripts if superb > 0 or subscripts if superb < 0. |
| 40 | ' Used by SuperbChemistry. |
| 41 | sub SuperbReplace(doc as object, searchStr as string, replaceStr as string, superb as integer) |
| 42 | |
| 43 | dim rd as object |
| 44 | rd = doc.createReplaceDescriptor() |
| 45 | |
| 46 | rd.SearchCaseSensitive = true |
| 47 | rd.SearchRegularExpression = true |
| 48 | rd.setSearchString(searchStr) |
| 49 | rd.setReplaceString(replaceStr) |
| 50 | |
| 51 | if superb <> 0 then |
| 52 | dim replaceAttrs(1) as new com.sun.star.beans.PropertyValue |
| 53 | replaceAttrs(0).Name = "CharEscapement" |
| 54 | if superb > 0 then |
| 55 | replaceAttrs(0).Value = 33 |
| 56 | else |
| 57 | replaceAttrs(0).Value = -9 |
| 58 | end if |
| 59 | replaceAttrs(1).Name = "CharEscapementHeight" |
| 60 | replaceAttrs(1).Value = 58 |
| 61 | rd.setReplaceAttributes(replaceAttrs) |
| 62 | end if |
| 63 | |
| 64 | doc.replaceAll(rd) |
| 65 | |
| 66 | end sub |
| 67 | |
| 68 | ' Formats the current document |
| 69 | sub FormatDocument |
| 70 | |
| 71 | ' Idiom: Match something and tag it on the left or right with @x@ |
| 72 | ' for further processing. If the replacement text could use |
| 73 | ' backreferences, this would be easier. |
| 74 | |
| 75 | ' Tag candidate charges following symbols or ), but not in compound words, etc. |
| 76 | ' Acceptable next character. (Has to be before end of line to avoid matching @g@ tag itself.) |
| 77 | SuperbReplace(ThisComponent, "([A-Z][a-z]?|[\])}])[0-9]*[-+−][^[({A-Za-z0-9<>]", "&@G@", 0) |
| 78 | ' Retag in front. |
| 79 | SuperbReplace(ThisComponent, ".@G@", "@g@&", 0) |
| 80 | ' End of line. |
| 81 | SuperbReplace(ThisComponent, "([A-Z][a-z]?|[\])}])[0-9]*[-+−]$", "&@g@", 0) |
| 82 | |
| 83 | ' O and )]} grab a single digit as quantity. |
| 84 | SuperbReplace(ThisComponent, "[\])}O][0-9]", "&@n@", 0) |
| 85 | |
| 86 | ' Real minus signs in charges. |
| 87 | SuperbReplace(ThisComponent, "-@g@", "−@g@", 0) |
| 88 | |
| 89 | ' Make charges: at most one digit. |
| 90 | SuperbReplace(ThisComponent, "[0-9]?[−+]@g@", "@q@&", 1) |
| 91 | |
| 92 | ' Remove the O and ) markers in case of O57. |
| 93 | SuperbReplace(ThisComponent, "@n@", "", 0) |
| 94 | |
| 95 | ' Tag quantities: as many digits as we can still grab. |
| 96 | SuperbReplace(ThisComponent, "([A-Z][a-z]?|[\])}])[0-9]+", "&@n@", 0) |
| 97 | |
| 98 | ' Make quantities. |
| 99 | SuperbReplace(ThisComponent, "[0-9]+@n@", "&", -1) |
| 100 | |
| 101 | ' Clean up all markers. |
| 102 | SuperbReplace(ThisComponent, "@[gGnq]@", "", 0) |
| 103 | |
| 104 | end sub |
| 105 | |
| 106 | </script:module> |