home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / SpellHandler.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  47.2 KB  |  1,873 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.    SpellHandler.cpp -- class definition for the Spell Handler class
  20.    Created: Richard Hess <rhess@netscape.com>, 12-May-97
  21.  */
  22.  
  23.  
  24. #include "SpellHandler.h"
  25.  
  26. #include "spellchk.h"
  27.  
  28. #include "xpgetstr.h"
  29. #include "fe_proto.h"
  30. #include "edt.h"
  31. #include "xeditor.h"
  32.  
  33. #include "prefs.h"
  34. #include "prefapi.h"
  35. #include "prlink.h"
  36.  
  37. #include <Xm/Text.h>
  38. #include <DtWidgets/ComboBoxP.h>
  39. #include <Xfe/Xfe.h>
  40.  
  41. extern "C" {
  42.     void fe_GetProgramDirectory(char *path, int len);
  43. }
  44.  
  45. static XFE_SpellHandler  *xfe_spellHandler = NULL;
  46.  
  47. // Preference strings
  48. static char *LanguagePref = "spellchecker.default_language";
  49. static char *DialectPref  = "spellchecker.default_dialect";
  50.  
  51. extern int NO_SPELL_SHLIB_FOUND;
  52.  
  53. // WARNING... [ be VERY careful with this index stuff ]
  54. //
  55. #define XSP_NULL       0
  56. #define XSP_REPLACE    1
  57. #define XSP_REPLACEALL 2
  58. #define XSP_CHECK      3
  59. #define XSP_IGNORE     4
  60. #define XSP_IGNOREALL  5
  61. #define XSP_LEARN      6
  62. #define XSP_STOP       7
  63. //
  64. // IMPORTANT:  if you add to this list you need to update the value of
  65. //             XSP_CACHE_SIZE in SpellHandler.h to reflect the change
  66. //             in the size of the tag cache...
  67. //
  68.  
  69.  
  70. static void
  71. xfe_spell_focus_in_cb (Widget , XtPointer closure, XtPointer )
  72. {
  73.     struct xfe_spell_data *data = (struct xfe_spell_data *) closure;
  74.     char *tmp = XmTextFieldGetString(data->text);
  75.         
  76.     if (data->inList) {
  77.         data->inList = FALSE;
  78.         XmListDeselectAllItems(data->list);
  79.  
  80.         if (XP_STRCMP( tmp, data->xWord ) == 0) {
  81.             XtSetSensitive(data->replace, FALSE);
  82.             XtSetSensitive(data->replaceAll, FALSE);
  83.             XtSetSensitive(data->check, FALSE);
  84.  
  85.             XtVaSetValues(data->dialog,  XmNdefaultButton, data->ignore, 0);
  86.             XtVaSetValues(data->replace, XmNshowAsDefault, False, 0);
  87.             XtVaSetValues(data->ignore,  XmNshowAsDefault, True, 0);
  88.             XmProcessTraversal(data->ignore, XmTRAVERSE_CURRENT);
  89.         } else {
  90.             XtSetSensitive(data->replace, True);
  91.             XtSetSensitive(data->replaceAll, True);
  92.             XtSetSensitive(data->check, TRUE);
  93.  
  94.             XtVaSetValues(data->dialog,  XmNdefaultButton, data->replace, 0);
  95.             XtVaSetValues(data->ignore,  XmNshowAsDefault, False, 0);
  96.             XtVaSetValues(data->replace, XmNshowAsDefault, True, 0);
  97.             XmProcessTraversal(data->replace, XmTRAVERSE_CURRENT);
  98.         }
  99.     }
  100.  
  101.     if (data->nuText)
  102.         XP_FREE(data->nuText);
  103.     
  104.     data->nuText = XP_STRDUP(tmp);
  105.     
  106.     if (tmp)
  107.         XtFree(tmp);
  108. }
  109.  
  110. static void
  111. xfe_spell_focus_out_cb (Widget , XtPointer closure, XtPointer )
  112. {
  113.     struct xfe_spell_data *data = (struct xfe_spell_data *) closure;
  114.         
  115.     if (data->inList) {
  116.         XtSetSensitive(data->check, False);
  117.     }
  118. }
  119.  
  120. static void
  121. xfe_spell_text_cb (Widget , XtPointer closure, XtPointer )
  122. {
  123.     struct xfe_spell_data *data = (struct xfe_spell_data *) closure;
  124.     char *tmp = XmTextFieldGetString(data->text);
  125.         
  126.     if (data->xWord != NULL) {
  127.         if (XP_STRCMP( tmp, data->xWord ) == 0) {
  128.             XtSetSensitive(data->replace, FALSE);
  129.             XtSetSensitive(data->replaceAll, FALSE);
  130.             XtSetSensitive(data->check, FALSE);
  131.  
  132.             XtVaSetValues(data->dialog,  XmNdefaultButton, data->ignore, 0);
  133.             XtVaSetValues(data->replace, XmNshowAsDefault, False, 0);
  134.             XtVaSetValues(data->ignore,  XmNshowAsDefault, True, 0);
  135.         } else {
  136.             XtSetSensitive(data->replace, True);
  137.             XtSetSensitive(data->replaceAll, True);
  138.             XtSetSensitive(data->check, TRUE);
  139.  
  140.             XtVaSetValues(data->dialog,  XmNdefaultButton, data->replace, 0);
  141.             XtVaSetValues(data->ignore,  XmNshowAsDefault, False, 0);
  142.             XtVaSetValues(data->replace, XmNshowAsDefault, True, 0);
  143.         }
  144.     }
  145.  
  146.     if (data->nuText)
  147.         XP_FREE(data->nuText);
  148.     
  149.     data->nuText = XP_STRDUP(tmp);
  150.     
  151.     if (tmp)
  152.         XtFree(tmp);
  153. }
  154.  
  155. static void
  156. xfe_spell_list_cb (Widget , XtPointer closure, XtPointer call_data)
  157. {
  158.     struct xfe_spell_data *data = (struct xfe_spell_data *) closure;
  159.     XmListCallbackStruct *cdata = (XmListCallbackStruct *) call_data;
  160.     ISpellChecker        *spell = data->spell;
  161.     char tmp[125];
  162.  
  163.     int  i = cdata->item_position - 1;
  164.  
  165.     if (!data->inList) {
  166.         XtSetSensitive(data->replace, True);
  167.         XtSetSensitive(data->replaceAll, True);
  168.  
  169.         XtSetSensitive(data->check, False);
  170.  
  171.         XtVaSetValues(data->dialog,  XmNdefaultButton, data->replace, 0);
  172.         XtVaSetValues(data->ignore,  XmNshowAsDefault, False, 0);
  173.         XtVaSetValues(data->replace, XmNshowAsDefault, True, 0);
  174.     }
  175.  
  176.     data->inList = TRUE;
  177.  
  178.     if (spell)
  179.         spell->GetAlternative(i, tmp, sizeof(tmp));
  180.  
  181.     if (data->nuText)
  182.         XP_FREE(data->nuText);
  183.  
  184.     data->nuText = XP_STRDUP(tmp);
  185. }
  186.     
  187. static void
  188. xfe_spell_combo_cb (Widget , XtPointer closure, XtPointer call_data)
  189. {
  190.     struct xfe_spell_data    *data = (struct xfe_spell_data *) closure;
  191.     DtComboBoxCallbackStruct *info = (DtComboBoxCallbackStruct*)call_data;
  192.     int i = info->item_position;
  193.     int NewLanguage = data->langTags[i].language;
  194.     int NewDialect  = data->langTags[i].dialect;
  195.  
  196.     PREF_SetIntPref(LanguagePref, NewLanguage);
  197.     PREF_SetIntPref(DialectPref, NewDialect);
  198.  
  199.     if (data->langIndx != i) {
  200.         data->langIndx = i;
  201.  
  202.         xfe_spellHandler->ReprocessDocument();
  203.     }
  204. }
  205.     
  206. static void
  207. xfe_spell_doit_cb (Widget , XtPointer closure, XtPointer )
  208. {
  209.     struct xfe_spell_tag  *tag  = (struct xfe_spell_tag *) closure;
  210.     
  211.     xfe_spellHandler->ProcessError(tag);
  212.     xfe_spellHandler->UpdateGUI();
  213. }
  214.     
  215. static void
  216. xfe_spell_destroy_cb (Widget , XtPointer , XtPointer )
  217. {
  218.     xfe_spellHandler->DialogDestroyed();
  219. }
  220.     
  221.  
  222. // -----------------------------------------------------------[ SpellHandler ]
  223.  
  224.  
  225. /*static*/ PRLibrary* XFE_SpellHandler::m_spellCheckerLib = NULL;
  226. /*static*/ XP_Bool XFE_SpellHandler::m_triedToLoad = FALSE;
  227.  
  228. XFE_SpellHandler::XFE_SpellHandler(MWContext* )
  229. {
  230.     int i = 0;
  231.  
  232.     m_triedToLoad = FALSE;
  233.     m_active = FALSE;
  234.  
  235.     m_data.spell     = NULL;
  236.     m_data.interface = NULL;
  237.     m_data.dialog  = NULL;
  238.     m_data.list    = NULL;
  239.     m_data.combo   = NULL;
  240.     m_data.replace = NULL;
  241.     m_data.replaceAll = NULL;
  242.     m_data.check      = NULL;
  243.     m_data.ignore     = NULL;
  244.     m_data.ignoreAll  = NULL;
  245.     m_data.learn      = NULL;
  246.     m_data.stop       = NULL;
  247.     m_data.status  = NULL;
  248.     m_data.text    = NULL;
  249.     m_data.nuText  = NULL;
  250.     m_data.langTags  = NULL;
  251.     m_data.langCount = 0;
  252.     m_data.langIndx  = 0;
  253.     m_data.inList  = TRUE;
  254.     m_data.inCheck = FALSE;
  255.     m_data.isOk    = FALSE;
  256.     m_data.isDone  = FALSE;
  257.  
  258.     for (i = 0 ; i < XSP_CACHE_SIZE ; i++) {
  259.         //
  260.         // WARNING... [ be VERY careful with this index stuff ]
  261.         //
  262.         m_tags[i].action = i;
  263.         m_tags[i].data = &m_data;
  264.     }
  265.  
  266.     // NOTE:  we try to create the spell checker backend in order to 
  267.     //        determine it's availability... [ m_active ]
  268.     //
  269.     initSpellChecker();
  270.     nukeSpellChecker();
  271. }
  272.  
  273. XFE_SpellHandler::~XFE_SpellHandler()
  274. {
  275.     if (m_data.interface != NULL)
  276.         delete m_data.interface;
  277.  
  278.     if (m_data.spell != NULL)
  279.         nukeSpellChecker();
  280.  
  281.     if (m_data.langTags != NULL)
  282.         XP_FREE(m_data.langTags);
  283.  
  284.     m_active       = FALSE;
  285.  
  286.     m_data.spell     = NULL;
  287.     m_data.interface = NULL;
  288.     m_data.dialog  = NULL;
  289.     m_data.list    = NULL;
  290.     m_data.combo   = NULL;
  291.     m_data.replace = NULL;
  292.     m_data.replaceAll = NULL;
  293.     m_data.check      = NULL;
  294.     m_data.ignore     = NULL;
  295.     m_data.ignoreAll  = NULL;
  296.     m_data.learn      = NULL;
  297.     m_data.stop       = NULL;
  298.     m_data.status  = NULL;
  299.     m_data.text    = NULL;
  300.     m_data.langTags  = NULL;
  301.     m_data.langCount = 0;
  302.     m_data.langIndx  = 0;
  303.     m_data.inList  = TRUE;
  304.     m_data.inCheck = FALSE;
  305.     m_data.isOk    = FALSE;
  306.     m_data.isDone  = FALSE;
  307. }
  308.  
  309. void
  310. XFE_SpellHandler::initSpellChecker()
  311. {
  312.     // Let people disable spell checking in case they have NFS-related hangs:
  313.     XP_Bool disable_spell_checker;
  314.     PREF_GetBoolPref("editor.disable_spell_checker", &disable_spell_checker);
  315.     if (disable_spell_checker) {
  316.         m_active = FALSE;
  317.         return;
  318.     }
  319.  
  320.     if (m_data.spell != NULL)
  321.         return;     // already initialized
  322.  
  323.     if (!m_triedToLoad)
  324.     {
  325.         m_triedToLoad = TRUE;
  326.         //const char* libPath = PR_GetLibraryPath();
  327.         //PR_SetLibraryPath("/usr/local/netscape/");
  328.  
  329.         char* libname = "libspellchk.so";
  330.         m_spellCheckerLib = PR_LoadLibrary(libname);
  331.  
  332.         // Set path back to original path
  333.         //PR_SetLibraryPath(libPath);
  334.  
  335.         if (m_spellCheckerLib == NULL)
  336.         {
  337. #ifdef DEBUG_akkana
  338.             printf("Couldn't find library NSSpellChecker\n");
  339. #endif
  340.             m_active = 0;
  341.             return;
  342.         }
  343.         m_active = TRUE;
  344.     }
  345.  
  346.     if (m_data.spell == NULL && m_active)
  347.     {
  348.         typedef ISpellChecker*(*sc_create_func)();
  349.         sc_create_func sc_createProc =
  350.             (sc_create_func)PR_FindSymbol(m_spellCheckerLib, "SC_Create");
  351.         if (sc_createProc == NULL)
  352.         {
  353. #ifdef DEBUG_akkana
  354.             printf("Couldn't find symbol SC_Create\n");
  355. #endif
  356.             m_active = FALSE;
  357.             return;
  358.         }
  359.  
  360.         m_data.spell = sc_createProc();
  361.     }
  362.  
  363.     if (m_data.spell == NULL)
  364.     {
  365. #ifdef DEBUG_akkana
  366.         printf("Couldn't initialize spellchecker\n");
  367. #endif
  368.         m_active = FALSE;
  369.         return;
  370.     }
  371.  
  372.     int32 Language = 0;
  373.     int32 Dialect = 0;
  374.  
  375.     // First see if any language preferences have been set
  376.     PREF_GetIntPref(LanguagePref, &Language);
  377.     PREF_GetIntPref(DialectPref, &Dialect);
  378.  
  379.     char *spellDir = getSpellCheckerDir();
  380.     char *personal = getPersonalDicPath();
  381.  
  382. #ifdef DEBUG_spellcheck
  383.     fprintf(stderr, "spellDir::[ %s ]\n", spellDir);
  384.     fprintf(stderr, "personal::[ %s ]\n", personal);
  385. #endif
  386.  
  387.     if (m_data.spell->Initialize(Language, Dialect, 
  388.                                  spellDir, personal)) {
  389.         m_active = FALSE;
  390.     }
  391.     else {
  392.         m_active = TRUE;
  393.     }
  394. }
  395.  
  396. void
  397. XFE_SpellHandler::nukeSpellChecker()
  398. {
  399.     if (m_data.spell != NULL
  400.         && m_spellCheckerLib != NULL
  401.         )
  402.     {
  403.         typedef void (*sc_destroy_func)(ISpellChecker*);
  404.         sc_destroy_func sc_destroyProc =
  405.             (sc_destroy_func)PR_FindSymbol(m_spellCheckerLib, "SC_Destroy");
  406.         if (sc_destroyProc != NULL)
  407.             sc_destroyProc(m_data.spell);
  408.         m_data.spell = NULL;
  409.     }
  410. }
  411.  
  412. char *
  413. XFE_SpellHandler::getSpellCheckerDir()
  414. {
  415.     char *home = NULL;
  416.     char *mozilla_home = NULL;
  417.     char buf[MAXPATHLEN];
  418.  
  419.  
  420.     if (home = getenv("HOME")) {
  421.         XP_MEMSET(buf, '\0', sizeof(buf));
  422.  
  423.         // Form "$HOME/.netscape/spell/" into buf...
  424.         //
  425.         XP_STRNCPY_SAFE(buf, home, sizeof(buf)-1);
  426.         XP_STRNCAT_SAFE(buf, "/.netscape/spell/",
  427.                         sizeof(buf)-1 - XP_STRLEN(buf));
  428.         buf[sizeof(buf)-1] = '\0';
  429.         
  430.         if (fe_isDir(buf)) {
  431.             return XP_STRDUP(buf);
  432.         }
  433.     }
  434.  
  435.     if (mozilla_home = getenv("MOZILLA_HOME")) {
  436.         XP_MEMSET(buf, '\0', sizeof(buf));
  437.  
  438.         // Form "$MOZILLA_HOME/spell/" into buf...
  439.         //
  440.         XP_STRNCPY_SAFE(buf, mozilla_home, sizeof(buf)-1);
  441.         XP_STRNCAT_SAFE(buf, "/spell/", 
  442.                         sizeof(buf)-1 - XP_STRLEN(buf));
  443.         buf[sizeof(buf)-1] = '\0';
  444.  
  445.         if (fe_isDir(buf)) {
  446.             return XP_STRDUP(buf);
  447.         }
  448.     }
  449.  
  450.     XP_MEMSET(buf, '\0', sizeof(buf));
  451.     //
  452.     // Form "<program-dir>/spell/" into buf...
  453.     //
  454.     fe_GetProgramDirectory(buf, sizeof(buf)-1);
  455.     if (XP_STRLEN(buf) > 0) {
  456.         // WARNING... [ the program dir already has a trailing slash ]
  457.         //
  458.         XP_STRNCAT_SAFE(buf, "spell/",
  459.                         sizeof(buf)-1 - XP_STRLEN(buf));
  460.         buf[sizeof(buf)-1] = '\0';
  461.  
  462.         if (fe_isDir(buf)) {
  463.             return XP_STRDUP(buf);
  464.         }
  465.     }
  466.  
  467.     // last chance, look for "/usr/local/netscape/spell/"...
  468.     //
  469.     if (fe_isDir("/usr/local/netscape/spell/")) {
  470.         return XP_STRDUP("/usr/local/netscape/spell/");
  471.     }
  472.  
  473.     // NOTE:  punt on the directory...
  474.     //
  475.     return XP_STRDUP(".");
  476. }
  477.  
  478. char *
  479. XFE_SpellHandler::getPersonalDicPath()
  480. {
  481.     char buf[MAXPATHLEN];
  482.     char *home = NULL;
  483.  
  484.     if (home = getenv("HOME"))
  485.     {
  486.         /* Form "$HOME/.netscape/custom.dic" into buf */
  487.         XP_STRNCPY_SAFE(buf, home, sizeof(buf)-1);
  488.         XP_STRNCAT_SAFE(buf, "/.netscape/custom.dic",
  489.                         sizeof(buf)-1 - XP_STRLEN(buf));
  490.         buf[sizeof(buf)-1] = '\0';
  491.     }
  492.  
  493.     return XP_STRDUP(buf);
  494. }
  495.  
  496. XP_Bool
  497. XFE_SpellHandler::IsActive()
  498. {
  499.     return m_active;
  500. }
  501.  
  502. XP_Bool
  503. XFE_SpellHandler::IsAvailable()
  504. {
  505.     return (m_active && (m_data.spell == NULL));
  506. }
  507.  
  508. void
  509. XFE_SpellHandler::DialogDestroyed()
  510. {
  511.     if (m_data.xWord) {
  512.         m_data.interface->RemoveAllErrorHilites();
  513.     }
  514.  
  515.     if (m_data.nuText) {
  516.         XP_FREE(m_data.nuText);
  517.     }
  518.  
  519.     if (m_data.langTags != NULL)
  520.         XP_FREE(m_data.langTags);
  521.  
  522.     delete m_data.interface;
  523.     nukeSpellChecker();
  524.  
  525.     m_data.spell     = NULL;
  526.     m_data.interface = NULL;
  527.     m_data.dialog  = NULL;
  528.     m_data.list    = NULL;
  529.     m_data.combo   = NULL;
  530.     m_data.replace = NULL;
  531.     m_data.replaceAll = NULL;
  532.     m_data.check      = NULL;
  533.     m_data.ignore     = NULL;
  534.     m_data.ignoreAll  = NULL;
  535.     m_data.learn      = NULL;
  536.     m_data.stop       = NULL;
  537.     m_data.status  = NULL;
  538.     m_data.text    = NULL;
  539.     m_data.nuText  = NULL;
  540.     m_data.langTags  = NULL;
  541.     m_data.langCount = 0;
  542.     m_data.langIndx  = 0;
  543.     m_data.inList  = TRUE;
  544.     m_data.inCheck = FALSE;
  545.     m_data.isOk    = FALSE;
  546.     m_data.isDone  = FALSE;
  547. }
  548.  
  549. void 
  550. XFE_SpellHandler::UpdateGUI()
  551. {
  552.     char  *string = NULL;
  553.     XmString xstr = NULL;
  554.  
  555.     XmListDeleteAllItems(m_data.list);
  556.  
  557.     if (m_data.inCheck) {
  558.         // WARNING... [ don't nuke the text that you're going to use!! ]
  559.         //
  560.     }
  561.     else {
  562.         if (m_data.nuText) {
  563.             XP_FREE(m_data.nuText);
  564.             m_data.nuText  = NULL;
  565.         }
  566.     }
  567.  
  568.     if (m_data.isDone) {
  569.         string = XfeSubResourceGetStringValue(m_data.dialog,
  570.                                               "done", 
  571.                                               "Done",
  572.                                               XmNlabelString, 
  573.                                               XmCLabelString,
  574.                                               NULL);
  575.     }
  576.     else {
  577.         string = XfeSubResourceGetStringValue(m_data.dialog,
  578.                                               "replace",
  579.                                               "Replace",
  580.                                               XmNlabelString, 
  581.                                               XmCLabelString,
  582.                                               NULL);
  583.     }
  584.     xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
  585.     XtVaSetValues(m_data.replace, XmNlabelString, xstr, 0);
  586.     XmStringFree(xstr);
  587.  
  588.     xstr = NULL;
  589.  
  590.     if (m_data.xWord) {
  591.         int numAlts = 0;
  592.  
  593.         if (!m_data.isOk) {
  594.             numAlts = m_data.spell->GetNumAlternatives(m_data.xWord);
  595.             XmTextSetString(m_data.text, m_data.xWord);
  596.         }
  597.  
  598.         if (numAlts) {
  599.             char AltString[125];
  600.             char *tmp;
  601.             int i = 0;
  602.  
  603.             for (i=0;i<numAlts;i++) {
  604.                 m_data.spell->GetAlternative(i, AltString, 
  605.                                              sizeof(AltString));
  606.                 tmp = XP_STRDUP(AltString);
  607.                 xstr = XmStringCreateLtoR( tmp, XmSTRING_DEFAULT_CHARSET);
  608.                 XmListAddItem(m_data.list, xstr, 0);
  609.                 XmStringFree(xstr);
  610.                 XP_FREE(tmp);
  611.             }
  612.             XmListSelectPos(m_data.list, 1, True);
  613.  
  614.             string = XfeSubResourceGetStringValue(m_data.dialog,
  615.                                                   "msgUnRecognized", 
  616.                                                   "MsgUnRecognized",
  617.                                                   XmNlabelString, 
  618.                                                   XmCLabelString,
  619.                                                   NULL);
  620.  
  621.             xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
  622.             XtVaSetValues(m_data.status, XmNlabelString, xstr, 0);
  623.             XmStringFree(xstr);
  624.  
  625.             XtSetSensitive(m_data.text, True);
  626.             XtSetSensitive(m_data.list, True);
  627.             XtSetSensitive(m_data.replace, True);
  628.             XtSetSensitive(m_data.replaceAll, True);
  629.             XtSetSensitive(m_data.check, False);
  630.             XtSetSensitive(m_data.ignore, True);
  631.             XtSetSensitive(m_data.ignoreAll, True);
  632.             XtSetSensitive(m_data.learn, True);
  633.             XtSetSensitive(m_data.stop, True);
  634.  
  635.             XtVaSetValues(m_data.dialog,  XmNdefaultButton, m_data.replace, 0);
  636.             XtVaSetValues(m_data.ignore,  XmNshowAsDefault, False, 0);
  637.             XtVaSetValues(m_data.replace, XmNshowAsDefault, True, 0);
  638.             XmProcessTraversal(m_data.replace, XmTRAVERSE_CURRENT);
  639.         }
  640.         else {
  641.             if (m_data.isOk) {
  642.                 string = XfeSubResourceGetStringValue(m_data.dialog,
  643.                                                       "msgCorrect", 
  644.                                                       "MsgCorrect",
  645.                                                       XmNlabelString, 
  646.                                                       XmCLabelString,
  647.                                                       NULL);
  648.             }
  649.             else {
  650.                 string = XfeSubResourceGetStringValue(m_data.dialog,
  651.                                                       "msgNoSuggestions", 
  652.                                                       "MsgNoSuggestions",
  653.                                                       XmNlabelString, 
  654.                                                       XmCLabelString,
  655.                                                       NULL);
  656.             }
  657.  
  658.             xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
  659.             XtVaSetValues(m_data.status, XmNlabelString, xstr, 0);
  660.             XmStringFree(xstr);
  661.  
  662.             XtSetSensitive(m_data.text, True);
  663.             XtSetSensitive(m_data.list, False);
  664.             XtSetSensitive(m_data.replace, m_data.inCheck);
  665.             XtSetSensitive(m_data.replaceAll, m_data.inCheck);
  666.             XtSetSensitive(m_data.check, False);
  667.             XtSetSensitive(m_data.ignore, True);
  668.             XtSetSensitive(m_data.ignoreAll, True);
  669.             XtSetSensitive(m_data.learn, True);
  670.             XtSetSensitive(m_data.stop, True);
  671.  
  672.             if (m_data.inCheck) {
  673.                 XtVaSetValues(m_data.dialog, 
  674.                               XmNdefaultButton, m_data.replace, 0);
  675.                 XtVaSetValues(m_data.ignore,  XmNshowAsDefault, False, 0);
  676.                 XtVaSetValues(m_data.replace, XmNshowAsDefault, True, 0);
  677.                 XmProcessTraversal(m_data.replace, XmTRAVERSE_CURRENT);
  678.             }
  679.             else {
  680.                 XtVaSetValues(m_data.dialog, 
  681.                               XmNdefaultButton, m_data.ignore, 0);
  682.                 XtVaSetValues(m_data.replace, XmNshowAsDefault, False, 0);
  683.                 XtVaSetValues(m_data.ignore,  XmNshowAsDefault, True, 0);
  684.                 XmProcessTraversal(m_data.ignore, XmTRAVERSE_CURRENT);
  685.             }
  686.         }
  687.     }
  688.     else {
  689.         XtSetSensitive(m_data.text, False);
  690.         // WARNING... [ need to use resource string ]
  691.         //
  692.         XmTextSetString(m_data.text, "");
  693.  
  694.         string = XfeSubResourceGetStringValue(m_data.dialog,
  695.                                               "msgFinished", 
  696.                                               "MsgFinished",
  697.                                               XmNlabelString, 
  698.                                               XmCLabelString,
  699.                                               NULL);
  700.  
  701.         xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
  702.         XtVaSetValues(m_data.status, XmNlabelString, xstr, 0);
  703.         XmStringFree(xstr);
  704.  
  705.         XtSetSensitive(m_data.list, False);
  706.         XtSetSensitive(m_data.replace, True);
  707.         XtSetSensitive(m_data.replaceAll, False);
  708.         XtSetSensitive(m_data.check, False);
  709.         XtSetSensitive(m_data.ignore, False);
  710.         XtSetSensitive(m_data.ignoreAll, False);
  711.         XtSetSensitive(m_data.learn, False);
  712.         XtSetSensitive(m_data.stop, False);
  713.     }
  714.  
  715.     m_data.inList  = TRUE;
  716. }
  717.  
  718.  
  719. void
  720. XFE_SpellHandler::PopupDialog(MWContext* context, char* eWord)
  721. {
  722.     Widget   dialog;
  723.     Widget   label;
  724.     Widget   list;
  725.     Widget   status;
  726.     Widget   frame;
  727.     Widget   text;
  728.     Widget   form;
  729.     Widget   replace;
  730.     Widget   replaceAll;
  731.     Widget   check;
  732.     Widget   ignore;
  733.     Widget   ignoreAll;
  734.     Widget   learn;
  735.     Widget   stop;
  736.     Widget   right_rc;
  737.     Widget   left_rc;
  738.     Widget   space;
  739.     Widget   cframe;
  740.     Widget   combo;
  741.     Arg      args[20];
  742.     int      n;
  743.     int      rc_delta;
  744.     char*    string;
  745.     XmString xstr = NULL;
  746.     Dimension height;
  747.  
  748.     dialog = fe_CreatePromptDialog(context, "spellDialog",
  749.                                    FALSE, FALSE, FALSE, FALSE, TRUE);
  750.  
  751.     n = 0;
  752.     form = XmCreateForm(dialog, "form", args, n);
  753.     XtManageChild(form);
  754.  
  755.     n = 0;
  756.     XtSetArg(args [n], XmNbottomAttachment, XmATTACH_FORM); n++;
  757.     XtSetArg(args [n], XmNleftAttachment, XmATTACH_FORM); n++;
  758.     XtSetArg(args [n], XmNrightAttachment, XmATTACH_FORM); n++;
  759.     frame = XmCreateFrame(form, "frame", args, n);
  760.     XtManageChild(frame);
  761.  
  762.     n = 0;
  763.     XtSetArg(args [n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
  764.     status = XmCreateLabelGadget(frame, "status", args, n);
  765.     XtManageChild(status);
  766.  
  767.     string = XfeSubResourceGetStringValue(dialog,
  768.                                           "msgNull", 
  769.                                           "MsgNull",
  770.                                           XmNlabelString, 
  771.                                           XmCLabelString,
  772.                                           NULL);
  773.  
  774.     xstr = XmStringCreateLtoR( string, XmSTRING_DEFAULT_CHARSET);
  775.     XtVaSetValues(status, XmNlabelString, xstr, 0);
  776.     XmStringFree(xstr);
  777.  
  778.     n = 0;
  779.     XtSetArg(args [n], XmNrightAttachment, XmATTACH_FORM); n++;
  780.     XtSetArg(args [n], XmNtopAttachment, XmATTACH_FORM); n++;
  781.     XtSetArg(args [n], XmNorientation, XmVERTICAL); n++;
  782.     // SPacINg madness...
  783.     //
  784.     XtSetArg(args [n], XmNmarginWidth, 0); n++;
  785.     XtSetArg(args [n], XmNmarginHeight, 0); n++;
  786.     XtSetArg(args [n], XmNspacing, 0); n++;
  787.     right_rc = XmCreateRowColumn(form, "right_rc", args, n);
  788.     XtManageChild(right_rc);
  789.  
  790.     n = 0;
  791.     XtSetArg(args [n], XmNleftAttachment, XmATTACH_FORM); n++;
  792.     XtSetArg(args [n], XmNtopAttachment, XmATTACH_FORM); n++;
  793.     XtSetArg(args [n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  794.     XtSetArg(args [n], XmNrightWidget, right_rc); n++;
  795.     XtSetArg(args [n], XmNorientation, XmVERTICAL); n++;
  796.     //
  797.     // WARNING... [ these should go in the Resource file ]
  798.     //
  799.     XtSetArg(args [n], XmNrightOffset, 15); n++;
  800.     XtSetArg(args [n], XmNmarginWidth, 0); n++;
  801.     XtSetArg(args [n], XmNmarginHeight, 0); n++;
  802.     XtSetArg(args [n], XmNspacing, 0); n++;
  803.     left_rc = XmCreateRowColumn(form, "left_rc", args, n);
  804.     XtManageChild(left_rc);
  805.  
  806.     n = 0;
  807.     XtSetArg(args [n], XmNmarginWidth, 0); n++;
  808.     XtSetArg(args [n], XmNmarginHeight, 0); n++;
  809.     XtSetArg(args [n], XmNspacing, 0); n++;
  810.     XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
  811.     replace = XmCreatePushButtonGadget(right_rc, "replace", args, n);
  812.     XtManageChild(replace);
  813.  
  814.     n = 0;
  815.     XtSetArg(args [n], XmNmarginWidth, 0); n++;
  816.     XtSetArg(args [n], XmNmarginHeight, 0); n++;
  817.     XtSetArg(args [n], XmNspacing, 0); n++;
  818.     XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
  819.     replaceAll = XmCreatePushButtonGadget(right_rc, "replace_all", args, n);
  820.     XtManageChild(replaceAll);
  821.  
  822.     n = 0;
  823.     XtSetArg(args [n], XmNmarginWidth, 0); n++;
  824.     XtSetArg(args [n], XmNmarginHeight, 0); n++;
  825.     XtSetArg(args [n], XmNspacing, 0); n++;
  826.     XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
  827.     check = XmCreatePushButtonGadget(right_rc, "check", args, n);
  828.     XtManageChild(check);
  829.  
  830.     n = 0;
  831.     XtSetArg(args [n], XmNmarginWidth, 0); n++;
  832.     XtSetArg(args [n], XmNmarginHeight, 0); n++;
  833.     XtSetArg(args [n], XmNspacing, 0); n++;
  834.     XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
  835.     ignore = XmCreatePushButtonGadget(right_rc, "ignore", args, n);
  836.     XtManageChild(ignore);
  837.  
  838.     n = 0;
  839.     XtSetArg(args [n], XmNmarginWidth, 0); n++;
  840.     XtSetArg(args [n], XmNmarginHeight, 0); n++;
  841.     XtSetArg(args [n], XmNspacing, 0); n++;
  842.     XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
  843.     ignoreAll = XmCreatePushButtonGadget(right_rc, "ignore_all", args, n);
  844.     XtManageChild(ignoreAll);
  845.  
  846.     n = 0;
  847.     XtSetArg(args [n], XmNmarginWidth, 0); n++;
  848.     XtSetArg(args [n], XmNmarginHeight, 0); n++;
  849.     XtSetArg(args [n], XmNspacing, 0); n++;
  850.     XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
  851.     learn = XmCreatePushButtonGadget(right_rc, "learn", args, n);
  852.     XtManageChild(learn);
  853.  
  854.     n = 0;
  855.     XtSetArg(args [n], XmNmarginWidth, 0); n++;
  856.     XtSetArg(args [n], XmNmarginHeight, 0); n++;
  857.     XtSetArg(args [n], XmNspacing, 0); n++;
  858.     XtSetArg(args [n], XmNdefaultButtonShadowThickness, 1); n++;
  859.     stop = XmCreatePushButtonGadget(right_rc, "stop", args, n);
  860.     XtManageChild(stop);
  861.  
  862.     n = 0;
  863.     label = XmCreateLabelGadget(left_rc, "text_label", args, n);
  864.     XtManageChild(label);
  865.  
  866.     // WARNING... [ mAjOR layout hackery ]
  867.     //
  868.     XtVaGetValues(label, XmNheight, &height, 0);
  869.     rc_delta = (int)height - 5;
  870.     XtVaSetValues(right_rc, XmNtopOffset, rc_delta, 0);
  871.  
  872.     // WARNING... [ do I need to dup this? ]
  873.     //
  874.     string = eWord;
  875.  
  876.     n = 0;
  877.     XtSetArg(args [n], XmNvalue, string); n++;
  878.     XtSetArg(args [n], XmNeditable, True); n++;
  879.     XtSetArg(args [n], XmNcursorPositionVisible, True); n++;
  880.     text = fe_CreateTextField(left_rc, "errorText", args, n);
  881.     XtManageChild(text);
  882.  
  883.     n = 0;
  884.     label = XmCreateLabelGadget(left_rc, "list_label", args, n);
  885.     XtManageChild(label);
  886.  
  887.     n = 0;
  888.     XtSetArg(args [n], XmNvisibleItemCount, 10); n++;
  889.     list = XmCreateScrolledList(left_rc, "list", args, n);
  890.     XtManageChild(list);
  891.  
  892.     n = 0;
  893.     XtSetArg(args [n], XmNseparatorType, XmNO_LINE); n++;
  894.     XtSetArg(args [n], XmNheight, 4); n++;
  895.     space = XmCreateSeparatorGadget(left_rc, "space", args, n);
  896.     XtManageChild(space);
  897.  
  898.     n = 0;
  899.     XtSetArg(args [n], XmNshadowType, XmSHADOW_IN); n++;
  900.     XtSetArg(args [n], XmNshadowThickness, 1); n++;
  901.     cframe = XmCreateFrame(left_rc, "combo_frame", args, n);
  902.     XtManageChild(cframe);
  903.  
  904.     Visual*  v = 0;
  905.     Colormap cmap = 0;
  906.     Cardinal depth = 0;
  907.     XtVaGetValues(XfeAncestorFindTopLevelShell(form),
  908.                   XtNvisual, &v,
  909.                   XtNcolormap, &cmap,
  910.                   XtNdepth, &depth,
  911.                   0);
  912.  
  913.     n = 0;
  914.     XtSetArg(args [n], XmNvisual, v); n++;
  915.     XtSetArg(args [n], XmNdepth, depth); n++;
  916.     XtSetArg(args [n], XmNcolormap, cmap); n++;
  917.     XtSetArg(args [n], XmNtype, XmDROP_DOWN_LIST_BOX); n++;
  918.     XtSetArg(args [n], XmNshadowThickness, 1); n++;
  919.     XtSetArg(args [n], XmNarrowType, XmMOTIF); n++;
  920.     combo = DtCreateComboBox(cframe, "comboBox", args, n);
  921.     XtManageChild(combo);
  922.  
  923.     XtVaSetValues(left_rc, 
  924.                   XmNbottomAttachment, XmATTACH_WIDGET, 
  925.                   XmNbottomWidget,     frame,
  926.                   XmNbottomOffset,     6, 
  927.                   0);
  928.  
  929.     XtVaSetValues(right_rc, 
  930.                   XmNbottomAttachment, XmATTACH_WIDGET, 
  931.                   XmNbottomWidget,     frame,
  932.                   XmNbottomOffset,     6, 
  933.                   0);
  934.  
  935.     m_data.dialog  = dialog;
  936.     m_data.list    = list;
  937.     m_data.combo   = combo;
  938.     m_data.replace = replace;
  939.     m_data.replaceAll = replaceAll;
  940.     m_data.check      = check;
  941.     m_data.ignore     = ignore;
  942.     m_data.ignoreAll  = ignoreAll;
  943.     m_data.learn      = learn;
  944.     m_data.stop       = stop;
  945.     m_data.status  = status;
  946.     m_data.text    = text;
  947.  
  948.     XtVaSetValues(dialog, XmNdefaultButton, replace, 0);
  949.     XtVaSetValues(dialog, XmNinitialFocus, list, 0);
  950.  
  951.     // XtAddCallback(dialog, XmNcancelCallback, fe_open_url_cb, data);
  952.     // XtAddCallback(dialog, XmNapplyCallback, fe_clear_text_cb, text);
  953.  
  954.     XtAddCallback(text, 
  955.                   XmNvalueChangedCallback, xfe_spell_text_cb, &m_data);
  956.     XtAddCallback(text, 
  957.                   XmNfocusCallback, xfe_spell_focus_in_cb, &m_data);
  958.     XtAddCallback(text, 
  959.                   XmNlosingFocusCallback, xfe_spell_focus_out_cb, &m_data);
  960.     XtAddCallback(list, 
  961.                   XmNbrowseSelectionCallback, xfe_spell_list_cb, &m_data);
  962.     XtAddCallback(combo, 
  963.                   XmNselectionCallback, xfe_spell_combo_cb, &m_data);
  964.  
  965.     XtAddCallback(replace, XmNactivateCallback, 
  966.                   xfe_spell_doit_cb, &m_tags[XSP_REPLACE]);
  967.  
  968.     XtAddCallback(replaceAll, XmNactivateCallback, 
  969.                   xfe_spell_doit_cb, &m_tags[XSP_REPLACEALL]);
  970.  
  971.     XtAddCallback(check, XmNactivateCallback, 
  972.                   xfe_spell_doit_cb, &m_tags[XSP_CHECK]);
  973.  
  974.     XtAddCallback(ignore, XmNactivateCallback, 
  975.                   xfe_spell_doit_cb, &m_tags[XSP_IGNORE]);
  976.  
  977.     XtAddCallback(ignoreAll, XmNactivateCallback, 
  978.                   xfe_spell_doit_cb, &m_tags[XSP_IGNOREALL]);
  979.  
  980.     XtAddCallback(learn, XmNactivateCallback, 
  981.                   xfe_spell_doit_cb, &m_tags[XSP_LEARN]);
  982.  
  983.     XtAddCallback(stop, XmNactivateCallback, 
  984.                   xfe_spell_doit_cb, &m_tags[XSP_STOP]);
  985.  
  986.  
  987.     XtAddCallback(dialog, 
  988.                   XmNdestroyCallback, xfe_spell_destroy_cb, &m_data);
  989.     
  990.     // NOTE:  load the combo box...
  991.     //
  992.     initLanguageList();
  993.  
  994.     fe_NukeBackingStore (dialog);
  995.  
  996.     XtManageChild (dialog);
  997. }
  998.  
  999. void 
  1000. XFE_SpellHandler::initLanguageList()
  1001. {
  1002.     int       Language;
  1003.     int       Dialect;
  1004.     int       i;
  1005.     char     *string;
  1006.     XmString  xm_string;
  1007.     int       count = m_data.spell->GetNumOfDictionaries();
  1008.  
  1009.     
  1010.     m_data.langCount = count;
  1011.     m_data.langTags = (xfe_lang_tag *) XP_CALLOC(count, sizeof(xfe_lang_tag));
  1012.  
  1013.     for (i = 0; i < count; i++)
  1014.     {
  1015.         if (m_data.spell->GetDictionaryLanguage(i, Language, Dialect) == 0)
  1016.         {
  1017.             string = getLanguageString(Language, Dialect);
  1018.  
  1019.             xm_string = XmStringCreateLocalized(string);
  1020.             DtComboBoxAddItem(m_data.combo, xm_string, i + 1, FALSE);
  1021.             XmStringFree(xm_string);
  1022.         }
  1023.         else {
  1024.             Language = 0;
  1025.             Dialect = 0;
  1026.  
  1027.             xm_string = XmStringCreateLocalized("");
  1028.             DtComboBoxAddItem(m_data.combo, xm_string, i + 1, FALSE);
  1029.             XmStringFree(xm_string);
  1030.         }
  1031.         m_data.langTags[i].language = Language;
  1032.         m_data.langTags[i].dialect = Dialect;
  1033.     }
  1034.     XtVaSetValues(m_data.combo, XmNvisibleItemCount, (XtPointer)i, 0);
  1035.  
  1036.     // Select the current default
  1037.     //
  1038.     m_data.spell->GetCurrentLanguage(Language, Dialect);
  1039.  
  1040.     if (Language == 0 && Dialect == 0) {
  1041.         updateLang(-1);
  1042.     }
  1043.     else {
  1044.         for (i = 0; i < count; i++)
  1045.         {
  1046.             if (m_data.langTags[i].language == Language &&
  1047.                 m_data.langTags[i].dialect == Dialect)
  1048.             {
  1049.                 updateLang(i);
  1050.                 break;
  1051.             }
  1052.         }
  1053.     }
  1054. }
  1055.  
  1056. void
  1057. XFE_SpellHandler::updateLang(int indx)
  1058. {
  1059.    if (indx < 0) {
  1060.        m_data.langIndx = indx;
  1061.  
  1062.        XmString blank = XmStringCreateLocalized("");
  1063.        XtVaSetValues(m_data.combo,
  1064.                      XmNupdateLabel, False,
  1065.                      XmNlabelString, blank,
  1066.                      0);
  1067.        XmStringFree(blank);
  1068.    } else {
  1069.        m_data.langIndx = indx;
  1070.  
  1071.        XtVaSetValues(m_data.combo,
  1072.                      XmNupdateLabel, True,
  1073.                      XmNselectedPosition, indx,
  1074.                      0);
  1075.    }
  1076. }
  1077.  
  1078. char *
  1079. XFE_SpellHandler::getLanguageString(int lang, int dialect)
  1080. {
  1081.     char *string;
  1082.  
  1083.     switch (lang)
  1084.     {
  1085.     case L_CZECH:
  1086.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1087.                                               "langCzech", 
  1088.                                               "LangCzech",
  1089.                                               XmNlabelString, 
  1090.                                               XmCLabelString,
  1091.                                               NULL);
  1092.         break;
  1093.     case L_RUSSIAN:
  1094.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1095.                                               "langRussian", 
  1096.                                               "LangRussian",
  1097.                                               XmNlabelString, 
  1098.                                               XmCLabelString,
  1099.                                               NULL);
  1100.         break;
  1101.     case L_CATALAN:
  1102.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1103.                                               "langCatalan", 
  1104.                                               "LangCatalan",
  1105.                                               XmNlabelString, 
  1106.                                               XmCLabelString,
  1107.                                               NULL);
  1108.         break;
  1109.     case L_HUNGARIAN:
  1110.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1111.                                               "langHungarian", 
  1112.                                               "LangHungarian",
  1113.                                               XmNlabelString, 
  1114.                                               XmCLabelString,
  1115.                                               NULL);
  1116.         break;
  1117.     case L_FRENCH:
  1118.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1119.                                               "langFrench", 
  1120.                                               "LangFrench",
  1121.                                               XmNlabelString, 
  1122.                                               XmCLabelString,
  1123.                                               NULL);
  1124.         break;
  1125.     case L_GERMAN:
  1126.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1127.                                               "langGerman", 
  1128.                                               "LangGerman",
  1129.                                               XmNlabelString, 
  1130.                                               XmCLabelString,
  1131.                                               NULL);
  1132.         break;
  1133.     case L_SWEDISH:
  1134.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1135.                                               "langSwedish", 
  1136.                                               "LangSwedish",
  1137.                                               XmNlabelString, 
  1138.                                               XmCLabelString,
  1139.                                               NULL);
  1140.         break;
  1141.     case L_SPANISH:
  1142.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1143.                                               "langSpanish", 
  1144.                                               "LangSpanish",
  1145.                                               XmNlabelString, 
  1146.                                               XmCLabelString,
  1147.                                               NULL);
  1148.         break;
  1149.     case L_ITALIAN:
  1150.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1151.                                               "langItalian", 
  1152.                                               "LangItalian",
  1153.                                               XmNlabelString, 
  1154.                                               XmCLabelString,
  1155.                                               NULL);
  1156.         break;
  1157.     case L_DANISH:
  1158.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1159.                                               "langDanish", 
  1160.                                               "LangDanish",
  1161.                                               XmNlabelString, 
  1162.                                               XmCLabelString,
  1163.                                               NULL);
  1164.         break;
  1165.     case L_DUTCH:
  1166.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1167.                                               "langDutch", 
  1168.                                               "LangDutch",
  1169.                                               XmNlabelString, 
  1170.                                               XmCLabelString,
  1171.                                               NULL);
  1172.         break;
  1173.  
  1174.     case L_PORTUGUESE:  
  1175.         if (dialect == D_BRAZILIAN)
  1176.             string = XfeSubResourceGetStringValue(m_data.dialog,
  1177.                                                   "langPortugueseBrazilian", 
  1178.                                                   "LangPortugueseBrazilian",
  1179.                                                   XmNlabelString, 
  1180.                                                   XmCLabelString,
  1181.                                                   NULL);
  1182.         else if (dialect == D_EUROPEAN)
  1183.             string = XfeSubResourceGetStringValue(m_data.dialog,
  1184.                                                   "langPortugueseEuropean", 
  1185.                                                   "LangPortugueseEuropean",
  1186.                                                   XmNlabelString, 
  1187.                                                   XmCLabelString,
  1188.                                                   NULL);
  1189.         else
  1190.             string = XfeSubResourceGetStringValue(m_data.dialog,
  1191.                                                   "langPortuguese", 
  1192.                                                   "LangPortuguese",
  1193.                                                   XmNlabelString, 
  1194.                                                   XmCLabelString,
  1195.                                                   NULL);
  1196.         break;
  1197.  
  1198.     case L_NORWEGIAN:   
  1199.         if (dialect == D_BOKMAL)
  1200.             string = XfeSubResourceGetStringValue(m_data.dialog,
  1201.                                                   "langNorwegianBokmal", 
  1202.                                                   "LangNorwegianBokmal",
  1203.                                                   XmNlabelString, 
  1204.                                                   XmCLabelString,
  1205.                                                   NULL);
  1206.         else if (dialect == D_NYNORSK)
  1207.             string = XfeSubResourceGetStringValue(m_data.dialog,
  1208.                                                   "langNorwegianNynorsk",
  1209.                                                   "LangNorwegianNynorsk",
  1210.                                                   XmNlabelString, 
  1211.                                                   XmCLabelString,
  1212.                                                   NULL);
  1213.         else
  1214.             string = XfeSubResourceGetStringValue(m_data.dialog,
  1215.                                                   "langNorwegian",
  1216.                                                   "LangNorwegian",
  1217.                                                   XmNlabelString, 
  1218.                                                   XmCLabelString,
  1219.                                                   NULL);
  1220.         break;
  1221.  
  1222.     case L_FINNISH:     
  1223.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1224.                                               "langFinnish",
  1225.                                               "LangFinnish",
  1226.                                               XmNlabelString, 
  1227.                                               XmCLabelString,
  1228.                                               NULL);
  1229.         break;
  1230.     case L_GREEK:       
  1231.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1232.                                               "langGreek",
  1233.                                               "LangGreek",
  1234.                                               XmNlabelString, 
  1235.                                               XmCLabelString,
  1236.                                               NULL);
  1237.         break;
  1238.  
  1239.     case L_ENGLISH:     
  1240.         if (dialect == D_US_ENGLISH)
  1241.             string = XfeSubResourceGetStringValue(m_data.dialog,
  1242.                                                   "langEnglishUS",
  1243.                                                   "LangEnglishUS",
  1244.                                                   XmNlabelString, 
  1245.                                                   XmCLabelString,
  1246.                                                   NULL);
  1247.         else if (dialect == D_UK_ENGLISH)
  1248.             string = XfeSubResourceGetStringValue(m_data.dialog,
  1249.                                                   "langEnglishUK",
  1250.                                                   "LangEnglishUK",
  1251.                                                   XmNlabelString, 
  1252.                                                   XmCLabelString,
  1253.                                                   NULL);
  1254.         else
  1255.             string = XfeSubResourceGetStringValue(m_data.dialog,
  1256.                                                   "langEnglish",
  1257.                                                   "LangEnglish",
  1258.                                                   XmNlabelString, 
  1259.                                                   XmCLabelString,
  1260.                                                   NULL);
  1261.         break;
  1262.  
  1263.     case L_AFRIKAANS:
  1264.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1265.                                               "langAfrikaans",
  1266.                                               "LangAfrikaans",
  1267.                                               XmNlabelString, 
  1268.                                               XmCLabelString,
  1269.                                               NULL);
  1270.         break;
  1271.     case L_POLISH:
  1272.         string = XfeSubResourceGetStringValue(m_data.dialog,
  1273.                                               "langPolish",
  1274.                                               "LangPolish",
  1275.                                               XmNlabelString, 
  1276.                                               XmCLabelString,
  1277.                                               NULL);
  1278.         break;
  1279.  
  1280.     default:
  1281.         string = "";
  1282.         break;
  1283.     }
  1284.  
  1285.     return string;
  1286. }
  1287.  
  1288. XP_Bool
  1289. XFE_SpellHandler::ProcessDocument(MWContext* context, XP_Bool isHtml)
  1290. {
  1291.     initSpellChecker();
  1292.  
  1293.     if (m_data.spell == NULL)
  1294.         return FALSE;
  1295.  
  1296.     if (m_data.interface == NULL) {
  1297.         if (isHtml) {
  1298.             m_data.interface = new XFE_HtmlSpellCheck(m_data.spell, context);
  1299.         }
  1300.         else {
  1301.             m_data.interface = new XFE_TextSpellCheck(m_data.spell, context);
  1302.         }
  1303.     }
  1304.  
  1305.     m_data.inCheck = FALSE;
  1306.     m_data.isOk    = FALSE;
  1307.     m_data.isDone  = FALSE;
  1308.  
  1309.     XP_Bool oops = m_data.interface->ProcessDocument(&m_tags[XSP_NULL]);
  1310.  
  1311.     PopupDialog(context, m_data.xWord);
  1312.     UpdateGUI();
  1313.  
  1314.     return oops;
  1315. }
  1316.  
  1317. XP_Bool
  1318. XFE_SpellHandler::ReprocessDocument()
  1319. {
  1320.     m_data.interface->ProcessError(&m_tags[XSP_STOP]);
  1321.  
  1322.     nukeSpellChecker();
  1323.     initSpellChecker();
  1324.  
  1325.     m_data.inCheck = FALSE;
  1326.     m_data.isOk    = FALSE;
  1327.     m_data.isDone  = FALSE;
  1328.  
  1329.     XP_Bool oops = m_data.interface->ProcessDocument(&m_tags[XSP_NULL]);
  1330.  
  1331.     UpdateGUI();
  1332.  
  1333.     return oops;
  1334. }
  1335.  
  1336. XP_Bool
  1337. XFE_SpellHandler::ProcessError(xfe_spell_tag *tag)
  1338. {
  1339.     int              action  = tag->action;
  1340.     xfe_spell_data  *data    = tag->data;
  1341.     ISpellChecker   *spell   = data->spell;
  1342.  
  1343.     data->inCheck = FALSE;
  1344.     data->isOk    = FALSE;
  1345.  
  1346.     switch (action) {
  1347.     case XSP_STOP:
  1348.         // call this to cleanup before nuking the dialog...
  1349.         (data->interface)->ProcessError(tag);
  1350.         (data->interface)->resetVars();
  1351.     case XSP_REPLACE:
  1352.         if (data->isDone) {
  1353.             XtUnmanageChild(data->dialog);
  1354.             //
  1355.             // Nuke it...
  1356.             //
  1357.             XtDestroyWidget(data->dialog);
  1358.  
  1359.             return FALSE;
  1360.         }
  1361.         break;
  1362.     case XSP_CHECK:
  1363.         data->inCheck = TRUE;
  1364.  
  1365.         if (spell->CheckWord(data->nuText)) {
  1366.             data->isOk = TRUE;
  1367.         } 
  1368.         data->xWord = data->nuText;
  1369.  
  1370.         return TRUE;
  1371.     default:
  1372.         break;
  1373.     }
  1374.  
  1375.     return (data->interface)->ProcessError(tag);
  1376. }
  1377.  
  1378.  
  1379. // -------------------------------------------------------------[ SpellCheck ]
  1380.  
  1381.  
  1382. XFE_SpellCheck::XFE_SpellCheck(ISpellChecker *spell, MWContext* context)
  1383. {
  1384.     m_spellChecker     = spell;
  1385.  
  1386.     m_bufferSize       = 0;
  1387.     m_xpDelta          = 0;
  1388.     m_contextData      = context;
  1389.     m_misspelledWord   = NULL;
  1390.     m_selStart         = 0;
  1391.     m_selEnd           = 0;
  1392. }
  1393.  
  1394. XFE_SpellCheck::~XFE_SpellCheck()
  1395. {
  1396.     m_spellChecker     = NULL;
  1397. }
  1398.  
  1399. void
  1400. XFE_SpellCheck::resetVars()
  1401. {
  1402.     m_bufferSize       = 0;
  1403.     m_xpDelta          = 0;
  1404.     m_selStart         = 0;
  1405.     m_selEnd           = 0;
  1406. }
  1407.  
  1408. XP_Bool
  1409. XFE_SpellCheck::ProcessError(xfe_spell_tag* tag)
  1410. {
  1411.     int              action  = tag->action;
  1412.     xfe_spell_data  *data    = tag->data;
  1413.     char            *usrText = data->nuText;
  1414.     char            *tmp     = NULL;
  1415.  
  1416.     if (m_misspelledWord) {
  1417.         switch (action) {
  1418.         case XSP_REPLACE:
  1419.             ReplaceHilitedText(usrText, FALSE);
  1420.             break;
  1421.         case XSP_REPLACEALL:
  1422.             ReplaceHilitedText(usrText, TRUE);
  1423.             break;
  1424.         case XSP_IGNORE:
  1425.             IgnoreHilitedText(FALSE);
  1426.             break;
  1427.         case XSP_IGNOREALL:
  1428.             IgnoreHilitedText(TRUE);
  1429.             break;
  1430.         case XSP_LEARN:
  1431.             tmp = XmTextFieldGetString(data->text);
  1432.  
  1433.             if (tmp) {
  1434.                 m_spellChecker->AddWordToPersonalDictionary(tmp);
  1435.  
  1436.                 if (XP_STRCMP( m_misspelledWord, tmp) == 0) {
  1437.                     IgnoreHilitedText(TRUE);
  1438.                 }
  1439.                 else {
  1440.                     ReplaceHilitedText(tmp, TRUE);
  1441.                 }
  1442.  
  1443.                 XtFree(tmp);
  1444.             }
  1445.             break;
  1446.         case XSP_STOP:
  1447.             m_misspelledWord = NULL;
  1448.             data->xWord  = NULL;
  1449.             data->isDone = TRUE;
  1450.  
  1451.             RemoveAllErrorHilites();
  1452.             return FALSE;
  1453.         default:
  1454.             break;
  1455.         }
  1456.         m_misspelledWord = GetNextError();
  1457.     }
  1458.     else {
  1459.         m_misspelledWord = GetFirstError();
  1460.     }
  1461.  
  1462.     if (!m_misspelledWord) {
  1463.         m_misspelledWord = NULL;
  1464.         data->xWord  = NULL;
  1465.         data->isDone = TRUE;
  1466.         
  1467.         RemoveAllErrorHilites();
  1468.         return FALSE;
  1469.     }
  1470.     else {
  1471.         data->xWord = m_misspelledWord;
  1472.         return TRUE;
  1473.     }
  1474. }
  1475.  
  1476. XP_Bool
  1477. XFE_SpellCheck::ProcessDocument(xfe_spell_tag* tag)
  1478. {
  1479.     xfe_spell_data  *data    = tag->data;
  1480.     ISpellChecker   *spell   = data->spell;
  1481.     
  1482.     // NOTE: important to make sure that we are in sync with the Handler...
  1483.     //
  1484.     if (m_spellChecker != spell) {
  1485.         m_spellChecker = spell;
  1486.     }
  1487.  
  1488.     // Get the text buffer from the document
  1489.     XP_HUGE_CHAR_PTR pBuf = GetBuffer();
  1490.  
  1491.     if (pBuf == NULL)
  1492.         return 0;                       // nothing to spell check
  1493.  
  1494.     // If we were spell checking a selection in the previous pass,
  1495.     // adjust the selection for any corrections made in the last pass.
  1496.     //
  1497.     if (m_selEnd > 0) {
  1498.         m_selEnd += (XP_STRLEN(pBuf) - (m_bufferSize - m_xpDelta));
  1499.     }
  1500.     else {
  1501.         GetSelection(m_selStart, m_selEnd);
  1502.     }
  1503.  
  1504.     // pass text buffer to the spell checker
  1505.     int retcode = m_spellChecker->SetBuf(pBuf, m_selStart, m_selEnd);
  1506.  
  1507.     m_bufferSize = (int) m_spellChecker->GetBufSize();
  1508.     m_xpDelta    = m_bufferSize - XP_STRLEN(pBuf);
  1509.  
  1510.     // release the buffer (the Spell Checker makes a local copy)
  1511.     XP_HUGE_FREE(pBuf);         
  1512.  
  1513.     // WARNING... [ marking all misspelled words ]
  1514.     //
  1515.     return ProcessError(tag);
  1516. }
  1517.  
  1518. // ---------------------------------------------------------[ HtmlSpellCheck ]
  1519.  
  1520. XFE_HtmlSpellCheck::XFE_HtmlSpellCheck(ISpellChecker *spell, 
  1521.                                        MWContext *context)
  1522.   : XFE_SpellCheck(spell, context)
  1523. {
  1524. }
  1525.  
  1526. XFE_HtmlSpellCheck::~XFE_HtmlSpellCheck()
  1527. {
  1528. }
  1529.  
  1530. char *
  1531. XFE_HtmlSpellCheck::GetBuffer()
  1532. {
  1533.     return EDT_GetPositionalText(m_contextData);    
  1534. }
  1535.  
  1536. void 
  1537. XFE_HtmlSpellCheck::IgnoreHilitedText(int AllInstances)
  1538. {
  1539.     char *pOldWord = (char *)LO_GetSelectionText(m_contextData);
  1540.  
  1541.     if (pOldWord != NULL)
  1542.     {
  1543.         EDT_IgnoreMisspelledWord(m_contextData, pOldWord, AllInstances);
  1544.         XP_FREE(pOldWord);
  1545.     }
  1546. }
  1547.  
  1548. void 
  1549. XFE_HtmlSpellCheck::RemoveAllErrorHilites()
  1550. {
  1551.     //    EDT_BeginOfDocument(m_contextData, FALSE);
  1552.     //    EDT_SetRefresh(m_contextData, TRUE);
  1553.  
  1554.     // ignore any unprocessed misspelled words 
  1555.     EDT_IgnoreMisspelledWord(m_contextData, NULL, TRUE);
  1556. }
  1557.  
  1558. char *
  1559. XFE_HtmlSpellCheck::GetFirstError()
  1560. {
  1561.     // turn off refreshing and spell check the text.
  1562.     EDT_SetRefresh(m_contextData, FALSE);
  1563.  
  1564.     // underline the misspelled words
  1565.     EDT_CharacterData* pCharData = EDT_NewCharacterData();
  1566.     pCharData->mask = TF_SPELL;
  1567.     pCharData->values = TF_SPELL;
  1568.  
  1569.     unsigned long Offset, Len;
  1570.     while (m_spellChecker->GetNextMisspelledWord(Offset, Len) == 0)
  1571.         EDT_SetCharacterDataAtOffset(m_contextData, pCharData, Offset, Len);
  1572.   
  1573.     XP_FREE(pCharData);
  1574.  
  1575.     // set sursor position at the beginning of document so that 
  1576.     // EDT_SelectNextMisspelledWord() to start at the beginning.
  1577.     EDT_BeginOfDocument(m_contextData, FALSE);
  1578.     EDT_SetRefresh(m_contextData, TRUE);
  1579.  
  1580.     // m_pView->UpdateWindow();
  1581.     fe_EditorRefresh(m_contextData);
  1582.  
  1583.     // Select and return the first mispelled word 
  1584.     if (EDT_SelectFirstMisspelledWord(m_contextData))
  1585.         return (char *)LO_GetSelectionText(m_contextData);
  1586.     else
  1587.         return NULL;
  1588. }
  1589.  
  1590. char *
  1591. XFE_HtmlSpellCheck::GetNextError()
  1592. {
  1593.     if (EDT_SelectNextMisspelledWord(m_contextData))
  1594.         return (char *)LO_GetSelectionText(m_contextData);
  1595.     else
  1596.         return 0;
  1597. }
  1598.  
  1599. XP_Bool
  1600. XFE_HtmlSpellCheck::GetSelection(int32 &SelStart, int32 &SelEnd)
  1601. {
  1602.     char *pSelection;
  1603.    
  1604.     if ((pSelection = (char *)LO_GetSelectionText(m_contextData)) != NULL)
  1605.     {
  1606.         XP_FREE(pSelection);
  1607.         EDT_GetSelectionOffsets(m_contextData, &SelStart, &SelEnd);
  1608.         return TRUE;
  1609.     }
  1610.     else
  1611.         return FALSE;       // no selection
  1612. }
  1613.  
  1614. void
  1615. XFE_HtmlSpellCheck::ReplaceHilitedText(const char *NewText, 
  1616.                                        XP_Bool AllInstances)
  1617. {
  1618.     char *pOldWord = (char *)LO_GetSelectionText(m_contextData);
  1619.  
  1620.     if (pOldWord != NULL)
  1621.     {
  1622.         EDT_ReplaceMisspelledWord(m_contextData, 
  1623.                                   pOldWord, (char*)NewText, AllInstances);
  1624.         XP_FREE(pOldWord);
  1625.     }
  1626.     else {
  1627. #ifdef DEBUG_spellcheck
  1628.         fprintf(stderr, "WARNING... [ unable to fetch pOldWord ]\n");
  1629. #endif        
  1630.     }
  1631. }
  1632.  
  1633.  
  1634.  
  1635. // --------------------------------------------------------[ TextSpellCheck ]
  1636.  
  1637. XFE_TextSpellCheck::XFE_TextSpellCheck(ISpellChecker *spell,
  1638.                                        MWContext *context)
  1639.   : XFE_SpellCheck(spell, context)
  1640. {
  1641.     m_textWidget = CONTEXT_DATA(m_contextData)->mcBodyText;
  1642.     m_dirty = FALSE;
  1643.     m_offset = 0;
  1644.     m_len = 0;
  1645. }
  1646.  
  1647. XFE_TextSpellCheck::~XFE_TextSpellCheck()
  1648. {
  1649.     m_textWidget = NULL;
  1650. }
  1651.  
  1652. char *
  1653. XFE_TextSpellCheck::GetBuffer()
  1654. {
  1655.     return XmTextGetString(m_textWidget);
  1656. }
  1657.  
  1658. void  
  1659. XFE_TextSpellCheck::IgnoreHilitedText(int AllInstances)
  1660. {
  1661.     if (m_selEnd > 0) {
  1662.         XmTextSetHighlight(m_textWidget, 
  1663.                            m_offset, (m_offset + m_len),
  1664.                            XmHIGHLIGHT_SECONDARY_SELECTED
  1665.                            );
  1666.     }
  1667.     else {
  1668.         XmTextSetHighlight(m_textWidget, 
  1669.                            m_offset, (m_offset + m_len),
  1670.                            XmHIGHLIGHT_NORMAL 
  1671.                            );
  1672.     }
  1673.  
  1674.     if (AllInstances) {
  1675.         m_spellChecker->IgnoreWord(m_misspelledWord);
  1676.     }
  1677. }
  1678.  
  1679. void  
  1680. XFE_TextSpellCheck::RemoveAllErrorHilites()
  1681. {
  1682.     if (m_selEnd > 0 && !m_dirty) {
  1683.         Time time = XtLastTimestampProcessed(XtDisplay(m_textWidget));
  1684.  
  1685.         // Nuke the selection if it still exists after the spell check...
  1686.         //
  1687.         XmTextClearSelection(m_textWidget, time);
  1688.  
  1689.         //        XmTextSetHighlight(m_textWidget, 
  1690.         //                           m_selStart, m_selEnd, 
  1691.         //                           XmHIGHLIGHT_SELECTED
  1692.         //                           );
  1693.     }
  1694.     else {
  1695.         XmTextSetHighlight(m_textWidget, 
  1696.                            0, (m_bufferSize - 1), 
  1697.                            XmHIGHLIGHT_NORMAL
  1698.                            );
  1699.     }
  1700. }
  1701.  
  1702. char *
  1703. XFE_TextSpellCheck::GetFirstError()
  1704. {
  1705.     if (m_selEnd > m_selStart) {
  1706.         XmTextSetHighlight(m_textWidget, 
  1707.                            m_selStart, m_selEnd, 
  1708.                            XmHIGHLIGHT_SECONDARY_SELECTED
  1709.                            );
  1710.     }
  1711.  
  1712.     return GetNextError();
  1713. }
  1714.  
  1715. char *
  1716. XFE_TextSpellCheck::GetNextError()
  1717. {
  1718.     unsigned long Offset, Len;
  1719.     char *pMisspelledWord = NULL;
  1720.  
  1721.     if (m_spellChecker->GetNextMisspelledWord(Offset, Len) == 0)
  1722.     {
  1723.         m_offset = (int) Offset;
  1724.         m_len = (int) Len;
  1725.         // hilight mispelled word
  1726.         XmTextSetHighlight(m_textWidget, 
  1727.                            m_offset, (m_offset + m_len),
  1728.                            XmHIGHLIGHT_SELECTED 
  1729.                            );
  1730.  
  1731.         // Extract mispelled word 
  1732.         XP_HUGE_CHAR_PTR pBuf = GetBuffer();
  1733.         if (pBuf != NULL)
  1734.         {
  1735.             pMisspelledWord = (char *)XP_ALLOC(Len + 1);
  1736.             if (pMisspelledWord != NULL)
  1737.                 XP_STRNCPY_SAFE(pMisspelledWord, pBuf + Offset, Len+1);
  1738.  
  1739.             XP_HUGE_FREE(pBuf);
  1740.         }
  1741.     }
  1742.     else {
  1743.         m_offset = 0;
  1744.         m_len = 0;
  1745.     }
  1746.  
  1747.     return pMisspelledWord;
  1748. }
  1749.  
  1750. XP_Bool
  1751. XFE_TextSpellCheck::GetSelection(int32 &SelStart, int32 &SelEnd)
  1752. {
  1753.     XmTextPosition xRight;
  1754.     XmTextPosition xLeft;
  1755.  
  1756.     XmTextGetSelectionPosition(m_textWidget, &xRight, &xLeft);
  1757.  
  1758.     if (xLeft > xRight)
  1759.     {
  1760.         SelStart = (int) xRight;
  1761.         SelEnd = (int) xLeft;
  1762.  
  1763.         XmTextSetHighlight(m_textWidget, 
  1764.                            SelStart, SelEnd, 
  1765.                            XmHIGHLIGHT_SECONDARY_SELECTED
  1766.                            );
  1767.         return TRUE;
  1768.     }
  1769.     else {
  1770.         SelStart = 0;
  1771.         SelEnd = 0;
  1772.  
  1773.         return FALSE;
  1774.     }
  1775. }
  1776.  
  1777. void
  1778. XFE_TextSpellCheck::ReplaceHilitedText(const char *NewText, 
  1779.                                        XP_Bool AllInstances)
  1780. {
  1781.     if (m_spellChecker->ReplaceMisspelledWord(NewText, AllInstances) != 0) {
  1782. #ifdef DEBUG_spellcheck
  1783.         fprintf(stderr, "WARNING... [ ReplaceMisspelledWord failed ]\n");
  1784. #endif
  1785.     }
  1786.  
  1787.     unsigned long NewBufSize = m_spellChecker->GetBufSize();
  1788.     char *pNewBuf = (char *)XP_ALLOC(NewBufSize);
  1789.  
  1790.     if (pNewBuf == NULL) {
  1791. #ifdef DEBUG_spellcheck
  1792.         fprintf(stderr, "WARNING... [ unable to alloc pNewBuf ]\n");
  1793. #endif
  1794.         return;
  1795.     }
  1796.  
  1797.     int delta = NewBufSize - m_bufferSize;
  1798.     int nuEnd = 0;
  1799.  
  1800.     if (m_selEnd > 0) {
  1801.         nuEnd = m_selEnd + delta;
  1802.  
  1803.         if (nuEnd < m_selEnd) {
  1804.             // NOTE: we have to fix up the end of the the selection marker...
  1805.             //
  1806.             XmTextSetHighlight(m_textWidget, 
  1807.                                m_selStart, m_selEnd, 
  1808.                                XmHIGHLIGHT_NORMAL
  1809.                                );
  1810.         }
  1811.     }
  1812.  
  1813.     m_spellChecker->GetBuf(pNewBuf, NewBufSize);
  1814.     XmTextSetString(m_textWidget, pNewBuf);
  1815.  
  1816.     // NOTE: this denotes the lose of the "selection" in the text widget...
  1817.     //
  1818.     m_dirty = True;
  1819.  
  1820.     m_bufferSize = (int)NewBufSize;
  1821.  
  1822.     if (m_selEnd > 0) {
  1823.         m_selEnd = nuEnd;
  1824.  
  1825.         XmTextSetHighlight(m_textWidget, 
  1826.                            m_selStart, m_selEnd, 
  1827.                            XmHIGHLIGHT_SECONDARY_SELECTED
  1828.                            );
  1829.     }
  1830.  
  1831.     XP_FREE(pNewBuf);
  1832. }
  1833.  
  1834.  
  1835.  
  1836. // --------------------------------------------------------------------[ API ]
  1837.  
  1838. Boolean
  1839. xfe_SpellCheckerAvailable(MWContext* context)
  1840. {
  1841.     if (xfe_spellHandler == NULL) {
  1842.         xfe_spellHandler = new XFE_SpellHandler(context);
  1843.     }
  1844.  
  1845.     return xfe_spellHandler->IsAvailable();
  1846. }
  1847.  
  1848. Boolean
  1849. xfe_EditorSpellCheck(MWContext* context)
  1850. {
  1851.     if (xfe_SpellCheckerAvailable(context)) {
  1852.         xfe_spellHandler->ProcessDocument(context, TRUE);
  1853.         return TRUE;
  1854.     }
  1855.     else {
  1856.         return FALSE;
  1857.     }
  1858. }
  1859.  
  1860. Boolean
  1861. xfe_TextSpellCheck(MWContext* context)
  1862. {
  1863.     if (xfe_SpellCheckerAvailable(context)) {
  1864.         xfe_spellHandler->ProcessDocument(context, FALSE);
  1865.         return TRUE;
  1866.     }
  1867.     else {
  1868.         return FALSE;
  1869.     }
  1870. }
  1871.  
  1872. // ----<eof>
  1873.