Import xinha so we can switch from htmlarea and fix a bunch of in-browser issues that htmlarea has

This commit is contained in:
Chris Morgan
2005-09-30 02:25:07 +00:00
committed by WineHQ
parent 2311d4d572
commit 9242a68c4a
375 changed files with 26623 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
ExecCGI Note:
If you intend to use the perl (.cgi) backend then you will need to have the ExecCGI option enabled for this directory (if you are using Apache), you may be able to do this by adding a file called .htaccess in this directory, with the below contents.
## EXAMPLE .htaccess
Options +ExecCGI
####################
It is however recommended that you use the PHP backend where possible.

View File

@@ -0,0 +1,90 @@
<?php
umask(000);
$temptext = tempnam('/tmp', 'spell_');
if ((!isset($_POST['dictionary'])) || (strlen(trim($_POST['dictionary'])) < 1))
{
$lang = 'en_GB';
}
else
{
$lang = $_POST['dictionary'];
}
$aspell = 'aspell';
$aspell_args = '-a --lang=' . $lang;
if(DIRECTORY_SEPARATOR == '\\') //windows
{
$aspell = 'C:\Progra~1\Aspell\bin\aspell.exe';
}
else //linux
{
// See if there is a local install of aspell here
if(file_exists(dirname(__FILE__) . '/aspell/bin/aspell'))
{
putenv('PATH=' . dirname(__FILE__) . '/aspell/bin:' . getenv('PATH'));
putenv('LD_LIBRARY_PATH=' . dirname(__FILE__) . '/aspell/lib:' . getenv('LD_LIBRARY_PATH'));
$dicfil = dirname(__FILE__) .'/aspell/lib/' . preg_replace('/^.*\/lib\/(aspell\S*)\n.*/s', '$1', `aspell config dict-dir`);
$aspell_args .= ' --dict-dir=' . $dicfil . ' --add-filter-path=' . $dicfil ;
}
}
// Old aspell doesn't know about encoding, which means that unicode will be broke, but
// we should at least let it try.
preg_match('/really aspell ([0-9]+)\.([0-9]+)(?:\.([0-9]+))?/i', `$aspell version`, $aVer);
$aVer = array('major' => (int)$aVer[1], 'minor' => (int)$aVer[2], 'release' => (int)$aVer[3]);
if($aVer['major'] >= 0 && $aVer['minor'] >= 60)
{
$aspell_args .= ' -H --encoding=utf-8';
}
elseif(preg_match('/--encoding/', shell_exec('aspell 2>&1')))
{
$aspell_args .= ' --mode=none --add-filter=sgml --encoding=utf-8';
}
else
{
$aspell_args .= ' --mode=none --add-filter=sgml';
}
// Personal dictionaries
if(!isset($_REQUEST['p_dicts_path']))
{
$_REQUEST['p_dicts_path'] = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'personal_dicts';
}
if(file_exists($_REQUEST['p_dicts_path']) && is_writable($_REQUEST['p_dicts_path']))
{
if(!isset($_REQUEST['p_dicts_name']))
{
if(isset($_COOKIE['SpellChecker_p_dicts_name']))
{
$_REQUEST['p_dicts_name'] = $_COOKIE['SpellChecker_p_dicts_name'];
}
else
{
$_REQUEST['p_dicts_name'] = uniqid('dict');
setcookie('SpellChecker_p_dicts_name', $_REQUEST['p_dicts_name'], time() + 60*60*24*365*10);
}
}
$p_dict_path = $_REQUEST['p_dicts_path'] . DIRECTORY_SEPARATOR . $_REQUEST['p_dicts_name'];
if(!file_exists($p_dict_path))
{
mkdir($p_dict_path);
chmod($p_dict_path, 02770);
}
if(file_exists($p_dict_path) && is_writable($p_dict_path))
{
// Good To Go!
$aspell_args .= ' --home-dir=' . $p_dict_path ;
}
}
$aspelldictionaries = "$aspell dump dicts";
$aspellcommand = "$aspell $aspell_args < $temptext";
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

View File

@@ -0,0 +1,37 @@
// I18N constants
// LANG: "cz", ENCODING: UTF-8
// Author: Jiri Löw, <jirilow@jirilow.com>
// FOR TRANSLATORS:
//
// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
// (at least a valid email address)
//
// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
// (if this is not possible, please include a comment
// that states what encoding is necessary.)
{
"Please confirm that you want to open this link": "Prosím potvrďte otevření tohoto odkazu",
"Cancel": "Zrušit",
"Dictionary": "Slovník",
"Finished list of mispelled words": "Dokončen seznam chybných slov",
"I will open it in a new page.": "Bude otevřen jej v nové stránce.",
"Ignore all": "Ignorovat vše",
"Ignore": "Ignorovat",
"No mispelled words found with the selected dictionary.": "Podle zvoleného slovníku nebyla nalezena žádná chybná slova.",
"Spell check complete, didn't find any mispelled words. Closing now...": "Kontrola správnosti slov dokončena, nebyla nalezena žádná chybná slova. Ukončování ...",
"OK": "OK",
"Original word": "Původní slovo",
"Please wait. Calling spell checker.": "Prosím čekejte. Komunikuace s kontrolou správnosti slov.",
"Please wait: changing dictionary to": "Prosím čekejte: změna adresáře na",
"This will drop changes and quit spell checker. Please confirm.": "Změny budou zrušeny a kontrola správnosti slov ukončena. Prosím potvrďte.",
"Re-check": "Překontrolovat",
"Replace all": "Zaměnit všechno",
"Replace with": "Zaměnit za",
"Replace": "Zaměnit",
"Spell-check": "Kontrola správnosti slov",
"Suggestions": "Doporučení",
"One moment...": "strpení prosím ;-)"
}

View File

@@ -0,0 +1,36 @@
// I18N constants
// LANG: "da", ENCODING: UTF-8
// Author: Steen SÞnderup, <steen@soenderup.com>
// FOR TRANSLATORS:
//
// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
// (at least a valid email address)
//
// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
// (if this is not possible, please include a comment
// that states what encoding is necessary.)
{
"Please confirm that you want to open this link": "Vil du fÞlge dette link?",
"Cancel": "Anuler",
"Dictionary": "Ordbog",
"Finished list of mispelled words": "Listen med stavefejl er gennemgået",
"I will open it in a new page.": "Jeg vil åbne det i en ny side.",
"Ignore all": "Ignorer alle",
"Ignore": "Ignorer",
"No mispelled words found with the selected dictionary.": "Der blev ikke fundet nogle stavefejl med den valgte ordbog.",
"Spell check complete, didn't find any mispelled words. Closing now...": "Stavekontrollen er gennemfÞrt, der blev ikke fundet nogle stavefejl. Lukker...",
"OK": "OK",
"Original word": "Oprindeligt ord",
"Please wait. Calling spell checker.": "Vent venligst. Henter stavekontrol.",
"Please wait: changing dictionary to": "Vent venligst: skifter ordbog til",
"This will drop changes and quit spell checker. Please confirm.": "Alle dine Êndringer vil gå tabt, vil du fortsÊtte?",
"Re-check": "Tjek igen",
"Replace all": "Erstat alle",
"Replace with": "Erstat med",
"Replace": "Erstat",
"Spell-check": "Stavekontrol",
"Suggestions": "Forslag",
"One moment...": "Vent venligst"
}

