home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / mdi / regmpad / mpfind.c < prev    next >
C/C++ Source or Header  |  1995-11-26  |  9KB  |  297 lines

  1. /***************************************************************************
  2.  *                                       *
  3.  *  MODULE    : MpFind.c                           *
  4.  *                                       *
  5.  *  PURPOSE    : Code to do text searches in MultiPad.            *
  6.  *                                       *
  7.  *  FUNCTIONS    : RealSlowCompare () - Compares subject string with target *
  8.  *                       string.                   *
  9.  *                                       *
  10.  *          Local_FindText ()         - Looks for the search string in the  *
  11.  *                       active window.               *
  12.  *                                       *
  13.  *          FindPrev ()         - Find previous occurence of search   *
  14.  *                       string.                   *
  15.  *                                       *
  16.  *          FindNext ()         - Find next occurence of search string*
  17.  *                                       *
  18.  *          FindDlgProc ()     - Dialog function for Search/Find.    *
  19.  *                                       *
  20.  *          Find ()         - Invokes FindDlgProc ()           *
  21.  *                                       *
  22.  ***************************************************************************/
  23. #include "multipad.h"
  24. #include <mbstring.h>
  25.  
  26. #undef HIWORD
  27. #undef LOWORD
  28.  
  29. #define HIWORD(l) (((WORD*)&(l))[1])
  30. #define LOWORD(l) (((WORD*)&(l))[0])
  31.  
  32. BOOL fCase       = FALSE;    /* Turn case sensitivity off */
  33. CHAR szSearch[160] = "";       /* Initialize search string  */
  34.  
  35. //LPSTR WINAPI AnsiLower (LPSTR);
  36.  
  37. /****************************************************************************
  38.  *                                        *
  39.  *  FUNCTION   : RealSlowCompare ()                        *
  40.  *                                        *
  41.  *  PURPOSE    : Compares subject string with the target string. This fn/   *
  42.  *         is called repeatedly so that all substrings are compared,  *
  43.  *         which makes it O(n ** 2), hence it's name.                 *
  44.  *                                        *
  45.  *  RETURNS    : TRUE  - If pSubject is identical to pTarget.            *
  46.  *         FALSE - otherwise.                        *
  47.  *                                        *
  48.  ****************************************************************************/
  49.  
  50. BOOL NEAR PASCAL RealSlowCompare (
  51.     register PSTR pSubject,
  52.     register PSTR pTarget)
  53. {
  54.     if (_mbsncmp(pTarget, pSubject, _mbslen(pTarget)))
  55.       return FALSE;
  56.  
  57.     return TRUE;
  58. }
  59.  
  60. /****************************************************************************
  61.  *                                        *
  62.  *  FUNCTION   : Local_FindText ()                            *
  63.  *                                        *
  64.  *  PURPOSE    : Finds the search string in the active window according to  *
  65.  *         search direction (dch) specified ( -1 for reverse and 1 for*
  66.  *         forward searches).                        *
  67.  *                                        *
  68.  ****************************************************************************/
  69. VOID NEAR PASCAL Local_FindText(register INT dch)
  70. {
  71.     register PSTR pText;
  72.     register PSTR pTextBase;
  73.     HANDLE      hT;
  74.     LONG      l;
  75.     WORD      cch;
  76.     INT       i, DBCSCheck = dch;
  77.  
  78.     if (!*szSearch)
  79.     return;
  80.  
  81.     /* Find the current selection range */
  82.     l = (LONG)SendMessage(hwndActiveEdit, EM_GETSEL, 0, 0);
  83.  
  84.     /* Get the handle to the text buffer and lock it */
  85.     hT      = (HANDLE)SendMessage (hwndActiveEdit, EM_GETHANDLE, 0, 0L);
  86.     pText = LocalLock(hT);
  87.  
  88.     /* Get the length of the text */
  89.     cch = (WORD)SendMessage (hwndActiveEdit, WM_GETTEXTLENGTH, 0, 0L);
  90.  
  91.     /* Start with the next char. in selected range ... */
  92.     pTextBase = pText;
  93.     pText += LOWORD(l);
  94.     if(dch < 0 && LOWORD(l) > 0) { /* if backward search.. */
  95.         pText = CharPrev(pTextBase,pText);
  96.         if(IsDBCSLeadByte((BYTE)*pText)) LOWORD(l)--;
  97.         LOWORD(l)--;
  98.     }
  99.     else if(dch > 0) {
  100.         if(IsDBCSLeadByte((BYTE)*pText)) LOWORD(l)++;
  101.         LOWORD(l)++;
  102.         pText = CharNext(pText);
  103.     }
  104.  
  105.     /* Compute how many characters are before/after the current selection*/
  106.     if (dch < 0) {
  107.         i = LOWORD(l);
  108.         if(IsDBCSLeadByte((BYTE)*pText)) i++;
  109.         if(LOWORD(l)) i++;
  110.     }
  111.     else {
  112.         i = cch - LOWORD(l);
  113.         if(i < lstrlen(szSearch)) i=0;
  114.     }
  115.  
  116.     /* While there are uncompared substrings... */
  117.     while ( i > 0) {
  118.  
  119.     /* Does this substring match? */
  120.     if (RealSlowCompare(pText,szSearch)){
  121.  
  122.         /* Yes, unlock the buffer.*/
  123.         LocalUnlock(hT);
  124.  
  125.         /* Scroll parent edit control */
  126.         SendMessage(hwndActiveEdit, EM_LINESCROLL, 0, 
  127.             SendMessage(hwndActiveEdit, EM_LINEFROMCHAR, LOWORD(l), 0) - 
  128.             SendMessage(hwndActiveEdit, EM_GETFIRSTVISIBLELINE, 0, 0));
  129.  
  130.         /* Select the located string */
  131.         HIWORD(l) = LOWORD(l) + (WORD)lstrlen (szSearch);
  132.         SendMessage(hwndActiveEdit, EM_SETSEL, GET_EM_SETSEL_MPS(LOWORD(l), HIWORD(l)));
  133.         return;
  134.     }
  135.     i--;
  136.  
  137.     /* increment/decrement start position by 1 */
  138.         LOWORD(l) += dch;
  139.         if(dch < 0) {  /* backward search */
  140.             pText = CharPrev(pTextBase,pText);
  141.             if(IsDBCSLeadByte((BYTE)*pText)) {
  142.                 i--;
  143.                 LOWORD(l) += dch;
  144.             }
  145.         }
  146.         else {         /* forward search */
  147.             if(IsDBCSLeadByte((BYTE)*pText)) {
  148.                 i--;
  149.                 LOWORD(l) += dch;
  150.             }
  151.             pText = CharNext(pText);
  152.         }
  153.     }
  154.  
  155.     /* Not found... unlock buffer. */
  156.     LocalUnlock (hT);
  157.  
  158.     /* Give a message */
  159.     MPError (NULL, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
  160.             IDS_CANTFIND, (LPSTR)szSearch);
  161.  
  162.     return;
  163. }
  164.  
  165. /****************************************************************************
  166.  *                                        *
  167.  *  FUNCTION   : FindPrev ()                            *
  168.  *                                        *
  169.  *  PURPOSE    : Finds the previous occurence of the search string. Calls   *
  170.  *         Local_FindText () with a negative search direction.            *
  171.  *                                        *
  172.  ****************************************************************************/
  173. VOID APIENTRY FindPrev()
  174. {
  175.     Local_FindText(-1);
  176. }
  177.  
  178. /****************************************************************************
  179.  *                                        *
  180.  *  FUNCTION   : FindNext ()                            *
  181.  *                                        *
  182.  *  PURPOSE    : Finds the next occurence of search string. Calls        *
  183.  *         Local_FindText () with a positive search direction.            *
  184.  *                                        *
  185.  ****************************************************************************/
  186. VOID APIENTRY FindNext()
  187. {
  188.     Local_FindText(1);
  189. }
  190.  
  191. /****************************************************************************
  192.  *                                        *
  193.  *  FUNCTION   : FindDlgProc(hwnd, message, wParam, lParam)            *
  194.  *                                        *
  195.  *  PURPOSE    : Dialog function for the Search/Find command. Prompts user  *
  196.  *         for target string, case flag and search direction.        *
  197.  *                                        *
  198.  ****************************************************************************/
  199. BOOL APIENTRY FindDlgProc(
  200.     HWND hwnd,
  201.     UINT msg,
  202.     UINT wParam,
  203.     LONG lParam)
  204. {
  205.     switch (msg){
  206.     case WM_INITDIALOG:{
  207.  
  208.         /* Check/uncheck case button */
  209.         CheckDlgButton (hwnd, (int)IDD_CASE, (WORD)fCase);
  210.  
  211.         /* Set default search string to most recently searched string */
  212.         SetDlgItemText (hwnd, IDD_SEARCH, szSearch);
  213.  
  214.         /* Allow search only if target is nonempty */
  215.         if (!lstrlen (szSearch)){
  216.         EnableWindow (GetDlgItem (hwnd, IDOK), FALSE);
  217.         EnableWindow (GetDlgItem (hwnd, IDD_PREV), FALSE);
  218.         }
  219.         break;
  220.     }
  221.  
  222.     case WM_COMMAND:
  223.     {
  224.  
  225.         /* Search forward by default (see IDOK below) */
  226.         INT i = 1;
  227.  
  228.         switch (LOWORD(wParam)){
  229.         /* if the search target becomes non-empty, enable searching */
  230.         case IDD_SEARCH:
  231.             if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE){
  232.             if (!(WORD) SendDlgItemMessage (hwnd,
  233.                             IDD_SEARCH,
  234.                             WM_GETTEXTLENGTH,
  235.                             0,
  236.                             0L))
  237.                 i = FALSE;
  238.             else
  239.                 i = TRUE;
  240.             EnableWindow (GetDlgItem (hwnd, IDOK), i);
  241.             EnableWindow (GetDlgItem (hwnd, IDD_PREV), i);
  242.             }
  243.             break;
  244.  
  245.         case IDD_CASE:
  246.             /* Toggle state of case button */
  247.             CheckDlgButton (hwnd,
  248.                     (int)IDD_CASE,
  249.                     (WORD)!IsDlgButtonChecked (hwnd, (int)IDD_CASE));
  250.             break;
  251.  
  252.         case IDD_PREV:
  253.             /* Set direction to backwards */
  254.             i=-1;
  255.             /*** FALL THRU ***/
  256.  
  257.         case IDOK:
  258.             /* Save case selection */
  259.             fCase = IsDlgButtonChecked( hwnd, IDD_CASE);
  260.  
  261.             /* Get search string */
  262.             GetDlgItemText (hwnd, IDD_SEARCH, szSearch, sizeof (szSearch));
  263.  
  264.             /* Find the text */
  265.             Local_FindText (i);
  266.             /*** FALL THRU ***/
  267.  
  268.         /* End the dialog */
  269.         case IDCANCEL:
  270.             EndDialog (hwnd, 0);
  271.             break;
  272.  
  273.         default:
  274.             return FALSE;
  275.         }
  276.         break;
  277.     }
  278.     default:
  279.         return FALSE;
  280.     }
  281.     return TRUE;
  282.     UNREFERENCED_PARAMETER(lParam);
  283. }
  284.  
  285. /****************************************************************************
  286.  *                                        *
  287.  *  FUNCTION   : Find()                             *
  288.  *                                        *
  289.  *  PURPOSE    : Invokes the Search/Find dialog.                *
  290.  *                                        *
  291.  ****************************************************************************/
  292.  
  293. VOID APIENTRY Find()
  294. {
  295.     DialogBox (hInst, IDD_FIND, hwndFrame, FindDlgProc);
  296. }
  297.