home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / QBAS / SPMATE12.ZIP / SPELL.CP$ / spell.cpp
C/C++ Source or Header  |  1993-07-13  |  11KB  |  305 lines

  1. // spell.cpp
  2. // A few functions to demonstrate how to integrate the SPELMATE DLL with ObjectWindows.
  3. // (c) 1993, Stewart McSporran for Aciran Software Systems  
  4.  
  5. // NB: The tab size for this file is 2
  6.  
  7. #include <windows.h>
  8. #include <string.h>
  9. #include "spelmate.h"
  10. #include "spell.h"
  11.  
  12. // spelmate.dll instance
  13. HINSTANCE hSpellLibrary;
  14.  
  15. // function prototypes
  16. BOOL GetWord(PTEdit pEdit, LPSTR lpWord, WORD &Start, WORD &Finish);
  17. BOOL GetWord(LPSTR lpStr, LPSTR lpWord, WORD &Start, WORD &Finish);
  18. BOOL ValidChar(char C);
  19. BOOL LoadSpelmateDLL();
  20. void UnloadSpelmateDLL();
  21. void HourGlass(BOOL iOn);
  22.  
  23.  
  24. //******************  TEdit functions  ********************************************
  25. /*
  26.     Spell : Spell checks the supplied edit control.  This version of the
  27.     function always checks the entire text.
  28. */
  29. void  Spell(PTEdit pEdit)
  30. {
  31.     BOOL Abort = FALSE;
  32.     int  OriginX, OriginY;          // location of cursor when spellchecking starts
  33.     char TempWord[MaxWordLen+1];    // holds each word as it is retrieved from the string
  34.     char NewWord[MaxWordLen+1];     // any replacements selected by user
  35.     WORD StartChar = 0;             // First char in current word
  36.     WORD FinishChar = 0;            // last char of current word
  37.     // load spelmate dll
  38.     if (LoadSpelmateDLL())
  39.     {
  40.         // set cursor to busy
  41.     HourGlass(TRUE);
  42.         //  get cursor location
  43.         pEdit->GetSelection(OriginX,OriginY);
  44.         // Extract and check each word
  45.         while (GetWord(pEdit,TempWord,StartChar,FinishChar) && !Abort)  // for every word in lpString
  46.         {
  47.             if (!SpellCheck(TempWord))  // word not in any dictionary
  48.             {
  49.                 // highlight word
  50.                 pEdit->SetSelection(StartChar,FinishChar);
  51.                 // Find if text in upper half of screen (NOT trivial!)
  52.                 int FirstLine = (int)SendMessage(pEdit->HWindow,EM_GETFIRSTVISIBLELINE,0,0);
  53.                 int CurrentLine = pEdit->GetLineFromPos(-1);  // -1 gets line selected text is on
  54.                 int NoLinesVisible = CurrentLine - FirstLine + 1;
  55.         // get the height of each line
  56.                 TEXTMETRIC Tm;
  57.                 HDC EditDC = GetDC(pEdit->HWindow);
  58.                 GetTextMetrics(EditDC,&Tm);
  59.                 ReleaseDC(pEdit->HWindow,EditDC);
  60.         // Now get the distance from the text to the top of the client area
  61.         // The following is not 100% accurate but is good enough for our purposes
  62.                 int DistFromMenuBar = Tm.tmHeight * NoLinesVisible;
  63.         // get height of menu bar + title + frame (SM_CYCAPTION does title & frame)
  64.                 int NCAHeight = GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYCAPTION);
  65.                 // get y co-ord of top of window pEdit belongs to
  66.                 int WinY = ((PTWindow)(pEdit->Parent))->Attr.Y;
  67.                 // calculate absolute Y location of text
  68.         int TextY = WinY + NCAHeight + DistFromMenuBar;
  69.                 // get height of screen
  70.                 int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
  71.                 // FINALLY! if text in lower half of screen put suggest word dialog at top
  72.                 if (TextY > (ScreenHeight /2))
  73.             DisplayAtTop();
  74.                 // activate cursor
  75.         HourGlass(FALSE);
  76.                 // provide user with list of suggestions
  77.                 strcpy(NewWord,SuggestWord(TempWord));
  78.                 if (NewWord[0] != 0)    // not canceled
  79.                 {
  80.                     if (lstrcmp(NewWord,TempWord) != 0)  // if different word
  81.                     {
  82.                         // replace TempWord with NewWord.
  83.                         // delete old word
  84.                         pEdit->DeleteSelection();
  85.                         // insert new word
  86.                         pEdit->Insert(NewWord);
  87.                         // amend FinishChar to point to end of new word
  88.                         FinishChar += strlen(NewWord) - strlen(TempWord);
  89.                     }
  90.                 }
  91.                 else
  92.                 {
  93.                     Abort = TRUE;   // finish spell checking (user pressed cancel)
  94.                 }
  95.             }// if
  96.             StartChar = ++FinishChar;  // point to start on (possibly) next word
  97.       HourGlass(TRUE);
  98.         }// while
  99.         // restore cursor to original place (might not be exact if words have been changed)
  100.         // Uses OriginX twice so that no text is actually selected, just places the cursor
  101.         pEdit->SetSelection(OriginX,OriginX);
  102.     }
  103.   HourGlass(FALSE);
  104.     UnloadSpelmateDLL();
  105.     MessageBox(GetFocus(),"Spell check complete.","Spelling",MB_OK);
  106. }
  107.  
  108. // Parse words from an edit control, return true if word found.
  109. // pEdit : control to be parsed
  110. // lpWord : on exit contains next word, MUST be of size MaxWordLen.
  111. // Start : index position in lpStr of first char of lpWord
  112. // Finish : index position in lpStr of last char of lpWord
  113. BOOL GetWord(PTEdit pEdit, LPSTR lpWord, WORD &Start, WORD &Finish)
  114. {
  115.     // Clear contents of lpWord
  116.     _fmemset(lpWord,'\0',MaxWordLen);
  117.     // check for empty lpString
  118.     WORD len = pEdit->GetTextLen();
  119.     if (len == 0) return FALSE;
  120.     // find first character in word, DON'T use ValidChar, want to ignore "'" as first char
  121.     LPSTR Char = new char[2];
  122.     do{
  123.         pEdit->GetSubText(Char,Start,Start + 1);
  124.         Start++;
  125.     }while ((!IsCharAlpha(Char[0])) && (Start < len));
  126.     // if Char[0] = '\0' then string contains no valid words so return FALSE
  127.     if ((Char[0] == '\0') || (Start == len))
  128.         return FALSE;
  129.     else
  130.         Start--;    //  Position Start to first character.  (because of Start++ above)
  131.     // set finish to first character before continuing search 
  132.     Finish = Start;
  133.     // Now find last valid char in word
  134.     do{
  135.         pEdit->GetSubText(Char,Finish,Finish + 1);
  136.         Finish++;
  137.     }while (ValidChar(Char[0]) && ((Finish - Start) < MaxWordLen));
  138.     Finish--;  // don't want Finish to point to space after the word
  139.     // now extract complete word from edit control into lpWord
  140.     pEdit->GetSubText(lpWord,Start,Finish);
  141.     // if last character in word is "'" remove it
  142.     if (lpWord[lstrlen(lpWord)-1] == '\'')
  143.     {
  144.         lpWord[lstrlen(lpWord)-1] = '\0';
  145.         Finish--;
  146.     }
  147.     // we've got this for so we must have a valid word
  148.     return TRUE;
  149. }
  150.  
  151. //******************  String functions ********************************
  152.  
  153. void  Spell(LPSTR lpString)
  154. {
  155.     char TempWord[MaxWordLen];    // holds each word as it is retrieved from the string
  156.     char NewWord[MaxWordLen];     // any replacements selected by user
  157.     WORD StartChar = 0;           // begining of the string  (start of current word)
  158.     WORD FinishChar = 0;          // end of current word
  159.     // load spelmate dll
  160.     if (LoadSpelmateDLL())
  161.     {
  162.         // spell check string
  163.         // set cursor to busy
  164.     HourGlass(TRUE);
  165.         while (GetWord(lpString,TempWord,StartChar,FinishChar))  // for every word in lpString
  166.         {
  167.             if (!SpellCheck(TempWord))  // word not in any dictionary
  168.             {
  169.         HourGlass(FALSE);   // enable cursor again
  170.                 // provide user with list of suggestions
  171.                 strcpy(NewWord,SuggestWord(TempWord));
  172.         HourGlass(TRUE);
  173.                 if (strlen(NewWord) != 0)
  174.                 {
  175.                     // replace TempWord with NewWord
  176.                     LPSTR lpEnd;  // temporary string to hold section of lpString after old word
  177.                     lpEnd = new char[lstrlen(lpString)];
  178.                     // copy all text after the old word into lpEnd
  179.                     _fstrcpy(lpEnd,(LPSTR)(lpString + FinishChar+1)); //,lstrlen(lpString)-(FinishChar+1));
  180.                     lpString[StartChar] = '\0';   // terminate at start of old word
  181.                     // add new word to end of lpString
  182.                     _fstrcat(lpString,NewWord);
  183.                     // append remainder of lpString to end of new word
  184.                     _fstrcat(lpString,lpEnd);
  185.                     // amend FinishChar to point to end of new word
  186.                     FinishChar += strlen(NewWord) - strlen(TempWord);
  187.                     delete lpEnd;
  188.                 }
  189.             }// if
  190.             StartChar = ++FinishChar;  // point to start on (possibly) next word
  191.         }// while
  192.     HourGlass(FALSE);
  193.     }
  194.     // unload dll (if loaded)
  195.     UnloadSpelmateDLL();
  196. }
  197.  
  198.  
  199.  
  200. // Parse words from string, return true if word found.
  201. // lpStr : string to be parsed
  202. // lpWord : on exit contains next word, MUST be of size MaxWordLen.
  203. // Start : index position in lpStr of first char of lpWord
  204. // Finish : index position in lpStr of last char of lpWord
  205. BOOL GetWord(LPSTR lpStr, LPSTR lpWord, WORD &Start, WORD &Finish)
  206. {
  207.     int  TempIndex = 0;
  208.     // Clear contents of lpWord
  209.     _fmemset(lpWord,'\0',MaxWordLen);
  210.     // check for empty lpString
  211.     WORD len = lstrlen(lpStr);
  212.     if (len == 0) return FALSE;
  213.     // find first character in word, DON'T use ValidChar, want to ignore "'" as first char
  214.     for (char Char = lpStr[Start];(!IsCharAlpha(Char))&&(Start < len);Char = lpStr[++Start]);
  215.     // if Char = '\0' then string contains no valid words
  216.     if (Char == '\0') return FALSE;
  217.     // read word into temp string
  218.     Finish = Start;
  219.     while (ValidChar(lpStr[Finish]) && (TempIndex < MaxWordLen)){
  220.         lpWord[TempIndex++] = lpStr[Finish++];
  221.     }
  222.     Finish--;  // don't want Finish to point to space after the word
  223.     // if last character in word is "'" remove it
  224.     if (lpWord[--TempIndex] == '\'')
  225.     {
  226.         lpWord[TempIndex] = '\0';
  227.         Finish--;
  228.     }
  229.     // we've got this for so we must have a valid word
  230.     return TRUE;
  231. }
  232.  
  233. //************************  General purpose functions ***************************
  234.  
  235. // check if char is an alphabetic character, also
  236. // allow "'" to be a valid character (for "it's" etc.)
  237. // and also "-" for hyphenated words
  238. BOOL ValidChar(char C)
  239. {
  240.     return ( (IsCharAlpha(C)) || (C == '\'') || (C == '-') );
  241. }
  242.  
  243.  
  244. // Loads and initialises the DLL.  Returns TRUE if OK, FALSE otherwise
  245. BOOL LoadSpelmateDLL()
  246. {
  247.     BOOL Ok = FALSE;
  248.     hSpellLibrary = LoadLibrary("spelmate.dll");
  249.     if((UINT)hSpellLibrary <= 32)
  250.     {
  251.         MessageBeep(MB_ICONHAND);
  252.         MessageBox(NULL, "Unable to load the Spell Checking Dynamic Link Library.\n"
  253.                                          "Ensure that SPELMATE.DLL is in this applications' directory"
  254.                                          " or on your DOS path.","Application Error", MB_OK | MB_ICONHAND);
  255.     }
  256.     else
  257.     {
  258.         // initialise the DLL and check for errors
  259.     HourGlass(TRUE);
  260.         int result = SpelmateInit();
  261.     HourGlass(FALSE);
  262.         if (result < 0)  // ie. everything ok
  263.         {
  264.             Ok = TRUE;
  265.         }
  266.         else  // ie. result >= 0
  267.         {
  268.             // flag error to user
  269.             char lpError[60];
  270.             switch (result){
  271.                 case 0 : strcpy(lpError,"Insufficient memory");break;
  272.                 case 1 : strcpy(lpError,"Main dictionary not found");break;
  273.                 case 2 : strcpy(lpError,"Stream access error, main dictionary");break;
  274.                 case 3 : strcpy(lpError,"Initialisation error, main dictionary");break;
  275.                 case 4 : strcpy(lpError,"Read error, main dictionary");break;
  276.                 case 5 : strcpy(lpError,"Corrupt file or wrong file type error, main dictionary");break;
  277.                 case 6 : strcpy(lpError,"Stream access error, private dictionary");break;
  278.                 case 7 : strcpy(lpError,"Initialisation error, private dictionary");break;
  279.                 case 8 : strcpy(lpError,"Read error, private dictionary");break;
  280.                 case 9 : strcpy(lpError,"Corrupt file or wrong file type error, private dictionary");break;
  281.                 default: strcpy(lpError,"Unknown error");
  282.             }
  283.             MessageBeep(MB_ICONEXCLAMATION);
  284.             MessageBox(GetFocus(),lpError,"Spell check initialisation error",MB_OK|MB_ICONEXCLAMATION);
  285.         }
  286.     }
  287.     return Ok;
  288. }
  289.  
  290. void UnloadSpelmateDLL()
  291. {
  292.     if((UINT)hSpellLibrary > 32)
  293.         FreeLibrary(hSpellLibrary);
  294. }
  295.  
  296.  
  297. // turns hourglass cursor on or off
  298. void HourGlass(BOOL iOn)
  299. {
  300.     static HCURSOR hcurSave;
  301.   if (iOn)
  302.         hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  303.     else
  304.         SetCursor(hcurSave);
  305. }