Author: szimano Date: 2005-11-12 07:58:50 -0500 (Sat, 12 Nov 2005) New Revision: 1563 Added: trunk/forge/portal-extensions/forge-speller/ trunk/forge/portal-extensions/forge-speller/.classpath trunk/forge/portal-extensions/forge-speller/.project trunk/forge/portal-extensions/forge-speller/maven.xml trunk/forge/portal-extensions/forge-speller/project.properties trunk/forge/portal-extensions/forge-speller/project.xml trunk/forge/portal-extensions/forge-speller/src/ trunk/forge/portal-extensions/forge-speller/src/etc/ trunk/forge/portal-extensions/forge-speller/src/etc/blank.html trunk/forge/portal-extensions/forge-speller/src/etc/controlWindow.js trunk/forge/portal-extensions/forge-speller/src/etc/controls.html trunk/forge/portal-extensions/forge-speller/src/etc/index.html trunk/forge/portal-extensions/forge-speller/src/etc/spellChecker.js trunk/forge/portal-extensions/forge-speller/src/etc/spellchecker.html trunk/forge/portal-extensions/forge-speller/src/etc/spellerStyle.css trunk/forge/portal-extensions/forge-speller/src/etc/wordWindow.js trunk/forge/portal-extensions/forge-speller/src/java/ trunk/forge/portal-extensions/forge-speller/src/java/org/ trunk/forge/portal-extensions/forge-speller/src/java/org/jboss/ trunk/forge/portal-extensions/forge-speller/src/java/org/jboss/labs/ trunk/forge/portal-extensions/forge-speller/src/java/org/jboss/labs/speller/ trunk/forge/portal-extensions/forge-speller/src/java/org/jboss/labs/speller/SpellerServlet.java trunk/forge/portal-extensions/forge-speller/src/web/ trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/ trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/jsp/ trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/jsp/normal.jsp trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/tld/ trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/tld/forge.tld trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/tld/portlet.tld trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/web.xml Modified: trunk/forge/portal-extensions/forge-ear/src/META-INF/application.xml trunk/forge/portal-extensions/forge-theme/jbossForgeLayout.war/layouts/jbossForge.jsp trunk/forge/portal-extensions/jbosswiki/forge-wiki/src/web/WEB-INF/jsp/Edit.jsp Log: http://jira.jboss.com/jira/browse/JBWIKI-18 Added spell checker that can be used _everywhere_ in portal. Please reade this wiki page: http://labs.jboss.com/wiki/AddSpellChecker Modified nasty application.xml commited by someone :->. Modified: trunk/forge/portal-extensions/forge-ear/src/META-INF/application.xml =================================================================== --- trunk/forge/portal-extensions/forge-ear/src/META-INF/application.xml 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-ear/src/META-INF/application.xml 2005-11-12 12:58:50 UTC (rev 1563) @@ -87,7 +87,6 @@ <web> <web-uri>forge-status.war</web-uri> </web> - </module> </module> <module> <web> Added: trunk/forge/portal-extensions/forge-speller/.classpath =================================================================== --- trunk/forge/portal-extensions/forge-speller/.classpath 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/.classpath 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<classpath> + <classpathentry excluding="" kind="src" path="src/java"> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/tmate/jars/javasvn.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/tmate/jars/jsch.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/javax.servlet/jars/servlet-api-2.2.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/jboss-forge/jars/forge-common-1.0.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/portlet-api/jars/portlet-api-1.0.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/jboss/jars/jboss-jmx.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/jboss/jars/jboss-common.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/jboss/jars/portal-common-lib.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/jboss/jars/portal-core-lib.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/jboss/jars/portal-portlet-lib.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/shotoku/jars/shotoku-base.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/shotoku/jars/shotoku-aop.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/velocity/jars/velocity-1.4.jar"> + </classpathentry> + <classpathentry kind="var" path="MAVEN_REPO/velocity/jars/velocity-dep-1.4.jar"> + </classpathentry> + <classpathentry kind="output" path="target/classes"> + </classpathentry> +</classpath> \ No newline at end of file Added: trunk/forge/portal-extensions/forge-speller/.project =================================================================== --- trunk/forge/portal-extensions/forge-speller/.project 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/.project 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<projectDescription> + <name>ads-portlet</name> + <comment> + </comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> \ No newline at end of file Added: trunk/forge/portal-extensions/forge-speller/maven.xml =================================================================== --- trunk/forge/portal-extensions/forge-speller/maven.xml 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/maven.xml 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,29 @@ +<!-- + JBoss, the OpenSource J2EE webOS + Distributable under LGPL license. + See terms of license at gnu.org. + --> +<project xmlns:j="jelly:core" xmlns:ant="jelly:ant" xmlns:u="jelly:util"> + <!-- Default war-project goals --> + + <goal name="all"> + <attainGoal name="build" /> + <attainGoal name="deploy" /> + </goal> + + <goal name="build"> + <attainGoal name="war" /> + </goal> + + <goal name="deploy"> + <ant:copy todir="${local.deploy.dir}" flatten="true"> + <ant:fileset dir="."> + <ant:filename name="target/*.war" /> + </ant:fileset> + </ant:copy> + </goal> + + <goal name="clean"> + <attainGoal name="prj-clean" /> + </goal> +</project> Added: trunk/forge/portal-extensions/forge-speller/project.properties =================================================================== --- trunk/forge/portal-extensions/forge-speller/project.properties 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/project.properties 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,3 @@ +maven.repo.remote=http://repository.atlassian.com,http://www.ibiblio.org/maven,http://dist.codehaus.org/ +maven.junit.fork=yes +maven.war.src=${basedir}/src/web Added: trunk/forge/portal-extensions/forge-speller/project.xml =================================================================== --- trunk/forge/portal-extensions/forge-speller/project.xml 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/project.xml 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,59 @@ +<?xml version='1.0' encoding='ISO-8859-1'?> +<!-- + JBoss, the OpenSource J2EE webOS + Distributable under LGPL license. + See terms of license at gnu.org. + --> +<project> + <pomVersion>3</pomVersion> + <extend>../common.xml</extend> + <id>speller</id> + <name>speller servlet</name> + <currentVersion>1.0</currentVersion> + <build> + <sourceDirectory>src/java</sourceDirectory> + <resources> + <resource> + <directory>src/etc/</directory> + <include>**/*.js</include> + </resource> + <resource> + <directory>src/etc/</directory> + <include>**/*.html</include> + </resource> + </resources> + </build> + + <organization> + <name>Tomasz Szymanski</name> + <url>http://mamut.net.pl</url> + </organization> + <description></description> + <dependencies> + <dependency> + <groupId>tmate</groupId> + <artifactId>javasvn</artifactId> + <version>1.0</version> + <jar>javasvn.jar</jar> + </dependency> + + <dependency> + <groupId>tmate</groupId> + <artifactId>jsch</artifactId> + <version>1.0</version> + <jar>jsch.jar</jar> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <version>2.2</version> + </dependency> + + <dependency> + <groupId>jboss-forge</groupId> + <artifactId>forge-common</artifactId> + <version>1.0</version> + </dependency> + </dependencies> +</project> Added: trunk/forge/portal-extensions/forge-speller/src/etc/blank.html =================================================================== Added: trunk/forge/portal-extensions/forge-speller/src/etc/controlWindow.js =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/etc/controlWindow.js 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/etc/controlWindow.js 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,86 @@ +//////////////////////////////////////////////////// +// controlWindow object +//////////////////////////////////////////////////// +function controlWindow( controlForm ) { + // private properties + this._form = controlForm; + + // public properties + this.windowType = "controlWindow"; + this.noSuggestionSelection = "- No suggestions -"; + // set up the properties for elements of the given control form + this.suggestionList = this._form.sugg; + this.evaluatedText = this._form.misword; + this.replacementText = this._form.txtsugg; + this.undoButton = this._form.btnUndo; + + // public methods + this.addSuggestion = addSuggestion; + this.clearSuggestions = clearSuggestions; + this.selectDefaultSuggestion = selectDefaultSuggestion; + this.resetForm = resetForm; + this.setSuggestedText = setSuggestedText; + this.enableUndo = enableUndo; + this.disableUndo = disableUndo; +} + +function resetForm() { + if( this._form ) { + this._form.reset(); + } +} + +function setSuggestedText() { + var slct = this.suggestionList; + var txt = this.replacementText; + var str = ""; + if( (slct.options[0].text) && slct.options[0].text != this.noSuggestionSelection ) { + str = slct.options[slct.selectedIndex].text; + } + txt.value = str; +} + +function selectDefaultSuggestion() { + var slct = this.suggestionList; + var txt = this.replacementText; + if( slct.options.length == 0 ) { + this.addSuggestion( this.noSuggestionSelection ); + } else { + slct.options[0].selected = true; + } + this.setSuggestedText(); +} + +function addSuggestion( sugg_text ) { + var slct = this.suggestionList; + if( sugg_text ) { + var i = slct.options.length; + var newOption = new Option( sugg_text, 'sugg_text'+i ); + slct.options[i] = newOption; + } +} + +function clearSuggestions() { + var slct = this.suggestionList; + for( var j = slct.length - 1; j > -1; j-- ) { + if( slct.options[j] ) { + slct.options[j] = null; + } + } +} + +function enableUndo() { + if( this.undoButton ) { + if( this.undoButton.disabled == true ) { + this.undoButton.disabled = false; + } + } +} + +function disableUndo() { + if( this.undoButton ) { + if( this.undoButton.disabled == false ) { + this.undoButton.disabled = true; + } + } +} Added: trunk/forge/portal-extensions/forge-speller/src/etc/controls.html =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/etc/controls.html 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/etc/controls.html 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,153 @@ +<html> +<head> +<link rel="stylesheet" type="text/css" href="spellerStyle.css"/> + +<script src="controlWindow.js"></script> + +<script> +var spellerObject; +var controlWindowObj; + +if( parent.opener ) { + spellerObject = parent.opener.speller; +} + +function ignore_word() { + if( spellerObject ) { + spellerObject.ignoreWord(); + } +} + +function ignore_all() { + if( spellerObject ) { + spellerObject.ignoreAll(); + } +} + +function replace_word() { + if( spellerObject ) { + spellerObject.replaceWord(); + } +} + +function replace_all() { + if( spellerObject ) { + spellerObject.replaceAll(); + } +} + +function end_spell() { + if( spellerObject ) { + spellerObject.terminateSpell(); + } +} + +function undo() { + if( spellerObject ) { + spellerObject.undo(); + } +} + +function suggText() { + if( controlWindowObj ) { + controlWindowObj.setSuggestedText(); + } +} + +function init_spell() { + var controlForm = document.spellcheck; + + // create a new controlWindow object + controlWindowObj = new controlWindow( controlForm ); + + // call the init_spell() function in the parent frameset + if( parent.frames.length ) { + parent.init_spell( controlWindowObj ); + } else { + alert( 'This page was loaded outside of a frameset. It might not display properly' ); + } +} + +</script> + +</head> + +<body class="controlWindowBody" onLoad="init_spell();"> + +<form name="spellcheck"> + +<table border="0" cellpadding="0" cellspacing="0" border="0"> +<tr> + <td colspan="3" class="normalLabel">Not in dictionary:</td> +</tr> +<tr> + <td colspan="3"><input class="readonlyInput" type="text" name="misword" readonly /></td> +</tr> +<tr> + <td colspan="3" height="5"></td> +</tr> +<tr> + <td class="normalLabel">Change to:</td> +</tr> +<tr valign="top"> + <td> + <table border="0" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td class="normalLabel"> + <input class="textDefault" type="text" name="txtsugg" /> + </td> + </tr> + <tr> + <td> + <select class="suggSlct" name="sugg" size="7" onChange="suggText();" onDblClick="replace_word();"> + <option></option> + </select> + </td> + </tr> + </table> + </td> + <td> </td> + <td> + <table border="0" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td> + <input class="buttonDefault" type="button" value="Ignore" onClick="ignore_word();"> + </td> + <td> </td> + <td> + <input class="buttonDefault" type="button" value="Ignore All" onClick="ignore_all();"> + </td> + </tr> + <tr> + <td colspan="3" height="5"></td> + </tr> + <tr> + + <td> + <input class="buttonDefault" type="button" value="Replace" onClick="replace_word();"> + </td> + <td> </td> + <td> + <input class="buttonDefault" type="button" value="Replace All" onClick="replace_all();"> + </td> + </tr> + <tr> + <td colspan="3" height="5"></td> + </tr> + <tr> + <td> + <input class="buttonDefault" type="button" name="btnUndo" value="Undo" onClick="undo();" disabled> + </td> + <td> </td> + <td> + <input class="buttonDefault" type="button" value="Close" onClick="end_spell();"> + </td> + </tr> + </table> + </td> +</tr> +</table> + +</form> +</body> +</html> Added: trunk/forge/portal-extensions/forge-speller/src/etc/index.html =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/etc/index.html 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/etc/index.html 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,137 @@ +<html> +<head> +<title>Spell Check Tester</title> + +<style type="text/css"> +body { + font-family:verdana, helvetica, arial, sans-serif; + font-size:small; + color:black; + background:white; + margin-top:0; + margin-left:0; + margin-right:0; +} +table { + color:#000000; + background:#FFFFFF; +} +td, p { + font-family:verdana, helvetica, arial, sans-serif; + font-size:small; +} +h1 { + font-family: sans-serif; + font-size: 150%; + font-weight: bold; + margin-top:.8em; + letter-spacing:2; +} +h2 { + font-family: sans-serif; + font-size: 125%; + font-weight: bold; + letter-spacing:2; +} +h3 { + font-family: sans-serif; + font-size: 100%; + font-weight: bold; + letter-spacing:2; +} +img { + vertical-align: middle; +} +a { + text-decoration: none; +} +a:hover { + color: blue; + background-color: #EBEBEB; +} +a.headerlink { + color: #EBEBEB; + /*text-decoration: none;*/ + background-color: #999999; +} +a.headerlink:hover { + color: #FFFFFF; + background-color: transparent; + text-decoration: underline; +} +a.imghref:hover { + background-color: transparent; +} +.smaller { + font-size: 75%; +} +</style> + +<script src="/speller/pages/spellChecker.js"></script> + +<script> +// +// openSpellChecker() +// +// this function is an example that illustrates the various ways you can invoke +// the the Speller Pages spell-checking process +// +function openSpellChecker() { + + // example 1. + // Pass in the text inputs or textarea inputs that you + // want to spell-check to the object's constructor, + // then call the openChecker() method. + /*var text1 = document.form1.text1; + var textarea1 = document.form1.textarea1; + var speller = new spellChecker( text1, textarea1 ); + speller.openChecker();*/ + + // example 2. + // Rather than passing in the form elements to the object's + // constructor, populate the object's textInputs property, + // then call the openChecker() method. + + /* + var speller = new spellChecker(); + var spellerInputs = new Array(); + for( var i = 0 ; i < document.form1.elements.length; i++ ) { + if( document.form1.elements[i].type.match( /^text/ )) { + spellerInputs[spellerInputs.length] = document.form1.elements[i]; + } + } + speller.textInputs = spellerInputs; + speller.openChecker(); + */ + + // example 3. + // use the spellCheckAll() method to check every text input + // and textarea input in every form in the HTML document. + // You can also use the checkTextBoxes() method or checkTextAreas() + // method instead of spellCheckAll() to check only text inputs + // or textarea inputs, respectively + + var speller = new spellChecker(); + speller.spellCheckAll(); + +} + +</script> +</head> + +<body> + +<h1>Speller Pages</h1> +<h3>This is only a demo of working Speller Pages ported to Labs</h3> +<form name="form1"> +<input type="text" name="text1" size="30"> +<br /> +<textarea name="textarea1" rows="10" cols="60"> +</textarea> +<br /> +<input type="button" value="Check Spelling" onClick="openSpellChecker();"/> +</form> + + +</body> +</html> Added: trunk/forge/portal-extensions/forge-speller/src/etc/spellChecker.js =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/etc/spellChecker.js 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/etc/spellChecker.js 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,451 @@ +//////////////////////////////////////////////////// +// spellChecker.js +// +// spellChecker object +// +// This file is sourced on web pages that have a textarea object to evaluate +// for spelling. It includes the implementation for the spellCheckObject. +// +//////////////////////////////////////////////////// + + +// constructor +function spellChecker( textObject ) { + + // public properties - configurable + this.popUpUrl = '/speller/pages/spellchecker.html'; + //this.popUpUrl = 'http://www.netjs.com/speller/spellchecker.html' + this.popUpName = 'spellchecker'; + this.popUpProps = "menu=no,width=440,height=350,top=70,left=120,resizable=yes,status=yes"; + this.spellCheckScript = '/speller'; + //this.spellCheckScript = 'http://www.netjs.com/speller/server-scripts/spellchecker.php'; + //this.spellCheckScript = '/cgi-bin/spellchecker.pl'; + + // values used to keep track of what happened to a word + this.replWordFlag = "R"; // single replace + this.ignrWordFlag = "I"; // single ignore + this.replAllFlag = "RA"; // replace all occurances + this.ignrAllFlag = "IA"; // ignore all occurances + this.fromReplAll = "~RA"; // an occurance of a "replace all" word + this.fromIgnrAll = "~IA"; // an occurance of a "ignore all" word + // properties set at run time + this.wordFlags = new Array(); + this.currentTextIndex = 0; + this.currentWordIndex = 0; + this.spellCheckerWin = null; + this.controlWin = null; + this.wordWin = null; + this.textArea = textObject; // deprecated + this.textInputs = arguments; + + // private methods + this._spellcheck = _spellcheck; + this._getSuggestions = _getSuggestions; + this._setAsIgnored = _setAsIgnored; + this._getTotalReplaced = _getTotalReplaced; + this._setWordText = _setWordText; + this._getFormInputs = _getFormInputs; + + // public methods + this.openChecker = openChecker; + this.startCheck = startCheck; + this.checkTextBoxes = checkTextBoxes; + this.checkTextAreas = checkTextAreas; + this.spellCheckAll = spellCheckAll; + this.ignoreWord = ignoreWord; + this.ignoreAll = ignoreAll; + this.replaceWord = replaceWord; + this.replaceAll = replaceAll; + this.terminateSpell = terminateSpell; + this.undo = undo; + + // set the current window's "speller" property to the instance of this class. + // this object can now be referenced by child windows/frames. + window.speller = this; +} + +// call this method to check all text boxes (and only text boxes) in the HTML document +function checkTextBoxes() { + this.textInputs = this._getFormInputs( "^text$" ); + this.openChecker(); +} + +// call this method to check all textareas (and only textareas ) in the HTML document +function checkTextAreas() { + this.textInputs = this._getFormInputs( "^textarea$" ); + this.openChecker(); +} + +// call this method to check all text boxes and textareas in the HTML document +function spellCheckAll() { + this.textInputs = this._getFormInputs( "^text(area)?$" ); + this.openChecker(); +} + +// call this method to check text boxe(s) and/or textarea(s) that were passed in to the +// object's constructor or to the textInputs property +function openChecker() { + this.spellCheckerWin = window.open( this.popUpUrl, this.popUpName, this.popUpProps ); + if( !this.spellCheckerWin.opener ) { + this.spellCheckerWin.opener = window; + } +} + +function startCheck( wordWindowObj, controlWindowObj ) { + + // set properties from args + this.wordWin = wordWindowObj; + this.controlWin = controlWindowObj; + + // reset properties + this.wordWin.resetForm(); + this.controlWin.resetForm(); + this.currentTextIndex = 0; + this.currentWordIndex = 0; + // initialize the flags to an array - one element for each text input + this.wordFlags = new Array( this.wordWin.textInputs.length ); + // each element will be an array that keeps track of each word in the text + for( var i=0; i<this.wordFlags.length; i++ ) { + this.wordFlags[i] = []; + } + + // start + this._spellcheck(); + + return true; +} + +function ignoreWord() { + var wi = this.currentWordIndex; + var ti = this.currentTextIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + if( !this.wordWin.getTextVal( ti, wi )) { + alert( 'Error: "Not in dictionary" text is missing.' ); + return false; + } + // set as ignored + if( this._setAsIgnored( ti, wi, this.ignrWordFlag )) { + this.currentWordIndex++; + this._spellcheck(); + } +} + +function ignoreAll() { + var wi = this.currentWordIndex; + var ti = this.currentTextIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + // get the word that is currently being evaluated. + var s_word_to_repl = this.wordWin.getTextVal( ti, wi ); + if( !s_word_to_repl ) { + alert( 'Error: "Not in dictionary" text is missing' ); + return false; + } + + // set this word as an "ignore all" word. + this._setAsIgnored( ti, wi, this.ignrAllFlag ); + + // loop through all the words after this word + for( var i = ti; i < this.wordWin.textInputs.length; i++ ) { + for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == ti && j > wi ) || i > ti ) { + // future word: set as "from ignore all" if + // 1) do not already have a flag and + // 2) have the same value as current word + if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl ) + && ( !this.wordFlags[i][j] )) { + this._setAsIgnored( i, j, this.fromIgnrAll ); + } + } + } + } + + // finally, move on + this.currentWordIndex++; + this._spellcheck(); +} + +function replaceWord() { + var wi = this.currentWordIndex; + var ti = this.currentTextIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + if( !this.wordWin.getTextVal( ti, wi )) { + alert( 'Error: "Not in dictionary" text is missing' ); + return false; + } + if( !this.controlWin.replacementText ) { + return; + } + var txt = this.controlWin.replacementText; + if( txt.value ) { + var newspell = new String( txt.value ); + if( this._setWordText( ti, wi, newspell, this.replWordFlag )) { + this.currentWordIndex++; + this._spellcheck(); + } + } +} + +function replaceAll() { + var ti = this.currentTextIndex; + var wi = this.currentWordIndex; + if( !this.wordWin ) { + alert( 'Error: Word frame not available.' ); + return false; + } + var s_word_to_repl = this.wordWin.getTextVal( ti, wi ); + if( !s_word_to_repl ) { + alert( 'Error: "Not in dictionary" text is missing' ); + return false; + } + var txt = this.controlWin.replacementText; + if( !txt.value ) return; + var newspell = new String( txt.value ); + + // set this word as a "replace all" word. + this._setWordText( ti, wi, newspell, this.replAllFlag ); + + // loop through all the words after this word + for( var i = ti; i < this.wordWin.textInputs.length; i++ ) { + for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == ti && j > wi ) || i > ti ) { + // future word: set word text to s_word_to_repl if + // 1) do not already have a flag and + // 2) have the same value as s_word_to_repl + if(( this.wordWin.getTextVal( i, j ) == s_word_to_repl ) + && ( !this.wordFlags[i][j] )) { + this._setWordText( i, j, newspell, this.fromReplAll ); + } + } + } + } + + // finally, move on + this.currentWordIndex++; + this._spellcheck(); +} + +function terminateSpell() { + // called when we have reached the end of the spell checking. + var msg = "Spell check complete:\n\n"; + var numrepl = this._getTotalReplaced(); + if( numrepl == 0 ) { + // see if there were no misspellings to begin with + if( !this.wordWin ) { + msg = ""; + } else { + if( this.wordWin.totalMisspellings() ) { + msg += "No words changed."; + } else { + msg += "No misspellings found."; + } + } + } else if( numrepl == 1 ) { + msg += "One word changed."; + } else { + msg += numrepl + " words changed."; + } + if( msg ) { + msg += "\n"; + alert( msg ); + } + + if( numrepl > 0 ) { + // update the text field(s) on the opener window + for( var i = 0; i < this.textInputs.length; i++ ) { + // this.textArea.value = this.wordWin.text; + if( this.wordWin ) { + if( this.wordWin.textInputs[i] ) { + this.textInputs[i].value = this.wordWin.textInputs[i]; + } + } + } + } + + // return back to the calling window + this.spellCheckerWin.close(); + + return true; +} + +function undo() { + // skip if this is the first word! + var ti = this.currentTextIndex; + var wi = this.currentWordIndex + + if( this.wordWin.totalPreviousWords( ti, wi ) > 0 ) { + this.wordWin.removeFocus( ti, wi ); + + // go back to the last word index that was acted upon + do { + // if the current word index is zero then reset the seed + if( this.currentWordIndex == 0 && this.currentTextIndex > 0 ) { + this.currentTextIndex--; + this.currentWordIndex = this.wordWin.totalWords( this.currentTextIndex )-1; + if( this.currentWordIndex < 0 ) this.currentWordIndex = 0; + } else { + if( this.currentWordIndex > 0 ) { + this.currentWordIndex--; + } + } + } while ( + this.wordWin.totalWords( this.currentTextIndex ) == 0 + || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromIgnrAll + || this.wordFlags[this.currentTextIndex][this.currentWordIndex] == this.fromReplAll + ); + + var text_idx = this.currentTextIndex; + var idx = this.currentWordIndex; + var preReplSpell = this.wordWin.originalSpellings[text_idx][idx]; + + // if we got back to the first word then set the Undo button back to disabled + if( this.wordWin.totalPreviousWords( text_idx, idx ) == 0 ) { + this.controlWin.disableUndo(); + } + + // examine what happened to this current word. + switch( this.wordFlags[text_idx][idx] ) { + // replace all: go through this and all the future occurances of the word + // and revert them all to the original spelling and clear their flags + case this.replAllFlag : + for( var i = text_idx; i < this.wordWin.textInputs.length; i++ ) { + for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == text_idx && j >= idx ) || i > text_idx ) { + var origSpell = this.wordWin.originalSpellings[i][j]; + if( origSpell == preReplSpell ) { + this._setWordText ( i, j, origSpell, undefined ); + } + } + } + } + break; + + // ignore all: go through all the future occurances of the word + // and clear their flags + case this.ignrAllFlag : + for( var i = text_idx; i < this.wordWin.textInputs.length; i++ ) { + for( var j = 0; j < this.wordWin.totalWords( i ); j++ ) { + if(( i == text_idx && j >= idx ) || i > text_idx ) { + var origSpell = this.wordWin.originalSpellings[i][j]; + if( origSpell == preReplSpell ) { + this.wordFlags[i][j] = undefined; + } + } + } + } + break; + + // replace: revert the word to its original spelling + case this.replWordFlag : + this._setWordText ( text_idx, idx, preReplSpell, undefined ); + break; + } + + // For all four cases, clear the wordFlag of this word. re-start the process + this.wordFlags[text_idx][idx] = undefined; + this._spellcheck(); + } +} + +function _spellcheck() { + var ww = this.wordWin; + + // check if this is the last word in the current text element + if( this.currentWordIndex == ww.totalWords( this.currentTextIndex) ) { + this.currentTextIndex++; + this.currentWordIndex = 0; + // keep going if we're not yet past the last text element + if( this.currentTextIndex < this.wordWin.textInputs.length ) { + this._spellcheck(); + return; + } else { + this.terminateSpell(); + return; + } + } + + // if this is after the first one make sure the Undo button is enabled + if( this.currentWordIndex > 0 ) { + this.controlWin.enableUndo(); + } + + // skip the current word if it has already been worked on + if( this.wordFlags[this.currentTextIndex][this.currentWordIndex] ) { + // increment the global current word index and move on. + this.currentWordIndex++; + this._spellcheck(); + } else { + var evalText = ww.getTextVal( this.currentTextIndex, this.currentWordIndex ); + if( evalText ) { + this.controlWin.evaluatedText.value = evalText; + ww.setFocus( this.currentTextIndex, this.currentWordIndex ); + this._getSuggestions( this.currentTextIndex, this.currentWordIndex ); + } + } +} + +function _getSuggestions( text_num, word_num ) { + this.controlWin.clearSuggestions(); + // add suggestion in list for each suggested word. + // get the array of suggested words out of the + // three-dimensional array containing all suggestions. + var a_suggests = this.wordWin.suggestions[text_num][word_num]; + if( a_suggests ) { + // got an array of suggestions. + for( var ii = 0; ii < a_suggests.length; ii++ ) { + this.controlWin.addSuggestion( a_suggests[ii] ); + } + } + this.controlWin.selectDefaultSuggestion(); +} + +function _setAsIgnored( text_num, word_num, flag ) { + // set the UI + this.wordWin.removeFocus( text_num, word_num ); + // do the bookkeeping + this.wordFlags[text_num][word_num] = flag; + return true; +} + +function _getTotalReplaced() { + var i_replaced = 0; + for( var i = 0; i < this.wordFlags.length; i++ ) { + for( var j = 0; j < this.wordFlags[i].length; j++ ) { + if(( this.wordFlags[i][j] == this.replWordFlag ) + || ( this.wordFlags[i][j] == this.replAllFlag ) + || ( this.wordFlags[i][j] == this.fromReplAll )) { + i_replaced++; + } + } + } + return i_replaced; +} + +function _setWordText( text_num, word_num, newText, flag ) { + // set the UI and form inputs + this.wordWin.setText( text_num, word_num, newText ); + // keep track of what happened to this word: + this.wordFlags[text_num][word_num] = flag; + return true; +} + +function _getFormInputs( inputPattern ) { + var inputs = new Array(); + for( var i = 0; i < document.forms.length; i++ ) { + for( var j = 0; j < document.forms[i].elements.length; j++ ) { + if( document.forms[i].elements[j].type.match( inputPattern )) { + inputs[inputs.length] = document.forms[i].elements[j]; + } + } + } + return inputs; +} + Added: trunk/forge/portal-extensions/forge-speller/src/etc/spellchecker.html =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/etc/spellchecker.html 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/etc/spellchecker.html 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,71 @@ + +<script> + +var wordWindow = null; +var controlWindow = null; + +function init_spell( spellerWindow ) { + + if( spellerWindow ) { + if( spellerWindow.windowType == "wordWindow" ) { + wordWindow = spellerWindow; + } else if ( spellerWindow.windowType == "controlWindow" ) { + controlWindow = spellerWindow; + } + } + + if( controlWindow && wordWindow ) { + // populate the speller object and start it off! + var speller = opener.speller; + wordWindow.speller = speller; + speller.startCheck( wordWindow, controlWindow ); + } +} + +// encodeForPost +function encodeForPost( str ) { + var s = new String( str ); + s = encodeURIComponent( s ); + // additionally encode single quotes to evade any PHP + // magic_quotes_gpc setting (it inserts escape characters and + // therefore skews the btye positions of misspelled words) + return s.replace( /\'/g, '%27' ); +} + +// post the text area data to the script that populates the speller +function postWords() { + var bodyDoc = window.frames[0].document; + bodyDoc.open(); + bodyDoc.write('<html>'); + bodyDoc.write('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'); + bodyDoc.write('<link rel="stylesheet" type="text/css" href="spellerStyle.css"/>'); + if (opener) { + var speller = opener.speller; + bodyDoc.write('<body class="normalText" onLoad="document.forms[0].submit();">'); + bodyDoc.write('<p>Spell check in progress...</p>'); + bodyDoc.write('<form action="'+speller.spellCheckScript+'" method="get">'); + for( var i = 0; i < speller.textInputs.length; i++ ) { + bodyDoc.write('<input type="hidden" name="textinputs[]" value="'+encodeForPost(speller.textInputs[i].value)+'">'); + } + bodyDoc.write('</form>'); + bodyDoc.write('</body>'); + } else { + bodyDoc.write('<body class="normalText">'); + bodyDoc.write('<p><b>This page cannot be displayed</b></p><p>The window was not opened from another window.</p>'); + bodyDoc.write('</body>'); + } + bodyDoc.write('</html>'); + bodyDoc.close(); +} +</script> + +<html> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<head> +<title>Speller Pages</title> +</head> +<frameset rows="*,201" onLoad="postWords();"> +<frame src="blank.html"> +<frame src="controls.html"> +</frameset> +</html> Added: trunk/forge/portal-extensions/forge-speller/src/etc/spellerStyle.css =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/etc/spellerStyle.css 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/etc/spellerStyle.css 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,47 @@ +.blend { + font-family: courier new; + font-size: 10pt; + border: 0; + margin-bottom:-1; +} +.normalLabel { + font-size:8pt; +} +.normalText { + font-family:arial, helvetica, sans-serif; + font-size:10pt; + color:000000; + background-color:FFFFFF; +} +.plainText { + font-family: courier new, courier, monospace; + font-size: 10pt; + color:000000; + background-color:FFFFFF; +} +.controlWindowBody { + font-family:arial, helvetica, sans-serif; + font-size:8pt; + color:000000; + background-color:DADADA; +} +.readonlyInput { + background-color:DADADA; + color:000000; + font-size:8pt; + width:392px; +} +.textDefault { + font-size:8pt; + width: 200px; +} +.buttonDefault { + width:90px; + height:22px; + font-size:8pt; +} +.suggSlct { + width:200px; + margin-top:2; + font-size:8pt; +} \ No newline at end of file Added: trunk/forge/portal-extensions/forge-speller/src/etc/wordWindow.js =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/etc/wordWindow.js 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/etc/wordWindow.js 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,269 @@ +//////////////////////////////////////////////////// +// wordWindow object +//////////////////////////////////////////////////// +function wordWindow() { + // private properties + this._forms = []; + + // private methods + this._getWordObject = _getWordObject; + //this._getSpellerObject = _getSpellerObject; + this._wordInputStr = _wordInputStr; + this._adjustIndexes = _adjustIndexes; + this._isWordChar = _isWordChar; + this._lastPos = _lastPos; + + // public properties + this.wordChar = /[a-zA-Z]/; + this.windowType = "wordWindow"; + this.originalSpellings = new Array(); + this.suggestions = new Array(); + this.checkWordBgColor = "pink"; + this.normWordBgColor = "white"; + this.text = ""; + this.textInputs = new Array(); + this.indexes = new Array(); + //this.speller = this._getSpellerObject(); + + // public methods + this.resetForm = resetForm; + this.totalMisspellings = totalMisspellings; + this.totalWords = totalWords; + this.totalPreviousWords = totalPreviousWords; + //this.getTextObjectArray = getTextObjectArray; + this.getTextVal = getTextVal; + this.setFocus = setFocus; + this.removeFocus = removeFocus; + this.setText = setText; + //this.getTotalWords = getTotalWords; + this.writeBody = writeBody; + this.printForHtml = printForHtml; +} + +function resetForm() { + if( this._forms ) { + for( var i = 0; i < this._forms.length; i++ ) { + this._forms[i].reset(); + } + } + return true; +} + +function totalMisspellings() { + var total_words = 0; + for( var i = 0; i < this.textInputs.length; i++ ) { + total_words += this.totalWords( i ); + } + return total_words; +} + +function totalWords( textIndex ) { + return this.originalSpellings[textIndex].length; +} + +function totalPreviousWords( textIndex, wordIndex ) { + var total_words = 0; + for( var i = 0; i <= textIndex; i++ ) { + for( var j = 0; j < this.totalWords( i ); j++ ) { + if( i == textIndex && j == wordIndex ) { + break; + } else { + total_words++; + } + } + } + return total_words; +} + +//function getTextObjectArray() { +// return this._form.elements; +//} + +function getTextVal( textIndex, wordIndex ) { + var word = this._getWordObject( textIndex, wordIndex ); + if( word ) { + return word.value; + } +} + +function setFocus( textIndex, wordIndex ) { + var word = this._getWordObject( textIndex, wordIndex ); + if( word ) { + if( word.type == "text" ) { + word.focus(); + word.style.backgroundColor = this.checkWordBgColor; + } + } +} + +function removeFocus( textIndex, wordIndex ) { + var word = this._getWordObject( textIndex, wordIndex ); + if( word ) { + if( word.type == "text" ) { + word.blur(); + word.style.backgroundColor = this.normWordBgColor; + } + } +} + +function setText( textIndex, wordIndex, newText ) { + var word = this._getWordObject( textIndex, wordIndex ); + var beginStr; + var endStr; + if( word ) { + var pos = this.indexes[textIndex][wordIndex]; + var oldText = word.value; + // update the text given the index of the string + beginStr = this.textInputs[textIndex].substring( 0, pos ); + endStr = this.textInputs[textIndex].substring( + pos + oldText.length, + this.textInputs[textIndex].length + ); + this.textInputs[textIndex] = beginStr + newText + endStr; + + // adjust the indexes on the stack given the differences in + // length between the new word and old word. + var lengthDiff = newText.length - oldText.length; + this._adjustIndexes( textIndex, wordIndex, lengthDiff ); + + word.size = newText.length; + word.value = newText; + this.removeFocus( textIndex, wordIndex ); + } +} + + +function writeBody() { + var d = window.document; + var is_html = false; + + d.open(); + + // iterate through each text input. + for( var txtid = 0; txtid < this.textInputs.length; txtid++ ) { + var end_idx = 0; + var begin_idx = 0; + d.writeln( '<form name="textInput'+txtid+'">' ); + var wordtxt = this.textInputs[txtid]; + this.indexes[txtid] = []; + + if( wordtxt ) { + var orig = this.originalSpellings[txtid]; + if( !orig ) break; + + //!!! plain text, or HTML mode? + d.writeln( '<div class="plainText">' ); + // iterate through each occurrence of a misspelled word. + for( var i = 0; i < orig.length; i++ ) { + // find the position of the current misspelled word, + // starting at the last misspelled word. + // and keep looking if it's a substring of another word + do { + begin_idx = wordtxt.indexOf( orig[i], end_idx ); + end_idx = begin_idx + orig[i].length; + // word not found? messed up! + if( begin_idx == -1 ) break; + // look at the characters immediately before and after + // the word. If they are word characters we'll keep looking. + var before_char = wordtxt.charAt( begin_idx - 1 ); + var after_char = wordtxt.charAt( end_idx ); + } while ( + this._isWordChar( before_char ) + || this._isWordChar( after_char ) + ); + + // keep track of its position in the original text. + this.indexes[txtid][i] = begin_idx; + + // write out the characters before the current misspelled word + for( var j = this._lastPos( txtid, i ); j < begin_idx; j++ ) { + // !!! html mode? make it html compatible + d.write( this.printForHtml( wordtxt.charAt( j ))); + } + + // write out the misspelled word. + d.write( this._wordInputStr( orig[i] )); + + // if it's the last word, write out the rest of the text + if( i == orig.length-1 ){ + d.write( printForHtml( wordtxt.substr( end_idx ))); + } + } + + d.writeln( '</div>' ); + + } + d.writeln( '</form>' ); + } + //for ( var j = 0; j < d.forms.length; j++ ) { + // alert( d.forms[j].name ); + // for( var k = 0; k < d.forms[j].elements.length; k++ ) { + // alert( d.forms[j].elements[k].name + ": " + d.forms[j].elements[k].value ); + // } + //} + + // set the _forms property + this._forms = d.forms; + d.close(); +} + +// return the character index in the full text after the last word we evaluated +function _lastPos( txtid, idx ) { + if( idx > 0 ) + return this.indexes[txtid][idx-1] + this.originalSpellings[txtid][idx-1].length; + else + return 0; +} + +function printForHtml( n ) { + var htmlstr = n; + if( htmlstr.length == 1 ) { + // do simple case statement if it's just one character + switch ( n ) { + case "\n": + htmlstr = '<br/>'; + break; + case "<": + htmlstr = '<'; + break; + case ">": + htmlstr = '>'; + break; + } + return htmlstr; + } else { + htmlstr = htmlstr.replace( /</g, '<' ); + htmlstr = htmlstr.replace( />/g, '>' ); + htmlstr = htmlstr.replace( /\n/g, '<br/>' ); + return htmlstr; + } +} + +function _isWordChar( letter ) { + if( letter.search( this.wordChar ) == -1 ) { + return false; + } else { + return true; + } +} + +function _getWordObject( textIndex, wordIndex ) { + if( this._forms[textIndex] ) { + if( this._forms[textIndex].elements[wordIndex] ) { + return this._forms[textIndex].elements[wordIndex]; + } + } + return null; +} + +function _wordInputStr( word ) { + var str = '<input readonly '; + str += 'class="blend" type="text" value="' + word + '" size="' + word.length + '">'; + return str; +} + +function _adjustIndexes( textIndex, wordIndex, lengthDiff ) { + for( var i = wordIndex + 1; i < this.originalSpellings[textIndex].length; i++ ) { + this.indexes[textIndex][i] = this.indexes[textIndex][i] + lengthDiff; + } +} Added: trunk/forge/portal-extensions/forge-speller/src/java/org/jboss/labs/speller/SpellerServlet.java =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/java/org/jboss/labs/speller/SpellerServlet.java 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/java/org/jboss/labs/speller/SpellerServlet.java 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,334 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005, JBoss Inc., and individual contributors as indicated + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.labs.speller; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.URLDecoder; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * This file was orignally written in PHP by James Shimada, admin of the Speller + * Pages project http://sourceforge.net/projects/spellerpages/ and then ported + * to work as servlet by Tomasz Szymanski + * + * James Shimada did really great work. + * + * @author James Shimada jsh...@us... + * @author Tomasz Szymanski tom...@jb... + * + */ +public class SpellerServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private static final String SERVLET_PREFIX = "/speller/"; + + private String spellercss = "/speller/pages/spellerStyle.css"; + + private String word_win_src = "/speller/pages/wordWindow.js"; + + private String pageLocation = "/home/tomek/tmp/spellerpages-0.5.1/speller/"; + + private String[] textinputs = null; // $_POST['textinputs']; # array + + private String aspell_prog = "aspell"; + + private String lang = "en_US"; + + private String aspell_opts = "-a --lang=" + lang + " --encoding=utf-8"; + + private String input_separator = "A"; + + /* + * set the JavaScript variable to the submitted text. textinputs is an + * array, each element corresponding to the (url-encoded) value of the text + * control submitted for spell-checking + */ + + private void print_textinputs_var(PrintWriter writer) { + for (int i = 0; (textinputs != null) && (i < textinputs.length); i++ /* + * as + * $key=>$val + */) { + textinputs[i] = textinputs[i].replaceAll("'", "%27"); + writer.write("textinputs[" + i + "] = decodeURIComponent(\"" + + textinputs[i] + "\");\n"); + } + + } // make declarations for the text input index + + private void print_textindex_decl(int text_input_idx, PrintWriter writer) { + writer.write("words[" + text_input_idx + "] = [];\n"); + writer.write("suggs[" + text_input_idx + "] = [];\n"); + } + + // set an element of the JavaScript 'words' array to a misspelled word + private void print_words_elem(String word, int index, int textInputIdx, + PrintWriter writer) { + writer.write("words[" + textInputIdx + "][" + index + "] = '" + + escape_quote(word) + "';\n"); + } + + // set an element of the JavaScript 'suggs' array to a list of suggestions + private void print_suggs_elem(String[] suggs, int index, int textInputIdx, + PrintWriter writer) { + writer.write("suggs[" + textInputIdx + "][" + index + "] = ["); + + for (int i = 0; i < suggs.length; i++ /* as $key=>$val */) { + if (!suggs[i].equals("")) { + writer.write("'" + escape_quote(suggs[i]) + "'"); + if (i + 1 < suggs.length) { + writer.write(", "); + } + } + } + + writer.write("];\n"); + } + + // escape single quote + private String escape_quote(String str) { + return str.replaceAll("'", "\\\\'"); + } + + // handle a server-side error. + private void error_handler(String err, PrintWriter writer) { + writer.write("error = '" + escape_quote(err) + "';\n"); + } + + /* + * get the list of misspelled words. Put the results in the javascript words + * array for each misspelled word, get suggestions and put in the javascript + * suggs array + */ + + private void print_checker_results(PrintWriter writer) { + + String aspell_err = ""; + // create temp file + File tempfile; + try { + tempfile = File.createTempFile("to_translate", "aspell_data_"); + } catch (IOException e1) { + error_handler("Couldn't create tmpfile", writer); + e1.printStackTrace(); + return; + } + // $tempfile = tempnam( tempfiledir, "aspelldata" ); + + try { + // open temp file, add the submitted text. + // FileOutputStream fos = new FileOutputStream(tempfile); + PrintWriter w = new PrintWriter(tempfile); + + for (int i = 0; i < textinputs.length; i++) { + String text = URLDecoder.decode(textinputs[i], "utf-8"); + String[] lines = text.split("\n"); + w.write("%\n"); // exit terse mode + w.write("^" + input_separator + "\n"); + w.write("!\n"); // enter terse mode + + for (int j = 0; j < lines.length; j++/* as $key=>$value */) { + // use carat on each line to escape possible aspell commands + w.write("^" + lines[j] + "\n"); + } + + } + + w.close(); + + // exec aspell command - redirect STDERR to STDOUT + String cmd = aspell_prog + " " + aspell_opts; + + try { + int chr; + String aspellret = ""; + + Process proc = Runtime.getRuntime().exec(cmd); + + BufferedInputStream cmdout = new BufferedInputStream(proc + .getInputStream()); + + OutputStream out = proc.getOutputStream(); + + InputStream in = new FileInputStream(tempfile); + + while ((chr = in.read()) != -1) + out.write(chr); + + in.close(); + out.close(); + + while ((chr = cmdout.read()) != -1) { + aspellret += (char) chr; + } + aspellret += "\n"; + + String[] linesout = aspellret.split("\n"); + + int index = 0; + int text_input_index = -1; + // parse each line of aspell return + for (int i = 0; i < linesout.length; i++/* as $key=>$val */) { + if (linesout[i].length() > 0) { + + String[] suggs = null; + + char chardesc = linesout[i].charAt(0); + // if '&', then not in dictionary but has suggestions + // if '#', then not in dictionary and no suggestions + // if '*', then it is a delimiter between text inputs + // if '@' then version info + + if ((chardesc == '&') || (chardesc == '#')) { + String[] line = linesout[i].split(" ", 5); + print_words_elem(line[1], index, text_input_index, + writer); + if (line.length > 4) { + suggs = line[4].split(", "); + } else { + suggs = new String[0]; + } + print_suggs_elem(suggs, index, text_input_index, + writer); + index++; + } else if (chardesc == '*') { + text_input_index++; + print_textindex_decl(text_input_index, writer); + index = 0; + } else if ((chardesc != '@') && (chardesc != '\0')) { + // assume this is error output + aspell_err += linesout[i]; + } + } + } + if (!aspell_err.equals("")) { + aspell_err = "Error executing " + cmd + "\\n" + aspell_err; + error_handler(aspell_err, writer); + } + } catch (Exception e) { + e.printStackTrace(); + error_handler("System error: Aspell program execution failed (" + + cmd + ")", writer); + } + } catch (Exception e) { + error_handler("System error: Could not open file '" + tempfile + + "' for writing", writer); + } + + // close temp file, delete file + tempfile.delete(); + } + + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + response.setContentType("text/html"); + PrintWriter writer = response.getWriter(); + + String URI = request.getRequestURI(); + + if ((URI.equals(SERVLET_PREFIX)) + && (request.getParameterValues("textinputs[]") == null)) { + InputStream fin = SpellerServlet.class + .getResourceAsStream("/index.html"); + + int chr; + + while ((chr = fin.read()) != -1) { + writer.write(chr); + } + + fin.close(); + } else if (URI.startsWith(SERVLET_PREFIX + "pages/")) { + String[] t = URI.split("/"); + + InputStream fin = SpellerServlet.class.getResourceAsStream("/" + + t[t.length - 1]); + + int chr; + + while ((chr = fin.read()) != -1) { + writer.write(chr); + } + + fin.close(); + } else { + + textinputs = request.getParameterValues("textinputs[]"); + + writer + .write("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n<link rel=\"stylesheet\" type=\"text/css\" href=\"" + + spellercss + + "\" />\n<script language=\"javascript\" src=\"" + + word_win_src + + "\"></script>\n<script language=\"javascript\">\n"); + writer.write("var suggs = new Array();\n" + + "var words = new Array();\n" + + "var textinputs = new Array();\n" + "var error;\n"); + + print_textinputs_var(writer); + + print_checker_results(writer); + + writer.write("\nvar wordWindowObj = new wordWindow();\n" + + "wordWindowObj.originalSpellings = words;\n" + + "wordWindowObj.suggestions = suggs;\n" + + "wordWindowObj.textInputs = textinputs;\n\n"); + + writer + .write("function init_spell() {\n" + + " // check if any error occured during server-side processing\n" + + " if( error ) {\n" + + " alert( error );\n" + + " } else {\n" + + " // call the init_spell() function in the parent frameset\n" + + " if (parent.frames.length) {\n" + + " parent.init_spell( wordWindowObj );\n" + + " } else {\n" + + " alert('This page was loaded outside of a frameset. It might not display properly');\n" + + " }\n" + " }\n" + "}\n"); + + writer.write("</script></head>\n" + + "<body onLoad=\"init_spell();\">\n" + + "<script type=\"text/javascript\">\n" + + "wordWindowObj.writeBody();\n" + "</script>\n" + + "</body>\n" + "</html>\n"); + } + + writer.close(); + } +} \ No newline at end of file Added: trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/jsp/normal.jsp =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/jsp/normal.jsp 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/jsp/normal.jsp 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,26 @@ +<!-- + JBoss, the OpenSource J2EE webOS + Distributable under LGPL license. + See terms of license at gnu.org. + --> +<%@ page language="java" extends="org.jboss.portal.core.servlet.jsp.PortalJsp" %> + <%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="n" %> + <%@ taglib uri="/WEB-INF/tld/forge.tld" prefix="forge" %> + <%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %> + <%@ page isELIgnored ="false" %> + <portlet:defineObjects/> + +<div id="LeftAds"> + +<n:iterate ctx="menuentry"> + <!-- iterated menuentry --> + <div class="item"> + <a href="${n:out("menuentry.url")}"><img src="<forge:imagePath src="ads/images/${n:out('menuentry.name')}"/>" + width="175" height="64" border="0" /> + </a> + </div> +</n:iterate> + +</div> + + \ No newline at end of file Added: trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/tld/forge.tld =================================================================== --- trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/tld/forge.tld 2005-11-11 23:57:37 UTC (rev 1562) +++ trunk/forge/portal-extensions/forge-speller/src/web/WEB-INF/tld/forge.tld 2005-11-12 12:58:50 UTC (rev 1563) @@ -0,0 +1,139 @@ +<taglib xmlns="http://java.sun.com/xml/ns/j2ee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd" + version="2.0"> + <!-- + JBoss, the OpenSource J2EE webOS + Distributable under LGPL license. + See terms of license at gnu.org. + --> + <tlib-version>1.1</tlib-version> + <jsp-version>2.0</jsp-version> + <shortname>forge</shortname> + <info>Forge tags</info> + + <tag> + <name>pageURL</name> + <tagclass>org.jboss.forge.common.taglib.PageURLTag</tagclass> + <attribute> + <name>page</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + <attribute> + <name>form</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + </tag> + + <tag> + <name>param</name> + <tagclass>org.jboss.forge.common.taglib.ParamTag</tagclass> + <attribute> + <name>name</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + <attribute> + <name>value</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + </tag> + + <tag> + <name>wikiURL</name> + <tagclass>org.jboss.forge.common.taglib.WikiURLTag</tagclass> + <attribute> + <name>page</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + </tag> + + <tag> + <name>freezoneURL</name> + <tagclass>org.jboss.forge.common.taglib.FreezoneURLTag</tagclass> + <attribute> + <name>page</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + </tag> + + <tag> + <name>projectURL</name> + <tagclass>org.jboss.forge.common.taglib.ProjectURLTag</tagclass> + <attribute> + <name>project</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + <attribute> + <name>page</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + <attribute> + <name>form</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + </tag> + + <tag> + <name>categoryURL</name> + <tagclass>org.jboss.forge.common.taglib.CategoryURLTag</tagclass> + <attribute> + <name>category</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + <attribute> + <name>form</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + </tag> + + <tag> + <name>selectedProject</name> + <tagclass>org.jboss.forge.common.taglib.SelectedProjectTag</tagcl... [truncated message content] |