Blob Blame History Raw
# Libreoffice-voikko: Linguistic extension for LibreOffice
# Copyright (C) 2015 Harri Pitkänen <hatapitk@iki.fi>
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at http://mozilla.org/MPL/2.0/.
# 
# Alternatively, the contents of this file may be used under the terms of
# the GNU General Public License Version 3 or later (the "GPL"), in which
# case the provisions of the GPL are applicable instead of those above.

import logging
import unohelper
from com.sun.star.linguistic2 import XHyphenator, XLinguServiceEventBroadcaster
from com.sun.star.lang import XServiceInfo, XInitialization, XServiceDisplayName
from VoikkoHandlePool import VoikkoHandlePool
from HyphenatedWord import HyphenatedWord
from PossibleHyphens import PossibleHyphens
from PropertyManager import PropertyManager

class Hyphenator(unohelper.Base, XServiceInfo, XHyphenator, XLinguServiceEventBroadcaster, XInitialization, XServiceDisplayName):

	def __init__(self, ctx, *args):
		logging.debug("Hyphenator.__init__")

	# From XServiceInfo
	def getImplementationName(self):
		return Hyphenator.IMPLEMENTATION_NAME

	def supportsService(self, serviceName):
		return serviceName in self.getSupportedServiceNames()

	def getSupportedServiceNames(self):
		return Hyphenator.SUPPORTED_SERVICE_NAMES

	# From XSupportedLocales
	def getLocales(self):
		return VoikkoHandlePool.getInstance().getSupportedHyphenationLocales()

	def hasLocale(self, aLocale):
		return VoikkoHandlePool.getInstance().supportsHyphenationLocale(aLocale)

	# From XHyphenator
	def hyphenate(self, word, locale, nMaxLeading, properties):
		logging.debug("Hyphenator.hyphenate")
		if len(word) > 10000:
			return None
		VoikkoHandlePool.mutex.acquire()
		try:
			voikko = VoikkoHandlePool.getInstance().getHandle(locale)
			if voikko is None:
				return None
			PropertyManager.getInstance().setValues(properties)

			minLeading = PropertyManager.getInstance().getHyphMinLeading()
			minTrailing = PropertyManager.getInstance().getHyphMinTrailing()
			wlen = len(word)

			# If the word is too short to be hyphenated, return no hyphenation points
			if wlen < PropertyManager.getInstance().getHyphMinWordLength() or wlen < minLeading + minTrailing:
				PropertyManager.getInstance().resetValues(properties)
				return None

			hyphenationPoints = voikko.getHyphenationPattern(word)
			if hyphenationPoints is None:
				PropertyManager.getInstance().resetValues(properties)
				return None

			# find the hyphenation point
			hyphenPos = -1
			i = wlen - minTrailing # The last generally allowed hyphenation point
			if i > nMaxLeading:
				i = nMaxLeading # The last allowed point on this line
			while i >= minLeading and hyphenPos == -1:
				if word[i] == '\'':
					i = i - 1
					continue
				if hyphenationPoints[i] == '-' or hyphenationPoints[i] == '=':
					hyphenPos = i
					break
				i = i - 1

			# return the result
			PropertyManager.getInstance().resetValues(properties)
			if hyphenPos != -1:
				return HyphenatedWord(word, hyphenPos - 1, locale)
			else:
				return None
		finally:
			VoikkoHandlePool.mutex.release()

	def queryAlternativeSpelling(self, word, locale, index, properties):
		logging.debug("Hyphenator.queryAlternativeSpelling")
		# Implementing this might be necessary, although everything seems to work fine without it.
		return None

	def createPossibleHyphens(self, word, locale, properties):
		logging.debug("Hyphenator.createPossibleHyphens")
		wlen = len(word)
		if wlen > 10000:
			return None
		VoikkoHandlePool.mutex.acquire()
		try:
			voikko = VoikkoHandlePool.getInstance().getHandle(locale)
			if voikko is None:
				return None
			PropertyManager.getInstance().setValues(properties)

			# If the word is too short to be hyphenated, return no hyphenation points
			minLeading = PropertyManager.getInstance().getHyphMinLeading()
			minTrailing = PropertyManager.getInstance().getHyphMinTrailing()
			if wlen < PropertyManager.getInstance().getHyphMinWordLength() or wlen < minLeading + minTrailing:
				PropertyManager.getInstance().resetValues(properties)
				return None

			hyphenationPoints = voikko.getHyphenationPattern(word)
			if hyphenationPoints is None:
				PropertyManager.getInstance().resetValues(properties)
				return None

			hyphenSeq = []
			hyphenatedWord = ""
			for i in range(0, wlen):
				hyphenatedWord = hyphenatedWord + word[i]
				if i >= minLeading - 1 and i < wlen - minTrailing and hyphenationPoints[i + 1] == '-':
					hyphenSeq.append(i)
					hyphenatedWord = hyphenatedWord + "="

			res = PossibleHyphens(word, hyphenatedWord, hyphenSeq, locale)
			PropertyManager.getInstance().resetValues(properties)
			return res
		finally:
			VoikkoHandlePool.mutex.release()

	# From XLinguServiceEventBroadcaster
	def addLinguServiceEventListener(self, xLstnr):
		logging.debug("Hyphenator.addLinguServiceEventListener")
		VoikkoHandlePool.mutex.acquire()
		try:
			return PropertyManager.getInstance().addLinguServiceEventListener(xLstnr)
		finally:
			VoikkoHandlePool.mutex.release()

	def removeLinguServiceEventListener(self, xLstnr):
		logging.debug("Hyphenator.removeLinguServiceEventListener")
		VoikkoHandlePool.mutex.acquire()
		try:
			return PropertyManager.getInstance().removeLinguServiceEventListener(xLstnr)
		finally:
			VoikkoHandlePool.mutex.release()

	# From XInitialization
	def initialize(self, seq):
		pass

	# From XServiceDisplayName
	def getServiceDisplayName(self, locale):
		if locale.Language == "fi":
			return "Tavutus (Voikko)"
		else:
			return "Hyphenator (Voikko)"

Hyphenator.IMPLEMENTATION_NAME = "voikko.Hyphenator"
Hyphenator.SUPPORTED_SERVICE_NAMES = ("com.sun.star.linguistic2.Hyphenator",)