<?php
/*
 * $Horde: imp/spelling.php,v 2.28.2.13 2004/03/26 22:43:24 jan Exp $
 *
 * Copyright 1999-2004 Charles J. Hagenbuch <chuck@horde.org>
 * Copyright 1999-2004 Jon Parise <jon@horde.org>
 *
 * See the enclosed file COPYING for license information (GPL).  If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 */

define('CHANGE',     1);
define('CHANGE_ALL', 2);
define('IGNORE',     3);
define('IGNORE_ALL', 4);

function find_offset($message, $word, $start)
{
    $offset = $start;
    $pos = -1;
    /* If all things are right the word is at offset - 1 */
    if ($start > 3) {
        $start -= 3;
    } else {
        $start = 0;
    }
    while ($pos == -1 && $start >= 0) {
        $pos = strpos($message, $word, $start);
        if ($pos == '' && !is_int($pos)) {
            $start--;
            $pos = -1;
        }
    }
    return $pos;
}

function highlight_error($error, $message, $offset)
{
    $pos = strpos($message, $error, ($offset - 1 > 0 ? $offset - 1 : 0));
    if ($pos - 15 > 0) {
        $start = $pos - 15;
    } else {
        $start = 0;
    }
    $length = strlen($error) + 30;

    $message = substr_replace($message, "<font color=\"ff0000\">$error</font>", $pos, strlen($error));
    $message = substr($message, $start, $length + 28);

    return $message;
}

function member($string, $array)
{
    foreach ($array as $key => $val) {
        if (strtolower($val) == strtolower($string)) {
            return true;
	}
    }
    return false;
}

if (isset($nls['spelling']) && isset($nls['spelling'][$language])) {
    $spell_opt = $nls['spelling'][$language];
}
else {
    $spell_opt = '';
}

/* Fetch and clean form data. */
$f_opt = Horde::getFormData('opt');
$f_subs = Horde::getFormData('subs');
$f_oldword = Horde::getFormData('oldword');
$f_subtext = Horde::getFormData('subtext');
$f_wordoffset = Horde::getFormData('wordoffset');
$f_ignoreall = Horde::getFormData('ignoreall');
$f_message = Horde::getFormData('message');
$f_oldmsg = Horde::getFormData('oldmsg');
$f_newmsg = Horde::getFormData('newmsg');
$f_to = Horde::getFormData('to');
$f_to_new = Horde::getFormData('to_new');
$f_to_list = Horde::getFormData('to_list');
$f_to_field = Horde::getFormData('to_field');
$f_cc = Horde::getFormData('cc');
$f_cc_new = Horde::getFormData('cc_new');
$f_cc_list = Horde::getFormData('cc_list');
$f_cc_field = Horde::getFormData('cc_field');
$f_bcc = Horde::getFormData('bcc');
$f_bcc_new = Horde::getFormData('bcc_new');
$f_bcc_list = Horde::getFormData('bcc_list');
$f_bcc_field = Horde::getFormData('bcc_field');

if ($actionID == SPELL_CHECK_FORWARD) {
    for ($i = 0; $i < count($f_opt); $i++) {
        /* If they have an word with no suggestions and they
           dont type in a replacement, ignore it. */
        $skipword = 0;
        if (!empty($f_subtext[$i])) {
            $replacement = $f_subtext[$i];
        } else {
            if ($f_subs[$i] == '0') {
                $ignoreall = $f_ignoreall . ',' . $f_oldword[$i];
                $skipword = 1;
            } else {
                $replacement = $f_subs[$i];
            }
        }

        if (!$skipword) {
            $pos = -1;

            $realoffset = $f_wordoffset[$i];
            /* Just in case things are whackily out. */
            if ($realoffset > strlen($f_message)) $realoffset = strlen($f_message) - 1;

            $pos = find_offset($f_message, $f_oldword[$i], $realoffset);

            switch ($f_opt[$i]) {
            case IGNORE:
                $consume = $pos + strlen($f_oldword[$i]);
                $addition = substr($f_message, 0, $consume);
                $f_newmsg .= $addition;
                $f_message = substr($f_message, $consume);

                /* Adjust offsets, as they could be wildly out */
                for ($msgnum = 0; $msgnum < count($f_wordoffset); $msgnum++) {
                    $f_wordoffset[$msgnum] -= $consume;
                }
                break;

            case IGNORE_ALL:
                $ignoreall = $f_ignoreall . ',' . $f_oldword[$i];
                break;

            case CHANGE_ALL:
                $f_message = str_replace($f_oldword[$i], $replacement, $f_message);
                break;

            case CHANGE:
                $ignores = explode(',', $f_ignoreall);
                if (!member($f_oldword[$i], $ignores)) {
                    /* Let's try and keep those offsets semi correct. */
                    $adjoffset = strlen($replacement) - strlen($f_oldword[$i]);
                    for ($msgnum = 0; $msgnum < count($f_wordoffset); $msgnum++) {
                        $f_wordoffset[$msgnum] += $adjoffset;
                    }

                    $tempmessage  = substr($f_message, 0, $pos);
                    $tempmessage .= $replacement;
                    $tempmessage .= substr($f_message, $pos + strlen($f_oldword[$i]));
                    $f_message = $tempmessage;
                }
                break;
            }
        }
    }
} else {
    $f_oldmsg = $f_message;

    /* Have to start another wordlist to incorporate into the spell check
       dictionary methinks. */
    $ignoreall = 'com,Cc,www,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,Fwd,DNS,http,CC,ca,html,tm,COM,mmunity,Co,op,https,netscape,webmail,bcc,jpg,gif,email,Tel,ie,eg';
}

// Special treatment depending on language (quotes are not equally
// treated by ispell in english and in french).
switch ($language) {
case 'fr_FR':
    $tocheck = str_replace("'", "\\'", escapeShellCmd($f_message));
    break;

default:
    $tocheck = $f_message;
    break;
}

$spellFile = Horde::getTempFile('spell');
$fp = fopen($spellFile, 'w');
fwrite($fp, $tocheck);
fclose($fp);

exec($conf['utils']['spellchecker'] . ' -a ' . $spell_opt . ' < ' . $spellFile, $warnings);

$msg = '';
for ($i = 0; $i < count($warnings); $i++) {
    if (substr($warnings[$i], 0, 1) == '&') {
        $parts = explode(': ', $warnings[$i]);
        $info = explode(' ', $parts[0]);
        if (preg_match('|^[A-Z]*$|', $info[1])) {
            $ignoreall .= ',' . $info[1];
        } else {
            $error[] = array($info[1],$info[3],$parts[1]);
        }
    }
    if (preg_match('|^#|', $warnings[$i])) {
        $info = explode(' ', $warnings[$i]);
        if (preg_match('|^[A-Z]*$|', $info[1])) {
            $ignoreall .= ',' . $info[1];
        } else {
            $error[] = array($info[1], $info[2], '');
        }
    }
}

// Generate a pretty word-wrapped version for displaying
$display_msg = htmlspecialchars($f_newmsg . $f_message);
$display_msg = Text::wrap($display_msg, $prefs->getValue('wrap_width'), "\n", Lang::getCharset());

?>
