mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
1250 lines
34 KiB
C++
1250 lines
34 KiB
C++
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
|
*
|
||
|
* The contents of this file are subject to the Netscape Public License
|
||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||
|
* http://www.mozilla.org/NPL/
|
||
|
*
|
||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* NPL.
|
||
|
*
|
||
|
* The Initial Developer of this code under the NPL is Netscape
|
||
|
* Communications Corporation. Portions created by Netscape are
|
||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||
|
* Reserved.
|
||
|
*/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
// the dialog box & string resources are in edtrcdll DLL
|
||
|
#include "edtrcdll\src\resource.h"
|
||
|
//#include "limits.h"
|
||
|
#include "edview.h"
|
||
|
#include "edt.h"
|
||
|
#include "spellcli.h"
|
||
|
#include "prefapi.h"
|
||
|
#include "edtrccln.h"
|
||
|
#include "nethelp.h"
|
||
|
#include "xp_help.h"
|
||
|
|
||
|
// typedef's for the spell checker library public API's
|
||
|
|
||
|
typedef ISpellChecker* (FAR SCAPI *SC_CREATE_PROC)();
|
||
|
typedef void (FAR SCAPI *SC_DESTROY_PROC)(ISpellChecker *pSpellChecker);
|
||
|
|
||
|
// Preference strings
|
||
|
static LPCTSTR LanguagePref = "SpellChecker.DefaultLanguage";
|
||
|
static LPCTSTR DialectPref = "SpellChecker.DefaultDialect";
|
||
|
|
||
|
static void ShowSpellCheckerError(CWnd *pParentWnd, int ErrorCode);
|
||
|
|
||
|
// Spell Checker loading and initialization error codes
|
||
|
#define SPELL_ERR_NOT_INSTALLED 1
|
||
|
#define SPELL_ERR_COULD_NOT_LOAD 2
|
||
|
#define SPELL_ERR_INSTANCE_ACTIVE 3
|
||
|
#define SPELL_ERR_CORRUPT 4
|
||
|
|
||
|
// Returns the spell checker install directory
|
||
|
|
||
|
static LPCTSTR GetSpellCheckerDir()
|
||
|
{
|
||
|
static CString Dir;
|
||
|
|
||
|
if (Dir.IsEmpty())
|
||
|
{
|
||
|
char ModuleFile[_MAX_PATH];
|
||
|
|
||
|
if (GetModuleFileName(AfxGetInstanceHandle(), ModuleFile, sizeof(ModuleFile)))
|
||
|
{
|
||
|
Dir = ModuleFile;
|
||
|
int i = Dir.ReverseFind('\\');
|
||
|
if (i != -1)
|
||
|
{
|
||
|
Dir.SetAt(i, 0);
|
||
|
// The += operator doesn't copy at the new EOS location if I don't do this.
|
||
|
Dir = (LPCTSTR)Dir;
|
||
|
Dir += "\\spellchk\\";
|
||
|
}
|
||
|
else
|
||
|
Dir.Empty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Dir;
|
||
|
}
|
||
|
|
||
|
static LPCTSTR GetSpellCheckerDllPath()
|
||
|
{
|
||
|
static CString Path;
|
||
|
|
||
|
Path = GetSpellCheckerDir();
|
||
|
|
||
|
#ifdef XP_WIN32
|
||
|
Path += "sp3240.dll";
|
||
|
#else
|
||
|
Path += "sp1640.dll";
|
||
|
#endif
|
||
|
|
||
|
return Path;
|
||
|
}
|
||
|
|
||
|
// Returns the personal dictionary directory
|
||
|
|
||
|
static LPCTSTR GetPersonalDicDir()
|
||
|
{
|
||
|
static CString Dir;
|
||
|
|
||
|
if (Dir.IsEmpty())
|
||
|
{
|
||
|
Dir = (theApp.m_UserDirectory.IsEmpty() ? (LPCTSTR)GetSpellCheckerDir() : (LPCTSTR)theApp.m_UserDirectory);
|
||
|
|
||
|
// make sure there is a '\' at the end
|
||
|
if (Dir[Dir.GetLength() - 1] != '\\')
|
||
|
Dir += "\\";
|
||
|
}
|
||
|
|
||
|
return Dir;
|
||
|
}
|
||
|
|
||
|
// Returns the personal dictionary filename
|
||
|
|
||
|
static LPCTSTR GetPersonalDicFilename()
|
||
|
{
|
||
|
static CString Filename;
|
||
|
|
||
|
if (Filename.IsEmpty())
|
||
|
{
|
||
|
char *Pref = NULL;
|
||
|
PREF_CopyCharPref("SpellChecker.PersonalDictionary", &Pref);
|
||
|
|
||
|
if (Pref == NULL || *Pref == 0)
|
||
|
{
|
||
|
Filename = GetPersonalDicDir();
|
||
|
Filename += "custom.dic";
|
||
|
}
|
||
|
else
|
||
|
Filename = Pref;
|
||
|
|
||
|
if (Pref != NULL)
|
||
|
XP_FREE(Pref);
|
||
|
}
|
||
|
|
||
|
return Filename;
|
||
|
}
|
||
|
|
||
|
// This function returns the "default language & dialect" values from the registry. These
|
||
|
// default settings are only used when more than one languages/dialects are available.
|
||
|
// We only need to handle the cases where the marketing spec requires multiple languages/
|
||
|
// dialects.
|
||
|
static void GetDefaultLanguage(int32 &Language, int32 &Dialect)
|
||
|
{
|
||
|
CString csLanguage = theApp.GetProfileString("Spelling", "Default Language", NULL);
|
||
|
if (csLanguage.IsEmpty())
|
||
|
return;
|
||
|
|
||
|
// For the English version.
|
||
|
if (stricmp(csLanguage, "US English") == 0)
|
||
|
{
|
||
|
Language = L_ENGLISH;
|
||
|
Dialect = D_US_ENGLISH;
|
||
|
}
|
||
|
else if (stricmp(csLanguage, "UK English") == 0)
|
||
|
{
|
||
|
Language = L_ENGLISH;
|
||
|
Dialect = D_UK_ENGLISH;
|
||
|
}
|
||
|
|
||
|
// For the Portuguese version.
|
||
|
else if (stricmp(csLanguage, "Brazilian Portuguese") == 0)
|
||
|
{
|
||
|
Language = L_PORTUGUESE;
|
||
|
Dialect = D_BRAZILIAN;
|
||
|
}
|
||
|
else if (stricmp(csLanguage, "European Portuguese") == 0)
|
||
|
{
|
||
|
Language = L_PORTUGUESE;
|
||
|
Dialect = D_EUROPEAN;
|
||
|
}
|
||
|
|
||
|
// For the Spanish version.
|
||
|
else if (stricmp(csLanguage, "Spanish") == 0)
|
||
|
{
|
||
|
Language = L_SPANISH;
|
||
|
Dialect = D_DEFAULT;
|
||
|
}
|
||
|
else if (stricmp(csLanguage, "Catalan") == 0)
|
||
|
{
|
||
|
Language = L_CATALAN;
|
||
|
Dialect = D_DEFAULT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef XP_WIN32
|
||
|
#define IsValidHandle(h) (h != NULL)
|
||
|
#else
|
||
|
#define IsValidHandle(h) (h > HINSTANCE_ERROR)
|
||
|
#endif
|
||
|
|
||
|
static void ShowNoSpellCheckerDlg(CWnd *pParentWnd);
|
||
|
|
||
|
|
||
|
static LPCTSTR GetLanguageString(int Language, int Dialect)
|
||
|
{
|
||
|
UINT StringId;
|
||
|
|
||
|
switch (Language)
|
||
|
{
|
||
|
case L_CZECH: StringId = IDS_SPELL_CZECH; break;
|
||
|
case L_RUSSIAN: StringId = IDS_SPELL_RUSSIAN; break;
|
||
|
case L_CATALAN: StringId = IDS_SPELL_CATALAN; break;
|
||
|
case L_HUNGARIAN: StringId = IDS_SPELL_HUNGARIAN; break;
|
||
|
case L_FRENCH: StringId = IDS_SPELL_FRENCH; break;
|
||
|
case L_GERMAN: StringId = IDS_SPELL_GERMAN; break;
|
||
|
case L_SWEDISH: StringId = IDS_SPELL_SWEDISH; break;
|
||
|
case L_SPANISH: StringId = IDS_SPELL_SPANISH; break;
|
||
|
case L_ITALIAN: StringId = IDS_SPELL_ITALIAN; break;
|
||
|
case L_DANISH: StringId = IDS_SPELL_DANISH; break;
|
||
|
case L_DUTCH: StringId = IDS_SPELL_DUTCH; break;
|
||
|
|
||
|
case L_PORTUGUESE: if (Dialect == D_BRAZILIAN)
|
||
|
StringId = IDS_SPELL_PORTUGUESE_BRAZILIAN;
|
||
|
else if (Dialect == D_EUROPEAN)
|
||
|
StringId = IDS_SPELL_PORTUGUESE_EUROPEAN;
|
||
|
else
|
||
|
StringId = IDS_SPELL_PORTUGUESE;
|
||
|
break;
|
||
|
|
||
|
case L_NORWEGIAN: if (Dialect == D_BOKMAL)
|
||
|
StringId = IDS_SPELL_NORWEGIAN_BOKMAL;
|
||
|
else if (Dialect == D_NYNORSK)
|
||
|
StringId = IDS_SPELL_NORWEGIAN_NYNORSK;
|
||
|
else
|
||
|
StringId = IDS_SPELL_NORWEGIAN;
|
||
|
break;
|
||
|
|
||
|
case L_FINNISH: StringId = IDS_SPELL_FINNISH; break;
|
||
|
case L_GREEK: StringId = IDS_SPELL_GREEK; break;
|
||
|
|
||
|
case L_ENGLISH: if (Dialect == D_US_ENGLISH)
|
||
|
StringId = IDS_SPELL_ENGLISH_US;
|
||
|
else if (Dialect == D_UK_ENGLISH)
|
||
|
StringId = IDS_SPELL_ENGLISH_UK;
|
||
|
else
|
||
|
StringId = IDS_SPELL_ENGLISH;
|
||
|
break;
|
||
|
|
||
|
case L_AFRIKAANS: StringId = IDS_SPELL_AFRIKAANS; break;
|
||
|
case L_POLISH: StringId = IDS_SPELL_POLISH; break;
|
||
|
|
||
|
default: StringId = IDS_SPELL_UNKNOWN_LANGUAGE;
|
||
|
ASSERT(FALSE);
|
||
|
}
|
||
|
|
||
|
// Resource switcher object: It switches the default resource handle to the
|
||
|
// editorXX.dll, cause that's where the string resources are. The resource
|
||
|
// handle is automatically restored in the destructor.
|
||
|
CEditorResourceSwitcher ResourceSwitcher;
|
||
|
|
||
|
static CString theString;
|
||
|
theString.LoadString(StringId);
|
||
|
return theString;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CSpellCheckerDlg dialog
|
||
|
|
||
|
CSpellCheckerDlg::CSpellCheckerDlg(ISpellChecker *pSpellChecker, CSpellCheckerClient *pClient,
|
||
|
CWnd* pParent /*=NULL*/)
|
||
|
: CDialog(IDD, pParent)
|
||
|
{
|
||
|
//{{AFX_DATA_INIT(CSpellCheckerDlg)
|
||
|
m_NewWord = _T("");
|
||
|
//}}AFX_DATA_INIT
|
||
|
|
||
|
m_pSpellChecker = pSpellChecker;
|
||
|
m_pClient = pClient;
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::DoDataExchange(CDataExchange* pDX)
|
||
|
{
|
||
|
CDialog::DoDataExchange(pDX);
|
||
|
//{{AFX_DATA_MAP(CSpellCheckerDlg)
|
||
|
DDX_Control(pDX, IDC_SUGGESTIONS, m_SuggestionsListBox);
|
||
|
//}}AFX_DATA_MAP
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::SetAlternatives()
|
||
|
{
|
||
|
CString CurrString;
|
||
|
GetDlgItemText(IDC_NEW_WORD, CurrString);
|
||
|
|
||
|
// Delete any existing strings
|
||
|
m_SuggestionsListBox.ResetContent();
|
||
|
|
||
|
// Get alternative strings
|
||
|
int index;
|
||
|
m_NumSuggestions = m_pSpellChecker->GetNumAlternatives(CurrString);
|
||
|
for (int i = 0; i < m_NumSuggestions; i++)
|
||
|
{
|
||
|
char AltString[100];
|
||
|
|
||
|
int RetVal = m_pSpellChecker->GetAlternative(i, AltString, sizeof(AltString));
|
||
|
ASSERT(RetVal == 0 && strlen(AltString) > 0);
|
||
|
|
||
|
index = m_SuggestionsListBox.AddString(AltString);
|
||
|
m_SuggestionsListBox.SetItemData(index, 0);
|
||
|
}
|
||
|
|
||
|
if (m_NumSuggestions > 0)
|
||
|
{
|
||
|
m_SuggestionsListBox.SetCurSel(0);
|
||
|
m_SuggestionsListBox.SetFocus();
|
||
|
|
||
|
// Make the Change button the default, cause a correction is selected to be applied.
|
||
|
GotoDlgCtrl(GetDlgItem(IDC_CHANGE));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
index = m_SuggestionsListBox.AddString(m_strNoSuggestions);
|
||
|
m_SuggestionsListBox.SetItemData(index, 1);
|
||
|
|
||
|
GotoDlgCtrl(GetDlgItem(IDC_NEW_WORD));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// posted message to set the initial focus
|
||
|
#define WM_SET_INITIAL_FOCUS WM_USER + 1000
|
||
|
|
||
|
BEGIN_MESSAGE_MAP(CSpellCheckerDlg, CDialog)
|
||
|
//{{AFX_MSG_MAP(CSpellCheckerDlg)
|
||
|
ON_BN_CLICKED(IDC_CHANGE, OnChange)
|
||
|
ON_BN_CLICKED(IDC_IGNORE, OnIgnore)
|
||
|
ON_EN_CHANGE(IDC_NEW_WORD, OnChangeNewWord)
|
||
|
ON_EN_SETFOCUS(IDC_NEW_WORD, OnSetFocusNewWord)
|
||
|
ON_BN_CLICKED(IDC_IGNORE_ALL, OnIgnoreAll)
|
||
|
ON_BN_CLICKED(IDC_CHANGE_ALL, OnChangeAll)
|
||
|
ON_BN_CLICKED(IDC_CHECK_WORD, OnCheckWord)
|
||
|
ON_BN_CLICKED(IDC_ADD, OnAdd)
|
||
|
ON_LBN_DBLCLK(IDC_SUGGESTIONS, OnChange)
|
||
|
ON_LBN_SETFOCUS(IDC_SUGGESTIONS, OnSetFocusSuggestions)
|
||
|
ON_LBN_SELCHANGE(IDC_SUGGESTIONS, OnSelChangeSuggestions)
|
||
|
ON_BN_CLICKED(IDC_EDIT_DICTIONARY, OnEditDictionary)
|
||
|
ON_CBN_SELENDOK(IDC_LANGUAGE, OnSelendokLanguage)
|
||
|
ON_BN_CLICKED(ID_HELP, OnHelp)
|
||
|
//}}AFX_MSG_MAP
|
||
|
ON_MESSAGE(WM_SET_INITIAL_FOCUS, OnSetInitialFocus)
|
||
|
#ifdef XP_WIN32
|
||
|
ON_WM_HELPINFO()
|
||
|
#endif //XP_WIN32
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CSpellCheckerDlg message handlers
|
||
|
|
||
|
BOOL CSpellCheckerDlg::OnInitDialog()
|
||
|
{
|
||
|
// Load strings from the resource DLL
|
||
|
// The default resource handle is already set to the editor resource DLL
|
||
|
|
||
|
m_strChange.LoadString(IDS_SPELL_CHANGE);
|
||
|
m_strChangeAll.LoadString(IDS_SPELL_CHANGE_ALL);
|
||
|
m_strDelete.LoadString(IDS_SPELL_DELETE);
|
||
|
m_strDeleteAll.LoadString(IDS_SPELL_DELETE_ALL);
|
||
|
m_strNoSuggestions.LoadString(IDS_SPELL_NO_SUGGESTIONS);
|
||
|
m_strStop.LoadString(IDS_SPELL_STOP);
|
||
|
m_strDone.LoadString(IDS_SPELL_DONE);
|
||
|
m_strCorrectSpelling.LoadString(IDS_CORRECT_SPELLING);
|
||
|
|
||
|
// Don't need the editor resource handle any more. Switch back to the app.
|
||
|
m_DlgResource.Reset();
|
||
|
|
||
|
CDialog::OnInitDialog();
|
||
|
|
||
|
InitLanguageList();
|
||
|
|
||
|
// set initial focus
|
||
|
PostMessage(WM_SET_INITIAL_FOCUS, 0, 0);
|
||
|
|
||
|
return TRUE; // return TRUE unless you set the focus to a control
|
||
|
// EXCEPTION: OCX Property Pages should return FALSE
|
||
|
}
|
||
|
|
||
|
LRESULT CSpellCheckerDlg::OnSetInitialFocus(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
GetFirstError();
|
||
|
|
||
|
return 0L;
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnCancel()
|
||
|
{
|
||
|
CDialog::OnCancel();
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnChangeNewWord()
|
||
|
{
|
||
|
GetDlgItem(IDC_CHANGE)->EnableWindow(TRUE);
|
||
|
GetDlgItem(IDC_CHANGE_ALL)->EnableWindow(TRUE);
|
||
|
|
||
|
GetDlgItemText(IDC_NEW_WORD, m_NewWord);
|
||
|
|
||
|
UpdateChangeButton(); // update the label of the Change buttons
|
||
|
|
||
|
BOOL IsEmpty = m_NewWord.IsEmpty();
|
||
|
GetDlgItem(IDC_CHECK_WORD)->EnableWindow(!IsEmpty);
|
||
|
GetDlgItem(IDC_ADD)->EnableWindow(!IsEmpty);
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnSetFocusNewWord()
|
||
|
{
|
||
|
GetDlgItemText(IDC_NEW_WORD, m_NewWord);
|
||
|
|
||
|
m_SuggestionsListBox.SetCurSel(-1);
|
||
|
|
||
|
UpdateChangeButton(); // update the label of the Change buttons
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::UpdateChangeButton()
|
||
|
{
|
||
|
SetDlgItemText(IDC_CHANGE, m_NewWord.IsEmpty() ? m_strDelete : m_strChange);
|
||
|
SetDlgItemText(IDC_CHANGE_ALL, m_NewWord.IsEmpty() ? m_strDeleteAll : m_strChangeAll);
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnSetFocusSuggestions()
|
||
|
{
|
||
|
int Selection = m_SuggestionsListBox.GetCurSel();
|
||
|
if (Selection != LB_ERR)
|
||
|
m_SuggestionsListBox.GetText(Selection, m_NewWord);
|
||
|
else if (m_NumSuggestions > 0)
|
||
|
{
|
||
|
m_SuggestionsListBox.SetCurSel(0);
|
||
|
m_SuggestionsListBox.GetText(0, m_NewWord);
|
||
|
UpdateChangeButton(); // update the label of the Change buttons
|
||
|
}
|
||
|
else
|
||
|
GetDlgItem(IDC_NEW_WORD)->SetFocus();
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnSelChangeSuggestions()
|
||
|
{
|
||
|
int Selection = m_SuggestionsListBox.GetCurSel();
|
||
|
|
||
|
// check for the (no suggestions) string
|
||
|
if (m_SuggestionsListBox.GetItemData(Selection) != 1)
|
||
|
m_SuggestionsListBox.GetText(Selection, m_NewWord);
|
||
|
else
|
||
|
GetDlgItem(IDC_NEW_WORD)->SetFocus();
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnIgnore()
|
||
|
{
|
||
|
CWaitCursor WaitCursor; // Show the Wait cursor.
|
||
|
|
||
|
m_pClient->IgnoreHilitedText(FALSE);
|
||
|
GetNextError();
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnIgnoreAll()
|
||
|
{
|
||
|
CWaitCursor WaitCursor; // Show the Wait cursor.
|
||
|
|
||
|
m_pSpellChecker->IgnoreWord(m_MisspelledWord);
|
||
|
|
||
|
m_pClient->IgnoreHilitedText(TRUE);
|
||
|
GetNextError();
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnChange()
|
||
|
{
|
||
|
// Close dialog box if no more misspelled word
|
||
|
if (m_MisspelledWord.IsEmpty())
|
||
|
EndDialog(IDOK);
|
||
|
else
|
||
|
CommonOnChange(FALSE);
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnChangeAll()
|
||
|
{
|
||
|
CommonOnChange(TRUE);
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::CommonOnChange(BOOL ChangeAll)
|
||
|
{
|
||
|
CWaitCursor WaitCursor; // Show the Wait cursor.
|
||
|
|
||
|
// pasting NULL text, that is deleting mispelled word
|
||
|
m_pClient->ReplaceHilitedText(m_NewWord, ChangeAll);
|
||
|
GetNextError();
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnCheckWord()
|
||
|
{
|
||
|
CString String;
|
||
|
GetDlgItemText(IDC_NEW_WORD, String);
|
||
|
|
||
|
// If first make sure the new word is ok
|
||
|
if (!String.IsEmpty())
|
||
|
{
|
||
|
// the user may have entered multiple words
|
||
|
CString ErrMsg;
|
||
|
char *Separator = " ";
|
||
|
char *Token = XP_STRTOK((char*)(LPCTSTR)String, Separator);
|
||
|
|
||
|
while (Token != NULL)
|
||
|
{
|
||
|
if (!m_pSpellChecker->CheckWord(Token))
|
||
|
{
|
||
|
SetAlternatives();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// get the next work in the string
|
||
|
Token = XP_STRTOK(NULL, Separator);
|
||
|
}
|
||
|
|
||
|
// The new word(s) spelled correctly. Show feedback to user.
|
||
|
// Display "correct spelling" in the Suggestions listbox and
|
||
|
// mark it so that the user can't select this string.
|
||
|
m_SuggestionsListBox.ResetContent();
|
||
|
int index = m_SuggestionsListBox.AddString(m_strCorrectSpelling);
|
||
|
m_SuggestionsListBox.SetItemData(index, 1);
|
||
|
m_NumSuggestions = 0;
|
||
|
m_SuggestionsListBox.EnableWindow(TRUE);
|
||
|
|
||
|
// Make the Change button the default cause the word is OK to be applied.
|
||
|
GotoDlgCtrl(GetDlgItem(IDC_CHANGE));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnAdd()
|
||
|
{
|
||
|
CString String;
|
||
|
GetDlgItemText(IDC_NEW_WORD, String);
|
||
|
|
||
|
int Status = m_pSpellChecker->AddWordToPersonalDictionary(String);
|
||
|
|
||
|
if (Status)
|
||
|
{
|
||
|
TRACE1("ISpellChecker::AddWordToPersonalDictionary() returned %d\n", Status);
|
||
|
|
||
|
CString Msg;
|
||
|
AfxFormatString1(Msg, IDS_ERR_ADD_WORD, GetPersonalDicFilename());
|
||
|
MessageBox(Msg, NULL, MB_OK | MB_ICONSTOP);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pClient->ReplaceHilitedText(String,
|
||
|
String.Compare(m_MisspelledWord) == 0 ? TRUE : FALSE);
|
||
|
GetNextError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::GetNextError()
|
||
|
{
|
||
|
ProcessError(m_pClient->GetNextError());
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::GetFirstError()
|
||
|
{
|
||
|
// Reenable disabled controls from the last pass. Doing this after calling
|
||
|
// ProcessError() was not setting m_NewWord properly for the first error
|
||
|
// after the Language was changed.
|
||
|
m_MisspelledWord = " "; // must be non-empty for the controls to be enabled
|
||
|
ChangeState();
|
||
|
|
||
|
ProcessError(m_pClient->GetFirstError());
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::ProcessError(char *pMisspelledWord)
|
||
|
{
|
||
|
m_MisspelledWord = pMisspelledWord; // remember the misspelled word
|
||
|
|
||
|
if (pMisspelledWord != NULL)
|
||
|
{
|
||
|
SetDlgItemText(IDC_NEW_WORD, pMisspelledWord);
|
||
|
SetAlternatives();
|
||
|
|
||
|
XP_FREE(pMisspelledWord);
|
||
|
}
|
||
|
else
|
||
|
ChangeState();
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnHelp()
|
||
|
{
|
||
|
NetHelp(HELP_SPELL_CHECK);
|
||
|
}
|
||
|
|
||
|
// OnHelpInfo - Invokes Help window when F1 key is pressed
|
||
|
#ifdef XP_WIN32
|
||
|
BOOL CSpellCheckerDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
|
||
|
{
|
||
|
OnHelp();
|
||
|
return TRUE;
|
||
|
}
|
||
|
#endif//XP_WIN32
|
||
|
|
||
|
|
||
|
void CSpellCheckerDlg::OnEditDictionary()
|
||
|
{
|
||
|
CPersonalDictionaryDlg Dlg(m_pSpellChecker, this);
|
||
|
Dlg.DoModal();
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::InitLanguageList()
|
||
|
{
|
||
|
CComboBox *pLanguageCtrl = (CComboBox *)GetDlgItem(IDC_LANGUAGE);
|
||
|
if (pLanguageCtrl == NULL)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int Language, Dialect;
|
||
|
int Count = m_pSpellChecker->GetNumOfDictionaries();
|
||
|
for (int i = 0; i < Count; i++)
|
||
|
{
|
||
|
if (m_pSpellChecker->GetDictionaryLanguage(i, Language, Dialect) == 0)
|
||
|
{
|
||
|
int Index = pLanguageCtrl->AddString(GetLanguageString(Language, Dialect));
|
||
|
pLanguageCtrl->SetItemData(Index, MAKELONG(Language, Dialect));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Select the current default
|
||
|
m_pSpellChecker->GetCurrentLanguage(Language, Dialect);
|
||
|
|
||
|
if (Language == 0 && Dialect == 0)
|
||
|
pLanguageCtrl->SetCurSel(0);
|
||
|
else
|
||
|
{
|
||
|
DWORD ItemData = MAKELONG(Language, Dialect);
|
||
|
|
||
|
for (int i = 0; i < Count; i++)
|
||
|
{
|
||
|
if (ItemData == pLanguageCtrl->GetItemData(i))
|
||
|
{
|
||
|
pLanguageCtrl->SetCurSel(i);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::OnSelendokLanguage()
|
||
|
{
|
||
|
CComboBox *pLanguageCtrl = (CComboBox *)GetDlgItem(IDC_LANGUAGE);
|
||
|
if (pLanguageCtrl == NULL)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int CurrLanguage, CurrDialect;
|
||
|
int NewLanguage, NewDialect;
|
||
|
if (m_pSpellChecker->GetCurrentLanguage(CurrLanguage, CurrDialect) != 0)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
long ItemData = pLanguageCtrl->GetItemData(pLanguageCtrl->GetCurSel());
|
||
|
NewLanguage = LOWORD(ItemData);
|
||
|
NewDialect = HIWORD(ItemData);
|
||
|
|
||
|
if (NewLanguage != CurrLanguage || NewDialect != CurrDialect)
|
||
|
{
|
||
|
PREF_SetIntPref(LanguagePref, NewLanguage);
|
||
|
PREF_SetIntPref(DialectPref, NewDialect);
|
||
|
|
||
|
m_pClient->ReprocessDocument();
|
||
|
|
||
|
GetFirstError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CSpellCheckerDlg::ChangeState()
|
||
|
{
|
||
|
BOOL HaveError = !m_MisspelledWord.IsEmpty();
|
||
|
if (!HaveError)
|
||
|
m_SuggestionsListBox.SetCurSel(-1);
|
||
|
|
||
|
GetDlgItem(IDC_NEW_WORD)->EnableWindow(HaveError);
|
||
|
GetDlgItem(IDC_SUGGESTIONS)->EnableWindow(HaveError);
|
||
|
GetDlgItem(IDC_CHANGE_ALL)->EnableWindow(HaveError);
|
||
|
GetDlgItem(IDC_IGNORE)->EnableWindow(HaveError);
|
||
|
GetDlgItem(IDC_IGNORE_ALL)->EnableWindow(HaveError);
|
||
|
GetDlgItem(IDC_CHECK_WORD)->EnableWindow(HaveError);
|
||
|
GetDlgItem(IDC_ADD)->EnableWindow(HaveError);
|
||
|
GetDlgItem(IDCANCEL)->EnableWindow(HaveError);
|
||
|
|
||
|
// if no more errors, label the Change button "Done" and make it the default button
|
||
|
if (!HaveError)
|
||
|
{
|
||
|
SetDlgItemText(IDC_CHANGE, m_strDone);
|
||
|
GotoDlgCtrl(GetDlgItem(IDC_CHANGE));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/****************************************************************************************
|
||
|
* Spell Checker client class implementation.
|
||
|
****************************************************************************************/
|
||
|
|
||
|
// static instance count. We can only have a single instance of the spell checker.
|
||
|
int CSpellCheckerClient::m_InstanceCount = 0;
|
||
|
|
||
|
CSpellCheckerClient::CSpellCheckerClient(CWnd *pParentWnd)
|
||
|
{
|
||
|
m_hSpellCheckerDll = 0;
|
||
|
m_pParentWnd = pParentWnd;
|
||
|
m_pSpellChecker = NULL;
|
||
|
m_pDictionaryDlg = NULL;
|
||
|
m_BufferSize = 0;
|
||
|
m_SelStart = m_SelEnd = 0;
|
||
|
|
||
|
m_InstanceCount++;
|
||
|
}
|
||
|
|
||
|
CSpellCheckerClient::~CSpellCheckerClient()
|
||
|
{
|
||
|
if (m_pSpellChecker && IsValidHandle(m_hSpellCheckerDll))
|
||
|
{
|
||
|
SC_DESTROY_PROC SC_Destroy_proc = (SC_DESTROY_PROC)GetProcAddress(m_hSpellCheckerDll, "SC_DESTROY");
|
||
|
if (SC_Destroy_proc != NULL)
|
||
|
SC_Destroy_proc(m_pSpellChecker);
|
||
|
else
|
||
|
TRACE("Could not load resolve SC_DESTROY");
|
||
|
}
|
||
|
|
||
|
if (IsValidHandle(m_hSpellCheckerDll))
|
||
|
FreeLibrary(m_hSpellCheckerDll);
|
||
|
|
||
|
m_InstanceCount--;
|
||
|
}
|
||
|
|
||
|
int CSpellCheckerClient::ProcessDocument()
|
||
|
{
|
||
|
#define Fail(ErrorCode) { ShowSpellCheckerError(m_pParentWnd, ErrorCode); return -1; }
|
||
|
|
||
|
// Show the Wait cursor.
|
||
|
CWaitCursor WaitCursor;
|
||
|
|
||
|
// Make sure we don't have an instance of the spell checker already running.
|
||
|
if (m_InstanceCount > 1)
|
||
|
Fail(SPELL_ERR_INSTANCE_ACTIVE);
|
||
|
|
||
|
// Load the DLL
|
||
|
m_hSpellCheckerDll = LoadLibrary(GetSpellCheckerDllPath());
|
||
|
if (!IsValidHandle(m_hSpellCheckerDll))
|
||
|
{
|
||
|
// Check if the DLL exists
|
||
|
if (_access(GetSpellCheckerDllPath(), 0) != 0)
|
||
|
Fail(SPELL_ERR_NOT_INSTALLED)
|
||
|
else
|
||
|
Fail(SPELL_ERR_COULD_NOT_LOAD)
|
||
|
}
|
||
|
|
||
|
// resolve public API functions
|
||
|
SC_CREATE_PROC SC_Create_proc = (SC_CREATE_PROC)GetProcAddress(m_hSpellCheckerDll, "SC_CREATE");
|
||
|
if (SC_Create_proc == NULL)
|
||
|
Fail(SPELL_ERR_CORRUPT);
|
||
|
|
||
|
// instantiate spell checker server object
|
||
|
m_pSpellChecker = (*SC_Create_proc)();
|
||
|
if (m_pSpellChecker == NULL)
|
||
|
Fail(SPELL_ERR_CORRUPT);
|
||
|
|
||
|
// initialize the spell checker server
|
||
|
int32 Language = 0;
|
||
|
int32 Dialect = 0;
|
||
|
|
||
|
// First see if any language preferences have been set
|
||
|
PREF_GetIntPref(LanguagePref, &Language);
|
||
|
PREF_GetIntPref(DialectPref, &Dialect);
|
||
|
|
||
|
// If not, get the default language & dialect settings, if any.
|
||
|
if (Language == 0)
|
||
|
GetDefaultLanguage(Language, Dialect);
|
||
|
|
||
|
if ((m_pSpellChecker)->Initialize(Language, Dialect, GetSpellCheckerDir(), GetPersonalDicFilename()))
|
||
|
Fail(SPELL_ERR_CORRUPT);
|
||
|
|
||
|
// Get the text buffer from the document
|
||
|
XP_HUGE_CHAR_PTR pBuf = GetBuffer();
|
||
|
if (pBuf == NULL)
|
||
|
return 0; // nothing to spell check
|
||
|
|
||
|
m_BufferSize = XP_STRLEN(pBuf); // remember the size
|
||
|
|
||
|
// Is there a selection
|
||
|
GetSelection(m_SelStart, m_SelEnd);
|
||
|
|
||
|
// pass text buffer to the spell checker
|
||
|
int retcode = m_pSpellChecker->SetBuf(pBuf, m_SelStart, m_SelEnd);
|
||
|
TRACE1("m_pSpellChecker->SetBuf() returned %d\n", retcode);
|
||
|
|
||
|
// release the buffer (the Spell Checker makes a local copy)
|
||
|
XP_HUGE_FREE(pBuf);
|
||
|
|
||
|
if (retcode != 0)
|
||
|
return -1;
|
||
|
|
||
|
// Remove the Wait cursor, as we are ready to display the dialog box.
|
||
|
WaitCursor.Restore();
|
||
|
|
||
|
// show dialog box
|
||
|
CSpellCheckerDlg Dlg(m_pSpellChecker, this, m_pParentWnd);
|
||
|
int result = Dlg.DoModal() == IDOK ? 0 : -1;
|
||
|
|
||
|
RemoveAllErrorHilites();
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
int CSpellCheckerClient::ReprocessDocument()
|
||
|
{
|
||
|
// Show the Wait cursor.
|
||
|
CWaitCursor WaitCursor;
|
||
|
|
||
|
if (m_pSpellChecker == NULL)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
RemoveAllErrorHilites();
|
||
|
|
||
|
// Get the latest language defaults
|
||
|
int32 Language = 0;
|
||
|
int32 Dialect = 0;
|
||
|
|
||
|
PREF_GetIntPref(LanguagePref, &Language);
|
||
|
PREF_GetIntPref(DialectPref, &Dialect);
|
||
|
|
||
|
if (m_pSpellChecker->SetCurrentLanguage(Language, Dialect) == 0)
|
||
|
{
|
||
|
// Get the text buffer from the document
|
||
|
XP_HUGE_CHAR_PTR pBuf = GetBuffer();
|
||
|
if (pBuf == NULL)
|
||
|
return 0; // nothing to spell check
|
||
|
|
||
|
// If we were spell checking a selection in the previous pass,
|
||
|
// adjust the selection for any corrections made in the last pass.
|
||
|
if (m_SelEnd > 0)
|
||
|
{
|
||
|
m_SelEnd += (XP_STRLEN(pBuf) - m_BufferSize);
|
||
|
}
|
||
|
|
||
|
m_BufferSize = XP_STRLEN(pBuf); // remember the size
|
||
|
|
||
|
// pass text buffer to the spell checker
|
||
|
int retcode = m_pSpellChecker->SetBuf(pBuf, m_SelStart, m_SelEnd);
|
||
|
|
||
|
// release the buffer (the Spell Checker makes a local copy)
|
||
|
XP_HUGE_FREE(pBuf);
|
||
|
|
||
|
if (retcode != 0)
|
||
|
return -1;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CHtmlSpellChecker - HTML document spell checker client object
|
||
|
|
||
|
CHtmlSpellChecker::CHtmlSpellChecker(MWContext *pMWContext, CNetscapeEditView *pHtmlView)
|
||
|
: CSpellCheckerClient(pHtmlView)
|
||
|
{
|
||
|
m_pMWContext = pMWContext;
|
||
|
m_pView = pHtmlView;
|
||
|
}
|
||
|
|
||
|
// Implementation of base class virtuals.
|
||
|
|
||
|
XP_HUGE_CHAR_PTR CHtmlSpellChecker::GetBuffer()
|
||
|
{
|
||
|
// Get the document text
|
||
|
return EDT_GetPositionalText(m_pMWContext);
|
||
|
}
|
||
|
|
||
|
BOOL CHtmlSpellChecker::GetSelection(int32 &SelStart, int32 &SelEnd)
|
||
|
{
|
||
|
char *pSelection;
|
||
|
|
||
|
if ((pSelection = (char *)LO_GetSelectionText(m_pMWContext)) != NULL)
|
||
|
{
|
||
|
XP_FREE(pSelection);
|
||
|
EDT_GetSelectionOffsets(m_pMWContext, &SelStart, &SelEnd);
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
return FALSE; // no selection
|
||
|
}
|
||
|
|
||
|
char *CHtmlSpellChecker::GetFirstError()
|
||
|
{
|
||
|
// turn off refreshing and spell check the text.
|
||
|
EDT_SetRefresh(m_pMWContext, FALSE);
|
||
|
|
||
|
// underline the misspelled words
|
||
|
EDT_CharacterData* pCharData = EDT_NewCharacterData();
|
||
|
pCharData->mask = TF_SPELL;
|
||
|
pCharData->values = TF_SPELL;
|
||
|
|
||
|
unsigned long Offset, Len;
|
||
|
while (m_pSpellChecker->GetNextMisspelledWord(Offset, Len) == 0)
|
||
|
EDT_SetCharacterDataAtOffset(m_pMWContext, pCharData, Offset, Len);
|
||
|
|
||
|
XP_FREE(pCharData);
|
||
|
|
||
|
// set sursor position at the beginning of document so that
|
||
|
// EDT_SelectNextMisspelledWord() to start at the beginning.
|
||
|
EDT_BeginOfDocument(m_pMWContext, FALSE);
|
||
|
EDT_SetRefresh(m_pMWContext, TRUE);
|
||
|
|
||
|
m_pView->UpdateWindow();
|
||
|
|
||
|
// Select and return the first mispelled word
|
||
|
if (EDT_SelectFirstMisspelledWord(m_pMWContext))
|
||
|
return (char *)LO_GetSelectionText(m_pMWContext);
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
char *CHtmlSpellChecker::GetNextError()
|
||
|
{
|
||
|
if (EDT_SelectNextMisspelledWord(m_pMWContext))
|
||
|
return (char *)LO_GetSelectionText(m_pMWContext);
|
||
|
else
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void CHtmlSpellChecker::ReplaceHilitedText(const char *NewText, int AllInstances)
|
||
|
{
|
||
|
char *pOldWord = (char *)LO_GetSelectionText(m_pMWContext);
|
||
|
if (pOldWord != NULL)
|
||
|
{
|
||
|
EDT_ReplaceMisspelledWord(m_pMWContext, pOldWord, (char*)NewText, AllInstances);
|
||
|
XP_FREE(pOldWord);
|
||
|
}
|
||
|
else
|
||
|
ASSERT(FALSE);
|
||
|
}
|
||
|
|
||
|
void CHtmlSpellChecker::IgnoreHilitedText(int AllInstances)
|
||
|
{
|
||
|
char *pOldWord = (char *)LO_GetSelectionText(m_pMWContext);
|
||
|
if (pOldWord != NULL)
|
||
|
{
|
||
|
EDT_IgnoreMisspelledWord(m_pMWContext, pOldWord, AllInstances);
|
||
|
XP_FREE(pOldWord);
|
||
|
}
|
||
|
else
|
||
|
ASSERT(FALSE);
|
||
|
}
|
||
|
|
||
|
void CHtmlSpellChecker::RemoveAllErrorHilites()
|
||
|
{
|
||
|
// ignore any unprocessed misspelled words
|
||
|
EDT_IgnoreMisspelledWord(m_pMWContext, NULL, TRUE);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPlainTextSpellChecker - Plain Text spell checker client object
|
||
|
|
||
|
CPlainTextSpellChecker::CPlainTextSpellChecker(CEdit *pTextView)
|
||
|
: CSpellCheckerClient(pTextView)
|
||
|
{
|
||
|
m_pTextView = pTextView;
|
||
|
}
|
||
|
|
||
|
// Implentation of base class virtuals.
|
||
|
|
||
|
XP_HUGE_CHAR_PTR CPlainTextSpellChecker::GetBuffer()
|
||
|
{
|
||
|
// Get the document text
|
||
|
int32 Length = m_pTextView->GetWindowTextLength();
|
||
|
if (Length == 0)
|
||
|
Length = 1; // return NULL;
|
||
|
|
||
|
XP_HUGE_CHAR_PTR pText = (XP_HUGE_CHAR_PTR) XP_HUGE_ALLOC(Length + 1);
|
||
|
if (pText != NULL)
|
||
|
m_pTextView->GetWindowText(pText, Length + 1);
|
||
|
|
||
|
return pText;
|
||
|
}
|
||
|
|
||
|
BOOL CPlainTextSpellChecker::GetSelection(int32 &SelStart, int32 &SelEnd)
|
||
|
{
|
||
|
// hilight mispelled word
|
||
|
int Start, End;
|
||
|
m_pTextView->GetSel(Start, End);
|
||
|
if (End > Start)
|
||
|
{
|
||
|
SelStart = Start;
|
||
|
SelEnd = End;
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
char *CPlainTextSpellChecker::GetFirstError()
|
||
|
{
|
||
|
return GetNextError();
|
||
|
}
|
||
|
|
||
|
char *CPlainTextSpellChecker::GetNextError()
|
||
|
{
|
||
|
unsigned long Offset, Len;
|
||
|
char *pMisspelledWord = NULL;
|
||
|
|
||
|
if (m_pSpellChecker->GetNextMisspelledWord(Offset, Len) == 0)
|
||
|
{
|
||
|
// hilight mispelled word
|
||
|
m_pTextView->SetSel((int)Offset, (int)(Offset+Len));
|
||
|
m_pTextView->UpdateWindow();
|
||
|
|
||
|
// Extract mispelled word
|
||
|
XP_HUGE_CHAR_PTR pBuf = GetBuffer();
|
||
|
if (pBuf != NULL)
|
||
|
{
|
||
|
pMisspelledWord = (char *)XP_ALLOC(Len + 1);
|
||
|
if (pMisspelledWord != NULL)
|
||
|
XP_STRNCPY_SAFE(pMisspelledWord, (LPCTSTR)pBuf + Offset, Len+1);
|
||
|
|
||
|
XP_HUGE_FREE(pBuf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pMisspelledWord;
|
||
|
}
|
||
|
|
||
|
void CPlainTextSpellChecker::ReplaceHilitedText(const char *NewText, int AllInstances)
|
||
|
{
|
||
|
if (m_pSpellChecker->ReplaceMisspelledWord(NewText, AllInstances) != 0)
|
||
|
ASSERT(FALSE); // maybe display an out of memory error
|
||
|
|
||
|
unsigned long NewBufSize = m_pSpellChecker->GetBufSize();
|
||
|
char *pNewBuf = (char *)XP_ALLOC(NewBufSize);
|
||
|
if (pNewBuf == NULL)
|
||
|
{
|
||
|
ASSERT(FALSE); // maybe display an out of memory error
|
||
|
return;
|
||
|
}
|
||
|
m_pSpellChecker->GetBuf(pNewBuf, NewBufSize);
|
||
|
m_pTextView->SetWindowText(pNewBuf);
|
||
|
XP_FREE(pNewBuf);
|
||
|
}
|
||
|
|
||
|
void CPlainTextSpellChecker::IgnoreHilitedText(int AllInstances)
|
||
|
{
|
||
|
// Unlike the HTML document, there are no error highlights to remove.
|
||
|
// However, if we need to ignore all subsequent instances of the word,
|
||
|
// we need to tell the spell checker to ignore this word.
|
||
|
|
||
|
if (AllInstances)
|
||
|
{
|
||
|
int StartChar, EndChar;
|
||
|
m_pTextView->GetSel(StartChar, EndChar);
|
||
|
|
||
|
CString Buf;
|
||
|
m_pTextView->GetWindowText(Buf);
|
||
|
|
||
|
int OldWordLen = EndChar - StartChar;
|
||
|
CString OldWord;
|
||
|
OldWord.Format("%.*s", OldWordLen, (LPCTSTR)Buf + StartChar);
|
||
|
|
||
|
m_pSpellChecker->IgnoreWord(OldWord);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ShowSpellCheckerError(CWnd *pParentWnd, int ErrorCode)
|
||
|
{
|
||
|
// Resource switcher object: It switches the default resource handle to the
|
||
|
// editorXX.dll, cause that's where the string resources are. The resource
|
||
|
// handle is automatically restored in the destructor.
|
||
|
CEditorResourceSwitcher ResourceSwitcher;
|
||
|
|
||
|
CString Msg, Title;
|
||
|
int MsgId;
|
||
|
|
||
|
switch (ErrorCode)
|
||
|
{
|
||
|
case SPELL_ERR_NOT_INSTALLED:
|
||
|
MsgId = IDS_SPELL_NOT_INSTALLED;
|
||
|
break;
|
||
|
case SPELL_ERR_COULD_NOT_LOAD:
|
||
|
MsgId = IDS_SPELL_COULD_NOT_LOAD;
|
||
|
break;
|
||
|
case SPELL_ERR_INSTANCE_ACTIVE:
|
||
|
MsgId = IDS_SPELL_INSTANCE_ACTIVE;
|
||
|
break;
|
||
|
case SPELL_ERR_CORRUPT:
|
||
|
default:
|
||
|
MsgId = IDS_SPELL_CORRUPT;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Msg.LoadString(MsgId);
|
||
|
Title.LoadString(IDS_CHECK_SPELLING);
|
||
|
pParentWnd->MessageBox(Msg, Title, MB_ICONSTOP | MB_OK);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CPersonalDictionaryDlg dialog
|
||
|
|
||
|
CPersonalDictionaryDlg::CPersonalDictionaryDlg(ISpellChecker *pSpellChecker, CWnd* pParent /*=NULL*/)
|
||
|
: CDialog(IDD, pParent)
|
||
|
{
|
||
|
m_pSpellChecker = pSpellChecker;
|
||
|
}
|
||
|
|
||
|
void CPersonalDictionaryDlg::DoDataExchange(CDataExchange* pDX)
|
||
|
{
|
||
|
CDialog::DoDataExchange(pDX);
|
||
|
//{{AFX_DATA_MAP(CPersonalDictionaryDlg)
|
||
|
DDX_Control(pDX, IDC_WORD_LIST, m_WordList);
|
||
|
//}}AFX_DATA_MAP
|
||
|
}
|
||
|
|
||
|
BOOL CPersonalDictionaryDlg::OnInitDialog()
|
||
|
{
|
||
|
// Don't need the editor resource handle any more. Switch back to the app.
|
||
|
m_DlgResource.Reset();
|
||
|
|
||
|
CDialog::OnInitDialog();
|
||
|
|
||
|
char Word[128];
|
||
|
if (m_pSpellChecker->GetFirstPersonalDictionaryWord(Word, sizeof(Word)) >= 0)
|
||
|
{
|
||
|
do
|
||
|
m_WordList.AddString(Word);
|
||
|
while (m_pSpellChecker->GetNextPersonalDictionaryWord(Word, sizeof(Word)) >= 0);
|
||
|
}
|
||
|
|
||
|
EnableButtons();
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void CPersonalDictionaryDlg::OnOK()
|
||
|
{
|
||
|
m_pSpellChecker->ResetPersonalDictionary();
|
||
|
|
||
|
CString Word;
|
||
|
int Count = m_WordList.GetCount();
|
||
|
|
||
|
for (int Index = 0; Index < Count; Index++)
|
||
|
{
|
||
|
m_WordList.GetText(Index, Word);
|
||
|
ASSERT(Word.GetLength() > 0);
|
||
|
m_pSpellChecker->AddWordToPersonalDictionary(Word);
|
||
|
}
|
||
|
|
||
|
CDialog::OnOK();
|
||
|
}
|
||
|
|
||
|
BEGIN_MESSAGE_MAP(CPersonalDictionaryDlg, CDialog)
|
||
|
ON_BN_CLICKED(IDC_ADD, OnAddWord)
|
||
|
ON_BN_CLICKED(IDC_REPLACE, OnReplaceWord)
|
||
|
ON_BN_CLICKED(IDC_REMOVE, OnRemoveWord)
|
||
|
ON_LBN_SELCHANGE(IDC_WORD_LIST, OnSelChangeWordList)
|
||
|
ON_EN_CHANGE(IDC_NEW_WORD, EnableButtons)
|
||
|
ON_BN_CLICKED(ID_HELP, OnHelp)
|
||
|
#ifdef XP_WIN32
|
||
|
ON_WM_HELPINFO()
|
||
|
#endif //XP_WIN32
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
void CPersonalDictionaryDlg::OnAddWord()
|
||
|
{
|
||
|
CString NewWord;
|
||
|
GetDlgItemText(IDC_NEW_WORD, NewWord);
|
||
|
|
||
|
if (NewWord.IsEmpty())
|
||
|
return;
|
||
|
|
||
|
int Index = m_WordList.FindStringExact(-1, NewWord);
|
||
|
if (Index == LB_ERR)
|
||
|
{
|
||
|
// clear current selection
|
||
|
for (int i = m_WordList.GetCount() - 1; i >= 0; i--)
|
||
|
m_WordList.SetSel(Index, FALSE);
|
||
|
|
||
|
Index = m_WordList.AddString(NewWord);
|
||
|
m_WordList.SetSel(Index, TRUE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CPersonalDictionaryDlg::OnReplaceWord()
|
||
|
{
|
||
|
CString NewWord;
|
||
|
GetDlgItemText(IDC_NEW_WORD, NewWord);
|
||
|
|
||
|
if (NewWord.IsEmpty())
|
||
|
return;
|
||
|
|
||
|
if (m_WordList.GetSelCount() != 1)
|
||
|
return;
|
||
|
|
||
|
OnRemoveWord();
|
||
|
OnAddWord();
|
||
|
}
|
||
|
|
||
|
void CPersonalDictionaryDlg::OnRemoveWord()
|
||
|
{
|
||
|
CString Word;
|
||
|
|
||
|
for (int Index = m_WordList.GetCount() - 1; Index >= 0; Index--)
|
||
|
{
|
||
|
if (m_WordList.GetSel(Index))
|
||
|
m_WordList.DeleteString(Index);
|
||
|
}
|
||
|
|
||
|
EnableButtons();
|
||
|
}
|
||
|
|
||
|
void CPersonalDictionaryDlg::OnSelChangeWordList()
|
||
|
{
|
||
|
if (m_WordList.GetSelCount() == 1)
|
||
|
{
|
||
|
CString Text;
|
||
|
m_WordList.GetText(m_WordList.GetCurSel(), Text);
|
||
|
SetDlgItemText(IDC_NEW_WORD, Text);
|
||
|
}
|
||
|
|
||
|
EnableButtons();
|
||
|
}
|
||
|
|
||
|
void CPersonalDictionaryDlg::EnableButtons()
|
||
|
{
|
||
|
CString NewWord;
|
||
|
GetDlgItemText(IDC_NEW_WORD, NewWord);
|
||
|
|
||
|
BOOL NewWordEmpty = NewWord.IsEmpty();
|
||
|
int SelCount = m_WordList.GetSelCount();
|
||
|
|
||
|
GetDlgItem(IDC_ADD)->EnableWindow(!NewWordEmpty);
|
||
|
GetDlgItem(IDC_REPLACE)->EnableWindow(!NewWordEmpty && SelCount == 1);
|
||
|
GetDlgItem(IDC_REMOVE)->EnableWindow(SelCount > 0);
|
||
|
}
|
||
|
|
||
|
void CPersonalDictionaryDlg::OnHelp()
|
||
|
{
|
||
|
NetHelp(HELP_EDIT_DICTIONARY);
|
||
|
}
|
||
|
|
||
|
// OnHelpInfo - Invokes Help window when F1 key is pressed
|
||
|
#ifdef XP_WIN32
|
||
|
BOOL CPersonalDictionaryDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
|
||
|
{
|
||
|
OnHelp();
|
||
|
return TRUE;
|
||
|
}
|
||
|
#endif//XP_WIN32
|