[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    [PATCH] KEdFind / KEdReplace from koffice to kdelibs
From:       Mickael Marchand <m.marcha () alemtid ! asso ! fr>
Date:       2001-11-18 0:08:11
[Download RAW message or body]

Hello,

->what is it:
here is a the patch for the new KEdFind / KEdReplace dialogs for kdelibs
this is an import of KOffice's one written by S.R. Haque.
it adds internal regexp and find/replace functions but breaks compatibility 
with old KEdFind and KEdReplace :/
i have done a patch to kedit to give you an example of what that can do or 
just look to kword and kspread's find dialog.

->how it works : 
you have two class , KEdFind and KEdFindNext, the first one is the dialog you 
see when you press 'find' which asks for the text to search, regexp, options 
... the second class is invoked after the execution of  KEdFind, creating if 
necessary a 'Find Next' message box and doing all the find stuff .
It provides a 'highlight' signal which allows you to implement highlighting 
of the searched text in your text editor.
replace works the same way, but gives you two signals 'highlight' and 
'replace' to update the replaced text in the editor.

->problems:
The patch breaks khtml (as it has its own regexp stuff, but this can be 
easily fixed i think) in kdelibs and maybe kwrite/kate in kdebase (haven't 
tested yet)

i don't commit it for now as it will break some apps,
let me know what you think about it and what i should do of it ;p

Cheers,
Mik

PS : i've tested most of the functions but it may still contain some 
bugs...tell me! 

-- 
Mickael Marchand
Elève-ingénieur / Engineer Student 
Ecole des Mines de Douai - France

["kedit.patch" (text/x-diff)]

Index: kedit.cpp
===================================================================
RCS file: /home/kde/kdeutils/kedit/kedit.cpp,v
retrieving revision 1.153
diff -u -3 -p -r1.153 kedit.cpp
--- kedit.cpp	2001/10/19 23:29:34	1.153
+++ kedit.cpp	2001/11/17 23:09:01
@@ -198,7 +198,7 @@ void TopLevel::setupActions()
     KStdAction::paste(this, SLOT(paste()), actionCollection());
     KStdAction::selectAll(this, SLOT(select_all()), actionCollection());
     KStdAction::find(this, SLOT(search()), actionCollection());
-    KStdAction::findNext(this, SLOT(search_again()), actionCollection());
+//    KStdAction::findNext(this, SLOT(search_again()), actionCollection());
     KStdAction::replace(this, SLOT(replace()), actionCollection());
 
     (void)new KAction(i18n("&Insert File"), 0, this, SLOT(file_insert()),
@@ -896,11 +896,11 @@ void TopLevel::toggleStatusBar()
 }
 
 
-void TopLevel::search_again()
+/*void TopLevel::search_again()
 {
   eframe->repeatSearch();
   statusbar_slot();
-}
+}*/
 
 
 void TopLevel::setFileCaption()
Index: kedit.h
===================================================================
RCS file: /home/kde/kdeutils/kedit/kedit.h,v
retrieving revision 1.61
diff -u -3 -p -r1.61 kedit.h
--- kedit.h	2001/10/14 04:16:55	1.61
+++ kedit.h	2001/11/17 23:09:01
@@ -193,7 +193,7 @@ public slots:
     void replace();
     void toggleStatusBar();
     void toggleToolBar();
-    void search_again();
+//    void search_again();
     void toggle_overwrite();
     void writeSettings();
 

["kdeui.patch" (text/x-diff)]

Index: Makefile.am
===================================================================
RCS file: /home/kde/kdelibs/kdeui/Makefile.am,v
retrieving revision 1.248
diff -u -3 -p -r1.248 Makefile.am
--- Makefile.am	2001/11/17 17:13:10	1.248
+++ Makefile.am	2001/11/17 23:41:55
@@ -57,7 +57,7 @@ include_HEADERS = kprogress.h kcolordlg.
 		kpanelapplet.h kpushbutton.h kdcopactionproxy.h kcolorcombo.h \
 		kpanelextension.h kcompletionbox.h ksqueezedtextlabel.h \
 		kcommand.h kwindowlistmenu.h kfontcombo.h kaccelgen.h ktip.h \
-		kdatewidget.h karrowbutton.h kguiitem.h
+		kdatewidget.h karrowbutton.h kguiitem.h kedfind.h kedreplace.h
 
 # the order of the sources isn't randomly (at least not completly).
 # the order is predictated by the use of X11 header files
@@ -95,7 +95,7 @@ libkdeui_la_SOURCES = \
 		kcompletionbox.cpp ksqueezedtextlabel.cpp kcmodule.cpp \
 		kcommand.cpp kwindowlistmenu.cpp kfontcombo.cpp ktip.cpp \
 		kdatewidget.cpp karrowbutton.cpp kmainwindowiface.cpp \
-                kmainwindowiface.skel kguiitem.cpp
+				kmainwindowiface.skel kguiitem.cpp kedfind.cpp kedreplace.cpp
 
 noinst_HEADERS = kdockwidget_private.h klistviewlineedit.h kkeybutton.h \
 		kdialogbase_priv.h kaboutdialog_private.h kcursor_private.h \
Index: kedfind.cpp
===================================================================
RCS file: kedfind.cpp
diff -N kedfind.cpp
--- /dev/null	Tue May  5 20:32:27 1998
+++ kedfind.cpp	Sat Nov 17 23:42:04 2001
@@ -0,0 +1,615 @@
+/*
+    Copyright (C) 2001, S.R.Haque <srhaque@iee.org>.
+    This file is part of the KDE project
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpopupmenu.h>
+#include <qpushbutton.h>
+#include <qregexp.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kedfind.h>
+#include <kmessagebox.h>
+
+KEdFind::KEdFind(QWidget *parent, const char *name, long options, const QStringList \
&findStrings, bool hasSelection) : +    KDialogBase(parent, name, true, i18n("Find \
Text"), Ok | Cancel, Ok) +{
+    init(false, findStrings, hasSelection);
+    setOptions(options);
+}
+
+KEdFind::KEdFind(QWidget *parent, const char *name, bool /*forReplace*/) :
+    KDialogBase(parent, name, true, i18n("Replace Text"), Ok | Cancel, Ok)
+{
+}
+
+KEdFind::~KEdFind()
+{
+}
+
+QWidget *KEdFind::findExtension()
+{
+    return m_findExtension;
+}
+
+QStringList KEdFind::findHistory() const
+{
+    return m_find->historyItems();
+}
+
+void KEdFind::init(bool forReplace, const QStringList &findStrings, bool \
hasSelection) +{
+    QVBoxLayout *topLayout;
+    QGridLayout *optionsLayout;
+
+    // Create common parts of dialog.
+    QWidget *page = new QWidget(this);
+    setMainWidget(page);
+
+    topLayout = new QVBoxLayout(page);
+    topLayout->setSpacing( KDialog::spacingHint() );
+    topLayout->setMargin( KDialog::marginHint() );
+
+    m_findGrp = new QGroupBox(0, Qt::Vertical, i18n("Find"), page);
+    m_findGrp->layout()->setSpacing(KDialog::spacingHint());
+    m_findGrp->layout()->setMargin(KDialog::marginHint());
+    m_findLayout = new QGridLayout(m_findGrp->layout());
+    m_findLayout->setSpacing( KDialog::spacingHint() );
+    m_findLayout->setMargin( KDialog::marginHint() );
+
+    m_findLabel = new QLabel(i18n("&Text To Find"), m_findGrp);
+    m_find = new KHistoryCombo(true, m_findGrp);
+    m_find->setMaxCount(10);
+    m_find->setDuplicatesEnabled(false);
+    m_regExp = new QCheckBox(i18n("Use Patterns"), m_findGrp);
+    m_regExpItem = new QPushButton(i18n("Insert Pattern"), m_findGrp);
+    m_regExpItem->setEnabled(false);
+    m_findExtension = new QWidget(m_findGrp);
+
+    m_findLayout->addWidget(m_findLabel, 0, 0);
+    m_findLayout->addMultiCellWidget(m_find, 1, 1, 0, 1);
+    m_findLayout->addWidget(m_regExp, 2, 0);
+    m_findLayout->addWidget(m_regExpItem, 2, 1);
+    m_findLayout->addMultiCellWidget(m_findExtension, 3, 3, 0, 1);
+    topLayout->addWidget(m_findGrp);
+
+    m_replaceGrp = new QGroupBox(0, Qt::Vertical, i18n("Replace With"), page);
+    m_replaceGrp->layout()->setSpacing(KDialog::spacingHint());
+    m_replaceGrp->layout()->setMargin(KDialog::marginHint());
+    m_replaceLayout = new QGridLayout(m_replaceGrp->layout());
+    m_replaceLayout->setSpacing( KDialog::spacingHint() );
+    m_replaceLayout->setMargin( KDialog::marginHint() );
+
+    m_replaceLabel = new QLabel(i18n("&Replacement Text"), m_replaceGrp);
+    m_replace = new KHistoryCombo(true, m_replaceGrp);
+    m_replace->setMaxCount(10);
+    m_replace->setDuplicatesEnabled(false);
+    m_backRef = new QCheckBox(i18n("&Use Placeholders"), m_replaceGrp);
+    m_backRefItem = new QPushButton(i18n("Insert Placeholder"), m_replaceGrp);
+    m_backRefItem->setEnabled(false);
+    m_replaceExtension = new QWidget(m_replaceGrp);
+
+    m_replaceLayout->addWidget(m_replaceLabel, 0, 0);
+    m_replaceLayout->addMultiCellWidget(m_replace, 1, 1, 0, 1);
+    m_replaceLayout->addWidget(m_backRef, 2, 0);
+    m_replaceLayout->addWidget(m_backRefItem, 2, 1);
+    m_replaceLayout->addMultiCellWidget(m_replaceExtension, 3, 3, 0, 1);
+    topLayout->addWidget(m_replaceGrp);
+
+    m_optionGrp = new QGroupBox(0, Qt::Vertical, i18n("Options"), page);
+    m_optionGrp->layout()->setSpacing(KDialog::spacingHint());
+    m_optionGrp->layout()->setMargin(KDialog::marginHint());
+    optionsLayout = new QGridLayout(m_optionGrp->layout());
+    optionsLayout->setSpacing( KDialog::spacingHint() );
+    optionsLayout->setMargin( KDialog::marginHint() );
+
+    m_caseSensitive = new QCheckBox(i18n("C&ase Sensitive"), m_optionGrp);
+    m_wholeWordsOnly = new QCheckBox(i18n("&Whole Words Only"), m_optionGrp);
+    m_fromCursor = new QCheckBox(i18n("&From Cursor"), m_optionGrp);
+    m_findBackwards = new QCheckBox(i18n("Find &Backwards"), m_optionGrp);
+    m_selectedText = new QCheckBox(i18n("&Selected Text"), m_optionGrp);
+    setHasSelection( hasSelection );
+    m_promptOnReplace = new QCheckBox(i18n("&Prompt On Replace"), m_optionGrp);
+    m_promptOnReplace->setChecked( true );
+
+    optionsLayout->addWidget(m_caseSensitive, 0, 0);
+    optionsLayout->addWidget(m_wholeWordsOnly, 1, 0);
+    optionsLayout->addWidget(m_fromCursor, 2, 0);
+    optionsLayout->addWidget(m_findBackwards, 0, 1);
+    optionsLayout->addWidget(m_selectedText, 1, 1);
+    optionsLayout->addWidget(m_promptOnReplace, 2, 1);
+    topLayout->addWidget(m_optionGrp);
+
+    // We delay creation of these until needed.
+    m_patterns = 0L;
+    m_placeholders = 0L;
+
+    // signals and slots connections
+    connect(m_selectedText, SIGNAL(toggled(bool)), this, \
SLOT(slotSelectedTextToggled(bool))); +    connect(m_regExp, SIGNAL(toggled(bool)), \
m_regExpItem, SLOT(setEnabled(bool))); +    connect(m_backRef, SIGNAL(toggled(bool)), \
m_backRefItem, SLOT(setEnabled(bool))); +    connect(m_regExpItem, SIGNAL(pressed()), \
this, SLOT(showPatterns())); +    connect(m_backRefItem, SIGNAL(pressed()), this, \
SLOT(showPlaceholders())); +
+    connect(m_find, SIGNAL(textChanged ( const QString & )),this, \
SLOT(textSearchChanged( const QString & ))); +
+    // tab order
+    setTabOrder(m_find, m_regExp);
+    setTabOrder(m_regExp, m_regExpItem);
+    setTabOrder(m_regExpItem, m_replace);
+    setTabOrder(m_replace, m_backRef);
+    setTabOrder(m_backRef, m_backRefItem);
+    setTabOrder(m_backRefItem, m_caseSensitive);
+    setTabOrder(m_caseSensitive, m_wholeWordsOnly);
+    setTabOrder(m_wholeWordsOnly, m_fromCursor);
+    setTabOrder(m_fromCursor, m_findBackwards);
+    setTabOrder(m_findBackwards, m_selectedText);
+    setTabOrder(m_selectedText, m_promptOnReplace);
+
+    // buddies
+    m_findLabel->setBuddy(m_find);
+    m_replaceLabel->setBuddy(m_replace);
+
+    if (!forReplace)
+    {
+        m_promptOnReplace->hide();
+        m_replaceGrp->hide();
+    }
+    setFindHistory(findStrings);
+    m_find->setFocus();
+    enableButtonOK( !getText().isEmpty() );
+}
+
+void KEdFind::textSearchChanged( const QString & text)
+{
+    enableButtonOK( !text.isEmpty() );
+}
+
+long KEdFind::options() const
+{
+    long options = 0;
+
+    if (m_caseSensitive->isChecked())
+        options |= CaseSensitive;
+    if (m_wholeWordsOnly->isChecked())
+        options |= WholeWordsOnly;
+    if (m_fromCursor->isChecked())
+        options |= FromCursor;
+    if (m_findBackwards->isChecked())
+        options |= FindBackwards;
+    if (m_selectedText->isChecked())
+        options |= SelectedText;
+    if (m_regExp->isChecked())
+        options |= RegularExpression;
+    return options;
+}
+
+QString KEdFind::getText() const
+{
+    return m_find->currentText();
+}
+
+void KEdFind::setText(QString string)
+{
+	m_find->setEditText(string);
+}
+
+void KEdFind::setCaseSensitive (bool cs)
+{
+	if (m_caseSensitive) m_caseSensitive->setChecked (cs);
+}
+
+void KEdFind::setDirection (bool d)
+{
+	if (m_findBackwards) m_findBackwards->setChecked (d);
+}
+
+bool KEdFind::case_sensitive () const
+{
+	return (m_caseSensitive ? m_caseSensitive->isChecked() : false);
+}
+
+bool KEdFind::get_direction () const
+{
+	return (m_findBackwards ? m_findBackwards->isChecked() : false);
+}
+
+void KEdFind::setFindHistory(const QStringList &strings)
+{
+    if (strings.count() > 0)
+    {
+        m_find->setHistoryItems(strings, true);
+        m_find->lineEdit()->setText( strings.first() );
+        m_find->lineEdit()->selectAll();
+    }
+    else
+        m_find->clearHistory();
+}
+
+void KEdFind::setHasSelection(bool hasSelection)
+{
+    m_selectedText->setEnabled( hasSelection );
+    // If we have a selection, we make 'find in selection' default
+    // and if we don't, then the option has to be unchecked, obviously.
+    m_selectedText->setChecked( hasSelection );
+    slotSelectedTextToggled( hasSelection );
+}
+
+void KEdFind::slotSelectedTextToggled(bool selec)
+{
+    // From cursor doesn't make sense if we have a selection
+    m_fromCursor->setEnabled( !selec );
+    if ( selec ) // uncheck if disabled
+        m_fromCursor->setChecked( false );
+}
+
+void KEdFind::setOptions(long options)
+{
+    m_caseSensitive->setChecked(options & CaseSensitive);
+    m_wholeWordsOnly->setChecked(options & WholeWordsOnly);
+    m_fromCursor->setChecked(options & FromCursor);
+    m_findBackwards->setChecked(options & FindBackwards);
+    m_selectedText->setChecked(options & SelectedText);
+    m_regExp->setChecked(options & RegularExpression);
+}
+
+// Create a popup menu with a list of regular expression terms, to help the user
+// compose a regular expression search pattern.
+void KEdFind::showPatterns()
+{
+    typedef struct
+    {
+        const char *description;
+        const char *regExp;
+        int cursorAdjustment;
+    } term;
+    static const term items[] =
+    {
+        { I18N_NOOP("Any Character"),                 ".",        0 },
+        { I18N_NOOP("Start of Line"),                 "^",        0 },
+        { I18N_NOOP("End of Line"),                   "$",        0 },
+        { I18N_NOOP("Set of Characters"),             "[]",       -1 },
+        { I18N_NOOP("Repeats, zero or more times"),   "*",        0 },
+        { I18N_NOOP("Repeats, one or more times"),    "+",        0 },
+        { I18N_NOOP("Optional"),                      "?",        0 },
+        { I18N_NOOP("Escape"),                        "\\",       0 },
+        { I18N_NOOP("TAB"),                           "\\t",      0 },
+        { I18N_NOOP("NL"),                            "\\n",      0 },
+        { I18N_NOOP("CR"),                            "\\r",      0 },
+        { I18N_NOOP("White Space"),                   "\\s",      0 },
+        { I18N_NOOP("Digit"),                         "\\d",      0 },
+        { I18N_NOOP("Unicode point"),                 "\x0000",   0 },
+        { I18N_NOOP("ASCII/Latin-1 character"),       "\000",     0 }
+    };
+    int i;
+
+    // Populate the popup menu.
+    if (!m_patterns)
+    {
+        m_patterns = new QPopupMenu(this);
+        for (i = 0; (unsigned)i < sizeof(items) / sizeof(items[0]); i++)
+        {
+            m_patterns->insertItem(i18n(items[i].description), i, i);
+        }
+    }
+
+    // Insert the selection into the edit control.
+    i = m_patterns->exec(QCursor::pos());
+    if (i != -1)
+    {
+        QLineEdit *editor = m_find->lineEdit();
+
+        editor->insert(items[i].regExp);
+        editor->setCursorPosition(editor->cursorPosition() + \
items[i].cursorAdjustment); +    }
+}
+
+// Create a popup menu with a list of backreference terms, to help the user
+// compose a regular expression replacement pattern.
+void KEdFind::showPlaceholders()
+{
+    typedef struct
+    {
+        const char *description;
+        const char *backRef;
+    } term;
+    static const term items[] =
+    {
+        { I18N_NOOP("Complete text found"),             "/0" },
+    };
+    int i;
+
+    // Populate the popup menu.
+    if (!m_placeholders)
+    {
+        m_placeholders = new QPopupMenu(this);
+        for (i = 0; (unsigned)i < sizeof(items) / sizeof(items[0]); i++)
+        {
+            m_placeholders->insertItem(i18n(items[i].description), i, i);
+        }
+    }
+
+    // Insert the selection into the edit control.
+    i = m_placeholders->exec(QCursor::pos());
+    if (i != -1)
+    {
+        QLineEdit *editor = m_replace->lineEdit();
+
+        editor->insert(items[i].backRef);
+    }
+}
+
+void KEdFind::slotOk()
+{
+    // Nothing to find?
+    if (getText().isEmpty())
+    {
+        KMessageBox::error(this, i18n("You must enter some text to search for."));
+        return;
+    }
+
+    if (m_regExp->isChecked())
+    {
+        // Check for a valid regular expression.
+        QRegExp regExp(getText());
+
+        if (!regExp.isValid())
+        {
+            KMessageBox::error(this, i18n("Invalid regular expression."));
+            return;
+        }
+    }
+    m_find->addToHistory(getText());
+    emit okClicked();
+    accept();
+}
+
+// Create the dialog.
+KEdFindNext::KEdFindNext(const QString &pattern, long options, QWidget *parent) :
+    KDialogBase(parent, __FILE__, false,  // non-modal!
+        i18n("Find"),
+        User1 | Close,
+        User1,
+        false,
+        i18n("&Yes"))
+{
+    setMainWidget( new QLabel( i18n("Find next '%1'").arg(pattern), this ) );
+
+    m_cancelled = false;
+    m_options = options;
+    m_parent = parent;
+    m_matches = 0;
+    if (m_options & KEdFind::RegularExpression)
+        m_regExp = new QRegExp(pattern, m_options & KEdFind::CaseSensitive);
+    else
+        m_pattern = pattern;
+    resize(minimumSize());
+}
+
+KEdFindNext::~KEdFindNext()
+{
+    if (!m_matches && !m_cancelled)
+        KMessageBox::information(m_parent, i18n("No match was found."));
+}
+
+void KEdFindNext::slotClose()
+{
+    m_cancelled = true;
+    kapp->exit_loop();
+}
+
+void KEdFindNext::abort()
+{
+    slotClose();
+}
+
+bool KEdFindNext::find(const QString &text, const QRect &expose)
+{
+    if (m_options & KEdFind::FindBackwards)
+    {
+        m_index = text.length();
+    }
+    else
+    {
+        m_index = 0;
+    }
+    m_text = text;
+    m_expose = expose;
+    do
+    {
+        // Find the next match.
+        if (m_options & KEdFind::RegularExpression)
+            m_index = KEdFindNext::find(m_text, *m_regExp, m_index, m_options, \
&m_matchedLength); +        else
+            m_index = KEdFindNext::find(m_text, m_pattern, m_index, m_options, \
&m_matchedLength); +        if (m_index != -1)
+        {
+            // Tell the world about the match we found, in case someone wants to
+            // highlight it.
+            emit highlight(m_text, m_index, m_matchedLength, m_expose, m_options);
+            show();
+            kapp->enter_loop();
+        }
+    }
+    while ((m_index != -1) && !m_cancelled);
+
+    // Should the user continue?
+    return !m_cancelled;
+}
+
+int KEdFindNext::find(const QString &text, const QString &pattern, int index, long \
options, int *matchedLength) +{
+    // Handle regular expressions in the appropriate way.
+    if (options & KEdFind::RegularExpression)
+    {
+        QRegExp regExp(pattern, options & KEdFind::CaseSensitive);
+
+        return find(text, regExp, index, options, matchedLength);
+    }
+
+    bool caseSensitive = (options & KEdFind::CaseSensitive);
+
+    if (options & KEdFind::WholeWordsOnly)
+    {
+        if (options & KEdFind::FindBackwards)
+        {
+            // Backward search, until the beginning of the line...
+            while (index >= 0)
+            {
+                // ...find the next match.
+                index = text.findRev(pattern, index, caseSensitive);
+                if (index == -1)
+                    break;
+
+                // Is the match delimited correctly?
+                *matchedLength = pattern.length();
+                if (isWholeWords(text, index, *matchedLength))
+                    break;
+                index--;
+            }
+        }
+        else
+        {
+            // Forward search, until the end of the line...
+            while (index < (int)text.length())
+            {
+                // ...find the next match.
+                index = text.find(pattern, index, caseSensitive);
+                if (index == -1)
+                    break;
+
+                // Is the match delimited correctly?
+                *matchedLength = pattern.length();
+                if (isWholeWords(text, index, *matchedLength))
+                    break;
+                index++;
+            }
+        }
+    }
+    else
+    {
+        // Non-whole-word search.
+        if (options & KEdFind::FindBackwards)
+        {
+            index = text.findRev(pattern, index, caseSensitive);
+        }
+        else
+        {
+            index = text.find(pattern, index, caseSensitive);
+        }
+        if (index != -1)
+        {
+            *matchedLength = pattern.length();
+        }
+    }
+    return index;
+}
+
+int KEdFindNext::find(const QString &text, const QRegExp &pattern, int index, long \
options, int *matchedLength) +{
+    if (options & KEdFind::WholeWordsOnly)
+    {
+        if (options & KEdFind::FindBackwards)
+        {
+            // Backward search, until the beginning of the line...
+            while (index >= 0)
+            {
+                // ...find the next match.
+                index = text.findRev(pattern, index);
+                if (index == -1)
+                    break;
+
+                // Is the match delimited correctly?
+                pattern.match(text, index, matchedLength, false);
+                if (isWholeWords(text, index, *matchedLength))
+                    break;
+                index--;
+            }
+        }
+        else
+        {
+            // Forward search, until the end of the line...
+            while (index < (int)text.length())
+            {
+                // ...find the next match.
+                index = text.find(pattern, index);
+                if (index == -1)
+                    break;
+
+                // Is the match delimited correctly?
+                pattern.match(text, index, matchedLength, false);
+                if (isWholeWords(text, index, *matchedLength))
+                    break;
+                index++;
+            }
+        }
+    }
+    else
+    {
+        // Non-whole-word search.
+        if (options & KEdFind::FindBackwards)
+        {
+            index = text.findRev(pattern, index);
+        }
+        else
+        {
+            index = text.find(pattern, index);
+        }
+        if (index != -1)
+        {
+            pattern.match(text, index, matchedLength, false);
+        }
+    }
+    return index;
+}
+
+bool KEdFindNext::isInWord(QChar ch)
+{
+    return ch.isLetter() || ch.isDigit() || ch == '_';
+}
+
+bool KEdFindNext::isWholeWords(const QString &text, int starts, int matchedLength)
+{
+    if ((starts == 0) || (!isInWord(text[starts - 1])))
+    {
+        int ends = starts + matchedLength;
+
+        if ((ends == (int)text.length()) || (!isInWord(text[ends])))
+            return true;
+    }
+    return false;
+}
+
+// Yes.
+void KEdFindNext::slotUser1()
+{
+    m_matches++;
+    if (m_options & KEdFind::FindBackwards)
+        m_index--;
+    else
+        m_index++;
+    kapp->exit_loop();
+}
+
+#include "kedfind.moc"
Index: kedfind.h
===================================================================
RCS file: kedfind.h
diff -N kedfind.h
--- /dev/null	Tue May  5 20:32:27 1998
+++ kedfind.h	Sat Nov 17 23:42:06 2001
@@ -0,0 +1,347 @@
+/*
+    Copyright (C) 2001, S.R.Haque <srhaque@iee.org>.
+    This file is part of the KDE project
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#ifndef KEDFIND_H
+#define KEDFIND_H
+
+#include <kdialogbase.h>
+
+class KHistoryCombo;
+class QCheckBox;
+class QGroupBox;
+class QLabel;
+class QPopupMenu;
+class QPushButton;
+class QRect;
+class QGridLayout;
+
+/**
+ * @short A generic "find" widget.
+ *
+ * @author S.R.Haque <srhaque@iee.org>
+ *
+ * @sect Detail
+ *
+ * This widget inherits from @ref KDialogBase and implements
+ * the following additional functionalities:  a find string
+ * object and an area for a user-defined widget to extend the dialog.
+ *
+ * @sect Example
+ *
+ * To use the basic find dialog:
+ *
+ * <pre>
+ *  KEdFind dlg(....)
+ *  if ( dlg.exec() != QDialog::Accepted )
+ *      return;
+ *
+ *  // proceed with KEdFindNext from here
+ * </pre>
+ *
+ * To use your own extensions:
+ *
+ * <pre>
+ * </pre>
+ */
+
+class KEdFind:
+    public KDialogBase
+{
+    Q_OBJECT
+
+public:
+
+    // Options.
+
+    typedef enum
+    {
+        WholeWordsOnly = 1,     // Match whole words only.
+        FromCursor = 2,         // Start from current cursor position.
+        SelectedText = 4,       // Only search selected area.
+        CaseSensitive = 8,      // Consider case when matching.
+        FindBackwards = 16,     // Go backwards.
+        RegularExpression = 32, // Interpret the pattern as a regular expression.
+        // User extensions can use boolean options above this value.
+        MinimumUserOption = 65536
+    } Options;
+
+    /**
+     * Construct a find dialog with a parent object and a name.
+     *
+     * @param parent The parent object of this widget.
+     * @param name The name of this widget.
+     * @param options A bitfield of the @ref Options to be enabled.
+     * @param findStrings The find history, @see findHistory()
+     * @param hasSelection Whether a selection exists
+     */
+    KEdFind( QWidget *parent = 0, const char *name = 0, long options = 0,
+                  const QStringList &findStrings = QStringList(), bool hasSelection \
= true ); +
+    /**
+     * Destructor.
+     */
+    virtual ~KEdFind();
+
+    /**
+     * Provide the list of @p strings to be displayed as the history
+     * of find strings. @p strings might get truncated if it is
+     * too long.
+     *
+     * @param history The find history.
+     * @see #findHistory
+     */
+    void setFindHistory( const QStringList &strings );
+
+    /**
+     * Returns the list of history items.
+     *
+     * @see #setFindHistory
+     */
+    QStringList findHistory() const;
+
+    /**
+     * Enable/disable the 'search in selection' option, depending
+     * on whether there actually is a selection.
+     *
+     * @param hasSelection true if a selection exists
+     */
+    void setHasSelection( bool hasSelection );
+
+    /**
+     * Set the options which are enabled.
+     *
+     * @param options The setting of the @ref Options.
+     */
+    void setOptions( long options );
+
+    /**
+     * Returns the state of the options. Disabled options may be returned in
+     * an indeterminate state.
+     *
+     * @see #setOptions
+     */
+    long options() const;
+
+    /**
+     * Returns the pattern to find.
+     */
+    QString getText() const;
+
+    /**
+     * Returns an empty widget which the user may fill with additional UI
+     * elements as required. The widget occupies the width of the dialog,
+     * and is positioned immediately below the regular expression support
+     * widgets for the pattern string.
+     */
+    QWidget *findExtension();
+
+	/**
+	 * Backwards compatibility functions
+	 */
+	
+    void setText(QString string);
+    void setCaseSensitive( bool b );
+    bool case_sensitive() const;
+    void setDirection( bool b );
+    bool get_direction() const;
+
+
+signals:
+
+    /**
+     * The OK button was pressed, the pattern was not empty, and if it is
+     * supposed to be a regular expression, it is known to be valid.
+     */
+    void okClicked();
+
+protected slots:
+
+    void slotOk();
+    void slotSelectedTextToggled(bool);
+    void showPatterns();
+    void showPlaceholders();
+    void textSearchChanged( const QString &);
+private:
+
+    QGroupBox *m_findGrp;
+    QLabel *m_findLabel;
+    KHistoryCombo *m_find;
+    QCheckBox *m_regExp;
+    QPushButton *m_regExpItem;
+    QGridLayout *m_findLayout;
+    QWidget *m_findExtension;
+
+    QGroupBox *m_optionGrp;
+    QCheckBox *m_wholeWordsOnly;
+    QCheckBox *m_fromCursor;
+    QCheckBox *m_selectedText;
+    QCheckBox *m_caseSensitive;
+    QCheckBox *m_findBackwards;
+
+    QPopupMenu *m_patterns;
+
+    // Our dirty little secret is that we also implement the "replace" dialog. But \
we +    // keep that fact hidden from all but our friends.
+
+    friend class KEdReplace;
+
+    /**
+     * Construct a find dialog with a parent object and a name. This version of the
+     * constructor is for use by friends only!
+     *
+     * @param forReplace Is this a replace dialog?
+     */
+    KEdFind( QWidget *parent, const char *name, bool forReplace );
+    void init( bool forReplace, const QStringList &findStrings, bool hasSelection );
+
+    QGroupBox *m_replaceGrp;
+    QLabel *m_replaceLabel;
+    KHistoryCombo *m_replace;
+    QCheckBox* m_backRef;
+    QPushButton* m_backRefItem;
+    QGridLayout *m_replaceLayout;
+    QWidget *m_replaceExtension;
+
+    QCheckBox* m_promptOnReplace;
+
+    QPopupMenu *m_placeholders;
+
+    // Binary compatible extensibility.
+    class KEdFindPrivate;
+    KEdFindPrivate *d;
+};
+
+/**
+ * @short A generic implementation of the "find" function.
+ *
+ * @author S.R.Haque <srhaque@iee.org>
+ *
+ * @sect Detail
+ *
+ * This class includes prompt handling etc. Also provides some
+ * static functions which can be used to create custom behaviour
+ * instead of using the class directly.
+ *
+ * @sect Example
+ *
+ * To use the class to implement a complete find feature:
+ *
+ * <pre>
+ *
+ *  // This creates a find-next-prompt dialog if needed.
+ *  dialog = new KEdFindNext(find, options);
+ *
+ *  // Connect signals to code which handles highlighting
+ *  // of found text.
+ *  connect(dialog, SIGNAL( highlight( const QString &, int, int, const QRect & ) ),
+ *          this, SLOT( highlight( const QString &, int, int, const QRect & ) ) );
+ *
+ *  // Loop over all the text fragments of our document or selection
+ *  for (text chosen by option SelectedText and in a direction set by FindBackwards)
+ *       // don't forget to honour FromCursor too
+ *  {
+ *      // Let KEdFindNext inspect the text fragment, and display a dialog if a \
match is found + *      if ( !dialog->find( text_fragment, region_to_expose ) )
+ *          break; // if cancelled by user
+ *  }
+ *  delete dialog;
+ *
+ * </pre>
+ */
+
+class KEdFindNext :
+    public KDialogBase
+{
+    Q_OBJECT
+
+public:
+
+    // Will create a prompt dialog and use it as needed.
+    KEdFindNext(const QString &pattern, long options, QWidget *parent = 0);
+    ~KEdFindNext();
+
+    /**
+     * Walk the text fragment (e.g. kwrite line, kspread cell) looking for matches.
+     * For each match, emits the expose() signal and displays the find-again dialog
+     * proceeding.
+     *
+     * @param text The text fragment to modify.
+     * @param expose The region to expose
+     * @return false if the user elected to discontinue the find.
+     */
+    bool find(const QString &text, const QRect &expose);
+
+    /**
+     * Search the given string, and returns whether a match was found. If one is,
+     * the length of the string matched is also returned.
+     *
+     * A performance optimised version of the function is provided for use
+     * with regular expressions.
+     *
+     * @param text The string to search.
+     * @param pattern The pattern to look for.
+     * @param index The starting index into the string.
+     * @param options. The options to use.
+     * @return The index at which a match was found, or -1 if no match was found.
+     */
+    static int find( const QString &text, const QString &pattern, int index, long \
options, int *matchedlength ); +    static int find( const QString &text, const \
QRegExp &pattern, int index, long options, int *matchedlength ); +
+    /**
+     * Abort the current find process. Call this when the parent widget
+     * is getting destroyed.
+     */
+    void abort();
+
+	
+	
+signals:
+
+    // Connect to this signal to implement highlighting of found text during the \
find +    // operation.
+    void highlight(const QString &text, int matchingIndex, int matchedLength, const \
QRect &expose, long options); +
+private:
+
+    QString m_pattern;
+    QRegExp *m_regExp;
+    long m_options;
+    QWidget *m_parent;
+    unsigned m_matches;
+    QString m_text;
+    int m_index;
+    QRect m_expose;
+    int m_matchedLength;
+    bool m_cancelled;
+
+    static bool isInWord( QChar ch );
+    static bool isWholeWords( const QString &text, int starts, int matchedLength );
+
+    // Binary compatible extensibility.
+    class KEdFindNextPrivate;
+    KEdFindNextPrivate *d;
+
+private slots:
+
+    virtual void slotUser1();   // Yes
+    virtual void slotClose();
+};
+
+#endif
Index: keditcl.h
===================================================================
RCS file: /home/kde/kdelibs/kdeui/keditcl.h,v
retrieving revision 1.51
diff -u -3 -p -r1.51 keditcl.h
--- keditcl.h	2001/10/12 17:06:28	1.51
+++ keditcl.h	2001/11/17 23:42:10
@@ -23,7 +23,10 @@
 
 #include <qmultilineedit.h>
 #include <qstring.h>