View File

@@ -0,0 +1,28 @@
// I18N constants
// LANG: "en", ENCODING: UTF-8
// Author: Broxx, <broxx@broxx.com>
{
"Please confirm that you want to open this link": "Wollen Sie diesen Link oeffnen",
"Cancel": "Abbrechen",
"Dictionary": "Woerterbuch",
"Finished list of mispelled words": "Liste der nicht bekannten Woerter",
"I will open it in a new page.": "Wird auf neuer Seite geoeffnet",
"Ignore all": "Alle ignorieren",
"Ignore": "Ignorieren",
"No mispelled words found with the selected dictionary.": "Keine falschen Woerter mit gewaehlten Woerterbuch gefunden",
"Spell check complete, didn't find any mispelled words. Closing now...": "Rechtsschreibpruefung wurde ohne Fehler fertiggestellt. Wird nun geschlossen...",
"OK": "OK",
"Original word": "Original Wort",
"Please wait. Calling spell checker.": "Bitte warten. Woerterbuch wird durchsucht.",
"Please wait: changing dictionary to": "Bitte warten: Woerterbuch wechseln zu",
"This will drop changes and quit spell checker. Please confirm.": "Aenderungen werden nicht uebernommen. Bitte bestaettigen.",
"Re-check": "Neuueberpruefung",
"Replace all": "Alle ersetzen",
"Replace with": "Ersetzen mit",
"Replace": "Ersetzen",
"Spell-check": "Ueberpruefung",
"Suggestions": "Vorschlag",
"One moment...": "bittsche wartn ;-)"
}

View File

@@ -0,0 +1,38 @@
// I18N constants
// LANG: "fr", ENCODING: UTF-8
// Author: Laurent Vilday, mokhet@mokhet.com
// FOR TRANSLATORS:
//
// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
// (at least a valid email address)
//
// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
// (if this is not possible, please include a comment
// that states what encoding is necessary.)
{
"Please confirm that you want to open this link": "Veuillez confirmer l'ouverture de ce lien",
"Cancel": "Annuler",
"Dictionary": "Dictionnaire",
"Finished list of mispelled words": "Liste des mots mal orthographiés",
"I will open it in a new page.": "Ouverture dans une nouvelle fenêtre",
"Ignore all": "Tout ignorer",
"Ignore": "Ignorer",
"No mispelled words found with the selected dictionary.": "Aucune erreur orthographique avec le dictionnaire sélectionné.",
"Spell check complete, didn't find any mispelled words. Closing now...": "Vérification terminée, aucune erreur orthographique détectée. Fermeture en cours...",
"OK": "OK",
"Original word": "Mot original",
"Please wait. Calling spell checker.": "Veuillez patienter. Appel du correcteur.",
"Please wait: changing dictionary to": "Veuillez patienter. Changement du dictionnaire vers",
"This will drop changes and quit spell checker. Please confirm.": "Ceci fermera la fenêtre et annulera les modifications. Veuillez confirmer.",
"Re-check": "Vérifier encore",
"Replace all": "Tout remplacer",
"Replace with": "Remplacer par",
"Replace": "Remplacer",
"Revert": "Annuler",
"Spell-check": "Correction",
"Suggestions": "Suggestions",
"One moment...": "Veuillez patienter"
}

View File

@@ -0,0 +1,38 @@
// I18N constants
// LANG: "en", ENCODING: UTF-8
// Author: Mihai Bazon, http://dynarch.com/mishoo
// FOR TRANSLATORS:
//
// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
// (at least a valid email address)
//
// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
// (if this is not possible, please include a comment
// that states what encoding is necessary.)
{
"Please confirm that you want to open this link": "אנא אשר שברצונך לפתוח קישור זה",
"Cancel": "ביטול",
"Dictionary": "מילון",
"Finished list of mispelled words": "הסתיימה רשימת המילים המאויתות באופן שגוי",
"I will open it in a new page.": "אני אפתח את זה בחלון חדש.",
"Ignore all": "התעלם מהכל",
"Ignore": "התעלם",
"No mispelled words found with the selected dictionary.": "לא נמצאו מילים מאויתות באופן שגוי עם המילון הנבחר.",
"Spell check complete, didn't find any mispelled words. Closing now...": "בדיקת האיות נסתיימה, לא נמצאו מילים מאויתות באופן שגוי. נסגר כעת...",
"OK": "אישור",
"Original word": "המילה המקורית",
"Please wait. Calling spell checker.": "אנא המתן. קורא לבודק איות.",
"Please wait: changing dictionary to": "אנא המתן: מחליף מילון ל-",
"This will drop changes and quit spell checker. Please confirm.": "זה יבטל את השינויים ויצא מבודק האיות. אנא אשר.",
"Re-check": "בדוק מחדש",
"Replace all": "החלף הכל",
"Replace with": "החלף ב-",
"Replace": "החלף",
"Revert": "החזר שינויים",
"Spell-check": "בדיקת איות",
"Suggestions": "הצעות",
"One moment...": "ענא המטן ;-)"
}

View File

@@ -0,0 +1,37 @@
// I18N constants
// LANG: "hu", ENCODING: UTF-8
// Author: Miklós Somogyi, <somogyine@vnet.hu>
// FOR TRANSLATORS:
//
// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
// (at least a valid email address)
//
// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
// (if this is not possible, please include a comment
// that states what encoding is necessary.)
{
"Please confirm that you want to open this link": "Megerősítés",
"Cancel": "Mégsem",
"Dictionary": "Szótár",
"Finished list of mispelled words": "A tévesztett szavak listájának vége",
"I will open it in a new page.": "Megnyitás új lapon",
"Ignore all": "Minden elvetése",
"Ignore": "Elvetés",
"No mispelled words found with the selected dictionary.": "A választott szótár szerint nincs tévesztett szó.",
"Spell check complete, didn't find any mispelled words. Closing now...": "A helyesírásellenőrzés kész, tévesztett szó nem fordult elő. Bezárás...",
"OK": "Rendben",
"Original word": "Eredeti szó",
"Please wait. Calling spell checker.": "Kis türelmet, a helyesírásellenőrző hívása folyamatban.",
"Please wait: changing dictionary to": "Kis türelmet, szótár cseréje",
"This will drop changes and quit spell checker. Please confirm.": "Kilépés a változások eldobásával. Jóváhagyja?",
"Re-check": "Újraellenőrzés",
"Replace all": "Mind cseréje",
"Replace with": "Csere a következőre:",
"Replace": "Csere",
"Spell-check": "Helyesírásellenőrzés",
"Suggestions": "Tippek",
"One moment...": "Kis türelmet ;-)"
}

View File

