home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK8 / MFC / SAMPLES / MULTIPAD / MPFIND.CP$ / mpfind
Encoding:
Text File  |  1992-03-16  |  5.9 KB  |  236 lines

  1. // mpfind.cpp : Defines the class behaviors for the text searches.
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and Microsoft
  9. // QuickHelp documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "multipad.h"
  14. #include "ctype.h" // for _tolower
  15.  
  16. #pragma code_seg("_MPFIND")
  17.  
  18. // HIWORD and LOWORD as defined are not able to be used as lvalues, so
  19. // "HIWORD(dwVar) = 0xFFFF" are normally impossible.  These macros allow it.
  20. //
  21. #undef HIWORD
  22. #undef LOWORD
  23. #define HIWORD(l) (((WORD*)&(l))[1])
  24. #define LOWORD(l) (((WORD*)&(l))[0])
  25.  
  26. ///////////////////////////////////////////////////////////////////////////
  27. // Search dialog stuff
  28. UINT CMPFrame::m_nMsgFind = ::RegisterWindowMessage(FINDMSGSTRING);
  29. CFindReplaceDialog* CMPFrame::m_pFindReplace = NULL;
  30. CString CMPFrame::m_strFind;
  31. static BOOL bMatchCase = FALSE;
  32.  
  33. LONG
  34. CMPFrame::CmdFindHelper(UINT wParam, LONG lParam)
  35. {
  36.     CFindReplaceDialog* pDlgFR = CFindReplaceDialog::GetNotifier(lParam);
  37.     ASSERT(pDlgFR == m_pFindReplace);
  38.  
  39.     if (pDlgFR->IsTerminating())
  40.     {
  41.         SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  42.         m_pFindReplace = NULL;  // DO NOT DELETE, DONE AUTOMATICALLY
  43.  
  44.         GetMenu()->EnableMenuItem(IDM_SEARCHFIND, MF_ENABLED);
  45.         if (m_strFind.GetLength() > 0)
  46.         {
  47.             GetMenu()->EnableMenuItem(IDM_SEARCHNEXT, MF_ENABLED);
  48.             GetMenu()->EnableMenuItem(IDM_SEARCHPREV, MF_ENABLED);
  49.         }
  50.     }
  51.     else
  52.     {
  53.         ASSERT(m_pActiveChild != NULL);
  54.  
  55.         // look for string
  56.         m_strFind = m_pFindReplace->GetFindString();
  57.         if (m_strFind.GetLength() == 0)
  58.             return 0;
  59.  
  60.         if (m_pActiveChild->FindText(m_strFind,
  61.             m_pFindReplace->SearchDown() ? 
  62.                     CMPChild::searchDown : CMPChild::searchUp,
  63.             bMatchCase = m_pFindReplace->MatchCase()) == FALSE)
  64.         {
  65.             MPError(MB_OK|MB_ICONEXCLAMATION, IDS_CANTFIND, (LPCSTR)m_strFind);
  66.         }
  67.         else
  68.         {
  69.             GetMenu()->EnableMenuItem(IDM_SEARCHNEXT, MF_ENABLED);
  70.             GetMenu()->EnableMenuItem(IDM_SEARCHPREV, MF_ENABLED);
  71.             SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  72.         }
  73.     }
  74.     return 0;
  75. }
  76.  
  77. // CmdFind:
  78. // Invoke the search dialog.  Returns when the dialog is closed by the user.
  79. //
  80. void CMPFrame::CmdFind()
  81. {
  82.     ASSERT(m_pFindReplace == NULL);
  83.  
  84.     m_pFindReplace = new CFindReplaceDialog;
  85.     if (m_pFindReplace->Create(TRUE, m_strFind, NULL,
  86.             FR_HIDEWHOLEWORD | FR_DOWN) == FALSE)
  87.     {
  88.         delete m_pFindReplace;
  89.         m_pFindReplace = NULL;
  90.         return;
  91.     }
  92.     GetMenu()->EnableMenuItem(IDM_SEARCHFIND, MF_GRAYED);
  93. }
  94.  
  95. // CmdFindPrev:
  96. //
  97. void CMPFrame::CmdFindPrev(void)
  98. {
  99.     ASSERT(m_strFind.GetLength() != 0);
  100.     ASSERT(m_pActiveChild != NULL);
  101.  
  102.     if (m_pActiveChild->FindText(m_strFind, CMPChild::searchUp,
  103.             bMatchCase) == FALSE)
  104.         MPError(MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPCSTR)m_strFind);
  105.     else
  106.         SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  107. }
  108.  
  109. // CmdFindNext:
  110. //
  111. void CMPFrame::CmdFindNext(void)
  112. {
  113.     ASSERT(m_strFind.GetLength() != 0);
  114.     ASSERT(m_pActiveChild != NULL);
  115.  
  116.     if (m_pActiveChild->FindText(m_strFind, CMPChild::searchDown,
  117.             bMatchCase) == FALSE)
  118.         MPError(MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPCSTR)m_strFind);
  119.     else
  120.         SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  121. }
  122.  
  123. /////////////////////////////////////////////////////////////////////////////
  124. // Search Engine code
  125. // This code is the workhorse code to search through the text buffer looking
  126. // for a particular substring.
  127.  
  128. // RealSlowCompare:
  129. // This is the brute-force method, which leaves a lot to be desired in
  130. // performance.  However, this works fine for the typical text-file-sized
  131. // buffer, which is currently limited by Windows to 32Kb anyway.
  132. //
  133. BOOL NEAR PASCAL RealSlowCompare(PSTR pSubject, LPSTR pTarget, 
  134.         BOOL fCase = FALSE)
  135. {
  136.     if (fCase)
  137.     {
  138.         while (*pTarget)
  139.         {
  140.             if (*pTarget++ != *pSubject++)
  141.                 return FALSE;
  142.         }
  143.     }
  144.     else
  145.     {
  146.         // If case-insensitive, convert both subject and target
  147.         // to lowercase before comparing.
  148.         //
  149.         while (*pTarget)
  150.         {
  151.             if (::AnsiLower((LPSTR)(DWORD)*pTarget++) != 
  152.                 ::AnsiLower((LPSTR)(DWORD)*pSubject++))
  153.                 return FALSE;
  154.         }
  155.     }
  156.     return TRUE;
  157. }
  158.  
  159. // FindText:
  160. // Takes the szSearch buffer and tries to find it in the text buffer.
  161. // The nDirection may be 1 for forward searches or -1 for backward searches.
  162. //
  163. BOOL CMPChild::FindText(LPCSTR lpszSearch, 
  164.         int nDirection /* = searchDown */, 
  165.         BOOL bMatchCase /* = FALSE */,
  166.         BOOL bWholeWord /* = FALSE */)
  167. {
  168.     PSTR pText;
  169.     HANDLE hText;
  170.     LONG lSel;
  171.     UINT cch;
  172.     int i;
  173.     
  174.     if (*lpszSearch == '\0')
  175.         return TRUE;
  176.     
  177.     // Find the current selection range.
  178.     //
  179.     lSel = m_edit.GetSel();
  180.     
  181.     // Get the handle to the text buffer and lock it.
  182.     //
  183.     hText = m_edit.GetHandle();
  184.     pText = (PSTR)LocalLock(hText);
  185.     
  186.     // Get the length of the text.
  187.     //
  188.     cch = m_edit.GetWindowTextLength();
  189.     
  190.     // Start with the next char in selected range.
  191.     //
  192.     pText += LOWORD(lSel) + nDirection;
  193.     
  194.     // Compute how many characters are before/after the current selection.
  195.     //
  196.     if (nDirection < 0)
  197.         i = LOWORD(lSel);
  198.     else
  199.         i = cch - LOWORD(lSel) + 1 - lstrlen(lpszSearch);
  200.     
  201.     // While there are uncompared substrings.
  202.     //
  203.     while (i > 0)
  204.     {
  205.         LOWORD(lSel) += nDirection;
  206.     
  207.         // Does this substring match?
  208.         //
  209.         if (RealSlowCompare(pText, (LPSTR)lpszSearch, bMatchCase))
  210.         {
  211.             // Unlock the buffer.
  212.             //
  213.             LocalUnlock(hText);
  214.             
  215.             // Select the located string.
  216.             //
  217.             HIWORD(lSel) = LOWORD(lSel) + lstrlen(lpszSearch);
  218.             m_edit.SetSel(lSel);
  219.             return TRUE;
  220.         }
  221.         i--;
  222.         
  223.         // Increment/decrement start position.
  224.         //
  225.         pText += nDirection;
  226.     }
  227.     
  228.     // Not found... unlock buffer.
  229.     //
  230.     LocalUnlock(hText);
  231.     
  232.     return FALSE;
  233. }
  234.  
  235.  
  236.