+#include <qstringlist.h>
 #include <kdialogbase.h>
+#include <kedfind.h>
+#include <kedreplace.h>
 
 class QDropEvent;
 class QPushButton;
@@ -34,6 +37,8 @@ class QTextStream;
 class KHistoryCombo;
 class KIntNumInput;
 class QVButtonGroup;
+class KEdFind;
+class KEdReplace;
 
 class KEdGotoLine : public KDialogBase
 {
@@ -53,109 +58,6 @@ private:
     KEdGotoLinePrivate *d;
 };
 
-///
-class KEdFind : public KDialogBase
-{
-    Q_OBJECT
-    Q_PROPERTY( QString text READ getText WRITE setText )
-    Q_PROPERTY( bool caseSensitivity READ case_sensitive WRITE setCaseSensitive )
-    Q_PROPERTY( bool direction READ get_direction WRITE setDirection )
-public:
-
-    KEdFind( QWidget *parent = 0, const char *name=0, bool modal=true);
-    ~KEdFind();
-
-    QString getText() const;
-    void setText(QString string);
-    void setCaseSensitive( bool b );
-    bool case_sensitive() const;
-    void setDirection( bool b );
-    bool get_direction() const;
-
-    /**
-     * @returns the combobox containing the history of searches. Can be used
-     * to save and restore the history.
-     */
-    KHistoryCombo *searchCombo() const;
-
-protected slots:
-    void slotCancel( void );
-    void slotUser1( void );
-    void textSearchChanged ( const QString & );
-
-protected:
-  QVButtonGroup* group;
-
-private:
-    QCheckBox *sensitive;
-    QCheckBox *direction;
-    QLineEdit *value; // FIXME: remove, unused
-
-    class KEdFindPrivate;
-    KEdFindPrivate *d;
-    virtual void done(int i ) { KDialogBase::done(i); }
-
-signals:
-
-    void search();
-    void done();
-};
-
-///
-class KEdReplace : public KDialogBase
-{
-    Q_OBJECT
-
-public:
-
-    KEdReplace ( QWidget *parent = 0, const char *name=0, bool modal=true );
-    ~KEdReplace();
-
-    QString 	getText();
-    QString 	getReplaceText();
-    void 	setText(QString);
-
-    /**
-     * @returns the combobox containing the history of searches. Can be used
-     * to save and restore the history.
-     */
-    KHistoryCombo *searchCombo() const;
-
-    /**
-     * @returns the combobox containing the history of replaces. Can be used
-     * to save and restore the history.
-     */
-    KHistoryCombo *replaceCombo() const;
-
-    QLineEdit 	*value; // FIXME: remove, unused
-    QLineEdit 	*replace_value; // FIXME: remove, unused
-    bool 	case_sensitive();
-    bool 	get_direction();
-
-protected slots:
-    void slotCancel( void );
-    void slotClose( void );
-    void slotUser1( void );
-    void slotUser2( void );
-    void slotUser3( void );
-    void textSearchChanged ( const QString & );
-
-private:
-    QCheckBox 	*sensitive;
-    QCheckBox 	*direction;
-
-    class KEdReplacePrivate;
-    KEdReplacePrivate *d;
-	virtual void done(int i ) { KDialogBase::done(i); }
-
-signals:
-    void replace();
-    void find();
-    void replaceAll();
-    void done();
-};
-
-
 /**
  * A simple text editor for the KDE project.
  *
@@ -175,13 +77,6 @@ public:
     ~KEdit();
 
     /**
-     * Search directions.
-     * @internal
-     **/
-    enum { NONE,
-	   FORWARD,
-	   BACKWARD };
-    /**
      * Insert text from the text stream into the edit widget.
      **/
     void insertText(QTextStream *);
