/** Editor ED - Modul FR: Suchen und Ersetzen **/
#include "top.h"
#ifdef BUILD_FR
#include <windows.h>
#include "ut.h"
#include "res.h"
#ifdef BUILD_RE
#error Die Suche sollte besser mit RICHEDIT-eigener Funktion implementiert werden!
#else
#define MAX_STRING_SIZE 256
HWND fr_hDlg;
static FINDREPLACE fr_dlgStruc;
static TCHAR fr_findStr[MAX_STRING_SIZE], fr_replStr[MAX_STRING_SIZE];
static int fr_findCt, fr_replCt, fr_focusLost;
#ifdef BUILD_FR_PR
/** Function: Besetze Suchmuster in Suchen-Ersetzen-Dialogbox mit markiertem Text vor **/
static void fr_preset(HWND hWinEdit)
{
int selLen;
TCHAR *sel;
if ((sel=ut_getEditSel(hWinEdit, &selLen)) == NULL)
return;
if (selLen >= MAX_STRING_SIZE)
selLen = MAX_STRING_SIZE - 1;
lstrcpyn(fr_findStr, sel, selLen+1); // Im Unterschied zu strncpy kopiert
GlobalFree(sel); // lstrcpyn max. selLen-1 Zeichen, um NUL mitanzuhaengen!
}
#endif
/** Function: Rufe Suchen-Ersetzen-Dialogbox auf **/
HWND fr_dlg(HWND hWnd, BOOL replDlg)
{
// fr_dlg ist nur eine Huelse und kehrt sofort zum Aufrufer zurueck; werden die Buttons betaetigt,
// werden fr_msg-Nachrichten erzeugt, die die eigentlichen Arbeitsfunktionen fr_find*() ansteuern.
// Nachfolgende Aenderungen von Suchoptionen (matchCase etc.) in fr_dlgStruc werden ueber Dialog
// sofort an Variable fr_dlgStruc gegeben, sodass Arbeitsfunktionen immer aktuellen Zustand haben.
fr_findCt = fr_replCt = 0;
#ifdef BUILD_FR_PR
fr_preset(GetDlgItem(hWnd, IDW_WIN_EDIT)); // fr_FindText mit evt. Markierung vorbesetzen
#endif
ZeroMemory(&fr_dlgStruc, sizeof(FINDREPLACE));
fr_dlgStruc.lStructSize = sizeof(FINDREPLACE);
fr_dlgStruc.hwndOwner = hWnd; // Bestimmt, an welches Fenster Nachrichten gesendet werden
fr_dlgStruc.Flags = FR_DOWN | FR_NOUPDOWN; // DOWN voreinstellen und fixieren
fr_dlgStruc.lpstrFindWhat = fr_findStr;
fr_dlgStruc.wFindWhatLen = MAX_STRING_SIZE;
if (replDlg) {
fr_dlgStruc.lpstrReplaceWith = fr_replStr; fr_dlgStruc.wReplaceWithLen = MAX_STRING_SIZE;
return ReplaceText(&fr_dlgStruc);
}
else
return FindText(&fr_dlgStruc); // Dialog aufgerufen; Find/ReplaceText warten Benutzereingaben
// in Suchfelder NICHT ab, sondern kehren sofort mit Rueckgabe von hFindDlg zurueck (moduslos).
}
// fr_find() wird durch den "Suchen"-Knopf im Suchdialog oder im Suchen-Ersetzen-Dialog
// aufgerufen, fr_replace() durch den "Ersetzen"-Knopf im Suchen-Ersetzen-Dialog.
// Beide Routinen bilden ein Gespann:
// fr_find() sucht und markiert Text, fr_replace() ersetzt ihn. fr_repl() muß jedoch intern
// (d.h., ohne, daß Benutzer "Suchen" drückt) manchmal erst fr_find() aufrufen, z.B. beim
// ersten Aufruf des Dialogs, wenn noch kein zu ersetzender Text markiert ist.
/** Function: Suche Suchmuster **/
BOOL fr_find(HWND hWinEdit)
{
int sos, eos, start;
TCHAR *buf, *found;
// Dokument in Puffer kopieren und dort suchen, da es leider kein direktes Find fuer EDIT-Controls
// gibt, wohl aber fuer RICHEDIT! Puffer muss auch jedesmal neu angelegt werden, da bei einem
// moduslosem Dialog der Benutzer Text zwischenzeitlich aendern koennte.
fr_focusLost = 0;
if ((buf=ut_getEditText(hWinEdit,NULL)) == NULL)
return FALSE;
/* Suche Text im Dokument */
SendMessage(hWinEdit, EM_GETSEL, (WPARAM)&sos, (LPARAM)&eos);
start = (sos != eos) ? sos+1 : sos;
found = ut_strstr(buf+start, fr_dlgStruc.lpstrFindWhat, fr_dlgStruc.Flags&FR_MATCHCASE,
fr_dlgStruc.Flags&FR_WHOLEWORD);
if (found)
start = (int)(found - buf); // FIX 1.4: Typecast fuer WIN64
GlobalFree(buf);
if (found == NULL)
return FALSE;
/* Markiere gefundenen Text fuer Benutzer */
SendMessage(hWinEdit, EM_SETSEL, start, start+lstrlen(fr_dlgStruc.lpstrFindWhat));
SendMessage(hWinEdit, EM_SCROLLCARET, 0, 0); // Aktualisiere Fenster, so dass Caret sichtbar wird
++fr_findCt;
return TRUE;
}
/** Function: Ersetze naechstes Suchmuster **/
static BOOL fr_repl(HWND hWinEdit)
{
int sos, eos, selIsValid;
TCHAR *sel;
SendMessage(hWinEdit, EM_GETSEL, (WPARAM)&sos, (LPARAM)&eos);
/* A - FIND muss erst laufen ... */
if (sos == eos) // weil kein Text zur Ersetzung markiert ist oder
return fr_find(hWinEdit);
if (fr_focusLost) { // weil der Benutzer zwischenzeitlich im EDIT-Control war
selIsValid = 0; // und die Markierung nicht mehr stimmen muss
if ((sel=ut_getEditSel(hWinEdit, NULL)) != NULL) {
selIsValid = lstrcmp(sel,fr_dlgStruc.lpstrFindWhat) == 0;
GlobalFree(sel); // Markierung stimmt nicht!
}
if (!selIsValid) {
SendMessage(hWinEdit, EM_SETSEL, sos, sos);
return fr_find(hWinEdit);
}
}
/* B - REPL */
SendMessage(hWinEdit, EM_REPLACESEL, TRUE, (LPARAM)fr_dlgStruc.lpstrReplaceWith);
++fr_replCt;
/* C - FIND markiert (sichtbar für Benutzer) den nächsten zu ersetzenden String */
return fr_find(hWinEdit);
}
/** Function: Ersetze alle Suchmuster **/
static UINT fr_replAll(HWND hWinEdit)
{
fr_findCt = fr_replCt = 0;
SendMessage(hWinEdit, EM_SETSEL, 0, 0);
while (fr_repl(hWinEdit))
;
return fr_replCt;
}
/** Function: Informiere andere Module ueber Suchmuster **/
TCHAR *fr_getFindStr(void)
{
return fr_findStr;
}
/** Function: Dispatcher **/
int fr_dispatch(HWND hWinEdit)
{
// Returns:
// -3 FR_DIALOGTERM
// -2 No more found
// -1 Something found
// 0..n Count of replacements
if (fr_dlgStruc.Flags & FR_DIALOGTERM)
return -3;
else
if (fr_dlgStruc.Flags & FR_FINDNEXT)
return fr_find(hWinEdit) ? -1 : -2;
else
if (fr_dlgStruc.Flags & FR_REPLACE)
return fr_repl(hWinEdit) ? -1 : -2;
else
if (fr_dlgStruc.Flags & FR_REPLACEALL)
return fr_replAll(hWinEdit);
else
return -4; // Unknown
}
/** Function: Informiere FR-Modul, dass Benutzer in das Hauptfenster gewechselt war **/
void fr_setFocusLost(void)
{
fr_focusLost = 1; // fr_repl() fragt spaeter fr_setFocusLost ab und fr_find setzt es zurueck
}
#endif
#endif