home *** CD-ROM | disk | FTP | other *** search
- // spell.cpp
- // A few functions to demonstrate how to integrate the SPELMATE DLL with ObjectWindows.
- // (c) 1993, Stewart McSporran for Aciran Software Systems
-
- // NB: The tab size for this file is 2
-
- #include <windows.h>
- #include <string.h>
- #include "spelmate.h"
- #include "spell.h"
-
- // spelmate.dll instance
- HINSTANCE hSpellLibrary;
-
- // function prototypes
- BOOL GetWord(PTEdit pEdit, LPSTR lpWord, WORD &Start, WORD &Finish);
- BOOL GetWord(LPSTR lpStr, LPSTR lpWord, WORD &Start, WORD &Finish);
- BOOL ValidChar(char C);
- BOOL LoadSpelmateDLL();
- void UnloadSpelmateDLL();
- void HourGlass(BOOL iOn);
-
-
- //****************** TEdit functions ********************************************
- /*
- Spell : Spell checks the supplied edit control. This version of the
- function always checks the entire text.
- */
- void Spell(PTEdit pEdit)
- {
- BOOL Abort = FALSE;
- int OriginX, OriginY; // location of cursor when spellchecking starts
- char TempWord[MaxWordLen+1]; // holds each word as it is retrieved from the string
- char NewWord[MaxWordLen+1]; // any replacements selected by user
- WORD StartChar = 0; // First char in current word
- WORD FinishChar = 0; // last char of current word
- // load spelmate dll
- if (LoadSpelmateDLL())
- {
- // set cursor to busy
- HourGlass(TRUE);
- // get cursor location
- pEdit->GetSelection(OriginX,OriginY);
- // Extract and check each word
- while (GetWord(pEdit,TempWord,StartChar,FinishChar) && !Abort) // for every word in lpString
- {
- if (!SpellCheck(TempWord)) // word not in any dictionary
- {
- // highlight word
- pEdit->SetSelection(StartChar,FinishChar);
- // Find if text in upper half of screen (NOT trivial!)
- int FirstLine = (int)SendMessage(pEdit->HWindow,EM_GETFIRSTVISIBLELINE,0,0);
- int CurrentLine = pEdit->GetLineFromPos(-1); // -1 gets line selected text is on
- int NoLinesVisible = CurrentLine - FirstLine + 1;
- // get the height of each line
- TEXTMETRIC Tm;
- HDC EditDC = GetDC(pEdit->HWindow);
- GetTextMetrics(EditDC,&Tm);
- ReleaseDC(pEdit->HWindow,EditDC);
- // Now get the distance from the text to the top of the client area
- // The following is not 100% accurate but is good enough for our purposes
- int DistFromMenuBar = Tm.tmHeight * NoLinesVisible;
- // get height of menu bar + title + frame (SM_CYCAPTION does title & frame)
- int NCAHeight = GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYCAPTION);
- // get y co-ord of top of window pEdit belongs to
- int WinY = ((PTWindow)(pEdit->Parent))->Attr.Y;
- // calculate absolute Y location of text
- int TextY = WinY + NCAHeight + DistFromMenuBar;
- // get height of screen
- int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
- // FINALLY! if text in lower half of screen put suggest word dialog at top
- if (TextY > (ScreenHeight /2))
- DisplayAtTop();
- // activate cursor
- HourGlass(FALSE);
- // provide user with list of suggestions
- strcpy(NewWord,SuggestWord(TempWord));
- if (NewWord[0] != 0) // not canceled
- {
- if (lstrcmp(NewWord,TempWord) != 0) // if different word
- {
- // replace TempWord with NewWord.
- // delete old word
- pEdit->DeleteSelection();
- // insert new word
- pEdit->Insert(NewWord);
- // amend FinishChar to point to end of new word
- FinishChar += strlen(NewWord) - strlen(TempWord);
- }
- }
- else
- {
- Abort = TRUE; // finish spell checking (user pressed cancel)
- }
- }// if
- StartChar = ++FinishChar; // point to start on (possibly) next word
- HourGlass(TRUE);
- }// while
- // restore cursor to original place (might not be exact if words have been changed)
- // Uses OriginX twice so that no text is actually selected, just places the cursor
- pEdit->SetSelection(OriginX,OriginX);
- }
- HourGlass(FALSE);
- UnloadSpelmateDLL();
- MessageBox(GetFocus(),"Spell check complete.","Spelling",MB_OK);
- }
-
- // Parse words from an edit control, return true if word found.
- // pEdit : control to be parsed
- // lpWord : on exit contains next word, MUST be of size MaxWordLen.
- // Start : index position in lpStr of first char of lpWord
- // Finish : index position in lpStr of last char of lpWord
- BOOL GetWord(PTEdit pEdit, LPSTR lpWord, WORD &Start, WORD &Finish)
- {
- // Clear contents of lpWord
- _fmemset(lpWord,'\0',MaxWordLen);
- // check for empty lpString
- WORD len = pEdit->GetTextLen();
- if (len == 0) return FALSE;
- // find first character in word, DON'T use ValidChar, want to ignore "'" as first char
- LPSTR Char = new char[2];
- do{
- pEdit->GetSubText(Char,Start,Start + 1);
- Start++;
- }while ((!IsCharAlpha(Char[0])) && (Start < len));
- // if Char[0] = '\0' then string contains no valid words so return FALSE
- if ((Char[0] == '\0') || (Start == len))
- return FALSE;
- else
- Start--; // Position Start to first character. (because of Start++ above)
- // set finish to first character before continuing search
- Finish = Start;
- // Now find last valid char in word
- do{
- pEdit->GetSubText(Char,Finish,Finish + 1);
- Finish++;
- }while (ValidChar(Char[0]) && ((Finish - Start) < MaxWordLen));
- Finish--; // don't want Finish to point to space after the word
- // now extract complete word from edit control into lpWord
- pEdit->GetSubText(lpWord,Start,Finish);
- // if last character in word is "'" remove it
- if (lpWord[lstrlen(lpWord)-1] == '\'')
- {
- lpWord[lstrlen(lpWord)-1] = '\0';
- Finish--;
- }
- // we've got this for so we must have a valid word
- return TRUE;
- }
-
- //****************** String functions ********************************
-
- void Spell(LPSTR lpString)
- {
- char TempWord[MaxWordLen]; // holds each word as it is retrieved from the string
- char NewWord[MaxWordLen]; // any replacements selected by user
- WORD StartChar = 0; // begining of the string (start of current word)
- WORD FinishChar = 0; // end of current word
- // load spelmate dll
- if (LoadSpelmateDLL())
- {
- // spell check string
- // set cursor to busy
- HourGlass(TRUE);
- while (GetWord(lpString,TempWord,StartChar,FinishChar)) // for every word in lpString
- {
- if (!SpellCheck(TempWord)) // word not in any dictionary
- {
- HourGlass(FALSE); // enable cursor again
- // provide user with list of suggestions
- strcpy(NewWord,SuggestWord(TempWord));
- HourGlass(TRUE);
- if (strlen(NewWord) != 0)
- {
- // replace TempWord with NewWord
- LPSTR lpEnd; // temporary string to hold section of lpString after old word
- lpEnd = new char[lstrlen(lpString)];
- // copy all text after the old word into lpEnd
- _fstrcpy(lpEnd,(LPSTR)(lpString + FinishChar+1)); //,lstrlen(lpString)-(FinishChar+1));
- lpString[StartChar] = '\0'; // terminate at start of old word
- // add new word to end of lpString
- _fstrcat(lpString,NewWord);
- // append remainder of lpString to end of new word
- _fstrcat(lpString,lpEnd);
- // amend FinishChar to point to end of new word
- FinishChar += strlen(NewWord) - strlen(TempWord);
- delete lpEnd;
- }
- }// if
- StartChar = ++FinishChar; // point to start on (possibly) next word
- }// while
- HourGlass(FALSE);
- }
- // unload dll (if loaded)
- UnloadSpelmateDLL();
- }
-
-
-
- // Parse words from string, return true if word found.
- // lpStr : string to be parsed
- // lpWord : on exit contains next word, MUST be of size MaxWordLen.
- // Start : index position in lpStr of first char of lpWord
- // Finish : index position in lpStr of last char of lpWord
- BOOL GetWord(LPSTR lpStr, LPSTR lpWord, WORD &Start, WORD &Finish)
- {
- int TempIndex = 0;
- // Clear contents of lpWord
- _fmemset(lpWord,'\0',MaxWordLen);
- // check for empty lpString
- WORD len = lstrlen(lpStr);
- if (len == 0) return FALSE;
- // find first character in word, DON'T use ValidChar, want to ignore "'" as first char
- for (char Char = lpStr[Start];(!IsCharAlpha(Char))&&(Start < len);Char = lpStr[++Start]);
- // if Char = '\0' then string contains no valid words
- if (Char == '\0') return FALSE;
- // read word into temp string
- Finish = Start;
- while (ValidChar(lpStr[Finish]) && (TempIndex < MaxWordLen)){
- lpWord[TempIndex++] = lpStr[Finish++];
- }
- Finish--; // don't want Finish to point to space after the word
- // if last character in word is "'" remove it
- if (lpWord[--TempIndex] == '\'')
- {
- lpWord[TempIndex] = '\0';
- Finish--;
- }
- // we've got this for so we must have a valid word
- return TRUE;
- }
-
- //************************ General purpose functions ***************************
-
- // check if char is an alphabetic character, also
- // allow "'" to be a valid character (for "it's" etc.)
- // and also "-" for hyphenated words
- BOOL ValidChar(char C)
- {
- return ( (IsCharAlpha(C)) || (C == '\'') || (C == '-') );
- }
-
-
- // Loads and initialises the DLL. Returns TRUE if OK, FALSE otherwise
- BOOL LoadSpelmateDLL()
- {
- BOOL Ok = FALSE;
- hSpellLibrary = LoadLibrary("spelmate.dll");
- if((UINT)hSpellLibrary <= 32)
- {
- MessageBeep(MB_ICONHAND);
- MessageBox(NULL, "Unable to load the Spell Checking Dynamic Link Library.\n"
- "Ensure that SPELMATE.DLL is in this applications' directory"
- " or on your DOS path.","Application Error", MB_OK | MB_ICONHAND);
- }
- else
- {
- // initialise the DLL and check for errors
- HourGlass(TRUE);
- int result = SpelmateInit();
- HourGlass(FALSE);
- if (result < 0) // ie. everything ok
- {
- Ok = TRUE;
- }
- else // ie. result >= 0
- {
- // flag error to user
- char lpError[60];
- switch (result){
- case 0 : strcpy(lpError,"Insufficient memory");break;
- case 1 : strcpy(lpError,"Main dictionary not found");break;
- case 2 : strcpy(lpError,"Stream access error, main dictionary");break;
- case 3 : strcpy(lpError,"Initialisation error, main dictionary");break;
- case 4 : strcpy(lpError,"Read error, main dictionary");break;
- case 5 : strcpy(lpError,"Corrupt file or wrong file type error, main dictionary");break;
- case 6 : strcpy(lpError,"Stream access error, private dictionary");break;
- case 7 : strcpy(lpError,"Initialisation error, private dictionary");break;
- case 8 : strcpy(lpError,"Read error, private dictionary");break;
- case 9 : strcpy(lpError,"Corrupt file or wrong file type error, private dictionary");break;
- default: strcpy(lpError,"Unknown error");
- }
- MessageBeep(MB_ICONEXCLAMATION);
- MessageBox(GetFocus(),lpError,"Spell check initialisation error",MB_OK|MB_ICONEXCLAMATION);
- }
- }
- return Ok;
- }
-
- void UnloadSpelmateDLL()
- {
- if((UINT)hSpellLibrary > 32)
- FreeLibrary(hSpellLibrary);
- }
-
-
- // turns hourglass cursor on or off
- void HourGlass(BOOL iOn)
- {
- static HCURSOR hcurSave;
- if (iOn)
- hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
- else
- SetCursor(hcurSave);
- }