@@ -208,16 +103,6 @@ public:
     void 	search();
 
     /**
-     * Repeat the last search specified on the search dialog.
-     *
-     *  If the user hasn't searched for anything until now, this method
-     *   will simply return without doing anything.
-     *
-     * @return @p true if a search was done. @p false if no search was done.
-     **/
-    bool 	repeatSearch();
-
-    /**
      * Present a Search and Replace Dialog to the user.
      **/
     void 	replace();
@@ -329,37 +214,6 @@ private slots:
        **/
     void misspelling (QString word, QStringList *, unsigned pos);
 
-      /**
-       * @internal
-       * Called from search dialog.
-       **/
-    void search_slot();
-
-      /**
-       * @internal
-       **/
-    void searchdone_slot();
-
-      /**
-       * @internal
-       **/
-    void replace_slot();
-
-      /**
-       * @internal
-       **/
-    void replace_all_slot();
-
-      /**
-       * @internal
-       **/
-    void replace_search_slot();
-
-      /**
-       * @internal
-       **/
-    void replacedone_slot();
-
     void computePosition();
 
       /**
@@ -367,14 +221,28 @@ private slots:
        **/
     void repaintAll();
 
+protected slots:
+			/**
+			 * Called by search when the pattern is found
+			 */
+		virtual void highlight( const QString &, int, int, const QRect &, long );
+		
+			/**
+			 * Called by the FindNext window when ok is pressed
+			 */
+		virtual void FindNextOk ();
+			
+			/*
+			 * Called by the FindNext window when close is pressed
+			 */
+		virtual void FindNextClose ();
+
+			/*
+			 * Called by replace dialog when ok is pressed
+			 */
+		virtual void doreplace (const QString &, int, int,int, const QRect &, long);
 
 protected:
