Mozilla/mozilla/cmd/xfe/src/SpellHandler.cpp
akkana%netscape.com e64f9c8ba0 Show no-spellchecker-found dialog only if NETSCAPE_COMMERCIAL
git-svn-id: svn://10.0.0.236/trunk@11810 18797224-902f-48f8-a5cc-f745e15eee43
1998-10-02 22:15:23 +00:00

1858 lines
45 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
SpellHandler.cpp -- class definition for the Spell Handler class
Created: Richard Hess <rhess@netscape.com>, 12-May-97
*/
#include "SpellHandler.h"
#include "spellchk.h"
#include "xpgetstr.h"
#include "fe_proto.h"
#include "edt.h"
#include "xeditor.h"
#include "prefs.h"
#include "prefapi.h"
#include "prlink.h"
#include <Xm/Text.h>
#include <DtWidgets/ComboBoxP.h>
#include <Xfe/Xfe.h>
extern "C" {
void fe_GetProgramDirectory(char *path, int len);
}
static XFE_SpellHandler *xfe_spellHandler = NULL;
// Preference strings
static char *LanguagePref = "spellchecker.default_language";
static char *DialectPref = "spellchecker.default_dialect";
extern int NO_SPELL_SHLIB_FOUND;
// WARNING... [ be VERY careful with this index stuff ]
//
#define XSP_NULL 0
#define XSP_REPLACE 1
#define XSP_REPLACEALL 2
#define XSP_CHECK 3
#define XSP_IGNORE 4
#define XSP_IGNOREALL 5
#define XSP_LEARN 6
#define XSP_STOP 7
//
// IMPORTANT: if you add to this list you need to update the value of
// XSP_CACHE_SIZE in SpellHandler.h to reflect the change
// in the size of the tag cache...
//
static void
xfe_spell_focus_in_cb (Widget , XtPointer closure, XtPointer )
{
struct xfe_spell_data *data = (struct xfe_spell_data *) closure;
char *tmp = XmTextFieldGetString(data->text);
if (data->inList) {
data->inList = FALSE;
XmListDeselectAllItems(data->list);
if (XP_STRCMP( tmp, data->xWord ) == 0) {
XtSetSensitive(data->replace, FALSE);
XtSetSensitive(data->replaceAll, FALSE);
XtSetSensitive(data->check, FALSE);
XtVaSetValues(data->dialog, XmNdefaultButton, data->ignore, 0);
XtVaSetValues(data->replace, XmNshowAsDefault, False, 0);
XtVaSetValues(data->ignore, XmNshowAsDefault, True, 0);
XmProcessTraversal(data->ignore, XmTRAVERSE_CURRENT);
} else {
XtSetSensitive(data->replace, True);
XtSetSensitive(data->replaceAll, True);
XtSetSensitive(data->check, TRUE);
XtVaSetValues(data->dialog, XmNdefaultButton, data->replace, 0);
XtVaSetValues(data->ignore, XmNshowAsDefault, False, 0);
XtVaSetValues(data->replace, XmNshowAsDefault, True, 0);
XmProcessTraversal(data->replace, XmTRAVERSE_CURRENT);
}
}
if (data->nuText)
XP_FREE(data->nuText);
data->nuText = XP_STRDUP(tmp);
if (tmp)
XtFree(tmp);
}
static void
xfe_spell_focus_out_cb (Widget , XtPointer closure, XtPointer )
{
struct xfe_spell_data *data = (struct xfe_spell_data *) closure;
if (data->inList) {
XtSetSensitive(data->check, False);
}
}
static void
xfe_spell_text_cb (Widget , XtPointer closure, XtPointer )
{
struct xfe_spell_data *data = (struct xfe_spell_data *) closure;
char *tmp = XmTextFieldGetString(data->text);
if (data->xWord != NULL) {
if (XP_STRCMP( tmp, data->xWord ) == 0) {
XtSetSensitive(data->replace, FALSE);
XtSetSensitive(data->replaceAll, FALSE);
XtSetSensitive(data->check, FALSE);
XtVaSetValues(data->dialog, XmNdefaultButton, data->ignore, 0);
XtVaSetValues(data->replace, XmNshowAsDefault, False, 0);
XtVaSetValues(data->ignore, XmNshowAsDefault, True, 0);
} else {
XtSetSensitive(data->replace, True);
XtSetSensitive(data->replaceAll, True);
XtSetSensitive(data->check, TRUE);
XtVaSetValues(data->dialog, XmNdefaultButton, data->replace, 0);
XtVaSetValues(data->ignore, XmNshowAsDefault, False, 0);
XtVaSetValues(data->replace, XmNshowAsDefault, True, 0);
}
}
if (data->nuText)
XP_FREE(data->nuText);
data->nuText = XP_STRDUP(tmp);
if (tmp)
XtFree(tmp);
}
static void
xfe_spell_list_cb (Widget , XtPointer closure, XtPointer call_data)
{
struct xfe_spell_data *data = (struct xfe_spell_data *) closure;
XmListCallbackStruct *cdata = (XmListCallbackStruct *) call_data;
ISpellChecker *spell = data->spell;
char tmp[125];
int i = cdata->item_position - 1;
if (!data->inList) {
XtSetSensitive(data->replace, True);
XtSetSensitive(data->replaceAll, True);
XtSetSensitive(data->check, False);
XtVaSetValues(data->dialog, XmNdefaultButton, data->replace, 0);
XtVaSetValues(data->ignore, XmNshowAsDefault, False, 0);
XtVaSetValues(data->replace, XmNshowAsDefault, True, 0);
}
data->inList = TRUE;
if (spell)
spell->GetAlternative(i, tmp, sizeof(tmp));
if (data->nuText)
XP_FREE(data->nuText);
data->nuText = XP_STRDUP(tmp);
}
static void
xfe_spell_combo_cb (Widget , XtPointer closure, XtPointer call_data)
{
struct xfe_spell_data *data = (struct xfe_spell_data *) closure;
DtComboBoxCallbackStruct *info = (DtComboBoxCallbackStruct*)call_data;
int i = info->item_position;
int NewLanguage = data->langTags[i].language;
int NewDialect = data->langTags[i].dialect;
PREF_SetIntPref(LanguagePref, NewLanguage);
PREF_SetIntPref(DialectPref, NewDialect);
if (data->langIndx != i) {
data->langIndx = i;
xfe_spellHandler->ReprocessDocument();
}
}
static void
xfe_spell_doit_cb (Widget , XtPointer closure, XtPointer )
{
struct xfe_spell_tag *tag = (struct xfe_spell_tag *) closure;
xfe_spellHandler->ProcessError(tag);
xfe_spellHandler->UpdateGUI();
}
static void
xfe_spell_destroy_cb (Widget , XtPointer , XtPointer )
{
xfe_spellHandler->DialogDestroyed();
}
// -----------------------------------------------------------[ SpellHandler ]
/*static*/ PRLibrary* XFE_SpellHandler::m_spellCheckerLib = NULL;
/*static*/ XP_Bool XFE_SpellHandler::m_triedToLoad = FALSE;
XFE_SpellHandler::XFE_SpellHandler(MWContext* context)
{
int i = 0;
m_context = context;
m_triedToLoad = FALSE;
m_active = FALSE;
m_data.spell = NULL;
m_data.interface = NULL;
m_data.dialog = NULL;
m_data.list = NULL;
m_data.combo = NULL;
m_data.replace = NULL;
m_data.replaceAll = NULL;
m_data.check = NULL;
m_data.ignore = NULL;
m_data.ignoreAll = NULL;
m_data.learn = NULL;
m_data.stop = NULL;
m_data.status = NULL;
m_data.text = NULL;
m_data.nuText = NULL;
m_data.langTags = NULL;
m_data.langCount = 0;
m_data.langIndx = 0;
m_data.inList = TRUE;
m_data.inCheck = FALSE;
m_data.isOk = FALSE;
m_data.isDone = FALSE;
for (i = 0 ; i < XSP_CACHE_SIZE ; i++) {
//
// WARNING... [ be VERY careful with this index stuff ]
//
m_tags[i].action = i;
m_tags[i].data = &m_data;
}
// NOTE: we try to create the spell checker backend in order to
// determine it's availability... [ m_active ]
//
initSpellChecker();
nukeSpellChecker();
}
XFE_SpellHandler::~XFE_SpellHandler()
{
if (m_data.interface != NULL)
delete m_data.interface;
if (m_data.spell != NULL)
nukeSpellChecker();
if (m_data.langTags != NULL)
XP_FREE(m_data.langTags);
m_active = FALSE;
m_data.spell = NULL;
m_data.interface = NULL;
m_data.dialog = NULL;
m_data.list = NULL;
m_data.combo = NULL;
m_data.replace = NULL;
m_data.replaceAll = NULL;
m_data.check = NULL;
m_data.ignore = NULL;
m_data.ignoreAll = NULL;
m_data.learn = NULL;
m_data.stop = NULL;
m_data.status = NULL;
m_data.text = NULL;
m_data.langTags = NULL;
m_data.langCount = 0;
m_data.langIndx = 0;
m_data.inList = TRUE;
m_data.inCheck = FALSE;
m_data.isOk = FALSE;
m_data.isDone = FALSE;
}
void
XFE_SpellHandler::initSpellChecker()
{
// Let people disable spell checking in case they have NFS-related hangs:
XP_Bool disable_spell_checker;
PREF_GetBoolPref("editor.disable_spell_checker", &disable_spell_checker);
if (disable_spell_checker) {
m_active = FALSE;
return;
}
if (m_data.spell != NULL)
return; // already initialized
if (!m_triedToLoad)
{
m_triedToLoad = TRUE;
//const char* libPath = PR_GetLibraryPath();
//PR_SetLibraryPath("/usr/local/netscape/");
char* libname = "libspellchk.so";
m_spellCheckerLib = PR_LoadLibrary(libname);
// Set path back to original path
//PR_SetLibraryPath(libPath);
if (m_spellCheckerLib == NULL)
{
#ifdef DEBUG
printf("Couldn't find library %s\n", libname);
#endif
#ifdef NETSCAPE_COMMERCIAL
FE_Alert(m_context, XP_GetString(NO_SPELL_SHLIB_FOUND));
#endif
m_active = 0;
return;
}
m_active = TRUE;
}
if (m_data.spell == NULL && m_active)
{
typedef ISpellChecker*(*sc_create_func)();
sc_create_func sc_createProc =
(sc_create_func)PR_FindSymbol(m_spellCheckerLib, "SC_Create");
if (sc_createProc == NULL)
{
#ifdef DEBUG_akkana
printf("Couldn't find symbol SC_Create\n");
#endif
m_active = FALSE;
return;
}
m_data.spell = sc_createProc();
}
if (m_data.spell == NULL)
{
#ifdef DEBUG_akkana
printf("Couldn't initialize spellchecker\n");
#endif
m_active = FALSE;
return;
}
int32 Language = 0;
int32 Dialect = 0;
// First see if any language preferences have been set
PREF_GetIntPref(LanguagePref, &Language);
PREF_GetIntPref(DialectPref, &Dialect);
char *spellDir = getSpellCheckerDir();
char *personal = getPersonalDicPath();
#ifdef DEBUG_spellcheck
fprintf(stderr, "spellDir::[ %s ]\n", spellDir);
fprintf(stderr, "personal::[ %s ]\n", personal);
#endif
if (m_data.spell->Initialize(Language, Dialect,
spellDir, personal)) {
m_active = FALSE;
}
else {
m_active = TRUE;
}
}
void
XFE_SpellHandler::nukeSpellChecker()
{
if (m_data.spell != NULL
&& m_spellCheckerLib != NULL
)
{
typedef void (*sc_destroy_func)(ISpellChecker*);
sc_destroy_func sc_destroyProc =
(sc_destroy_func)PR_FindSymbol(m_spellCheckerLib, "SC_Destroy");
if (sc_destroyProc != NULL)
sc_destroyProc(m_data.spell);
m_data.spell = NULL;
}
}
char *
XFE_SpellHandler::getSpellCheckerDir()
{
char *configdir_spelldir;
char *mozilla_home = NULL;
char buf[MAXPATHLEN];
// check the "$HOME/.netscape"-type directory
configdir_spelldir = fe_GetConfigDirFilename("spell/");
if(configdir_spelldir) {
if(fe_isDir(configdir_spelldir))
return configdir_spelldir;
free(configdir_spelldir);
}
if (mozilla_home = getenv("MOZILLA_HOME")) {
XP_MEMSET(buf, '\0', sizeof(buf));
// Form "$MOZILLA_HOME/spell/" into buf...
//
XP_STRNCPY_SAFE(buf, mozilla_home, sizeof(buf)-1);
XP_STRNCAT_SAFE(buf, "/spell/",
sizeof(buf)-1 - XP_STRLEN(buf));
buf[sizeof(buf)-1] = '\0';
if (fe_isDir(buf)) {
return XP_STRDUP(buf);
}
}
XP_MEMSET(buf, '\0', sizeof(buf));
//
// Form "<program-dir>/spell/" into buf...
//
fe_GetProgramDirectory(buf, sizeof(buf)-1);
if (XP_STRLEN(buf) > 0) {
// WARNING... [ the program dir already has a trailing slash ]
//
XP_STRNCAT_SAFE(buf, "spell/",
sizeof(buf)-1 - XP_STRLEN(buf));
buf[sizeof(buf)-1] = '\0';
if (fe_isDir(buf)) {
return XP_STRDUP(buf);
}
}
// last chance, look for "/usr/local/netscape/spell/"...
//
if (fe_isDir("/usr/local/netscape/spell/")) {
return XP_STRDUP("/usr/local/netscape/spell/");
}
// NOTE: punt on the directory...
//
return XP_STRDUP(".");
}
char *
XFE_SpellHandler::getPersonalDicPath()
{
return fe_GetConfigDirFilename("custom.dic");
}
XP_Bool
XFE_SpellHandler::IsActive()
{
return m_active;
}
XP_Bool
XFE_SpellHandler::IsAvailable()
{
return (m_active && (m_data.spell == NULL));
}
void
XFE_SpellHandler::DialogDestroyed()
{
if (m_data.xWord) {
m_data.interface->RemoveAllErrorHilites();
}
if (m_data.nuText) {
XP_FREE(m_data.nuText);
}
if (m_data.langTags != NULL)
XP_FREE(m_data.langTags);
delete m_data.interface;
nukeSpellChecker();
m_data.spell = NULL;
m_data.interface = NULL;
m_data.dialog = NULL;
m_data.list = NULL;
m_data.combo = NULL;
m_data.replace = NULL;
m_data.replaceAll = NULL;
m_data.check = NULL;
m_data.ignore = NULL;
m_data.ignoreAll = NULL;
m_data.learn = NULL;
m_data.stop = NULL;
m_data.status = NULL;
m_data.text = NULL;
m_data.nuText = NULL;
m_data.langTags = NULL;
m_data.langCount = 0;
m_data.langIndx = 0;
m_data.inList = TRUE;
m_data.inCheck = FALSE;
m_data.isOk = FALSE;
m_data.isDone = FALSE;
}
void
XFE_SpellHandler::UpdateGUI()
{
char *string = NULL;
XmString xstr = NULL;
XmListDeleteAllItems(m_data.list);
if (m_data.inCheck) {
// WARNING... [ don't nuke the text that you're going to use!! ]
//
}
else {
if (m_data.nuText) {
XP_FREE(m_data.nuText);
m_data.nuText = NULL;
}
}
if (m_data.isDone) {
string = XfeSubResourceGetStringValue(m_data.dialog,
"done",
"Done",
XmNlabelString,
XmCLabelString,
NULL);
}
else {
string = XfeSubResourceGetStringValue(m_data.dialog,
"replace",
"Replace",
XmNlabelString,
XmCLabelString,
NULL);
}
xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
XtVaSetValues(m_data.replace, XmNlabelString, xstr, 0);
XmStringFree(xstr);
xstr = NULL;
if (m_data.xWord) {
int numAlts = 0;
if (!m_data.isOk) {
numAlts = m_data.spell->GetNumAlternatives(m_data.xWord);
XmTextSetString(m_data.text, m_data.xWord);
}
if (numAlts) {
char AltString[125];
char *tmp;
int i = 0;
for (i=0;i<numAlts;i++) {
m_data.spell->GetAlternative(i, AltString,
sizeof(AltString));
tmp = XP_STRDUP(AltString);
xstr = XmStringCreateLtoR( tmp, XmSTRING_DEFAULT_CHARSET);
XmListAddItem(m_data.list, xstr, 0);
XmStringFree(xstr);
XP_FREE(tmp);
}
XmListSelectPos(m_data.list, 1, True);
string = XfeSubResourceGetStringValue(m_data.dialog,
"msgUnRecognized",
"MsgUnRecognized",
XmNlabelString,
XmCLabelString,
NULL);
xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
XtVaSetValues(m_data.status, XmNlabelString, xstr, 0);
XmStringFree(xstr);
XtSetSensitive(m_data.text, True);
XtSetSensitive(m_data.list, True);
XtSetSensitive(m_data.replace, True);
XtSetSensitive(m_data.replaceAll, True);
XtSetSensitive(m_data.check, False);
XtSetSensitive(m_data.ignore, True);
XtSetSensitive(m_data.ignoreAll, True);
XtSetSensitive(m_data.learn, True);
XtSetSensitive(m_data.stop, True);
XtVaSetValues(m_data.dialog, XmNdefaultButton, m_data.replace, 0);
XtVaSetValues(m_data.ignore, XmNshowAsDefault, False, 0);
XtVaSetValues(m_data.replace, XmNshowAsDefault, True, 0);
XmProcessTraversal(m_data.replace, XmTRAVERSE_CURRENT);
}
else {
if (m_data.isOk) {
string = XfeSubResourceGetStringValue(m_data.dialog,
"msgCorrect",
"MsgCorrect",
XmNlabelString,
XmCLabelString,
NULL);
}
else {
string = XfeSubResourceGetStringValue(m_data.dialog,
"msgNoSuggestions",
"MsgNoSuggestions",
XmNlabelString,
XmCLabelString,
NULL);
}
xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
XtVaSetValues(m_data.status, XmNlabelString, xstr, 0);
XmStringFree(xstr);
XtSetSensitive(m_data.text, True);
XtSetSensitive(m_data.list, False);
XtSetSensitive(m_data.replace, m_data.inCheck);
XtSetSensitive(m_data.replaceAll, m_data.inCheck);
XtSetSensitive(m_data.check, False);
XtSetSensitive(m_data.ignore, True);
XtSetSensitive(m_data.ignoreAll, True);
XtSetSensitive(m_data.learn, True);
XtSetSensitive(m_data.stop, True);
if (m_data.inCheck) {
XtVaSetValues(m_data.dialog,
XmNdefaultButton, m_data.replace, 0);
XtVaSetValues(m_data.ignore, XmNshowAsDefault, False, 0);
XtVaSetValues(m_data.replace, XmNshowAsDefault, True, 0);
XmProcessTraversal(m_data.replace, XmTRAVERSE_CURRENT);
}
else {
XtVaSetValues(m_data.dialog,
XmNdefaultButton, m_data.ignore, 0);
XtVaSetValues(m_data.replace, XmNshowAsDefault, False, 0);
XtVaSetValues(m_data.ignore, XmNshowAsDefault, True, 0);
XmProcessTraversal(m_data.ignore, XmTRAVERSE_CURRENT);
}
}
}
else {
XtSetSensitive(m_data.text, False);
// WARNING... [ need to use resource string ]
//
XmTextSetString(m_data.text, "");
string = XfeSubResourceGetStringValue(m_data.dialog,
"msgFinished",
"MsgFinished",
XmNlabelString,
XmCLabelString,
NULL);
xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
XtVaSetValues(m_data.status, XmNlabelString, xstr, 0);
XmStringFree(xstr);
XtSetSensitive(m_data.list, False);
XtSetSensitive(m_data.replace, True);
XtSetSensitive(m_data.replaceAll, False);
XtSetSensitive(m_data.check, False);
XtSetSensitive(m_data.ignore, False);
XtSetSensitive(m_data.ignoreAll, False);
XtSetSensitive(m_data.learn, False);
XtSetSensitive(m_data.stop, False);
}
m_data.inList = TRUE;
}
void
XFE_SpellHandler::PopupDialog(MWContext* context, char* eWord)
{
Widget dialog;
Widget label;
Widget list;
Widget status;
Widget frame;
Widget text;
Widget form;
Widget replace;
Widget replaceAll;
Widget check;
Widget ignore;
Widget ignoreAll;
Widget learn;
Widget stop;
Widget right_rc;
Widget left_rc;
Widget space;
Widget cframe;
Widget combo;
Arg args[20];
int n;
int rc_delta;
char* string;
XmString xstr = NULL;
Dimension height;
dialog = fe_CreatePromptDialog(context, "spellDialog",
FALSE, FALSE, FALSE, FALSE, TRUE);
n = 0;
form = XmCreateForm(dialog, "form", args, n);
XtManageChild(form);
n = 0;
XtSetArg(args [n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args [n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args [n], XmNrightAttachment, XmATTACH_FORM); n++;
frame = XmCreateFrame(form, "frame", args, n);
XtManageChild(frame);
n = 0;
XtSetArg(args [n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
status = XmCreateLabelGadget(frame, "status", args, n);
XtManageChild(status);
string = XfeSubResourceGetStringValue(dialog,
"msgNull",
"MsgNull",
XmNlabelString,
XmCLabelString,
NULL);
xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
XtVaSetValues(status, XmNlabelString, xstr, 0);
XmStringFree(xstr);
n = 0;
XtSetArg(args [n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args [n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args [n], XmNorientation, XmVERTICAL); n++;
// SPacINg madness...
//
XtSetArg(args [n], XmNmarginWidth, 0); n++;
XtSetArg(args [n], XmNmarginHeight, 0); n++;
XtSetArg(args [n], XmNspacing, 0); n++;
right_rc = XmCreateRowColumn(form, "right_rc", args, n);
XtManageChild(right_rc);
n = 0;
XtSetArg(args [n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args [n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args [n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args [n], XmNrightWidget, right_rc); n++;
XtSetArg(args [n], XmNorientation, XmVERTICAL); n++;
//
// WARNING... [ these should go in the Resource file ]
//
XtSetArg(args [n], XmNrightOffset, 15); n++;
XtSetArg(args [n], XmNmarginWidth, 0); n++;
XtSetArg(args [n], XmNmarginHeight, 0); n++;
XtSetArg(args [n], XmNspacing, 0); n++;
left_rc = XmCreateRowColumn(form, "left_rc", args, n);
XtManageChild(left_rc);
n = 0;
XtSetArg(args [n], XmNmarginWidth, 0); n++;
XtSetArg(args [n], XmNmarginHeight, 0); n++;
XtSetArg(args [n], XmNspacing, 0); n++;
XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
replace = XmCreatePushButtonGadget(right_rc, "replace", args, n);
XtManageChild(replace);
n = 0;
XtSetArg(args [n], XmNmarginWidth, 0); n++;
XtSetArg(args [n], XmNmarginHeight, 0); n++;
XtSetArg(args [n], XmNspacing, 0); n++;
XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
replaceAll = XmCreatePushButtonGadget(right_rc, "replace_all", args, n);
XtManageChild(replaceAll);
n = 0;
XtSetArg(args [n], XmNmarginWidth, 0); n++;
XtSetArg(args [n], XmNmarginHeight, 0); n++;
XtSetArg(args [n], XmNspacing, 0); n++;
XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
check = XmCreatePushButtonGadget(right_rc, "check", args, n);
XtManageChild(check);
n = 0;
XtSetArg(args [n], XmNmarginWidth, 0); n++;
XtSetArg(args [n], XmNmarginHeight, 0); n++;
XtSetArg(args [n], XmNspacing, 0); n++;
XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
ignore = XmCreatePushButtonGadget(right_rc, "ignore", args, n);
XtManageChild(ignore);
n = 0;
XtSetArg(args [n], XmNmarginWidth, 0); n++;
XtSetArg(args [n], XmNmarginHeight, 0); n++;
XtSetArg(args [n], XmNspacing, 0); n++;
XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
ignoreAll = XmCreatePushButtonGadget(right_rc, "ignore_all", args, n);
XtManageChild(ignoreAll);
n = 0;
XtSetArg(args [n], XmNmarginWidth, 0); n++;
XtSetArg(args [n], XmNmarginHeight, 0); n++;
XtSetArg(args [n], XmNspacing, 0); n++;
XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
learn = XmCreatePushButtonGadget(right_rc, "learn", args, n);
XtManageChild(learn);
n = 0;
XtSetArg(args [n], XmNmarginWidth, 0); n++;
XtSetArg(args [n], XmNmarginHeight, 0); n++;
XtSetArg(args [n], XmNspacing, 0); n++;
XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
stop = XmCreatePushButtonGadget(right_rc, "stop", args, n);
XtManageChild(stop);
n = 0;
label = XmCreateLabelGadget(left_rc, "text_label", args, n);
XtManageChild(label);
// WARNING... [ mAjOR layout hackery ]
//
XtVaGetValues(label, XmNheight, &height, 0);
rc_delta = (int)height - 5;
XtVaSetValues(right_rc, XmNtopOffset, rc_delta, 0);
// WARNING... [ do I need to dup this? ]
//
string = eWord;
n = 0;
XtSetArg(args [n], XmNvalue, string); n++;
XtSetArg(args [n], XmNeditable, True); n++;
XtSetArg(args [n], XmNcursorPositionVisible, True); n++;
text = fe_CreateTextField(left_rc, "errorText", args, n);
XtManageChild(text);
n = 0;
label = XmCreateLabelGadget(left_rc, "list_label", args, n);
XtManageChild(label);
n = 0;
XtSetArg(args [n], XmNvisibleItemCount, 10); n++;
list = XmCreateScrolledList(left_rc, "list", args, n);
XtManageChild(list);
n = 0;
XtSetArg(args [n], XmNseparatorType, XmNO_LINE); n++;
XtSetArg(args [n], XmNheight, 4); n++;
space = XmCreateSeparatorGadget(left_rc, "space", args, n);
XtManageChild(space);
n = 0;
XtSetArg(args [n], XmNshadowType, XmSHADOW_IN); n++;
XtSetArg(args [n], XmNshadowThickness, 1); n++;
cframe = XmCreateFrame(left_rc, "combo_frame", args, n);
XtManageChild(cframe);
Visual* v = 0;
Colormap cmap = 0;
Cardinal depth = 0;
XtVaGetValues(XfeAncestorFindTopLevelShell(form),
XtNvisual, &v,
XtNcolormap, &cmap,
XtNdepth, &depth,
0);
n = 0;
XtSetArg(args [n], XmNvisual, v); n++;
XtSetArg(args [n], XmNdepth, depth); n++;
XtSetArg(args [n], XmNcolormap, cmap); n++;
XtSetArg(args [n], XmNtype, XmDROP_DOWN_LIST_BOX); n++;
XtSetArg(args [n], XmNshadowThickness, 1); n++;
XtSetArg(args [n], XmNarrowType, XmMOTIF); n++;
combo = DtCreateComboBox(cframe, "comboBox", args, n);
XtManageChild(combo);
XtVaSetValues(left_rc,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, frame,
XmNbottomOffset, 6,
0);
XtVaSetValues(right_rc,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, frame,
XmNbottomOffset, 6,
0);
m_data.dialog = dialog;
m_data.list = list;
m_data.combo = combo;
m_data.replace = replace;
m_data.replaceAll = replaceAll;
m_data.check = check;
m_data.ignore = ignore;
m_data.ignoreAll = ignoreAll;
m_data.learn = learn;
m_data.stop = stop;
m_data.status = status;
m_data.text = text;
XtVaSetValues(dialog, XmNdefaultButton, replace, 0);
XtVaSetValues(dialog, XmNinitialFocus, list, 0);
// XtAddCallback(dialog, XmNcancelCallback, fe_open_url_cb, data);
// XtAddCallback(dialog, XmNapplyCallback, fe_clear_text_cb, text);
XtAddCallback(text,
XmNvalueChangedCallback, xfe_spell_text_cb, &m_data);
XtAddCallback(text,
XmNfocusCallback, xfe_spell_focus_in_cb, &m_data);
XtAddCallback(text,
XmNlosingFocusCallback, xfe_spell_focus_out_cb, &m_data);
XtAddCallback(list,
XmNbrowseSelectionCallback, xfe_spell_list_cb, &m_data);
XtAddCallback(combo,
XmNselectionCallback, xfe_spell_combo_cb, &m_data);
XtAddCallback(replace, XmNactivateCallback,
xfe_spell_doit_cb, &m_tags[XSP_REPLACE]);
XtAddCallback(replaceAll, XmNactivateCallback,
xfe_spell_doit_cb, &m_tags[XSP_REPLACEALL]);
XtAddCallback(check, XmNactivateCallback,
xfe_spell_doit_cb, &m_tags[XSP_CHECK]);
XtAddCallback(ignore, XmNactivateCallback,
xfe_spell_doit_cb, &m_tags[XSP_IGNORE]);
XtAddCallback(ignoreAll, XmNactivateCallback,
xfe_spell_doit_cb, &m_tags[XSP_IGNOREALL]);
XtAddCallback(learn, XmNactivateCallback,
xfe_spell_doit_cb, &m_tags[XSP_LEARN]);
XtAddCallback(stop, XmNactivateCallback,
xfe_spell_doit_cb, &m_tags[XSP_STOP]);
XtAddCallback(dialog,
XmNdestroyCallback, xfe_spell_destroy_cb, &m_data);
// NOTE: load the combo box...
//
initLanguageList();
fe_NukeBackingStore (dialog);
XtManageChild (dialog);
}
void
XFE_SpellHandler::initLanguageList()
{
int Language;
int Dialect;
int i;
char *string;
XmString xm_string;
int count = m_data.spell->GetNumOfDictionaries();
m_data.langCount = count;
m_data.langTags = (xfe_lang_tag *) XP_CALLOC(count, sizeof(xfe_lang_tag));
for (i = 0; i < count; i++)
{
if (m_data.spell->GetDictionaryLanguage(i, Language, Dialect) == 0)
{
string = getLanguageString(Language, Dialect);
xm_string = XmStringCreateLocalized(string);
DtComboBoxAddItem(m_data.combo, xm_string, i + 1, FALSE);
XmStringFree(xm_string);
}
else {
Language = 0;
Dialect = 0;
xm_string = XmStringCreateLocalized("");
DtComboBoxAddItem(m_data.combo, xm_string, i + 1, FALSE);
XmStringFree(xm_string);
}
m_data.langTags[i].language = Language;
m_data.langTags[i].dialect = Dialect;
}
XtVaSetValues(m_data.combo, XmNvisibleItemCount, (XtPointer)i, 0);
// Select the current default
//
m_data.spell->GetCurrentLanguage(Language, Dialect);
if (Language == 0 && Dialect == 0) {
updateLang(-1);
}
else {
for (i = 0; i < count; i++)
{
if (m_data.langTags[i].language == Language &&
m_data.langTags[i].dialect == Dialect)
{
updateLang(i);
break;
}
}
}
}
void
XFE_SpellHandler::updateLang(int indx)
{
if (indx < 0) {
m_data.langIndx = indx;
XmString blank = XmStringCreateLocalized("");
XtVaSetValues(m_data.combo,
XmNupdateLabel, False,
XmNlabelString, blank,
0);
XmStringFree(blank);
} else {
m_data.langIndx = indx;
XtVaSetValues(m_data.combo,
XmNupdateLabel, True,
XmNselectedPosition, indx,
0);
}
}
char *
XFE_SpellHandler::getLanguageString(int lang, int dialect)
{
char *string;
switch (lang)
{
case L_CZECH:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langCzech",
"LangCzech",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_RUSSIAN:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langRussian",
"LangRussian",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_CATALAN:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langCatalan",
"LangCatalan",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_HUNGARIAN:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langHungarian",
"LangHungarian",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_FRENCH:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langFrench",
"LangFrench",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_GERMAN:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langGerman",
"LangGerman",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_SWEDISH:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langSwedish",
"LangSwedish",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_SPANISH:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langSpanish",
"LangSpanish",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_ITALIAN:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langItalian",
"LangItalian",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_DANISH:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langDanish",
"LangDanish",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_DUTCH:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langDutch",
"LangDutch",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_PORTUGUESE:
if (dialect == D_BRAZILIAN)
string = XfeSubResourceGetStringValue(m_data.dialog,
"langPortugueseBrazilian",
"LangPortugueseBrazilian",
XmNlabelString,
XmCLabelString,
NULL);
else if (dialect == D_EUROPEAN)
string = XfeSubResourceGetStringValue(m_data.dialog,
"langPortugueseEuropean",
"LangPortugueseEuropean",
XmNlabelString,
XmCLabelString,
NULL);
else
string = XfeSubResourceGetStringValue(m_data.dialog,
"langPortuguese",
"LangPortuguese",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_NORWEGIAN:
if (dialect == D_BOKMAL)
string = XfeSubResourceGetStringValue(m_data.dialog,
"langNorwegianBokmal",
"LangNorwegianBokmal",
XmNlabelString,
XmCLabelString,
NULL);
else if (dialect == D_NYNORSK)
string = XfeSubResourceGetStringValue(m_data.dialog,
"langNorwegianNynorsk",
"LangNorwegianNynorsk",
XmNlabelString,
XmCLabelString,
NULL);
else
string = XfeSubResourceGetStringValue(m_data.dialog,
"langNorwegian",
"LangNorwegian",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_FINNISH:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langFinnish",
"LangFinnish",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_GREEK:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langGreek",
"LangGreek",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_ENGLISH:
if (dialect == D_US_ENGLISH)
string = XfeSubResourceGetStringValue(m_data.dialog,
"langEnglishUS",
"LangEnglishUS",
XmNlabelString,
XmCLabelString,
NULL);
else if (dialect == D_UK_ENGLISH)
string = XfeSubResourceGetStringValue(m_data.dialog,
"langEnglishUK",
"LangEnglishUK",
XmNlabelString,
XmCLabelString,
NULL);
else
string = XfeSubResourceGetStringValue(m_data.dialog,
"langEnglish",
"LangEnglish",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_AFRIKAANS:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langAfrikaans",
"LangAfrikaans",
XmNlabelString,
XmCLabelString,
NULL);
break;
case L_POLISH:
string = XfeSubResourceGetStringValue(m_data.dialog,
"langPolish",
"LangPolish",
XmNlabelString,
XmCLabelString,
NULL);
break;
default:
string = "";
break;
}
return string;
}
XP_Bool
XFE_SpellHandler::ProcessDocument(MWContext* context, XP_Bool isHtml)
{
initSpellChecker();
if (m_data.spell == NULL)
return FALSE;
if (m_data.interface == NULL) {
if (isHtml) {
m_data.interface = new XFE_HtmlSpellCheck(m_data.spell, context);
}
else {
m_data.interface = new XFE_TextSpellCheck(m_data.spell, context);
}
}
m_data.inCheck = FALSE;
m_data.isOk = FALSE;
m_data.isDone = FALSE;
XP_Bool oops = m_data.interface->ProcessDocument(&m_tags[XSP_NULL]);
PopupDialog(context, m_data.xWord);
UpdateGUI();
return oops;
}
XP_Bool
XFE_SpellHandler::ReprocessDocument()
{
m_data.interface->ProcessError(&m_tags[XSP_STOP]);
nukeSpellChecker();
initSpellChecker();
m_data.inCheck = FALSE;
m_data.isOk = FALSE;
m_data.isDone = FALSE;
XP_Bool oops = m_data.interface->ProcessDocument(&m_tags[XSP_NULL]);
UpdateGUI();
return oops;
}
XP_Bool
XFE_SpellHandler::ProcessError(xfe_spell_tag *tag)
{
int action = tag->action;
xfe_spell_data *data = tag->data;
ISpellChecker *spell = data->spell;
data->inCheck = FALSE;
data->isOk = FALSE;
switch (action) {
case XSP_STOP:
// call this to cleanup before nuking the dialog...
(data->interface)->ProcessError(tag);
(data->interface)->resetVars();
case XSP_REPLACE:
if (data->isDone) {
XtUnmanageChild(data->dialog);
//
// Nuke it...
//
XtDestroyWidget(data->dialog);
return FALSE;
}
break;
case XSP_CHECK:
data->inCheck = TRUE;
if (spell->CheckWord(data->nuText)) {
data->isOk = TRUE;
}
data->xWord = data->nuText;
return TRUE;
default:
break;
}
return (data->interface)->ProcessError(tag);
}
// -------------------------------------------------------------[ SpellCheck ]
XFE_SpellCheck::XFE_SpellCheck(ISpellChecker *spell, MWContext* context)
{
m_spellChecker = spell;
m_bufferSize = 0;
m_xpDelta = 0;
m_contextData = context;
m_misspelledWord = NULL;
m_selStart = 0;
m_selEnd = 0;
}
XFE_SpellCheck::~XFE_SpellCheck()
{
m_spellChecker = NULL;
}
void
XFE_SpellCheck::resetVars()
{
m_bufferSize = 0;
m_xpDelta = 0;
m_selStart = 0;
m_selEnd = 0;
}
XP_Bool
XFE_SpellCheck::ProcessError(xfe_spell_tag* tag)
{
int action = tag->action;
xfe_spell_data *data = tag->data;
char *usrText = data->nuText;
char *tmp = NULL;
if (m_misspelledWord) {
switch (action) {
case XSP_REPLACE:
ReplaceHilitedText(usrText, FALSE);
break;
case XSP_REPLACEALL:
ReplaceHilitedText(usrText, TRUE);
break;
case XSP_IGNORE:
IgnoreHilitedText(FALSE);
break;
case XSP_IGNOREALL:
IgnoreHilitedText(TRUE);
break;
case XSP_LEARN:
tmp = XmTextFieldGetString(data->text);
if (tmp) {
m_spellChecker->AddWordToPersonalDictionary(tmp);
if (XP_STRCMP( m_misspelledWord, tmp) == 0) {
IgnoreHilitedText(TRUE);
}
else {
ReplaceHilitedText(tmp, TRUE);
}
XtFree(tmp);
}
break;
case XSP_STOP:
m_misspelledWord = NULL;
data->xWord = NULL;
data->isDone = TRUE;
RemoveAllErrorHilites();
return FALSE;
default:
break;
}
m_misspelledWord = GetNextError();
}
else {
m_misspelledWord = GetFirstError();
}
if (!m_misspelledWord) {
m_misspelledWord = NULL;
data->xWord = NULL;
data->isDone = TRUE;
RemoveAllErrorHilites();
return FALSE;
}
else {
data->xWord = m_misspelledWord;
return TRUE;
}
}
XP_Bool
XFE_SpellCheck::ProcessDocument(xfe_spell_tag* tag)
{
xfe_spell_data *data = tag->data;
ISpellChecker *spell = data->spell;
// NOTE: important to make sure that we are in sync with the Handler...
//
if (m_spellChecker != spell) {
m_spellChecker = spell;
}
// Get the text buffer from the document
XP_HUGE_CHAR_PTR pBuf = GetBuffer();
if (pBuf == NULL)
return 0; // nothing to spell check
// If we were spell checking a selection in the previous pass,
// adjust the selection for any corrections made in the last pass.
//
if (m_selEnd > 0) {
m_selEnd += (XP_STRLEN(pBuf) - (m_bufferSize - m_xpDelta));
}
else {
GetSelection(m_selStart, m_selEnd);
}
// pass text buffer to the spell checker
int retcode = m_spellChecker->SetBuf(pBuf, m_selStart, m_selEnd);
m_bufferSize = (int) m_spellChecker->GetBufSize();
m_xpDelta = m_bufferSize - XP_STRLEN(pBuf);
// release the buffer (the Spell Checker makes a local copy)
XP_HUGE_FREE(pBuf);
// WARNING... [ marking all misspelled words ]
//
return ProcessError(tag);
}
// ---------------------------------------------------------[ HtmlSpellCheck ]
XFE_HtmlSpellCheck::XFE_HtmlSpellCheck(ISpellChecker *spell,
MWContext *context)
: XFE_SpellCheck(spell, context)
{
}
XFE_HtmlSpellCheck::~XFE_HtmlSpellCheck()
{
}
char *
XFE_HtmlSpellCheck::GetBuffer()
{
return EDT_GetPositionalText(m_contextData);
}
void
XFE_HtmlSpellCheck::IgnoreHilitedText(int AllInstances)
{
char *pOldWord = (char *)LO_GetSelectionText(m_contextData);
if (pOldWord != NULL)
{
EDT_IgnoreMisspelledWord(m_contextData, pOldWord, AllInstances);
XP_FREE(pOldWord);
}
}
void
XFE_HtmlSpellCheck::RemoveAllErrorHilites()
{
// EDT_BeginOfDocument(m_contextData, FALSE);
// EDT_SetRefresh(m_contextData, TRUE);
// ignore any unprocessed misspelled words
EDT_IgnoreMisspelledWord(m_contextData, NULL, TRUE);
}
char *
XFE_HtmlSpellCheck::GetFirstError()
{
// turn off refreshing and spell check the text.
EDT_SetRefresh(m_contextData, FALSE);
// underline the misspelled words
EDT_CharacterData* pCharData = EDT_NewCharacterData();
pCharData->mask = TF_SPELL;
pCharData->values = TF_SPELL;
unsigned long Offset, Len;
while (m_spellChecker->GetNextMisspelledWord(Offset, Len) == 0)
EDT_SetCharacterDataAtOffset(m_contextData, pCharData, Offset, Len);
XP_FREE(pCharData);
// set sursor position at the beginning of document so that
// EDT_SelectNextMisspelledWord() to start at the beginning.
EDT_BeginOfDocument(m_contextData, FALSE);
EDT_SetRefresh(m_contextData, TRUE);
// m_pView->UpdateWindow();
fe_EditorRefresh(m_contextData);
// Select and return the first mispelled word
if (EDT_SelectFirstMisspelledWord(m_contextData))
return (char *)LO_GetSelectionText(m_contextData);
else
return NULL;
}
char *
XFE_HtmlSpellCheck::GetNextError()
{
if (EDT_SelectNextMisspelledWord(m_contextData))
return (char *)LO_GetSelectionText(m_contextData);
else
return 0;
}
XP_Bool
XFE_HtmlSpellCheck::GetSelection(int32 &SelStart, int32 &SelEnd)
{
char *pSelection;
if ((pSelection = (char *)LO_GetSelectionText(m_contextData)) != NULL)
{
XP_FREE(pSelection);
EDT_GetSelectionOffsets(m_contextData, &SelStart, &SelEnd);
return TRUE;
}
else
return FALSE; // no selection
}
void
XFE_HtmlSpellCheck::ReplaceHilitedText(const char *NewText,
XP_Bool AllInstances)
{
char *pOldWord = (char *)LO_GetSelectionText(m_contextData);
if (pOldWord != NULL)
{
EDT_ReplaceMisspelledWord(m_contextData,
pOldWord, (char*)NewText, AllInstances);
XP_FREE(pOldWord);
}
else {
#ifdef DEBUG_spellcheck
fprintf(stderr, "WARNING... [ unable to fetch pOldWord ]\n");
#endif
}
}
// --------------------------------------------------------[ TextSpellCheck ]
XFE_TextSpellCheck::XFE_TextSpellCheck(ISpellChecker *spell,
MWContext *context)
: XFE_SpellCheck(spell, context)
{
m_textWidget = CONTEXT_DATA(m_contextData)->mcBodyText;
m_dirty = FALSE;
m_offset = 0;
m_len = 0;
}
XFE_TextSpellCheck::~XFE_TextSpellCheck()
{
m_textWidget = NULL;
}
char *
XFE_TextSpellCheck::GetBuffer()
{
return XmTextGetString(m_textWidget);
}
void
XFE_TextSpellCheck::IgnoreHilitedText(int AllInstances)
{
if (m_selEnd > 0) {
XmTextSetHighlight(m_textWidget,
m_offset, (m_offset + m_len),
XmHIGHLIGHT_SECONDARY_SELECTED
);
}
else {
XmTextSetHighlight(m_textWidget,
m_offset, (m_offset + m_len),
XmHIGHLIGHT_NORMAL
);
}
if (AllInstances) {
m_spellChecker->IgnoreWord(m_misspelledWord);
}
}
void
XFE_TextSpellCheck::RemoveAllErrorHilites()
{
if (m_selEnd > 0 && !m_dirty) {
Time time = XtLastTimestampProcessed(XtDisplay(m_textWidget));
// Nuke the selection if it still exists after the spell check...
//
XmTextClearSelection(m_textWidget, time);
// XmTextSetHighlight(m_textWidget,
// m_selStart, m_selEnd,
// XmHIGHLIGHT_SELECTED
// );
}
else {
XmTextSetHighlight(m_textWidget,
0, (m_bufferSize - 1),
XmHIGHLIGHT_NORMAL
);
}
}
char *
XFE_TextSpellCheck::GetFirstError()
{
if (m_selEnd > m_selStart) {
XmTextSetHighlight(m_textWidget,
m_selStart, m_selEnd,
XmHIGHLIGHT_SECONDARY_SELECTED
);
}
return GetNextError();
}
char *
XFE_TextSpellCheck::GetNextError()
{
unsigned long Offset, Len;
char *pMisspelledWord = NULL;
if (m_spellChecker->GetNextMisspelledWord(Offset, Len) == 0)
{
m_offset = (int) Offset;
m_len = (int) Len;
// hilight mispelled word
XmTextSetHighlight(m_textWidget,
m_offset, (m_offset + m_len),
XmHIGHLIGHT_SELECTED
);
// Extract mispelled word
XP_HUGE_CHAR_PTR pBuf = GetBuffer();
if (pBuf != NULL)
{
pMisspelledWord = (char *)XP_ALLOC(Len + 1);
if (pMisspelledWord != NULL)
XP_STRNCPY_SAFE(pMisspelledWord, pBuf + Offset, Len+1);
XP_HUGE_FREE(pBuf);
}
}
else {
m_offset = 0;
m_len = 0;
}
return pMisspelledWord;
}
XP_Bool
XFE_TextSpellCheck::GetSelection(int32 &SelStart, int32 &SelEnd)
{
XmTextPosition xRight;
XmTextPosition xLeft;
XmTextGetSelectionPosition(m_textWidget, &xRight, &xLeft);
if (xLeft > xRight)
{
SelStart = (int) xRight;
SelEnd = (int) xLeft;
XmTextSetHighlight(m_textWidget,
SelStart, SelEnd,
XmHIGHLIGHT_SECONDARY_SELECTED
);
return TRUE;
}
else {
SelStart = 0;
SelEnd = 0;
return FALSE;
}
}
void
XFE_TextSpellCheck::ReplaceHilitedText(const char *NewText,
XP_Bool AllInstances)
{
if (m_spellChecker->ReplaceMisspelledWord(NewText, AllInstances) != 0) {
#ifdef DEBUG_spellcheck
fprintf(stderr, "WARNING... [ ReplaceMisspelledWord failed ]\n");
#endif
}
unsigned long NewBufSize = m_spellChecker->GetBufSize();
char *pNewBuf = (char *)XP_ALLOC(NewBufSize);
if (pNewBuf == NULL) {
#ifdef DEBUG_spellcheck
fprintf(stderr, "WARNING... [ unable to alloc pNewBuf ]\n");
#endif
return;
}
int delta = NewBufSize - m_bufferSize;
int nuEnd = 0;
if (m_selEnd > 0) {
nuEnd = m_selEnd + delta;
if (nuEnd < m_selEnd) {
// NOTE: we have to fix up the end of the the selection marker...
//
XmTextSetHighlight(m_textWidget,
m_selStart, m_selEnd,
XmHIGHLIGHT_NORMAL
);
}
}
m_spellChecker->GetBuf(pNewBuf, NewBufSize);
XmTextSetString(m_textWidget, pNewBuf);
// NOTE: this denotes the lose of the "selection" in the text widget...
//
m_dirty = True;
m_bufferSize = (int)NewBufSize;
if (m_selEnd > 0) {
m_selEnd = nuEnd;
XmTextSetHighlight(m_textWidget,
m_selStart, m_selEnd,
XmHIGHLIGHT_SECONDARY_SELECTED
);
}
XP_FREE(pNewBuf);
}
// --------------------------------------------------------------------[ API ]
Boolean
xfe_SpellCheckerAvailable(MWContext* context)
{
if (xfe_spellHandler == NULL) {
xfe_spellHandler = new XFE_SpellHandler(context);
}
return xfe_spellHandler->IsAvailable();
}
Boolean
xfe_EditorSpellCheck(MWContext* context)
{
if (xfe_SpellCheckerAvailable(context)) {
xfe_spellHandler->ProcessDocument(context, TRUE);
return TRUE;
}
else {
return FALSE;
}
}
Boolean
xfe_TextSpellCheck(MWContext* context)
{
if (xfe_SpellCheckerAvailable(context)) {
xfe_spellHandler->ProcessDocument(context, FALSE);
return TRUE;
}
else {
return FALSE;
}
}
// ----<eof>