@@ -0,0 +1,39 @@
// I18N constants
// LANG: "nl", ENCODING: UTF-8
// Author: A.H van den Broek http://www.kontaktfm.nl
// Email : tonbroek@kontaktfm.nl
// FOR TRANSLATORS:
//
// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
// (at least a valid email address)
//
// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
// (if this is not possible, please include a comment
// that states what encoding is necessary.)
{
"Please confirm that you want to open this link": "Weet u zeker dat u deze link wilt openen?",
"Cancel": "Annuleer",
"Dictionary": "Woordenboek",
"Finished list of mispelled words": "klaar met de lijst van fouten woorden",
"I will open it in a new page.": "Ik zal het in een nieuwe pagina openen.",
"Ignore all": "alles overslaan",
"Ignore": "Overslaan",
"No mispelled words found with the selected dictionary.": "Geen fouten gevonden met dit woordenboek.",
"Spell check complete, didn't find any mispelled words. Closing now...": "Spell checking is klaar, geen fouten gevonden. spell checking word gesloten...",
"OK": "OK",
"Original word": "Originele woord",
"Please wait. Calling spell checker.": "Even wachten. spell checker wordt geladen.",
"Please wait: changing dictionary to": "even wachten: woordenboek wordt veranderd naar",
"This will drop changes and quit spell checker. Please confirm.": "Dit zal alle veranderingen annuleren en de spell checker sluiten. Weet u het zeker?",
"Re-check": "Opnieuw",
"Replace all": "Alles vervangen",
"Replace with": "Vervangen met",
"Replace": "Vervangen",
"Revert": "Omkeren",
"Spell-check": "Spell-check",
"Suggestions": "Suggestie",
"One moment...": "Even wachten ;-)"
}

View File

@@ -0,0 +1,27 @@
// I18N constants
// LANG: "no", ENCODING: UTF-8
// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com
{
"Please confirm that you want to open this link": "Ønsker du å åpne denne lenken",
"Cancel": "Avbryt",
"Dictionary": "Ordliste",
"Finished list of mispelled words": "Ferdig med liste over feilstavede ord",
"I will open it in a new page.": "Åpnes i ny side",
"Ignore all": "Ignorer alle",
"Ignore": "Ignorer",
"No mispelled words found with the selected dictionary.": "Ingen feilstavede ord funnet med den valgte ordlisten",
"Spell check complete, didn't find any mispelled words. Closing now...": "Stavekontroll fullført, ingen feilstavede ord ble funnet, stavekontroll avsluttes.",
"OK": "OK",
"Original word": "Opprinnelig ord",
"Please wait. Calling spell checker.": "Vennligst vennt, kaller opp stavekontrollprogrammet",
"Please wait: changing dictionary to": "Vennligst vennt, endrer ordliste til",
"This will drop changes and quit spell checker. Please confirm.": "Dette vil droppe endringene og avbryte stavekontrollen, vennligst bekreft.",
"Re-check": "Kjør stavekontroll på nytt",
"Replace all": "Erstatt alle",
"Replace with": "Erstatt med",
"Replace": "Erstatt",
"Spell-check": "Stavekontroll",
"Suggestions": "Forslag",
"One moment...": "Et øyeblikk..."
}

View File

@@ -0,0 +1,37 @@
// I18N constants
// LANG: "ro", ENCODING: UTF-8
// Author: Mihai Bazon, http://dynarch.com/mishoo
// FOR TRANSLATORS:
//
// 1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
// (at least a valid email address)
//
// 2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
// (if this is not possible, please include a comment
// that states what encoding is necessary.)
{
"Please confirm that you want to open this link": "Vă rog confirmaţi că vreţi să deschideţi acest link",
"Cancel": "Anulează",
"Dictionary": "Dicţionar",
"Finished list of mispelled words": "Am terminat lista de cuvinte greşite",
"I will open it in a new page.": "O voi deschide într-o altă fereastră.",
"Ignore all": "Ignoră toate",
"Ignore": "Ignoră",
"No mispelled words found with the selected dictionary.": "Nu am găsit nici un cuvânt greşit cu acest dicţionar.",
"Spell check complete, didn't find any mispelled words. Closing now...": "Am terminat, nu am detectat nici o greşeală. Acum închid fereastra...",
"OK": "OK",
"Original word": "Cuvântul original",
"Please wait. Calling spell checker.": "Vă rog aşteptaţi. Apelez spell-checker-ul.",
"Please wait: changing dictionary to": "Vă rog aşteptaţi. Schimb dicţionarul cu",
"This will drop changes and quit spell checker. Please confirm.": "Doriţi să renunţaţi la modificări şi să închid spell-checker-ul?",
"Re-check": "Scanează",
"Replace all": "Înlocuieşte toate",
"Replace with": "Înlocuieşte cu",
"Replace": "Înlocuieşte",
"Spell-check": "Detectează greşeli",
"Suggestions": "Sugestii",
"One moment...": "va rog ashteptatzi ;-)"
}

View File

@@ -0,0 +1,114 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
<html>
<head>
<title>HTMLArea Spell Checker</title>
</head>
<body>
<h1>HTMLArea Spell Checker</h1>
<p>The HTMLArea Spell Checker subsystem consists of the following
files:</p>
<ul>
<li>spell-checker.js &mdash; the spell checker plugin interface for
HTMLArea</li>
<li>spell-checker-ui.html &mdash; the HTML code for the user
interface</li>
<li>spell-checker-ui.js &mdash; functionality of the user
interface</li>
<li>spell-checker-logic.cgi &mdash; Perl CGI script that checks a text
given through POST for spelling errors</li>
<li>spell-checker-style.css &mdash; style for mispelled words</li>
<li>lang/en.js &mdash; main language file (English).</li>
</ul>
<h2>Process overview</h2>
<p>
When an end-user clicks the "spell-check" button in the HTMLArea
editor, a new window is opened with the URL of "spell-check-ui.html".
This window initializes itself with the text found in the editor (uses
<tt>window.opener.SpellChecker.editor</tt> global variable) and it
submits the text to the server-side script "spell-check-logic.cgi".
The target of the FORM is an inline frame which is used both to
display the text and correcting.
</p>
<p>
Further, spell-check-logic.cgi calls Aspell for each portion of plain
text found in the given HTML. It rebuilds an HTML file that contains
clear marks of which words are incorrect, along with suggestions for
each of them. This file is then loaded in the inline frame. Upon
loading, a JavaScript function from "spell-check-ui.js" is called.
This function will retrieve all mispelled words from the HTML of the
iframe and will setup the user interface so that it allows correction.
</p>
<h2>The server-side script (spell-check-logic.cgi)</h2>
<p>
<strong>Unicode safety</strong> &mdash; the program <em>is</em>
Unicode safe. HTML entities are expanded into their corresponding
Unicode characters. These characters will be matched as part of the
word passed to Aspell. All texts passed to Aspell are in Unicode
(when appropriate). <strike>However, Aspell seems to not support Unicode
yet (<a
href="http://mail.gnu.org/archive/html/aspell-user/2000-11/msg00007.html">thread concerning Aspell and Unicode</a>).
This mean that words containing Unicode
characters that are not in 0..255 are likely to be reported as "mispelled" by Aspell.</strike>
</p>
<p>
<strong style="font-variant: small-caps; color:
red;">Update:</strong> though I've never seen it mentioned
anywhere, it looks that Aspell <em>does</em>, in fact, speak
Unicode. Or else, maybe <code>Text::Aspell</code> does
transparent conversion; anyway, this new version of our
SpellChecker plugin is, as tests show so far, fully
Unicode-safe... well, probably the <em>only</em> freeware
Web-based spell-checker which happens to have Unicode support.
</p>
<p>
The Perl Unicode manual (man perluniintro) states:
</p>
<blockquote>
<em>
Starting from Perl 5.6.0, Perl has had the capacity to handle Unicode
natively. Perl 5.8.0, however, is the first recommended release for
serious Unicode work. The maintenance release 5.6.1 fixed many of the
problems of the initial Unicode implementation, but for example regular
expressions still do not work with Unicode in 5.6.1.
</em>
</blockquote>
<p>In other words, do <em>not</em> assume that this script is
Unicode-safe on Perl interpreters older than 5.8.0.</p>
<p>The following Perl modules are required:</p>
<ul>
<li><a href="http://search.cpan.org/search?query=Text%3A%3AAspell&mode=all" target="_blank">Text::Aspell</a></li>
<li><a href="http://search.cpan.org/search?query=XML%3A%3ADOM&mode=all" target="_blank">XML::DOM</a></li>
<li><a href="http://search.cpan.org/search?query=CGI&mode=all" target="_blank">CGI</a></li>
</ul>
<p>Of these, only Text::Aspell might need to be installed manually. The
others are likely to be available by default in most Perl distributions.</p>
<hr />
<address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
<!-- Created: Thu Jul 17 13:22:27 EEST 2003 -->
<!-- hhmts start --> Last modified: Fri Jan 30 19:14:11 EET 2004 <!-- hhmts end -->
<!-- doc-lang: English -->
</body>
</html>