-    int 	doSearch(QString s_pattern, bool case_sensitive,
-			 bool regex, bool forward,int line, int col);
-
-    int 	doReplace(QString s_pattern, bool case_sensitive,
-			  bool regex, bool forward,int line, int col,bool replace);
-
       /**
        * Sets line and col to the position pos, considering word wrap.
        **/
@@ -411,10 +279,12 @@ private:
 
     QTimer* repaintTimer;
 
-    QString	killbufferstring;
+    QString		killbufferstring;
     QWidget     *parent;
     KEdFind 	*srchdialog;
     KEdReplace 	*replace_dialog;
+	QStringList	*findlist;
+	QStringList	*replacelist;
     KEdGotoLine *gotodialog;
 
     QString     pattern;
@@ -423,13 +293,13 @@ private:
     bool	killing;
     bool 	killtrue;
     bool 	lastwasanewline;
-    bool        saved_readonlystate;
+    bool	saved_readonlystate;
     int 	last_search;
     int 	last_replace;
     int 	replace_all_line;
     int 	replace_all_col;
 
-    int 	line_pos, col_pos;
+    int			line_pos, col_pos;
     bool        fill_column_is_set;
     bool        word_wrap_is_set;
     int         fill_column_value;
Index: keditcl1.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdeui/keditcl1.cpp,v
retrieving revision 1.52
diff -u -3 -p -r1.52 keditcl1.cpp
--- keditcl1.cpp	2001/10/12 22:17:14	1.52
+++ keditcl1.cpp	2001/11/17 23:42:13
@@ -61,6 +61,8 @@ KEdit::KEdit(QWidget *_parent, const cha
 
     srchdialog = NULL;
     replace_dialog= NULL;
+	findlist=new QStringList();
+	replacelist=new QStringList();
     gotodialog = NULL;
 
     setAcceptDrops(true);
@@ -70,7 +72,9 @@ KEdit::KEdit(QWidget *_parent, const cha
 
 KEdit::~KEdit()
 {
-  delete d;
+	delete findlist;
+	delete replacelist;
+	delete d;
 }
 
 void
Index: keditcl2.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdeui/keditcl2.cpp,v
retrieving revision 1.43
diff -u -3 -p -r1.43 keditcl2.cpp
--- keditcl2.cpp	2001/10/12 17:06:28	1.43
+++ keditcl2.cpp	2001/11/17 23:42:17
@@ -47,197 +47,148 @@
 // Find Methods
 //
 
-void KEdit::search(){
-
+void KEdit::search()
+{
+	int options;
+	
   if( replace_dialog != 0 && replace_dialog->isVisible() == true )
   {
     replace_dialog->hide();
   }
-
-  if( srchdialog == 0 )
-  {
-    srchdialog = new KEdFind( this, "searchdialog", false);
-    connect(srchdialog,SIGNAL(search()),this,SLOT(search_slot()));
-    connect(srchdialog,SIGNAL(done()),this,SLOT(searchdone_slot()));
-  }
-
-  // If we already searched / replaced something before make sure it shows
-  // up in the find dialog line-edit.
-
-  QString string;
-  string = srchdialog->getText();
-  srchdialog->setText(string.isEmpty() ? pattern : string);
-
-  this->deselect();
-  last_search = NONE;
-
-  srchdialog->show();
-  srchdialog->result();
-}
-
-
-void KEdit::search_slot(){
-
-  int line, col;
-
-  if (!srchdialog)
-    return;
-
-  QString to_find_string = srchdialog->getText();
-  getCursorPosition(&line,&col);
-
-  // srchdialog->get_direction() is true if searching backward
-
-  if (last_search != NONE && srchdialog->get_direction()){
-    col = col  - pattern.length() - 1 ;
-  }
-
-again:
-  int  result = doSearch(to_find_string, srchdialog->case_sensitive(),
-			 FALSE, (!srchdialog->get_direction()),line,col);
-
-  if(result == 0){
-    if(!srchdialog->get_direction()){ // forward search
-
-      int query = KMessageBox::questionYesNo(
-			srchdialog,
-                        i18n("End of document reached.\n"\
-                             "Continue from the beginning?"),
-                        i18n("Find"));
-      if (query == KMessageBox::Yes){
-	line = 0;
-	col = 0;
-	goto again;
-      }
-    }
-    else{ //backward search
-
-      int query = KMessageBox::questionYesNo(
-			srchdialog,
-                        i18n("Beginning of document reached.\n"\
-                             "Continue from the end?"),
-                        i18n("Find"));
-      if (query == KMessageBox::Yes){
-	QString string = textLine( numLines() - 1 );
-	line = numLines() - 1;
-	col  = string.length();
-	last_search = BACKWARD;
-	goto again;
-      }
-    }
-  }
-  else{
-    emit CursorPositionChanged();
-  }
-}
-
-
-
-void KEdit::searchdone_slot(){
-
-  if (!srchdialog)
-    return;
-
-  srchdialog->hide();
-  this->setFocus();
-  last_search = NONE;
-
-}
-
-int KEdit::doSearch(QString s_pattern, bool case_sensitive,
-		    bool wildcard, bool forward, int line, int col){
-
-  (void) wildcard; // reserved for possible extension to regex
-
-
-  int i, length;
-  int pos = -1;
-
-  if(forward){
-
-    QString string;
-
-    for(i = line; i < numLines(); i++) {
-
-      string = textLine(i);
-
-      pos = string.find(s_pattern, i == line ? col : 0, case_sensitive);
-
-      if( pos != -1){
-
-	length = s_pattern.length();
 
-	setCursorPosition(i,pos,FALSE);
-
-	for(int l = 0 ; l < length; l++){
-	  cursorRight(TRUE);
-	}
-
-	setCursorPosition( i , pos + length, TRUE );
-	pattern = s_pattern;
-	last_search = FORWARD;
-
-	return 1;
-      }
-    }
-  }
-  else{ // searching backwards
-
-    QString string;
-
-    for(i = line; i >= 0; i--) {
-
-      string = textLine(i);
-      int line_length = string.length();
-
-      pos = string.findRev(s_pattern, line == i ? col : line_length , \
                case_sensitive);
-
-      if (pos != -1){
-
-	length = s_pattern.length();
-
-	if( ! (line == i && pos > col ) ){
-
-	  setCursorPosition(i ,pos ,FALSE );
-
-	  for(int l = 0 ; l < length; l++){
-	    cursorRight(TRUE);
-	  }
-
-	  setCursorPosition(i ,pos + length ,TRUE );
-	  pattern = s_pattern;
-	  last_search = BACKWARD;
-	  return 1;
-
+	srchdialog = new KEdFind (this, \
"searchdialog",0,*findlist,this->hasSelectedText()); \
+	srchdialog->setText(findlist->last()); +	if ( srchdialog->exec() != \
QDialog::Accepted ) return; +	
+	if (findlist->contains(srchdialog->getText())==0) \
findlist->append(srchdialog->getText()); +	KEdFindNext fn \
(srchdialog->getText(),srchdialog->options(),this); +
+	connect (&fn, SIGNAL( highlight( const QString &, int, int, const QRect &, long ) \
), this, SLOT( highlight( const QString &, int, int, const QRect &, long ) ) ); +
+	options = srchdialog->options();
+		
+	QString _text;
+	QRect r(0,0,0,0);
+	int paraf,parat,idxf,idxt;
+	if (options & KEdFind::SelectedText) {
+		getSelection(&paraf,&idxf,&parat,&idxt);
+		/* a small hack to show where is the selected text, this is transmitted with no \
change to the highlight function */ +		r.setTop(paraf);
+		r.setLeft(idxf);
+		r.setRight(idxt);
+		r.setBottom(parat);
+		_text=this->selectedText();
+	} else {
+		/* FromCursor now */
+		if (options & KEdFind::FromCursor) {
+			int currentpara=0;
+			getCursorPosition (&currentpara,&idxf);
+			/* get global index */
+			int i=0;
+			while (i< currentpara) {
+					idxf+=paragraphLength(i++)+1;
+			}
+			_text=this->text();
+			if (options & KEdFind::FindBackwards) {
+				_text.truncate(idxf);
+				//r.setRight(idxf);
+			} else {
+				_text.remove(0,idxf);
+				r.setRight(idxf);
+			}
+			
+		} else {
+			_text= this->text();
+		}
+	}
+	fn.find(_text,r);
+	
+  delete srchdialog;
+	srchdialog=0;
+
+}
+
+void KEdit::highlight ( const QString &, int matchingIndex, int matchingLength, \
const QRect &r , long options )  +{
+	int parafrom=0,parato=0,indexfrom=0,indexto=0;
+
+	/* check our little hack first */
+	if (options & KEdFind::FromCursor && !(options & KEdFind::FindBackwards)) {
+		matchingIndex+=r.right();
+	}
+	
+	/* find the right paragraph and index using absolute matchingIndex */
+	int currentpara=0, currentidx=0;
+	
+	while (currentpara<r.top() ) {
+					matchingIndex+=paragraphLength(currentpara)+1;
+					currentpara++;
+					//kdDebug(294) << "currentpara : " << currentpara << " currentidx :" << \
currentidx << endl; +	}
+	matchingIndex+=r.left();
+//	kdDebug(294) << "matchingIndex from : " << matchingIndex << endl;
+	currentpara=0;
+	while (currentpara < paragraphs() && paragraphLength(currentpara)+currentidx </*=*/ \
matchingIndex) { +		currentidx+=paragraphLength(currentpara++)+1;
+	}
+	/* we should be on the right starting parag now */
+	indexfrom = (matchingIndex>=currentidx) ? matchingIndex - currentidx : \
matchingIndex; +//	if (options & KEdFind::FindBackwards && options & \
KEdFind::FromCursor) indexfrom++; // don't know why i need this +	parafrom = \
currentpara; +	//kdDebug(294) << "indexfrom :" << indexfrom << " parafrom: " << \
parafrom << endl; +	
+	/* check if the selection overrides current parag */
+  while (currentpara < paragraphs() && currentidx+paragraphLength(currentpara) <= \
matchingIndex+matchingLength-1) { +		currentidx+=paragraphLength(currentpara++);
+	}
+	if (currentpara>0) indexto=matchingIndex+matchingLength-currentidx;
+	else indexto=matchingIndex+matchingLength;
+//	if (options & KEdFind::FindBackwards && options & KEdFind::FromCursor) indexto++; \
// don't know why i need this +	parato=currentpara;
+	//kdDebug(294) << "indexto :" << indexto << " parato: " << parato << endl;
+
+	this->setSelection (parafrom,indexfrom,parato,indexto,1);
+	this->setSelectionAttributes(1,QColor("lightblue"),false);
+	
+}
+
+void KEdit::doreplace (const QString &text, int /*replacementIndex*/, int \
/*replacedLength*/,int /*matchedLength*/, const QRect &r, long options)  +{
+	if (options & KEdFind::SelectedText) {
+		this->removeSelectedText();	
+	} else if (options & KEdFind::FromCursor) {
+		int currentpara=0,currentidx=0;
+		while (currentidx+paragraphLength(currentpara) < r.right()) {
+			currentidx+=paragraphLength(currentpara++)+1;
+		}
+		//kdDebug(294) << "currentidx : " << currentidx << endl;
+		//kdDebug(294) << "currentpara  : " << currentpara << " r.right : " << r.right() \
<< "paragraphs() : " << paragraphs() << " paragraphLength(paragraphs()) : " << \
paragraphLength(paragraphs()-1) << endl; +		if (options & KEdFind::FindBackwards) {
+			setCursorPosition(0,0);
+			this->setSelection(0,0,currentpara,r.right()-currentidx);
+			//kdDebug(294) << "removing text :" << selectedText() << "!" << endl;
+			this->removeSelectedText();
+			setCursorPosition(0,0);
+		} else {
+			setCursorPosition(currentpara,r.right()-currentidx);
+			this->setSelection(currentpara,r.right()-currentidx,paragraphs()-1,paragraphLength(paragraphs()-1));
 +			//kdDebug(294) << "selected text : "  << selectedText() << endl;
+			this->removeSelectedText();
+			setCursorPosition(currentpara,r.right()-currentidx);
+		}
+	} else {
+		this->clear();
 	}
-      }
-
-    }
-  }
-
-  return 0;
-
+	//kdDebug(294) << "inserting text :" << text << "!" << endl;
+	this->insert(text,false,true,false);
 }
 
-
 
-bool KEdit::repeatSearch() {
+void KEdit::FindNextOk () {}
 
-  if(!srchdialog)
-      return false;
+void KEdit::FindNextClose () {}
 
 
-  if(pattern.isEmpty()) // there wasn't a previous search
-    return false;
-
-  search_slot();
-
-  this->setFocus();
-  return true;
-
-}
-
-
 //////////////////////////////////////////////////////////////////////////
 //
 // Replace Methods
@@ -246,675 +197,64 @@ bool KEdit::repeatSearch() {
 
 void KEdit::replace()
 {
+	int options;
+	
   if( srchdialog != 0 && srchdialog->isVisible() == true)
   {
     srchdialog->hide();
   }
-
-  if( replace_dialog == 0 )
-  {
-    replace_dialog = new KEdReplace( this, "replace_dialog", false );
-    connect(replace_dialog,SIGNAL(find()),this,SLOT(replace_search_slot()));
-    connect(replace_dialog,SIGNAL(replace()),this,SLOT(replace_slot()));
-    connect(replace_dialog,SIGNAL(replaceAll()),this,SLOT(replace_all_slot()));
-    connect(replace_dialog,SIGNAL(done()),this,SLOT(replacedone_slot()));
-  }
-
-  QString string = replace_dialog->getText();
-  replace_dialog->setText(string.isEmpty() ? pattern : string);
-
-
-  this->deselect();
-  last_replace = NONE;
-
-  replace_dialog->show();
-  replace_dialog->result();
-}
-
-
-void KEdit::replace_slot(){
-
-  if (!replace_dialog)
-    return;
-
-  if(!can_replace){
-    KNotifyClient::beep();
-    return;
-  }
-
-  int line,col, length;
-
-  QString string = replace_dialog->getReplaceText();
-  length = string.length();
-
-  this->cut();
-
-  getCursorPosition(&line,&col);
-
-  insertAt(string,line,col);
-  setModified(true);
-  can_replace = FALSE;
-
-  setCursorPosition(line,col);
-  for( int k = 0; k < length; k++){
-    cursorRight(TRUE);
-  }
-
-}
-
-void KEdit::replace_all_slot(){
-
-  if (!replace_dialog)
-    return;
-
-  QString to_find_string = replace_dialog->getText();
-  getCursorPosition(&replace_all_line,&replace_all_col);
-
-  // replace_dialog->get_direction() is true if searching backward
-
-  if (last_replace != NONE && replace_dialog->get_direction()){
-    replace_all_col = replace_all_col  - pattern.length() - 1 ;
-  }
-
-  deselect();
-
-again:
-
-  setAutoUpdate(FALSE);
-  int result = 1;
-
-  while(result){
-
-    result = doReplace(to_find_string, replace_dialog->case_sensitive(),
-		       FALSE, (!replace_dialog->get_direction()),
-		       replace_all_line,replace_all_col,TRUE);
-
-  }
-
-  setAutoUpdate(TRUE);
-  update();
-
-  if(!replace_dialog->get_direction()){ // forward search
-
-    int query = KMessageBox::questionYesNo(
-			srchdialog,
-                        i18n("End of document reached.\n"\
-                             "Continue from the beginning?"),
-                        i18n("Find"));
-    if (query == KMessageBox::Yes){
-      replace_all_line = 0;
-      replace_all_col = 0;
-      goto again;
-    }
-  }
-  else{ //backward search
-
-    int query = KMessageBox::questionYesNo(
-			srchdialog,
-                        i18n("Beginning of document reached.\n"\
-                             "Continue from the end?"),
-                        i18n("Find"));
-    if (query == KMessageBox::Yes){
-      QString string = textLine( numLines() - 1 );
-      replace_all_line = numLines() - 1;
-      replace_all_col  = string.length();
-      last_replace = BACKWARD;
-      goto again;
-    }
-  }
-
-  emit CursorPositionChanged();
-
-}
-
-
-void KEdit::replace_search_slot(){
-
-  int line, col;
-
-  if (!replace_dialog)
-    return;
-
-  QString to_find_string = replace_dialog->getText();
-  getCursorPosition(&line,&col);
-
-  // replace_dialog->get_direction() is true if searching backward
-
-  //printf("col %d length %d\n",col, pattern.length());
-
-  if (last_replace != NONE && replace_dialog->get_direction()){
-    col = col  - pattern.length() -1;
-    if (col < 0 ) {
-      if(line !=0){
-	col = textLine(line - 1).length();
-	line --;
-      }
-      else{
-
-        int query = KMessageBox::questionYesNo(
-			replace_dialog,
-                        i18n("Beginning of document reached.\n"\
-                             "Continue from the end?"),
-                        i18n("Replace"));
-        if (query == KMessageBox::Yes){
-	  QString string = textLine( numLines() - 1 );
-	  line = numLines() - 1;
-	  col  = string.length();
-	  last_replace = BACKWARD;
-	}
-      }
-    }
-  }
-
-again:
-
-  //  printf("Col %d \n",col);
-
-  int  result = doReplace(to_find_string, replace_dialog->case_sensitive(),
-			 FALSE, (!replace_dialog->get_direction()), line, col, FALSE );
-
-  if(result == 0){
-    if(!replace_dialog->get_direction()){ // forward search
-
-     int query = KMessageBox::questionYesNo(
-			replace_dialog,
-                        i18n("End of document reached.\n"\
-                             "Continue from the beginning?"),
-                        i18n("Replace"));
-     if (query == KMessageBox::Yes){
-	line = 0;
-	col = 0;
-	goto again;
-      }
-    }
-    else{ //backward search
-
-     int query = KMessageBox::questionYesNo(
-			replace_dialog,
-                        i18n("Beginning of document reached.\n"\
-                             "Continue from the end?"),
-                        i18n("Replace"));
-      if (query == KMessageBox::Yes){
-	QString string = textLine( numLines() - 1 );
-	line = numLines() - 1;
-	col  = string.length();
-	last_replace = BACKWARD;
-	goto again;
-      }
-    }
-  }
-  else{
-
-    emit CursorPositionChanged();
-  }
-}
-
-
-
-void KEdit::replacedone_slot(){
-
-  if (!replace_dialog)
-    return;
-
-  replace_dialog->hide();
-  //  replace_dialog->clearFocus();
-
-  this->setFocus();
-
-  last_replace = NONE;
-  can_replace  = FALSE;
-
-}
-
-
-
-int KEdit::doReplace(QString s_pattern, bool case_sensitive,
-	   bool wildcard, bool forward, int line, int col, bool replace_all){
-
-
-  (void) wildcard; // reserved for possible extension to regex
-
-  int line_counter, length;
-  int pos = -1;
-
-  QString string;
-  QString stringnew;
-  QString replacement;
-
-  replacement = replace_dialog->getReplaceText();
-  line_counter = line;
-  replace_all_col = col;
-
-  if(forward){
-
-    int num_lines = numLines();
-
-    while (line_counter < num_lines){
-
-      string = "";
-      string = textLine(line_counter);
-
-      if (replace_all){
-	pos = string.find(s_pattern, replace_all_col, case_sensitive);
-      }
-      else{
-	pos = string.find(s_pattern, line_counter == line ? col : 0, case_sensitive);
-      }
-
-      if (pos == -1 ){
-	line_counter ++;
-	replace_all_col = 0;
-	replace_all_line = line_counter;
-      }
-
-      if( pos != -1){
-
-	length = s_pattern.length();
-
-	if(replace_all){ // automatic
-
-	  stringnew = string.copy();
-	  stringnew.replace(pos,length,replacement);
-
-	  removeLine(line_counter);
-	  insertLine(stringnew,line_counter);
-
-	  replace_all_col = replace_all_col + replacement.length();
-	  replace_all_line = line_counter;
-
-	  setModified(true);
-	}
-	else{ // interactive
-
-	  setCursorPosition( line_counter , pos, FALSE );
-
-	  for(int l = 0 ; l < length; l++){
-	    cursorRight(TRUE);
-	  }
-
-	  setCursorPosition( line_counter , pos + length, TRUE );
-	  pattern = s_pattern;
-	  last_replace = FORWARD;
-	  can_replace = TRUE;
-
-	  return 1;
-
-	}
-
-      }
-    }
-  }
-  else{ // searching backwards
-
-    while(line_counter >= 0){
-
-      string = "";
-      string = textLine(line_counter);
-
-      int line_length = string.length();
-
-      if( replace_all ){
-      	pos = string.findRev(s_pattern, replace_all_col , case_sensitive);
-      }
-      else{
-	pos = string.findRev(s_pattern,
-			   line == line_counter ? col : line_length , case_sensitive);
-      }
-
-      if (pos == -1 ){
-	line_counter --;
-
-	if(line_counter >= 0){
-	  string = "";
-	  string = textLine(line_counter);
-	  replace_all_col = string.length();
-
-	}
-	replace_all_line = line_counter;
-      }
-
-
-      if (pos != -1){
-	length = s_pattern.length();
-
-	if(replace_all){ // automatic
-
-	  stringnew = string.copy();
-	  stringnew.replace(pos,length,replacement);
-
-	  removeLine(line_counter);
-	  insertLine(stringnew,line_counter);
-
-	  replace_all_col = replace_all_col - replacement.length();
-	  replace_all_line = line_counter;
-
-	  setModified(true);
-
-	}
-	else{ // interactive
-
-	  //	  printf("line_counter %d pos %d col %d\n",line_counter, pos,col);
-	  if( ! (line == line_counter && pos > col ) ){
-
-	    setCursorPosition(line_counter ,pos ,FALSE );
-
-	    for(int l = 0 ; l < length; l++){
-	      cursorRight(TRUE);
-	    }
-
-	    setCursorPosition(line_counter ,pos + length ,TRUE );
-	    pattern = s_pattern;
-
-	    last_replace = BACKWARD;
-	    can_replace = TRUE;
-
-	    return 1;
-	  }
-	}
-      }
-    }
-  }
-
-  return 0;
-
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Find Dialog
-//
-
-class KEdFind::KEdFindPrivate
-{
-public:
-    KEdFindPrivate( QWidget *parent ) {
-	combo = new KHistoryCombo( parent, "value" );
-	combo->setMaxCount( 20 ); // just some default
-    }
-    ~KEdFindPrivate() {
-	delete combo;
-    }
-
-    KHistoryCombo *combo;
-};
-
-
-KEdFind::KEdFind( QWidget *parent, const char *name, bool modal )
-  :KDialogBase( parent, name, modal, i18n("Find"),
-		modal ? User1|Cancel : User1|Close, User1, false, i18n("&Find") )
-{
-  setWFlags( WType_TopLevel );
-
-  QWidget *page = new QWidget( this );
-  setMainWidget(page);
-  QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
-
-  d = new KEdFindPrivate( page );
-
-  QString text = i18n("Find:");
-  QLabel *label = new QLabel( text, page , "find" );
-  topLayout->addWidget( label );
-
-  d->combo->setMinimumWidth(fontMetrics().maxWidth()*20);
-  d->combo->setFocus();
-
-  connect(d->combo, SIGNAL(textChanged ( const QString & )),
-          this,SLOT(textSearchChanged ( const QString & )));
-
-  topLayout->addWidget(d->combo);
-
-  group = new QVButtonGroup( i18n("Options"), page );
-  topLayout->addWidget( group );
-
-  QHBox* row1 = new QHBox( group );
-  
-  text = i18n("Case &Sensitive");
-  sensitive = new QCheckBox( text, row1, "case");
-  text = i18n("Find &Backwards");
-  direction = new QCheckBox( text, row1, "direction" );
-
-  
-  enableButton( KDialogBase::User1, !d->combo->currentText().isEmpty() );
-
-  if ( !modal )
-    connect( this, SIGNAL( closeClicked() ), this, SLOT( slotCancel() ) );
-}
-
-KEdFind::~KEdFind()
-{
-    delete d;
-}
-
-void KEdFind::textSearchChanged ( const QString &text )
-{
-   enableButton( KDialogBase::User1, !text.isEmpty() );
-}
-
-void KEdFind::slotCancel( void )
-{
-  emit done();
-  d->combo->clearEdit();
-  KDialogBase::slotCancel();
-}
-
-void KEdFind::slotUser1( void )
-{
-  if( !d->combo->currentText().isEmpty() )
-  {
-    d->combo->addToHistory( d->combo->currentText() );
-    emit search();
-  }
-}
-
-
-QString KEdFind::getText() const
-{
-    return d->combo->currentText();
-}
-
-
-void KEdFind::setText(QString string)
-{
-  d->combo->setEditText(string);
-  d->combo->lineEdit()->selectAll();
-}
-
-void KEdFind::setCaseSensitive( bool b )
-{
-  sensitive->setChecked( b );
-}
-
-bool KEdFind::case_sensitive() const
-{
-  return sensitive->isChecked();
-}
-
-void KEdFind::setDirection( bool b )
-{
-  direction->setChecked( b );
-}
-
-bool KEdFind::get_direction() const
-{
-  return direction->isChecked();
-}
-
-KHistoryCombo * KEdFind::searchCombo() const
-{
-    return d->combo;
-}
-
-
-
-////////////////////////////////////////////////////////////////////
-//
-//  Replace Dialog
-//
-
-class KEdReplace::KEdReplacePrivate
-{
-public:
-    KEdReplacePrivate( QWidget *parent ) {
-	searchCombo = new KHistoryCombo( parent, "value" );
-	replaceCombo = new KHistoryCombo( parent, "replace_value" );
-
-	searchCombo->setMaxCount( 20 ); // just some defaults
-	replaceCombo->setMaxCount( 20 );
-    }
-    ~KEdReplacePrivate() {
-	delete searchCombo;
-	delete replaceCombo;
-    }
-
-    KHistoryCombo *searchCombo, *replaceCombo;
-};
-
-KEdReplace::KEdReplace( QWidget *parent, const char *name, bool modal )
-  :KDialogBase( parent, name, modal, i18n("Replace"),
-		modal ? User3|User2|User1|Cancel : User3|User2|User1|Close,
-                User3, false,
-		i18n("Replace &All"), i18n("&Replace"), i18n("&Find") )
-{
-  setWFlags( WType_TopLevel );
-
-  setButtonBoxOrientation( Vertical );
-
-  QFrame *page = makeMainWidget();
-  QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
-
-  d = new KEdReplacePrivate( page );
-
-  QString text = i18n("Find:");
-  QLabel *label = new QLabel( text, page, "find" );
-  topLayout->addWidget( label );
-
-  d->searchCombo->setMinimumWidth(fontMetrics().maxWidth()*20);
-  d->searchCombo->setFocus();
-  topLayout->addWidget(d->searchCombo);
-
-  text = i18n("Replace with:");
-  label = new QLabel( text, page, "replace" );
-  topLayout->addWidget( label );
-
-  d->replaceCombo->setMinimumWidth(fontMetrics().maxWidth()*20);
-  topLayout->addWidget(d->replaceCombo);
-
-  connect(d->searchCombo, SIGNAL(textChanged ( const QString & )),
-          this,SLOT(textSearchChanged ( const QString & )));
-
-  QButtonGroup *group = new QButtonGroup( i18n("Options"), page );
-  topLayout->addWidget( group );
-
-  QGridLayout *gbox = new QGridLayout( group, 3, 2, spacingHint() );
-  gbox->addRowSpacing( 0, fontMetrics().lineSpacing() );
-
-  text = i18n("Case &Sensitive");
-  sensitive = new QCheckBox( text, group, "case");
-  text = i18n("Find &Backwards");
-  direction = new QCheckBox( text, group, "direction" );
-  gbox->addWidget( sensitive, 1, 0 );
-  gbox->addWidget( direction, 1, 1 );
-  gbox->setRowStretch( 2, 10 );
-}
-
-
-KEdReplace::~KEdReplace()
-{
-    delete d;
-}
-
-void KEdReplace::textSearchChanged ( const QString &text )
-{
-    bool state=text.isEmpty();
-    enableButton( KDialogBase::User1, !state );
-    enableButton( KDialogBase::User2, !state );
-    enableButton( KDialogBase::User3, !state );
-}
-
-void KEdReplace::slotCancel( void )
-{
-  emit done();
-  d->searchCombo->clearEdit();
-  d->replaceCombo->clearEdit();
-  KDialogBase::slotCancel();
-}
-
-void KEdReplace::slotClose( void )
-{
-  slotCancel();
-}
-
-void KEdReplace::slotUser1( void )
-{
-    if( !d->searchCombo->currentText().isEmpty() )
-    {
-        d->replaceCombo->addToHistory( d->replaceCombo->currentText() );
-        emit replaceAll();
-    }
-}
-
-
-void KEdReplace::slotUser2( void )
-{
-    if( !d->searchCombo->currentText().isEmpty() )
-    {
-        d->replaceCombo->addToHistory( d->replaceCombo->currentText() );
-        emit replace();
-    }
-}
-
-void KEdReplace::slotUser3( void )
-{
-  if( !d->searchCombo->currentText().isEmpty() )
-  {
-    d->searchCombo->addToHistory( d->searchCombo->currentText() );
-    emit find();
-  }
-}
-
-
-QString KEdReplace::getText()
-{
-    return d->searchCombo->currentText();
-}
 
+  replace_dialog = new KEdReplace( this, "replace_dialog" \
,0,*findlist,*replacelist,this->hasSelectedText()); \
+	replace_dialog->setText(findlist->last()); \
+	replace_dialog->setReplaceText(replacelist->last()); +
+	if ( replace_dialog->exec() != QDialog::Accepted ) return;
+	if (findlist->contains(replace_dialog->getText())==0) \
findlist->append(replace_dialog->getText()); +	if \
(replacelist->contains(replace_dialog->replacement())==0) \
replacelist->append(replace_dialog->replacement()); +
+	KEdReplaceNext rn (replace_dialog->getText(),replace_dialog->getReplaceText(),replace_dialog->options(),this);
 +	
+  connect(&rn,SIGNAL(highlight(const QString &, int, int, const QRect &, \
long)),this,SLOT(highlight(const QString &, int, int, const QRect &, long))); +  \
connect(&rn,SIGNAL(replace(const QString &, int, int,int, const QRect &, \
long)),this,SLOT(doreplace(const QString &, int, int,int, const QRect &, long)) ); +	
+	QString _text=this->text();
+	QRect r(0,0,0,0);
+	options=replace_dialog->options();
+	
+	int paraf,parat,idxf,idxt;
+	if (options & KEdFind::SelectedText) {
+		getSelection(&paraf,&idxf,&parat,&idxt);
+		/* a small hack to show where is the selected text, this is transmitted with no \
change to the highlight function */ +		r.setTop(paraf);
+		r.setLeft(idxf);
+		r.setRight(idxt);
+		r.setBottom(parat);
+		_text=this->selectedText();
+	} else {
+		if (options & KEdFind::FromCursor) {
+			int currentpara=0;
+			getCursorPosition (&currentpara,&idxf);
+			/* get global index */
+			int i=0;
+			while (i< currentpara) {
+					idxf+=paragraphLength(i++)+1;
+			}
+			_text=this->text();
+			if (options & KEdFind::FindBackwards) {
+				_text.truncate(idxf);
+				r.setRight(idxf);
+			} else {
+				_text.remove(0,idxf);
+				r.setRight(idxf);
+			}
+		}
+	}
+//	kdDebug(294) << "text: " << _text << endl;
+	rn.replace(_text,r);
+	
 
-QString KEdReplace::getReplaceText()
-{
-    return d->replaceCombo->currentText();
-}
-
-
-void KEdReplace::setText(QString string)
-{
-  d->searchCombo->setEditText(string);
-  d->searchCombo->lineEdit()->selectAll();
-}
-
-
-bool KEdReplace::case_sensitive()
-{
-  return sensitive->isChecked();
-}
-
-
-bool KEdReplace::get_direction()
-{
-  return direction->isChecked();
-}
-
-KHistoryCombo * KEdReplace::searchCombo() const
-{
-    return d->searchCombo;
-}
-
-KHistoryCombo * KEdReplace::replaceCombo() const
-{
-    return d->replaceCombo;
+	delete replace_dialog;
+	replace_dialog=0;
 }
 
 
Index: kedreplace.cpp
===================================================================
RCS file: kedreplace.cpp
diff -N kedreplace.cpp
--- /dev/null	Tue May  5 20:32:27 1998
+++ kedreplace.cpp	Sat Nov 17 23:42:18 2001
@@ -0,0 +1,271 @@
+/*
+    Copyright (C) 2001, S.R.Haque <srhaque@iee.org>.
+    This file is part of the KDE project
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qregexp.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kedreplace.h>
+#include <kmessagebox.h>
+
+KEdReplace::KEdReplace(QWidget *parent, const char *name, long options, const \
QStringList &findStrings, const QStringList &replaceStrings, bool hasSelection) : +   \
KEdFind(parent, name, true) +{
+    init(true, findStrings, hasSelection);
+    setOptions(options);
+    setReplacementHistory(replaceStrings);
+}
+
+KEdReplace::~KEdReplace()
+{
+}
+
+long KEdReplace::options() const
+{
+    long options = 0;
+
+    options = KEdFind::options();
+    if (m_promptOnReplace->isChecked())
+        options |= PromptOnReplace;
+    if (m_backRef->isChecked())
+        options |= BackReference;
+    return options;
+}
+
+QWidget *KEdReplace::replaceExtension()
+{
+    return m_replaceExtension;
+}
+
+QString KEdReplace::replacement() const
+{
+    return m_replace->currentText();
+}
+
+QString KEdReplace::getReplaceText() const
+{
+	return m_replace->currentText();
+}
+
+void KEdReplace::setReplaceText(QString string)
+{
+	m_replace->setEditText(string);
+}
+
+QStringList KEdReplace::replacementHistory() const
+{
+    return m_find->historyItems();
+}
+
+void KEdReplace::setOptions(long options)
+{
+    KEdFind::setOptions(options);
+    m_promptOnReplace->setChecked(options & PromptOnReplace);
+    m_backRef->setChecked(options & BackReference);
+}
+
+void KEdReplace::setReplacementHistory(const QStringList &strings)
+{
+    if (strings.count() > 0)
+        m_replace->setHistoryItems(strings, true);
+    else
+        m_replace->clearHistory();
+}
+
+void KEdReplace::slotOk()
+{
+    KEdFind::slotOk();
+    m_replace->addToHistory(replacement());
+}
+
+// Create the dialog.
+KEdReplaceNext::KEdReplaceNext(const QString &pattern, const QString &replacement, \
long options, QWidget *parent) : +    KDialogBase(parent, __FILE__, false,  // \
non-modal! +        i18n("Replace"),
+        User3 | User2 | User1 | Close,
+        User3,
+        false,
+        i18n("&All"), i18n("&Skip"), i18n("&Yes"))
+{
+    setMainWidget( new QLabel( i18n("Replace '%1' with \
'%2'?").arg(pattern).arg(replacement), this ) ); +    m_cancelled = false;
+    m_options = options;
+    m_parent = parent;
+    m_replacements = 0;
+    if (m_options & KEdReplace::RegularExpression)
+        m_regExp = new QRegExp(pattern, m_options & KEdReplace::CaseSensitive);
+    else
+        m_pattern = pattern;
+    m_replacement = replacement;
+    resize(minimumSize());
+}
+
+KEdReplaceNext::~KEdReplaceNext()
+{
+    if (!m_replacements && !m_cancelled)
+        KMessageBox::information(m_parent, i18n("No text was replaced."));
+}
+
+void KEdReplaceNext::slotClose()
+{
+    m_cancelled = true;
+    kapp->exit_loop();
+}
+
+void KEdReplaceNext::abort()
+{
+    slotClose();
+}
+
+bool KEdReplaceNext::replace(QString &text, const QRect &expose)
+{
+    if (m_options & KEdFind::FindBackwards)
+    {
+        m_index = text.length();
+    }
+    else
+    {
+        m_index = 0;
+    }
+    m_text = text;
+    m_expose = expose;
+    do
+    {
+        // Find the next match.
+        if (m_options & KEdReplace::RegularExpression)
+            m_index = KEdFindNext::find(m_text, *m_regExp, m_index, m_options, \
&m_matchedLength); +        else
+            m_index = KEdFindNext::find(m_text, m_pattern, m_index, m_options, \
&m_matchedLength); +        if (m_index != -1)
+        {
+            if (m_options & KEdReplace::PromptOnReplace)
+            {
+                // Tell the world about the match we found, in case someone wants to
+                // highlight it.
+                emit highlight(m_text, m_index, m_matchedLength, m_expose, \
m_options); +                show();
+                kapp->enter_loop();
+            }
+            else
+            {
+                doReplace();
+            }
+        }
+    }
+    while ((m_index != -1) && !m_cancelled);
+    text = m_text;
+
+    // Should the user continue?
+    return !m_cancelled;
+}
+
+int KEdReplaceNext::replace(QString &text, const QString &pattern, const QString \
&replacement, int index, long options, int *replacedLength) +{
+    int matchedLength;
+
+    index = KEdFindNext::find(text, pattern, index, options, &matchedLength);
+    if (index != -1)
+    {
+        *replacedLength = replace(text, replacement, index, matchedLength);
+        if (options & KEdReplace::FindBackwards)
+            index--;
+        else
+            index += *replacedLength;
+    }
+    return index;
+}
+
+int KEdReplaceNext::replace(QString &text, const QRegExp &pattern, const QString \
&replacement, int index, long options, int *replacedLength) +{
+    int matchedLength;
+
+    index = KEdFindNext::find(text, pattern, index, options, &matchedLength);
+    if (index != -1)
+    {
+        *replacedLength = replace(text, replacement, index, matchedLength);
+        if (options & KEdReplace::FindBackwards)
+            index--;
+        else
+            index += *replacedLength;
+    }
+    return index;
+}
+
+int KEdReplaceNext::replace(QString &text, const QString &replacement, int index, \
int length) +{
+    // TBD: implement backreferences.
+    text.replace(index, length, replacement);
+    return replacement.length();
+}
+
+// All.
+void KEdReplaceNext::slotUser1()
+{
+    int replacedLength;
+
+    replacedLength = KEdReplaceNext::replace(m_text, m_replacement, m_index, \
m_matchedLength); +
+    // Tell the world about the replacement we made, in case someone wants to
+    // highlight it.
+    emit replace(m_text, m_index, replacedLength,m_matchedLength , m_expose, \
m_options); +    m_replacements++;
+    if (m_options & KEdReplace::FindBackwards)
+        m_index--;
+    else
+        m_index += replacedLength;
+    m_options &= ~KEdReplace::PromptOnReplace;
+    kapp->exit_loop();
+}
+
+// Skip.
+void KEdReplaceNext::slotUser2()
+{
+    if (m_options & KEdFind::FindBackwards) m_index--;
+	else  m_index++;
+    kapp->exit_loop();
+}
+
+// Yes.
+void KEdReplaceNext::slotUser3()
+{
+    doReplace();
+    kapp->exit_loop();
+}
+
+void KEdReplaceNext::doReplace()
+{
+    int replacedLength;
+
+    replacedLength = KEdReplaceNext::replace(m_text, m_replacement, m_index, \
m_matchedLength); +
+    // Tell the world about the replacement we made, in case someone wants to
+    // highlight it.
+    emit replace(m_text, m_index, replacedLength,m_matchedLength, m_expose, \
m_options); +    m_replacements++;
+    if (m_options & KEdReplace::FindBackwards)
+        m_index--;
+    else
+        m_index += replacedLength;
+}
+
+#include "kedreplace.moc"
Index: kedreplace.h
===================================================================
RCS file: kedreplace.h
diff -N kedreplace.h
--- /dev/null	Tue May  5 20:32:27 1998
+++ kedreplace.h	Sat Nov 17 23:42:21 2001
@@ -0,0 +1,284 @@
+/*
+    Copyright (C) 2001, S.R.Haque <srhaque@iee.org>.
+    This file is part of the KDE project
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#ifndef KEDREPLACE_H
+#define KEDREPLACE_H
+
+#include <kedfind.h>
+
+class KHistoryCombo;
+class QCheckBox;
+class QGroupBox;
+class QLabel;
+class QPopupMenu;
+class QPushButton;
+class QRect;
+
+/**
+ * @short A generic "replace" widget.
+ *
+ * @author S.R.Haque <srhaque@iee.org>
+ *
+ * @sect Detail
+ *
+ * This widget inherits from @ref KEdFind and implements
+ * the following additional functionalities:  a replacement string
+ * object and an area for a user-defined widget to extend the dialog.
+ *
+ * @sect Example
+ *
+ * To use the basic replace dialog:
+ *
+ * <pre>
+ * </pre>
+ *
+ * To use your own extensions:
+ *
+ * <pre>
+ * </pre>
+ */
+
+class KEdReplace:
+    public KEdFind
+{
+    Q_OBJECT
+
+public:
+
+    // Options.
+
+    typedef enum
+    {
+        // Should the user be prompted before the replace operation?
+        PromptOnReplace = 256,
+        BackReference = 512
+    } Options;
+
+    /**
+     * Construct a replace dialog.read-only or rather select-only combo box with a
+     * parent object and a name.
+     *
+     * @param parent The parent object of this widget
+     * @param name The name of this widget
+     * @param options A bitfield of the @ref Options to be enabled.
+     * @param hasSelection Whether a selection exists
+     */
+    KEdReplace( QWidget *parent = 0, const char *name = 0, long options = 0,
+                     const QStringList &findStrings = QStringList(), const \
QStringList &replaceStrings = QStringList(), +                     bool hasSelection \
= true ); +
+    /**
+     * Destructor.
+     */
+    virtual ~KEdReplace();
+
+    /**
+     * Provide the list of @p strings to be displayed as the history
+     * of replacement strings. @p strings might get truncated if it is
+     * too long.
+     *
+     * @param history The replacement history.
+     * @see #replacementHistory
+     */
+    void setReplacementHistory( const QStringList &strings );
+
+    /**
+     * Returns the list of history items.
+     *
+     * @see #setReplacementHistory
+     */
+    QStringList replacementHistory() const;
+
+    /**
+     * Set the options which are enabled.
+     *
+     * @param options The setting of the @ref Options.
+     */
+    void setOptions( long options );
+
+    /**
+     * Returns the state of the options. Disabled options may be returned in
+     * an indeterminate state.
+     *
+     * @see #setOptions
+     */
+    long options() const;
+
+    /**
+     * Returns the replacement string.
+     */
+    QString replacement() const;
+
+	/*
+	 * Sets the replace text
+	 */
+	void setReplaceText(QString string);
+
+    /**
+     * Returns an empty widget which the user may fill with additional UI
+     * elements as required. The widget occupies the width of the dialog,
+     * and is positioned immediately the regular expression support widgets
+     * for the replacement string.
+     */
+    QWidget *replaceExtension();
+
+	/**
+	 * Backwards compatibility functions
+	 */
+
+	QString getReplaceText() const;
+
+
+protected slots:
+
+    void slotOk();
+
+private:
+
+    // Binary compatible extensibility.
+    class KEdReplacePrivate;
+    KEdReplacePrivate *d;
+};
+
+/**
+ * @short A generic implementation of the "replace" function.
+ *
+ * @author S.R.Haque <srhaque@iee.org>
+ *
+ * @sect Detail
+ *
+ * This class includes prompt handling etc. Also provides some
+ * static functions which can be used to create custom behaviour
+ * instead of using the class directly.
+ *
+ * @sect Example
+ *
+ * To use the class to implement a complete replace feature:
+ *
+ * <pre>
+ *
+ *  // This creates a replace-on-prompt dialog if needed.
+ *  dialog = new KEdReplaceNext(find, replace, options);
+ *
+ *  // Connect signals to code which handles highlighting
+ *  // of found text, and on-the-fly replacement.
+ *  QObject::connect(
+ *      dialog, SIGNAL( highlight( const QString &, int, int, const QRect & ) ),
+ *      this, SLOT( highlight( const QString &, int, int, const QRect & ) ) );
+ *  QObject::connect(
+ *      dialog, SIGNAL( replace( const QString &, int, int, const QRect & ) ),
+ *      this, SLOT( replace( const QString &, int, int, const QRect & ) ) );
+ *
+ *  for (text chosen by option SelectedText and in a direction set by FindBackwards)
+ *  {
+ *      dialog->replace()
+ *  }
+ *  delete dialog;
+ *
+ * </pre>
+ */
+
+class KEdReplaceNext :
+    public KDialogBase
+{
+    Q_OBJECT
+
+public:
+
+    /** Will create a prompt dialog and use it as needed. */
+    KEdReplaceNext(const QString &pattern, const QString &replacement, long options, \
QWidget *parent = 0); +    ~KEdReplaceNext();
+
+    /**
+     * Walk the text fragment (e.g. kwrite line, kspread cell) looking for matches.
+     * For each match, if prompt-on-replace is specified, emits the expose() signal
+     * and displays the prompt-for-replace dialog before doing the replace.
+     *
+     * @param text The text fragment to modify.
+     * @param exposeOnReplace The region to expose
+     * @return False if the user elected to discontinue the replace.
+     */
+    bool replace(QString &text, const QRect &expose);
+
+    /**
+     * Search the given string, and returns whether a match was found. If one is,
+     * the replacement string length is also returned.
+     *
+     * A performance optimised version of the function is provided for use
+     * with regular expressions.
+     *
+     * @param text The string to search.
+     * @param pattern The pattern to look for.
+     * @param index The starting index into the string.
+     * @param options. The options to use.
+     * @return The index at which a match was found, or -1 if no match was found.
+     */
+    static int replace( QString &text, const QString &pattern, const QString \
&replacement, int index, long options, int *replacedLength ); +    static int \
replace( QString &text, const QRegExp &pattern, const QString &replacement, int \
index, long options, int *replacedLength ); +
+    /**
+     * Abort the current find/replace process. Call this when the parent widget
+     * is getting destroyed.
+     */
+    void abort();
+
+signals:
+
+    /**
+     * Connect to this slot to implement highlighting of found text during the \
replace +     * operation.
+     */
+    void highlight(const QString &text, int matchingIndex, int matchedLength, const \
QRect &expose, long options); +
+    /**
+     * Connect to this slot to implement updating of replaced text during the \
replace +     * operation.
+     */
+    void replace(const QString &text, int replacementIndex, int replacedLength,int \
matchedLength, const QRect &expose, long options); +
+private:
+    void doReplace();
+
+    QString m_pattern;
+    QRegExp *m_regExp;
+    QString m_replacement;
+    long m_options;
+    QWidget *m_parent;
+    unsigned m_replacements;
+    QString m_text;
+    int m_index;
+    QRect m_expose;
+    int m_matchedLength;
+    bool m_cancelled;
+
+    static int replace( QString &text, const QString &replacement, int index, int \
length ); +
+    // Binary compatible extensibility.
+    class KEdReplaceNextPrivate;
+    KEdReplaceNextPrivate *d;
+
+private slots:
+
+    void slotUser1();   // All
+    void slotUser2();   // Skip
+    void slotUser3();   // Yes
+    void slotClose();
+};
+#endif



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic