summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2012-02-02 12:17:44 +0100
committerLászló Németh <nemeth@numbertext.org>2012-02-02 12:17:44 +0100
commit1a46fc1103856acae202f047528d1bbd837220e4 (patch)
treef78ec351f747ecfc76c685547f2bd97fe0a4be5b
Initial release
-rw-r--r--COPYING11
-rw-r--r--ChangeLog160
-rw-r--r--Dialog.py220
-rw-r--r--Lightproof.py153
-rw-r--r--Linguistic.xcu14
-rw-r--r--META-INF/manifest.xml12
-rw-r--r--NEWS86
-rw-r--r--README68
-rw-r--r--THANKS7
-rw-r--r--VERSION1
-rw-r--r--description.xml19
-rw-r--r--doc/dialog.txt52
-rw-r--r--doc/manual.txt69
-rw-r--r--doc/syntax.txt296
-rw-r--r--make.py45
-rw-r--r--pythonpath/__init__.py0
-rw-r--r--pythonpath/lightproof___implname__.py3
-rw-r--r--pythonpath/lightproof_compile___implname__.py276
-rw-r--r--pythonpath/lightproof_handler___implname__.py119
-rw-r--r--pythonpath/lightproof_impl___implname__.py229
-rw-r--r--src/editor/Addons.xcu97
-rw-r--r--src/editor/META-INF/manifest.xml19
-rw-r--r--src/editor/Office/Accelerators.xcu30
-rw-r--r--src/editor/Office/UI/StartModuleWindowState.xcu19
-rw-r--r--src/editor/Office/UI/WriterWindowState.xcu18
-rw-r--r--src/editor/README75
-rw-r--r--src/editor/editor.cfg11
-rw-r--r--src/editor/editor.dat1
-rw-r--r--src/editor/icons/comp.pngbin0 -> 901 bytes
-rw-r--r--src/editor/icons/comp16.pngbin0 -> 564 bytes
-rw-r--r--src/editor/icons/compall.pngbin0 -> 910 bytes
-rw-r--r--src/editor/icons/compall16.pngbin0 -> 563 bytes
-rw-r--r--src/editor/icons/debug.pngbin0 -> 1748 bytes
-rw-r--r--src/editor/icons/debug16.pngbin0 -> 925 bytes
-rw-r--r--src/editor/lightproof_editor/General.xba153
-rw-r--r--src/editor/lightproof_editor/RegisteredFlag0
-rw-r--r--src/editor/lightproof_editor/dialog.xlb4
-rw-r--r--src/editor/lightproof_editor/script.xlb5
-rw-r--r--src/en/README_lightproof_en.txt3
-rw-r--r--src/en/en.cfg13
-rw-r--r--src/en/en.dat382
-rw-r--r--src/en/en.dlg53
-rw-r--r--src/hu_HU/ChangeLog124
-rw-r--r--src/hu_HU/README_lightproof_hu_HU.txt3
-rw-r--r--src/hu_HU/hu_HU.cfg10
-rw-r--r--src/hu_HU/hu_HU.dat908
-rw-r--r--src/hu_HU/hu_HU.dlg99
-rw-r--r--src/ru_RU/README_lightproof_ru_RU.txt7
-rw-r--r--src/ru_RU/ru_RU.cfg13
-rw-r--r--src/ru_RU/ru_RU.dat248
-rw-r--r--src/ru_RU/ru_RU.dlg66
51 files changed, 4201 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..879b9c7
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,11 @@
+GPL 2.0/LGPL 2.1/MPL 1.1 tri-license
+
+The contents of this software may be used under the terms of
+the GNU General Public License Version 2 or later (the "GPL"), or
+the GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+or the Mozilla Public License Version 1.1 or later (the "MPL").
+
+Software distributed under these licenses is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the licences on
+http://www.fsf.org and http://www.opensource.org for the specific language
+governing rights and limitations under the licenses.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..8c9392f
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,160 @@
+2012-02-02 László Németh <nemeth@numbertext.org>:
+ - Lightproof editor (rule development extension for LibreOffice)
+ - use template and config system, based on
+ the work of Olivier Ronez, author of French
+ grammar checker Dicollecte.
+ - code cleanups
+ - move user code to different module to speed up
+ its load (submodules use Python pyc format)
+
+2011-12-16 László Németh <nemeth@numbertext.org>:
+ - add FullCommentURL support
+ - remove " [" from reversed space and punctuation
+ - remove traceback.print_exc (problems on Windows reported by Olivier Ronez)
+ - license: LGPL -> MPL/GPL/LGPL
+ - remove tabulators for LibreOffice Git
+ - options only in extension manager (temporarily)
+ - help separator in dlg: now "\n" instead of "/"
+ - long comments (\n), eg. # Did you mean:\nExplanation...
+ - expressions in comments, eg. # =expression({word})
+ - \u00AD (soft hyphen is not word boundary)
+ - print traceback in LibreOffice
+ - LOCALE, TEXT in rules, see doc.
+
+ * lightproof_py.py: fix hasLocale() for LibreOffice 3.5
+
+ - data/en_US.dat: improved English rules (a/an) rules
+
+ * Complile.py: support "_" in pattern names.
+ - add ^ for sentence beginning
+
+2011-07-12 László Németh <nemeth@numbertext.org>:
+ * lightproof_handler_py.py: fix for LibreOffice
+ Problem with option settings reported by Péter Benedek on
+ openscope.org and others
+
+ * Dialog.py: support for multiple options in a line.
+ syntax in dlg files: space and comma separated list, comma means new line:
+ item1 item2 ..., itemx itemz ..., itemA itemB ...
+
+ * Dialog.py: tooltip support, syntax in dlg files: slash separation
+ item = option caption/tooltip
+
+ * Dialog.py: fix localization of the extension name in the Options
+
+ * lightproof_py.py:
+ - stem(): new function for stemming, see doc/syntax.txt.
+ Problems with the experimental version reported by Olivier Ronez.
+ - generate(): new function for morphological generation, see doc/syntax.txt
+ - extended functions: optional "all" parameter of functions morph() and affix(),
+ see doc/syntax.txt
+
+ * Compile.py: fix for [code] (handling "\n" in strings)
+
+2010-02-19 László Németh <nemeth@numbertext.org>:
+ * Compile.py, make.py: add user code support
+ by [code] sections in the rule files,
+ see end of the doc/manual.txt
+
+ * Lightproof_handler.py: fix Mac OS X PyUNO problem
+ (problem with helper classes in the same file)
+
+2009-12-16 László Németh <nemeth@numbertext.org>:
+ * make.py: vendor/language specific grammar checker generator
+ * *_{py,xcu,xml}.py:
+ - template files for code generation
+ * Makefile, Compile.py:
+ - modified for code generation
+
+ * Dialog.py:
+ - Options dialog data generator (see doc/dialog.txt)
+
+ * data/{en_US,hu_HU}.dat:
+ - optional rules: word duplication etc.
+
+ * Lightproof.py:
+ - fix getAlternatives() handling (morphological analysis of unknown
+ words resulted in unchecked sentences)
+
+ - extended, simplified syntax:
+
+ rule sections ([Word], [word], [Char], [char]): see NEWS
+
+ - expressions in suggestions: specified by a starting equal sign
+ (see doc/syntax.txt):
+
+ - new library functions (see doc/syntax.txt):
+ option(): return the value of the option (see doc/dialog.txt)
+ spell(): spelling (Boolean function)
+ suggest(): suggestion
+ affix(): morph variant (only with affix fields)
+ calc(): Calc function access
+
+2009-10-23 László Németh <nemeth@numbertext.org>:
+ * data/hu_HU.dat:
+ - fix rule article "a". The problem with "13-a óta" reported by kiazaki
+ at openscope.hu.
+
+2009-10-20 László Németh <nemeth@numbertext.org>:
+ * data/hu_HU.dat:
+ - add the rule "mellet" for irregular nouns, too (eg. "a ház mellet")
+
+ - add -ban/-ben affixes to the rule "helyett kap", reported by
+ József Barna.
+
+ - fix digit separator rules for decimal digits, reported by joghurt at
+ OOo Wiki.
+
+ * Lightproof.py:
+ - add words with dots to word(). The problem with version numbers
+ (eg. in OpenOffice.org 3.1) reported by Kami.
+
+2009-10-19 László Németh <nemeth@numbertext.org>:
+ * Lightproof.py:
+ - Hunspell integration
+
+ - processing conditional rules by eval()
+
+ - helper functions: morph() and word() (see doc/syntax.txt)
+
+ - add try-except for proofing rule compiling (bad regexes of the
+ conditional rules detected only in loading phase yet, see stdout
+ of OpenOffice.org)
+
+ * Compile.py:
+
+ - conditional rules (see doc/syntax.txt and hu_HU.dat)
+
+ - multi-line rules
+
+ * data/hu_HU.dat:
+ - new Hungarian rules
+
+2009-09-03 László Németh <nemeth@numbertext.org>:
+ * Lightproof.py:
+
+ - fix: multiple space detection beetween sentences
+ - data/*.dat: modified rule for space detection beetween sentences
+
+ * data/en*.dat:
+
+ - fix: de *juro -> de jure, also extended by "de luxe"
+
+ - using "typographic apostrophe" message instead of "apostrophe".
+ Ambiguous warning message reported by Dave Pitts (davidmpitts at gmail)
+
+ * data/hu_HU.dat:
+ - add "döntetlenre" to the suggestions for "egyelőre"
+
+ * doc/manual.txt: reported by Olivier Ronez <dico dot savant at free dot fr>
+
+ - replace Convert.py with Compile.py
+
+ - suggesting yourname.dat argument instead of parameter substitution
+ for manual compilation under Windows
+
+2009-09-01 Yakov Reztsov <yr at myooo dot ru>
+ * data/ru_RU.dat: Russian translation of template.dat
+
+2009-04-25 László Németh <nemeth@numbertext.org>:
+ * first release
diff --git a/Dialog.py b/Dialog.py
new file mode 100644
index 0000000..b652618
--- /dev/null
+++ b/Dialog.py
@@ -0,0 +1,220 @@
+# -*- encoding: UTF-8 -*-
+import sys
+import re
+from string import split
+import os
+import codecs
+
+comment = re.compile(ur"[\n#]")
+ids = re.compile(ur"\w+:\s*\*?\w+(,\s*\*?\w+)*")
+langu = re.compile(ur"\[.+=.+\]\s*")
+titl = re.compile(ur"\w+\s*=\s*")
+helptexts = []
+
+xdl_header = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dlg:window PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "dialog.dtd">
+<dlg:window xmlns:dlg="http://openoffice.org/2000/dialog" xmlns:script="http://openoffice.org/2000/script" dlg:id="%s" dlg:left="101" dlg:top="52" dlg:width="196" dlg:height="72" dlg:closeable="true" dlg:moveable="true" dlg:withtitlebar="false">
+ <dlg:bulletinboard>
+"""
+xdl_footer = """</dlg:bulletinboard>
+</dlg:window>
+"""
+xdl_group = '<dlg:fixedline dlg:id="%s" dlg:tab-index="%d" dlg:left="5" dlg:top="%d" dlg:width="240" dlg:height="10" dlg:value="&amp;%s"/>\n'
+xdl_item = '<dlg:checkbox dlg:id="%s" dlg:tab-index="%d" dlg:left="%d" dlg:top="%d" dlg:width="%d" dlg:height="10" dlg:value="&amp;%s" dlg:checked="%s" %s/>\n'
+
+xcs_header = """<?xml version="1.0" encoding="UTF-8"?>
+<oor:component-schema xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+oor:name="%s" oor:package="org.openoffice" xml:lang="en-US">
+<info>
+<desc>Contains the options data used for the test extensions.</desc>
+</info>
+<templates>
+"""
+xcs_leaf_header = ur"""
+ <group oor:name="%s">
+ <info>
+ <desc>The data for one leaf.</desc>
+ </info>
+"""
+xcs_leaf = ur"""<prop oor:name="%s" oor:type="xs:string">
+ <value></value>
+</prop>
+"""
+xcs_leaf_footer = ur""" </group>
+"""
+xcs_component_header = """ </templates>
+ <component>
+ <group oor:name="Leaves">
+"""
+xcs_component = """
+ <node-ref oor:name="%s" oor:node-type="%s"/>
+"""
+xcs_footer = """ </group>
+ </component>
+
+</oor:component-schema>
+"""
+xcu_header = u"""<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE oor:component-data SYSTEM "../../../../component-update.dtd">
+<oor:component-data oor:name="OptionsDialog" oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <node oor:name="Nodes">
+ <node oor:name="org.openoffice.lightproof" oor:op="fuse">
+ <prop oor:name="Label">
+ <value xml:lang="en">Dictionaries</value>
+ <value xml:lang="hu">Szótárak</value>
+ </prop>
+ <node oor:name="Leaves">
+"""
+xcu_node_header = """
+ <node oor:name="org.openoffice.lightproof.%s" oor:op="fuse">
+
+ <prop oor:name="Id">
+ <value>org.openoffice.comp.pyuno.lightproof.oxt.%s</value>
+ </prop>
+
+ <prop oor:name="Label">
+"""
+xcu_node = """
+ <value xml:lang="%s">%s</value>
+"""
+xcu_node_footer = """
+ </prop>
+
+ <prop oor:name="OptionsPage">
+ <value>%%origin%%/%s.xdl</value>
+ </prop>
+
+ <prop oor:name="EventHandlerService">
+ <value>org.openoffice.comp.pyuno.LightproofOptionsEventHandler.%s</value>
+ </prop>
+
+ </node>
+"""
+xcu_footer = """
+ </node>
+ </node>
+ </node>
+</oor:component-data>
+"""
+
+indexes = {}
+indexes_def = {}
+modules = {}
+
+def create_xdl(pkg, lines, target, lang):
+ global indexes
+ global indexes_def
+ global modules
+ indexes[lang] = []
+ indexes_def[lang] = []
+ modules[lang] = []
+ f2 = ""
+ state = 0
+ f2n = "dialog/" + lang + ".xdl"
+ f2 = f2 + xdl_header%lang
+
+ k = 0
+ k2 = 0
+ lin = 0
+ ok = False
+ for i in lines:
+ i = i.strip()
+ if "=" in i and r"\n" in i:
+ helptexts.append(i.split("=")[0])
+ for i in lines:
+ i = unicode(i.strip().replace(r"\n", "@#@") + "\n", "UTF-8")
+ lin = lin + 1
+ if not comment.match(i):
+ if state == 0:
+ ok = True
+ if ids.match(i.strip()):
+ j = split(i.strip(),":")
+ f2 = f2 + xdl_group%(j[0].strip(), k, k2 * 10 + 5, j[0].strip())
+ for l in split(j[1],","):
+ k = k + 1
+ k2 = k2 + 1
+ l = l.strip()
+ la = split(l, " ")
+ l3 = 0
+ itemlen = int(240 / len(la))
+ for l2 in la:
+ if l2 != "-":
+ checked = "false"
+ if l2[0] == '*':
+ checked = "true"
+ l2 = l2[1:]
+ indexes_def[lang] += [l2]
+ indexes[lang] += [l2]
+ helptext = ""
+ if l2 in helptexts:
+ helptext = "dlg:help-text=\"&amp;hlp_" + l2 + "\""
+ f2 = f2 + xdl_item%(l2, k, 10 + itemlen * l3, k2 * 10 + 5, itemlen, l2, checked, helptext)
+ l3 = l3 + 1
+ k = k + 1
+ k2 = k2 + 1
+ k = k + 1
+ else:
+ ok = False
+ if langu.match(i.strip()):
+ if "xdl" in f2n:
+ f2 = f2 + xdl_footer
+ target.writestr(f2n, f2)
+ f2 = ""
+ i = i.strip()
+ langname = i[1:i.find("=")]
+ modules[lang] += [langname[:langname.find("_")], i[i.find("=")+1:-1]]
+ f2n = "dialog/" + lang + "_" + langname + ".properties"
+ state = state + 1
+ if state == 1:
+ target.writestr("dialog/" + lang + "_" + langname + ".default", "")
+ elif titl.match(i.strip()):
+ hlp = i.encode("unicode-escape").replace(r"\n","\n").replace(r"\t","\t").replace(r"\x","\\u00").split("@#@", 1)
+ if len(hlp) > 1:
+ helptexts.append(hlp[0].split("=")[0])
+ f2 = f2 + "hlp_" + hlp[0].split("=")[0] + "=" + hlp[1]
+ hlp[0] = hlp[0] + "\n"
+ f2 = f2 + hlp[0]
+ elif not ok:
+ print "Syntax error in line %d: %s" %(lin, i)
+ if "xdl" in f2n:
+ f2 = f2 + xdl_footer
+ target.writestr(f2n, f2)
+
+#def c(pkg, author, language, inpdir, target, prgtarget, dlg):
+
+def c(pkg, dlgdata, target, lang):
+
+ # create xdl dialog data files
+ create_xdl(pkg, dlgdata, target, lang)
+
+ s = xcs_header% ("Lightproof_" + pkg)
+ for i in indexes:
+ s = s + xcs_leaf_header%i + \
+ xcs_leaf*len(indexes[i])%tuple(indexes[i]) + \
+ xcs_leaf_footer
+ s = s + xcs_component_header
+ for i in indexes:
+ s = s + xcs_component%(i,i)
+
+ target.writestr("dialog/OptionsDialog.xcs", s + xcs_footer)
+
+ s = ""
+ for i in indexes:
+ s = s + xcu_node_header%(pkg, pkg) + \
+ xcu_node*(len(modules[i])/2)%tuple(modules[i]) + \
+ xcu_node_footer%(i, pkg)
+ target.writestr("dialog/OptionsDialog.xcu", (xcu_header + s + xcu_footer).encode("utf-8"))
+
+ # python resource file
+
+ s = """lopts = {}
+lopts_default = {}
+"""
+ for i in indexes:
+ s = s + "lopts['" + i + "'] = " + str(indexes[i]) + "\n"
+ for i in indexes:
+ s = s + "lopts_default['" + i + "'] = " + str(indexes_def[i]) + "\n"
+ target.writestr("pythonpath/lightproof_opts_%s.py"%pkg, s)
+
+
+
diff --git a/Lightproof.py b/Lightproof.py
new file mode 100644
index 0000000..a0c703f
--- /dev/null
+++ b/Lightproof.py
@@ -0,0 +1,153 @@
+# -*- encoding: UTF-8 -*-
+# Lightproof grammar checker for LibreOffice and OpenOffice.org
+# 2009-2012 (c) László Németh (nemeth at numbertext org), license: MPL 1.1 / GPLv3+ / LGPLv3+
+
+import uno, unohelper, sys, traceback
+from lightproof_impl_${implname} import locales
+from lightproof_impl_${implname} import pkg
+import lightproof_impl_${implname}
+import lightproof_handler_${implname}
+
+from com.sun.star.linguistic2 import XProofreader, XSupportedLocales
+from com.sun.star.linguistic2 import ProofreadingResult, SingleProofreadingError
+from com.sun.star.lang import XServiceInfo, XServiceName, XServiceDisplayName
+from com.sun.star.lang import Locale
+# reload in obj.reload in Python 3
+try:
+ from obj import reload
+except:
+ pass
+
+class Lightproof( unohelper.Base, XProofreader, XServiceInfo, XServiceName, XServiceDisplayName, XSupportedLocales):
+
+ def __init__( self, ctx, *args ):
+ self.ctx = ctx
+ self.ServiceName = "com.sun.star.linguistic2.Proofreader"
+ self.ImplementationName = "org.openoffice.comp.pyuno.Lightproof." + pkg
+ self.SupportedServiceNames = (self.ServiceName, )
+ self.locales = []
+ for i in locales:
+ l = locales[i]
+ self.locales += [Locale(l[0], l[1], l[2])]
+ self.locales = tuple(self.locales)
+ currentContext = uno.getComponentContext()
+ lightproof_impl_${implname}.SMGR = currentContext.ServiceManager
+ lightproof_impl_${implname}.spellchecker = \
+ lightproof_impl_${implname}.SMGR.createInstanceWithContext("com.sun.star.linguistic2.SpellChecker", currentContext)
+ lightproof_handler_${implname}.load(currentContext)
+
+ # XServiceName method implementations
+ def getServiceName(self):
+ return self.ImplementationName
+
+ # XServiceInfo method implementations
+ def getImplementationName (self):
+ return self.ImplementationName
+
+ def supportsService(self, ServiceName):
+ return (ServiceName in self.SupportedServiceNames)
+
+ def getSupportedServiceNames (self):
+ return self.SupportedServiceNames
+
+ # XSupportedLocales
+ def hasLocale(self, aLocale):
+ if aLocale in self.locales:
+ return True
+ for i in self.locales:
+ if (i.Country == aLocale.Country or i.Country == "") and aLocale.Language == i.Language:
+ return True
+ return False
+
+ def getLocales(self):
+ return self.locales
+
+ # XProofreader
+ def isSpellChecker(self):
+ return False
+
+ def doProofreading(self, nDocId, rText, rLocale, nStartOfSentencePos, \
+ nSuggestedSentenceEndPos, rProperties):
+ aRes = uno.createUnoStruct( "com.sun.star.linguistic2.ProofreadingResult" )
+ aRes.aDocumentIdentifier = nDocId
+ aRes.aText = rText
+ aRes.aLocale = rLocale
+ aRes.nStartOfSentencePosition = nStartOfSentencePos
+ aRes.nStartOfNextSentencePosition = nSuggestedSentenceEndPos
+ aRes.aProperties = ()
+ aRes.xProofreader = self
+ aRes.aErrors = ()
+ if len(rProperties) > 0 and rProperties[0].Name == "Update":
+ try:
+ import lightproof_compile_${implname}
+ try:
+ code = lightproof_compile_${implname}.c(rProperties[0].Value, rLocale.Language, True)
+ except Exception as e:
+ aRes.aText, aRes.nStartOfSentencePosition = e
+ return aRes
+ path = lightproof_impl_${implname}.get_path()
+ f = open(path.replace("_impl", ""), "w")
+ f.write("dic = %s" % code["rules"])
+ f.close()
+ if pkg in lightproof_impl_${implname}.langrule:
+ mo = lightproof_impl_${implname}.langrule[pkg]
+ reload(mo)
+ lightproof_impl_${implname}.compile_rules(mo.dic)
+ lightproof_impl_${implname}.langrule[pkg] = mo
+ if "code" in code:
+ f = open(path, "r")
+ ft = f.read()
+ f.close()
+ f = open(path, "w")
+ f.write(ft[:ft.find("# [code]") + 8] + "\n" + code["code"])
+ f.close()
+ try:
+ reload(lightproof_impl_${implname})
+ except Exception as e:
+ aRes.aText = e.args[0]
+ if e.args[1][3] == "": # "expected an indented block" (end of file)
+ aRes.nStartOfSentencePosition = len(rText.split("\n"))
+ else:
+ aRes.nStartOfSentencePosition = rText.split("\n").index(e.args[1][3][:-1]) + 1
+ return aRes
+ aRes.aText = ""
+ return aRes
+ except:
+ print traceback.format_exc()
+
+ l = rText[nSuggestedSentenceEndPos:nSuggestedSentenceEndPos+1]
+ while l == " ":
+ aRes.nStartOfNextSentencePosition = aRes.nStartOfNextSentencePosition + 1
+ l = rText[aRes.nStartOfNextSentencePosition:aRes.nStartOfNextSentencePosition+1]
+ if aRes.nStartOfNextSentencePosition == nSuggestedSentenceEndPos and l!="":
+ aRes.nStartOfNextSentencePosition = nSuggestedSentenceEndPos + 1
+ aRes.nBehindEndOfSentencePosition = aRes.nStartOfNextSentencePosition
+
+ try:
+ aRes.aErrors = lightproof_impl_${implname}.proofread( nDocId, rText, rLocale, \
+ nStartOfSentencePos, aRes.nBehindEndOfSentencePosition, rProperties)
+ except Exception as e:
+ if len(rProperties) > 0 and rProperties[0].Name == "Debug" and len(e.args) == 2:
+ aRes.aText, aRes.nStartOfSentencePosition = e
+ else:
+ print traceback.format_exc()
+ return aRes
+
+ def ignoreRule(self, rid, aLocale):
+ lightproof_impl_${implname}.ignore[rid] = 1
+
+ def resetIgnoreRules(self):
+ lightproof_impl_${implname}.ignore = {}
+
+ # XServiceDisplayName
+ def getServiceDisplayName(self, aLocale):
+ return lightproof_impl_${implname}.name
+
+g_ImplementationHelper = unohelper.ImplementationHelper()
+g_ImplementationHelper.addImplementation( Lightproof, \
+ "org.openoffice.comp.pyuno.Lightproof." + pkg,
+ ("com.sun.star.linguistic2.Proofreader",),)
+
+g_ImplementationHelper.addImplementation( lightproof_handler_${implname}.LightproofOptionsEventHandler, \
+ "org.openoffice.comp.pyuno.LightproofOptionsEventHandler." + pkg,
+ ("com.sun.star.awt.XContainerWindowEventHandler",),)
diff --git a/Linguistic.xcu b/Linguistic.xcu
new file mode 100644
index 0000000..00ae15e
--- /dev/null
+++ b/Linguistic.xcu
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<oor:component-data oor:name="Linguistic"
+ oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <node oor:name="ServiceManager">
+ <node oor:name="GrammarCheckers">
+ <node oor:name="org.openoffice.comp.pyuno.Lightproof.${implname}" oor:op="fuse">
+ <prop oor:name="Locales" oor:type="oor:string-list">
+ <value>${locales}</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+</oor:component-data>
diff --git a/META-INF/manifest.xml b/META-INF/manifest.xml
new file mode 100644
index 0000000..a3a40d2
--- /dev/null
+++ b/META-INF/manifest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<manifest:manifest>
+ <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcs"
+ manifest:media-type="application/vnd.sun.star.configuration-schema" />
+ <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcu"
+ manifest:media-type="application/vnd.sun.star.configuration-data" />
+ <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python"
+ manifest:full-path="Lightproof.py"/>
+ <manifest:file-entry
+ manifest:media-type="application/vnd.sun.star.configuration-data"
+ manifest:full-path="Linguistic.xcu" />
+</manifest:manifest> \ No newline at end of file
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..18aa726
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,86 @@
+2012-02-02: Version 1.5 beta 2
+- rule editor (Writer extension)
+- code cleanups, only Python dependency in config system
+
+2011-12-05: Version 1.5 beta (1.4.3)
+- Improved English and Hungarian rules
+- See ChangeLog
+
+2011-07-12: Version 1.4.1
+- fix option saving in LibreOffice
+
+- fix localization of the name of the grammar checker in OpenOffice.org/LibreOffice Options
+
+- multiple options in the same line in the Options dialog
+
+- new functions: stem(), generate()
+
+- improved Hungarian rules
+
+2010-02-19 Version 1.4
+- user code support ([code] sections in the rule files)
+
+- fix Mac OS X PyUNO problem
+
+2009-12-16 Version 1.3
+- Lightproof is a grammar checker extension generator (see doc/manual.txt):
+ the result of the generation is a single Lightproof or vendor specific
+ grammar checker language package, eg. lightproof-en_US.oxt or
+ your-grammar-checker-en_US.oxt.
+
+- native OpenOffice.org Options support (see Options->Language Settings
+ after the installation of en_US or hu_HU oxt packages of the Lightproof
+ distribution). Documentation: doc/dialog.txt
+
+- new, simplified rule syntax:
+ - rule sections ([Word], [word], [Char], [char]):
+ - word rules: patterns with default word boundaries
+ - [Word]: ignore case
+ - [word]: case sensitive
+
+ simplified syntax:
+
+ [Word] (default)
+
+ foo -> bar # bar is far better
+
+ instead of the old
+
+ (?i)\bfoo\b -> bar # bar is far better
+
+ - character rules: old default
+ - [Char]: ignore case
+ - [case]: case sensitive
+
+ - expressions in suggestions: specified by a starting equal sign
+
+ foo\w+ -> =\0.upper() # suggest with uppercase letters
+
+ - new library functions:
+ spell: spelling (Boolean function)
+ suggest: suggestion
+ affix: morph variant (only with affix fields)
+ calc: Calc function access (see NUMBERTEXT example in data/hu_HU.dat)
+
+2009-10-23 Version 1.2.2
+ - a small improvement in Hungarian grammar checking
+
+2009-10-20 Version 1.2.1
+ - small improvements in Hungarian grammar checking
+
+2009-10-19 Version 1.2
+ - Hunspell integration and
+
+ - extended syntax for grammar checking based on
+ morphological analysis (see data/hu_HU.dat)
+
+ - multi-line rules
+
+ - extended Hungarian rules
+
+2009-09-03 Version 1.1
+ - fixed multiple space detection beetween sentences
+
+ - Translated and extended Russian rule sets from Yakov Reztsov
+
+ - small improvements (see ChangeLog)
diff --git a/README b/README
new file mode 100644
index 0000000..3cd6f6a
--- /dev/null
+++ b/README
@@ -0,0 +1,68 @@
+Lightproof grammar checker framework for Libreoffice/OpenOffice.org
+
+source: git://anongit.freedesktop.org/libreoffice/lightproof
+
+or see cgit.freedesktop.org/libreoffice
+
+version 1.5 beta 2 (2012-02-02)
+
+2009–2012 (c) László Németh (nemeth at numbertext dot org), license: MPL 1.1 / GPLv3+ / LGPLv3+
+
+This software was developed with support from FSF.hu Foundation, Hungary.
+(For more information, see http://www.fsf.hu/index.php/About_us.)
+
+== Build OOo/LibO extension ==
+
+python make.py [config_file]
+
+For example:
+
+python make.py src/en/en.cfg
+
+or with own Python of LibreOffice on Windows:
+
+[install_path]\program\python make.py src\en\en.cfg
+
+The result is an oxt (OpenOffice.org/LibreOffice) extension.
+
+== Compile development tool ==
+
+python make.py src/editor/editor.cfg
+
+== Installation ==
+
+1. Via Tools -> Extension manager in OOo/LibreOffice
+
+2. or with unopkg tool, for example
+
+[install_path\program\]unopkg add -f lightproof_en-0.4.2.oxt
+
+== Features ==
+
+- Lightproof is a grammar checker extension generator (see doc/manual.txt):
+ the result of the generation is a single Lightproof or vendor specific
+ grammar checker language package, eg. lightproof-en.oxt or
+ your-grammar-checker-en_US.oxt.
+
+- language-neutral proofreading tool (see data/ for language data)
+- OpenOffice.org grammar checker extension generator
+- Lightproof editor (rule development tool / LibreOffice toolbar)
+- high-level regex-based rule definition language
+- optional Python conditions in the rules
+- integration with Hunspell morphological analyzer
+- written in Python using fast regex module of CPython
+- lazy loading of language modules
+- template (data/template.dat) for new languages
+
+== Rule compilation ==
+
+For the default language modules (en_US, hu_HU, ru_RU):
+
+make
+
+See doc/manual.txt to add a new language module or develop a
+new grammar checker extension for your language
+
+== Documentation ==
+
+doc/manual.txt
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..d418639
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,7 @@
+Thanks to
+
+András Tímár
+Olivier Ronez
+Michael Meeks
+
+See ChangeLog for other contributors.
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..1a71718
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1.5b2
diff --git a/description.xml b/description.xml
new file mode 100644
index 0000000..b6e548c
--- /dev/null
+++ b/description.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<description xmlns="http://openoffice.org/extensions/description/2006"
+ xmlns:d="http://openoffice.org/extensions/description/2006"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <identifier value="org.openoffice.comp.pyuno.lightproof.oxt.${implname}" />
+ <display-name>
+ <name lang="en-US">${name}</name>
+ </display-name>
+ <version value="${version}" />
+ <publisher>
+ <name lang="en" xlink:href="${link}">${provider}</name>
+ </publisher>
+ <icon>
+ <default xlink:href="img/logo.png" />
+ </icon>
+ <dependencies>
+ <OpenOffice.org-minimal-version value="3.2" d:name="OpenOffice.org 3.2" />
+ </dependencies>
+</description>
diff --git a/doc/dialog.txt b/doc/dialog.txt
new file mode 100644
index 0000000..e67f4aa
--- /dev/null
+++ b/doc/dialog.txt
@@ -0,0 +1,52 @@
+# 1. Copy this template to the data folder, under the name of your locale
+# eg. en_US.dlg.
+#
+# 2. Define your group ids and option ids and the localized title
+# texts (see later for the syntax).
+#
+# Syntax of the dialog data file:
+#
+# Options and title texts for the Settings and conditional rules
+#
+# The Lightproof dialogs contain only grouped checkboxes.
+#
+# Format of the dialog definition:
+#
+# GroupID: OptionID [OptionsInTheSameLines_or_hyphen_placeholder], OptionID ...
+# Group2ID: OptionID, OptionID ...
+# ...
+# [Language_code=title of the window]
+# GroupID=title of the group
+# OptionID=title of the option [\n tooltip]
+# Option2ID=title of the option [\n tooltip]
+#
+# The first language is the default language for the other locales
+# (use en_US or the common language of your country)
+#
+# The OptionIDs are used in the rules, too. For example:
+#
+# foo <- option("style") -> bar # bar is far better
+#
+# this rule depends from the state of the "style" checkbox.
+
+# options
+
+spelling: comma, hyphen
+proofreading: style, moregrammar
+
+# titles
+
+[en_US=Hungarian grammar checking]
+
+spelling=Spelling
+comma=Comma usage
+hyphen=Check compound words with hyphen
+proofreading=Proofreading
+style=Style checking
+moregrammar=Use grammar rules with ambiguous word analysis
+
+[yourlocale=yourtitle]
+
+spelling=...
+wordpart=...
+...
diff --git a/doc/manual.txt b/doc/manual.txt
new file mode 100644
index 0000000..96cd096
--- /dev/null
+++ b/doc/manual.txt
@@ -0,0 +1,69 @@
+= Making a new grammar checker for LibreOffice/OpenOffice.org =
+
+== Rule development ==
+
+Use Lightproof editor (LibreOffice Writer toolbar extension) to create a rule
+(Lightproof .dat) file. See doc/syntax.txt for more informations.
+
+After LibreOffice integration (see later) switch off the integrated grammar
+checker component in the Tools » Options » Language Settings » Writing Aids »
+Available language modules, eg. "Lightproof Grammar Checker (en)", and switch
+on the component "Lightproof editor" and *restart* LibreOffice for rule
+development.
+
+There is no visual editor for optional features, yet (dlg file), but you can
+compile and test all optional rules in the editor with the Apply all rules icon.
+Also copying your rule and dialog definition files to the src/editor folder,
+you can compile an extended editor extension with the
+following command: python make.py src/editor/editor.cfg
+
+Note: the default locales of the editor (supported languages of the edited rule
+document) cover only the languages with Hunspell dictionaries. Choose such
+languages for editing in Writer (eg. Esperanto), or add your language to the
+"locales" section of the src/editor/editor.cfg and compile the editor extension.
+
+== Extension development ==
+
+1. Copy src/en/en.cfg, dat and dlg files under the name src/your_locale/your_locale.cfg, dat and dlg.
+
+2. Set cfg, translate messages, dat and dlg files (see doc/dialog.txt).
+
+3. Compile and install your data (see README)
+
+== LibreOffice integration ==
+
+Short description about the Lightproof integration with the dictionary
+extensions (it is not an automatic process yet):
+
+1. Copy dialog/* and pythonpath/* directories and Lightproof.py, Linguistic.xcu
+of your Lightproof extension to the dictionaries/your_language/ directory of
+LibreOffice. (Note: pythonpath/lightproof_compiler* doesn't need for the
+integration.)
+
+2. Extend COMPONENT_FILES variable of makefile.mk with these new files.
+
+3. Extend manifest.xml with the following elements:
+
+ <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcs"
+
+manifest:media-type="application/vnd.sun.star.configuration-schema" />
+ <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcu"
+
+manifest:media-type="application/vnd.sun.star.configuration-data" />
+ <manifest:file-entry
+manifest:media-type="application/vnd.sun.star.uno-component;type=Python"
+ manifest:full-path="Lightproof.py"/>
+ <manifest:file-entry
+
+manifest:media-type="application/vnd.sun.star.configuration-data"
+ manifest:full-path="Linguistic.xcu" />
+
+4. Change extension ID of dialog/OptionsDialog.xcu to the ID of the dictionary
+extension (see in description.xml):
+
+<prop oor:name="Id">
+ <value>org.openoffice.en.hunspell.dictionaries</value>
+</prop>
+
+
+
diff --git a/doc/syntax.txt b/doc/syntax.txt
new file mode 100644
index 0000000..12da666
--- /dev/null
+++ b/doc/syntax.txt
@@ -0,0 +1,296 @@
+= Encoding =
+
+UTF-8
+
+= Rule syntax =
+
+pattern -> replacement # message
+
+or (see Conditions)
+
+pattern <- condition -> replacement # message
+
+or
+
+pattern <- condition -> = replacement # = expression_for_message
+pattern <- condition -> = expression_to_generate_replacement_string # message
+pattern <- condition -> = expression_to_generate_replacement_string # = expression_for_message
+
+
+Basically pattern and replacement will be the parameters of the
+standard Python re.sub() regular expression function (see also
+Python regex module documentation for regular expression syntax:
+http://docs.python.org/library/re.html).
+
+Example 0. Report "foo" in the text and suggest "bar":
+
+foo -> bar # Use bar instead of foo.
+
+Example 1. Recognize and suggest missing hyphen:
+
+foo bar -> foo-bar # Missing hyphen.
+
+= Rule Sections =
+
+Example 2. Recognize double or more spaces and suggests a single space:
+
+[char]
+
+" +" -> " " # Extra space.
+
+The line [char] changes the default word-level rules to character-level ones.
+Use [Word] to change back to the (case-insensitive) word-level rules.
+Also [word] is for the case-sensitive word-level rules, and [Char] for the
+case-insensitive character-level rules.
+
+ASCII " characters protect spaces in the pattern and in the replacement text.
+Plus sign means 1 or more repetitions of the previous space.
+
+= Other examples =
+
+Example 3. Suggest a word with correct quotation marks:
+
+\"(\w+)\" -> “\1” # Correct quotation marks.
+
+(Here \" is an ASCII quotation mark, \w means an arbitrary letter,
++ means 1 or more repetitions of the previous object,
+The parentheses define a regex group (the word). In the
+replacement, \1 is a reference to the (first) group of the pattern.)
+
+Example 4. Suggest the missing space after the !, ? or . signs:
+
+\b([?!.])([a-zA-Z]+) -> \1 \2 # Missing space?
+
+\b is the zero-length word boundary regex notation, so
+\b signs the end and the begin of the words.
+
+The [ and ] define a character pattern, the replacement will contain
+the actual matching character (?, ! or .), a space and the word after
+the punctuation character.
+Note: ? and . characters have special meanings in regular expressions,
+use [?] or [.] patterns to check "?" and "." signs in the text.
+
+== Multiple suggestions ==
+
+Use \n (new line) in the replacement text to add multiple suggestions:
+
+foo -> Foo\nFOO\nBar\nBAR # Did you mean:
+
+(Foo, FOO, Bar and BAR suggestions for the input word "foo")
+
+= Expressions in the suggestions =
+
+Suggestions (and warning messages) started by an equal sign are Python string expressions
+extended with possible back references and named definitions:
+
+Example:
+
+foo\w+ -> = '"' + \0.upper() + '"' # With uppercase letters and quoation marks
+
+All words beginning with "foo" will be recognized, and the suggestion is
+the uppercase form of the string with ASCII quoation marks: eg. foom -> "FOOM".
+
+== Longer explanations ==
+
+Warning messages can contain optional URLs for longer explanations separated by "\n":
+
+(your|her|our|their)['’]s -> \1s # Possessive pronoun: \n http://en.wikipedia.org/wiki/Possessive_pronoun
+
+== Default variables ==
+
+LOCALE
+
+It contains the current locale of the checked paragraph. Its fields:
+For en-US LOCALE.Language = "en" and LOCALE.Country = "US", eg.
+
+colour <- LOCALE.Language == "US" -> color # Use American English spelling.
+
+TEXT
+
+Full text of the checked paragraph.
+
+== Name definitions ==
+
+Lightproof supports name definitions to simplify the
+description of the complex rules.
+
+Definition:
+
+name pattern # name definition
+
+Usage in the rules:
+
+"{name} " -> "{name}. " # Missing dot?
+
+{Name}s in the first part of the rules mean
+subpatterns (groups). {Name}s in the second
+part of the rules mean back references to the
+matched texts of the subpatterns.
+
+Example: thousand markers (10000 -> 10,000 or 10 000)
+
+# definitions
+d \d\d\d # name definition: 3 digits
+d2 \d\d # 2 digits
+D \d{1,3} # 1, 2 or 3 digits
+
+# rules
+# ISO thousand marker: space, here: no-break space (U+00A0)
+{d2}{d} -> {d2},{d}\n{d2} {d} # Use thousand marker (common or ISO).
+{D}{d}{d} -> {D},{d},{d}\n{D} {d} {d} # Use thousand markers (common or ISO).
+
+Note: Lightproof uses named groups for name definitions and
+their references, adding a hidden number to the group names
+in the form of "_n". You can use these explicit names in the replacement:
+
+{d2}{d} -> {d2_1},{d_1}\n{d2_1} {d_1} # Use thousand marker (common or ISO).
+{D}{d}{d} -> {D_1},{d_1},{d_2}\n{D_1} {d_1} {d_2} # Use thousand markers (common or ISO).
+
+Note: back references of name definitions are zeroed after new line
+characters, see this and the following example:
+
+E ( |$) # name definition: space or end of sentence
+"\b[.][.]{E}" -> .{E}\n…{E} # Period or ellipsis?
+
+See src/en/en.dat for more examples.
+
+= Conditions =
+
+A Lightproof condition is a Python condition with some modifications:
+the \0..\9 regex notations and the Lightproof {name} notations in the condition will be
+replaced by the matched subpatterns. For example, the rule
+
+\w+ <- \0 == "foo" -> Foo # Foo is a capitalized word.
+
+is equivalent of the following rule:
+
+foo -> Foo # Foo is a capitalized word.
+
+== Standard functions ==
+
+There are some default function for the rule conditions.
+
+
+word(n) or word(-n):
+
+The function word(n) returns the Nth word (separated only by white spaces)
+before or after the matching pattern, or None, if this word doesn't exist.
+
+
+morph(word, regex pattern):
+morph(word, regex pattern, all):
+
+The function morph returns a matching subpattern of the morphological analysis
+of the input word or None, if the pattern won't match all items of the
+analysis of the input word. For example, the rule
+
+\ban ([a-z]\w+) <- morph(\1, "(po:verb|is:plural)") -> and \1 # Missing letter?
+
+will find the word "an" followed by a not capitalized verb or a plural noun (the notation depends from the morphological data of
+the Hunspell dictionary).
+
+The optional argument can modify the default "all" mode to "if exists", using
+the False value:
+
+morph(word, regex pattern, False):
+
+stem(word):
+
+The function returns an arraw with the stems of the input word.
+
+Usage:
+
+(\w+) <- "foo" in stem(\1) -> bar # One of the stem of the word is "foo"
+
+(\w+) <- stem(\1) == ["foo"] -> bar # The word has got only one stem, "foo".
+
+
+
+affix(word, regex pattern):
+affix(word, regex pattern, all):
+
+Variant of morph: it filters the affix fields from the result of the analysis
+before matching the pattern.
+
+The optional argument can modify the default "all" mode to "if exists", using
+the False value:
+
+affix(word, regex pattern, False):
+
+
+calc(functionname, functionparameters):
+
+Access to the Calc functions. Functionparameters is a tuple with the parameter
+of the Calc function:
+
+calc("CONCATENATE", ("string1", "string2"))
+
+
+generate(word, example_word):
+
+Morphological generation by example, eg. the result of generate("mouse",
+"rodents") is ["mice"] with the en_US English dictionary. (See also
+Hunspell (4) manual page for morphological generation.)
+
+option(optionname):
+
+Return the Boolean value of the option (see doc/dialog.txt).
+
+== Multi-line rules ==
+
+Rules can be break to multiple lines by leading tabulators:
+
+pattern <- condition
+ # only comment
+ -> replacement
+ # message (last comment)
+
+== User code support ==
+
+Use [code] sections to add your own Python functions for the rules:
+
+Example (suggesting uppercase form for all words with underline character,
+for example hello_world -> HELLO_WORLD)
+
+[code]
+
+def u(s):
+ return s.upper()
+
+[Word]
+
+# suggest uppercase form for all words with underline character
+
+\w+_\w+ -> =u(\0) # Use uppercase form
+
+(In fact, this is equivalent of the following rule:
+
+\w+_\w+ -> =\0.upper() # Use uppercase form)
+
+See English rules (src/en/en.dat) for more examples, eg. precompiled regular
+expressions for sentence checking, sets to handle more irregular words etc.
+
+= Typical problems =
+
+== Encoding ==
+
+Python expressions (< Python 3.0) need explicit Unicode declaration for non-ASCII
+characters:
+
+fó -> bár # example
+
+is equivalent of the following rule (see u'string' instead of 'string')
+
+fó -> = u'bár' # example
+
+== Pattern matching ==
+
+Repeating pattern matching of a single rule continues after the previous matching, so
+instead of general multiword patterns, like
+
+(\w+) (\w+) <- some_check(\1, \2) -> \1, \2 # foo
+
+use
+
+(\w+) <- some_check(\1, word(1)) -> \1, # foo
+
diff --git a/make.py b/make.py
new file mode 100644
index 0000000..f836e8a
--- /dev/null
+++ b/make.py
@@ -0,0 +1,45 @@
+# -*- encoding: UTF-8 -*-
+import sys, os, zipfile, traceback, Dialog
+import ConfigParser as cp # configparser in Python 3
+import pythonpath.lightproof_compile___implname__
+from string import Template
+
+def dist(fn, a):
+ a['locales'] = a["locales"].replace("_", "-")
+ a['loc'] = str(dict([[i, [i[0:2], i[3:5], ""]] for i in a["locales"].split(" ")]))
+ distname = a['implname'] + "-" + a['version'] + '.oxt'
+ z = zipfile.ZipFile(distname, mode='w', compression = zipfile.ZIP_DEFLATED)
+ f = open(fn + ".dat",'r')
+ code = pythonpath.lightproof_compile___implname__.c(unicode(f.read(), "UTF-8"), a['lang'])
+ a["code"] = code["code"]
+ a['data'] = code["rules"]
+
+ for i in ["META-INF/manifest.xml", "description.xml", "Linguistic.xcu", "Lightproof.py", \
+ "pythonpath/lightproof_handler___implname__.py", "pythonpath/lightproof_impl___implname__.py", \
+ "pythonpath/lightproof___implname__.py" ]:
+ z.writestr(i.replace("__implname__", a["implname"]), Template(open(i, "r").read()).safe_substitute(a))
+
+ for i in a["extras"].split(","):
+ z.writestr(i.strip().replace("../", "").replace("__implname__", a["implname"]), \
+ open(fn[:fn.rfind("/")+1] + i.strip()).read())
+
+ try:
+ d = open(fn + ".dlg", "r").readlines()
+ Dialog.c(a["implname"], d, z, a["lang"])
+ except:
+ z.writestr("pythonpath/lightproof_opts_%s.py"%a["implname"], "")
+
+if len(sys.argv) == 1:
+ print """Synopsis: python make.py config_file
+eg. python make.py src/en/en.cfg"""
+ sys.exit(0)
+
+fArgs = cp.SafeConfigParser()
+for i in sys.argv[1:]:
+ try:
+ fArgs.read(i)
+ dist(i[:-4], fArgs._sections['args'])
+ except:
+ print traceback.format_exc()
+ print "missing config file or options: ", i
+ sys.exit(0)
diff --git a/pythonpath/__init__.py b/pythonpath/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pythonpath/__init__.py
diff --git a/pythonpath/lightproof___implname__.py b/pythonpath/lightproof___implname__.py
new file mode 100644
index 0000000..c1fe0ce
--- /dev/null
+++ b/pythonpath/lightproof___implname__.py
@@ -0,0 +1,3 @@
+# -*- encoding: UTF-8 -*-
+dic = ${data}
+
diff --git a/pythonpath/lightproof_compile___implname__.py b/pythonpath/lightproof_compile___implname__.py
new file mode 100644
index 0000000..7c37bf4
--- /dev/null
+++ b/pythonpath/lightproof_compile___implname__.py
@@ -0,0 +1,276 @@
+import sys, re, traceback
+from string import split
+
+repl = {}
+tests = []
+comp = []
+modes = ["[Word]", "[word]", "[Char]", "[char]", "[code]"]
+mode = "[Word]"
+code = u""
+language = ""
+oldlinenums = {}
+
+def prepare_for_eval(s):
+ s = re.sub("(affix|spell|morph|stem|option|suggest|generate)\(", r'\1(LOCALE,', s)
+ s = re.sub(r"word\(\s*(\d)", r'word(s[m.end():],\1', s) # word(n)
+ s = re.sub(r"word\(\s*-(\d)", r'wordmin(s[:m.start()],\1', s) # word(-n)
+ s = re.sub(r"[\\](\d)", r'm.group(\1)', s)
+ s = re.sub("[{]([^}]+)}", r'm.group("\1_1")', s)
+ return s
+
+
+def mysplit(s, line, oldline, debug):
+ global repl
+ global tests
+ global comp
+ global modes
+ global mode
+ orig = s
+ if s[0:1] == '[':
+ if s.strip() in modes:
+ mode = s.strip()
+ return None
+ elif re.match(r"\[\w+\]$", s.strip()):
+ #sys.stderr.write("Unknown mode: " + s + "\n")
+ return oldline
+ dec = 0
+ exprep = 0 # replacement is a Python expression (beginning with sign =)
+ condition = False
+ # description
+ c = re.search("\s#\s", s)
+ com = u""
+ if c:
+ try:
+ c = c.start(c.lastindex - 1)
+ except:
+ c = c.start()
+ com = prepare_for_eval(s[c+2:].strip())
+ s = s[:c]
+ m1 = re.search("<-", s)
+ m2 = re.search("->", s)
+ if m1 and m2:
+ condition = prepare_for_eval(s[m1.end(0): m2.start(0)].strip())
+ s = s[0:m1.start(0)] + s[m2.start(0):]
+ if s[0:1] == '"':
+ # quoted
+ pos = s[1:].find('"')
+ while pos > 0 and s[pos] == '\\':
+ pos = s[pos:].find('"')
+ s1 = s[1:pos+1]
+ s2 = s[pos+2:].strip()
+ else:
+ m = re.compile("->").search(s)
+ if not m:
+ m = re.compile("[_a-zA-Z][_a-zA-Z0-9]*").match(s)
+ if not m:
+ # syntax error
+ return oldline
+ s1 = m.group(0)
+ s2 = s[m.end(0):].strip()
+ # replace previous definitions
+ for i in repl:
+ ire = re.compile("[{]" + i + "}")
+ if re.search(ire, s2):
+ s2 = ire.sub(repl[i], s2)
+ # make named group
+ s2 = "(?P<" + m.group(0) + ">" + s2 + ")"
+ dec = 1
+ else:
+ s1 = s[0:m.start(0)].strip()
+ if re.match("TEST: ", s1): # deprecated
+ tests += [[s1[5:].strip(), s[m.end(0):].strip(), oldline]]
+ return None
+ s2 = s[m.start(0):].strip()
+ m = re.compile("->").match(s2)
+ if dec!= 1 and m:
+ s2 = s2[m.end(0):].strip()
+ elif dec!=1:
+ # syntax error
+ return oldline
+ if s2[0:1] == '=':
+ exprep = 1
+ if s2[0:1] == '"' and s2[-1:]=='"':
+ s2 = s2[1:-1]
+ if dec==1:
+ repl[s1] = s2
+ return None
+ else:
+ for i in repl:
+ s1 = re.sub("[{]" + i + "}", repl[i], s1)
+ # modes
+ if mode == "[Word]" or mode == "[word]":
+ if s1[0] == '^':
+ s1 = ur"((?<=[!?.] )|^)" + s1[1:] + ur"(?![-\w\u2013\u00AD])"
+ else:
+ s1 = ur"(?<![-\w\u2013.,\u00AD])" + s1 + ur"(?![-\w\u2013\u00AD])"
+ # modes with casing ([Word] or [Char])
+ if mode == "[Word]" or mode == "[Char]":
+ s1 = "(?i)" + s1
+ # add Unicode flag to the regex by (?u)
+ s1 = re.sub("[(][?][iI][)]", "(?iu)", s1)
+ if not re.match("[(][?][iI][uU][)]", s1):
+ s1 = "(?u)" + s1
+ else:
+ # casing
+ lu = re.compile("(?u)\w")
+ s3 = u""
+ state = 0
+ for i in range(0, len(s1)):
+ c = s1[i]
+ if c == "[":
+ state = 1
+ if state == 1 and c == "]":
+ state = 0
+ if c == "<" and i > 3 and s1[i-3:i]=="(?P":
+ state = 2
+ if state == 2 and c == ">":
+ state = 0
+ if c == "?" and i > 0 and s1[i-1:i]=="(":
+ state = 5
+ if state == 5 and c == ")":
+ state = 0
+ if lu.match(c) and c.islower() and state == 0:
+ if c=="i" and (language == "tr" or language == "az"):
+ s3 += u"[\u0130" + c + "]"
+ else:
+ s3 += "[" + c.upper() + c + "]"
+ elif lu.match(c) and c.islower() and state == 1 and s1[i+1:i+2] != "-":
+ if s1[i-1:i] == "-" and s1[i-2:i-1].islower(): # [a-z] -> [a-zA-Z]
+ s3 += c + s1[i-2:i-1].upper() + "-" + c.upper()
+ elif c=="i" and (language == "tr" or language == "az"):
+ s3 += u"\u0130" + c
+ else:
+ s3 += c.upper() + c
+ else:
+ s3 += c
+ if c == "\\":
+ state = 4
+ elif state == 4:
+ state = 0
+ s1 = s3
+ s1 = renum("[?]P<([^<_]*)>", s1, "?P<")
+ if exprep == 0:
+ s2 = re.sub("[{]([_a-zA-Z][_a-zA-Z0-9]*)}", r"\\g<\1>", s2)
+ s2 = renum(r"\\g<([^<_]*)>", s2, r"\\g<")
+ else:
+ s2 = prepare_for_eval(s2)
+ # check
+ if re.compile("[(][?]iu[)]").match(s1):
+ cap = True
+ sc = re.sub("[(][?]iu[)]", "(?u)", s1)
+ else:
+ cap = False
+ sc = s1
+ try:
+ compr = re.compile(sc)
+ if not condition:
+ comp += [[compr, s2, com, cap, line]]
+ except Exception as e:
+ raise Exception(str(e), oldline)
+ if debug:
+ return [s1, s2, com, condition, oldline]
+ return [s1, s2, com, condition]
+
+# group renum (<groupname> -> <groupname_1> etc.)
+def renum(regex, s1, beg):
+ j={}
+ mr = re.compile(regex)
+ m = mr.search(s1)
+ nl = s1.find("\\n")
+ while m:
+ # restart numbering in new lines
+ if nl > -1 and m.start(0) > (nl + 1):
+ j={}
+ nl = s1[m.start(0):].find("\\n")
+ if nl > -1:
+ nl = m.start(0) + nl
+ n = m.group(1)
+ if n in j:
+ j[n] += 1
+ else:
+ j[n] = 1
+ s1 = re.sub(mr, beg + n + "_" + str(j[n]) + ">", s1, 1)
+ m = mr.search(s1)
+ return s1
+
+def cap(a, iscap):
+ global language
+ if iscap:
+ for i in range(0, len(a)):
+ if a[i][0:1] == "i":
+ if language == "tr" or language == "az":
+ a[i] = u"\u0130" + a[i][1:]
+ elif a[i][1:2] == "j" and language == "nl":
+ a[i] = "IJ" + a[i][2:]
+ else:
+ a[i] = "I" + a[i][1:]
+ else:
+ a[i] = a[i].capitalize()
+ return a
+
+def c(rules, lang, debug = False):
+ global language
+ global code
+ global oldlinenums
+ language = lang
+ r = re.compile("[\n#]")
+ code = ""
+ dic = []
+ oldlinenums = {}
+
+ lines = rules.split("\n")
+ lines2 = []
+ result = {}
+
+
+ cm = 0
+ lnums = 1
+ for i in lines:
+ if i.strip() in modes:
+ if i.strip() == "[code]":
+ cm = 1
+ continue
+ else:
+ cm = 0
+ if cm == 1:
+ code = code + i + "\n"
+ elif len(i.strip()) > 0:
+ lines2 = lines2 + [i]
+ oldlinenums[i] = lnums
+ lnums = lnums + 1
+
+ lines = lines2
+
+ # concatenate multiline commands
+ # last tabulator + comment is the message
+ l = u""
+ comment = 0
+ for i in range(len(lines)-1, -1, -1):
+ if re.match("\t", lines[i]):
+ if not (comment and re.match("\t+#", lines[i])):
+ l = lines[i].strip() + " " + l
+ if re.search("#", lines[i]):
+ comment = 1
+ del lines[i]
+ elif l != "":
+ lnums = oldlinenums[lines[i]]
+ lines[i] = lines[i].strip() + " " + l
+ oldlinenums[lines[i]] = lnums
+ l = ""
+ comment = 0
+
+ # processing
+ for i in range(0, len(lines)):
+ if not r.match(lines[i]):
+ item = mysplit(lines[i].strip(), i + 1, oldlinenums[lines[i]], debug)
+ if item != None:
+ if type(item) == type(1):
+ raise Exception("Syntax error in line ", item)
+ dic = dic + [item]
+
+ result["rules"] = dic
+ code = re.sub(r"(?<![\\])\\n", "\n", code.encode("unicode-escape"))
+
+ result["code"] = re.sub(r"(?<![\\])\\t", "\t", code).replace(r"\\n", r"\n").replace(r"\\t", r"\t")
+
+ return result
diff --git a/pythonpath/lightproof_handler___implname__.py b/pythonpath/lightproof_handler___implname__.py
new file mode 100644
index 0000000..3e5a284
--- /dev/null
+++ b/pythonpath/lightproof_handler___implname__.py
@@ -0,0 +1,119 @@
+import uno
+import unohelper
+import lightproof_opts_${implname}
+from lightproof_impl_${implname} import pkg
+
+from com.sun.star.lang import XServiceInfo
+from com.sun.star.awt import XContainerWindowEventHandler
+
+# options
+options = {}
+
+def load(context):
+ try:
+ l = LightproofOptionsEventHandler(context)
+ for i in lightproof_opts_${implname}.lopts:
+ l.load(i)
+ except:
+ pass
+
+def get_option(page, option):
+ try:
+ return options[page + "," + option]
+ except:
+ try:
+ return options[page[:2] + "," + option]
+ except:
+ return 0
+
+def set_option(page, option, value):
+ options[page + "," + option] = int(value)
+
+class LightproofOptionsEventHandler( unohelper.Base, XServiceInfo, XContainerWindowEventHandler ):
+ def __init__( self, ctx ):
+ p = uno.createUnoStruct( "com.sun.star.beans.PropertyValue" )
+ p.Name = "nodepath"
+ p.Value = "/org.openoffice.Lightproof_%s/Leaves"%pkg
+ self.xConfig = ctx.ServiceManager.createInstance( 'com.sun.star.configuration.ConfigurationProvider' )
+ self.node = self.xConfig.createInstanceWithArguments( 'com.sun.star.configuration.ConfigurationUpdateAccess', (p, ) )
+ self.service = "org.openoffice.comp.pyuno.LightproofOptionsEventHandler." + pkg
+ self.ImplementationName = self.service
+ self.services = (self.service, )
+
+ # XContainerWindowEventHandler
+ def callHandlerMethod(self, aWindow, aEventObject, sMethod):
+ if sMethod == "external_event":
+ return self.handleExternalEvent(aWindow, aEventObject)
+
+ def getSupportedMethodNames(self):
+ return ("external_event", )
+
+ def handleExternalEvent(self, aWindow, aEventObject):
+ sMethod = aEventObject
+ if sMethod == "ok":
+ self.saveData(aWindow)
+ elif sMethod == "back" or sMethod == "initialize":
+ self.loadData(aWindow)
+ return True
+
+ def load(self, sWindowName):
+ child = self.getChild(sWindowName)
+ for i in lightproof_opts_${implname}.lopts[sWindowName]:
+ sValue = child.getPropertyValue(i)
+ if sValue == '':
+ if i in lightproof_opts_${implname}.lopts_default[sWindowName]:
+ sValue = 1
+ else:
+ sValue = 0
+ set_option(sWindowName, i, sValue)
+
+ def loadData(self, aWindow):
+ sWindowName = self.getWindowName(aWindow)
+ if (sWindowName == None):
+ return
+ child = self.getChild(sWindowName)
+ for i in lightproof_opts_${implname}.lopts[sWindowName]:
+ sValue = child.getPropertyValue(i)
+ if sValue == '':
+ if i in lightproof_opts_${implname}.lopts_default[sWindowName]:
+ sValue = 1
+ else:
+ sValue = 0
+ xControl = aWindow.getControl(i)
+ xControl.State = sValue
+ set_option(sWindowName, i, sValue)
+
+ def saveData(self, aWindow):
+ sWindowName = self.getWindowName(aWindow)
+ if (sWindowName == None):
+ return
+ child = self.getChild(sWindowName)
+ for i in lightproof_opts_${implname}.lopts[sWindowName]:
+ xControl = aWindow.getControl(i)
+ sValue = xControl.State
+ child.setPropertyValue(i, str(sValue))
+ set_option(sWindowName, i, sValue)
+ self.commitChanges()
+
+ def getWindowName(self, aWindow):
+ sName = aWindow.getModel().Name
+ if sName in lightproof_opts_${implname}.lopts:
+ return sName
+ return None
+
+ # XServiceInfo method implementations
+ def getImplementationName (self):
+ return self.ImplementationName
+
+ def supportsService(self, ServiceName):
+ return (ServiceName in self.services)
+
+ def getSupportedServiceNames (self):
+ return self.services
+
+ def getChild(self, name):
+ return self.node.getByName(name)
+
+ def commitChanges(self):
+ self.node.commitChanges()
+ return True
diff --git a/pythonpath/lightproof_impl___implname__.py b/pythonpath/lightproof_impl___implname__.py
new file mode 100644
index 0000000..2344a77
--- /dev/null
+++ b/pythonpath/lightproof_impl___implname__.py
@@ -0,0 +1,229 @@
+# -*- encoding: UTF-8 -*-
+import uno, re, sys, os, traceback
+from string import join
+from com.sun.star.text.TextMarkupType import PROOFREADING
+from com.sun.star.beans import PropertyValue
+
+pkg = "${implname}"
+lang = "${lang}"
+locales = ${loc}
+version = "${version}"
+author = "${author}"
+name = "${name}"
+
+import lightproof_handler_${implname}
+
+# loaded rules (check for Update mechanism of the editor)
+try:
+ langrule
+except NameError:
+ langrule = {}
+
+# ignored rules
+ignore = {}
+
+# cache for morphogical analyses
+analyses = {}
+stems = {}
+suggestions = {}
+
+# assign Calc functions
+calcfunc = None
+
+# check settings
+def option(lang, opt):
+ return lightproof_handler_${implname}.get_option(lang.Language + "_" + lang.Country, opt)
+
+# filtering affix fields (ds, is, ts etc.)
+def onlymorph(st):
+ if st != None:
+ st = re.sub(r"^.*(st:|po:)", r"\\1", st) # keep last word part
+ st = re.sub(r"\\b(?=[dit][sp]:)","@", st) # and its affixes
+ st = re.sub(r"(?<!@)\\b\w\w:\w+","", st).replace('@','').strip()
+ return st
+
+# if the pattern matches all analyses of the input word,
+# return the last matched substring
+def _morph(rLoc, word, pattern, all, onlyaffix):
+ global analyses
+ if word == None:
+ return None
+ if word not in analyses:
+ x = spellchecker.spell(u"<?xml?><query type='analyze'><word>" + word + "</word></query>", rLoc, ())
+ if not x:
+ return None
+ t = x.getAlternatives()
+ if not t:
+ t = [""]
+ analyses[word] = t[0]
+ a = analyses[word].split("</a>")[:-1]
+ result = None
+ p = re.compile(pattern)
+ for i in a:
+ if onlyaffix:
+ i = onlymorph(i)
+ result = p.search(i)
+ if result:
+ result = result.group(0)
+ if not all:
+ return result
+ elif all:
+ return None
+ return result
+
+def morph(rLoc, word, pattern, all=True):
+ return _morph(rLoc, word, pattern, all, False)
+
+def affix(rLoc, word, pattern, all=True):
+ return _morph(rLoc, word, pattern, all, True)
+
+def spell(rLoc, word):
+ if word == None:
+ return None
+ return spellchecker.isValid(word, rLoc, ())
+
+# get the tuple of the stem of the word or an empty array
+def stem(rLoc, word):
+ global stems
+ if word == None:
+ return []
+ if not word in stems:
+ x = spellchecker.spell(u"<?xml?><query type='stem'><word>" + word + "</word></query>", rLoc, ())
+ if not x:
+ return []
+ t = x.getAlternatives()
+ if not t:
+ t = []
+ stems[word] = list(t)
+ return stems[word]
+
+# get the tuple of the morphological generation of a word or an empty array
+def generate(rLoc, word, example):
+ if word == None:
+ return []
+ x = spellchecker.spell(u"<?xml?><query type='generate'><word>" + word + "</word><word>" + example + "</word></query>", rLoc, ())
+ if not x:
+ return []
+ t = x.getAlternatives()
+ if not t:
+ t = []
+ return list(t)
+
+# get suggestions
+def suggest(rLoc, word):
+ global suggestions
+ if word == None:
+ return word
+ if word not in suggestions:
+ x = spellchecker.spell("_" + word, rLoc, ())
+ if not x:
+ return word
+ t = x.getAlternatives()
+ suggestions[word] = join(t, "\\n")
+ return suggestions[word]
+
+# get the nth word of the input string or None
+def word(s, n):
+ a = re.match("(?u)( [-.\w%%]+){" + str(n-1) + "}( [-.\w%%]+)", s)
+ if not a:
+ return None
+ return a.group(2)[1:]
+
+# get the (-)nth word of the input string or None
+def wordmin(s, n):
+ a = re.search("(?u)([-.\w%%]+ )([-.\w%%]+ ){" + str(n-1) + "}$", s)
+ if not a:
+ return None
+ return a.group(1)[:-1]
+
+def calc(funcname, par):
+ global calcfunc
+ global SMGR
+ if calcfunc == None:
+ calcfunc = SMGR.createInstance( "com.sun.star.sheet.FunctionAccess")
+ if calcfunc == None:
+ return None
+ return calcfunc.callFunction(funcname, par)
+
+def proofread( nDocId, TEXT, LOCALE, nStartOfSentencePos, nSuggestedSentenceEndPos, rProperties ):
+ global ignore
+ aErrs = []
+ s = TEXT[nStartOfSentencePos:nSuggestedSentenceEndPos]
+ for i in get_rule(LOCALE).dic:
+ if i[0] and not str(i[0]) in ignore:
+ for m in i[0].finditer(s):
+ try:
+ if not i[3] or eval(i[3]):
+ aErr = uno.createUnoStruct( "com.sun.star.linguistic2.SingleProofreadingError" )
+ aErr.nErrorStart = nStartOfSentencePos + m.start(0) # nStartOfSentencePos
+ aErr.nErrorLength = m.end(0) - m.start(0)
+ aErr.nErrorType = PROOFREADING
+ aErr.aRuleIdentifier = str(i[0])
+ iscap = (i[-1] and m.group(0)[0:1].isupper())
+ if i[1][0:1] == "=":
+ aErr.aSuggestions = tuple(cap(eval(i[1][1:]).split("\\n"), iscap, LOCALE))
+ else:
+ aErr.aSuggestions = tuple(cap(m.expand(i[1]).split("\\n"), iscap, LOCALE))
+ comment = i[2]
+ if comment[0:1] == "=":
+ comment = eval(comment[1:])
+ aErr.aShortComment = comment.split("\\n")[0].strip()
+ aErr.aFullComment = comment.split("\\n")[-1].strip()
+ if "://" in aErr.aFullComment:
+ p = PropertyValue()
+ p.Name = "FullCommentURL"
+ p.Value = aErr.aFullComment
+ aErr.aFullComment = aErr.aShortComment
+ aErr.aProperties = (p,)
+ else:
+ aErr.aProperties = ()
+ aErrs = aErrs + [aErr]
+ except Exception as e:
+ if len(i) == 6:
+ raise Exception(str(e), i[4])
+ raise
+
+ return tuple(aErrs)
+
+def cap(a, iscap, rLoc):
+ if iscap:
+ for i in range(0, len(a)):
+ if a[i][0:1] == "i":
+ if rLoc.Language == "tr" or rLoc.Language == "az":
+ a[i] = u"\u0130" + a[i][1:]
+ elif a[i][1:2] == "j" and rLoc.Language == "nl":
+ a[i] = "IJ" + a[i][2:]
+ else:
+ a[i] = "I" + a[i][1:]
+ else:
+ a[i] = a[i].capitalize()
+ return a
+
+def compile_rules(dic):
+ # compile regular expressions
+ for i in dic:
+ try:
+ if re.compile("[(][?]iu[)]").match(i[0]):
+ i += [True]
+ i[0] = re.sub("[(][?]iu[)]", "(?u)", i[0])
+ else:
+ i += [False]
+ i[0] = re.compile(i[0])
+ except:
+ print "Lightproof: bad regular expression: ", traceback.format_exc()
+ i[0] = None
+
+def get_rule(loc):
+ try:
+ return langrule[pkg]
+ except:
+ langrule[pkg] = __import__("lightproof_" + pkg)
+ compile_rules(langrule[pkg].dic)
+ return langrule[pkg]
+
+def get_path():
+ return os.path.join(os.path.dirname(sys.modules[__name__].__file__), __name__ + ".py")
+
+# [code]
+
+${code}
diff --git a/src/editor/Addons.xcu b/src/editor/Addons.xcu
new file mode 100644
index 0000000..958adc7
--- /dev/null
+++ b/src/editor/Addons.xcu
@@ -0,0 +1,97 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<oor:component-data
+ xmlns:oor="http://openoffice.org/2001/registry"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ oor:name="Addons"
+ oor:package="org.openoffice.Office">
+ <node oor:name="AddonUI">
+ <node oor:name="OfficeToolBar">
+ <node oor:name="lightproof_editor.OfficeToolBar" oor:op="replace">
+ <node oor:name="m0" oor:op="replace">
+ <prop oor:name="Context" oor:type="xs:string">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+ <prop oor:name="URL" oor:type="xs:string">
+ <value>macro:///lightproof_editor.General.Compile</value>
+ </prop>
+ <prop oor:name="Title" oor:type="xs:string">
+ <value>Apply rules (Alt-R)</value>
+ </prop>
+ <prop oor:name="Target" oor:type="xs:string">
+ <value>_self</value>
+ </prop>
+ </node>
+ <node oor:name="m1" oor:op="replace">
+ <prop oor:name="Context" oor:type="xs:string">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+ <prop oor:name="URL" oor:type="xs:string">
+ <value>macro:///lightproof_editor.General.CompileAll</value>
+ </prop>
+ <prop oor:name="Title" oor:type="xs:string">
+ <value>Apply all (also optional) rules (Alt-C)</value>
+ </prop>
+ <prop oor:name="Target" oor:type="xs:string">
+ <value>_self</value>
+ </prop>
+ </node>
+ <node oor:name="m2" oor:op="replace">
+ <prop oor:name="Context" oor:type="xs:string">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+ <prop oor:name="URL" oor:type="xs:string">
+ <value>macro:///lightproof_editor.General.Debug</value>
+ </prop>
+ <prop oor:name="Title" oor:type="xs:string">
+ <value>Debug rules (Alt-D)</value>
+ </prop>
+ <prop oor:name="Target" oor:type="xs:string">
+ <value>_self</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+
+ <node oor:name="Images">
+ <node oor:name="lightproof_editor-image-comp" oor:op="replace">
+ <prop oor:name="URL" oor:type="xs:string">
+ <value>macro:///lightproof_editor.General.Compile</value>
+ </prop>
+ <node oor:name="UserDefinedImages">
+ <prop oor:name="ImageSmallURL">
+ <value>%origin%/icons/comp16.png</value>
+ </prop>
+ <prop oor:name="ImageBigURL">
+ <value>%origin%/icons/comp.png</value>
+ </prop>
+ </node>
+ </node>
+ <node oor:name="lightproof_editor-image-compall" oor:op="replace">
+ <prop oor:name="URL" oor:type="xs:string">
+ <value>macro:///lightproof_editor.General.CompileAll</value>
+ </prop>
+ <node oor:name="UserDefinedImages">
+ <prop oor:name="ImageSmallURL">
+ <value>%origin%/icons/compall16.png</value>
+ </prop>
+ <prop oor:name="ImageBigURL">
+ <value>%origin%/icons/compall.png</value>
+ </prop>
+ </node>
+ </node>
+ <node oor:name="lightproof_editor-image-debug" oor:op="replace">
+ <prop oor:name="URL" oor:type="xs:string">
+ <value>macro:///lightproof_editor.General.Debug</value>
+ </prop>
+ <node oor:name="UserDefinedImages">
+ <prop oor:name="ImageSmallURL">
+ <value>%origin%/icons/debug16.png</value>
+ </prop>
+ <prop oor:name="ImageBigURL">
+ <value>%origin%/icons/debug.png</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+ </node>
+</oor:component-data>
diff --git a/src/editor/META-INF/manifest.xml b/src/editor/META-INF/manifest.xml
new file mode 100644
index 0000000..6c50439
--- /dev/null
+++ b/src/editor/META-INF/manifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<manifest:manifest>
+ <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcs"
+ manifest:media-type="application/vnd.sun.star.configuration-schema" />
+ <manifest:file-entry manifest:full-path="dialog/OptionsDialog.xcu"
+ manifest:media-type="application/vnd.sun.star.configuration-data" />
+ <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python"
+ manifest:full-path="Lightproof.py"/>
+ <manifest:file-entry
+ manifest:media-type="application/vnd.sun.star.configuration-data"
+ manifest:full-path="Linguistic.xcu" />
+ <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data" manifest:full-path ="Office/Accelerators.xcu"/>
+ <manifest:file-entry manifest:full-path="lightproof_editor/" manifest:media-type="application/vnd.sun.star.basic-library"/>
+ <manifest:file-entry manifest:full-path="pkg-desc/pkg-description.txt" manifest:media-type="application/vnd.sun.star.package-bundle-description"/>
+ <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data" manifest:full-path ="Office/Events.xcu"/>
+ <manifest:file-entry manifest:full-path="Office/UI/StartModuleWindowState.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>
+ <manifest:file-entry manifest:full-path="Office/UI/WriterWindowState.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>
+ <manifest:file-entry manifest:full-path="Addons.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>
+</manifest:manifest> \ No newline at end of file
diff --git a/src/editor/Office/Accelerators.xcu b/src/editor/Office/Accelerators.xcu
new file mode 100644
index 0000000..9492e4c
--- /dev/null
+++ b/src/editor/Office/Accelerators.xcu
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Accelerators" oor:package="org.openoffice.Office">
+ <node oor:name="PrimaryKeys">
+ <node oor:name="Modules">
+ <node oor:name="com.sun.star.text.TextDocument">
+ <node oor:name="R_MOD2" oor:op="replace">
+ <prop oor:name="Command">
+ <value xml:lang="hu">macro:///lightproof_editor.General.Compile</value>
+ </prop>
+ </node>
+ <node oor:name="C_MOD2" oor:op="replace">
+ <prop oor:name="Command">
+ <value xml:lang="hu">macro:///lightproof_editor.General.CompileAll</value>
+ </prop>
+ </node>
+ <node oor:name="D_MOD2" oor:op="replace">
+ <prop oor:name="Command">
+ <value xml:lang="hu">macro:///lightproof_editor.General.Debug</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+ </node>
+ <node oor:name="SecondaryKeys">
+ <node oor:name="Modules">
+ <node oor:name="com.sun.star.text.TextDocument">
+ </node>
+ </node>
+ </node>
+</oor:component-data> \ No newline at end of file
diff --git a/src/editor/Office/UI/StartModuleWindowState.xcu b/src/editor/Office/UI/StartModuleWindowState.xcu
new file mode 100644
index 0000000..19bcabe
--- /dev/null
+++ b/src/editor/Office/UI/StartModuleWindowState.xcu
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<oor:component-data xmlns:oor="http://openoffice.org/2001/registry"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ oor:name="StartModuleWindowState"
+ oor:package="org.openoffice.Office.UI">
+ <node oor:name="UIElements">
+ <node oor:name="States">
+ <node oor:name="private:resource/toolbar/addon_lightproof_editor.OfficeToolBar" oor:op="replace">
+ <prop oor:name="UIName" oor:type="xs:string">
+ <value>Lightproof editor
+ </value>
+ </prop>
+ <prop oor:name="Locked" oor:type="xs:boolean">
+ <value>false</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+</oor:component-data>
diff --git a/src/editor/Office/UI/WriterWindowState.xcu b/src/editor/Office/UI/WriterWindowState.xcu
new file mode 100644
index 0000000..14f4ed9
--- /dev/null
+++ b/src/editor/Office/UI/WriterWindowState.xcu
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<oor:component-data xmlns:oor="http://openoffice.org/2001/registry"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ oor:name="WriterWindowState"
+ oor:package="org.openoffice.Office.UI">
+ <node oor:name="UIElements">
+ <node oor:name="States">
+ <node oor:name="private:resource/toolbar/addon_lightproof_editor.OfficeToolBar" oor:op="replace">
+ <prop oor:name="UIName" oor:type="xs:string">
+ <value>Lightproof editor</value>
+ </prop>
+ <prop oor:name="Locked" oor:type="xs:boolean">
+ <value>false</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+</oor:component-data>
diff --git a/src/editor/README b/src/editor/README
new file mode 100644
index 0000000..dfca312
--- /dev/null
+++ b/src/editor/README
@@ -0,0 +1,75 @@
+Lightproof grammar checker rule editor for LibreOffice
+
+source: git://anongit.freedesktop.org/libreoffice/lightproof
+
+or see cgit.freedesktop.org/libreoffice
+
+version 0.1 (2012-02-02)
+
+2009–2012 (c) László Németh (nemeth at numbertext dot org), license: MPL 1.1 / GPLv3+ / LGPLv3+
+
+This software was developed with support from FSF.hu Foundation, Hungary.
+
+Introduction: http://libreoffice.hu/2011/12/08/grammar-checking-in-libreoffice/
+
+== Installation ==
+
+1. Via Tools -> Extension manager in OOo/LibreOffice
+
+2. or with unopkg tool, for example
+
+[install_path\program\]unopkg add -f lightproof_editor-0.1.oxt
+
+== Usage ==
+
+Note: there is a huge starting time (seconds) starting LibreOffice with the
+Lightproof editor. [Removing the unnecessary locales from src/editor/editor.cfg
+of Lightproof source and generating a new editor extension can solve this problem.]
+
+The Lightproof editor extension contains a special grammar checker component and
+a LibreOffice Writer toolbar. The editor can update its grammar checker component based
+on the Lightproof rules in the current Writer document.
+
+Note: for languages without 'official LibreOffice' Hunspell dictionaries or languages
+with default LibreOffice grammar checking (English, Russian and Hungarian in LibO 3.5)
+have to modify some settings, too, see doc/manual.txt in the zipped extension, or you
+can choose a neutral language (eg. Esperanto) for your Writer document during the rule
+development. Only the Hunspell-related Lightproof functions, eg. spell(), morph() need
+the correct language.
+
+After the successful installation (and settings), you can check the work of the grammar
+checking component of the editor with the following text:
+
+a a
+
+The repeating letters will be underlined with blue wavy line (thanks to the default
+a a -> a # Did you mean
+rule of the grammar checker component of the editor).
+
+Write the following Lightproof rule in an empty Writer document:
+
+b b -> b # suggestion
+
+Click on the first icon on the Lightproof editor toolbar. The 'b b' text will be
+underlined with blue wavy line as a grammar mistake with the 'b' suggestion and
+'suggestion' explanation.
+
+Load and modify the English Lightproof rules (src/en/en.dat) or decribe new rules
+based on doc/syntax.txt (these files can be found in the oxt (zipped) file of the
+Lightproof editor extension, too). See also doc/manual.txt and
+http://libreoffice.hu/2011/12/08/grammar-checking-in-libreoffice/
+
+= Toolbar icons =
+
+1. Apply rules
+
+Compile and the default Lightproof rules in the current document and update the Lightproof
+editor grammar checker component.
+
+2. Apply all rules
+
+Compile and apply all (including optional) Lightproof rules in the current document and update the relevant component.
+
+3. Debug rules
+
+Check the current text and report run time errors (eg. in the Python conditions of the rules).
diff --git a/src/editor/editor.cfg b/src/editor/editor.cfg
new file mode 100644
index 0000000..2145943
--- /dev/null
+++ b/src/editor/editor.cfg
@@ -0,0 +1,11 @@
+[args]
+lang = editor
+locales = af_ZA an_ES ar be_BY bg_BG bn_BD br_FR ca cs_CZ da_DK de_DE el_GR en_AU en_CA en_GB en_US en_ZA es_ES et_EE eo fr gd_GB gl_ES gu_IN he_IL hi_IN hr_HR hu_HU it_IT ku_TR lt_LT lv_LV ne_NP nl_NL nb_NO nn_NO oc_FR pl_PL pt_BR pt_PT ro_RO ru_RU si_LK sk_SK sl_SI sh sr sv_SE sw_TZ te_IN th_TH uk_UA vi_VN
+name = Lightproof editor
+version = 0.1
+author = László Németh
+provider = FSF.hu Foundation
+implname = lightproof_editor
+link = http://www.fsf.hu/about-us/
+description = Grammar checker rule editor for LibreOffice
+extras = ../../pythonpath/lightproof_compile___implname__.py, README, ../../doc/syntax.txt, ../../doc/manual.txt, ../../src/en/en.dat, lightproof_editor/script.xlb, lightproof_editor/RegisteredFlag, lightproof_editor/General.xba, lightproof_editor/dialog.xlb, Office/UI/StartModuleWindowState.xcu, Office/UI/WriterWindowState.xcu, Office/Accelerators.xcu, icons/comp.png, icons/compall.png, icons/comp16.png, icons/compall16.png, icons/debug16.png, icons/debug.png, META-INF/manifest.xml, Addons.xcu
diff --git a/src/editor/editor.dat b/src/editor/editor.dat
new file mode 100644
index 0000000..8dd5d64
--- /dev/null
+++ b/src/editor/editor.dat
@@ -0,0 +1 @@
+a a -> a # Did you mean:
diff --git a/src/editor/icons/comp.png b/src/editor/icons/comp.png
new file mode 100644
index 0000000..2a91ef5
--- /dev/null
+++ b/src/editor/icons/comp.png
Binary files differ
diff --git a/src/editor/icons/comp16.png b/src/editor/icons/comp16.png
new file mode 100644
index 0000000..dfa593f
--- /dev/null
+++ b/src/editor/icons/comp16.png
Binary files differ
diff --git a/src/editor/icons/compall.png b/src/editor/icons/compall.png
new file mode 100644
index 0000000..723a723
--- /dev/null
+++ b/src/editor/icons/compall.png
Binary files differ
diff --git a/src/editor/icons/compall16.png b/src/editor/icons/compall16.png
new file mode 100644
index 0000000..1e6fd39
--- /dev/null
+++ b/src/editor/icons/compall16.png
Binary files differ
diff --git a/src/editor/icons/debug.png b/src/editor/icons/debug.png
new file mode 100644
index 0000000..d1859e3
--- /dev/null
+++ b/src/editor/icons/debug.png
Binary files differ
diff --git a/src/editor/icons/debug16.png b/src/editor/icons/debug16.png
new file mode 100644
index 0000000..f11270b
--- /dev/null
+++ b/src/editor/icons/debug16.png
Binary files differ
diff --git a/src/editor/lightproof_editor/General.xba b/src/editor/lightproof_editor/General.xba
new file mode 100644
index 0000000..3dc048e
--- /dev/null
+++ b/src/editor/lightproof_editor/General.xba
@@ -0,0 +1,153 @@
+<?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="General" script:language="StarBasic">&apos; László Németh (c) 2012, License: MPL/LGPL/GPL
+
+Sub Compile()
+ Update(False)
+End Sub
+
+Sub CompileAll()
+ Update(True)
+End Sub
+
+Sub Update(all)
+ c = ThisComponent.CurrentController.getViewCursor()
+ Dim prop
+ prop = ThisComponent.getDocumentProperties()
+ locale = ThisComponent.StyleFamilies.getByName(&quot;ParagraphStyles&quot;).getByName(&quot;Standard&quot;).CharLocale
+ Dim values(1) As New com.sun.star.beans.PropertyValue
+ rules = ThisComponent.Text.getString()
+ if InStr(rules, &quot;→&quot;) Then Replace(&quot;→&quot;, &quot;-&gt;&quot;)
+ if InStr(rules, &quot;←&quot;) Then Replace(&quot;←&quot;, &quot;&lt;-&quot;)
+ rules = ThisComponent.Text.getString()
+ if all Then Replace(&quot;\&lt;option\([^)]*\)&quot;, &quot;True&quot;)
+ values(0).Name = &quot;Update&quot;
+ values(0).Value = ThisComponent.Text.getString()
+ &apos;spellchecker = createUnoService(&quot;com.sun.star.linguistic2.SpellChecker&quot;)
+ proofreader = createUnoService(&quot;org.openoffice.comp.pyuno.Lightproof.lightproof_editor&quot;)
+ result = proofreader.doProofreading(0, rules, locale, 0, len(rules), values())
+ ThisComponent.Text.setString(rules)
+ SetStyle()
+ Replace(&quot;\n&quot;, &quot;\n&quot;) &apos; convert new lines to paragraph breaks
+ If result.aText &lt;&gt; &quot;&quot; Then
+ If result.aText &lt;&gt; rules Then
+ MsgBox result.aText + &quot; in line &quot; + result.nStartOfSentencePosition
+ SetLine(result.nStartOfSentencePosition)
+ End If
+ End If
+End Sub
+
+Sub Debug()
+ c = ThisComponent.CurrentController.getViewCursor()
+ Dim prop
+ prop = ThisComponent.getDocumentProperties()
+ locale = ThisComponent.StyleFamilies.getByName(&quot;ParagraphStyles&quot;).getByName(&quot;Standard&quot;).CharLocale
+ Dim values(1) As New com.sun.star.beans.PropertyValue
+ rules = ThisComponent.Text.getString()
+ &apos;if InStr(rules, &quot;→&quot;) Then Replace(&quot;→&quot;, &quot;-&gt;&quot;)
+ &apos;if InStr(rules, &quot;←&quot;) Then Replace(&quot;←&quot;, &quot;&lt;-&quot;)
+ &apos;if all Then Replace(&quot;\&lt;option\([^)]*\)&quot;, &quot;True&quot;)
+ values(0).Name = &quot;Debug&quot;
+ values(0).Value = ThisComponent.Text.getString()
+ &apos;spellchecker = createUnoService(&quot;com.sun.star.linguistic2.SpellChecker&quot;)
+ proofreader = createUnoService(&quot;org.openoffice.comp.pyuno.Lightproof.lightproof_editor&quot;)
+ result = proofreader.doProofreading(0, rules, locale, 0, len(rules), values())
+ ThisComponent.Text.setString(rules)
+ SetStyle()
+ Replace(&quot;\n&quot;, &quot;\n&quot;) &apos; convert new lines to paragraph breaks
+ If result.aText &lt;&gt; &quot;&quot; Then
+ If result.aText &lt;&gt; rules Then
+ MsgBox result.aText + &quot; in line &quot; + result.nStartOfSentencePosition
+ SetLine(result.nStartOfSentencePosition)
+ Else
+ MsgBox &quot;Ok&quot;
+ End If
+ End If
+End Sub
+
+
+
+Sub SetStyle()
+ target = ThisComponent.StyleFamilies.getByName(&quot;ParagraphStyles&quot;).getByName(&quot;Standard&quot;)
+ source = ThisComponent.StyleFamilies.getByName(&quot;ParagraphStyles&quot;).getByName(&quot;Preformatted Text&quot;)
+ if target.CharFontName &lt;&gt; source.CharFontName or target.CharHeight &lt;&gt; source.CharHeight then
+ target.CharFontName = source.CharFontName
+ target.CharHeight = source.CharHeight
+ end if
+End Sub
+
+Sub SetLine(n)
+&apos; MsgBox &quot;hello&quot;
+ c = ThisComponent.Text.createTextCursor()
+&apos; c = ThisComponent.CurrentController.getViewCursor
+ c.GoToStart(False)
+ For i = 2 to n
+ c.gotoNextParagraph(False)
+&apos; c.gotoEndOfLine(False)
+&apos; c.goRight(1, False)
+&apos; c.setString(&quot;M&quot;)
+&apos; MsgBox c.getString()
+ Next
+ ThisComponent.CurrentController.getViewCursor.gotoRange(c, False)
+End Sub
+
+
+sub Replace(s, s2)
+rem ----------------------------------------------------------------------
+rem define variables
+dim document as object
+dim dispatcher as object
+rem ----------------------------------------------------------------------
+rem get access to the document
+document = ThisComponent.CurrentController.Frame
+dispatcher = createUnoService(&quot;com.sun.star.frame.DispatchHelper&quot;)
+
+rem ----------------------------------------------------------------------
+dispatcher.executeDispatch(document, &quot;.uno:GoToStartOfDoc&quot;, &quot;&quot;, 0, Array())
+
+rem ----------------------------------------------------------------------
+dim args2(18) as new com.sun.star.beans.PropertyValue
+args2(0).Name = &quot;SearchItem.StyleFamily&quot;
+args2(0).Value = 2
+args2(1).Name = &quot;SearchItem.CellType&quot;
+args2(1).Value = 0
+args2(2).Name = &quot;SearchItem.RowDirection&quot;
+args2(2).Value = true
+args2(3).Name = &quot;SearchItem.AllTables&quot;
+args2(3).Value = false
+args2(4).Name = &quot;SearchItem.Backward&quot;
+args2(4).Value = false
+args2(5).Name = &quot;SearchItem.Pattern&quot;
+args2(5).Value = false
+args2(6).Name = &quot;SearchItem.Content&quot;
+args2(6).Value = false
+args2(7).Name = &quot;SearchItem.AsianOptions&quot;
+args2(7).Value = false
+args2(8).Name = &quot;SearchItem.AlgorithmType&quot;
+args2(8).Value = 1
+args2(9).Name = &quot;SearchItem.SearchFlags&quot;
+args2(9).Value = 65536
+args2(10).Name = &quot;SearchItem.SearchString&quot;
+args2(10).Value = s
+args2(11).Name = &quot;SearchItem.ReplaceString&quot;
+args2(11).Value = s2
+args2(12).Name = &quot;SearchItem.Locale&quot;
+args2(12).Value = 255
+args2(13).Name = &quot;SearchItem.ChangedChars&quot;
+args2(13).Value = 2
+args2(14).Name = &quot;SearchItem.DeletedChars&quot;
+args2(14).Value = 2
+args2(15).Name = &quot;SearchItem.InsertedChars&quot;
+args2(15).Value = 2
+args2(16).Name = &quot;SearchItem.TransliterateFlags&quot;
+args2(16).Value = 1280
+args2(17).Name = &quot;SearchItem.Command&quot;
+args2(17).Value = 3
+args2(18).Name = &quot;Quiet&quot;
+args2(18).Value = true
+
+dispatcher.executeDispatch(document, &quot;.uno:ExecuteSearch&quot;, &quot;&quot;, 0, args2())
+
+
+end sub
+</script:module> \ No newline at end of file
diff --git a/src/editor/lightproof_editor/RegisteredFlag b/src/editor/lightproof_editor/RegisteredFlag
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/editor/lightproof_editor/RegisteredFlag
diff --git a/src/editor/lightproof_editor/dialog.xlb b/src/editor/lightproof_editor/dialog.xlb
new file mode 100644
index 0000000..1fe87d3
--- /dev/null
+++ b/src/editor/lightproof_editor/dialog.xlb
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd">
+<library:library xmlns:library="http://openoffice.org/2000/library" library:name="lightproof_editor" library:readonly="false" library:passwordprotected="false">
+</library:library> \ No newline at end of file
diff --git a/src/editor/lightproof_editor/script.xlb b/src/editor/lightproof_editor/script.xlb
new file mode 100644
index 0000000..68e8364
--- /dev/null
+++ b/src/editor/lightproof_editor/script.xlb
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd">
+<library:library xmlns:library="http://openoffice.org/2000/library" library:name="lightproof_editor" library:readonly="false" library:passwordprotected="false">
+ <library:element library:name="General"/>
+</library:library> \ No newline at end of file
diff --git a/src/en/README_lightproof_en.txt b/src/en/README_lightproof_en.txt
new file mode 100644
index 0000000..43c91fe
--- /dev/null
+++ b/src/en/README_lightproof_en.txt
@@ -0,0 +1,3 @@
+English sentence checker for LibreOffice
+see git://anongit.freedesktop.org/libreoffice/lightproof
+2011-2012 (c) László Németh, license: MPL 1.1 / GPLv3+ / LGPLv3+
diff --git a/src/en/en.cfg b/src/en/en.cfg
new file mode 100644
index 0000000..0844e90
--- /dev/null
+++ b/src/en/en.cfg
@@ -0,0 +1,13 @@
+[args]
+lang = en
+locales = en_GB en_US en_PH en_ZA en_NA en_ZW en_AU en_CA en_IE en_IN en_BZ en_BS en_GH en_JM en_NZ en_TT
+name = Lightproof grammar checker (English)
+version = 0.4.2
+author = László Németh
+provider = LibreOffice
+implname = lightproof_en
+link = http://www.libreoffice.org
+description = English grammar checker for LibreOffice
+extras = README_lightproof_en.txt
+# logo =
+# sourcefiles = \ No newline at end of file
diff --git a/src/en/en.dat b/src/en/en.dat
new file mode 100644
index 0000000..dd8ec6a
--- /dev/null
+++ b/src/en/en.dat
@@ -0,0 +1,382 @@
+# English sentence checking
+
+# word-level rules (case-sensitive)
+
+[word]
+
+# basic syntax of the rules:
+#
+# pattern -> suggestion # warning message
+# pattern <- condition -> suggestion # warning message
+#
+
+# duplicates
+
+and and -> and # Did you mean:
+or or -> or # Did you mean:
+for for -> for # Did you mean:
+the the -> the # Did you mean:
+
+# word-level rules (case-insensitive)
+
+[Word]
+
+# multiword expressions
+
+ying and yang -> yin and yang # Did you mean:
+
+# multiple suggestions separated by "\n"
+
+scot free -> scot-free\nscotfree # Did you mean:
+
+# possessive pronouns
+
+# Your's -> Yours
+(your|her|our|their)['’]s -> \1s # Possessive pronoun: \n http://en.wikipedia.org/wiki/Possessive_pronoun
+
+# a or an (rules for articles)#
+###############################
+
+[word]
+
+# pattern "a" matches "a" or "A":
+a [Aa]
+
+# pattern "_" matches space and optional quotation marks:
+_ [ ]['‘"“]?
+
+# pattern "vow" matches words beginning with vowels:
+vow [aeiouAEIOU]\w*
+
+# pattern "con" matches words beginning with consonants:
+con [bcdfghj-np-tv-zBCDFGHJ-NP-TV-Z]\w*
+
+# pattern "etc" matches other word parts separated by hyphen, endash or apostrophes:
+etc [-–'’\w]*
+
+# rules ("aA", "aAN", "aB" sets are defined at the end of the file)
+
+{a}n{_}{vow}{etc} <- {vow} in aA or {vow}.lower() in aA -> {a}{_}{vow}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an
+
+a{_}{vow}{etc} <- ({vow} <> {vow}.upper()) and not ({vow} in aA or
+ {vow}.lower() in aA) and spell({vow}) -> an{_}{vow}{etc} # Bad article? \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an
+
+a{_}{con}{etc} <- {con} in aAN or {con}.lower() in aAN -> an{_}{con}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an
+
+{a}n{_}{con}{etc} <- ({con} <> {con}.upper()) and not ({con} in aA or
+ {con}.lower() in aAN) and not {con} in aB and spell({con}) -> {a}{_}{con}{etc} # Bad article? \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an
+
+# rules for sentences beginning with "A"
+
+^A{_}{vow}{etc} <- ({vow} <> {vow}.upper()) and not ({vow} in aA or
+ {vow}.lower() in aA) and spell({vow}) -> An{_}{vow}{etc} # Bad article? \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an
+
+^A{_}{con}{etc} <- {con} in aAN or {con}.lower() in aAN -> An{_}{con}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an
+
+# check numbers
+
+nvow (8[0-9]*|1[18](000)*)(th)? # 8, 8th, 11, 11th, 18, 18th, 11000, 11000th...
+
+a{_}{nvow}{etc} -> an{_}{nvow}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an
+^A{_}{nvow}{etc} -> An{_}{nvow}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an
+
+ncon [0-79][0-9]*
+
+{a}n{_}{ncon}{etc} <- not {ncon}[:2] in ["11", "18"] -> {a}{_}{ncon}{etc} # Did you mean: \n http://en.wikipedia.org/wiki/English_articles#Discrimination_between_a_and_an
+
+# paragraph capitalization
+
+[code]
+# pattern matching for common English abbreviations
+abbrev = re.compile("(?i)\b([a-z]|acct|approx|appt|apr|apt|assoc|asst|aug|ave|avg|co(nt|rp)?|ct|dec|defn|dept|dr|eg|equip|esp|est|etc|excl|ext|feb|fri|ft|govt?|hrs?|ib(id)?|ie|in(c|t)?|jan|jr|jul|lit|ln|mar|max|mi(n|sc)?|mon|Mrs?|mun|natl?|neg?|no(rm|s|v)?|nw|obj|oct|org|orig|pl|pos|prev|proj|psi|qty|rd|rec|rel|reqd?|resp|rev|sat|sci|se(p|pt)?|spec(if)?|sq|sr|st|subj|sun|sw|temp|thurs|tot|tues|univ|var|vs)\.")
+
+# pattern for paragraph checking
+paralcap = re.compile(u"(?u)^[a-z].*[.?!] [A-Z].*[.?!][)”]?$")
+
+[word]
+
+# condition: the paragraph begins with a lowercase letter and it contains real sentence boundaries.
+
+low [a-z]+
+
+(^){low} <- paralcap.search(TEXT) and not abbrev.search(TEXT) -> = {low}.capitalize() # Missing capitalization?
+
+# optional sentence capitalization
+
+^{low} <- option("cap") and not abbrev.search(TEXT) -> = {low}.capitalize() # Missing capitalization?
+
+# punctuation
+
+[code]
+
+punct = { "?": "question mark", "!": "exclamation mark",
+ ",": "comma", ":": "colon", ";": "semicolon",
+ "(": "opening parenthesis", ")": "closing parenthesis",
+ "[": "opening square bracket", "]": "closing square bracket",
+ u"“": "opening quotation mark", u"”": "closing quotation mark"}
+
+[char]
+
+" ([.?!,:;)”\]])\b" -> "\1 " # Reversed space and punctuation?
+" +[.]" <- LOCALE.Country == "US" -> . # Extra space before the period?
+" +[.]" <- LOCALE.Country != "US" -> . # Extra space before the full stop?
+" +([?!,:;)”\]])" -> \1 # = "Extra space before the " + punct[\1] + "?"
+"([([“]) " -> \1 # = "Extra space after the " + punct[\1] + "?"
+
+# ( item ) -> (item)
+# A small - but important - example. -> A small – but important – example.
+
+# En dash and em dash
+
+\b(---?| --? )\b <- not option("ndash") and not option("mdash") -> " – \n—" # En dash or em dash:
+\b(---?| --? |—)\b <- option("ndash") and not option("mdash") -> " – " # En dash:
+\b(---?| --? | – )\b <- option("mdash") -> — # Em dash:
+
+# multiplication sign
+
+number \d+([.]\d+)?
+
+{number}(x| x ){number} <- option("times") -> {number}×{number} # Multiplication sign. \n http://en.wikipedia.org/wiki/Multiplication_sign
+# 800x600 -> 800×600
+
+# missing space
+
+abc [a-z]+
+ABC [A-Z]+
+Abc [a-zA-Z]+
+pun [?!,:;%‰‱˚“”‘]
+
+{Abc}{pun}{Abc} -> {Abc}{pun} {Abc} # Missing space?
+{abc}[.]{ABC} -> {abc}. {ABC} # Missing space?
+# missing,space -> missing, space
+# missing.Space -> missing. Space
+
+[)] <- option("pair") and not "(" in TEXT -> # Extra closing parenthesis?
+[(] <- option("pair") and TEXT[-1] in u"?!;:”’" and not ")" in TEXT -> # Extra opening parenthesis?
+(?<![0-9])” <- option("pair") and not u"“" in TEXT -> # Extra quotation mark?
+(?<=[0-9])” <- option("apostrophe") and not u"“" in TEXT -> ″\n # Bad double prime or extra quotation mark?
+“ <- option("pair") and TEXT[-1] in u"?!;:”’" and not u"”" in TEXT -> # Extra quotation mark?
+
+"[.]{3}" <- option("ellipsis") -> "…" # Ellipsis.
+
+\b {2,3}(\b|$) <- option("spaces") -> "\1 " # Extra space.
+# Extra space -> Extra space
+# End... -> End…
+
+(^|\b|{pun}|[.]) {2,3}(\b|$) <- option("spaces2") -> "\1 " # Extra space.
+# Extra space -> Extra space
+# End... -> End…
+
+(^|\b|{pun}|[.]) {4,}(\b|$) <- option("spaces3") -> "\1 \n " # Change multiple spaces to a single space or a tabulator:
+
+# quotation
+
+# Using typographic quotation marks is the
+
+(?i)[\"“”‟„]({abc}[^\"“”‟„]*)[\"“‟] <- option("quotation") -> “\1” # Quotation marks.
+(?i)[\"”‟„]({abc}[^\"“”‟„]*)[\"“”‟] <- option("quotation") -> “\1” # Quotation marks.
+
+(?i)'{abc}' <- option("apostrophe") -> ‘{abc}’ # Quotation marks.
+(?i)[\"”‟„]({abc}[^\"“”‟„]*)[\"“”‟] <- option("apostrophe") -> “\1” # Quotation marks.
+
+# apostrophe
+
+w \w*
+(?i){Abc}'{w} <- option("apostrophe") -> {Abc}’{w} # Replace typewriter apostrophe or quotation mark:
+# o'clock -> o’clock
+# singers' voices -> singers’ voices
+
+(?<= )'{Abc} <- option("apostrophe") -> ‘{Abc}\n’{Abc} # Replace typewriter quotation mark or apostrophe:
+^'{Abc} <- option("apostrophe") -> ‘{Abc}\n’{Abc} # Replace typewriter quotation mark or apostrophe:
+
+# formats
+
+# Thousand separators: 10000 -> 10,000 (common) or 10 000 (ISO standard)
+
+# definitions
+d \d\d\d # name definition: 3 digits
+d2 \d\d # 2 digits
+D \d{1,3} # 1, 2 or 3 digits
+
+# ISO thousand separators: space, here: narrow no-break space (U+202F)
+\b{d2}{d}\b <- option("numsep") -> {d2},{d}\n{d2} {d} # Use thousand separator (common or ISO).
+\b{D}{d}{d}\b <- option("numsep") -> {D},{d},{d}\n{D} {d} {d} # Use thousand separators (common or ISO).
+\b{D}{d}{d}{d}\b <- option("numsep") -> {D},{d},{d},{d}\n{D} {d} {d} {d} # Use thousand separators (common or ISO).
+# 1234567890 -> 1,234,567,890\n1 234 567 890
+
+# word duplication
+
+[word]
+
+{Abc} \1 <- option("dup") -> {Abc} # Word duplication?
+
+# Optional grammar checking
+
+([Tt])his {abc} <- option("grammar") and morph({abc}, "Ns") -> \1hese {abc}\n\1his, {abc} # Did you mean:
+
+with it['’]s <- option("grammar") -> with its\nwith, it’s # Did you mean:
+
+[Word]
+
+(it|s?he) don['’]t <- option("grammar") -> \1 doesn’t # Did you mean:
+
+################### measurements ##########################
+
+[word]
+
+# Temperature
+
+([-−]?\d+(?:[,.]\d+)*) (°F|Fahrenheit) <- option("metric") -> = measurement(\1, "F", "C", u" °C", ".", ",") # Convert to Celsius:
+([-−]?\d+(?:[,.]\d+)*) (°C|Celsius) <- option("nonmetric") -> = measurement(\1, "C", "F", u" °F", ".", ",") # Convert to Fahrenheit:
+
+# Length
+
+([-−]?\d+(?:[,.]\d+)*(?: 1/2| ?½)?) (ft|foot|feet)(?! [1-9]) <- option("metric") -> =
+ measurement(\1, "ft", "cm", " cm", ".", ",") + "\n" +
+ measurement(\1, "ft", "m", " m", ".", ",") # Convert to metric:
+
+([-−]?\d+(?:[,.]\d+)*(?: 1/2| ?½)?) ft[.]? ([0-9]+(?: 1/2| ?½)?) in <- option("metric") -> =
+ measurement(\1 + "*12+" + \2, "in", "cm", " cm", ".", ",") + "\n" +
+ measurement(\1 + "*12+" + \2, "in", "m", " m", ".", ",") # Convert to metric:
+
+([-−]?\d+(?:[,.]\d+)*(?: 1/2| ?½)?) in <- option("metric") -> =
+ measurement(\1, "in", "mm", " mm", ".", ",") + "\n" +
+ measurement(\1, "in", "cm", " cm", ".", ",") + "\n" +
+ measurement(\1, "in", "m", " m", ".", ",") # Convert to metric:
+
+([-−]?\d+(?:[,.]\d+)*) mm <- option("nonmetric") -> =
+ measurement(\1, "mm", "in", " in", ".", ",") # Convert from metric:
+
+([-−]?\d+(?:[,.]\d+)*) cm <- option("nonmetric") -> =
+ measurement(\1, "cm", "in", " in", ".", ",") + "\n" +
+ measurement(\1, "cm", "ft", " ft", ".", ",") # Convert from metric:
+
+([-−]?\d+(?:[,.]\d+)*) (m|meter|metre) <- option("nonmetric") -> =
+ measurement(\1, "m", "in", " in", ".", ",") + "\n" +
+ measurement(\1, "m", "ft", " ft", ".", ",") + "\n" +
+ measurement(\1, "m", "mi", " mi", ".", ",") # Convert from metric:
+
+([-−]?\d+(?:[,.]\d+)*(?: 1/2| ?½)?) miles? <- option("metric") -> =
+ measurement(\1, "mi", "m", " m", ".", ",") + "\n" +
+ measurement(\1, "mi", "km", " km", ".", ",") # Convert to metric:
+
+([-−]?\d+(?:[,.]\d+)*) km <- option("nonmetric") -> =
+ measurement(\1, "km", "mi", " mi", ".", ",") # Convert to miles:
+
+([-−]?\d+(?:,\d+)?) (yd|yards?) <- option("metric") -> = measurement(\1, "yd", "m", " m", ".", ",") # Convert to metric:
+
+# Volume
+
+([-−]?\d+(?:,\d+)?) (gal(lons?)?) <- option("metric") -> =
+ measurement(\1, "gal", "l", " l", ".", ",") + "\n" +
+ measurement(\1, "uk_gal", "l", " l (in UK)", ".", ",") # Convert to metric:
+
+([-−]?\d+(?:,\d+)?) (pint) <- option("metric") -> =
+ measurement(\1, "pt", "dl", " dl", ".", ",") + "\n" +
+ measurement(\1, "uk_pt", "dl", " dl (in UK)", ".", ",") + "\n" +
+ measurement(\1, "pt", "l", " l", ".", ",") + "\n" +
+ measurement(\1, "uk_pt", "l", " l (in UK)", ".", ",") # Convert to metric:
+
+([-−]?\d+(?:,\d+)?) (l|L|litres?|liters?) <- option("nonmetric") -> =
+ measurement(\1, "l", "gal", " gal", ".", ",") + "\n" +
+ measurement(\1, "l", "gal", " gal (in UK)", ".", ",") # Convert to gallons:
+
+# Weight
+
+([-−]?\d+(?:[,.]\d+)*) lbs?[.]? <- option("metric") -> =
+ measurement(\1, "lbm", "kg", " kg", ".", ",") # Convert to metric:
+([-−]?\d+(?:[,.]\d+)*) kg[.]? <- option("nonmetric") -> =
+ measurement(\1, "kg", "lbm", " lb", ".", ",") # Convert to pounds:
+
+# Speed
+
+([-−]?\d+(?:[,.]\d+)*) mph <- option("metric") -> = measurement(\1, "mph", "km/h", " km/h", ".", ",") # Convert to km/hour:
+([-−]?\d+(?:[,.]\d+)*) km/h <- option("nonmetric") -> = measurement(\1, "km/h", "mph", " mph", ".", ",") # Convert to miles/hour:
+
+[code]
+
+aA = set(["eucalypti", "eucalyptus", "Eucharist", "Eucharistic",
+"euchre", "euchred", "euchring", "Euclid", "euclidean", "Eudora",
+"eugene", "Eugenia", "eugenic", "eugenically", "eugenicist",
+"eugenicists", "eugenics", "Eugenio", "eukaryote", "Eula", "eulogies",
+"eulogist", "eulogists", "eulogistic", "eulogized", "eulogizer",
+"eulogizers", "eulogizing", "eulogy", "eulogies", "Eunice", "eunuch",
+"eunuchs", "Euphemia", "euphemism", "euphemisms", "euphemist",
+"euphemists", "euphemistic", "euphemistically", "euphonious",
+"euphoniously", "euphonium", "euphony", "euphoria", "euphoric",
+"Euphrates", "euphuism", "Eurasia", "Eurasian", "Eurasians", "eureka",
+"eurekas", "eurhythmic", "eurhythmy", "Euridyce", "Euripides", "euripus",
+"Euro", "Eurocentric", "Euroclydon", "Eurocommunism", "Eurocrat",
+"eurodollar", "Eurodollar", "Eurodollars", "Euromarket", "Europa",
+"Europe", "European", "Europeanisation", "Europeanise", "Europeanised",
+"Europeanization", "Europeanize", "Europeanized", "Europeans", "europium",
+"Eurovision", "Eustace", "Eustachian", "Eustacia", "euthanasia",
+"Ewart", "ewe", "Ewell", "ewer", "ewers", "Ewing", "once", "one",
+"oneness", "ones", "oneself", "onetime", "oneway", "oneyear", "u",
+"U", "UART", "ubiquitous", "ubiquity", "Udale", "Udall", "UEFA",
+"Uganda", "Ugandan", "ugric", "UK", "ukase", "Ukraine", "Ukrainian",
+"Ukrainians", "ukulele", "Ula", "ululated", "ululation", "Ulysses",
+"UN", "unanimity", "unanimous", "unanimously", "unary", "Unesco",
+"UNESCO", "UNHCR", "uni", "unicameral", "unicameralism", "Unicef",
+"UNICEF", "unicellular", "Unicode", "unicorn", "unicorns", "unicycle",
+"unicyclist", "unicyclists", "unidimensional", "unidirectional",
+"unidirectionality", "unifiable", "unification", "unified", "unifier",
+"unifilar", "uniform", "uniformally", "uniformed", "uniformer",
+"uniforming", "uniformisation", "uniformise", "uniformitarian",
+"uniformitarianism", "uniformity", "uniformly", "uniformness", "uniforms",
+"unify", "unifying", "unijugate", "unilateral", "unilateralisation",
+"unilateralise", "unilateralism", "unilateralist", "unilaterally",
+"unilinear", "unilingual", "uniliteral", "uniliteralism", "uniliteralist",
+"unimodal", "union", "unionism", "unionist", "unionists", "unionisation",
+"unionise", "unionised", "unionising", "unionization", "unionize",
+"unionized", "unionizing", "unions", "unipolar", "uniprocessor",
+"unique", "uniquely", "uniqueness", "uniquer", "Uniroyal", "unisex",
+"unison", "Unisys", "unit", "Unitarian", "Unitarianism", "Unitarians",
+"unitary", "unite", "united", "unitedly", "uniter", "unites", "uniting",
+"unitize", "unitizing", "unitless", "units", "unity", "univ", "Univac",
+"univalent", "univalve", "univariate", "universal", "universalisation",
+"universalise", "universalised", "universaliser", "universalisers",
+"universalising", "universalism", "universalist", "universalistic",
+"universality", "universalisation", "universalization", "universalize",
+"universalized", "universalizer", "universalizers", "universalizing",
+"universally", "universalness", "universe", "universes", "universities",
+"university", "univocal", "Unix", "uracil", "Urals", "uranium", "Uranus",
+"uranyl", "urate", "urea", "uremia", "uremic", "ureter", "urethane",
+"urethra", "urethral", "urethritis", "Urey", "Uri", "uric", "urinal",
+"urinalysis", "urinary", "urinated", "urinating", "urination", "urine",
+"urogenital", "urokinase", "urologist", "urologists", "urology",
+"Uruguay", "Uruguayan", "Uruguayans", "US", "USA", "usable", "usage",
+"usages", "use", "used", "useful", "usefulness", "usefully", "useless",
+"uselessly", "uselessness", "Usenet", "user", "users", "uses", "using",
+"usual", "usually", "usurer", "usurers", "usuress", "usurial", "usurious",
+"usurp", "usurpation", "usurped", "usurper", "usurping", "usurps",
+"usury", "Utah", "utensil", "utensils", "uterine", "uterus", "Utica",
+"utilitarian", "utilitarianism", "utilities", "utility", "utilizable",
+"utilization", "utilize", "utilized", "utilizes", "utilizing", "utopia",
+"utopian", "utopians", "utopias", "Utrecht", "Uttoxeter", "uvula",
+"uvular"])
+
+aAN = set(["f", "F", "FBI", "FDA", "heir", "heirdom", "heired",
+"heirer", "heiress", "heiring", "heirloom", "heirship", "honest",
+"honester", "honestly", "honesty", "honor", "honorable", "honorableness",
+"honorably", "honorarium", "honorary", "honored", "honorer", "honorific",
+"honoring", "honors", "honour", "honourable", "honourableness",
+"honourably", "honourarium", "honourary", "honoured", "honourer",
+"honourific", "honouring", "Honours", "hors", "hour", "hourglass", "hourlong",
+"hourly", "hours", "l", "L", "LCD", "m", "M", "MBA", "MP", "mpg", "mph",
+"MRI", "MSc", "MTV", "n", "N", "NBA", "NBC", "NFL", "NGO", "NHL", "r",
+"R", "s", "S", "SMS", "sos", "SOS", "SPF", "std", "STD", "SUV", "x",
+"X", "XML"])
+
+aB = set(["H", "hallucination", "haute", "hauteur", "herb", "herbaceous", "herbal",
+"herbalist", "herbalism", "heroic", "hilarious", "historian", "historic", "historical",
+"homage", "homophone", "horrendous", "hospitable", "horrific", "hotel", "hypothesis", "Xmas"])
+
+def measurement(mnum, min, mout, mstr, decimal, remove):
+ if min == "ft" or min == "in" or min == "mi":
+ mnum = mnum.replace(" 1/2", ".5").replace(u" ½", ".5").replace(u"½",".5")
+ m = calc("CONVERT_ADD", (float(eval(mnum.replace(remove, "").replace(decimal, ".").replace(u"−", "-"))), min, mout))
+ a = list(set([str(calc("ROUND", (m, 0)))[:-2], str(calc("ROUND", (m, 1))), str(calc("ROUND", (m, 2))), str(m)])) # remove duplicated rounded items
+ a.sort(lambda x, y: len(x) - len(y)) # sort by string length
+ return join(a, mstr + "\n").replace(".", decimal).replace("-", u"−") + mstr
+
diff --git a/src/en/en.dlg b/src/en/en.dlg
new file mode 100644
index 0000000..ca35c61
--- /dev/null
+++ b/src/en/en.dlg
@@ -0,0 +1,53 @@
+# Options and title texts for the Settings and conditional rules
+#
+# THe dialog windows contain only grouped checkboxes.
+#
+# Format of the dialog definition:
+#
+# GroupID: OptionID, OptionID ...
+# Group2ID: OptionID, OptionID ...
+# ...
+# [Language_code=[title of the node/]title of the window]
+# OptionID=title of the option
+# Option2ID=title of the option
+#
+# The first language is the default language for other locales
+# (use en_US or the common language of your country)
+#
+# The OptionIDs declared here are used in the rules, too. For example:
+#
+# foo <- option("style") -> bar # bar is far better
+#
+# this rule depends from the state of the "style" checkbox.
+
+# options (starred options are checked)
+
+spelling: grammar cap dup pair
+punctuation: *spaces mdash quotation *times, spaces2 ndash apostrophe ellipsis, spaces3 minus - -
+others: metric numsep, nonmetric
+
+# titles
+
+[en_US=English sentence checking]
+
+spelling=Grammar checking
+grammar=Possible mistakes \n Check more grammar errors.
+cap=Capitalization \n Check missing capitalization of sentences.
+dup=Word duplication \n Check repeated words.
+pair=Parentheses \n Check missing or extra parentheses and quotation marks.
+punctuation=Punctuation
+spaces=Word spacing\nCheck single spaces between words.
+mdash=Em dash\nForce unspaced em dash instead of spaced en dash.
+ndash=En dash\nForce spaced en dash instead of unspaced em dash.
+quotation=Quotation marks\nCheck double quotation marks: "x" → “x”
+times=Multiplication sign\nCheck true multipliction sign: 5x5 → 5×5
+spaces2=Sentence spacing\nCheck single spaces between sentences.
+spaces3=More spaces\nCheck more than two extra space characters between words and sentences.
+minus=Minus sign\nChange hyphen characters to real minus signs.
+apostrophe=Apostrophe\nChange typewriter apostrophe, single quotation marks and correct double primes.
+ellipsis=Ellipsis\nChange three dots with ellipsis.
+others=Others
+metric=Convert to metric (°C, km/h, m, kg, l)\nMeasurement conversion from °F, mph, ft, in, lb, gal and miles.
+numsep=Thousand separation of large numbers\nCommon (1000000 → 1,000,000) or ISO (1000000 → 1 000 000).
+nonmetric=Convert to non-metric (°F, mph, ft, lb, gal)\nMeasurement conversion from °C; km/h; cm, m, km; kg; l.
+
diff --git a/src/hu_HU/ChangeLog b/src/hu_HU/ChangeLog
new file mode 100644
index 0000000..a546f1a
--- /dev/null
+++ b/src/hu_HU/ChangeLog
@@ -0,0 +1,124 @@
+2012-02-02 László Németh <nemeth@numbertext.org>:
+- rövidebb magyarázat a „több mint” esetén + URL
+- "-szám" alakoknál nem feltételez kötőjeles felsorolást
+
+2011-12-16 László Németh <nemeth@numbertext.org>:
+- beállítások csak a kiterjesztéskezelőben hozzáférhetők ideiglenesen
+
+- webes bővebb magyarázatok támogatása (FullCommentURL) a LibO 3.5-ben,
+ pl. Fertő-tavi -> AkH. a Wikipédiában.
+
+- új opciók:
+ - nagy kezdőbetű: mondatok kis kezdőbetűjének keresése
+ - zárójelpárok és idézőjelek ellenőrzése
+ - nem elválasztott szavak elválasztását kínálja fel (pl.
+ megint -> me-gint, meg-int)
+
+- új szabályok:
+ - időről-időre, egytől-egyig -> időről időre, egytől egyig
+ - földrajzi nevek (Dél-Ázsiai -> Dél-ázsiai, Árpád-híd -> Árpád híd stb.)
+ - 1-e -> 1-je
+ - egyel kevesebb/több -> eggyel
+ - előre hátra -> előre-hátra
+ - ex-alelnök -> exalelnök stb.
+ - "kell hogy" esetén nem erőlteti az esetenként hibás vesszőt
+
+- javított szabályok:
+ - a/az névelőt csak a helyesírási szótárban meglévő szavak előtt ellenőriz
+
+- új licenc: MPL/GPL/LGPL
+
+2011-07-11 László Németh <nemeth@numbertext.org>:
+
+- javított csomagnév (Magyar nyelvi ellenőrzés)
+
+- új opciók:
+ - három pont
+ - dupla szóköz, sok szóköz
+ - idézőjelek, nagykötőjel
+ - törtek, indexek
+ - mínuszjel
+ - szóismétlés (egymást közvetlenül követő szavak)
+ - mértékegységek
+
+- 2003. Március -> 2003. március: hónap neve kisbetűvel jelenik meg a javaslatban is
+- javaslat: a Unikum -> nagybetűvel jelenik meg, ahogy a szövegben szerepelt
+- 2005 március-júniusa már nem hibásnak jelezve
+- a Unicode, a Unix most már nem hibás a névelővel sem
+- illetve hogy, illetve ha vessző nélkül
+- áld meg, mond el -> áldd meg, mondd el, ha a felszólítás felismerhető (mondat,
+ tagmondathatár, esetleg "ne" szócskával bevezetve)
+- jó kedvel, rossz kedvel -> jó kedvvel, rossz kedvvel
+- halott róla, nem halottunk semmit -> hallott róla, nem hallottunk semmit
+- C-vitamin hiány -> C-vitamin-hiány
+- C-vitaminhiány -> C-vitamin-hiány (minden egybeírt összetételnél)
+- médiák, unszimpatikus kijelzése az opcionális stílusellenőrzésbe került
+- Budapest Liszt Ferenc Nemzetközi Repülőtér -> a többszörös helyesírási hiba kijelzése
+- felsorolások kötőjele, nagykötőjele aláhúzva egybeírás esetén: -Egy -> – Egy
+- 2011 július -> 2011. július (a július hiányzott az ellenőrzőtt hónapnevek közül)
+- kellet -> kellett (*nem kellet volna, *meg kellet ezt csinálnom, *várni is kellet
+- mértékegységek (mérföld, yard, láb, hüvelyk, °F, font súlyú, gallon, pint) átalakítása
+
+2010-05-06 László Németh <nemeth@openoffice.org>:
+ - alapértelmezett ezreselválasztó-ellenőrzés kikapcsolása (Magyar
+ Linux Libertine G Graphite automatikus ezreselválasztása miatt)
+
+2010-02-19 László Németh <nemeth@openoffice.org>:
+ * hu_HU.dat:
+ - "a" névelő + szám szabály javítása ("a 10")
+ a regex match hiányzó $ jelének pótlásával
+ - nem törő szóköz beillesztése a Celsius fok elé
+ - a törtekre és egyéb jelekre vonatkozó tipográfiai opció bekapcsolása
+ esetén nem törő szóköz helyett nem törő keskeny szóközt javasol a számok
+ ezrestagolójaként, és ezt felismeri a pénzegység
+ konzisztenciaellenőrzésénél is, valamint a régi nem törő szóközök
+ cseréjét is javasolja.
+ - Unicode vessző ékezet felvétele a valódi aposztrófot javasló szabályba
+ (U+00B4 kódja miatt elöl van, és emiatt tévedésből könnyen beilleszthető)
+ - idézőjeles szabályok bővítése:
+ - ASCII idézőjelek cseréje:
+ ,,valami >>volt<< ott.'' -> „valami »volt« ott.”
+ - felcserélt belső idézőjelek cseréje
+ - angolszász nem dupla idézőjelek cseréje
+ - számok konzisztencia-ellenőrzésénél nem törő szóközök helyes felismerése
+
+2010-02-12 László Németh <nemeth@openoffice.org>:
+ * hu_HU.dat:
+ - sorszámok névelőjének ellenőrzése ("az" esetén alapból még szükséges
+ az "oldal" stb. a sorszám után: pl. *"az 2. oldalon")
+
+ * lightproof_handler.py: segédosztály megszüntetése a Mac OS X PyUNO hiba
+ lehetséges okának kiküszöbölésére
+
+2010-02-09 László Németh <nemeth@openoffice.org>:
+ * hu_HU.dat:
+ - mínuszjel
+ - szorzásjel javítása szóközök esetén is: 5 x 6 -> 5×6
+ - hibás névelőjavaslat tiltása római számoknál (a II., a III. stb.)
+ - új feltételes szabályok: ligatúrák javaslata és elutasítása
+ - nem törő szóköz és toldalékolás esetén is javasolva van a százalékjel
+ tapadása;
+ - javaslat évszámok előtti aposztróf esetén is ('76-ban)
+ - pénznemek 1234,00 Ft és sima szóköz elfogadása, mint ezres tagoló
+ (nem törő szóköz már korábban így volt kezelve): 34 500 Ft
+ - fokjel javítása és egybeírása
+ - törtek (ha van csak Unicode karakterrel, pl. 1/2,
+ egyébként ha 1/x-ed, akkor "1/" Unicode karakterrel és alsó index
+ Unicode karakterrel, különben felső index, törtjel és alsó index
+ karakterekkel), indexek (H2O, H2SO4 stb.), fokok (Celsius, Fahrenheit
+ jele külön Unicode karakterrel (szebb tipográfiájú pl. a Linux Libertine
+ betűtípusban)
+
+ * hu_HU.dlg: új feltételes szabályok:
+ - ligatúrák javaslata és elutasítása
+ - törtek, indexek, fokok menüpont
+
+ - átcsoportosítás
+
+2009-12-16 László Németh <nemeth@openoffice.org>:
+ * hu_HU.dlg:
+ - Beállítások menü a magyar nyelvi ellenőrzéshez
+
+ * hu_HU.dat:
+ - opcionális szabályok: szóismétlés, képzett
+ összetett szavak, (tizedes)vesszők ellenőrzése, stb.
diff --git a/src/hu_HU/README_lightproof_hu_HU.txt b/src/hu_HU/README_lightproof_hu_HU.txt
new file mode 100644
index 0000000..6c9f4f8
--- /dev/null
+++ b/src/hu_HU/README_lightproof_hu_HU.txt
@@ -0,0 +1,3 @@
+Hungarian sentence checker for LibreOffice
+see git://anongit.freedesktop.org/libreoffice/lightproof
+2009-2012 (c) László Németh, license: MPL 1.1 / GPLv3+ / LGPLv3+
diff --git a/src/hu_HU/hu_HU.cfg b/src/hu_HU/hu_HU.cfg
new file mode 100644
index 0000000..3e8db39
--- /dev/null
+++ b/src/hu_HU/hu_HU.cfg
@@ -0,0 +1,10 @@
+[args]
+lang = hu_HU
+locales = hu_HU
+name = Lightproof grammar checker (magyar)
+version = 1.4.3
+author = László Németh
+provider = FSF.hu
+implname = lightproof_hu
+link = http://www.fsf.hu
+extras = README_lightproof_hu_HU.txt, ChangeLog
diff --git a/src/hu_HU/hu_HU.dat b/src/hu_HU/hu_HU.dat
new file mode 100644
index 0000000..cbc1a8c
--- /dev/null
+++ b/src/hu_HU/hu_HU.dat
@@ -0,0 +1,908 @@
+# magyar szabályok (írta: Németh László)
+
+###################### szóismétlés ###################
+
+a a -> a # Szóismétlés.
+és és -> és # Szóismétlés.
+
+############## hogy (l. még vesszőhasználat) #########
+
+hogy[ -]hogy nem -> hogyhogy nem/hogy, hogy nem # Hiányzó vessző vagy egybeírás
+hogy-hogy -> hogyhogy # Egybeírás.
+
+[char]
+
+# hogy előtt vessző (csak igékre és főnevekre, vessző ne kövesse, mint a hogy, hogy nemben
+([-\w]+) hogy\b(?![-]) <- word(1) and morph(\1, r"po:(vrb|noun)\b") and not \1 in [u"feltéve", "kell"] -> \1, hogy # Hiányzó vessző?
+
+[word]
+
+# még több vessző
+
+([-\w]+) hogy <- option("comma") and
+ not re.match(u"(feltéve|ahelyett|anélkül|aszerint|hogy)$", \1)
+ -> \1, hogy # Hiányzó vessző?
+
+# túl sok vessző
+([-\w]+), (ahelyett|anélkül|aszerint), hogy -> \1, \2 hogy\n\1 \2, hogy # Kötőszószerű kapcsolat esetén nem írunk a „hogy” elé vesszőt. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#243.
+([-\w]+), illetve, (ha|hogy) -> \1, illetve \2 # Kötőszószerű kapcsolat esetén nem írunk az „illetve” után vesszőt. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#243.
+
+###################### nagybetűsítés #################
+[code]
+
+abbrev=re.compile(ur"(?i)\b([a-zöüóőúéáűíÖÜÓŐÚÉÁŰÍ]|Áe|Áht|AkH|al|ált|ápr|aug|Avtv|bek|Bp|br|bt|Btk|cca|ci(i|ii|v|x)?|cl(i|ii|iii|iv|ix|v|vi|vii|viii|x|xi|xii|xiii|xiv|xix|xv|xvi|xvii|xviii|xx|xxi|xxii|xxiii|xxiv|xxix|xxv|xxvi|xxvii|xxviii|xxx|xxxi|xxxii|xxxiii|xxxiv|xxxix|xxxv|xxxvi|xxxvii|xxxviii)?|Co|cv(i|ii|iii)?|cx(c|ci|cii|ciii|civ|cix|cv|cvi|cvii|cviii|i|ii|iii|iv|ix|l|li|lii|liii|liv|lix|lv|lvi|lvii|lviii|v|vi|vii|viii|x|xi|xii|xiii|xiv|xix|xv|xvi|xvii|xviii|xx|xxi|xxii|xxiii|xxiv|xxix|xxv|xxvi|xxvii|xxviii)?|cs|Csjt|Cstv|csüt|dec|dk|dny|dr|du|dz(s)?|egy|ék|ÉKsz|em|ény|Épt|érk|etc|Etv|eü|ev|évf|febr|felv|Flt|ford|főisk|fsz(la|t)?|Ftv|gimn|gör|gr|Gt|gy|Gyvt|habil|hg|hiv|Hjt|honv|Hpt|hrsz|hsz|Hszt|htb|id|ifj|ig(h)?|ii(i)?|ill|Inc|ind|isk|iv|ix|izr|jan|jegyz|júl|jún|kat|kb|Kbt|ker|kft|kgy|kht|kir|kiv|Kjt|kk(t)?|koll|korm|köv|kp|Kr|krt|Kt(v)?|ld|li(i|ii|v|x)?|Ltd|ltp|Ltv|luth|lv(i|ii|iii)?|lx(i|ii|iii|iv|ix|v|vi|vii|viii|x|xi|xii|xiii|xiv|xix|xv|xvi|xvii|xviii|xx|xxi|xxii|xxiii|xxiv|xxix|xxv|xxvi|xxvii|xxviii)?|ly|máj|márc|mat|max|mb|megh|megj|MHSz|min|mk|Mo|Mt|NB|nov|ny(á)?|Nyilv|nyrt|okl|okt|olv|op|orsz|ort|ov(h)?|össz|Ötv|özv|Pf|pl(d)?|prof|prot|Ptk|pu|ref|rk(p)?|róm|röv|rt|sgt|spec|stb|sz(ept|erk)?|Szjt|szoc|Szt(v)?|szül|Tbj|tc|tel|tkp|tszf|tvr|ty|ua|ui|úm|ún|uo|Ve|Vhr|vi(i|ii)?|vö|vsz|Vt(v)?|xc(i|ii|iii|iv|ix|v|vi|vii|viii)?|xi(i|ii|v|x)?|xl(i|ii|iii|iv|ix|v|vi|vii|viii)?|xv(i|ii|iii)?|xx(i|ii|iii|iv|ix|v|vi|vii|viii|x|xi|xii|xiii|xiv|xix|xv|xvi|xvii|xviii)?|zrt)\.")
+
+# pattern for paragraph checking
+paralcap = re.compile(u"(?u)^[a-zöüóőúéáűí].*[.?!] [A-ZÖÜÓŐÚÉÁŰÍ].*[.?!][)”]?$")
+
+[word]
+
+low [a-zöüóőúéáűí]+
+
+^{low} <- paralcap.search(TEXT) and not abbrev.search(TEXT) -> = {low}.capitalize() # Hiányzó nagy kezdőbetű?
+
+# optional sentence capitalization
+
+^{low} <- option("cap") and not abbrev.search(TEXT) -> = {low}.capitalize() # Hiányzó nagy kezdőbetű?
+
+###################### központozás ###################
+
+[char]
+
+abc [a-zöüóűőúéáí]
+ABC [A-ZÖÜÓŰŐÚÉÁÍ]
+Abc {abc}|{ABC}
+abc [a-zöüóűőúéáíA-ZÖÜÓŰŐÚÉÁÍ]+
+word [a-záéíóöőúüűA-ZÉÍÓÖŐÚÜŰ]\w*
+
+punct [?!,:;%‰‱°„”]
+
+"^[-—] " <- option("dash") -> "– " # A gondolatjel nagykötőjel \n http://hu.wikipedia.org/wiki/Nagykötőjel
+" [-—]([ ,;])" <- option("dash") -> " –\1" # A gondolatjel nagykötőjel \n http://hu.wikipedia.org/wiki/Nagykötőjel
+# És - hogy is mondjam -, jó. -> És – hogy is mondjam –, jó.
+
+^[-–]{word} <- option("dash") -> – {word} # Gondolatjel szóközzel a felsorolásnál \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#258.
+
+"[[][.][.][.]]" <- option("elli") -> […] # Három pont \n http://hu.wikipedia.org/wiki/Három_pont
+# [...] -> […]
+[.][.][.] <- option("elli") -> … # Három pont \n http://hu.wikipedia.org/wiki/Három_pont
+# Vége... -> Vége…
+
+" +([.?!,:;)”])\b" -> "\1 " # Felcserélt szóköz és írásjel?
+" +([.?!,:;)”])" -> \1 # Szóköz nélkül tapadó írásjel \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#239.
+# A ( kicsit ) más. -> A (kicsit) más.
+
+E ( |$) # space or end of sentence
+"[:,;]([.?!,;:]){E}" -> \1{E} # Felesleges írásjel.
+"\b[.][.]{E}" -> .{E}\n…{E} # Pont vagy három pont? \n http://hu.wikipedia.org/wiki/Három_pont
+#"\b[.]([?!]){E}" -> \1{E} # Felesleges írásjel.
+# És,, stb.? -> És, stb.?
+# És.. -> És.\n…
+
+(\w){punct}{Abc} -> \1{punct} {Abc} # Hiányzó szóköz?
+{abc}[.]{ABC} -> {abc}. {ABC} # Hiányzó szóköz?
+# macska,bár -> macska, bár
+# macska.Bár -> macska. Bár
+
+(^|\b|{punct}|[.]) {2,3}(\b|$) <- option("spaces") -> "\1 " # Felesleges szóköz.
+# dupla szóköz. Itt három. -> dupla szóköz. Itt három.
+
+(^|\b|{punct}|[.]) {4,}(\b|$) <- option("spaces2") -> "\1 \n\1 " # Szóközök cseréje egy szóközre vagy tabulátorra:
+
+(?i)(\d+)(x| x )(\d+(-\w+)?) -> \1×\3\n\1 · \3 # Szorzásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#275.
+# 5 x 6 -> 5 × 6
+# 800x600-as -> 800×600-as
+
+a {abc}+
+b {abc}*
+(?i){a}['´]{b} <- option("apost") -> {a}’{b} # Valódi aposztróf. \n http://hu.wikipedia.org/wiki/Aposztróf
+# biz' isten -> biz’ isten
+
+# ’79-ben
+
+['´](\d\d(-\w+)?) <- option("apost") -> ’\1 # Valódi aposztróf. \n http://hu.wikipedia.org/wiki/Aposztróf
+
+[)] <- option("par") and not "(" in TEXT -> # Felesleges zárójel?
+
+######################## idézés ######################
+
+(?i)[\"“”‟„]({abc}[^\"“”‟„]*)[\"“‟] <- option("quot") -> „\1” # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel
+(?i)[\"“”‟]({abc}[^\"“”‟„]*)[\"“”‟] <- option("quot") -> „\1” # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel
+# A "kicsi" macska. -> A „kicsi” macska.
+
+# ASCII idézőjelek cseréje (,,vmi'', >>vmi<<)
+
+(?i),,({abc}[^\"“”‟„><']*)'' -> „\1” # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel
+(?i)>>({abc}[^\"“”‟„><']*)<< -> »\1« # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel
+
+# angolszász idézőjelek cseréje
+
+(?i)‘+({abc}[^\"“”‟„’]*)’+ -> „\1”\n»\1« # Idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel
+
+[Word]
+
+"([(„»]) +" -> \1 # Szóköz nélkül tapadó írásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#239.
+
+" +([«])" -> \1 # Szóköz nélkül tapadó írásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#239.
+
+(?i)«({abc}[^\"“”‟„’]*)» -> »\1« # Felcserélt belső idézőjelek. \n http://hu.wikipedia.org/wiki/Idézőjel
+
+############### pénz #################################
+
+[Word]
+
+# 1 Ft (azaz két forint) -> 1 Ft (azaz egy forint)
+# 200.000,- Ft, azaz egyszázezer forint -> 100.000,- Ft, azaz kétszázezer forint
+
+(\d[\d   .]*)(,?(?:[-–]|00?)? Ft(?:-\w+)?(?: \(|, )(?:azaz|vagyis) )([-\w]+)( forint\w*\)?) <- option("money") and
+ # test NUMBERTEXT function access
+ calc("NUMBERTEXT", ("1", "hu")) and
+ calc("NUMBERTEXT", (re.sub(u"[   .]", "", \1), "hu")).replace(u"kettő", u"két").replace(u"ezeregyszáz", u"ezerszáz") !=
+ # változatok: száz vagy egyszáz, ezer vagy egyezer, kettő vagy két
+ re.sub(ur"\begy(száz|ezer)", r"\g<1>", \3).replace(u"ezeregyszáz", u"ezerszáz").replace(u"kettő", u"két")
+ -> = \1 + \2 + calc("NUMBERTEXT", (re.sub(u"[   .]", "", \1), "hu")) + \4
+ # A két összeg nem egyezik.
+
+######################## számok ######################
+
+[Word]
+
+# nagy számok tagolása nem törő szóközökkel (U+00A0)
+d1 −?\d{1,3} # 1, 2 vagy 3 számjegy (opcionális mínusszal)
+d2 −?\d{2,3} # 2 vagy 3 számjegy (opcionális mínusszal)
+d3 \d{3} # 3 számjegy
+dn \d{3}(,\w{1,4})?[%‰‱°]?(-\w+)? # 3 számjegy, toldalékkal is
+{d2}{dn} <- option("numpart") and not option("thou") -> {d2} {dn} # Nagy számok tagolása. (AkH. 274.)
+{d1}{d3}{dn} <- option("numpart") and not option("thou") -> {d1} {d3} {dn} # Nagy számok tagolása. (AkH. 274.)
+{d1}{d3}{d3}{dn} <- option("numpart") and not option("thou") -> {d1} {d3} {d3} {dn} # Nagy számok tagolása. (AkH. 274.)
+# Az 1234567890 -> Az 1 234 567 890
+
+# nagy számok tagolása nem törő keskeny szóközökkel (U+202F) (thou opciótól függően)
+{d2} ?{dn} <- option("numpart") and option("thou") -> {d2} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.)
+{d1} ?{d3} ?{dn} <- option("numpart") and option("thou") -> {d1} {d3} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.)
+{d1} ?{d3} ?{d3} ?{dn} <- option("numpart") and option("thou") -> {d1} {d3} {d3} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.)
+
+# nagy számok tagolása nem törő szóközökkel (U+00A0)
+d1 \d{1,3} # 1, 2 vagy 3 számjegy (opcionális mínusszal)
+d2 \d{2,3} # 2 vagy 3 számjegy (opcionális mínusszal)
+d3 \d{3} # 3 számjegy
+dn \d{3}(,\w+)?[%‰‱°]?(-\w+)? # 3 számjegy, toldalékkal is
+-{d2}{dn} <- option("numpart") and not option("thou") -> −{d2} {dn} # Nagy számok tagolása. (AkH. 274.)
+-{d1}{d3}{dn} <- option("numpart") and not option("thou") -> −{d1} {d3} {dn} # Nagy számok tagolása. (AkH. 274.)
+-{d1}{d3}{d3}{dn} <- option("numpart") and not option("thou") -> −{d1} {d3} {d3} {dn} # Nagy számok tagolása. (AkH. 274.)
+
+# nagy számok tagolása nem törő keskeny szóközökkel (U+202F)
+-{d2} ?{dn} <- option("numpart") and option("thou") -> −{d2} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.)
+-{d1} ?{d3} ?{dn} <- option("numpart") and option("thou") -> −{d1} {d3} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.)
+-{d1} ?{d3} ?{d3} ?{dn} <- option("numpart") and option("thou") -> −{d1} {d3} {d3} {dn} # Nagy számok tagolása nem törő keskeny szóközökkel. (AkH. 274.)
+
+
+([-−]?\d[\d,]*)[  ]([%‰‱°](-\w*)?)
+ -> \1\2 # Szóköz nélkül tapadó írásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#275.
+([-−]?\d\d*)[.](\d\d*)([%‰‱°](-\w*)?) <- option("comma")
+ -> \1,\2\3 # Tizedesvessző a helyes írásjel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#291.
+(\d\d*)[.](\d)
+ # kivéve, ha tulajdonnév előzi meg (pl. Firefox 3.5
+ <- option("comma") and (not word(-1) or not re.match("[A-Z]", word(-1)))
+ -> \1,\2\n\1.\2. # Tizedestört (AkH. 291.) vagy sorszám?
+((\d\d*[.]){2}\d)
+ # kivéve, ha tulajdonnév előzi meg (pl. Hunspell 1.2.8
+ <- option("comma") and not word(-1) or not re.match("[A-Z]", word(-1))
+ -> \1. # A sorszámot pont követi.
+(\d\d\d+)[.](\d\d) <- option("comma")
+ -> \1,\2\n\1.\2. # Tizedestört (AkH. 291.) vagy sorszám?
+# 25.30˚, de 10.20-kor -> 25,30˚, de 10.20-kor
+# 1.5 -> 1,5\n1.5.
+# 123.5 -> 123,5\n123.5.
+
+# mínuszjel
+
+-(\d+([  ]\d\d\d){0,3}(,\d+)?[%‰‱°]?(-\w+)?) <- option("minus") -> −\1 # Mínuszjel kiskötőjel helyett.
+
+-(\d+([  ]\d\d\d){0,3})[.](\d+[%‰‱°]?(-\w+)?) <- option("minus") -> −\1,\2 # Mínuszjel és tizedesvessző. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#291.
+
+(−\d+([  ]\d\d\d){0,3})[.](\d+[%‰‱°]?(-\w+)?) -> \1,\2 # Tizedesvessző pont helyett. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#291.
+
+######################## fok #########################
+
+[word]
+
+# 12°-kal
+
+([-−]?\d+(?:,\d+)?)[  ](°(-\w+)) -> \1\2 # Szóköz nélkül tapadó írásjel (AkH. 239.)
+
+# 12 °C-kal
+
+([-−]?\d+(?:,\d+)?)((°C|°F|℃|℉)(-\w+)?) -> \1 \2 # Nem törő szóközzel elválasztott mértékegység.
+
+######################## dátumok #####################
+
+[word]
+
+year [12]\d\d\d
+monthnum 0?[1-9]|1[012]
+month január|február|március|április|május|június|július|augusztus|szeptember|október|november|december|jan[.]|febr[.]|márc[.]|ápr[.]|máj[.]|jún[.]|júl[.]|aug[.]|szept[.]|okt[.]|nov[.]|dec[.]
+Month Január|Február|Március|Április|Május|Június|Július|Augusztus|Szeptember|Október|November|December
+day [12]\d|3[01]|0?[1-9]
+
+notmonthposs (|[^-–jaáeé][a-zöüóűőúéáí]*)
+
+# 2010 június-július
+notmonthcomp [-–]{month}{notmonthposs}
+
+# XXX: sentence boundary modification
+\b{year}[.] {Month}\b -> = {year} + ". " + {Month}.lower() # A hónap nevét kisbetűvel írjuk. (AkH. 144.)
+
+year2 \d\d
+
+{year} {month}{notmonthposs} -> {year}. {month}{notmonthposs} # Az évszám után itt pontot írunk. \n \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#294.
+{year} {month}{notmonthcomp} -> {year}. {month}{notmonthcomp} # Az évszám után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#294.
+{year} évi -> {year}. évi # Az évszám után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#294.
+{year}[-–]{year2} évi -> {year}–{year2}. évi # Az évszám után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#294.
+# 2005 január -> 2005. január
+# 1999 augusztusban -> 1999. augusztusban
+# 2009-10 évi -> 2009–10. évi
+
+nu folyamán|előtti?|utáni?|közötti?|nyara|nyará\w+|tele|telé\w+|tavasza|tavaszá\w+|ősze|őszé\w+
+\b{year}[.] {nu}\b -> {year} \g<nu> # Az évszám után itt nem írunk pontot. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#295.
+# 1974. előtti -> 1974 előtti
+
+monthposs ([jaáe]|é\w)\w*
+
+\b{year}[.] {month}{monthposs}\b -> {year} {month}{monthposs} # Az évszám után itt nem írunk pontot. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#295.
+# 1999. augusztusában -> 1999 augusztusában
+
+[char]
+
+optdot ([.]|)
+text [^\s][^\s]*
+w \w*
+djel [ ,;:?!]
+
+(?i)\b{month} {day}[.]-{w} -> {month} {day}-{w} # A nap után itt nem írunk pontot. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#296.
+(?i)\b{month} {day}{djel} -> {month} {day}.{djel} # Ha dátum, hiányzik a pont. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#296.
+# március 15.-én -> március 15-én
+# március 15 volt. -> március 15. volt.
+
+
+nu óta|előtti?|utáni?|közötti?
+(?i)\b{month} {day} {nu} -> {month} {day}. {nu} # A nap után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297.
+# március 15 óta -> március 15. óta
+(?i)\b{month} {day}[.] és {day} {nu} -> {month} {day}. és {day}. {nu} # A nap után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297.
+(?i)\b{month} {day} és {day}[.]? {nu} -> {month} {day}. és {day}. {nu} # A nap után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297.
+# március 15. és 27 között -> március 15. és 27. között
+# március 15 és 27. között -> március 15. és 27. között
+# március 15 és 27 között -> március 15. és 27. között
+(?i)\b{month} {day}[-–]{day} {nu} -> {month} {day}–{day}. {nu} # A nap után itt pontot írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297.
+(?i)\b{month} {day}-{day}. {nu} -> {month} {day}–{day}. {nu} # A napok közé nagykötőjelet írunk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#297.
+# március 15-22. között -> március 15–22. között
+# március 15-22 között -> március 15–22. között
+
+\b{year}[.]{monthnum}[.]{day}{optdot}{text} -> {year}. {monthnum}. {day}{optdot}{text} # Szóköz a dátumban. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#293.
+# 2009.05.12. -> 2009. 05. 12.
+
+# 1. = elseje
+e e|i|ei\w*|é\w+
+(?i){month} 1[.]?-{e}\b -> {month} 1-j{e} # Elseje számjegyes írása. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#296.
+# május 1-i -> május 1-ji
+# május 1-ei -> május 1-jei
+# május 1-én -> május 1-jén
+# április 1-étől május 1-ig -> április 1-jétől május 1-ig
+
+
+########################## stb. ######################
+
+#W \w+ # word
+# tagmondatok és mondatrészek megkülönböztetéséhez mondatelemzés kell
+#([(]|\w+: )(({W}, )+{W};( {W}[,;])* {W})[,]? stb. -> \1\2; stb. # Stb. előtt itt pontosvessző van. (AkH. 247/b) \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#247.
+#([(]|\w+: )(({W}, )*{W}), stb. -> \1\2 stb. # Stb. előtt itt nincs vessző. (AkH. 247/d) \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#247.
+\bstb[.], stb[.] -> stb. stb.\nstb.; stb. # Két stb. közé nem teszünk vesszőt.
+## Madarak: rigó, cinke, veréb, stb. -> Madarak: rigó, cinke, veréb stb.
+## Állatok (rigó, cinke; nyúl, pocok stb.) -> Állatok (rigó, cinke; nyúl, pocok; stb.)
+# stb., stb. -> stb. stb.\nstb.; stb.
+
+#################### rövidítések #####################
+
+[word]
+
+(db|Ft)[.](?= {abc}) -> \1 # Nem ponttal írjuk ezt a rövidítést.
+(db|Ft)[.](?=[,;:]) -> \1 # Nem ponttal írjuk ezt a rövidítést.
+# 25 db. vmi -> 25 db vmi
+
+##################### nagykötőjel ####################
+
+[char]
+
+country albán|amerikai|angol|belga|bolgár|bosnyák|brit|ciprusi|cseh|dán|észt|finn|francia|görög|holland|horvát|ír|japán|kínai|lengyel|lett|litván|macedón|magyar|máltai|német|norvég|olasz|orosz|osztrák|portugál|román|spanyol|svájci|svéd|szerb|szlovák|szlovén|török|ukrán
+(?i)\b{country}-{country}\b -> {country}–{country} # Népnevek közé nagykötőjelet teszünk.
+# magyar-német -> magyar–német
+
+# year2: Az 1000-1500 vagylagos összetételek kizárására
+year2 (1\d\d[1-9]|1\d[1-9]\d|20\d[1-9]|20[1-9]\d)
+"\b{year2}-{year}\b " -> "{year}–{year} " # Évszámok közé nagykötőjelet teszünk.
+"\b{year}-{year2}\b " -> "{year}–{year} " # Évszámok közé nagykötőjelet teszünk.
+"\b{year}-(\d\d)\b " -> "{year}–\2 " # Évszámok közé nagykötőjelet teszünk.
+# 1998-2000 -> 1998–2000
+# 1998-99 -> 1998–99
+
+([A-ZÖÜÓŰŐÚÉÁÍ]\w*)-(\d+(-\w+)?) -> \1–\2 # Típusnév és -szám közé nagykötőjelet teszünk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#263.
+# UTF-8 -> UTF–8
+# Apolló-13-nak -> Apolló–13-nak
+
+pp[.] (\d+)-(\d+)[.] -> pp. \1–\2. # Oldalszámok közé nagykötőjelet teszünk. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#263.
+(\d+)-(\d+)[.] (o[.]|oldal\w*) -> \1–\2. \3 # Oldalszám
+# 10-12. oldalon -> 10–12. oldalon
+
+" (u[.]|utca|út|tér) (\d\d*)-(\d\d*)[.]" -> " \1 \2–\3." # Nagykötőjel a házszámban. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Egyéb_tudnivalók#298.
+# Széna tér 123-125. -> Széna tér 123–125.
+
+
+###################### helyesírás ####################
+
+[Word]
+
+ne játs(zunk|zatok|zanak) -> ne játss\1 # Helyesírási hiba.
+
+###################### kifejezések ###################
+
+[Word]
+
+[aá] la carte -> à la carte # Helyesen à la carte.
+(állta(ss\w*|t\w*)) <- not morph(\1, "pa:") -> álta\2 # Áltat, hiteget értelemben egy l-lel írjuk.
+önáll(tat[óá]\w*) -> önál\1 # Helyesen egy l-lel.
+belsőséges -> bensőséges\nbelsőségből készült # Szótévesztés vagy szójáték?
+dehogy is -> dehogyis # Egybeírás „egyáltalán nem” jelentésben.
+dehogy nem -> dehogynem # Egybeírás „de igen” jelentésben.
+dehogyis nem -> dehogyisnem # Egybeírás „de igen” jelentésben.
+eképpen -> ekképpen # Helyesen két k-val.
+egyel (több\w*|kevesebb\w*) -> eggyel \1 # 1-gyel értelemben hosszú gy-vel írjuk.
+egyenlőre -> egyelőre\negyformára\ndöntetlenre\negyenlő számúra\nazonos méretűre # Helyesírási (egyelőre) vagy stílushiba (egyformára).
+egyi(vású\w*) -> egyí\1 # Hosszú í-vel helyes.
+egytől-egyig -> egytől egyig # Kötőjel nélkül írjuk.
+előre hátra -> előre-hátra # Kötőjellel írjuk.
+előre láthatólag -> előreláthatólag # Egybeírás.
+email: -> e-mail: # e-mail (elektronikus levél)
+email-lel -> e-maillel # e-mail (elektronikus levél)
+e(mail[ -]|-mail-|-mail)(cím\w*) -> e-mail \2 # Helyesen e-mail cím.
+ex[- ](\w+) <- spell("ex" + \1) -> ex\1 # Egybeírás.
+figyelemre(méltó\w*) <- word(-1) != "igen" -> figyelemre \1 # Különírás (kivéve: „igen figyelemreméltó”).
+igen figyelemre (méltó\w*) -> igen figyelemre\1 # Egybeírás.
+(állat|csepp|csillag|ék|ellipszis|ember|félgömb|félkör|gáz|gömb|gúla|harang|háromszög|hasáb|hatszög|henger|kagyló|kereszt|kocka|korong|kör|körte|kúp|négyszög|négyzet|nyereg|patkó|piramis|piskóta|szivar|tojás|tölcsér|trapéz|vese)(formájú|alakú) -> \1 \2 # Különírás.
+fő(irány\w*|közlekedés\w*|szabály\w*|szervező\w*) -> fő \1 # A „fő mű”-höz hasonlóan különírjuk.
+hátba (támadás\w*) -> hátba\1 # Egybeírás.
+időről-időre -> időről időre # Különírás.
+jing és jang -> jin és jang # Helyesen jin és jang.
+kőr((öz|út|ut)\w*) <- morph(\0, ur"st:kőr\b") -> kör\1 # Rövid ö-vel a kör összetételeiben.
+légyszíves -> légy szíves\nlegyél szíves # Legyél szíves értelemben különírjuk.
+legalább is -> legalábbis # Egybeírás.
+Lichten(stein\w*) -> Liechten\1 # Helyesen Liechtenstein.
+mellékhely(ség\w*) -> mellékhelyi\1 # Helyiség, mint szoba.
+mú(landó\w*) -> mu\1 # Helyesen rövid u-val.
+nembiztos -> nem biztos # Különírás.
+originált -> originál\neredeti\nbontatlan # Ha nem tárgyesetben van, „t” nélkül írjuk.
+(szén|kén|mangán|nitrogén|ón|titán|tórium)(dioxid\w*) -> \1-\2 # Kötőjeles alak.
+(szén|kén|nitrogén)(monoxid\w*) -> \1-\2 # Kötőjeles alak.
+továbbittunk -> továbbítunk\ntovább ittunk # Helyesírási hiba.
+
+[char]
+
+# Mivel az "un." rövidítésként szerepel az OpenOffice.org-ban, nagybetűs folytatás esetén nem húzzuk alá
+\bun[.] <- word(1) and not re.match(u"[A-ZÖÜÓŰŐÚÉÁÍ]", word(1)) -> ún. # Úgy nevezett rövidítése ún. (AkH. 282.)
+(?i)\bvíz(hang\w*)\b -> vissz\1 # Szótévesztés?
+
+#################### nyelvtani szabályok ##################
+
+# az "a" névelő (kivétel: a 4. a osztályban, a II. világháború, az A alaphang...)
+a [aA]
+aword [aáeéiíoóöőuúüűAÁEÉIÍOÓÖŐUÚÜŰ]\w*
+^[aA] {aword} <- not re.match(r"(?i)i(ii?|[vx])$|Unicode$|Unix\w*$", {aword}) and spell({aword}) -> az {aword} # Hibás névelő?
+(?<!(\d[.]|az) )\b{a} {aword} <- word(-1) and not re.match(r"(?i)i(ii?|[vx])$|Unicode$|Unix\w*$", {aword}) and
+ spell({aword}) -> {a}z {aword}\n{aword} # Hibás vagy felesleges névelő?
+# A 4. a osztály a órán az A alaphangot -> A 4. a osztály az órán\nórán az A alaphangot
+
+# névelők és számok
+
+[Word]
+
+a <- word(1) and re.match(r"(1|5\d*|[15]\d\d\d)[.]?$", word(1)) -> az # Hibás névelő.
+
+az <- not option("grammar") and word(2) and
+ re.match(ur"(alfejezet|alszakasz|ábr|bekezdés|diagram|fejezet|kép|lap|oldal|paragrafus|szakasz|táblázat)\w*", word(2)) and
+ re.match(r"([02-46-9]|[1-46-9]\d|[1-46-9]\d\d|[2346-9]\d\d\d)[.]", word(1)) -> a # Hibás névelő?
+
+az <- option("grammar") and word(1) and
+ re.match(r"([02-46-9]|[1-46-9]\d|[1-46-9]\d\d|[2346-9]\d\d\d)[.]", word(1)) -> a # Hibás névelő?
+
+# g = gramm
+
+num \d+|\d+,\d+
+{num} gr[.]?-mal -> {num} g-mal # grammal rövidítése g-mal (AkH. 286.)
+# 25 gr-mal -> 25 g-mal
+# 25,2 gr.-mal -> 25,2 g-mal
+
+[char]
+
+hw [a-zA-ZöüóűőúéáíÖÜÓŰŐÚÉÁÍ][a-zA-ZöüóűőúéáíÖÜÓŰŐÚÉÁÍ]*
+
+" A vitamin{w}" -> " A-vitamin{w}" # Kötőjeles név.
+
+[word]
+
+([B-Z]) vitamin{w} -> \1-vitamin{w} # Kötőjeles név.
+([A-Z])-(vitamin)(\w+) <- morph(\2+\3, "pa:") -> \1-vitamin-\2 # Két kötőjellel írt alak.
+# vitaminhiány külön szerepel a szótárban, ezért szóköz nélkül is javítani kell
+([A-Z])-(vitamin) *(hiány) -> \1-\2-\3 # Két kötőjellel írt alak.
+
+
+[char]
+
+(?i)\bnyílt szívű{w} -> nyíltszívű{w} # Egybeírás.
+(?i)\bjó szándékú{w} -> jószándékú{w} # Egybeírás.
+(?i)közös lónak túrós -> közös lónak túros # Helyes kifejezés.
+(?i)\bnejlon harisnya\b -> nejlonharisnya # Egybeírás.
+(?i)\boda-vissza{hw} -> oda-vissza {hw} # Különírás.
+(?i)\bpro és kontra\b -> pró és kontra # Helyes latin kifejezés.
+(?i)\brákövetkez{hw} -> rá következ{hw} # Különírás.
+(?i)\btáj jellegű{w} -> tájjellegű{w} # Egybeírás.
+(?i)([stluv])-alakú{w} -> \1 alakú{w} # Különírás.
+# B vitamin -> B-vitamin
+# Pro és kontra -> Pró és kontra
+# oda-visszamentek -> oda-vissza mentek
+# S-alakúakat -> S alakúakat
+
+(\d\d*)-szobás{w} -> \1 szobás{w} # Különírás.
+(\d\d*)-részes{w} -> \1 részes{w} # Különírás.
+# 5-szobásat -> 5 szobásat
+
+[word]
+
+event (Advent|Húsvét|Karácsony|Mindenszentek|Pünkösd|(Anyák|Apák|Halottak|Nők) [Nn]apj){abc}*
+{event} <- word(-1) and word(1) == word(1).lower() -> = {event}.lower() # Kisbetűs kifejezés, ha nem cím. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_kis_és_a_nagy_kezdőbetűk#145.
+# Nemsokára Anyák napja. -> Nemsokára anyák napja.
+
+[char]
+
+kw ([-][a-zA-ZöüóűőúéáíÖÜÓŰŐÚÉÁÍ][a-zA-ZöüóűőúéáíÖÜÓŰŐÚÉÁÍ]*)?
+
+foci ([Ev])[bB]{kw} -> foci-\1b{kw} # Kötőjeles kifejezés.
+# foci EB -> foci-Eb
+# foci vb-ről -> foci-vb-ről
+
+^Kétség kívül -> Kétségkívül # Egybeírás.
+# Kétség kívül -> Kétségkívül
+
+[Word]
+
+alig alig -> alig-alig # Kötőjeles szókettőzés. (AkH. 97.)
+ki ki -> ki-ki # Kötőjeles szókettőzés. (AkH. 97.)
+is is -> is-is # Kötőjeles szókettőzés. (AkH. 97.)
+kinek kinek -> kinek-kinek # Kötőjeles szókettőzés. (AkH. 97.)
+körbe körbe -> körbe-körbe # Kötőjeles szókettőzés. (AkH. 97.)
+közbe közbe -> közbe-közbe # Kötőjeles szókettőzés. (AkH. 97.)
+külön külön -> külön-külön # Kötőjeles szókettőzés. (AkH. 97.)
+már már -> már-már # Kötőjeles szókettőzés. (AkH. 97.)
+más más -> más-más # Kötőjeles szókettőzés. (AkH. 97.)
+messze messze -> messze-messze # Kötőjeles szókettőzés. (AkH. 97.)
+nagyon nagyon -> nagyon-nagyon # Kötőjeles szókettőzés. (AkH. 97.)
+néha néha -> néha-néha # Kötőjeles szókettőzés. (AkH. 97.)
+olykor olykor -> olykor-olykor # Kötőjeles szókettőzés. (AkH. 97.)
+túl túl -> túl-túl # Kötőjeles szókettőzés. (AkH. 97.)
+sok sok -> sok-sok # Kötőjeles szókettőzés. (AkH. 97.)
+úgy úgy -> úgy-úgy # Kötőjeles szókettőzés. (AkH. 97.)
+
+csip csup -> csip-csup # Kötőjeles ikerszó. (AkH. 103.)
+éhen szomjan -> éhen-szomjan # Mellérendelő szókapcsolat. (AkH. 100.)
+ingó bingó -> ingó-bingó # Kötőjeles ikerszó. (AkH. 103.)
+sebbel lobbal -> sebbel-lobbal # Mellérendelő szókapcsolat. (AkH. 100.)
+szegről végről -> szegről-végről # Mellérendelő szókapcsolat. (AkH. 100.)
+széltében hosszában -> széltében-hosszában # Mellérendelő szókapcsolat. (AkH. 100.)
+szőröstül bőröstül -> szőröstül-bőröstül # Mellérendelő szókapcsolat. (AkH. 100.)
+szőrén szálán -> szőrén-szálán # Mellérendelő szókapcsolat. (AkH. 100.)
+télen nyáron -> télen-nyáron # Mellérendelő szókapcsolat. (AkH. 100.)
+testestől lelkestől -> testestől-lelkestől # Mellérendelő szókapcsolat. (AkH. 100.)
+testestül lelkestül -> testestül-lelkestül # Mellérendelő szókapcsolat. (AkH. 100.)
+többé kevésbé -> többé-kevésbé # Mellérendelő szókapcsolat. (AkH. 100.)
+törik szakad -> törik-szakad # Mellérendelő szókapcsolat. (AkH. 100.)
+tűzön vízen -> tűzön-vízen # Mellérendelő szókapcsolat. (AkH. 100.)
+tűzzel vassal -> tűzzel-vassal # Mellérendelő szókapcsolat. (AkH. 100.)
+véges végig -> véges-végig # Mellérendelő szókapcsolat. (AkH. 100.)
+tüskén bokron -> tüskén-bokron # Mellérendelő szókapcsolat. (AkH. 100.)
+végre valahára -> végre-valahára # Mellérendelő szókapcsolat. (AkH. 100.)
+imígy amúgy -> imígy-amúgy # Mellérendelő szókapcsolat. (AkH. 100.)
+innen onnan -> innen-onnan # Mellérendelő szókapcsolat. (AkH. 100.)
+itt ott -> itt-ott # Mellérendelő szókapcsolat. (AkH. 100.)
+ízig vérig -> ízig-vérig # Mellérendelő szókapcsolat. (AkH. 100.)
+ízzé porrá -> ízzé-porrá # Mellérendelő szókapcsolat. (AkH. 100.)
+jajjal bajjal -> jajjal-bajjal # Mellérendelő szókapcsolat. (AkH. 100.)
+jóban rosszban -> jóban-rosszban # Mellérendelő szókapcsolat. (AkH. 100.)
+jobbra balra -> jobbra-balra # Mellérendelő szókapcsolat. (AkH. 100.)
+jól rosszul -> jól-rosszul # Mellérendelő szókapcsolat. (AkH. 100.)
+kékre zöldre -> kékre-zöldre # Mellérendelő szókapcsolat. (AkH. 100.)
+kénytelen kelletlen -> kénytelen-kelletlen # Mellérendelő szókapcsolat. (AkH. 100.)
+kézen közön -> kézen-közön # Mellérendelő szókapcsolat. (AkH. 100.)
+körös körül -> körös-körül # Mellérendelő szókapcsolat. (AkH. 100.)
+kézzel lábbal -> kézzel-lábbal # Mellérendelő szókapcsolat. (AkH. 100.)
+kurtán furcsán -> kurtán-furcsán # Mellérendelő szókapcsolat. (AkH. 100.)
+lépten nyomon -> lépten-nyomon # Mellérendelő szókapcsolat. (AkH. 100.)
+menet jövet -> menet-jövet # Mellérendelő szókapcsolat. (AkH. 100.)
+nyakra főre -> nyakra-főre # Mellérendelő szókapcsolat. (AkH. 100.)
+örökkön örökké -> örökkön-örökké # Mellérendelő szókapcsolat. (AkH. 100.)
+sülve főve -> sülve-főve # Mellérendelő szókapcsolat. (AkH. 100.)
+úton útfélen -> úton-útfélen # Mellérendelő szókapcsolat. (AkH. 100.)
+üggyel bajjal -> üggyel-bajjal # Mellérendelő szókapcsolat. (AkH. 100.)
+# alig alig -> alig-alig
+# Úgy úgy -> Úgy-úgy
+
+# ágat-bogat
+
+(ág\w*) (bog\w*) <- stem(\1) == [u"ág"] and stem(\2) == ["bog"] -> \1-\2 # Kötőjeles ikerszó. (AkH. 103.)
+
+###################### Földrajzi nevek ######################
+
+[word]
+
+(Északi|Déli)(?:-S| [Ss])ark{w} -> \1-sark{w} # Földrajzi név.
+# Az Északi sarkon -> Az Északi-sarkon # Földrajzi név.
+# Az Északi-Sarkon -> Az Északi-sarkon # Földrajzi név.
+
+dir észak|dél|kelet|nyugat|északkelet|északnyugat|délkelet|délnyugat
+Dir Észak|Dél|Kelet|Nyugat|Északkelet|Északnyugat|Délkelet|Délnyugat
+cap {ABC}{abc}+
+sc {abc}+
+w {Abc}+
+
+# Észak-Amerikai Észak-amerikai helyett
+
+{Dir}-{cap} <- morph({cap}, r"po:noun_prs.*is:i_PLACE", False) -> = {Dir} + "-" + {cap}.lower() # Kisbetűvel írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#179.
+
+# észak-Amerika Észak-Amerika helyett
+
+{dir}-{cap} <- morph({cap}, r"po:noun_prs", False) and not morph({cap},"is:i_PLACE", False) ->
+ = {dir}.capitalize() + "-" + {cap} # Nagybetűvel írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#179.
+
+# Észak-amerikai csak akkor nagybetűs, ha mondatkezdő és nem nagybetűs az utána jövő szó
+
+{Dir}-{sc} <- word(-1) and word(1) and not word(1) == word(1).capitalize() and
+ morph({sc}, r"po:noun_prs.*is:i_PLACE", False) -> = {Dir}.lower() + "-" + {sc} # Kisbetűvel írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#179.
+
+# hiányzó kötőjel
+
+{Dir} {w} <- morph({w}, r"po:noun_prs") -> {Dir}-{w} # Kötőjellel írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#179.
+
+# köznevek
+
+prop Tenger|Óceán|Sziget|Félsziget|Középhegység
+
+{cap}-{prop} -> = {cap} + "-" + {prop}.lower() # Kisbetűs írt köznévi tag. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#176.
+
+# AkH. 182.
+
+(Árpád|Erzsébet|Hajógyári|Margit|Megyeri|Petőfi|Rákóczi|Szabadság)-(híd\w*) -> \1 \2 # Különírás. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#182.
+(Szabadság)(híd\w*) -> \1 \2 # Különírás. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#182.
+(Szabadság ?)(szobo?r\w*) -> \1-\2 # Kötőjeles összetétel. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A különírás és az egybeírás#140.
+
+# AkH. 183.
+
+(Fertő)-(([tT]ó|[tT]av)\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183.
+(Góbi|Kalahári|Szahara)-([sS]ivatag\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183.
+(Börzsöny|Bükk|Mátra|Mecsek|Pilis|Zemplén|Vértes)-([Hh]egység\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183.
+(Duna)-(folyam\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183.
+(Bodrog|Duna|Dráva|Ipoly|Körös|Maros|Rába|Sajó|Tisza|Zala)-(([Ff]olyó|[Ff]olyam)\w*) -> = \1 + " " + \2.lower() # Kötőjel nélkül írt földrajzi név. \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/A_tulajdonnevek_írása#183.
+
+Budapest (Liszt Ferenc )([Nn]emzetközi [Rr]epülőt[eé])(r\w*) -> =
+ \1 + \2.lower() + \3 +
+ "\nferihegyi " + \1 + \2.lower() + \3 + "\n" +
+ \3.replace("r", "Ferihegy", 1).replace("gyrel", "ggyel").replace(u"gyré", u"ggyé") +
+ "\nBudapest, " + \1 + \2.lower() + \3
+ # A köznévi tag kisbetűs, a címet vesszővel tagoljuk. (AkH. 190., 247.; FNB 74.) \n http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#247.
+
+########################## vesszők ##########################
+
+(olya\w+) (aki\w*|ami\w*) <- morph(\2, r"st:(aki|ami|amilyen)\b") -> \1, \2 # Hiányzó vessző a tagmondatok határán?
+
+##################### nyelvtani szabályok ###################
+
+W \w+ # word
+W2 \w+ # word
+
+############### egybeírt segédigék és igekötők #############
+# megszabad csinálni -> meg szabad csinálni
+# megtudta volna tenni -> meg tudta volna tenni
+# megfogja majd tudni -> meg fogja majd tudni
+# megszeretném még enni -> meg szeretném még enni
+# -> Megpróbálom megcsinálni.
+
+igekoto abba|agyon|alá|által|át|be|bele|benn|egybe|együtt|el|ellen|elő|előre|fel|föl|félbe|félre|felül|fölül|fenn|fönn|hátra|haza|helyre|hozzá|ide|jóvá|keresztül|ketté|ki|kölcsön|körbe|körül|közbe|közre|külön|le|meg|mellé|neki|oda|össze|rá|rajta|széjjel|szembe|szerte|szét|tele|tova|tovább|túl|újjá|újra|utána|végbe|végig|vissza
+segedige (akar|bír|fog|legy|lehet|lenn|lesz|lett|szabad|szeret|talál|tud|van|vol)\w*
+szavak ( \w+){0,}
+igenev (\w+ni)
+
+[Word]
+
+{igekoto}{segedige}{szavak} {igenev}
+ <- morph({igenev}, "INFINITIVE") and
+ morph({igekoto}+{segedige}, r"is:[/\w]*DEF|ds:tt")
+ -> {igekoto} {segedige}{szavak} {igenev} # Az igekötőt nem írjuk egybe a segédigével.
+
+# elvan ez már rég felejtve
+letige (legy|lehet|lenn|lesz|lett|van|vol)\w*
+igenev (\w+v[ea])
+
+{igekoto}{letige}{szavak} {igenev}
+ <- morph({igenev}, "_PART") and
+ morph({igekoto}+{letige}, r"is:[/\w]*DEF|ds:tt")
+ -> {igekoto} {letige}{szavak} {igenev} # Az igekötő a lenni + -va/-ve szerkezetben nem a létigéhez kapcsolódik.
+
+############### had -> hadd ################
+# Eltusolták az ügyet. -> Eltussolták az ügyet.
+# Had legyen meglepetés! -> Hadd legyen meglepetés!
+
+(had|hagy)( (ne )?){W} <- morph({W}, r"(IMPER[_\w]*SG_1|is:[_/\w]*DEF_PL)") or
+ (not word(-1) and morph({W}, r"is:[_/\w]*DEF_SG_[23]"))
+ -> \1d\2{W} # Hadd helyesen.
+
+############### *Áld meg! stb. ###################
+(\w+[lnrz]d) {igekoto} <- (not word(-1) or word(-1).lower() == "ne") and
+ morph(\1, "st:" + \1.lower() + r"\b") and morph(\1+"d", r"IMPER") -> \1d \2 # Felszólító mód.
+
+############### kér, kérd ########################
+
+kérdd el -> kérd el # „kér” felszólító módja.
+
+############### megfedd, eltussol ##########
+# Aztán jól megfedte. -> Aztán jól megfeddte.
+# Eltusolták az ügyet. -> Eltussolták az ügyet.
+
+(megfe)(d\w*) <- morph(\1+\2, r"st:fed\b") -> \1d\2 # Megfedd helyesen.
+(eltus)(ol\w*) <- morph(\1+\2, r"st:tusol\b") -> \1s\2 # Eltussol helyesen (kivéve, ha zuhanyzásról van szó).
+
+############## főkép -> főképp #############
+főké(p|pen) <- word(-1) != "a" and word(-1) != "A"
+ -> főkép\1 # Ha határozószó, akkor főképp.
+
+############# számok ######################
+
+[char]
+
+\b0-á(\w+) -> 0-\1 # Hibás toldalék?
+(\d*[14])-el\b -> \1-gyel # Hibás toldalék?
+(\d*2)-ő(\w+) -> \1-\2 # Hibás toldalék?
+(\d*3)-á\b -> \1-má # Hibás toldalék?
+(\d*3)-al\b -> \1-mal # Hibás toldalék?
+(\d*[57])-el\b -> \1-tel # Hibás toldalék?
+(\d*6)-á\b -> \1-tá # Hibás toldalék?
+(\d*8)-á\b -> \1-cá # Hibás toldalék?
+(\d*9)-el\b -> \1-cel # Hibás toldalék?
+(\d*10)-el\b -> \1-zel # Hibás toldalék?
+(\d*20)-á\b -> \1-szá # Hibás toldalék?
+(\d*30)-á\b -> \1-cá # Hibás toldalék?
+(\d*[4579]0)-el\b -> \1-nel # Hibás toldalék?
+(\d*[68]0)-á\b -> \1-ná # Hibás toldalék?
+\b(\d)00-á\b <- \1 != "0" -> \100-zá # Hibás toldalék?
+\b(\d)000-el\b <- \1 != "0" -> \1000-rel # Hibás toldalék?
+#(\d*\d)0000-el\b <- \1 != "0" -> \1\2000-rel # Hibás toldalék?
+#(\d*)(\d)00000-el\b <- \1 != "0" -> \1\2000-rel # Hibás toldalék?
+
+############## több mint #######################
+# több, mint testőr -> több mint testőr XXX tavaly, délután stb. miatt nincs kezelve
+# -> több, mint tavaly
+# több, mint unalmas -> több mint unalmas
+# több, mint kiváló -> több mint kiváló
+# több, mint 70%-uk -> több mint 70%-uk
+# több, mint négyen -> több mint négyen
+# -> öt több, mint négy
+# több, mint 25 ezren -> több mint 25 ezren
+# több, mint két embert -> több mint két embert
+# több, mint 9 embert -> több mint 9 embert
+# több, mint 9 ezer fát -> több mint 9 ezer fát
+
+[Word]
+
+több, mint <-
+ # (több mint jó), több mint nyolcan, több mint 12-en
+ morph(word(1), r"(po:noun.*ds:s_\w*|po:adj|PRESPART_adj|po:adj_num.*(is:|An_MODE_adv))\b") or
+ # több mint 25 ezren, több mint 25 ezerről, több mint száz birkát
+ # (fix: "ezer" adj-ként is szerepel, ezért külön kezelve XXX)
+ (morph(word(1), r"(po:adj_num|^\d+$)") and morph(word(2), r"(po:noun\b.*is:|(po:adj_num|st:ezer\b).*(is:|An_MODE_adv))")) or
+ # több mint 25 ezer birkát
+ (re.match(r"\d+$", word(1)) and morph(word(2), r"po:adj_num|st:ezer\b") and morph(word(3), r"po:noun\b.*is:")) or
+ # több mint 75%-a
+ re.match(r"\d+%-", word(1)) -> több mint # Ha nem összehasonlítás,
+ hanem a mondanivaló erősítése, itt nem használunk vesszőt. \n
+ http://hu.wikisource.org/wiki/A_magyar_helyesírás_szabályai/Az_írásjelek#243.
+
+############ avagy, illetve, ill., valamint ##########
+
+(\w+)( avagy) -> \1,\2 # Az avagy kötőszó elé vesszőt teszünk.
+(\w+)( illetve) -> \1,\2 # Az illetve kötőszó elé vesszőt teszünk.
+(\w+)( ill[.]) -> \1,\2\n\1, illetve # Az illetve kötőszó elé vesszőt teszünk.
+(\w+)( valamint) -> \1,\2 # A valamint kötőszó elé vesszőt teszünk.
+
+############ mellet -> mellett ##################
+# a fa mellet -> a fa mellett
+# -> De! feszes mellet
+mellet <- morph(word(-1), r"po:noun.*:NOM(?!.*[di]s:)|_noun\s+ts:NOM$") -> mellett # Nem inkább mellett (vagy hibás különírás)?
+
+############ kellet -> kellett ##################
+# nem kellet volna -> nem kellett volna
+kellet <- morph(word(-1), r"INF_|_inf") or morph(word(-2), r"INF_|_inf") -> kellett # Helyesírási hiba.
+kellet <- morph(word(1), r"INF_|_inf") or morph(word(2), r"INF_|_inf") or word(1) == "volna" -> kellett # Helyesírási hiba.
+
+############### helyett kapott #######################
+# is helyett kapott -> is helyet kapott
+# a csomagban helyett kapott -> a csomagban helyet kapott
+(\w+) helyett (kap\w*) <- morph(\1, r"st:(is|ismét|mellett|még)\b|is:INE") and morph(\2, r"st:kap\b") -> \1 helyet \2 # Helyesen: helyet kap.
+
+############## halott -> hallott ##################
+
+(?<=[Nn]em )halott(am|unk) -> hallott\1 # Helyesírási hiba?
+
+(hal)(ott\w*)(?= róla\w*) -> \1l\2 # Helyesírási hiba?
+
+############### összetett szavak #################################
+
+[Word]
+
+# rövid összetett szó
+
+W \w{4,5}
+{W} <- option("compound") and morph({W}, "pa:") -> =suggest({W}) # Biztos, hogy helyes összetett szó?
+
+# rövid (kétbetűs) tagot tartalmazó összetett szó
+
+W \w{4,}
+{W} <- option("compound") and morph({W}, ur"(?u)pa:\w\w\b") -> =suggest({W}) # Biztos, hogy helyes összetett szó?
+
+# minden képzett összetett szó
+
+{W} <- option("allcompound") and morph({W}, "pa:") -> =suggest({W}) # Biztos, hogy helyes összetett szó?
+
+############### vesszőhasználat ########################
+
+############### Stílus #################################
+
+[Word]
+#asszem -> azt hiszem\nazt hiszem, hogy # Helyesírási hiba.
+#h <- option("style") -> hogy # Hibás rövidítés?
+#szar\w* <- option("style") and morph(\0, r"st:szar\b") -> rossz # Stílushiba.
+
+médiák <- option("style") -> médiák\nmédia\nhírek\nlapok\nhírcsatornák # Vitatott stílusértékű alak.
+unszimpatikus <- option("style") -> unszimpatikus\nellenszenves\nantipatikus # Vitatott stílusértékű alak.
+
+# ezresek számjegyekkel
+
+#(\d{2,3})[  ]?000-(\w+) <- option("style") and (not word(-1) or not re.match("[0-9]+$", word(-1))) and spell("ezer" + \2) and not morph("ezer" + \2, "_adj") -> \1 ezer\2 # Ha szám, javasolt betűkkel írni.
+#(\d{2,3})[  ]?000[  ]?000-(\w+)
+# <- option("style") and (not word(-1) or not re.match("[0-9]+$", word(-1))) and spell(u"millió" + \2) -> \1 millió\2 # Ha szám, javasolt betűkkel írni.
+
+############### különírás ###############################
+
+[char]
+" (-\w+)" <- option("wordpart") and morph(\0, "st:-e|po:(suffix|punct)")
+ -> \1 # A toldalékot szóköz nélkül írjuk.
+
+[Word]
+
+(a|az|egy) (\w+) (\w+) <- option("wordpart") and spell(\2 + \3) and
+ morph(word(1), "po:vrb") and
+ affix(\2, "ts:NOM$") and not morph(\2, "ts:PLUR") and
+ affix(\3, "[it]s:NOM$") -> \1 \2\3 # Hibás különírás?
+
+############### szóismétlés ###############################
+
+W [-\w]{3,}
+
+[word]
+
+{W} \1 <- option("dup0") and (not word(-1) or
+ not word(-1).lower() in ["a", "az", "minden"]) and word(1) != u"hátán" and word(1) != u"hátán." and
+ not morph(word(1), "po:post", False) -> {W}\n{W}-\1 # Szóismétlés vagy hiányzó kötőjel?
+
+{W}(?: [-–\w„”]+)* \1 <- option("dup") -> {W} # Túlzott szóismétlés?
+
+{W}[;,:]?(?: [-–\w„”]+[;,:]?)* \1 <- option("dup2") -> {W} # Túlzott szóismétlés?
+
+# toldalékolva is (de nem összetett szó)
+
+([-\w]{4})([-\w]+)(?: [-–\w„”]+)* \1(\w+) <- option("dup3") and
+ option("dup") and morph(\1+\2, r"(?u)st:\w+") ==
+ morph(\1+\3, r"(?u)st:\w+") and not morph(\1+\3, "pa:") and not morph(\1+\2, "pa:") -> \1\2 # Túlzott szóismétlés?
+
+([-\w]{4})([-\w]+)[;,:]?(?: [-–\w„”]+[;,:]?)* \1(\w+) <- option("dup3") and
+ option("dup2") and morph(\1+\2, r"(?u)st:\w+") ==
+ morph(\1+\3, r"(?u)st:\w+") and not morph(\1+\3, "pa:") and not morph(\1+\2, "pa:") -> \1\2 # Túlzott szóismétlés?
+
+################# ligatúrák #################################
+
+[word]
+
+[-\w]*f[fil][-\w]* <- option("ligature") -> =\0.replace("ffi",u"ffi").replace("ffl",u"ffl").replace("ff",u"ff").replace("fi",u"fi").replace("fl",u"fl")
+ # A szó unicode-os f-ligatúrákkal:
+
+[-\w]*(ffi|ffl|ff|fi|fl)[-\w]* <- option("noligature") -> =\0.replace(u"ffi","ffi").replace(u"ffl","ffl").replace(u"ff","ff").replace(u"fi","fi").replace(u"fl","fl")
+ # A szó unicode-os f-ligatúrák nélkül:
+
+
+################# indexek, törtek ##############################
+
+[word]
+
+1/2((-\w+)?) <- option("frac") -> ½\1 # Tipográfiai jel:
+1/3((-\w+)?) <- option("frac") -> ⅓\1 # Tipográfiai jel:
+1/4((-\w+)?) <- option("frac") -> ¼\1 # Tipográfiai jel:
+3/4((-\w+)?) <- option("frac") -> ¾\1 # Tipográfiai jel:
+2/3((-\w+)?) <- option("frac") -> ⅔\1 # Tipográfiai jel:
+1/5((-\w+)?) <- option("frac") -> ⅕\1 # Tipográfiai jel:
+1/6((-\w+)?) <- option("frac") -> ⅙\1 # Tipográfiai jel:
+5/6((-\w+)?) <- option("frac") -> ⅚\1 # Tipográfiai jel:
+1/8((-\w+)?) <- option("frac") -> ⅛\1 # Tipográfiai jel:
+3/8((-\w+)?) <- option("frac") -> ⅜\1 # Tipográfiai jel:
+5/8((-\w+)?) <- option("frac") -> ⅝\1 # Tipográfiai jel:
+7/8((-\w+)?) <- option("frac") -> ⅞\1 # Tipográfiai jel:
+
+1/(\d{1,3})((-\w+)?) <- option("frac") -> = u"⅟" + \1.replace("0", u"₀").replace("1", u"₁").replace("2",
+ u"₂").replace("3", u"₃").replace("4", u"₄").replace("5", u"₅").replace("6", u"₆").replace("7",
+ u"₇").replace("8", u"₈").replace("9", u"₉") + \2 # Tört tipográfiai jelekkel:
+
+([2-9]|\d{2,3})/(\d{1,3})((-\w+)?) <- option("frac") -> = \1.replace("0", u"⁰").replace("1", u"¹").replace("2", u"²").replace("3",
+ u"³").replace("4", u"⁴").replace("5", u"⁵").replace("6", u"⁶").replace("7", u"⁷").replace("8", u"⁸").replace("9", u"⁹") +
+ u"⁄" + \2.replace("0", u"₀").replace("1", u"₁").replace("2", u"₂").replace("3", u"₃").replace("4",
+ u"₄").replace("5", u"₅").replace("6", u"₆").replace("7", u"₇").replace("8", u"₈").replace("9", u"₉") + \3 # Tört tipográfiai jelekkel:
+
+[µmck]?m[23](-\w+)? <- option("idx") -> =\0.replace("2", u"²").replace("3", u"³") # Index tipográfiai jellel:
+
+(Ca(CO3|SO4)|CO2|(H2|Na2)(CO3|O|SO4)|[HNO]2|HNO3|Fe2O3|KMnO4|NO2|SiO2|SO[23])(-\w+)? <- option("idx") -> =\0.replace("2", u"₂").replace("3", u"₃").replace("4", u"₄") # Index tipográfiai jellel.
+
+[word]
+
+kedvel <- word(-1).lower() == u"jó" or word(-1).lower() == "rossz" -> kedvvel # Szótévesztés?
+
+################### mértékegységek ##########################
+
+([-−]?\d+(?:,\d+)?) (°F(-\w+)?) <- option("SI") -> = measurement(\1, "F", "C", " " + \2.replace("F", "C")) # Váltás SI mértékegységre
+([-−]?\d+(?:,\d+)?) (℉(-\w+)?) <- option("SI") -> = measurement(\1, "F", "C", " °C" + \2[1:]) # Váltás SI mértékegységre
+
+([-−]?\d(?:,\d+)?) (láb\w*) <- option("SI") and stem(\2) == [u"láb"] -> =
+ measurement(\1, "ft", "cm", " " + generate(u"centiméter", \2)[0]) + "\n" +
+ measurement(\1, "ft", "m", " " + generate(u"méter", \2)[0]) # Váltás SI mértékegységre
+
+([-−]?\d\d+(?:,\d+)?) (láb\w*) <- option("SI") and stem(\2) == [u"láb"] -> = measurement(\1, "ft", "m",
+ " " + generate(u"méter", \2)[0]) # Váltás SI mértékegységre
+
+([-−]?\d+(?:,\d+)?) (hüvelyk\w*) <- option("SI") -> = measurement(\1, "in", "cm",
+ " " + generate(u"centiméter", \2)[0]) # Váltás SI mértékegységre
+
+([-−]?\d+(?:,\d+)?) (mérföld\w*) <- option("SI") -> = measurement(\1, "mi", "km",
+ " " + generate(u"kilométer", \2)[0]) # Váltás SI mértékegységre
+
+([-−]?\d+(?:,\d+)?) (yard\w*) <- option("SI") -> = measurement(\1, "yd", "m",
+ " " + generate(u"méter", \2)[0]) # Váltás SI mértékegységre
+
+([-−]?\d+(?:,\d+)?) (font (súlyú\w*)) <- option("SI") -> = measurement(\1, "lbm", "kg",
+ " " + generate("kilogramm", u"szomor" + \3[4:])[0]) # Váltás SI mértékegységre
+
+([-−]?\d+(?:,\d+)?) (gallon\w*) <- option("SI") -> = measurement(\1, "gal", "l",
+ " " + generate("liter", \2)[0]) # Váltás SI mértékegységre
+
+([-−]?\d+(?:,\d+)?) (pint\w*) <- option("SI") -> =
+ measurement(\1, "uk_pt", "dl", " " + generate("deciliter", \2)[0]) + "\n" +
+ measurement(\1, "us_pt", "dl", " " + generate("deciliter", \2)[0]) # Váltás SI mértékegységre (angol és amerikai pint)
+
+# elválasztás
+
+adatút <- option("hyphen") -> ada­tút\nadat­út # Elválasztás:
+felett(em|ed|e|ünk|ük) <- option("hyphen") -> fe­let­t\1\nfel­et­t\1 # Elválasztás:
+felettetek <- option("hyphen") -> fe­let­te­tek\nfel­et­te­tek # Elválasztás:
+fölül <- option("hyphen") -> fö­lül\nföl­ül # Elválasztás:
+gépelem <- option("hyphen") -> gé­pe­lem\ngép­elem # Elválasztás:
+karóra <- option("hyphen") -> kar­óra\nka­ró­ra # Elválasztás:
+megás <- option("hyphen") -> me­gás\nmeg­ás # Elválasztás:
+megint <- option("hyphen") -> me­gint\nmeg­int # Elválasztás:
+
+[code]
+
+def measurement(mnum, min, mout, mstr):
+ m = calc("CONVERT_ADD", (float(mnum.replace(",", ".").replace(u"−", "-")), min, mout))
+ a = list(set([str(calc("ROUND", (m, 0)))[:-2], str(calc("ROUND", (m, 1))), str(calc("ROUND", (m, 2))), str(m)])) # remove duplicated rounded items
+ a.sort(lambda x, y: len(x) - len(y)) # sort by string length
+ return join(a, mstr + "\n").replace(".", ",").replace("-", u"−") + mstr
diff --git a/src/hu_HU/hu_HU.dlg b/src/hu_HU/hu_HU.dlg
new file mode 100644
index 0000000..6822f08
--- /dev/null
+++ b/src/hu_HU/hu_HU.dlg
@@ -0,0 +1,99 @@
+# Options and title texts for the Settings and conditional rules
+#
+# The Lightproof dialogs contain only grouped checkboxes.
+#
+# Format of the dialog definition:
+#
+# GroupID: OptionID, OptionID ...
+# Group2ID: OptionID, OptionID ...
+# ...
+# [Language_code=title of the window]
+# OptionID=title of the option
+# Option2ID=title of the option
+#
+# The first language is the default language for other locales
+# (use en_US or the common language of your country)
+#
+# The OptionIDs declared here are used in the rules, too. For example:
+#
+# foo <- option("style") -> bar # bar is far better
+#
+# this rule depends from the state of the "style" checkbox.
+
+# options (starred options are default checked ones)
+
+spelling: cap par, quot wordpart, *dash comma, numpart grammar
+proofreading: style *dup0, compound dup, allcompound dup2, *money dup3, SI hyphen
+typography: *apost *spaces frac ligature, elli spaces2 thin noligature, idx minus - -
+
+# titles
+
+[en_US=Hungarian sentence checking]
+
+spelling=Spelling
+cap=Capitalization
+par=Parentheses
+wordpart=Word parts of compounds
+comma=Comma usage
+proofreading=Proofreading
+style=Style checking
+compound=Underline typo-like compound words
+allcompound=Underline all generated compound words
+grammar=Possible mistakes
+money=Consistency of money amounts
+duplication=Word duplication
+dup0=Word duplication
+dup=Duplication within clauses
+dup2=Duplication within sentences
+dup3=Allow previous checkings with affixes
+numpart=Thousand separation of numbers
+typography=Typography
+quot=Quotation marks
+apost=Apostrophe
+dash=En dash
+elli=Ellipsis
+ligature=Ligature suggestion
+noligature=Underline ligatures
+frac=Fractions
+thin=Thin space
+spaces=Double spaces
+spaces2=More spaces
+idx=Indices
+minus=Minus
+SI=Measurements
+hyphen=Hyphenation of ambiguous words
+
+[hu_HU=Magyar mondatellenőrzés]
+
+spelling=Helyesírás
+cap=Nagy kezdőbetű\nMondatok nagy kezdőbetűjének ellenőrzése.
+par=Zárójelek\nZárójelpárok ellenőrzése.
+wordpart=Egybe- és különírási javaslatok
+comma=Vesszőhasználatra vonatkozó javaslatok\nA valószínűleg hiányzó és felesleges vesszők jelzése.
+numpart=Nagy számok tagolása szóközökkel\nEzrestagolás nem-törő szóközökkel (10000 → 10 000).
+proofreading=Korrektúra
+style=Stílusellenőrzés
+compound=Egyszerű nem szótári összetett szavak\nRövid, vagy rövid tagot tartalmazó, szóösszetételi szabályok alapján gyakran hibásan elfogadott alakok aláhúzása.
+allcompound=Minden nem szótári összetett szó\nMinden szóösszetételi szabály alapján elfogadott alak aláhúzása.
+grammar=Javaslat kevésbé egyértelmű esetben is
+dup0=Szóismétlés\nSzóismétlés egymást közvetlenül követő szavak esetében.
+dup=Szóismétlés tagmondaton belül
+dup2=Szóismétlés mondaton belül
+dup3=Szóismétlés eltérő toldalékok esetén is
+money=Számok és átírásuk\nA számmal és számnévvel is leírt mennyiség megegyezik-e? (Pl. 10, azaz tíz Ft.)
+typography=Tipográfia
+quot=Idézőjelek\nA magyar „külső” és »belső« idézőjelek ellenőrzése.
+apost=Aposztróf\nAz írógépes aposztróf cseréje a tipográfiailag megfelelőre (' → ’).
+dash=Nagykötőjel és gondolatjel\nA kiskötőjel cseréje a nagykötőjelre (- → –).
+elli=Három pont\nHárom pont cseréje az egalizált három pont karakterre (...→…).
+frac=Törtek\nPerjellel elválasztott törtek cseréje Unicode karakterre (1/2 → ½).
+thin=Keskeny szóköz\nKeskeny szóköz (spácium) használata ezrestagoláshoz és más esetekben.
+ligature=f-ligatúra javaslata\nCsere Unicode f-ligatúrára.
+noligature=f-ligatúra tiltása\nUnicode f-ligatúra cseréje különálló betűkre.
+spaces=Dupla szóköz\nKét vagy három ismétlődő szóköz cseréje egyre.
+spaces2=Sok szóköz\nNégy vagy több ismétlődő szóköz cseréje egy tabulátorra.
+idx=Indexek\nSzámok cseréje mértékegységekben és kémiai képletekben valódi indexekre (m2 → m²).
+minus=Mínuszjel\nKötőjelek cseréje Unicode mínuszjelre a számok előtt.
+SI=Mértékegységek\nNem SI mértékegységek átalakítása (°F, mérföld, yard, láb, hüvelyk, gallon, pint, font súlyú).
+hyphen=Hiányzó elválasztás megadása\nNem egyértelműen elválasztható szóalakok elválasztásának megadása (pl. megint, fölül).
+
diff --git a/src/ru_RU/README_lightproof_ru_RU.txt b/src/ru_RU/README_lightproof_ru_RU.txt
new file mode 100644
index 0000000..1744797
--- /dev/null
+++ b/src/ru_RU/README_lightproof_ru_RU.txt
@@ -0,0 +1,7 @@
+Russian grammar checker
+
+(developed by the Lightproof grammar checker extension generator,
+see http://launchpad.net/lightproof)
+
+2009, 2011 (c) Yakov Reztsov <yr at myooo dot ru>, license: MPL 1.1 / GPL / LGPL
+
diff --git a/src/ru_RU/ru_RU.cfg b/src/ru_RU/ru_RU.cfg
new file mode 100644
index 0000000..3ba09c7
--- /dev/null
+++ b/src/ru_RU/ru_RU.cfg
@@ -0,0 +1,13 @@
+[args]
+lang = ru_RU
+locales = ru_RU
+name = Lightproof grammar checker (Russian)
+version = 0.3.1
+author = Yakov Reztsov <yr at myooo dot ru>
+provider = LibreOffice
+implname = lightproof_ru_RU
+link = http://www.libreoffice.org
+description = Russian grammar checker for LibreOffice
+extras = README_lightproof_ru_RU.txt
+# logo =
+# sourcefiles = \ No newline at end of file
diff --git a/src/ru_RU/ru_RU.dat b/src/ru_RU/ru_RU.dat
new file mode 100644
index 0000000..512dc25
--- /dev/null
+++ b/src/ru_RU/ru_RU.dat
@@ -0,0 +1,248 @@
+# Sample proofreading rules for Russian (by Yakov Reztsov 2009, 2011)
+
+
+
+# test
+\bfoo\b -> bar # test
+# foo -> bar
+
+
+# punctuation
+
+" ([.?!,:;)”]($| ))" <- option("space") -> \1 # Лишний пробел перед знаком пунктуации.
+"([(“]) " <- option("space") -> \1 # Лишний пробел после знака пунктуации.
+# ( item ) -> (item)
+
+# definitions
+abc [a-zа-я]+
+ABC [A-ZА-Я]+
+Abc [a-zA-Zа-яА-Я]+
+punct [?!,:;%‰‱˚“”‘„]
+abbr руб|коп|грн|тыс|ул|кв|пос|ст|пр|просп|ед|экз|тел|исп
+
+novvod авось|буквально|будто|вдобавок|вдруг|ведь|вот|даже|исключительно|именно|небось|приблизительно|примерно|притом|почти|поэтому|просто|решительно|словно|якобы|в довершение|в конечном счете|вряд ли|все-таки|как будто|как бы|как раз|к тому же|между тем|по предложению|по постановлению|по решению
+
+vvod итак|следовательно|во-первых|во-вторых|в-третьих|в-четвертых|в-пятых|пожалуйста|как нарочно|как исключение|как правило
+
+adv1 кто|что|где|зачем|кое
+
+
+{Abc}{punct}{Abc} <- option("space") -> {Abc}{punct} {Abc} # Пропущен пробел?
+{abc}[.]{ABC} <- option("space") -> {abc}. {ABC} # Пропущен пробел?
+# missing,space -> missing, space
+# missing.Space -> missing. Space
+
+
+# typography
+"[.]{3}" <- option("typographica") -> "…" # Символ троеточия.
+(\d+)x(\d+) <- option("typographica") -> \1×\2 # Знак умножения.
+"^[-—] " <- option("typographica") -> "– " # Заменить на тире (n-dash)?
+" [-—]([ ,;])" <- option("typographica") -> " –\1" # Заменить на тире (n-dash)?
+
+# 800x600 -> 800×600
+# End... -> End…
+# A small - but reliable - example. -> A small – but reliable – example.
+
+"[,]{2}" <- option("comma") -> "," # Две запятые подряд.
+[ ]{abbr}[ ] <- option("abbreviation") -> " {abbr}. " # Точка после сокращений.
+(^|\b|{punct}|[.]) {2,3}(\b|$) <- option("space") -> "\1 " # Лишний пробел.
+# Extra space -> Extra space
+# " мм " -> " мм. "
+
+# quotation
+
+\"(\w[^\"“”]*[\w.?!,])\" <- option("quotation") -> «\1»\n„\1”\n“\1” # Кавычки.
+\B'(\w[^']*[\w.?!,])'\B <- option("quotation") -> ‘\1’ # Кавычки.
+# "The 'old' boy" -> „The ‘old’ boy”\n«The ‘old’ boy»\n“The ‘old’ boy”
+
+# apostrophe
+
+w \w*
+(?i){Abc}'{w} <- option("quotation") -> {Abc}’{w} # Апостроф.
+# o'clock -> o’clock
+# singers' voices -> singers’ voices
+
+# words
+
+
+# punctuation
+
+{abc}[ ]а[ ] <- option("comma") -> "{abc}, а " # Пропущена запятая перед а.
+{abc}[ ]но[ ] <- option("comma") -> "{abc}, но " # Пропущена запятая перед но.
+
+
+# nopunctuation
+
+"{abc}, {novvod}," <- option("comma") -> "{abc} {novvod}" # Слова, не являющиеся вводными.
+# думали, авось, -> думали авось
+
+
+
+# vvodpunctuation
+
+{abc} {vvod} <- option("comma") -> {abc}, {vvod}, # Слова, являющиеся вводными, выделяются запятыми.
+# дому следовательно -> дому, следовательно,
+
+
+
+# frequent mistakes
+
+\bложить\b <- option("common") -> класть # Общие ошибки
+\bляжь\b <- option("common") -> ляг # Общие ошибки
+\bехай\b <- option("common") -> поезжай # Общие ошибки
+
+\bихн{abc}\b <- option("common") -> их # Притяжательное местоимение не склоняется
+
+
+
+
+# common rules
+жы <- option("common") -> жи # Через "и"
+шы <- option("common") -> ши # Через "и"
+
+# жыр -> жир
+
+
+
+# multiword expressions
+
+
+\bнорд ост\b <- option("hyphen") -> норд-ост\nнордост # Дефис?
+# норд ост -> норд-ост\nнордост # Suggestions separated by new lines (\n)
+
+\bнорд вест\b <- option("hyphen") -> норд-вест\nнордвест # Дефис?
+# норд вест -> норд-вест\nнордвест # Suggestions separated by new lines (\n)
+
+\bсеверо западн{abc}\b <- option("hyphen") -> северо-западн{abc}\nсеверозападн{abc} # Дефис?
+# северо западный -> северо-западный\nсеверозападный # Suggestions separated by new lines (\n)
+
+
+\bюго западн{abc}\b <- option("hyphen") -> юго-западн{abc}\nюгозападн{abc} # Дефис?
+# юго западный -> юго-западный\nюгозападный # Suggestions separated by new lines (\n)
+
+\bсеверо восточн{abc}\b <- option("hyphen") -> северо-восточн{abc}\nсеверовосточн{abc} # Дефис?
+# северо восточный -> северо-восточный\nсеверовосточный # Suggestions separated by new lines (\n)
+
+\bюго восточн{abc}\b <- option("hyphen") -> юго-восточн{abc}\nюговосточн{abc} # Дефис?
+# юго восточный -> юго-восточный\nюговосточный # Suggestions separated by new lines (\n)
+
+
+\b{adv1} нибудь\b <- option("hyphen") -> {adv1}-нибудь # Дефис?
+# что нибудь -> что-нибудь # Suggestions separated by new lines (\n)
+
+\b{adv1} либо\b <- option("hyphen") -> {adv1}-либо # Дефис?
+# что либо -> что-либо # Suggestions separated by new lines (\n)
+
+\b{adv1} то\b <- option("hyphen") -> {adv1}-то # Дефис?
+# кто то -> кто-то # Suggestions separated by new lines (\n)
+
+\bточь в точь\b <- option("hyphen") -> точь-в-точь # Дефис?
+# точь в точь -> точь-в-точь # Suggestions separated by new lines (\n)
+
+\bиз за\b <- option("hyphen") -> из-за # Дефис?
+# из за -> из-за # Suggestions separated by new lines (\n)
+
+\bвсё таки\b <- option("hyphen") -> всё-таки # Дефис?
+# всё таки -> всё-таки # Suggestions separated by new lines (\n)
+
+\bкое кто\b <- option("hyphen") -> кое-кто # Дефис?
+# кое кто -> кое-кто # Suggestions separated by new lines (\n)
+
+\bкое что\b <- option("hyphen") -> кое-что # Дефис?
+# кое что -> кое-что # Suggestions separated by new lines (\n)
+
+\bво что бы то нe стало\b <- option("multiword") -> во что бы то ни стало # Имелось ввиду:
+\bво чтобы то нe стало\b <- option("multiword") -> во что бы то ни стало # Имелось ввиду:
+\bво чтобы то ни стало\b <- option("multiword") -> во что бы то ни стало # Имелось ввиду:
+
+
+\bтакже как и\b <- option("multiword") -> так же как и # Сложный союз.
+
+\bво избежании\b<- option("multiword") -> во избежание # Сложный предлог.
+
+\bравноправны друг другу\b<- option("multiword") -> равноправны друг c другом # Равноправны друг c другом.
+
+\bни кто иной как\b<- option("multiword") -> не кто иной, как # Оборот.
+\bни что иное как\b<- option("multiword") -> не что иное, как # Оборот.
+\bне кто иной как\b<- option("multiword") -> не кто иной, как # Оборот.
+\bне что иное как\b<- option("multiword") -> не что иное, как # Оборот.
+
+
+
+\bникто иной, не\b<- option("multiword") -> никто иной не # Оборот.
+\bничто иное, не\b<- option("multiword") -> ничто иное не # Оборот.
+
+\bнекто иной, не\b<- option("multiword") -> никто иной не # Оборот.
+\bнечто иное, не\b<- option("multiword") -> ничто иное не # Оборот.
+
+
+\bнекто иной не\b<- option("multiword") -> никто иной не # Оборот.
+\bнечто иное не\b<- option("multiword") -> ничто иное не # Оборот.
+
+
+\bне кто иной, не\b<- option("multiword") -> никто иной не # Оборот.
+\bне что иное, не\b<- option("multiword") -> ничто иное не # Оборот.
+
+
+\bне кто иной не\b<- option("multiword") -> никто иной не # Оборот.
+\bне что иное не\b<- option("multiword") -> ничто иное не # Оборот.
+
+
+\bникто иной, не\b<- option("multiword") -> никто иной не # Оборот.
+\bничто иное, не\b<- option("multiword") -> ничто иное не # Оборот.
+
+\bни кто иной, не\b<- option("multiword") -> никто иной не # Оборот.
+\bни что иное, не\b<- option("multiword") -> ничто иное не # Оборот.
+
+
+
+\bкакбудто<- option("together") -> как будто # Составная частица
+
+\bпо мимо\b <- option("together") -> помимо # Пишется слитно
+
+
+
+\bна кануне\b<- option("together") -> накануне # Слитно
+\bна подобие\b<- option("together") -> наподобие # Слитно
+\bна против\b<- option("together") -> напротив # Слитно
+\bв низу\b<- option("together") -> внизу # Слитно
+\bс низу\b<- option("together") -> снизу # Слитно
+\bна верху\b<- option("together") -> наверху # Слитно
+\bв верху\b<- option("together") -> вверху # Слитно
+\bс верху\b<- option("together") -> сверху # Слитно
+\bс верх\b<- option("together") -> сверх # Слитно
+\bс выше\b<- option("together") -> свыше # Слитно
+\bсо гласно\b<- option("together") -> согласно # Слитно
+\bв глубь\b<- option("together") -> вглубь # Слитно
+\bв доль\b<- option("together") -> вдоль # Слитно
+\bв замен\b<- option("together") -> взамен # Слитно
+
+# formats
+
+# Thousand separators: 10000 -> 10,000 (common) or 10 000 (ISO standard)
+
+# definitions
+d \d\d\d # name definition: 3 digits
+d2 \d\d # 2 digits
+D \d|\d\d|\d\d\d # 1, 2 or 3 digits
+
+# ISO thousand separatos: space, here: no-break space (U+00A0)
+\b{d2}{d}\b <- option("numsep") -> {d2} {d} # Добавить разделитель разрядов (ISO)?
+\b{D}{d}{d}\b <- option("numsep") -> {D} {d} {d} # Добавить разделитель разрядов (ISO)?
+\b{D}{d}{d}{d}\b <- option("numsep") -> {D} {d} {d} {d} # Добавить разделитель разрядов (ISO)?
+# 1234567890 -> 1 234 567 890
+
+
+# word duplication
+
+[Word]
+
+W [-\w]{3,}
+
+# within clauses
+
+{W}(?: [-–\w“”]+)* \1 <- option("dup") -> {W} # Повтор слова?
+
+# within sentences
+
+{W}[;,:]?(?: [-–\w“”]+[;,:]?)* \1 <- option("dup2") -> {W} # Повтор слова?
diff --git a/src/ru_RU/ru_RU.dlg b/src/ru_RU/ru_RU.dlg
new file mode 100644
index 0000000..b3b3c1b
--- /dev/null
+++ b/src/ru_RU/ru_RU.dlg
@@ -0,0 +1,66 @@
+# Options and title texts for the Settings and conditional rules
+# for Russian (translated by Yakov Reztsov 2011)
+# The Lightproof dialogs contain only grouped checkboxes.
+#
+# Format of the dialog definition:
+#
+# GroupID: OptionID, OptionID ...
+# Group2ID: OptionID, OptionID ...
+# ...
+# [Language_code=title of the window]
+# OptionID=title of the option
+# Option2ID=title of the option
+#
+# The first language is the default language for other locales
+# (use en_US or the common language of your country)
+#
+# The OptionIDs declared here are used in the rules, too. For example:
+#
+# foo <- option("style") -> bar # bar is far better
+#
+# this rule depends from the state of the "style" checkbox.
+
+# options (starred options are checked)
+
+grammar: *hyphen *comma, *multiword *together
+proofreading: *dup dup2, *common *space, *abbreviation
+others: numsep, *typographica, *quotation
+
+# titles
+
+[en_US=Russian sentence checking]
+
+abbreviation=Abbreviation
+grammar=Grammar
+hyphen=Compound words with hyphen
+comma=Comma usage
+common=General error
+multiword=Multiword expressions
+together=Together/separately
+proofreading=Proofreading
+space=Space mistake
+typographica=Typographica
+dup=Word duplication within clauses
+dup2=Word duplication within sentences
+others=Others
+numsep=Separation of large numbers (ISO)
+quotation=Quotation
+
+[ru_RU=Проверка грамматики (Русский язык)]
+
+abbreviation=Аббревиатуры
+grammar=Грамматика
+hyphen=Дефис
+comma=Пунктуация
+common=Общие ошибки
+multiword=Словосочетания
+together=Слитно/раздельно
+proofreading=Стилистика
+space=Пробел
+typographica=Типографика
+dup=Повтор слов в словосочетаниях
+dup2=Повтор слов в предложениях
+others=Прочее
+numsep=Разделители групп разрядов (ISO) для чисел
+quotation=Кавычки
+