summaryrefslogtreecommitdiff
path: root/inc
diff options
context:
space:
mode:
Diffstat (limited to 'inc')
-rw-r--r--inc/aspell.php236
-rw-r--r--inc/common.php2
-rw-r--r--inc/html.php19
-rw-r--r--inc/lang/de/lang.php6
-rw-r--r--inc/lang/en/lang.php6
-rw-r--r--inc/template.php7
-rw-r--r--inc/utf8.php16
7 files changed, 287 insertions, 5 deletions
diff --git a/inc/aspell.php b/inc/aspell.php
new file mode 100644
index 000000000..ea8a7e428
--- /dev/null
+++ b/inc/aspell.php
@@ -0,0 +1,236 @@
+<?php
+/**
+ * Aspell interface
+ *
+ * This library gives full access to aspell's pipe interface. Optionally it
+ * provides some of the functions from the pspell PHP extension by wrapping
+ * them to calls to the aspell binary.
+ *
+ * It can be simply dropped into code written for the pspell extension like
+ * the following
+ *
+ * if(!function_exists('pspell_suggest')){
+ * define('PSPELL_COMP',1);
+ * require_once ("pspell_comp.php");
+ * }
+ *
+ * Define the path to the aspell binary like this if needed:
+ *
+ * define('ASPELL_BIN','/path/to/aspell');
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @todo Not all pspell functions are supported
+ *
+ */
+
+// path to your aspell binary
+if(!defined('ASPELL_BIN')) define('ASPELL_BIN','aspell');
+
+
+if(!defined('PSPELL_FAST')) define(PSPELL_FAST,1); # Fast mode (least number of suggestions)
+if(!defined('PSPELL_NORMAL')) define(PSPELL_NORMAL,2); # Normal mode (more suggestions)
+if(!defined('PSPELL_BAD_SPELLERS')) define(PSPELL_BAD_SPELLERS,3); # Slow mode (a lot of suggestions)
+if(!defined('ASPELL_ULTRA')) define(ASPELL_ULTRA,4); # Ultra fast mode (not available in Pspell!)
+
+/**
+ * You can define PSPELL_COMP to use this class as drop in replacement
+ * for the pspell extension
+ */
+if(defined('PSPELL_COMP')){
+ // spelling is not supported by aspell and ignored
+ function pspell_config_create($language, $spelling=null, $jargon=null, $encoding='iso8859-1'){
+ return new Aspell($language, $jargon, $encoding);
+ }
+
+ function pspell_config_mode(&$config, $mode){
+ return $config->setMode($mode);
+ }
+
+ function pspell_new_config(&$config){
+ return $config;
+ }
+
+ function pspell_check(&$dict,$word){
+ return $dict->check($word);
+ }
+
+ function pspell_suggest(&$dict, $word){
+ return $dict->suggest($word);
+ }
+}
+
+/**
+ * Class to interface aspell
+ *
+ * Needs PHP >= 4.3.0
+ */
+class Aspell{
+ var $language = null;
+ var $jargon = null;
+ var $encoding = 'iso8859-1';
+ var $mode = PSPELL_NORMAL;
+
+ var $args='';
+
+ /**
+ * Constructor. Works like pspell_config_create()
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function Aspell($language, $jargon=null, $encoding='iso8859-1'){
+ $this->language = $language;
+ $this->jargon = $jargon;
+ $this->encoding = $encoding;
+ $this->_prepareArgs();
+ }
+
+ /**
+ * Set the spelling mode like pspell_config_mode()
+ *
+ * Mode can be PSPELL_FAST, PSPELL_NORMAL, PSPELL_BAD_SPELLER or ASPELL_ULTRA
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function setMode($mode){
+ if(!in_array($mode,array(PSPELL_FAST,PSPELL_NORMAL,PSPELL_BAD_SPELLER,ASPELL_ULTRA))){
+ $mode = PSPELL_NORMAL;
+ }
+
+ $this->mode = $mode;
+ $this->_prepareArgs();
+ return $mode;
+ }
+
+ /**
+ * Prepares the needed arguments for the call to the aspell binary
+ *
+ * No need to call this directly
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function _prepareArgs(){
+ $this->args = '';
+
+ if($this->language){
+ $this->args .= ' --lang='.escapeshellarg($this->language);
+ }else{
+ return false; // no lang no spell
+ }
+
+ if($this->jargon){
+ $this->args .= ' --jargon='.escapeshellarg($this->jargon);
+ }
+
+ if($this->encoding){
+ $this->args .= ' --encoding='.escapeshellarg($this->encoding);
+ }
+
+ switch ($this->mode){
+ case PSPELL_FAST:
+ $this->args .= ' --sug-mode=fast';
+ break;
+ case PSPELL_BAD_SPELLERS:
+ $this->args .= ' --sug-mode=bad-spellers';
+ break;
+ case ASPELL_ULTRA:
+ $this->args .= ' --sug-mode=ultra';
+ break;
+ default:
+ $this->args .= ' --sug-mode=normal';
+ }
+
+ return true;
+ }
+
+ /**
+ * Pipes a text to aspell
+ *
+ * This opens a bidirectional pipe to the aspell binary, writes
+ * the given text to STDIN and returns STDOUT and STDERR
+ *
+ * You have full access to aspell's pipe mode here - this means you need
+ * quote your lines yourself read the aspell manual for more info
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @link http://aspell.sf.net/man-html/Through-A-Pipe.html
+ */
+ function runAspell($text,&$out,&$err){
+ if(empty($text)) return true;
+
+ //prepare file descriptors
+ $descspec = array(
+ 0 => array('pipe', 'r'), // stdin is a pipe that the child will read from
+ 1 => array('pipe', 'w'), // stdout is a pipe that the child will write to
+ 2 => array('pipe', 'w') // stderr is a file to write to
+ );
+
+ $process = proc_open(ASPELL_BIN.' -a'.$this->args, $descspec, $pipes);
+ if (is_resource($process)) {
+ //write to stdin
+ fwrite($pipes[0],$text);
+ fclose($pipes[0]);
+
+ //read stdout
+ while (!feof($pipes[1])) {
+ $out .= fread($pipes[1], 8192);
+ }
+ fclose($pipes[1]);
+
+ //read stderr
+ while (!feof($pipes[2])) {
+ $err .= fread($pipes[2], 8192);
+ }
+ fclose($pipes[2]);
+
+ if(proc_close($process) != 0){
+ //something went wrong
+ trigger_error("aspell returned an error: $err", E_USER_WARNING);
+ return null;
+ }
+ return true;
+ }
+ //opening failed
+ trigger_error("Could not run aspell '".ASPELL_BIN."'", E_USER_WARNING);
+ return false;
+ }
+
+ /**
+ * Checks a single word for correctness
+ *
+ * @returns array of suggestions or true on correct spelling
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function suggest($word){
+ if($this->runAspell("^$word",$out,$err)){
+ //parse output
+ $lines = split("\n",$out);
+ foreach ($lines as $line){
+ $line = trim($line);
+ if(empty($line)) continue; // empty line
+ if($line[0] == '@') continue; // comment
+ if($line[0] == '*') return true; // no mistakes made
+ if($line[0] == '#') return array(); // mistake but no suggestions
+ if($line[0] == '&'){
+ $line = preg_replace('/&.*?: /','',$line);
+ return split(', ',$line);
+ }
+ }
+ }
+ return array();
+ }
+
+ /**
+ * Check if a word is mispelled like pspell_check
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function check($word){
+ if(is_array($this->suggest($word))){
+ return false;
+ }else{
+ return true;
+ }
+ }
+}
+
+//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/common.php b/inc/common.php
index 99cec10a9..80c866815 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -739,7 +739,7 @@ function filesize_h($size, $dec = 1){
}
/**
- * Run a few sanity checks
+ * Return DokuWikis version
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
diff --git a/inc/html.php b/inc/html.php
index d972c1abb..bd34bb609 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -833,6 +833,8 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
$ro='readonly="readonly"';
}
if(!$DATE) $DATE = $INFO['lastmod'];
+
+
?>
<form name="editform" method="post" action="<?=script()?>" accept-charset="<?=$lang['encoding']?>" onsubmit="return svchk()">
<input type="hidden" name="id" value="<?=$ID?>" />
@@ -842,7 +844,7 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
<input type="hidden" name="suffix" value="<?=formText($SUF)?>" />
<table style="width:99%">
<tr>
- <td class="toolbar" colspan="3">
+ <td class="toolbar" colspan="2">
<?if($wr){?>
<script language="JavaScript" type="text/javascript">
<?/* sets changed to true when previewed */?>
@@ -852,7 +854,7 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
formatButton('italic.png','<?=$lang['qb_italic']?>',"\/\/","\/\/",'<?=$lang['qb_italic']?>','i');
formatButton('underline.png','<?=$lang['qb_underl']?>','__','__','<?=$lang['qb_underl']?>','u');
formatButton('code.png','<?=$lang['qb_code']?>','\'\'','\'\'','<?=$lang['qb_code']?>','c');
- formatButton('strike.png','<?=$lang['qb_strike']?>','<del>','</del>','<?=$lang['qb_strike']?>','d');
+ formatButton('strike.png','<?=$lang['qb_strike']?>','<del>','<\/del>','<?=$lang['qb_strike']?>','d');
formatButton('fonth1.png','<?=$lang['qb_h1']?>','====== ',' ======\n','<?=$lang['qb_h1']?>','1');
formatButton('fonth2.png','<?=$lang['qb_h2']?>','===== ',' =====\n','<?=$lang['qb_h2']?>','2');
@@ -877,13 +879,20 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
</script>
<?}?>
</td>
+ <td>
+<!-- <span class="action" id="action"><a class="check_spelling" onClick="setObjToCheck('wikitext'); spellCheck();">Check Spelling</a></span>
+ <span class="status" id="status"></span> -->
+ <div id="spell_action"></div>
+ <div id="spell_suggest"></div>
+ </td>
</tr>
<tr>
<td colspan="3">
+ <div id="spell_result"></div>
<textarea name="wikitext" id="wikitext" <?=$ro?> cols="80" rows="10" class="edit" onchange="textChanged = true;" onkeyup="summaryCheck();" tabindex="1"><?="\n".formText($text)?></textarea>
</td>
</tr>
- <tr>
+ <tr id="wikieditbar">
<td>
<?if($wr){?>
<input class="button" type="submit" name="do" value="<?=$lang['btn_save']?>" accesskey="s" title="[ALT+S]" onclick="textChanged=false" onkeypress="textChanged=false" tabindex="3" />
@@ -902,6 +911,10 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
showSizeCtl();
<?if($wr){?>
init_locktimer(<?=$conf['locktime']-60?>,'<?=$lang['willexpire']?>');
+
+ //initialize spellchecker
+ ajax_spell.init('<?=$lang['spell_start']?>','<?=$lang['spell_stop']?>','<?=$lang['spell_wait']?>','<?=$lang['spell_noerr']?>','<?=$lang['spell_nosug']?>');
+
document.editform.wikitext.focus();
<?}?>
</script>
diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php
index bc6ff749a..325e46044 100644
--- a/inc/lang/de/lang.php
+++ b/inc/lang/de/lang.php
@@ -130,4 +130,10 @@ $lang['acl_perm8'] = 'Hochladen';
$lang['acl_perm16'] = 'Entfernen';
$lang['acl_new'] = 'Eintrag hinzufügen';
+$lang['spell_start']= 'Rechtschreibung prüfen';
+$lang['spell_stop'] = 'Bearbeiten fortsetzen';
+$lang['spell_wait'] = 'Bitte warten...';
+$lang['spell_noerr']= 'Keine Fehler gefunden';
+$lang['spell_nosug']= 'Keine Vorschläge';
+
//Setup VIM: ex: et ts=2 enc=utf-8 :
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index ba8736114..385e5a7e0 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -129,4 +129,10 @@ $lang['acl_perm8'] = 'Upload';
$lang['acl_perm16'] = 'Delete';
$lang['acl_new'] = 'Add new Entry';
+$lang['spell_start']= 'Check Spelling';
+$lang['spell_stop'] = 'Resume Editing';
+$lang['spell_wait'] = 'Please wait...';
+$lang['spell_noerr']= 'No Mistakes found';
+$lang['spell_nosug']= 'No Suggestions';
+
//Setup VIM: ex: et ts=2 enc=utf-8 :
diff --git a/inc/template.php b/inc/template.php
index 43c224926..035bfbdc1 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -135,6 +135,7 @@ function tpl_metaheaders(){
global $INFO;
global $ACT;
global $lang;
+ global $conf;
$it=2;
// the usual stuff
@@ -179,6 +180,12 @@ function tpl_metaheaders(){
ptln('<script language="JavaScript" type="text/javascript" src="'.
DOKU_BASE.'lib/scripts/ajax.js"></script>',$it);
+ // load spellchecker script if wanted
+ if($conf['spellchecker'] && ($ACT=='edit' || $ACT=='preview')){
+ ptln('<script language="JavaScript" type="text/javascript" src="'.
+ DOKU_BASE.'lib/scripts/spellcheck.js"></script>',$it);
+ }
+
//FIXME include some default CSS ? IE FIX?
}
diff --git a/inc/utf8.php b/inc/utf8.php
index 0b90c8586..70b16f1a5 100644
--- a/inc/utf8.php
+++ b/inc/utf8.php
@@ -105,7 +105,7 @@ function utf8_check($Str) {
* @see utf8_decode()
*/
function utf8_strlen($string){
- return strlen(utf8_decode($str));
+ return strlen(utf8_decode($string));
}
/**
@@ -126,6 +126,20 @@ function utf8_substr($str,$start,$length=null){
}
/**
+ * Unicode aware replacement for substr_replace()
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @see substr_replace()
+ */
+function utf8_substr_replace($string, $replacement, $start , $length=0 ){
+ $ret = '';
+ if($start>0) $ret .= utf8_substr($string, 0, $start);
+ $ret .= $replacement;
+ $ret .= utf8_substr($string, $start+$length);
+ return $ret;
+}
+
+/**
* Unicode aware replacement for explode
*
* @TODO support third limit arg