diff --git a/src/qtgui/preview/preview.pro b/src/qtgui/preview/preview.pro
new file mode 100644
index 00000000..0e26b65a
--- /dev/null
+++ b/src/qtgui/preview/preview.pro
@@ -0,0 +1,23 @@
+TEMPLATE = app
+LANGUAGE = C++
+
+CONFIG += qt warn_on release
+
+unix:LIBS += ../../lib/librcl.a ../../bincimapmime/libmime.a -L/usr/local/lib -lxapian -liconv -lfontconfig -lfreetype -lexpat -lz
+
+unix:INCLUDEPATH += ../ ../../common ../../index ../../query ../../unac ../../utils
+
+SOURCES += pvmain.cpp \
+ ../plaintorich.cpp
+
+FORMS = preview.ui
+
+#
+
+
+unix {
+ UI_DIR = .ui
+ MOC_DIR = .moc
+ OBJECTS_DIR = .obj
+ }
+
diff --git a/src/qtgui/preview/preview.ui b/src/qtgui/preview/preview.ui
new file mode 100644
index 00000000..c8078ab6
--- /dev/null
+++ b/src/qtgui/preview/preview.ui
@@ -0,0 +1,165 @@
+
+Preview
+
+
+ Preview
+
+
+
+ 159
+ 362
+ 469
+ 174
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+ 150
+ 30
+
+
+
+ Preview
+
+
+
+ unnamed
+
+
+
+ layout5
+
+
+
+ unnamed
+
+
+
+ pvEdit
+
+
+ true
+
+
+ false
+
+
+
+
+ layout4
+
+
+
+ unnamed
+
+
+
+ searchLabel
+
+
+ &Search for:
+
+
+ searchTextLine
+
+
+
+
+ searchTextLine
+
+
+ LineEditPanel
+
+
+ Sunken
+
+
+
+
+ nextButton
+
+
+ &Next
+
+
+ Alt+N
+
+
+
+
+ prevButton
+
+
+ &Previous
+
+
+ Alt+P
+
+
+
+
+ matchCheck
+
+
+ Match &Case
+
+
+ Alt+C
+
+
+
+
+
+
+
+
+
+
+ searchTextLine
+ textChanged(const QString&)
+ Preview
+ searchTextLine_textChanged(const QString&)
+
+
+ nextButton
+ clicked()
+ Preview
+ nextPressed()
+
+
+ prevButton
+ clicked()
+ Preview
+ prevPressed()
+
+
+
+ qapplication.h
+ preview.ui.h
+
+
+ int matchIndex;
+ int matchPara;
+ bool dynSearchActive;
+ bool canBeep;
+
+
+ searchTextLine_textChanged( const QString & text )
+ doSearch( bool next, bool reverse )
+ nextPressed()
+ prevPressed()
+
+
+ init()
+ eventFilter( QObject * target, QEvent * event )
+
+
+
diff --git a/src/qtgui/preview/preview.ui.h b/src/qtgui/preview/preview.ui.h
new file mode 100644
index 00000000..13109415
--- /dev/null
+++ b/src/qtgui/preview/preview.ui.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you want to add, delete, or rename functions or slots, use
+** Qt Designer to update this file, preserving your code.
+**
+** You should not define a constructor or destructor in this file.
+** Instead, write your code in functions called init() and destroy().
+** These will automatically be called by the form's constructor and
+** destructor.
+*****************************************************************************/
+
+void Preview::init()
+{
+ pvEdit->installEventFilter(this);
+ searchTextLine->installEventFilter(this);
+ dynSearchActive = false;
+ canBeep = true;
+ matchPara = 0;
+ matchIndex = 0;
+}
+
+bool Preview::eventFilter(QObject *target, QEvent *event)
+{
+
+ if (event->type() != QEvent::KeyPress)
+ return QWidget::eventFilter(target, event);
+
+ QKeyEvent *keyEvent = (QKeyEvent *)event;
+ if (dynSearchActive) {
+ if (keyEvent->key() == Key_F3) {
+ doSearch(true, false);
+ return true;
+ }
+ if (target != searchTextLine)
+ return QApplication::sendEvent(searchTextLine, event);
+ } else {
+ if (keyEvent->key() == Key_Slash && target == pvEdit) {
+ dynSearchActive = true;
+ return true;
+ }
+ }
+
+ return QWidget::eventFilter(target, event);
+}
+
+void Preview::searchTextLine_textChanged(const QString & text)
+{
+ //fprintf(stderr, "search line text changed. text: '%s'\n", text.ascii());
+ if (text.isEmpty()) {
+ dynSearchActive = false;
+ } else {
+ dynSearchActive = true;
+ doSearch(false, false);
+ }
+}
+
+
+// Perform text search. If next is true, we look for the next match of the
+// current search, trying to advance and possibly wrapping around. If next is
+// false, the search string has been modified, we search for the new string,
+// starting from the current position
+void Preview::doSearch(bool next, bool reverse)
+{
+ //fprintf(stderr, "Preview::doSearch: next %d rev %d para %d index %d\n",
+ // int(next), int(reverse), matchPara, matchIndex);
+
+ bool matchCase = matchCheck->isChecked();
+
+ if (next) {
+ // We search again, starting from the current match
+ if (reverse) {
+ // when searching backwards, have to move back one char
+ if (matchIndex > 0)
+ matchIndex --;
+ else if (matchPara > 0) {
+ matchPara --;
+ matchIndex = pvEdit->paragraphLength(matchPara);
+ }
+ } else {
+ // Forward search: start from end of selection
+ int bogus;
+ pvEdit->getSelection(&bogus, &bogus, &matchPara, &matchIndex);
+ //fprintf(stderr, "New para: %d index %d\n",matchPara, matchIndex);
+ }
+ }
+
+ bool found = pvEdit->find(searchTextLine->text(), matchCase, false,
+ !reverse, &matchPara, &matchIndex);
+
+ if (!found && next && true) { // need a 'canwrap' test here
+ if (reverse) {
+ matchPara = pvEdit->paragraphs();
+ matchIndex = pvEdit->paragraphLength(matchPara);
+ } else {
+ matchPara = matchIndex = 0;
+ }
+ found = pvEdit->find(searchTextLine->text(), matchCase, false,
+ !reverse, &matchPara, &matchIndex);
+ }
+
+ if (found) {
+ canBeep = true;
+ } else {
+ if (canBeep)
+ QApplication::beep();
+ canBeep = false;
+ }
+}
+
+
+void Preview::nextPressed()
+{
+ doSearch(true, false);
+}
+
+
+void Preview::prevPressed()
+{
+ doSearch(true, true);
+}
diff --git a/src/qtgui/preview/pvmain.cpp b/src/qtgui/preview/pvmain.cpp
new file mode 100644
index 00000000..0aefb98f
--- /dev/null
+++ b/src/qtgui/preview/pvmain.cpp
@@ -0,0 +1,42 @@
+#ifndef lint
+static char rcsid[] = "@(#$Id: pvmain.cpp,v 1.1 2005-09-27 06:20:16 dockes Exp $ (C) 2005 J.F.Dockes";
+#endif
+
+#include
+#include
+
+#include
+#include
+using std::string;
+using std::list;
+using std::pair;
+
+#include
+#include
+#include
+
+#include "preview.h"
+#include "../plaintorich.h"
+#include "readfile.h"
+
+const char *filename = "/home/dockes/tmp/tstpv-utf8.txt";
+
+int main( int argc, char ** argv )
+{
+ QApplication a(argc, argv);
+ Preview w;
+ w.show();
+
+ string text;
+ if (!file_to_string(filename, text)) {
+ fprintf(stderr, "Could not read %s\n", filename);
+ exit(1);
+ }
+ list terms;
+ list > termoffs;
+ string rich = plaintorich(text, terms, termoffs);
+ QString str = QString::fromUtf8(rich.c_str(), rich.length());
+ w.pvEdit->setText(str);
+
+ return a.exec();
+}