home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 19.ddi / SAMPLES / PENPAD / PPFIND.C_ / PPFIND.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  9.2 KB  |  275 lines

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