/* This file is part of the KDE project
 *
 * Copyright (C) 2008 Bernhard Beschow <bbeschow AT cs DOT tu-berlin DOT de>
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#ifndef __khtml_find_p_h__
#define __khtml_find_p_h__

#include <QObject>

#include "xml/dom_nodeimpl.h"

#include <kfind.h>

#include <QStringList>
#include <QPointer>
#include "khtmlfindbar.h"

class KHTMLPart;
class QString;
class QWidget;
class KFindDialog;
class KFind;

/**
 * This class implements the find activity for the @p KHTMLPart.
 *
 * 
 *
 * @author Bernhard Beschow <bbeschow cs tu berlin de>
 */
class KHTMLFind : public QObject
{
  Q_OBJECT
public:
  KHTMLFind( KHTMLPart *part, KHTMLFind *parent=0 );
  ~KHTMLFind();
  void findTextBegin();
  bool initFindNode( bool selection, bool reverse, bool fromCursor );
  void createNewKFind( const QString &str, long options, QWidget *parent, KFindDialog *findDialog );
  bool findTextNext( bool reverse = false );
  KHTMLFindBar *findBar() const { return m_parent ? m_parent->findBar() : m_findDialog.data(); }

public slots:
  void activate();
  void deactivate();

private slots:
  void slotFindDestroyed();
  void slotSelectionChanged();
  void slotHighlight( const QString &, int index, int length );
  void slotSearchChanged();
  void slotFindNext();
  void slotFindPrevious();

signals:
  void foundMatch( const DOM::Selection &selection, int length );

protected:
  KFind *find() const { return m_find; }

private:
  KHTMLPart *m_part;

  struct StringPortion
  {
      // Just basic ref/deref on our node to make sure it doesn't get deleted
      StringPortion( int i, DOM::NodeImpl* n ) : index(i), node(n) { if (node) node->ref(); }
      StringPortion() : index(0), node(0) {} // for QValueList
      StringPortion( const StringPortion& other ) : node(0) { operator=(other); }
      StringPortion& operator=( const StringPortion& other ) {
          index=other.index;
          if (other.node) other.node->ref();
          if (node) node->deref();
          node=other.node;
          return *this;
      }
      ~StringPortion() { if (node) node->deref(); }

      int index;
      DOM::NodeImpl *node;
  };
  QList<StringPortion> m_stringPortions;

  KFind *m_find;
  KHTMLFind *m_parent;
  QPointer<KHTMLFindBar> m_findDialog;

  struct findState
  {
    findState() : options( 0 ), last_dir( -1 ) {}
    QStringList history;
    QString text;
    int options;
    int last_dir; // -1=unknown,0=forward,1=backward
  };

  findState m_lastFindState;

  DOM::NodeImpl *m_findNode; // current node
  DOM::NodeImpl *m_findNodeEnd; // end node
  DOM::NodeImpl *m_findNodeStart; // start node
  DOM::NodeImpl *m_findNodePrevious; // previous node used for find
  int m_findPos; // current pos in current node
  int m_findPosEnd; // pos in end node
  int m_findPosStart; // pos in start node
};

#endif
