home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / spellcli.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  35.2 KB  |  1,250 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. #include "stdafx.h"
  20. // the dialog box & string resources are in edtrcdll DLL
  21. #include "edtrcdll\src\resource.h"
  22. //#include "limits.h"
  23. #include "edview.h"
  24. #include "edt.h"
  25. #include "spellcli.h"
  26. #include "prefapi.h"
  27. #include "edtrccln.h"
  28. #include "nethelp.h"
  29. #include "xp_help.h"
  30.  
  31. // typedef's for the spell checker library public API's
  32.  
  33. typedef ISpellChecker* (FAR SCAPI *SC_CREATE_PROC)();
  34. typedef void (FAR SCAPI *SC_DESTROY_PROC)(ISpellChecker *pSpellChecker);
  35.  
  36. // Preference strings
  37. static LPCTSTR LanguagePref = "SpellChecker.DefaultLanguage";
  38. static LPCTSTR DialectPref = "SpellChecker.DefaultDialect";
  39.  
  40. static void ShowSpellCheckerError(CWnd *pParentWnd, int ErrorCode);
  41.  
  42. // Spell Checker loading and initialization error codes
  43. #define SPELL_ERR_NOT_INSTALLED     1
  44. #define SPELL_ERR_COULD_NOT_LOAD    2
  45. #define SPELL_ERR_INSTANCE_ACTIVE   3
  46. #define SPELL_ERR_CORRUPT           4
  47.  
  48. // Returns the spell checker install directory
  49.  
  50. static LPCTSTR GetSpellCheckerDir()
  51. {
  52.     static CString Dir;
  53.  
  54.     if (Dir.IsEmpty())
  55.     {
  56.         char ModuleFile[_MAX_PATH];
  57.  
  58.         if (GetModuleFileName(AfxGetInstanceHandle(), ModuleFile, sizeof(ModuleFile)))
  59.         {
  60.             Dir = ModuleFile;
  61.             int i = Dir.ReverseFind('\\');
  62.             if (i != -1)
  63.             {
  64.                 Dir.SetAt(i, 0);
  65.                 // The += operator doesn't copy at the new EOS location if I don't do this.
  66.                 Dir = (LPCTSTR)Dir;   
  67.                 Dir += "\\spellchk\\";
  68.             }
  69.             else
  70.                 Dir.Empty();
  71.         }
  72.     }
  73.  
  74.     return Dir;
  75. }
  76.  
  77. static LPCTSTR GetSpellCheckerDllPath()
  78. {
  79.     static CString Path;
  80.     
  81.     Path = GetSpellCheckerDir();   
  82.     
  83. #ifdef XP_WIN32
  84.     Path += "sp3240.dll";
  85. #else
  86.     Path += "sp1640.dll";
  87. #endif
  88.     
  89.     return Path;
  90. }               
  91.  
  92. // Returns the personal dictionary directory
  93.  
  94. static LPCTSTR GetPersonalDicDir()
  95. {
  96.     static CString Dir;
  97.     
  98.     if (Dir.IsEmpty())
  99.     {
  100.         Dir = (theApp.m_UserDirectory.IsEmpty() ? (LPCTSTR)GetSpellCheckerDir() : (LPCTSTR)theApp.m_UserDirectory);
  101.  
  102.         // make sure there is a '\' at the end
  103.         if (Dir[Dir.GetLength() - 1] != '\\')
  104.             Dir += "\\";
  105.     }
  106.  
  107.     return Dir;
  108. }
  109.  
  110. // Returns the personal dictionary filename
  111.  
  112. static LPCTSTR GetPersonalDicFilename()
  113. {
  114.     static CString Filename;
  115.  
  116.     if (Filename.IsEmpty())
  117.     {
  118.         char *Pref = NULL;
  119.         PREF_CopyCharPref("SpellChecker.PersonalDictionary", &Pref);
  120.  
  121.         if (Pref == NULL || *Pref == 0)
  122.         {
  123.             Filename = GetPersonalDicDir();
  124.             Filename += "custom.dic";
  125.         }
  126.         else
  127.             Filename = Pref;
  128.  
  129.         if (Pref != NULL)
  130.             XP_FREE(Pref);
  131.     }
  132.  
  133.     return Filename;
  134. }
  135.  
  136. // This function returns the "default language & dialect" values from the registry. These
  137. // default settings are only used when more than one languages/dialects are available.
  138. // We only need to handle the cases where the marketing spec requires multiple languages/
  139. // dialects.
  140. static void GetDefaultLanguage(int32 &Language, int32 &Dialect)
  141. {
  142.     CString csLanguage = theApp.GetProfileString("Spelling", "Default Language", NULL);
  143.     if (csLanguage.IsEmpty())
  144.         return;
  145.  
  146.     // For the English version.
  147.     if (stricmp(csLanguage, "US English") == 0)
  148.     {
  149.         Language = L_ENGLISH;
  150.         Dialect = D_US_ENGLISH;
  151.     }
  152.     else if (stricmp(csLanguage, "UK English") == 0)
  153.     {
  154.         Language = L_ENGLISH;
  155.         Dialect = D_UK_ENGLISH;
  156.     }
  157.  
  158.     // For the Portuguese version.
  159.     else if (stricmp(csLanguage, "Brazilian Portuguese") == 0)
  160.     {
  161.         Language = L_PORTUGUESE;
  162.         Dialect = D_BRAZILIAN;
  163.     }
  164.     else if (stricmp(csLanguage, "European Portuguese") == 0)
  165.     {
  166.         Language = L_PORTUGUESE;
  167.         Dialect = D_EUROPEAN;
  168.     }
  169.  
  170.     // For the Spanish version.
  171.     else if (stricmp(csLanguage, "Spanish") == 0)
  172.     {
  173.         Language = L_SPANISH;
  174.         Dialect = D_DEFAULT;
  175.     }
  176.     else if (stricmp(csLanguage, "Catalan") == 0)
  177.     {
  178.         Language = L_CATALAN;
  179.         Dialect = D_DEFAULT;
  180.     }
  181. }
  182.  
  183. #ifdef XP_WIN32
  184. #define IsValidHandle(h)    (h != NULL)
  185. #else
  186. #define IsValidHandle(h)    (h > HINSTANCE_ERROR)
  187. #endif
  188.  
  189. static void ShowNoSpellCheckerDlg(CWnd *pParentWnd);
  190.  
  191.  
  192. static LPCTSTR GetLanguageString(int Language, int Dialect)
  193. {
  194.     UINT StringId;
  195.  
  196.     switch (Language)
  197.     {
  198.     case L_CZECH:       StringId = IDS_SPELL_CZECH; break;
  199.     case L_RUSSIAN:     StringId = IDS_SPELL_RUSSIAN; break;
  200.     case L_CATALAN:     StringId = IDS_SPELL_CATALAN; break;
  201.     case L_HUNGARIAN:   StringId = IDS_SPELL_HUNGARIAN; break;
  202.     case L_FRENCH:      StringId = IDS_SPELL_FRENCH; break;
  203.     case L_GERMAN:      StringId = IDS_SPELL_GERMAN; break;
  204.     case L_SWEDISH:     StringId = IDS_SPELL_SWEDISH; break;
  205.     case L_SPANISH:     StringId = IDS_SPELL_SPANISH; break;
  206.     case L_ITALIAN:     StringId = IDS_SPELL_ITALIAN; break;
  207.     case L_DANISH:      StringId = IDS_SPELL_DANISH; break;
  208.     case L_DUTCH:       StringId = IDS_SPELL_DUTCH; break;
  209.  
  210.     case L_PORTUGUESE:  if (Dialect == D_BRAZILIAN)
  211.                             StringId = IDS_SPELL_PORTUGUESE_BRAZILIAN;
  212.                         else if (Dialect == D_EUROPEAN)
  213.                             StringId = IDS_SPELL_PORTUGUESE_EUROPEAN;
  214.                         else
  215.                             StringId = IDS_SPELL_PORTUGUESE; 
  216.                         break;
  217.  
  218.     case L_NORWEGIAN:   if (Dialect == D_BOKMAL)
  219.                             StringId = IDS_SPELL_NORWEGIAN_BOKMAL;
  220.                         else if (Dialect == D_NYNORSK)
  221.                             StringId = IDS_SPELL_NORWEGIAN_NYNORSK;
  222.                         else
  223.                             StringId = IDS_SPELL_NORWEGIAN;
  224.                         break;
  225.  
  226.     case L_FINNISH:     StringId = IDS_SPELL_FINNISH; break;
  227.     case L_GREEK:       StringId = IDS_SPELL_GREEK; break;
  228.  
  229.     case L_ENGLISH:     if (Dialect == D_US_ENGLISH)
  230.                             StringId = IDS_SPELL_ENGLISH_US;
  231.                         else if (Dialect == D_UK_ENGLISH)
  232.                             StringId = IDS_SPELL_ENGLISH_UK;
  233.                         else
  234.                             StringId = IDS_SPELL_ENGLISH;
  235.                         break;
  236.  
  237.     case L_AFRIKAANS:   StringId = IDS_SPELL_AFRIKAANS; break;
  238.     case L_POLISH:      StringId = IDS_SPELL_POLISH; break;
  239.  
  240.     default:            StringId = IDS_SPELL_UNKNOWN_LANGUAGE;
  241.                         ASSERT(FALSE);
  242.     }
  243.  
  244.     // Resource switcher object: It switches the default resource handle to the 
  245.     // editorXX.dll, cause that's where the string resources are. The resource
  246.     // handle is automatically restored in the destructor.
  247.     CEditorResourceSwitcher ResourceSwitcher;
  248.  
  249.     static CString theString;
  250.     theString.LoadString(StringId);
  251.     return theString;
  252. }
  253.  
  254. /////////////////////////////////////////////////////////////////////////////
  255. // CSpellCheckerDlg dialog
  256.  
  257. CSpellCheckerDlg::CSpellCheckerDlg(ISpellChecker *pSpellChecker, CSpellCheckerClient *pClient, 
  258.                                    CWnd* pParent /*=NULL*/)
  259.     : CDialog(IDD, pParent)
  260. {
  261.     //{{AFX_DATA_INIT(CSpellCheckerDlg)
  262.     m_NewWord = _T("");
  263.     //}}AFX_DATA_INIT
  264.  
  265.     m_pSpellChecker = pSpellChecker;
  266.     m_pClient = pClient;
  267. }
  268.  
  269. void CSpellCheckerDlg::DoDataExchange(CDataExchange* pDX)
  270. {
  271.     CDialog::DoDataExchange(pDX);
  272.     //{{AFX_DATA_MAP(CSpellCheckerDlg)
  273.     DDX_Control(pDX, IDC_SUGGESTIONS, m_SuggestionsListBox);
  274.     //}}AFX_DATA_MAP
  275. }
  276.  
  277. void CSpellCheckerDlg::SetAlternatives()
  278. {
  279.     CString CurrString;
  280.     GetDlgItemText(IDC_NEW_WORD, CurrString);
  281.  
  282.     // Delete any existing strings
  283.     m_SuggestionsListBox.ResetContent();
  284.  
  285.     // Get alternative strings
  286.     int index;
  287.     m_NumSuggestions = m_pSpellChecker->GetNumAlternatives(CurrString);
  288.     for (int i = 0; i < m_NumSuggestions; i++)
  289.     {
  290.         char AltString[100];
  291.  
  292.         int RetVal = m_pSpellChecker->GetAlternative(i, AltString, sizeof(AltString));
  293.         ASSERT(RetVal == 0 && strlen(AltString) > 0);
  294.  
  295.         index = m_SuggestionsListBox.AddString(AltString);
  296.         m_SuggestionsListBox.SetItemData(index, 0);
  297.     }
  298.  
  299.     if (m_NumSuggestions > 0)
  300.     {
  301.         m_SuggestionsListBox.SetCurSel(0);
  302.         m_SuggestionsListBox.SetFocus();
  303.  
  304.         // Make the Change button the default, cause a correction is selected to be applied.
  305.         GotoDlgCtrl(GetDlgItem(IDC_CHANGE));
  306.     }
  307.     else
  308.     {
  309.         index = m_SuggestionsListBox.AddString(m_strNoSuggestions);
  310.         m_SuggestionsListBox.SetItemData(index, 1);
  311.  
  312.         GotoDlgCtrl(GetDlgItem(IDC_NEW_WORD));
  313.     }
  314. }
  315.  
  316. // posted message to set the initial focus
  317. #define WM_SET_INITIAL_FOCUS    WM_USER + 1000
  318.  
  319. BEGIN_MESSAGE_MAP(CSpellCheckerDlg, CDialog)
  320.     //{{AFX_MSG_MAP(CSpellCheckerDlg)
  321.     ON_BN_CLICKED(IDC_CHANGE, OnChange)
  322.     ON_BN_CLICKED(IDC_IGNORE, OnIgnore)
  323.     ON_EN_CHANGE(IDC_NEW_WORD, OnChangeNewWord)
  324.     ON_EN_SETFOCUS(IDC_NEW_WORD, OnSetFocusNewWord)
  325.     ON_BN_CLICKED(IDC_IGNORE_ALL, OnIgnoreAll)
  326.     ON_BN_CLICKED(IDC_CHANGE_ALL, OnChangeAll)
  327.     ON_BN_CLICKED(IDC_CHECK_WORD, OnCheckWord)
  328.     ON_BN_CLICKED(IDC_ADD, OnAdd)
  329.     ON_LBN_DBLCLK(IDC_SUGGESTIONS, OnChange)
  330.     ON_LBN_SETFOCUS(IDC_SUGGESTIONS, OnSetFocusSuggestions)
  331.     ON_LBN_SELCHANGE(IDC_SUGGESTIONS, OnSelChangeSuggestions)
  332.     ON_BN_CLICKED(IDC_EDIT_DICTIONARY, OnEditDictionary)
  333.     ON_CBN_SELENDOK(IDC_LANGUAGE, OnSelendokLanguage)
  334.     ON_BN_CLICKED(ID_HELP, OnHelp)
  335.     //}}AFX_MSG_MAP
  336.     ON_MESSAGE(WM_SET_INITIAL_FOCUS, OnSetInitialFocus)
  337. #ifdef XP_WIN32
  338.     ON_WM_HELPINFO()
  339. #endif //XP_WIN32
  340. END_MESSAGE_MAP()
  341.  
  342. /////////////////////////////////////////////////////////////////////////////
  343. // CSpellCheckerDlg message handlers
  344.  
  345. BOOL CSpellCheckerDlg::OnInitDialog() 
  346. {
  347.     // Load strings from the resource DLL
  348.     // The default resource handle is already set to the editor resource DLL
  349.  
  350.     m_strChange.LoadString(IDS_SPELL_CHANGE);
  351.     m_strChangeAll.LoadString(IDS_SPELL_CHANGE_ALL);
  352.     m_strDelete.LoadString(IDS_SPELL_DELETE);
  353.     m_strDeleteAll.LoadString(IDS_SPELL_DELETE_ALL);
  354.     m_strNoSuggestions.LoadString(IDS_SPELL_NO_SUGGESTIONS);
  355.     m_strStop.LoadString(IDS_SPELL_STOP);
  356.     m_strDone.LoadString(IDS_SPELL_DONE);
  357.     m_strCorrectSpelling.LoadString(IDS_CORRECT_SPELLING);
  358.  
  359.     // Don't need the editor resource handle any more. Switch back to the app.
  360.     m_DlgResource.Reset();
  361.  
  362.     CDialog::OnInitDialog();
  363.  
  364.     InitLanguageList();
  365.  
  366.     // set initial focus
  367.     PostMessage(WM_SET_INITIAL_FOCUS, 0, 0);
  368.  
  369.     return TRUE;  // return TRUE unless you set the focus to a control
  370.                   // EXCEPTION: OCX Property Pages should return FALSE
  371. }
  372.  
  373. LRESULT CSpellCheckerDlg::OnSetInitialFocus(WPARAM wParam, LPARAM lParam)
  374. {
  375.     GetFirstError();
  376.  
  377.     return 0L;
  378. }
  379.  
  380. void CSpellCheckerDlg::OnCancel() 
  381. {
  382.     CDialog::OnCancel();
  383. }
  384.  
  385. void CSpellCheckerDlg::OnChangeNewWord() 
  386. {
  387.     GetDlgItem(IDC_CHANGE)->EnableWindow(TRUE);
  388.     GetDlgItem(IDC_CHANGE_ALL)->EnableWindow(TRUE);
  389.  
  390.     GetDlgItemText(IDC_NEW_WORD, m_NewWord);
  391.  
  392.     UpdateChangeButton();       // update the label of the Change buttons
  393.  
  394.     BOOL IsEmpty = m_NewWord.IsEmpty();
  395.     GetDlgItem(IDC_CHECK_WORD)->EnableWindow(!IsEmpty);
  396.     GetDlgItem(IDC_ADD)->EnableWindow(!IsEmpty);
  397. }
  398.  
  399. void CSpellCheckerDlg::OnSetFocusNewWord() 
  400. {
  401.     GetDlgItemText(IDC_NEW_WORD, m_NewWord);
  402.  
  403.     m_SuggestionsListBox.SetCurSel(-1);
  404.  
  405.     UpdateChangeButton();       // update the label of the Change buttons
  406. }
  407.  
  408. void CSpellCheckerDlg::UpdateChangeButton()
  409. {
  410.     SetDlgItemText(IDC_CHANGE, m_NewWord.IsEmpty() ? m_strDelete : m_strChange);
  411.     SetDlgItemText(IDC_CHANGE_ALL, m_NewWord.IsEmpty() ? m_strDeleteAll : m_strChangeAll);
  412. }
  413.  
  414. void CSpellCheckerDlg::OnSetFocusSuggestions() 
  415. {
  416.     int Selection = m_SuggestionsListBox.GetCurSel();
  417.     if (Selection != LB_ERR)
  418.         m_SuggestionsListBox.GetText(Selection, m_NewWord);
  419.     else if (m_NumSuggestions > 0)
  420.     {
  421.         m_SuggestionsListBox.SetCurSel(0);
  422.         m_SuggestionsListBox.GetText(0, m_NewWord);
  423.         UpdateChangeButton();       // update the label of the Change buttons
  424.     }
  425.     else
  426.         GetDlgItem(IDC_NEW_WORD)->SetFocus();
  427. }
  428.  
  429. void CSpellCheckerDlg::OnSelChangeSuggestions() 
  430. {
  431.     int Selection = m_SuggestionsListBox.GetCurSel();
  432.  
  433.     // check for the (no suggestions) string
  434.     if (m_SuggestionsListBox.GetItemData(Selection) != 1)
  435.         m_SuggestionsListBox.GetText(Selection, m_NewWord);
  436.     else
  437.         GetDlgItem(IDC_NEW_WORD)->SetFocus();
  438. }
  439.  
  440. void CSpellCheckerDlg::OnIgnore() 
  441. {
  442.     CWaitCursor WaitCursor; // Show the Wait cursor.
  443.  
  444.     m_pClient->IgnoreHilitedText(FALSE);
  445.     GetNextError();
  446. }
  447.  
  448. void CSpellCheckerDlg::OnIgnoreAll() 
  449. {
  450.     CWaitCursor WaitCursor; // Show the Wait cursor.
  451.  
  452.     m_pSpellChecker->IgnoreWord(m_MisspelledWord);
  453.  
  454.     m_pClient->IgnoreHilitedText(TRUE);
  455.     GetNextError();   
  456. }
  457.  
  458. void CSpellCheckerDlg::OnChange() 
  459. {
  460.     // Close dialog box if no more misspelled word
  461.     if (m_MisspelledWord.IsEmpty())
  462.         EndDialog(IDOK);
  463.     else
  464.         CommonOnChange(FALSE);    
  465. }
  466.  
  467. void CSpellCheckerDlg::OnChangeAll() 
  468. {
  469.     CommonOnChange(TRUE);    
  470. }
  471.  
  472. void CSpellCheckerDlg::CommonOnChange(BOOL ChangeAll) 
  473. {
  474.     CWaitCursor WaitCursor; // Show the Wait cursor.
  475.  
  476.     // pasting NULL text, that is deleting mispelled word
  477.     m_pClient->ReplaceHilitedText(m_NewWord, ChangeAll);
  478.     GetNextError();  
  479. }
  480.  
  481. void CSpellCheckerDlg::OnCheckWord()
  482. {
  483.     CString String;
  484.     GetDlgItemText(IDC_NEW_WORD, String);
  485.  
  486.     // If first make sure the new word is ok
  487.     if (!String.IsEmpty()) 
  488.     {
  489.         // the user may have entered multiple words
  490.         CString ErrMsg;
  491.         char *Separator = " ";
  492.         char *Token = XP_STRTOK((char*)(LPCTSTR)String, Separator);
  493.         
  494.         while (Token != NULL)
  495.         {
  496.             if (!m_pSpellChecker->CheckWord(Token))
  497.             {
  498.                 SetAlternatives();
  499.                 return;
  500.             }
  501.  
  502.             // get the next work in the string
  503.             Token = XP_STRTOK(NULL, Separator);
  504.         }
  505.  
  506.         // The new word(s) spelled correctly. Show feedback to user.
  507.         // Display "correct spelling" in the Suggestions listbox and 
  508.         // mark it so that the user can't select this string.
  509.         m_SuggestionsListBox.ResetContent();
  510.         int index = m_SuggestionsListBox.AddString(m_strCorrectSpelling);
  511.         m_SuggestionsListBox.SetItemData(index, 1);
  512.         m_NumSuggestions = 0;
  513.         m_SuggestionsListBox.EnableWindow(TRUE);
  514.  
  515.         // Make the Change button the default cause the word is OK to be applied.
  516.         GotoDlgCtrl(GetDlgItem(IDC_CHANGE));
  517.     }
  518. }
  519.  
  520. void CSpellCheckerDlg::OnAdd()
  521. {
  522.     CString String;
  523.     GetDlgItemText(IDC_NEW_WORD, String);
  524.  
  525.     int Status = m_pSpellChecker->AddWordToPersonalDictionary(String);
  526.  
  527.     if (Status)
  528.     {
  529.         TRACE1("ISpellChecker::AddWordToPersonalDictionary() returned %d\n", Status);
  530.  
  531.         CString Msg;
  532.         AfxFormatString1(Msg, IDS_ERR_ADD_WORD, GetPersonalDicFilename());
  533.         MessageBox(Msg, NULL, MB_OK | MB_ICONSTOP);
  534.     }
  535.     else
  536.     {
  537.         m_pClient->ReplaceHilitedText(String, 
  538.                                       String.Compare(m_MisspelledWord) == 0 ? TRUE : FALSE);
  539.         GetNextError(); 
  540.     }
  541. }
  542.  
  543. void CSpellCheckerDlg::GetNextError()
  544. {
  545.     ProcessError(m_pClient->GetNextError());
  546. }
  547.  
  548. void CSpellCheckerDlg::GetFirstError()
  549. {
  550.     // Reenable disabled controls from the last pass. Doing this after calling 
  551.     // ProcessError() was not setting m_NewWord properly for the first error 
  552.     // after the Language was changed.
  553.     m_MisspelledWord = " ";     // must be non-empty for the controls to be enabled
  554.     ChangeState();
  555.  
  556.     ProcessError(m_pClient->GetFirstError());
  557. }
  558.  
  559. void CSpellCheckerDlg::ProcessError(char *pMisspelledWord)
  560. {
  561.     m_MisspelledWord = pMisspelledWord;        // remember the misspelled word
  562.  
  563.     if (pMisspelledWord != NULL)
  564.     {
  565.         SetDlgItemText(IDC_NEW_WORD, pMisspelledWord);
  566.         SetAlternatives();
  567.  
  568.         XP_FREE(pMisspelledWord);
  569.     }        
  570.     else
  571.         ChangeState();
  572. }
  573.  
  574. void CSpellCheckerDlg::OnHelp() 
  575. {
  576.     NetHelp(HELP_SPELL_CHECK);
  577. }
  578.  
  579. // OnHelpInfo - Invokes Help window when F1 key is pressed
  580. #ifdef XP_WIN32
  581. BOOL CSpellCheckerDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
  582. {
  583.     OnHelp();
  584.     return TRUE;
  585. }
  586. #endif//XP_WIN32
  587.  
  588.  
  589. void CSpellCheckerDlg::OnEditDictionary()
  590. {
  591.     CPersonalDictionaryDlg Dlg(m_pSpellChecker, this);
  592.     Dlg.DoModal();
  593. }
  594.  
  595. void CSpellCheckerDlg::InitLanguageList()
  596. {
  597.     CComboBox *pLanguageCtrl = (CComboBox *)GetDlgItem(IDC_LANGUAGE);
  598.     if (pLanguageCtrl == NULL)
  599.     {
  600.         ASSERT(FALSE);
  601.         return;
  602.     }
  603.  
  604.     int Language, Dialect;
  605.     int Count = m_pSpellChecker->GetNumOfDictionaries();
  606.     for (int i = 0; i < Count; i++)
  607.     {
  608.         if (m_pSpellChecker->GetDictionaryLanguage(i, Language, Dialect) == 0)
  609.         {
  610.             int Index = pLanguageCtrl->AddString(GetLanguageString(Language, Dialect));
  611.             pLanguageCtrl->SetItemData(Index, MAKELONG(Language, Dialect));
  612.         }
  613.     }
  614.  
  615.     // Select the current default
  616.     m_pSpellChecker->GetCurrentLanguage(Language, Dialect);
  617.  
  618.     if (Language == 0 && Dialect == 0)
  619.         pLanguageCtrl->SetCurSel(0);
  620.     else
  621.     {
  622.         DWORD ItemData = MAKELONG(Language, Dialect);
  623.     
  624.         for (int i = 0; i < Count; i++)
  625.         {
  626.             if (ItemData == pLanguageCtrl->GetItemData(i))
  627.             {
  628.                 pLanguageCtrl->SetCurSel(i);
  629.                 break;
  630.             }
  631.         }
  632.     }
  633. }
  634.  
  635. void CSpellCheckerDlg::OnSelendokLanguage() 
  636. {
  637.     CComboBox *pLanguageCtrl = (CComboBox *)GetDlgItem(IDC_LANGUAGE);
  638.     if (pLanguageCtrl == NULL)
  639.     {
  640.         ASSERT(FALSE);
  641.         return;
  642.     }
  643.  
  644.     int CurrLanguage, CurrDialect;
  645.     int NewLanguage, NewDialect;
  646.     if (m_pSpellChecker->GetCurrentLanguage(CurrLanguage, CurrDialect) != 0)
  647.     {
  648.         ASSERT(FALSE);
  649.         return;
  650.     }
  651.  
  652.     long ItemData = pLanguageCtrl->GetItemData(pLanguageCtrl->GetCurSel());
  653.     NewLanguage = LOWORD(ItemData);
  654.     NewDialect = HIWORD(ItemData);
  655.  
  656.     if (NewLanguage != CurrLanguage || NewDialect != CurrDialect)
  657.     {
  658.         PREF_SetIntPref(LanguagePref, NewLanguage);
  659.         PREF_SetIntPref(DialectPref, NewDialect);
  660.  
  661.         m_pClient->ReprocessDocument();
  662.         
  663.         GetFirstError();
  664.     }        
  665. }
  666.  
  667. void CSpellCheckerDlg::ChangeState() 
  668. {
  669.     BOOL HaveError = !m_MisspelledWord.IsEmpty();
  670.     if (!HaveError)
  671.         m_SuggestionsListBox.SetCurSel(-1);
  672.  
  673.     GetDlgItem(IDC_NEW_WORD)->EnableWindow(HaveError);
  674.     GetDlgItem(IDC_SUGGESTIONS)->EnableWindow(HaveError);
  675.     GetDlgItem(IDC_CHANGE_ALL)->EnableWindow(HaveError);
  676.     GetDlgItem(IDC_IGNORE)->EnableWindow(HaveError);
  677.     GetDlgItem(IDC_IGNORE_ALL)->EnableWindow(HaveError);
  678.     GetDlgItem(IDC_CHECK_WORD)->EnableWindow(HaveError);
  679.     GetDlgItem(IDC_ADD)->EnableWindow(HaveError);
  680.     GetDlgItem(IDCANCEL)->EnableWindow(HaveError);
  681.   
  682.     // if no more errors, label the Change button "Done" and make it the default button
  683.     if (!HaveError)
  684.     {
  685.         SetDlgItemText(IDC_CHANGE, m_strDone);
  686.         GotoDlgCtrl(GetDlgItem(IDC_CHANGE));
  687.     }
  688. }
  689.  
  690. /****************************************************************************************
  691.  * Spell Checker client class implementation.
  692.  ****************************************************************************************/
  693.  
  694. // static instance count. We can only have a single instance of the spell checker.
  695. int CSpellCheckerClient::m_InstanceCount = 0;
  696.  
  697. CSpellCheckerClient::CSpellCheckerClient(CWnd *pParentWnd) 
  698. {
  699.     m_hSpellCheckerDll = 0;
  700.     m_pParentWnd = pParentWnd;
  701.     m_pSpellChecker = NULL;
  702.     m_pDictionaryDlg = NULL;
  703.     m_BufferSize = 0;
  704.     m_SelStart = m_SelEnd = 0;
  705.  
  706.     m_InstanceCount++;
  707. }
  708.  
  709. CSpellCheckerClient::~CSpellCheckerClient()
  710. {
  711.     if (m_pSpellChecker && IsValidHandle(m_hSpellCheckerDll))
  712.     {        
  713.          SC_DESTROY_PROC SC_Destroy_proc = (SC_DESTROY_PROC)GetProcAddress(m_hSpellCheckerDll, "SC_DESTROY");
  714.         if (SC_Destroy_proc != NULL)
  715.             SC_Destroy_proc(m_pSpellChecker);
  716.         else
  717.             TRACE("Could not load resolve SC_DESTROY");
  718.     }
  719.     
  720.     if (IsValidHandle(m_hSpellCheckerDll))
  721.         FreeLibrary(m_hSpellCheckerDll);
  722.  
  723.     m_InstanceCount--;
  724. }
  725.  
  726. int CSpellCheckerClient::ProcessDocument()
  727. {
  728. #define Fail(ErrorCode) { ShowSpellCheckerError(m_pParentWnd, ErrorCode); return -1; }
  729.  
  730.     // Show the Wait cursor.
  731.     CWaitCursor WaitCursor;
  732.  
  733.     // Make sure we don't have an instance of the spell checker already running.
  734.     if (m_InstanceCount > 1)
  735.         Fail(SPELL_ERR_INSTANCE_ACTIVE);
  736.  
  737.     // Load the DLL
  738.     m_hSpellCheckerDll = LoadLibrary(GetSpellCheckerDllPath());
  739.        if (!IsValidHandle(m_hSpellCheckerDll))
  740.     {
  741.         // Check if the DLL exists
  742.         if (_access(GetSpellCheckerDllPath(), 0) != 0)
  743.             Fail(SPELL_ERR_NOT_INSTALLED)
  744.         else
  745.             Fail(SPELL_ERR_COULD_NOT_LOAD)
  746.     }
  747.  
  748.     // resolve public API functions
  749.     SC_CREATE_PROC SC_Create_proc = (SC_CREATE_PROC)GetProcAddress(m_hSpellCheckerDll, "SC_CREATE");
  750.     if (SC_Create_proc == NULL)
  751.         Fail(SPELL_ERR_CORRUPT);
  752.  
  753.     // instantiate spell checker server object
  754.     m_pSpellChecker = (*SC_Create_proc)();
  755.     if (m_pSpellChecker == NULL)
  756.         Fail(SPELL_ERR_CORRUPT);
  757.  
  758.     // initialize the spell checker server
  759.     int32 Language = 0;
  760.     int32 Dialect = 0;
  761.  
  762.     // First see if any language preferences have been set
  763.     PREF_GetIntPref(LanguagePref, &Language);
  764.     PREF_GetIntPref(DialectPref, &Dialect);
  765.  
  766.     // If not, get the default language & dialect settings, if any.
  767.     if (Language == 0)
  768.         GetDefaultLanguage(Language, Dialect);
  769.  
  770.     if ((m_pSpellChecker)->Initialize(Language, Dialect, GetSpellCheckerDir(),  GetPersonalDicFilename()))
  771.         Fail(SPELL_ERR_CORRUPT);
  772.  
  773.     // Get the text buffer from the document
  774.     XP_HUGE_CHAR_PTR pBuf = GetBuffer();
  775.     if (pBuf == NULL)
  776.         return 0;                       // nothing to spell check
  777.  
  778.     m_BufferSize = XP_STRLEN(pBuf);     // remember the size
  779.  
  780.     // Is there a selection
  781.     GetSelection(m_SelStart, m_SelEnd);
  782.  
  783.     // pass text buffer to the spell checker
  784.     int retcode = m_pSpellChecker->SetBuf(pBuf, m_SelStart, m_SelEnd);
  785.     TRACE1("m_pSpellChecker->SetBuf() returned %d\n", retcode);
  786.  
  787.     // release the buffer (the Spell Checker makes a local copy)
  788.     XP_HUGE_FREE(pBuf);         
  789.  
  790.     if (retcode != 0)
  791.         return -1;
  792.  
  793.     // Remove the Wait cursor, as we are ready to display the dialog box.
  794.     WaitCursor.Restore();
  795.  
  796.     // show dialog box
  797.     CSpellCheckerDlg Dlg(m_pSpellChecker, this, m_pParentWnd);
  798.     int result = Dlg.DoModal() == IDOK ? 0 : -1;
  799.  
  800.     RemoveAllErrorHilites();
  801.  
  802.     return result;
  803. }
  804.  
  805. int CSpellCheckerClient::ReprocessDocument()
  806. {
  807.     // Show the Wait cursor.
  808.     CWaitCursor WaitCursor;
  809.  
  810.     if (m_pSpellChecker == NULL)
  811.     {
  812.         ASSERT(FALSE);
  813.         return -1;
  814.     }
  815.  
  816.     RemoveAllErrorHilites();
  817.  
  818.     // Get the latest language defaults
  819.     int32 Language = 0;
  820.     int32 Dialect = 0;
  821.  
  822.     PREF_GetIntPref(LanguagePref, &Language);
  823.     PREF_GetIntPref(DialectPref, &Dialect);
  824.  
  825.     if (m_pSpellChecker->SetCurrentLanguage(Language, Dialect) == 0)
  826.     {
  827.         // Get the text buffer from the document
  828.         XP_HUGE_CHAR_PTR pBuf = GetBuffer();
  829.         if (pBuf == NULL)
  830.             return 0;                       // nothing to spell check
  831.  
  832.         // If we were spell checking a selection in the previous pass,
  833.         // adjust the selection for any corrections made in the last pass.
  834.         if (m_SelEnd > 0)
  835.         {
  836.             m_SelEnd += (XP_STRLEN(pBuf) - m_BufferSize);
  837.         }
  838.  
  839.         m_BufferSize = XP_STRLEN(pBuf);     // remember the size
  840.  
  841.         // pass text buffer to the spell checker
  842.         int retcode = m_pSpellChecker->SetBuf(pBuf, m_SelStart, m_SelEnd);
  843.  
  844.         // release the buffer (the Spell Checker makes a local copy)
  845.         XP_HUGE_FREE(pBuf);         
  846.  
  847.         if (retcode != 0)
  848.             return -1;
  849.  
  850.         return 0;
  851.     }
  852.  
  853.     return -1;
  854. }
  855.  
  856. /////////////////////////////////////////////////////////////////////////////
  857. // CHtmlSpellChecker - HTML document spell checker client object
  858.  
  859. CHtmlSpellChecker::CHtmlSpellChecker(MWContext *pMWContext, CNetscapeEditView *pHtmlView)
  860.                         : CSpellCheckerClient(pHtmlView)
  861. {
  862.     m_pMWContext = pMWContext;
  863.     m_pView = pHtmlView;
  864. }
  865.  
  866. // Implementation of base class virtuals.
  867.  
  868. XP_HUGE_CHAR_PTR CHtmlSpellChecker::GetBuffer()
  869. {
  870.     // Get the document text
  871.     return EDT_GetPositionalText(m_pMWContext); 
  872. }
  873.  
  874. BOOL CHtmlSpellChecker::GetSelection(int32 &SelStart, int32 &SelEnd)
  875. {
  876.     char *pSelection;
  877.    
  878.     if ((pSelection = (char *)LO_GetSelectionText(m_pMWContext)) != NULL)
  879.     {
  880.         XP_FREE(pSelection);
  881.         EDT_GetSelectionOffsets(m_pMWContext, &SelStart, &SelEnd);
  882.         return TRUE;
  883.     }
  884.     else
  885.         return FALSE;       // no selection
  886. }
  887.  
  888. char *CHtmlSpellChecker::GetFirstError()
  889. {
  890.     // turn off refreshing and spell check the text.
  891.     EDT_SetRefresh(m_pMWContext, FALSE);
  892.  
  893.     // underline the misspelled words
  894.     EDT_CharacterData* pCharData = EDT_NewCharacterData();
  895.     pCharData->mask = TF_SPELL;
  896.     pCharData->values = TF_SPELL;
  897.  
  898.     unsigned long Offset, Len;
  899.     while (m_pSpellChecker->GetNextMisspelledWord(Offset, Len) == 0)
  900.         EDT_SetCharacterDataAtOffset(m_pMWContext, pCharData, Offset, Len);
  901.   
  902.     XP_FREE(pCharData);
  903.  
  904.     // set sursor position at the beginning of document so that 
  905.     // EDT_SelectNextMisspelledWord() to start at the beginning.
  906.     EDT_BeginOfDocument(m_pMWContext, FALSE);
  907.     EDT_SetRefresh(m_pMWContext, TRUE);
  908.  
  909.     m_pView->UpdateWindow();
  910.  
  911.     // Select and return the first mispelled word 
  912.     if (EDT_SelectFirstMisspelledWord(m_pMWContext))
  913.         return (char *)LO_GetSelectionText(m_pMWContext);
  914.     else
  915.         return NULL;
  916. }
  917.  
  918. char *CHtmlSpellChecker::GetNextError()
  919. {
  920.     if (EDT_SelectNextMisspelledWord(m_pMWContext))
  921.         return (char *)LO_GetSelectionText(m_pMWContext);
  922.     else
  923.         return FALSE;
  924. }
  925.  
  926. void CHtmlSpellChecker::ReplaceHilitedText(const char *NewText, int AllInstances)
  927. {
  928.     char *pOldWord = (char *)LO_GetSelectionText(m_pMWContext);
  929.     if (pOldWord != NULL)
  930.     {
  931.         EDT_ReplaceMisspelledWord(m_pMWContext, pOldWord, (char*)NewText, AllInstances);
  932.         XP_FREE(pOldWord);
  933.     }
  934.     else
  935.         ASSERT(FALSE);
  936. }
  937.  
  938. void CHtmlSpellChecker::IgnoreHilitedText(int AllInstances)
  939. {
  940.     char *pOldWord = (char *)LO_GetSelectionText(m_pMWContext);
  941.     if (pOldWord != NULL)
  942.     {
  943.         EDT_IgnoreMisspelledWord(m_pMWContext, pOldWord, AllInstances);
  944.         XP_FREE(pOldWord);
  945.     }
  946.     else
  947.         ASSERT(FALSE);
  948. }
  949.  
  950. void CHtmlSpellChecker::RemoveAllErrorHilites()
  951. {
  952.     // ignore any unprocessed misspelled words 
  953.     EDT_IgnoreMisspelledWord(m_pMWContext, NULL, TRUE);
  954. }
  955.  
  956. /////////////////////////////////////////////////////////////////////////////
  957. // CPlainTextSpellChecker - Plain Text spell checker client object
  958.  
  959. CPlainTextSpellChecker::CPlainTextSpellChecker(CEdit *pTextView)
  960.                         : CSpellCheckerClient(pTextView)
  961. {
  962.     m_pTextView = pTextView;
  963. }
  964.  
  965. // Implentation of base class virtuals.
  966.  
  967. XP_HUGE_CHAR_PTR CPlainTextSpellChecker::GetBuffer()
  968. {
  969.     // Get the document text
  970.     int32 Length = m_pTextView->GetWindowTextLength();
  971.     if (Length == 0)
  972.         Length = 1;     // return NULL;
  973.  
  974.     XP_HUGE_CHAR_PTR pText = (XP_HUGE_CHAR_PTR) XP_HUGE_ALLOC(Length + 1);
  975.     if (pText != NULL)
  976.         m_pTextView->GetWindowText(pText, Length + 1);
  977.  
  978.     return pText;
  979. }
  980.  
  981. BOOL CPlainTextSpellChecker::GetSelection(int32 &SelStart, int32 &SelEnd)
  982. {
  983.     // hilight mispelled word
  984.     int Start, End;
  985.     m_pTextView->GetSel(Start, End);
  986.     if (End > Start)
  987.     {
  988.         SelStart = Start;
  989.         SelEnd = End;
  990.         return TRUE;
  991.     }
  992.     else
  993.         return FALSE;
  994. }
  995.  
  996. char *CPlainTextSpellChecker::GetFirstError()
  997. {
  998.     return GetNextError();
  999. }
  1000.  
  1001. char *CPlainTextSpellChecker::GetNextError()
  1002. {
  1003.     unsigned long Offset, Len;
  1004.     char *pMisspelledWord = NULL;
  1005.  
  1006.     if (m_pSpellChecker->GetNextMisspelledWord(Offset, Len) == 0)
  1007.     {
  1008.         // hilight mispelled word
  1009.         m_pTextView->SetSel((int)Offset, (int)(Offset+Len));
  1010.         m_pTextView->UpdateWindow();
  1011.  
  1012.         // Extract mispelled word 
  1013.         XP_HUGE_CHAR_PTR pBuf = GetBuffer();
  1014.         if (pBuf != NULL)
  1015.         {
  1016.             pMisspelledWord = (char *)XP_ALLOC(Len + 1);
  1017.             if (pMisspelledWord != NULL)
  1018.                 XP_STRNCPY_SAFE(pMisspelledWord, (LPCTSTR)pBuf + Offset, Len+1);
  1019.  
  1020.             XP_HUGE_FREE(pBuf);
  1021.         }
  1022.     }
  1023.  
  1024.     return pMisspelledWord;
  1025. }
  1026.  
  1027. void CPlainTextSpellChecker::ReplaceHilitedText(const char *NewText, int AllInstances)
  1028. {
  1029.     if (m_pSpellChecker->ReplaceMisspelledWord(NewText, AllInstances) != 0)
  1030.         ASSERT(FALSE);      // maybe display an out of memory error
  1031.  
  1032.     unsigned long NewBufSize = m_pSpellChecker->GetBufSize();
  1033.     char *pNewBuf = (char *)XP_ALLOC(NewBufSize);
  1034.     if (pNewBuf == NULL)
  1035.     {
  1036.         ASSERT(FALSE);      // maybe display an out of memory error
  1037.         return;
  1038.     }
  1039.     m_pSpellChecker->GetBuf(pNewBuf, NewBufSize);
  1040.     m_pTextView->SetWindowText(pNewBuf);
  1041.     XP_FREE(pNewBuf);
  1042. }
  1043.  
  1044. void CPlainTextSpellChecker::IgnoreHilitedText(int AllInstances)
  1045. {
  1046.     // Unlike the HTML document, there are no error highlights to remove. 
  1047.     // However, if we need to ignore all subsequent instances of the word,
  1048.     // we need to tell the spell checker to ignore this word.
  1049.  
  1050.     if (AllInstances)
  1051.     {
  1052.         int StartChar, EndChar;
  1053.         m_pTextView->GetSel(StartChar, EndChar);
  1054.  
  1055.         CString Buf;
  1056.         m_pTextView->GetWindowText(Buf);
  1057.     
  1058.         int OldWordLen = EndChar - StartChar;
  1059.         CString OldWord;
  1060.         OldWord.Format("%.*s", OldWordLen, (LPCTSTR)Buf + StartChar);
  1061.  
  1062.         m_pSpellChecker->IgnoreWord(OldWord);
  1063.     }
  1064. }
  1065.  
  1066. void ShowSpellCheckerError(CWnd *pParentWnd, int ErrorCode)
  1067. {
  1068.     // Resource switcher object: It switches the default resource handle to the 
  1069.     // editorXX.dll, cause that's where the string resources are. The resource
  1070.     // handle is automatically restored in the destructor.
  1071.     CEditorResourceSwitcher ResourceSwitcher;
  1072.  
  1073.     CString Msg, Title;
  1074.     int MsgId;
  1075.  
  1076.     switch (ErrorCode)
  1077.     {
  1078.     case SPELL_ERR_NOT_INSTALLED:
  1079.         MsgId = IDS_SPELL_NOT_INSTALLED;
  1080.         break;
  1081.     case SPELL_ERR_COULD_NOT_LOAD:
  1082.         MsgId = IDS_SPELL_COULD_NOT_LOAD;
  1083.         break;
  1084.     case SPELL_ERR_INSTANCE_ACTIVE:
  1085.         MsgId = IDS_SPELL_INSTANCE_ACTIVE;
  1086.         break;
  1087.     case SPELL_ERR_CORRUPT:
  1088.     default:
  1089.         MsgId = IDS_SPELL_CORRUPT;
  1090.         break;
  1091.     }
  1092.  
  1093.     Msg.LoadString(MsgId);
  1094.     Title.LoadString(IDS_CHECK_SPELLING);
  1095.     pParentWnd->MessageBox(Msg, Title, MB_ICONSTOP | MB_OK);
  1096. }
  1097.  
  1098. /////////////////////////////////////////////////////////////////////////////
  1099. // CPersonalDictionaryDlg dialog
  1100.  
  1101. CPersonalDictionaryDlg::CPersonalDictionaryDlg(ISpellChecker *pSpellChecker, CWnd* pParent /*=NULL*/)
  1102.     : CDialog(IDD, pParent)
  1103. {
  1104.     m_pSpellChecker = pSpellChecker;
  1105. }
  1106.  
  1107. void CPersonalDictionaryDlg::DoDataExchange(CDataExchange* pDX)
  1108. {
  1109.     CDialog::DoDataExchange(pDX);
  1110.     //{{AFX_DATA_MAP(CPersonalDictionaryDlg)
  1111.     DDX_Control(pDX, IDC_WORD_LIST, m_WordList);
  1112.     //}}AFX_DATA_MAP
  1113. }
  1114.  
  1115. BOOL CPersonalDictionaryDlg::OnInitDialog() 
  1116. {
  1117.     // Don't need the editor resource handle any more. Switch back to the app.
  1118.     m_DlgResource.Reset();
  1119.  
  1120.     CDialog::OnInitDialog();
  1121.  
  1122.     char Word[128];
  1123.     if (m_pSpellChecker->GetFirstPersonalDictionaryWord(Word, sizeof(Word)) >= 0)
  1124.     {
  1125.         do 
  1126.             m_WordList.AddString(Word);
  1127.         while (m_pSpellChecker->GetNextPersonalDictionaryWord(Word, sizeof(Word)) >= 0);
  1128.     }
  1129.  
  1130.     EnableButtons();
  1131.  
  1132.     return TRUE;
  1133. }
  1134.  
  1135. void CPersonalDictionaryDlg::OnOK()
  1136. {
  1137.     m_pSpellChecker->ResetPersonalDictionary();
  1138.  
  1139.     CString Word;
  1140.     int Count = m_WordList.GetCount();
  1141.  
  1142.     for (int Index = 0; Index < Count; Index++)
  1143.     {
  1144.         m_WordList.GetText(Index, Word);
  1145.         ASSERT(Word.GetLength() > 0);
  1146.         m_pSpellChecker->AddWordToPersonalDictionary(Word);
  1147.     }
  1148.     
  1149.     CDialog::OnOK();
  1150. }
  1151.  
  1152. BEGIN_MESSAGE_MAP(CPersonalDictionaryDlg, CDialog)
  1153.     ON_BN_CLICKED(IDC_ADD, OnAddWord)
  1154.     ON_BN_CLICKED(IDC_REPLACE, OnReplaceWord)
  1155.     ON_BN_CLICKED(IDC_REMOVE, OnRemoveWord)
  1156.     ON_LBN_SELCHANGE(IDC_WORD_LIST, OnSelChangeWordList)
  1157.     ON_EN_CHANGE(IDC_NEW_WORD, EnableButtons)
  1158.     ON_BN_CLICKED(ID_HELP, OnHelp)
  1159. #ifdef XP_WIN32
  1160.     ON_WM_HELPINFO()
  1161. #endif //XP_WIN32
  1162. END_MESSAGE_MAP()
  1163.  
  1164. void CPersonalDictionaryDlg::OnAddWord()
  1165. {
  1166.     CString NewWord;
  1167.     GetDlgItemText(IDC_NEW_WORD, NewWord);
  1168.  
  1169.     if (NewWord.IsEmpty())
  1170.         return;
  1171.  
  1172.     int Index = m_WordList.FindStringExact(-1, NewWord);
  1173.     if (Index == LB_ERR)
  1174.     {
  1175.         // clear current selection
  1176.         for (int i = m_WordList.GetCount() - 1; i >= 0; i--)
  1177.             m_WordList.SetSel(Index, FALSE);
  1178.  
  1179.         Index = m_WordList.AddString(NewWord);
  1180.         m_WordList.SetSel(Index, TRUE);
  1181.     }
  1182. }
  1183.  
  1184. void CPersonalDictionaryDlg::OnReplaceWord()
  1185. {
  1186.     CString NewWord;
  1187.     GetDlgItemText(IDC_NEW_WORD, NewWord);
  1188.  
  1189.     if (NewWord.IsEmpty())
  1190.         return;
  1191.  
  1192.     if (m_WordList.GetSelCount() != 1)
  1193.         return;
  1194.  
  1195.     OnRemoveWord();
  1196.     OnAddWord();
  1197. }
  1198.  
  1199. void CPersonalDictionaryDlg::OnRemoveWord()
  1200. {
  1201.     CString Word;
  1202.  
  1203.     for (int Index = m_WordList.GetCount() - 1; Index >= 0; Index--)
  1204.     {
  1205.         if (m_WordList.GetSel(Index))
  1206.             m_WordList.DeleteString(Index);
  1207.     }
  1208.  
  1209.     EnableButtons();
  1210. }
  1211.  
  1212. void CPersonalDictionaryDlg::OnSelChangeWordList()
  1213. {
  1214.     if (m_WordList.GetSelCount() == 1)
  1215.     {
  1216.         CString Text;
  1217.         m_WordList.GetText(m_WordList.GetCurSel(), Text);
  1218.         SetDlgItemText(IDC_NEW_WORD, Text);
  1219.     }
  1220.  
  1221.     EnableButtons();
  1222. }
  1223.  
  1224. void CPersonalDictionaryDlg::EnableButtons()
  1225. {
  1226.     CString NewWord;
  1227.     GetDlgItemText(IDC_NEW_WORD, NewWord);
  1228.  
  1229.     BOOL    NewWordEmpty = NewWord.IsEmpty();
  1230.     int     SelCount = m_WordList.GetSelCount();
  1231.  
  1232.     GetDlgItem(IDC_ADD)->EnableWindow(!NewWordEmpty);
  1233.     GetDlgItem(IDC_REPLACE)->EnableWindow(!NewWordEmpty && SelCount == 1);
  1234.     GetDlgItem(IDC_REMOVE)->EnableWindow(SelCount > 0);
  1235. }
  1236.  
  1237. void CPersonalDictionaryDlg::OnHelp() 
  1238. {
  1239.     NetHelp(HELP_EDIT_DICTIONARY);
  1240. }
  1241.  
  1242. // OnHelpInfo - Invokes Help window when F1 key is pressed
  1243. #ifdef XP_WIN32
  1244. BOOL CPersonalDictionaryDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
  1245. {
  1246.     OnHelp();
  1247.     return TRUE;
  1248. }
  1249. #endif//XP_WIN32
  1250.