http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SquigglyCustomContainerController.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SquigglyCustomContainerController.as b/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SquigglyCustomContainerController.as deleted file mode 100644 index 9ea0f9a..0000000 --- a/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SquigglyCustomContainerController.as +++ /dev/null @@ -1,258 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// Licensed to the Apache Software Foundation (ASF) under one or more -// contributor license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright ownership. -// The ASF licenses this file to You under the Apache License, Version 2.0 -// (the "License"); you may not use this file except in compliance with -// the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////////// -package com.adobe.linguistics.spelling -{ - import com.adobe.linguistics.spelling.SpellUIForTLF; - import com.adobe.linguistics.spelling.framework.SpellingService; - import com.adobe.linguistics.spelling.ui.IHighlighter; - import com.adobe.linguistics.spelling.ui.IWordProcessor; - import com.adobe.linguistics.spelling.ui.TLFHighlighter; - import com.adobe.linguistics.spelling.ui.TLFWordProcessor; - import com.adobe.linguistics.utils.TextTokenizer; - import com.adobe.linguistics.utils.Token; - - import flash.display.Sprite; - import flash.events.ContextMenuEvent; - import flash.events.Event; - import flash.events.EventDispatcher; - import flash.geom.Point; - import flash.geom.Rectangle; - import flash.ui.ContextMenu; - import flash.ui.ContextMenuItem; - - import flashx.textLayout.compose.StandardFlowComposer; - import flashx.textLayout.compose.TextFlowLine; - import flashx.textLayout.container.ContainerController; - import flashx.textLayout.conversion.TextConverter; - import flashx.textLayout.edit.SelectionManager; - import flashx.textLayout.elements.FlowLeafElement; - import flashx.textLayout.elements.ParagraphElement; - import flashx.textLayout.elements.TextFlow; - import flashx.textLayout.events.CompositionCompleteEvent; - import flashx.textLayout.events.StatusChangeEvent; - import flashx.textLayout.tlf_internal; - - /** Custom container controller for populating context menu and hanlding menu item selection */ - internal class SquigglyCustomContainerController extends ContainerController - { - private var disableMenuItem:ContextMenuItem = new ContextMenuItem("Disable spell checking",true); - private var enableMenuItem:ContextMenuItem = new ContextMenuItem("Enable spell checking"); - - private var controlMenuItemList:Array = new Array(); - private var suggestionMenuItemList:Array = new Array(); - private var _spellingEnabled:Boolean; - private var _contextMenu:ContextMenu; - private var mTextHighlighter:IHighlighter; - private var mWordProcessor:IWordProcessor; - private var mSpellEngine:SpellingService; - private var mTextFlow:TextFlow; - private var _ignoreWordFunctionProcessor:Function; - private var _misspelledToken:Token; - private var _misspelled:String; - - public function SquigglyCustomContainerController(container:Sprite,textHighlighter:IHighlighter, wordProcessor:IWordProcessor, engine:SpellingService, - func:Function, compositionWidth:Number=100,compositionHeight:Number=100) - { - super (container, compositionWidth, compositionHeight); - mTextHighlighter = textHighlighter; - mWordProcessor = wordProcessor; - mSpellEngine = engine; - _ignoreWordFunctionProcessor = func; - - spellingEnabled = true; - } - - /** Overridden to add custom items to the context menu */ - override protected function createContextMenu():ContextMenu - { - // Get the default context menu used by TLF for editable flows - _contextMenu = super.container.contextMenu; - if (_contextMenu == null) - _contextMenu = super.createContextMenu(); - - - enableMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleEnableSpellCheck); - disableMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleDisableSpellCheck); - controlMenuItemList.push(enableMenuItem); - controlMenuItemList.push(disableMenuItem); - - _contextMenu.customItems.push(disableMenuItem); - _contextMenu.customItems.push(enableMenuItem); - - // Listen for menu selection - _contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, updateCustomMenuItems); - - return _contextMenu; - } - - /** Update the state of the custom menu items before the context menu is displayed */ - private function updateCustomMenuItems(event:ContextMenuEvent):void - { - /* Clear the context menu */ - //spellingEnabled= mTextHighlighter.spellingEnabled; - //SpellUI.doSpelling1(); - var removedNum:int = 0; - var count:uint = _contextMenu.customItems.length; - for (var j:uint=count; j>0; j--) { - if ( isWordItem(_contextMenu.customItems[j-1]) ) { - _contextMenu.customItems.splice(j-1,1); - removedNum++ - } - } - if ( removedNum != suggestionMenuItemList.length ) { - trace("internal error"); - } - - - suggestionMenuItemList = new Array(); - - // localized entries - var entries:Object = SpellUIForTLF.getSpellingMenuEntries(); - disableMenuItem.caption = entries.disable; - enableMenuItem.caption = entries.enable; - - if (spellingEnabled == true) { - (mWordProcessor as TLFWordProcessor).textFlowContainerController = this; - - //trace("stageX " + super.container.stage.mouseX); - //trace("stageY " + super.container.stage.mouseY); - //trace("mouseX " + super.container.mouseX); - //trace("mouseY " + super.container.mouseY); - _misspelledToken = mWordProcessor.getWordAtPoint(this.container.mouseX, this.container.mouseY); - if (_misspelledToken==null) return; - var currentLeaf:FlowLeafElement = this.textFlow.findLeaf(_misspelledToken.first); - var currentParagraph:ParagraphElement = currentLeaf ? currentLeaf.getParagraph() : null; - _misspelled = currentParagraph.getText().substring(_misspelledToken.first - currentParagraph.getAbsoluteStart(), - _misspelledToken.last - currentParagraph.getAbsoluteStart()); - if ((_misspelled==null) || (_misspelled == "")) return; - - if (mSpellEngine.checkWord(_misspelled)==true) return; - - var suseAddToItem:ContextMenuItem = new ContextMenuItem(entries.add); - suseAddToItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleAddToItemSelect); - suggestionMenuItemList.push(suseAddToItem); - _contextMenu.customItems.splice(0,0,suseAddToItem); - //var result:Array = mWordProcessor.getSuggestionsAtPoint(); - var resultVector:Vector.<String> = mSpellEngine.getSuggestions(_misspelled); - var result:Array = new Array(); - if (resultVector) { - for each (var w:String in resultVector) - result.push(w); - } - if (result!=null) { - for (var i:int=result.length-1;i>=0;i-- ) { - var suseMenuItem:ContextMenuItem = new ContextMenuItem(result[i]); - suseMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleSuseItemSelect); - suggestionMenuItemList.push(suseMenuItem); - //_contextMenu.customItems.push(suseMenuItem); - _contextMenu.customItems.splice(0,0,suseMenuItem); - } - } - } - } - - private function handleAddToItemSelect(event:ContextMenuEvent):void - { - if ( _ignoreWordFunctionProcessor == null ) return; - - /* - var menuEntry:String = (event.currentTarget as ContextMenuItem).caption; - var start:uint = 5; - var end:uint = menuEntry.length - 15; - var word:String = menuEntry.substring(start, end); - */ - _ignoreWordFunctionProcessor(_misspelled); - SpellUIForTLF.UITable[SpellUIForTLF.parentComp[super.textFlow]].doSpellingJob(); - } - - private function handleSuseItemSelect(event:ContextMenuEvent):void - { - mWordProcessor.replaceText(_misspelledToken, (event.currentTarget as ContextMenuItem).caption ); - SpellUIForTLF.UITable[SpellUIForTLF.parentComp[super.textFlow]].doSpellingJob(); - } - - private function set spellingEnabled(value:Boolean) :void { - _spellingEnabled = value; - disableMenuItem.visible=spellingEnabled; - enableMenuItem.visible=!spellingEnabled; - } - private function get spellingEnabled():Boolean { - return this._spellingEnabled; - } - - private function isWordItem(item:ContextMenuItem):Boolean { - - for ( var i:int=0; i<suggestionMenuItemList.length; ++i ) { - if ( suggestionMenuItemList[i] == item ) return true; - } - return false; - } - - private function isControlItem(item:ContextMenuItem):Boolean { - for (var i:int=0; i<controlMenuItemList.length; ++i) { - if ( controlMenuItemList[i] == item) return true; - } - return false; - } - - private function handleEnableSpellCheck(event:ContextMenuEvent):void - { - spellingEnabled= true; - //mTextHighlighter.spellingEnabled= spellingEnabled; - //SpellUI.doSpellingJob(); - //dispatchEvent(new Event(Event.RENDER)); - - SpellUIForTLF.UITable[SpellUIForTLF.parentComp[this.textFlow]].spellingEnabled = spellingEnabled; - SpellUIForTLF.UITable[SpellUIForTLF.parentComp[this.textFlow]].doSpellingJob(); - //spellCheckRange(getValidFirstWordIndex(), getValidLastWordIndex()); - } - private function handleDisableSpellCheck(event:ContextMenuEvent):void - { - spellingEnabled= false; - SpellUIForTLF.UITable[SpellUIForTLF.parentComp[this.textFlow]].spellingEnabled = spellingEnabled; - mTextHighlighter.clearSquiggles(); - } - - public function cleanUpContextMenu():void - { - mTextHighlighter=null; - mWordProcessor=null; - spellingEnabled = false; - _ignoreWordFunctionProcessor=null; - - _contextMenu.removeEventListener(ContextMenuEvent.MENU_SELECT, updateCustomMenuItems); - - var removedNum:int = 0; - var count:uint = _contextMenu.customItems.length; - for (var j:uint=count; j>0; j--) { - if ( isWordItem(_contextMenu.customItems[j-1]) || isControlItem(_contextMenu.customItems[j-1]) ) { - _contextMenu.customItems.splice(j-1,1); - removedNum++ - } - } - if ( removedNum != suggestionMenuItemList.length + controlMenuItemList.length ) { - trace("internal error"); - } - - suggestionMenuItemList = null; - controlMenuItemList = null; - } - - } -} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as b/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as new file mode 100644 index 0000000..e40772d --- /dev/null +++ b/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as @@ -0,0 +1,76 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + + + +package com.adobe.linguistics.utils +{ + /** + * The <code>ITokenizer</code> Interface. + * This interface defines default methods which will be used for Adobe Linguistic Service. + * Be independent from any UI component or be able to adapt to a given UI component. + * Provide or define standardized way so that third-party can switch to their tokenizer. + * Be able to use for any given language either by some kind of language specific handling or by some kind of unified logic for any given language. + * More sophisticated implementations can be done for particular locales or environments in an application by implementing this interface. + + * @playerversion Flash 10 + * @langversion 3.0 + */ + public interface ITokenizer + { + + /** + * Return the first word in the text being scanned. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + function getFirstToken():Token; + + /** + * Return the last word in the text being scanned. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + function getLastToken():Token; + + /** + * Determine the next word following the current token. + * + * Return the token of the next word or <code>lastToken</code> object if all word have been returned. + * @param token A <code>Token</code> object to be used for determining next word. + * @playerversion Flash 10 + * @langversion 3.0 + */ + function getNextToken(token:Token):Token; + + /** + * Determine the previous word preceding the current token. + * + * Return the token of the previous word or <code>firstToken</code> object if all word have been returned. + * @param token A <code>Token</code> object to be used for determining previous word. + * @playerversion Flash 10 + * @langversion 3.0 + */ + function getPreviousToken(token:Token):Token; + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as b/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as new file mode 100644 index 0000000..596481c --- /dev/null +++ b/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as @@ -0,0 +1,393 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.utils +{ + import __AS3__.vec.Vector; + + import flash.utils.Dictionary; + + import flash.text.engine.TextBlock; + import flash.text.engine.TextElement; + import flash.text.engine.ElementFormat; + + + /** + * <p>The <code>TextTokenizer</code> class locates the boundaries of words in a + * block of text.</p> + * + * Word boundary locations are found according to these general principles: + * <ul> + * <li> Be able to tokenize a block of text specified by start and end positions </li> + * <li> Default separator is Unicode white space character. Also break on newlines </li> + * <li> Tokens consist of either words or numbers in which case it may include commas, etc.. </li> + * <li> Apostrophes or hyphens within a word are kept with the word </li> + * <li> Punctuation, spaces and other characters that are not part of a token, are broken out separately </li> + * </ul> + * <p>In the future versions, this class would also provide a way for the developers to customize the separators used by the tokenizer. </p> + * + * @playerversion Flash 9.x + * @langversion 3.0 + */ + public class TextTokenizer implements ITokenizer + { + + + private var _textBlock:TextBlock; + private var _textHolder:String; + private var _startIndex:int; + private var _endIndex:int; + private var _firstToken:Token; + private var _lastToken:Token; + + private var _ignoredCharactersDict:Dictionary = new Dictionary(); + + + /** + * The tokenizer for a String object. + * This class implements the ITokenizer interface. + * Constructs a new TextTokenizer object to break String to words by creating with a new piece of text. + * @param textHolder A <code>String</code> object to hold the text which will be processed by this tokenizer. + * @param startIndex A <code>int</code> type input to hold the starting index of input text should be scanned. + * @param endIndex A <code>int</code> type input to hold the ending index of input text should be scanned. + * <span class="hide"> TODO param requestedLocaleIDName The LocaleID name to be used by this TextTokenizer object. </span> + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function TextTokenizer(textHolder:String, startIndex:int=0, endIndex:int=int.MAX_VALUE)//, requestedLocaleIDName:String=null) + { + //requestedLocaleIDName parameter is useful for potential extension. won't handle it in the first round of implementation. + // same comments for API: requestedLocaleIDName()/actualLocaleIDName()/getAvailableLocaleIDNames() + var textElement:TextElement = new TextElement(textHolder, new ElementFormat()); + var textBlock:TextBlock = new TextBlock(); + textBlock.content = textElement; + + /* init a tokenizer object */ + this._textBlock = textBlock; + this._textHolder = textHolder; + this._startIndex = 0; + this._endIndex = this._textBlock.content.text.length; + initDefaultIgnoredCharacters(); + setStartIndex(startIndex); + setEndIndex(endIndex); + + } + + private function setStartIndex(value:int):void { + if ( value <= 0 ) + this._startIndex = 0; + else if ( value >= this._endIndex ) + this._startIndex = this._endIndex; + else + this._startIndex=value; + } + + // strange behaviour with String.substring() function... need more thinking.... + private function setEndIndex(value:int):void { + if ( value >= this._textBlock.content.text.length ) + this._endIndex = this._textBlock.content.text.length; + else if ( value <= this._startIndex ) + this._endIndex = this._startIndex; + else + this._endIndex = value; + } + + private function initDefaultIgnoredCharacters():void { + var ignoredCharsArray:Array = [ + 0x002d, + 0x2010 + ]; + var ignoredChars:String = ""; + for ( var i:int=0; i< ignoredCharsArray.length; ++i ) { + ignoredChars=ignoredChars+String.fromCharCode(ignoredCharsArray[i]); + } + this.ignoredCharacters = ignoredChars; + } + + private function getNextTokenByIndex( startPos:int ):Token{ + var resultToken:Token = null; + /* calculate first token and return it. */ + var i:int = (startPos > this._startIndex) ? startPos: this._startIndex; + while ( i< this._endIndex ) { + var begin:int = i; + i = this._textBlock.findNextWordBoundary(begin); + var end:int = ( i <= this._endIndex) ? i : this._endIndex; + if ( !isSingleSpecialCharacter( this._textHolder.substring(begin,end) ) ) { + resultToken = new Token(begin,end); + break; + } + } + if ( resultToken==null ) resultToken = this.getLastToken(); + return resultToken; + } + + private function getPreviousTokenByIndex( endPos:int):Token { + var resultToken:Token = null; + /* calculate first token and return it. */ + var i:int = (endPos < this._endIndex) ? endPos: this._endIndex; + + /* special handling for last element in the word, bof */ + var specialHandling:Boolean = false; + if ( i == this._endIndex ) { + specialHandling = true; + i = this._endIndex -1; + } + /* special handling for last element in the word, eof */ + + while ( i > this._startIndex ) { + var end:int = i; + i = this._textBlock.findPreviousWordBoundary(end); + var begin:int = ( i > this._startIndex) ? i : this._startIndex; + + /* special handling for last element in the word, bof */ + if ( specialHandling ) { + end = (this._textBlock.findNextWordBoundary(begin)<this._endIndex) ?this._textBlock.findNextWordBoundary(begin):this._endIndex; + specialHandling=false; + if ( (end != this._endIndex) && !isSingleSpecialCharacter(this._textHolder.substring(this._endIndex-1,this._endIndex)) ) { + begin = this._endIndex-1; + i=begin; + end = this._endIndex; + } + } + /* special handling for last element in the word, eof */ + + if ( !isSingleSpecialCharacter( this._textHolder.substring(begin,end) ) ) { + resultToken = new Token(begin,end); + break; + } + } + if ( resultToken==null ) resultToken = this.getFirstToken(); + return resultToken; + } + + private function isExceptionCharacter(word:String):Boolean { + if ( word.length != 1 ) return false; + if ( this._ignoredCharactersDict[word] == true ) return true; + return false; + } + + private function getNextFilteredTokenByIndex(startPos:int):Token { + var token:Token = getNextTokenByIndex(startPos); + var firstToken:Token = token; + var cursor:int=token.last+1; + + while ( (cursor < this._endIndex) ) { + if ( !isExceptionCharacter(this._textHolder.substring(cursor-1,cursor)) ) { + break; + }else { + //another request from Harish about handling case abc\\abc abc\.abc case...not 100% sure about the correct behavior... + /*bof*/ + while( cursor < this._endIndex && isExceptionCharacter(this._textHolder.substring(cursor-1,cursor)) ) { + cursor++; + } + cursor--; + /*eof*/ + } + token = getNextTokenByIndex(cursor); + if ( token.first != cursor ) { + token = firstToken; + break; + } + token.first=firstToken.first; + firstToken = token; + cursor = token.last+1; + } + return token; + } + + private function getPreviousFilteredTokenByIndex(endPos:int):Token { + var token:Token = getPreviousTokenByIndex(endPos); + var lastToken:Token = token; + var cursor:int=token.first-1; + + while ( ( cursor > this._startIndex ) ) { + if ( !isExceptionCharacter(this._textHolder.substring(cursor,cursor+1)) ) { + break; + }else { + //another request from Harish about handling case abc\\abc abc\.abc case...not 100% sure about the correct behavior... + /*bof*/ + while( cursor > this._startIndex && isExceptionCharacter(this._textHolder.substring(cursor,cursor+1)) ) { + cursor--; + } + cursor++; + /*eof*/ + } + token = getPreviousTokenByIndex(cursor); + if ( token.last != cursor ) { + token = lastToken; + break; + } + token.last=lastToken.last; + lastToken = token; + cursor = token.first-1; + } + return token; + } + + private function isSingleSpecialCharacter(word:String):Boolean{ + if ( word.length != 1 ) return false; + if ( word.toLocaleLowerCase() == word.toLocaleUpperCase() ) return true; + return false; + } + + /** + * Set all of ignored separators to this tokenizer class. + * + * A vector of int containing all of ignored separators code point which are used by this class. + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function set ignoredSeparators(characters:Vector.<int>):void { + if ( characters == null || characters.length==0 ) return; + this._ignoredCharactersDict = new Dictionary(); + for ( var i:int =0;i<characters.length;++i) { + this._ignoredCharactersDict[String.fromCharCode(characters[i])]=true; + } + } + + /** + * Get all of ignored separators used by this tokenizer class. + * + * A vector of int containing all of ignored separators code point which are used by this class. + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function get ignoredSeparators():Vector.<int>{ + var result:Vector.<int> = new Vector.<int>(); + for ( var key:String in _ignoredCharactersDict) { + result.push(key.charCodeAt(0) ); + } + return result; + + } + + private function set ignoredCharacters(value:String ) :void { + if( value == null || value == "" ) return; + var charArr:Array = value.split(""); + this._ignoredCharactersDict = new Dictionary(); + for ( var i:int = 0;i< charArr.length;++i) { + this._ignoredCharactersDict[charArr[i]]=true; + } + } + + private function get ignoredCharacters():String { + var result:String = ""; + for ( var key:String in _ignoredCharactersDict) { + result +=key; + } + return result; + } + + /** + * The name of the requested locale ID that was passed to the constructor of this TextTokenizer object. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ /* + public function get requestedLocaleIDName():String { + return null; + } + + + /** + * The name of the actual locale ID used by this TextTokenizer object. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ /* + public function get actualLocaleIDName():String { + return null; + } + + /** + * Lists all of the locale ID names supported by this class. + * + * A vector of strings containing all of the locale ID names supported by this class. + * @playerversion Flash 10 + * @langversion 3.0 + */ /* + public static function getAvailableLocaleIDNames():Vector.<String>{ return null;} +*/ + /** + * Return the first word in the text being scanned. + * <p> NOTE: In a special case when there are no valid tokens in text, it returns a pseudo token having first and last index set to int.MAX_VALUE. As a result<code> firstToken().first </code>equals int.MAX_VALUE and<code> firstToken().last </code>equals int.MAX_VALUE.</p> + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function getFirstToken():Token { + + /* return the cached one. */ + if ( this._firstToken != null ) + return this._firstToken; + + /* calculate first token and return it. */ + //this._firstToken = getNextTokenByIndex(this._startIndex); // without any filter from LS, directly use FTE tokenizer... + this._firstToken = getNextFilteredTokenByIndex(this._startIndex); + + return this._firstToken; + } + + /** + * @private + * Return the last word in the text being scanned. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function getLastToken():Token { + /* return the cached one. */ + if ( this._lastToken != null ) + return this._lastToken; + + /* calculate last token and return it. */ + this._lastToken = new Token(int.MAX_VALUE,int.MAX_VALUE); + return this._lastToken; + } + + /** + * Determine the next word following the current token. + * + * <p>Returns the token of the next word.</p><p> NOTE: When there are no more valid tokens, it returns a pseudo token having first and last index set to int.MAX_VALUE. As a result<code> getNextToken().first </code>equals int.MAX_VALUE and<code> getNextToken().last </code>equals int.MAX_VALUE.</p> + * @param token A <code>Token</code> object to be used for determining next word. + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function getNextToken(token:Token):Token { + //return getNextTokenByIndex(token.last); // without any filter from LS, directly use FTE tokenizer... + return getNextFilteredTokenByIndex(token.last); + } + + /** + * Determine the word preceding the current token. + * + * <p>Returns the token of the previous word or<code> getFirstToken </code>object if there is no preceding word.</p> + * @param token A <code>Token</code> object to be used for determining previous word. + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function getPreviousToken(token:Token):Token { + //return getPreviousTokenByIndex( token.first );// without any filter from LS, directly use FTE tokenizer... + return getPreviousFilteredTokenByIndex( token.first ) + } + + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/Token.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/Token.as b/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/Token.as new file mode 100644 index 0000000..27fcfb2 --- /dev/null +++ b/Squiggly/main/LinguisticUtils/src/com/adobe/linguistics/utils/Token.as @@ -0,0 +1,94 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + + + +package com.adobe.linguistics.utils +{ + /** + * A Token is an occurrence of a word in a block of text. It consists of the start and end offset of the word in the block of text. + * The start and end offsets permit applications to re-associate a token with its source text, e.g., to display highlighted misspelled word in + * a block of text. + * @playerversion Flash 10 + * @langversion 3.0 + */ + public class Token + { + private var _first:uint; + private var _last:uint; + + /** + * The Token class. + * Constructs a Token with first and last offsets. . + * @param first A <code>int</code> type input to point start offset in the source text. + * @param last A <code>int</code> type input to point end offset in the source text. + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function Token(inFirst:int, inLast:int) + { + _first = inFirst; + _last = inLast; + + } + + /** + * Set the start offset in the source text. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function set first(value:int):void { + _first=value; + } + + /** + * Return the start offset in the source text. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function get first():int + { + return _first; + } + + /** + * Set the end offset in the source text. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function set last(value:int):void { + _last = value; + } + + /** + * Return the end offset in the source text. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function get last():int + { + return _last; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/HunspellDictionary.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/HunspellDictionary.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/HunspellDictionary.as new file mode 100644 index 0000000..7ec0312 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/HunspellDictionary.as @@ -0,0 +1,205 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling +{ + import com.adobe.linguistics.spelling.core.LinguisticRule; + import com.adobe.linguistics.spelling.core.SquigglyDictionary; + import com.adobe.linguistics.spelling.core.utils.LinguisticRuleLoader; + import com.adobe.linguistics.spelling.core.utils.SquigglyDictionaryLoader; + + import flash.errors.IllegalOperationError; + import flash.events.ErrorEvent; + import flash.events.Event; + import flash.events.EventDispatcher; + import flash.events.IOErrorEvent; + import flash.events.SecurityErrorEvent; + + /** + * + * This class enables creation and loading of spelling metadata including rules and dictionary data + * + * @playerversion Flash 10 + * @langversion 3.0 + * @includeExample Examples/Air/CheckWord/src/CheckWord.mxml -noswf + */ + + public final class HunspellDictionary extends EventDispatcher implements ISpellingDictionary + { + private var _dict:SquigglyDictionary; + private var _attrMgr:LinguisticRule; + private var _rulePath:String; + private var _dictionaryPath:String; + + private var ruleLoader:LinguisticRuleLoader = new LinguisticRuleLoader(); + private var dictLoader:SquigglyDictionaryLoader = new SquigglyDictionaryLoader(); + + private var _loaded:Boolean; + + //adding vars for loading dictionaries in parts + private var _enableDictionarySplit:Boolean; + private var _wordsPerDictionarySplit:int; + + /** + * Constructs a new <code>HunspellDictionary</code> which can later be used by a <code>SpellChecker</code> object. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function HunspellDictionary() + { + _attrMgr = null; + _dict = null; + _rulePath = null ; + _dictionaryPath = null; + _loaded = false; + //giving default values in case user does not want to specify these + _enableDictionarySplit =false; + _wordsPerDictionarySplit= 20000; + + } + + /** + @private + (This property is for Squiggly Developer use only.) + */ + public function get linguisticRule():LinguisticRule { + return _attrMgr; + } + + /** + @private + (This property is for Squiggly Developer use only.) + */ + public function get squigglyDictionary():SquigglyDictionary { + return _dict; + } + + /** + * Loads a Hunspell dictionary and corresponding rules files as specified by the <code>dictionaryURL</code> and the <code>rulesURL</code>. + * + * <p>The actual loading is done asynchronously and + * the <code>HunspellDictionary</code> object will dispatch an <code>Event.COMPLETE</code> event. + * When an error condition occurs, it will dispatch an <code>IOErrorEvent.IO_ERROR</code> event.</p> + * @param rulesURL The URL of rule file to be loaded. + * @param dictionaryURL The URL of Dictionary file to be loaded. + * @playerversion Flash 10 + * @langversion 3.0 + * @example The following code shows how load API is called to load a Rule and Dictionary file to create a HunspellDictionay. + * <listing version="3.0"> + * private var _newdict:HunspellDictionary = new HunspellDictionary(); + * _newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic"); + * </listing> + */ + public function load(rulesURL:String, dictionaryURL:String):void { + if ( rulesURL == null || dictionaryURL == null ) { + throw new IllegalOperationError("load function did not receive two valid URLs."); + } + _rulePath = rulesURL; + _dictionaryPath = dictionaryURL; + + ruleLoader.addEventListener(Event.COMPLETE,loadRuleComplete); + ruleLoader.addEventListener(IOErrorEvent.IO_ERROR,handleError); + ruleLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,handleError); + ruleLoader.load( _rulePath); + + } + + /** + * A flag that indicates if the dictionary has finished loading. + * + * @return <code>true</code> if loading is completed. <code>false</code> if loading has not completed. + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function get loaded():Boolean + { + return _loaded; + } + + + // Private method to dispatch complete Event. + private function loadRuleComplete(evt:Event):void { + _attrMgr = ruleLoader.linguisticRule; + + dictLoader.linguisticRule = _attrMgr; + dictLoader.addEventListener(Event.COMPLETE,loadDictionaryComplete); + dictLoader.addEventListener(IOErrorEvent.IO_ERROR,handleError); + dictLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,handleError); + dictLoader.load(_dictionaryPath, _enableDictionarySplit, _wordsPerDictionarySplit); + } + + // Private method to dispatch complete Event. + private function loadDictionaryComplete(evt:Event):void { + _dict = dictLoader.squigglyDictionary; + _loaded = true; + dispatchEvent(new Event(Event.COMPLETE)); + } + + //Private method to dispatch an error event. + private function handleError(evt:Event):void { + bounceEvent(evt); + } + + private function bounceEvent(evt:Event):void { + dispatchEvent(evt.clone()); + } + + /** + * This is a flag that enables/disables loading of dictionary in splits. + * By default this flag is set to <code>false</code>. In case the initial loading time of dictionaries is found slow, this flag should be set to <code>true</code>. By enabling this, squiggly will load dictionary in splits with each split having <code>wordsPerDictionarySplit</code> number of words. + * <p>NOTE: This property, if used, should be set before calling <code>HunspellDictionary.load</code>. Once <code>HunspellDictionary.load</code> is called dictionaries will be loaded according to default values, and this property will not be used. </p> + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function get enableDictionarySplit():Boolean + { + return _enableDictionarySplit; + } + + public function set enableDictionarySplit(enableDictionarySplit:Boolean):void + { + _enableDictionarySplit = enableDictionarySplit; + } + + /** + * This property defines the number of words in one dictionary split. + * By default the value of this property is set to 20000 words. This property is used only if <code>enableDictionarySplit</code> is set to <code>true</code>. If <code>enableDictionarySplit</code> is set to <code>flase</code> this property turns void. + * <p>NOTE: This property, if used, should be defined before calling <code>HunspellDictionary.load</code>. Once <code>HunspellDictionary.load</code> is called dictionaries will be loaded according to default values, and this property will not be used. </p> + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function get wordsPerDictionarySplit():int + { + + return _wordsPerDictionarySplit; + } + + public function set wordsPerDictionarySplit(wordsPerDictionarySplit:int):void + { + if(wordsPerDictionarySplit<=0){ + //Do error Handling + throw new IllegalOperationError("wordsPerDictionarySplit should be a positive non-zero value."); + } + _wordsPerDictionarySplit = wordsPerDictionarySplit; + } + } + +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/ISpellChecker.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/ISpellChecker.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/ISpellChecker.as new file mode 100644 index 0000000..34917bd --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/ISpellChecker.as @@ -0,0 +1,62 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +package com.adobe.linguistics.spelling +{ + /** + * Interface for actual SpellChecker class implementations + * + * <p>If a new SpellChecker class is created, it must implement the methods and properties defined by this interface. + * The <code>SpellChecker</code> class implements this interface.</p> + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public interface ISpellChecker + { + /** + * Spellchecks a word. + * + * @param word A string containing a word. + * <p><strong>Note: </strong>Please be aware that it is the caller's responsibility to break down sentences into words that can be handled by this method. + * For example, this method does not support punctuation marks such as comma, colon, quotes, etc. + * Punctuation marks should be stripped out from the word prior to calling this method.</p> + * @return <code>true</code> if the word is properly spelled. <code>false</code> if the word is misspelled. + * + * @includeExample Examples/Flex/CheckWord/src/CheckWord.mxml + * @playerversion Flash 10 + * @langversion 3.0 + */ + function checkWord(word:String):Boolean; + + /** + * Gets suggestions for a misspelled word. + * + * @param word A string containing a misspelled word. + * <p>A properly spelled word does not generate any suggestions.</p> + * @return A list of suggestions. + * If the input word is properly spelled, an empty list will be returned.</p> + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + function getSuggestions(word:String):Array; + + } +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/ISpellingDictionary.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/ISpellingDictionary.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/ISpellingDictionary.as new file mode 100644 index 0000000..8a46ef4 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/ISpellingDictionary.as @@ -0,0 +1,45 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling +{ + import com.adobe.linguistics.spelling.core.LinguisticRule; + import com.adobe.linguistics.spelling.core.SquigglyDictionary; + public interface ISpellingDictionary + { + + /** + * @private + * (This property is for Squiggly Developer use only.) + * @playerversion Flash 10 + * @langversion 3.0 + */ + function get linguisticRule():LinguisticRule; + + /** + * @private + * (This property is for Squiggly Developer use only.) + * @playerversion Flash 10 + * @langversion 3.0 + */ + function get squigglyDictionary():SquigglyDictionary; + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/SpellChecker.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/SpellChecker.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/SpellChecker.as new file mode 100644 index 0000000..bc23a91 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/SpellChecker.as @@ -0,0 +1,387 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling +{ + import com.adobe.linguistics.spelling.core.*; + + /** + * The spelling engine. + * + * <p>This class implements the <code>ISpellChecker</code> interface. + * This class performs spell-checking and generates suggestion lists for misspelled words. + * This class does not include any user-interface elements. Use this class if you want to offer + * control over how all upper case words are handled or words with numbers are handled, as this + * level of control is not offered by the SpellUI class. However, please keep in mind that if + * you use this class, you will need to write your own UI.</p> + * + * <p>This class is based on the Hunspell algorithm and works with Hunspell/MySpell + * dictionaries and corresponding language rules files.</p> + * <p>Currently, we support a subset of Hunspell rules(options). </p> + * <p>The future of this class is to align as much as possible with existing Hunspell solution + * both for the algorithms and the content. </p> + * <p>In this version, users can also directly load Open-Office dictionaries to HunspellDictionary + * class and initialize a SpellChecker instance with this HunspellDictionary object. When using this + * class, the language of use is implied by the dictionary supplied. Please make sure you load the + * appropriate dictionary based on the language the user selects to input.</p> + * + * <p>Note: In the current implementation, only one main dictionary can be used at a time. In addition, + * in this version, suggestions for misspelled words do not include words from the user dictionary.</p> + * + * @includeExample Examples/Flex/TextEditor/src/TextEditor.mxml -noswf + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public class SpellChecker implements ISpellChecker + { + private var _spellingEngine:SquigglyEngine; + private var _rule:LinguisticRule; + private var _dict:SquigglyDictionary; + + private var _udEngine:UserDictionaryEngine; + + /** + * Constructs a new <code>SpellChecker</code> object that performs language sensitive spell checking. + * + * @param spellingDictionary A <code>ISpellingDictionary</code> interface to be used by this <code>SpellChecker</code>. + * For example, you can pass a <code>HunspellDictonary</code> object which already implemented the <code>ISpellingDictionary</code> interface to this constructor. + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function SpellChecker(spellingDictionary:ISpellingDictionary) + { + _rule = spellingDictionary.linguisticRule; + _dict = spellingDictionary.squigglyDictionary; + _spellingEngine = new SquigglyEngine(_rule,_dict); + _spellingEngine.fastMode = true; + _udEngine = new UserDictionaryEngine(); + } + + /** + * Add a user dictionary to the SpellChecker. + * + * @return <code>true</code> if the operation is successful. <code>false</code> if the operation failed. + * @param userDictionary A <code>UserDictionary</code> object to be added to this <code>SpellChecker</code>. + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function addUserDictionary(userDictionary:UserDictionary):Boolean + { + return _udEngine.addDictionary(userDictionary.internalUserDictionary); + } + + /** + * Remove a user dictionary from the SpellChecker. + * + * @return <code>true</code> if the operation is successful. <code>false</code> if the operation failed. + * @param userDictionary A <code>UserDictionary</code> object to be removed from this <code>SpellChecker</code>. + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function removeUserDictionary(userDictionary:UserDictionary):Boolean + { + return _udEngine.removeDictionary(userDictionary.internalUserDictionary); + } + + + /** + * Spellchecks a word. + * + * @param word A string containing a word. + * <p><strong>Notes:</strong></p> + * <ul> + * <li> + * Please be aware that it is the caller's responsibility to break down sentences into words that can be handled by this method. + * For example, this method does not support punctuation marks such as comma, colon, quotes, etc. + * Punctuation marks should be stripped out from the word prior to calling this method. + * If a word contains white spaces (such as a regular space or non-breaking space), the word will be considered as misspelled. + * </li> + * </ul> + * @return <code>true</code> if the word is properly spelled. <code>false</code> if the word is misspelled. + * + * @includeExample Examples/Flex/CheckWord/src/CheckWord.mxml -noswf + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function checkWord(word:String):Boolean + { + return (_spellingEngine==null)? false:(_udEngine.spell(word) || _spellingEngine.spell(word)); + } + + /** + * Gets suggestions for a misspelled word. + * + * @param word A string containing a misspelled word. + * + * @return A list of suggestions. <p>Up to ten suggestions may be returned.</p> + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function getSuggestions(word:String):Array + { + return (_spellingEngine==null)? null:_spellingEngine.suggest(word); + } + + + /** @private + * The version of this <code>SpellChecker</code> class. + * + * <p>Example: "0.3"</p> + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public static function get version():String + { + return "0.5"; + } + + + + /** + * This property controls if Title Case Words should be considered as properly spelled. + * + * <p>The default value is <code>false</code>.</p> + * + * <p>If <code>ignoreTitleCase</code> is set to <code>true</code>, any words with first character capped are always considered as properly spelled.</p> + * <p>If <code>ignoreWordWithTitleCase</code> is set to <code>true</code>, "Spel" will be considered as properly spelled even if the dictionary does not contain "spel" or "Spel". + * If <code>ignoreWordWithTitleCase</code> is set to <code>false</code>, "Spel" will be considered as mispelled unless the dictionary contain "Spel".</p> + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + private function get ignoreWordWithTitleCase():Boolean + { + return _spellingEngine.ignoreCappedWord; + } + private function set ignoreWordWithTitleCase(value:Boolean):void + { + _spellingEngine.ignoreCappedWord = value; + } + + /** + * This property controls if words in all upper case should be considered as properly spelled or not. + * + * <table class="innertable"> + * <tr> + * <td align="center"><strong><code>ignoreWordWithAllUpperCase</code></strong></td> + * <td align="center"><strong> </strong></td> + * <td align="center"><strong>Description</strong></td> + * </tr> + * <tr> + * <td><code>false</code></td> + * <td>Default</td> + * <td><p>Words with all characters in upper case are checked against the dictionary for proper spelling.</p> + * <p>Example: if <code>ignoreWordWithAllUpperCase = false</code>, "MISPEL" will be checked for proper spelling.</p></td> + * </tr> + * <tr> + * <td><code>true</code></td> + * <td> </td> + * <td><p>Any words with all characters in upper case are always considered as properly spelled, + * no matter whether the word is in the dictionary or not.</p> + * <p>Example: if <code>ignoreWordWithAllUpperCase = true</code>, "MISPEL" will be considered as properly spelled.</p></td> + * </tr> + * </table> + * + * <!-- + * <p>Following table contains some examples to show how this property works.</p> + * <p>Assumption: <code>ignoreWordWithTitleCase</code> = <code>false</code></p> + * <table class="innertable"> + * <tr> + * <td rowspan=2 align="center"><strong>Word in dictionary</strong></td> + * <td rowspan=2 align="center"><strong>Input word</strong></td> + * <td colspan=2 align="center"><strong><code>ignoreWordWithAllUpperCase</code></strong></td> + * </tr> + * <tr> + * <td align="center"><strong><code>false</code></strong></td> + * <td align="center"><strong><code>true</code></strong></td> + * </tr> + * <tr> + * <td rowspan="4">apple</td> + * <td>apple</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>APPLE</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>Apple</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>aPPLe</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td rowspan="4">NATO</td> + * <td>nato</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>NATO</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>Nato</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>NaTo</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td rowspan="4">London</td> + * <td>london</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>LONDON</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>London</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>LoNDoN</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td rowspan="4">iPhone</td> + * <td>iphone</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>IPHONE</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>IPhone</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * <tr> + * <td>iPHoNe</td> + * <td>Properly spelled</td> + * <td>Properly spelled</td> + * </tr> + * </table> + * --> + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function get ignoreWordWithAllUpperCase():Boolean + { + return _spellingEngine.ignoreAllUpperCase; + } + public function set ignoreWordWithAllUpperCase(value:Boolean):void + { + _spellingEngine.ignoreAllUpperCase = value; + } + + + /** + * This property controls if words with numbers, such as windows95, should be considered as properly spelled. + * + * <table class="innertable"> + * <tr> + * <td align="center"><strong><code>ignoreWordWithNumber</code></strong></td> + * <td align="center"><strong> </strong></td> + * <td align="center"><strong>Description</strong></td> + * </tr> + * <tr> + * <td><code>false</code></td> + * <td>Default</td> + * <td><p>Any words containing digits are checked for proper spelling.</p> + * <p>Example: If <code>ignoreWordWithNumber</code> = <code>false</code>, "mispel99" will be checked for proper spelling.</p> + * </td> + * </tr> + * <tr> + * <td><code>true</code></td> + * <td> </td> + * <td><p>Words containing digits are always ignored/skipped regardless of the dictionary.</p> + * <p>Example: If <code>ignoreWordWithNumber</code> = <code>true</code>, "mispel99" will be considered as properly spelled.</p> + * </td> + * </tr> + * </table> + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function get ignoreWordWithNumber():Boolean + { + return _spellingEngine.ignoreWordWithNumber; + } + public function set ignoreWordWithNumber(value:Boolean):void + { + _spellingEngine.ignoreWordWithNumber = value; + } + + + /** + * <span class="hide"> + * TODO: Decide this block based API. + * Check a block of text and find out all misspelled words in the text. + * + * + * @param text A string containing a block of texts. + * @param separators An array of separators. + * + * @return An Array of misspelled word tokens, each token contains the startIndex and length + * + * @playerversion Flash 10 + * @langversion 3.0 + * + * Option 1: + * + * public function checkText(text:String, separators:Array):Array + * { + * } + * + * Option 2: + * + * public function checkText(text:String, tokenizer:ITokenizer):SpellResultIterator + * { + * } + * </span> + */ + } +} + http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as new file mode 100644 index 0000000..d22f42c --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as @@ -0,0 +1,113 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +package com.adobe.linguistics.spelling +{ + import __AS3__.vec.Vector; + + import com.adobe.linguistics.spelling.UserDictionaryInternal; + /** + * Represents a user dictionary. + * + * <p>This class represents a user dictionary that is used by the <code>SpellingService</code> class. This class itself is an in-memory object + * and doesn't store persistent data. However, developers can import/export a <code>UserDictionary</code> object from/to a vector of String, + * and use other flash classes to keep the data persistent. You may want to consider using one of the following options for permanent storage: + * + * <ul> + * <li>SharedObject, which is used in our SpellingUI class to store words added from the ContextMenu</li> + * <li>File/FileStream, which is used in our UserDictionaryExample and can be shared across AIR applications</li> + * <li>Server side storage, for example database so that it can be shared across users</li> + * </ul> + * </p> + * <p>If you are using our SpellingUI class the UserDictionary will be created behind the scene and stored in a SharedObject.</p> + */ + public class UserDictionary + { + private var _ud:UserDictionaryInternal; + + /** + * @private + */ + public function get internalUserDictionary():UserDictionaryInternal + { + return _ud; + } + + /** + * Constructs a new <code>UserDictionary</code> which can later be added to a <code>SpellingService</code> object. + * + * @param wordList A vector of words (String) to be added as the initial entries of this <code>UserDictionary</code> + * @see UserDictionary.wordList + * + */ + public function UserDictionary(wordList:Vector.<String>=null) + { + var array:Array = new Array(); + if (wordList) { + for each (var w:String in wordList) + array.push(w); + } + + _ud = new UserDictionaryInternal(array); + } + + /** + * Add a word to the user dictionary. + * + * @param word A word to be added to this <code>UserDictionary</code>. + * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed, for example if the word is already added. + * @see UserDictionary.removeWord() + * + */ + public function addWord(word:String):Boolean + { + return _ud.addWord(word); + } + + /** + * Removes a word from the user dicitonary. + * + * @param word A word to be removed from this <code>UserDictionary</code>. + * @return True if the operation was successful, false if the operation was failed, for example if the word doesn't exist in the dictionary. + * @see UserDictionary.addWord() + * + */ + public function removeWord(word:String):Boolean + { + return _ud.removeWord(word); + } + + /** + * All words in this user dictionary. + * + * @return A vector of String that contains all words in this user dictionary + * + */ + public function get wordList():Vector.<String> + { + var result:Vector.<String> = new Vector.<String>(); + var array:Array = _ud.wordList; + + for each (var w:String in array) + result.push(w); + + return result; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as new file mode 100644 index 0000000..d4034a8 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as @@ -0,0 +1,115 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + + +package com.adobe.linguistics.spelling +{ + import com.adobe.linguistics.spelling.utils.WordList; + + /** + * Represents a user dictionary. + * + * <p>This class represents a user dictionary that is used by the <code>SpellChecker</code> class. This class itself is an in-memory object + * and doesn't store persistent data. However, developers can import/export a <code>UserDictionaryInternal</code> object from/to an Array of String, + * and use other flash classes to keep the data persistent. You may want to consider using one of the following options for permanent storage: + * + * <ul> + * <li>SharedObject, which is used in our SpellUI class to store words added from the ContextMenu</li> + * <li>File/FileStream, which is used in our UserDictionaryInternalExample and can be shared across AIR applications</li> + * <li>Server side storage, for example database so that it can be shared across users</li> + * </ul> + * </p> + * <p>If you are using our SpellUI class the UserDictionaryInternal will be created behind the scene and stored in a SharedObject.</p> + * @includeExample Examples/Air/UserDictionaryInternalExample/src/UserDictionaryInternalExample.mxml -noswf + * @playerversion Flash 10 + * @langversion 3.0 + */ + public class UserDictionaryInternal + { + /** + @private + (This property is for Squiggly Developer use only.) + */ + public var _wordList:WordList; + + /** + * Constructs a new <code>UserDictionaryInternal</code> which can later be added to a <code>SpellChecker</code> object. + * + * @param wordList An array of words (String) to be added as the initial entries of this <code>UserDictionaryInternal</code> + * @see UserDictionaryInternal.wordList + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function UserDictionaryInternal(wordList:Array=null) + { + // TODO: exception if has some problem with insert + _wordList= new WordList(); + if (wordList) { + for each (var w:String in wordList) + _wordList.insert(w); + } + } + + /** + * Add a word to the user dictionary. + * + * @param word A word to be added to this <code>UserDictionaryInternal</code>. + * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed. + * @see UserDictionaryInternal.removeWord() + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function addWord(word:String):Boolean + { + return _wordList.insert(word); + } + + /** + * Removes a word from the user dicitonary. + * + * @param word A word to be removed from this <code>UserDictionaryInternal</code>. + * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed. + * @see UserDictionaryInternal.addWord() + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function removeWord(word:String):Boolean + { + return _wordList.remove(word); + } + + /** + * List of all words in this user dictionary. + * + * @return An Array of String that contains all words in this user dictionary + * + * @playerversion Flash 10 + * @langversion 3.0 + */ + public function get wordList():Array + { + // TODO: make sure no return by reference + return _wordList.toArray(); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/DictionaryManager.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/DictionaryManager.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/DictionaryManager.as new file mode 100644 index 0000000..cef5b0d --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/DictionaryManager.as @@ -0,0 +1,73 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core +{ + import com.adobe.linguistics.spelling.core.container.HashTable; + public class DictionaryManager + { + private var _table:Array; + public function DictionaryManager() + { + _table = new Array(); + } + + public function addDictionary(dict:SquigglyDictionary):Boolean { + if ( dict == null ) return false; + for ( var i:int = 0; i< _table.length; ++i ) { + if ( dict == _table[i] ) + return false; + } + _table.push(dict); + return true; + } + + public function removeDictionary(dict:SquigglyDictionary):Boolean { + if ( dict == null) return false; + for ( var i:int = 0; i< _table.length; ++i ) { + if ( dict == _table[i] ) { + _table = _table.slice(i,1); // remove dictionary from the table. + } + } + return true; + + } + + public function get dictonaryList():Array { + return this._table; + } + + public function isEmpty():Boolean { + return (this._table == null ) ? true : false; + } + + public function get size():int { + return this._table.length; + } + + public function lookup( word:String ) :HashEntry { + for ( var i:int = 0; i < _table.length; ++i ) { + if ( _table[i].containsKey(word) ) + return _table[i].getElement(word); + } + return null; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/HashEntry.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/HashEntry.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/HashEntry.as new file mode 100644 index 0000000..64ac685 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/HashEntry.as @@ -0,0 +1,108 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core +{ + import com.adobe.linguistics.spelling.core.utils.StringUtils; + public class HashEntry + { + private var _affStr:String; // affix flag vector + private var _nextEntry:HashEntry; + + // Not sure now..just leave it here. + private var _variableFields:String; // variable fields (only for special pronounciation yet) + + + public function HashEntry(affStr:String=null,desc:String = null) + { + this._affStr = StringUtils.sort(affStr); + this._variableFields = desc; + this._nextEntry = null; + } + + public function addEntry(affStr:String=null,desc:String = null):Boolean { + if ( this._nextEntry != null ) return false; + this._nextEntry = new HashEntry(affStr, desc); + return true; + } + + public function get next():HashEntry { + return this._nextEntry; + } + + public function get affixFlagVector():String { + return this._affStr; + } + + public function set affixFlagVector(affStr:String):void { + this._affStr = StringUtils.sort(affStr); + } + + public function get variableFields():String { + return this._variableFields; + } + + public function set variableFields( varF:String) :void { + this._variableFields = varF; + } + + public function testAffix(flag:Number):Boolean { + if ( this._affStr == null ) return false; + var mid:int, left:int=0, right:int= this._affStr.length - 1; + while ( left <= right ) { + mid = (right+left)/2; + if ( this._affStr.charCodeAt(mid) == flag ) + return true; + if ( flag < this._affStr.charCodeAt(mid) ) right = mid -1; + else left = mid + 1; + } + return false; + } + + public function testAffixs(flags:Array):Boolean { + for ( var i:int; i< flags.length; ++i) { + if( testAffix(flags[i]) ) + return true; + } + return false; + } + //For develepors only, this function is made so that when flagmode=flag_long flags can be viewed. + public function printFlag(flag:Number):void{ + var result:String = String.fromCharCode(flag>>8) + String.fromCharCode(flag-((flag>>8)<<8)); + + } + + + static public function TESTAFF(affix:String, flag:Number):Boolean { + if ( affix == null ) return false; + affix = StringUtils.sort(affix); + var mid:int, left:int=0, right:int= affix.length - 1; + while ( left <= right ) { + mid = (right+left)/2; + if ( affix.charCodeAt(mid) == flag ) + return true; + if ( flag < affix.charCodeAt(mid) ) right = mid -1; + else left = mid + 1; + } + return false; + + } + } +} \ No newline at end of file