View File

@@ -0,0 +1,210 @@
#! /usr/bin/perl -w
# Spell Checker Plugin for HTMLArea-3.0
# Sponsored by www.americanbible.org
# Implementation by Mihai Bazon, http://dynarch.com/mishoo/
#
# (c) dynarch.com 2003.
# Distributed under the same terms as HTMLArea itself.
# This notice MUST stay intact for use (see license.txt).
#
# $Id$
use strict;
use utf8;
use Encode;
use Text::Aspell;
use XML::DOM;
use CGI;
my $TIMER_start = undef;
eval {
use Time::HiRes qw( gettimeofday tv_interval );
$TIMER_start = [gettimeofday()];
};
# use POSIX qw( locale_h );
binmode STDIN, ':utf8';
binmode STDOUT, ':utf8';
my $debug = 0;
my $speller = new Text::Aspell;
my $cgi = new CGI;
my $total_words = 0;
my $total_mispelled = 0;
my $total_suggestions = 0;
my $total_words_suggested = 0;
# FIXME: report a nice error...
die "Can't create speller!" unless $speller;
my $dict = $cgi->param('dictionary') || $cgi->cookie('dictionary') || 'en';
# add configurable option for this
$speller->set_option('lang', $dict);
$speller->set_option('encoding', 'UTF-8');
#setlocale(LC_CTYPE, $dict);
# ultra, fast, normal, bad-spellers
# bad-spellers seems to cause segmentation fault
$speller->set_option('sug-mode', 'normal');
my %suggested_words = ();
keys %suggested_words = 128;
my $file_content = decode('UTF-8', $cgi->param('content'));
$file_content = parse_with_dom($file_content);
my $ck_dictionary = $cgi->cookie(-name => 'dictionary',
-value => $dict,
-expires => '+30d');
print $cgi->header(-type => 'text/html; charset: utf-8',
-cookie => $ck_dictionary);
my $js_suggested_words = make_js_hash(\%suggested_words);
my $js_spellcheck_info = make_js_hash_from_array
([
[ 'Total words' , $total_words ],
[ 'Mispelled words' , $total_mispelled . ' in dictionary \"'.$dict.'\"' ],
[ 'Total suggestions' , $total_suggestions ],
[ 'Total words suggested' , $total_words_suggested ],
[ 'Spell-checked in' , defined $TIMER_start ? (tv_interval($TIMER_start) . ' seconds') : 'n/a' ]
]);
print qq^<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" media="all" href="spell-check-style.css" />
<script type="text/javascript">
var suggested_words = { $js_suggested_words };
var spellcheck_info = { $js_spellcheck_info }; </script>
</head>
<body onload="window.parent.finishedSpellChecking();">^;
print $file_content;
if ($cgi->param('init') eq '1') {
my @dicts = $speller->dictionary_info();
my $dictionaries = '';
foreach my $i (@dicts) {
next if $i->{jargon};
my $name = $i->{name};
if ($name eq $dict) {
$name = '@'.$name;
}
$dictionaries .= ',' . $name;
}
$dictionaries =~ s/^,//;
print qq^<div id="HA-spellcheck-dictionaries">$dictionaries</div>^;
}
print '</body></html>';
# Perl is beautiful.
sub spellcheck {
my $node = shift;
my $doc = $node->getOwnerDocument;
my $check = sub { # called for each word in the text
# input is in UTF-8
my $word = shift;
my $already_suggested = defined $suggested_words{$word};
++$total_words;
if (!$already_suggested && $speller->check($word)) {
return undef;
} else {
# we should have suggestions; give them back to browser in UTF-8
++$total_mispelled;
if (!$already_suggested) {
# compute suggestions for this word
my @suggestions = $speller->suggest($word);
my $suggestions = decode($speller->get_option('encoding'), join(',', @suggestions));
$suggested_words{$word} = $suggestions;
++$total_suggestions;
$total_words_suggested += scalar @suggestions;
}
# HA-spellcheck-error
my $err = $doc->createElement('span');
$err->setAttribute('class', 'HA-spellcheck-error');
my $tmp = $doc->createTextNode;
$tmp->setNodeValue($word);
$err->appendChild($tmp);
return $err;
}
};
while ($node->getNodeValue =~ /([\p{IsWord}']+)/) {
my $word = $1;
my $before = $`;
my $after = $';
my $df = &$check($word);
if (!$df) {
$before .= $word;
}
{
my $parent = $node->getParentNode;
my $n1 = $doc->createTextNode;
$n1->setNodeValue($before);
$parent->insertBefore($n1, $node);
$parent->insertBefore($df, $node) if $df;
$node->setNodeValue($after);
}
}
};
sub check_inner_text {
my $node = shift;
my $text = '';
for (my $i = $node->getFirstChild; defined $i; $i = $i->getNextSibling) {
if ($i->getNodeType == TEXT_NODE) {
spellcheck($i);
}
}
};
sub parse_with_dom {
my ($text) = @_;
$text = '<spellchecker>'.$text.'</spellchecker>';
my $parser = new XML::DOM::Parser;
if ($debug) {
open(FOO, '>:utf8', '/tmp/foo');
print FOO $text;
close FOO;
}
my $doc = $parser->parse($text);
my $nodes = $doc->getElementsByTagName('*');
my $n = $nodes->getLength;
for (my $i = 0; $i < $n; ++$i) {
my $node = $nodes->item($i);
if ($node->getNodeType == ELEMENT_NODE) {
check_inner_text($node);
}
}
my $ret = $doc->toString;
$ret =~ s{<spellchecker>(.*)</spellchecker>}{$1}sg;
return $ret;
};
sub make_js_hash {
my ($hash) = @_;
my $js_hash = '';
while (my ($key, $val) = each %$hash) {
$js_hash .= ',' if $js_hash;
$js_hash .= '"'.$key.'":"'.$val.'"';
}
return $js_hash;
};
sub make_js_hash_from_array {
my ($array) = @_;
my $js_hash = '';
foreach my $i (@$array) {
$js_hash .= ',' if $js_hash;
$js_hash .= '"'.$i->[0].'":"'.$i->[1].'"';
}
return $js_hash;
};

View File

@@ -0,0 +1,166 @@
<?php
$text = stripslashes($_POST['content']);
// Convert UTF-8 multi-bytes into decimal character entities. This is because
// aspell isn't fully utf8-aware
$text = preg_replace('/([\xC0-\xDF][\x80-\xBF])/e', "'&#' . utf8_ord('\$1') . ';'", $text);
$text = preg_replace('/([\xE0-\xEF][\x80-\xBF][\x80-\xBF])/e', "'&#' . utf8_ord('\$1') . ';'", $text);
$text = preg_replace('/([\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])/e', "'&#' . utf8_ord('\$1') . ';'", $text);
function utf8_ord($chr)
{
switch(strlen($chr))
{
case 1 :
return ord($chr);
case 2 :
$ord = ord($chr{1}) & 63;
$ord = $ord | ((ord($chr{0}) & 31) << 6);
return $ord;
case 3 :
$ord = ord($chr{2}) & 63;
$ord = $ord | ((ord($chr{1}) & 63) << 6);
$ord = $ord | ((ord($chr{0}) & 15) << 12);
return $ord;
case 4 :
$ord = ord($chr{3}) & 63;
$ord = $ord | ((ord($chr{2}) & 63) << 6);
$ord = $ord | ((ord($chr{1}) & 63) << 12);
$ord = $ord | ((ord($chr{0}) & 7) << 18);
return $ord;
default :
trigger_error('Character not utf-8', E_USER_ERROR);
}
}
require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'aspell_setup.php');
##############################################################################
header('Content-Type: text/html; charset=utf-8');
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" media="all" href="spell-check-style.css" />';
// Lets define some values outside the condition below, in case we have an empty
// document.
$textarray = array();
$varlines = '<script type="text/javascript">var suggested_words = { ';
$infolines = 'var spellcheck_info = {';
$counter = 0;
$suggest_count = 0;
if (trim($text) != "")
{
if ($fd = fopen($temptext, 'w'))
{
$textarray = explode("\n", $text);
fwrite ($fd, "!\n");
foreach ($textarray as $key=>$value)
{
// adding the carat to each line prevents the use of aspell commands within the text...
fwrite($fd, "^$value\n");
}
fclose($fd);
chmod($temptext, 0777);
// next run aspell
$return = shell_exec($aspellcommand . ' 2>&1');
// echo $return;
unlink($temptext);
$returnarray = explode("\n", $return);
$returnlines = count($returnarray);
//print_r(htmlentities($return));
$textlines = count($textarray);
$lineindex = -1;
$poscorrect = 0;
foreach ($returnarray as $key=>$value)
{
// if there is a correction here, processes it, else move the $textarray pointer to the next line
if (substr($value, 0, 1) == '&')
{
$counter=$counter+1;
$correction = explode(' ', $value);
$word = $correction[1];
$suggest_count += $correction[2];
$absposition = substr($correction[3], 0, -1) - 1;
$position = $absposition + $poscorrect;
$niceposition = $lineindex.','.$absposition;
$suggstart = strpos($value, ':') + 2;
$suggestions = substr($value, $suggstart);
$suggestionarray = explode(', ', $suggestions);
$beforeword = substr($textarray[$lineindex], 0, $position);
$afterword = substr($textarray[$lineindex], $position + strlen($word));
$textarray[$lineindex] = $beforeword.'<span class="HA-spellcheck-error">'.$word.'</span>'.$afterword;
$suggestion_list = '';
foreach ($suggestionarray as $key=>$value)
{
$suggestion_list .= $value.',';
}
$suggestion_list = substr($suggestion_list, 0, strlen($suggestion_list) - 1);
$varlines .= '"'.$word.'":"'.$suggestion_list.'",';
$poscorrect = $poscorrect + 41;
}
elseif (substr($value, 0, 1) == '#')
{
$correction = explode(' ', $value);
$word = $correction[1];
$absposition = $correction[2] - 1;
$position = $absposition + $poscorrect;
$niceposition = $lineindex.','.$absposition;
$beforeword = substr($textarray[$lineindex], 0, $position);
$afterword = substr($textarray[$lineindex], $position + strlen($word));
$textarray[$lineindex] = $beforeword.$word.$afterword;
$textarray[$lineindex] = $beforeword.'<span class="HA-spellcheck-error">'.$word.'</span><span class="HA-spellcheck-suggestions">'.$word.'</span>'.$afterword;
// $poscorrect = $poscorrect;
$poscorrect = $poscorrect + 88 + strlen($word);
}
else
{
//print "Done with line $lineindex, next line...<br><br>";
$poscorrect = 0;
$lineindex = $lineindex + 1;
}
}
}
else
{
// This one isnt used for anything at the moment!
$return = 'failed to open!';
}
}
else
{
$returnlines=0;
}
$infolines .= '"Language Used":"'.$lang.'",';
$infolines .= '"Mispelled words":"'.$counter.'",';
$infolines .= '"Total words suggested":"'.$suggest_count.'",';
$infolines .= '"Total Lines Checked":"'.$returnlines.'"';
$infolines .= '};';
$varlines = substr($varlines, 0, strlen($varlines) - 1);
echo $varlines.'};'.$infolines.'</script>';
echo '</head>
<body onload="window.parent.finishedSpellChecking();">';
foreach ($textarray as $key=>$value)
{
echo $value;
}
$dictionaries = str_replace(chr(10),",", shell_exec($aspelldictionaries));
if(ereg(",$",$dictionaries))
$dictionaries = ereg_replace(",$","",$dictionaries);
echo '<div id="HA-spellcheck-dictionaries">'.$dictionaries.'</div>';
echo '</body></html>';
?>

View File

@@ -0,0 +1,38 @@
<?php
require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'aspell_setup.php');
$to_p_dict = $_REQUEST['to_p_dict'] ? $_REQUEST['to_p_dict'] : array();
$to_r_list = $_REQUEST['to_r_list'] ? $_REQUEST['to_r_list'] : array();
print_r($to_r_list);
if($to_p_dict || $to_r_list)
{
if($fh = fopen($temptext, 'w'))
{
foreach($to_p_dict as $personal_word)
{
$cmd = '&' . $personal_word . "\n";
echo $cmd;
fwrite($fh, $cmd, strlen($cmd));
}
foreach($to_r_list as $replace_pair)
{
$cmd = '$$ra ' . $replace_pair[0] . ' , ' . $replace_pair[1] . "\n";
echo $cmd;
fwrite($fh, $cmd, strlen($cmd));
}
$cmd = "#\n";
echo $cmd;
fwrite($fh, $cmd, strlen($cmd));
fclose($fh);
}
else
{
die("Can't Write");
}
echo $aspellcommand."\n";
echo shell_exec($aspellcommand . ' 2>&1');
unlink($temptext);
}
?>

View File

@@ -0,0 +1,10 @@
.HA-spellcheck-error { border-bottom: 1px dashed #f00; cursor: default; }
.HA-spellcheck-same { background-color: #cef; color: #000; }
.HA-spellcheck-hover { background-color: #433; color: white; }
.HA-spellcheck-fixed { border-bottom: 1px dashed #0b8; }
.HA-spellcheck-current { background-color: #9be; color: #000; }
.HA-spellcheck-suggestions { display: none; }
#HA-spellcheck-dictionaries { display: none; }
a:link, a:visited { color: #55e; }

View File

@@ -0,0 +1,124 @@
<!--
Strangely, IE sucks with or without the DOCTYPE switch.
I thought it would only suck without it.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
Spell Checker Plugin for HTMLArea-3.0
Sponsored by www.americanbible.org
Implementation by Mihai Bazon, http://dynarch.com/mishoo/
(c) dynarch.com 2003.
Distributed under the same terms as HTMLArea itself.
This notice MUST stay intact for use (see license.txt).
$Id$
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Spell Checker</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="spell-check-ui.js"></script>
<style type="text/css">
html, body { height: 100%; margin: 0px; padding: 0px; background-color: #fff;
color: #000; }
a:link, a:visited { color: #00f; text-decoration: none; }
a:hover { color: #f00; text-decoration: underline; }
table { background-color: ButtonFace; color: ButtonText;
font-family: tahoma,verdana,sans-serif; font-size: 11px; }
iframe { background-color: #fff; color: #000; height: 100%; width: 100%; }
.controls { width: 13em; }
.controls .sectitle { /* background-color: #736c6c; color: #fff;
border-top: 1px solid #000; border-bottom: 1px solid #fff; */
text-align: center;
font-weight: bold; padding: 2px 4px; }
.controls .secbody { margin-bottom: 10px; }
button, select { font-family: tahoma,verdana,sans-serif; font-size: 11px; }
button { width: 6em; padding: 0px; }
input, select { font-family: fixed,"andale mono",monospace; }
#v_currentWord { color: #f00; font-weight: bold; }
#statusbar { padding: 7px 0px 0px 5px; }
#status { font-weight: bold; }
</style>
</head>
<body onload="initDocument()">
<form style="display: none;" action="spell-check-logic.cgi"
method="post" target="framecontent"
accept-charset="UTF-8"
><input type="hidden" name="content" id="f_content"
/><input type="hidden" name="dictionary" id="f_dictionary"
/><input type="hidden" name="init" id="f_init" value="1"
/></form>
<table style="height: 100%; width: 100%; border-collapse: collapse;" cellspacing="0" cellpadding="0">
<tr>
<td colspan="2" style="height: 1em; padding: 2px;">
<div style="float: right; padding: 2px;"><span>Dictionary</span>
<select id="v_dictionaries" style="width: 10em"></select>
<button id="b_recheck">Re-check</button>
</div>
<span id="status">Please wait. Calling spell checker.</span>
</td>
</tr>
<tr>
<td valign="top" class="controls">
<div class="secbody" style="text-align: center">
<button id="b_info">Info</button>
</div>
<div class="sectitle">Original word</div>
<div class="secbody" id="v_currentWord" style="text-align:
center; margin-bottom: 0px;">pliz weit ;-)</div>
<div class="secbody" style="text-align: center">
<button id="b_revert">Revert</button>
</div>
<div class="sectitle">Replace with</div>
<div class="secbody">
<input type="text" id="v_replacement" style="width: 94%; margin-left: 3%;" /><br />
<div style="text-align: center; margin-top: 2px;">
<button id="b_replace">Replace</button><button
id="b_replall">Replace all</button><br /><button
id="b_ignore">Ignore</button><button
id="b_ignall">Ignore all</button>
<button
id="b_learn">Learn</button>
</div>
</div>
<div class="sectitle">Suggestions</div>
<div class="secbody">
<select size="11" style="width: 94%; margin-left: 3%;" id="v_suggestions"></select>
</div>
</td>
<td>
<iframe src="about:blank" width="100%" height="100%"
id="i_framecontent" name="framecontent"></iframe>
</td>
</tr>
<tr>
<td style="height: 1em;" colspan="2">
<div style="padding: 4px 2px 2px 2px; float: right;">
<button id="b_ok">OK</button>
<button id="b_cancel">Cancel</button>
</div>
<div id="statusbar"></div>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,445 @@
// Spell Checker Plugin for HTMLArea-3.0
// Sponsored by www.americanbible.org
// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
//
// (c) dynarch.com 2003.
// Distributed under the same terms as HTMLArea itself.
// This notice MUST stay intact for use (see license.txt).
//
// $Id$
// internationalization file was already loaded in parent ;-)
var SpellChecker = window.opener.SpellChecker;
var HTMLArea = window.opener.HTMLArea;
var _editor_url = window.opener._editor_url;
var is_ie = HTMLArea.is_ie;
var editor = SpellChecker.editor;
var frame = null;
var currentElement = null;
var wrongWords = null;
var modified = false;
var allWords = {};
var fixedWords = [];
var suggested_words = {};
var to_p_dict = []; // List of words to add to personal dictionary.
var to_r_list = []; // List of words to add to replacement list.
function _lc(string) {
return HTMLArea._lc(string, 'SpellChecker');
}
function makeCleanDoc(leaveFixed) {
// document.getElementById("status").innerHTML = 'Please wait: rendering valid HTML';
var words = wrongWords.concat(fixedWords);
for (var i = words.length; --i >= 0;) {
var el = words[i];
if (!(leaveFixed && /HA-spellcheck-fixed/.test(el.className))) {
el.parentNode.insertBefore(el.firstChild, el);
el.parentNode.removeChild(el);
} else
el.className = "HA-spellcheck-fixed";
}
// we should use innerHTML here, but IE6's implementation fucks up the
// HTML to such extent that our poor Perl parser doesn't understand it
// anymore.
return window.opener.HTMLArea.getHTML(frame.contentWindow.document.body, false, editor);
};
function recheckClicked() {
document.getElementById("status").innerHTML = _lc("Please wait: changing dictionary to") + ': "' + document.getElementById("f_dictionary").value + '".';
var field = document.getElementById("f_content");
field.value = makeCleanDoc(true);
field.form.submit();
};
function saveClicked() {
if (modified) {
editor.setHTML(makeCleanDoc(false));
}
if(to_p_dict.length || to_r_list.length && editor.config.SpellChecker.backend == 'php')
{
var data = {};
for(var i = 0;i < to_p_dict.length;i++)
{
data['to_p_dict[' + i + ']'] = to_p_dict[i];
}
for(var i = 0;i < to_r_list.length;i++)
{
data['to_r_list[' + i + '][0]'] = to_r_list[i][0];
data['to_r_list[' + i + '][1]'] = to_r_list[i][1];
}
// var win = window;
window.opener.HTMLArea._postback(_editor_url + '/plugins/SpellChecker/spell-check-savedicts.php', data);
window.close();
}
else
{
window.close();
}
return false;
};
function cancelClicked() {
var ok = true;
if (modified) {
ok = confirm(_lc("This will drop changes and quit spell checker. Please confirm."));
}
if (ok) {
window.close();
}
return false;
};
function replaceWord(el) {
var replacement = document.getElementById("v_replacement").value;
var this_word_modified = (el.innerHTML != replacement);
if (this_word_modified)
modified = true;
if (el) {
el.className = el.className.replace(/\s*HA-spellcheck-(hover|fixed)\s*/g, " ");
}
el.className += " HA-spellcheck-fixed";
el.__msh_fixed = true;
if (!this_word_modified) {
return false;
}
to_r_list.push([el.innerHTML, replacement]);
el.innerHTML = replacement;
};
function replaceClicked() {
replaceWord(currentElement);
var start = currentElement.__msh_id;
var index = start;
do {
++index;
if (index == wrongWords.length) {
index = 0;
}
} while ((index != start) && wrongWords[index].__msh_fixed);
if (index == start) {
index = 0;
alert(_lc("Finished list of mispelled words"));
}
wrongWords[index].__msh_wordClicked(true);
return false;
};
function revertClicked() {
document.getElementById("v_replacement").value = currentElement.__msh_origWord;
replaceWord(currentElement);
currentElement.className = "HA-spellcheck-error HA-spellcheck-current";
return false;
};
function replaceAllClicked() {
var replacement = document.getElementById("v_replacement").value;
var ok = true;
var spans = allWords[currentElement.__msh_origWord];
if (spans.length == 0) {
alert("An impossible condition just happened. Call FBI. ;-)");
} else if (spans.length == 1) {
replaceClicked();
return false;
}
/*
var message = "The word \"" + currentElement.__msh_origWord + "\" occurs " + spans.length + " times.\n";
if (replacement == currentElement.__msh_origWord) {
ok = confirm(message + "Ignore all occurrences?");
} else {
ok = confirm(message + "Replace all occurrences with \"" + replacement + "\"?");
}
*/
if (ok) {
for (var i = 0; i < spans.length; ++i) {
if (spans[i] != currentElement) {
replaceWord(spans[i]);
}
}
// replace current element the last, so that we jump to the next word ;-)
replaceClicked();
}
return false;
};
function ignoreClicked() {
document.getElementById("v_replacement").value = currentElement.__msh_origWord;
replaceClicked();
return false;
};
function ignoreAllClicked() {
document.getElementById("v_replacement").value = currentElement.__msh_origWord;
replaceAllClicked();
return false;
};
function learnClicked() {
to_p_dict.push(currentElement.__msh_origWord);
return ignoreAllClicked();
};
function internationalizeWindow() {
var types = ["div", "span", "button"];
for (var i = 0; i < types.length; ++i) {
var tag = types[i];
var els = document.getElementsByTagName(tag);
for (var j = els.length; --j >= 0;) {
var el = els[j];
if (el.childNodes.length == 1 && /\S/.test(el.innerHTML)) {
var txt = el.innerHTML;
el.innerHTML = _lc(txt);
}
}
}
};
function initDocument() {
internationalizeWindow();
modified = false;
frame = document.getElementById("i_framecontent");
var field = document.getElementById("f_content");
field.value = HTMLArea.getHTML(editor._doc.body, false, editor);
var dict = document.getElementById("f_dictionary");
if(typeof editor.config.SpellChecker.defaultDictionary != "undefined"
&& editor.config.SpellChecker.defaultDictionary != "") {
dict.value = editor.config.SpellChecker.defaultDictionary;
} else {
dict.value = "en_GB";
}
if(editor.config.SpellChecker.backend == 'php')
{
field.form.action = _editor_url + '/plugins/SpellChecker/spell-check-logic.php';
}
field.form.submit();
document.getElementById("f_init").value = "0";
// assign some global event handlers
var select = document.getElementById("v_suggestions");
select.onchange = function() {
document.getElementById("v_replacement").value = this.value;
};
if (is_ie) {
select.attachEvent("ondblclick", replaceClicked);
} else {
select.addEventListener("dblclick", replaceClicked, true);
}
document.getElementById("b_replace").onclick = replaceClicked;
if(editor.config.SpellChecker.backend == 'php')
{
document.getElementById("b_learn").onclick = learnClicked;
}
else
{
document.getElementById("b_learn").parent.removeChild(document.getElementById("b_learn"));
}
document.getElementById("b_replall").onclick = replaceAllClicked;
document.getElementById("b_ignore").onclick = ignoreClicked;
document.getElementById("b_ignall").onclick = ignoreAllClicked;
document.getElementById("b_recheck").onclick = recheckClicked;
document.getElementById("b_revert").onclick = revertClicked;
document.getElementById("b_info").onclick = displayInfo;
document.getElementById("b_ok").onclick = saveClicked;
document.getElementById("b_cancel").onclick = cancelClicked;
select = document.getElementById("v_dictionaries");
select.onchange = function() {
document.getElementById("f_dictionary").value = this.value;
};
};
function getAbsolutePos(el) {
var r = { x: el.offsetLeft, y: el.offsetTop };
if (el.offsetParent) {
var tmp = getAbsolutePos(el.offsetParent);
r.x += tmp.x;
r.y += tmp.y;
}
return r;
};
function wordClicked(scroll) {
var self = this;
if (scroll) (function() {
var pos = getAbsolutePos(self);
var ws = { x: frame.offsetWidth - 4,
y: frame.offsetHeight - 4 };
var wp = { x: frame.contentWindow.document.body.scrollLeft,
y: frame.contentWindow.document.body.scrollTop };
pos.x -= Math.round(ws.x/2);
if (pos.x < 0) pos.x = 0;
pos.y -= Math.round(ws.y/2);
if (pos.y < 0) pos.y = 0;
frame.contentWindow.scrollTo(pos.x, pos.y);
})();
if (currentElement) {
var a = allWords[currentElement.__msh_origWord];
currentElement.className = currentElement.className.replace(/\s*HA-spellcheck-current\s*/g, " ");
for (var i = 0; i < a.length; ++i) {
var el = a[i];
if (el != currentElement) {
el.className = el.className.replace(/\s*HA-spellcheck-same\s*/g, " ");
}
}
}
currentElement = this;
this.className += " HA-spellcheck-current";
var a = allWords[currentElement.__msh_origWord];
for (var i = 0; i < a.length; ++i) {
var el = a[i];
if (el != currentElement) {
el.className += " HA-spellcheck-same";
}
}
// document.getElementById("b_replall").disabled = (a.length <= 1);
// document.getElementById("b_ignall").disabled = (a.length <= 1);
var txt;
if (a.length == 1) {
txt = "one occurrence";
} else if (a.length == 2) {
txt = "two occurrences";
} else {
txt = a.length + " occurrences";
}
var suggestions = suggested_words[this.__msh_origWord];
if (suggestions)
suggestions = suggestions.split(/,/);
else
suggestions = [];
var select = document.getElementById("v_suggestions");
document.getElementById("statusbar").innerHTML = "Found " + txt +
' for word "<b>' + currentElement.__msh_origWord + '</b>"';
for (var i = select.length; --i >= 0;) {
select.remove(i);
}
for (var i = 0; i < suggestions.length; ++i) {
var txt = suggestions[i];
var option = document.createElement("option");
option.value = txt;
option.appendChild(document.createTextNode(txt));
select.appendChild(option);
}
document.getElementById("v_currentWord").innerHTML = this.__msh_origWord;
if (suggestions.length > 0) {
select.selectedIndex = 0;
select.onchange();
} else {
document.getElementById("v_replacement").value = this.innerHTML;
}
select.style.display = "none";
select.style.display = "block";
return false;
};
function wordMouseOver() {
this.className += " HA-spellcheck-hover";
};
function wordMouseOut() {
this.className = this.className.replace(/\s*HA-spellcheck-hover\s*/g, " ");
};
function displayInfo() {
var info = frame.contentWindow.spellcheck_info;
if (!info)
alert("No information available");
else {
var txt = "** Document information **";
for (var i in info) {
txt += "\n" + i + " : " + info[i];
}
alert(txt);
}
return false;
};
function finishedSpellChecking() {
// initialization of global variables
currentElement = null;
wrongWords = null;
allWords = {};
fixedWords = [];
suggested_words = frame.contentWindow.suggested_words;
document.getElementById("status").innerHTML = "HTMLArea Spell Checker (<a href='readme-tech.html' target='_blank' title='Technical information'>info</a>)";
var doc = frame.contentWindow.document;
var spans = doc.getElementsByTagName("span");
var sps = [];
var id = 0;
for (var i = 0; i < spans.length; ++i) {
var el = spans[i];
if (/HA-spellcheck-error/.test(el.className)) {
sps.push(el);
el.__msh_wordClicked = wordClicked;
el.onclick = function(ev) {
ev || (ev = window.event);
ev && HTMLArea._stopEvent(ev);
return this.__msh_wordClicked(false);
};
el.onmouseover = wordMouseOver;
el.onmouseout = wordMouseOut;
el.__msh_id = id++;
var txt = (el.__msh_origWord = el.firstChild.data);
el.__msh_fixed = false;
if (typeof allWords[txt] == "undefined") {
allWords[txt] = [el];
} else {
allWords[txt].push(el);
}
} else if (/HA-spellcheck-fixed/.test(el.className)) {
fixedWords.push(el);
}
}
var dicts = doc.getElementById("HA-spellcheck-dictionaries");
if (dicts) {
dicts.parentNode.removeChild(dicts);
dicts = dicts.innerHTML.split(/,/);
var select = document.getElementById("v_dictionaries");
for (var i = select.length; --i >= 0;) {
select.remove(i);
}
var activeDictionary = document.getElementById("f_dictionary").value;
for (var i = 0; i < dicts.length; ++i) {
var txt = dicts[i];
var option = document.createElement("option");
if(txt == activeDictionary) {
option.selected = true;
}
option.value = txt;
option.appendChild(document.createTextNode(txt));
select.appendChild(option);
}
}
wrongWords = sps;
if (sps.length == 0) {
if (!modified) {
alert(_lc("No mispelled words found with the selected dictionary."));
// window.close();
} else {
alert(_lc("No mispelled words found with the selected dictionary."));
}
return false;
}
(currentElement = sps[0]).__msh_wordClicked(true);
var as = doc.getElementsByTagName("a");
for (var i = as.length; --i >= 0;) {
var a = as[i];
a.onclick = function() {
if (confirm(_lc("Please confirm that you want to open this link") + ":\n" +
this.href + "\n" + _lc("I will open it in a new page."))) {
window.open(this.href);
}
return false;
};
}
};

View File

@@ -0,0 +1,73 @@
// Spell Checker Plugin for HTMLArea-3.0
// Sponsored by www.americanbible.org
// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
//
// (c) dynarch.com 2003.
// Distributed under the same terms as HTMLArea itself.
// This notice MUST stay intact for use (see license.txt).
//
// $Id$
HTMLArea.Config.prototype.SpellChecker = { 'backend': 'php', 'personalFilesDir' : '', 'defaultDictionary' : 'en_GB' };
function SpellChecker(editor) {
this.editor = editor;
var cfg = editor.config;
var bl = SpellChecker.btnList;
var self = this;
// see if we can find the mode switch button, insert this before that
var id = "SC-spell-check";
cfg.registerButton(id, this._lc("Spell-check"), editor.imgURL("spell-check.gif", "SpellChecker"), false,
function(editor, id) {
// dispatch button press event
self.buttonPress(editor, id);
});
cfg.addToolbarElement("SC-spell-check", "htmlmode", 1);
};
SpellChecker._pluginInfo = {
name : "SpellChecker",
version : "1.0",
developer : "Mihai Bazon",
developer_url : "http://dynarch.com/mishoo/",
c_owner : "Mihai Bazon",
sponsor : "American Bible Society",
sponsor_url : "http://www.americanbible.org",
license : "htmlArea"
};
SpellChecker.prototype._lc = function(string) {
return HTMLArea._lc(string, 'SpellChecker');
}
SpellChecker.btnList = [
null, // separator
["spell-check"]
];
SpellChecker.prototype.buttonPress = function(editor, id) {
switch (id) {
case "SC-spell-check":
SpellChecker.editor = editor;
SpellChecker.init = true;
var uiurl = _editor_url + "plugins/SpellChecker/spell-check-ui.html";
var win;
if (HTMLArea.is_ie) {
win = window.open(uiurl, "SC_spell_checker",
"toolbar=no,location=no,directories=no,status=no,menubar=no," +
"scrollbars=no,resizable=yes,width=600,height=450");
} else {
win = window.open(uiurl, "SC_spell_checker",
"toolbar=no,menubar=no,personalbar=no,width=600,height=450," +
"scrollbars=no,resizable=yes");
}
win.focus();
break;
}
};
// this needs to be global, it's accessed from spell-check-ui.html
SpellChecker.editor = null;