diff --git a/src/kde/kioslave/kio_recoll/htmlif.cpp b/src/kde/kioslave/kio_recoll/htmlif.cpp index 083be203..d31cd62c 100644 --- a/src/kde/kioslave/kio_recoll/htmlif.cpp +++ b/src/kde/kioslave/kio_recoll/htmlif.cpp @@ -204,24 +204,32 @@ void RecollProtocol::queryDetails() class PlainToRichKio : public PlainToRich { public: PlainToRichKio(const string& nm) - : PlainToRich() , m_name(nm) + : m_name(nm) { } - virtual ~PlainToRichKio() {} + virtual string header() { if (m_inputhtml) { - return snull; + return cstr_null; } else { - return - string("
" - "");
+ return string(""
+ "").
+ append(m_name).
+ append(" ");
}
}
- virtual string startMatch() {return string("");}
- virtual string endMatch() {return string("");}
+
+ virtual string startMatch(unsigned int)
+ {
+ return string("");
+ }
+
+ virtual string endMatch()
+ {
+ return string("");
+ }
+
const string &m_name;
};
diff --git a/src/qtgui/preview_w.cpp b/src/qtgui/preview_w.cpp
index b0e8ab01..a0105175 100644
--- a/src/qtgui/preview_w.cpp
+++ b/src/qtgui/preview_w.cpp
@@ -68,54 +68,130 @@ using std::pair;
// Subclass plainToRich to add s and anchors to the preview text
class PlainToRichQtPreview : public PlainToRich {
public:
- int lastanchor;
- PlainToRichQtPreview()
+
+ PlainToRichQtPreview()
+ : m_curanchor(1), m_lastanchor(0)
{
- lastanchor = 0;
}
- virtual ~PlainToRichQtPreview() {}
- virtual string header() {
+
+ bool haveAnchors()
+ {
+ return m_lastanchor != 0;
+ }
+
+ virtual string header()
+ {
if (m_inputhtml) {
- return snull;
+ return cstr_null;
} else {
if (prefs.previewPlainPre) {
m_eolbr = false;
return string(" "
"");
-// Note we could also use the following for line-folding instead of
s
-// This would be possible without recomputing the whole text, much better perfs
-// for toggling wrap/no-wrap
-// "");
+ // Note: we could also use the following for
+ // line-folding instead of
s This would be
+ // possible without recomputing the whole text, much
+ // better perfs for toggling wrap/no-wrap:
+ //
} else {
m_eolbr = true;
return string(" ");
}
}
}
- virtual string startMatch()
+
+ virtual string startMatch(unsigned int grpidx)
{
- return string("");
+ LOGDEB2(("startMatch, grpidx %u\n", grpidx));
+ grpidx = m_hdata->grpsugidx[grpidx];
+ LOGDEB2(("startMatch, ugrpidx %u\n", grpidx));
+ m_groupanchors[grpidx].push_back(++m_lastanchor);
+ m_groupcuranchors[grpidx] = 0;
+ return string("").
+ append("");
}
- virtual string endMatch() {return string("");}
- virtual string termAnchorName(int i) {
+
+ virtual string endMatch()
+ {
+ return string("");
+ }
+
+ virtual string termAnchorName(int i) const
+ {
static const char *termAnchorNameBase = "TRM";
char acname[sizeof(termAnchorNameBase) + 20];
sprintf(acname, "%s%d", termAnchorNameBase, i);
- if (i > lastanchor)
- lastanchor = i;
return string(acname);
}
- virtual string startAnchor(int i) {
- return string("";
+ virtual string startChunk()
+ {
+ return "";
}
- virtual string endAnchor() {
- return string("");
+
+ int nextAnchorNum(int grpidx)
+ {
+ LOGDEB2(("nextAnchorNum: group %d\n", grpidx));
+ map::iterator curit =
+ m_groupcuranchors.find(grpidx);
+ map >::iterator vecit =
+ m_groupanchors.find(grpidx);
+ if (grpidx == -1 || curit == m_groupcuranchors.end() ||
+ vecit == m_groupanchors.end()) {
+ if (m_curanchor >= m_lastanchor)
+ m_curanchor = 1;
+ else
+ m_curanchor++;
+ } else {
+ if (curit->second >= vecit->second.size() -1)
+ m_groupcuranchors[grpidx] = 0;
+ else
+ m_groupcuranchors[grpidx]++;
+ m_curanchor = vecit->second[m_groupcuranchors[grpidx]];
+ LOGDEB2(("nextAnchorNum: curanchor now %d\n", m_curanchor));
+ }
+ return m_curanchor;
}
- virtual string startChunk() { return "";}
+
+ int prevAnchorNum(int grpidx)
+ {
+ map::iterator curit =
+ m_groupcuranchors.find(grpidx);
+ map >::iterator vecit =
+ m_groupanchors.find(grpidx);
+ if (grpidx == -1 || curit == m_groupcuranchors.end() ||
+ vecit == m_groupanchors.end()) {
+ if (m_curanchor <= 1)
+ m_curanchor = m_lastanchor;
+ else
+ m_curanchor--;
+ } else {
+ if (curit->second <= 0)
+ m_groupcuranchors[grpidx] = vecit->second.size() -1;
+ else
+ m_groupcuranchors[grpidx]--;
+ m_curanchor = vecit->second[m_groupcuranchors[grpidx]];
+ }
+ return m_curanchor;
+ }
+
+ QString curAnchorName() const
+ {
+ return QString::fromUtf8(termAnchorName(m_curanchor).c_str());
+ }
+
+private:
+ int m_curanchor;
+ int m_lastanchor;
+ // Lists of anchor numbers (match locations) for the term (groups)
+ // in the query (the map key is and index into HighlightData.groups).
+ map > m_groupanchors;
+ map m_groupcuranchors;
};
void Preview::init()
@@ -141,8 +217,24 @@ void Preview::init()
QHBoxLayout *layout3 = new QHBoxLayout(0);
searchLabel = new QLabel(this);
layout3->addWidget(searchLabel);
- searchTextLine = new QLineEdit(this);
- layout3->addWidget(searchTextLine);
+
+ searchTextCMB = new QComboBox(this);
+ searchTextCMB->setEditable(true);
+ searchTextCMB->setInsertPolicy(QComboBox::NoInsert);
+ searchTextCMB->setDuplicatesEnabled(false);
+ for (unsigned int i = 0; i < m_hData.ugroups.size(); i++) {
+ QString s;
+ for (unsigned int j = 0; j < m_hData.ugroups[i].size(); j++) {
+ s.append(QString::fromUtf8(m_hData.ugroups[i][j].c_str()));
+ if (j != m_hData.ugroups[i].size()-1)
+ s.append(" ");
+ }
+ searchTextCMB->addItem(s);
+ }
+ searchTextCMB->setEditText("");
+
+ layout3->addWidget(searchTextCMB);
+
nextButton = new QPushButton(this);
nextButton->setEnabled(TRUE);
layout3->addWidget(nextButton);
@@ -160,7 +252,7 @@ void Preview::init()
resize(QSize(640, 480).expandedTo(minimumSizeHint()));
// buddies
- searchLabel->setBuddy(searchTextLine);
+ searchLabel->setBuddy(searchTextCMB);
searchLabel->setText(tr("&Search for:"));
nextButton->setText(tr("&Next"));
@@ -176,26 +268,25 @@ void Preview::init()
"RCL.SEARCH.PREVIEW");
// signals and slots connections
- connect(searchTextLine, SIGNAL(textChanged(const QString&)),
- this, SLOT(searchTextLine_textChanged(const QString&)));
+ connect(searchTextCMB, SIGNAL(activated(int)),
+ this, SLOT(searchTextFromIndex(int)));
+ connect(searchTextCMB, SIGNAL(editTextChanged(const QString&)),
+ this, SLOT(searchTextChanged(const QString&)));
connect(nextButton, SIGNAL(clicked()), this, SLOT(nextPressed()));
connect(prevButton, SIGNAL(clicked()), this, SLOT(prevPressed()));
- connect(clearPB, SIGNAL(clicked()), searchTextLine, SLOT(clear()));
+ connect(clearPB, SIGNAL(clicked()), searchTextCMB, SLOT(clearEditText()));
connect(pvTab, SIGNAL(currentChanged(QWidget *)),
this, SLOT(currentChanged(QWidget *)));
connect(bt, SIGNAL(clicked()), this, SLOT(closeCurrentTab()));
m_dynSearchActive = false;
m_canBeep = true;
- m_currentW = 0;
if (prefs.pvwidth > 100) {
resize(prefs.pvwidth, prefs.pvheight);
}
m_loading = false;
currentChanged(pvTab->currentWidget());
m_justCreated = true;
- m_haveAnchors = false;
- m_curAnchor = 1;
}
void Preview::closeEvent(QCloseEvent *e)
@@ -273,11 +364,11 @@ bool Preview::eventFilter(QObject *target, QEvent *event)
} else if (m_dynSearchActive) {
if (keyEvent->key() == Qt::Key_F3) {
LOGDEB2(("Preview::eventFilter: got F3\n"));
- doSearch(searchTextLine->text(), true, false);
+ doSearch(searchTextCMB->currentText(), true, false);
return true;
}
- if (target != searchTextLine)
- return QApplication::sendEvent(searchTextLine, event);
+ if (target != searchTextCMB)
+ return QApplication::sendEvent(searchTextCMB, event);
} else {
if (edit &&
(target == edit || target == edit->viewport())) {
@@ -285,7 +376,7 @@ bool Preview::eventFilter(QObject *target, QEvent *event)
(keyEvent->key() == Qt::Key_F &&
(keyEvent->modifiers() & Qt::ControlModifier))) {
LOGDEB2(("Preview::eventFilter: got / or C-F\n"));
- searchTextLine->setFocus();
+ searchTextCMB->setFocus();
m_dynSearchActive = true;
return true;
} else if (keyEvent->key() == Qt::Key_Space) {
@@ -307,23 +398,27 @@ bool Preview::eventFilter(QObject *target, QEvent *event)
return false;
}
-void Preview::searchTextLine_textChanged(const QString & text)
+void Preview::searchTextChanged(const QString & text)
{
- LOGDEB2(("search line text changed. text: '%s'\n", text.ascii()));
+ LOGDEB1(("Search line text changed. text: '%s'\n",
+ (const char *)text.toAscii()));
+ m_searchTextFromIndex = -1;
if (text.isEmpty()) {
m_dynSearchActive = false;
- // nextButton->setEnabled(false);
- // prevButton->setEnabled(false);
clearPB->setEnabled(false);
} else {
m_dynSearchActive = true;
- // nextButton->setEnabled(true);
- // prevButton->setEnabled(true);
clearPB->setEnabled(true);
doSearch(text, false, false);
}
}
+void Preview::searchTextFromIndex(int idx)
+{
+ LOGDEB1(("search line from index %d\n", idx));
+ m_searchTextFromIndex = idx;
+}
+
PreviewTextEdit *Preview::currentEditor()
{
LOGDEB2(("Preview::currentEditor()\n"));
@@ -351,9 +446,9 @@ void Preview::emitSaveDocToFile()
void Preview::doSearch(const QString &_text, bool next, bool reverse,
bool wordOnly)
{
- LOGDEB(("Preview::doSearch: text [%s] txtlen %d next %d rev %d word %d\n",
- (const char *)_text.toUtf8(), _text.length(), int(next),
- int(reverse), int(wordOnly)));
+ LOGDEB(("Preview::doSearch: text [%s] idx %d next %d rev %d word %d\n",
+ (const char *)_text.toUtf8(), m_searchTextFromIndex, int(next),
+ int(reverse), int(wordOnly)));
QString text = _text;
bool matchCase = matchCheck->isChecked();
@@ -363,25 +458,19 @@ void Preview::doSearch(const QString &_text, bool next, bool reverse,
return;
}
- if (text.isEmpty()) {
- if (m_haveAnchors == false) {
+ if (text.isEmpty() || m_searchTextFromIndex != -1) {
+ if (!edit->m_plaintorich->haveAnchors()) {
LOGDEB(("NO ANCHORS\n"));
return;
}
+ // The combobox indices are equal to the search ugroup indices
+ // in hldata, that's how we built the list.
if (reverse) {
- if (m_curAnchor == 1)
- m_curAnchor = edit->m_plaintorich->lastanchor;
- else
- m_curAnchor--;
+ edit->m_plaintorich->prevAnchorNum(m_searchTextFromIndex);
} else {
- if (m_curAnchor == edit->m_plaintorich->lastanchor)
- m_curAnchor = 1;
- else
- m_curAnchor++;
+ edit->m_plaintorich->nextAnchorNum(m_searchTextFromIndex);
}
- LOGDEB(("m_curAnchor: %d\n", m_curAnchor));
- QString aname =
- QString::fromUtf8(edit->m_plaintorich->termAnchorName(m_curAnchor).c_str());
+ QString aname = edit->m_plaintorich->curAnchorName();
LOGDEB(("Calling scrollToAnchor(%s)\n", (const char *)aname.toUtf8()));
edit->scrollToAnchor(aname);
// Position the cursor approximately at the anchor (top of
@@ -440,14 +529,14 @@ void Preview::doSearch(const QString &_text, bool next, bool reverse,
void Preview::nextPressed()
{
- LOGDEB2(("PreviewTextEdit::nextPressed\n"));
- doSearch(searchTextLine->text(), true, false);
+ LOGDEB2(("Preview::nextPressed\n"));
+ doSearch(searchTextCMB->currentText(), true, false);
}
void Preview::prevPressed()
{
- LOGDEB2(("PreviewTextEdit::prevPressed\n"));
- doSearch(searchTextLine->text(), true, true);
+ LOGDEB2(("Preview::prevPressed\n"));
+ doSearch(searchTextCMB->currentText(), true, true);
}
// Called when user clicks on tab
@@ -456,7 +545,6 @@ void Preview::currentChanged(QWidget * tw)
LOGDEB2(("PreviewTextEdit::currentChanged\n"));
PreviewTextEdit *edit =
tw->findChild("pvEdit");
- m_currentW = tw;
LOGDEB1(("Preview::currentChanged(). Editor: %p\n", edit));
if (edit == 0) {
@@ -470,7 +558,7 @@ void Preview::currentChanged(QWidget * tw)
connect(this, SIGNAL(printCurrentPreviewRequest()), edit, SLOT(print()));
edit->installEventFilter(this);
edit->viewport()->installEventFilter(this);
- searchTextLine->installEventFilter(this);
+ searchTextCMB->installEventFilter(this);
emit(previewExposed(this, m_searchId, edit->m_docnum));
}
@@ -507,7 +595,7 @@ PreviewTextEdit *Preview::addEditorTab()
void Preview::setCurTabProps(const Rcl::Doc &doc, int docnum)
{
- LOGDEB1(("PreviewTextEdit::setCurTabProps\n"));
+ LOGDEB1(("Preview::setCurTabProps\n"));
QString title;
string ctitle;
if (doc.getmeta(Rcl::Doc::keytt, &ctitle) && !ctitle.empty()) {
@@ -721,8 +809,6 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
LoadGuard guard(&m_loading);
CancelCheck::instance().setCancel(false);
- m_haveAnchors = false;
-
setCurTabProps(idoc, docnum);
QString msg = QString("Loading: %1 (size %2 bytes)")
@@ -956,23 +1042,20 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
// Position the editor so that the first search term is visible
- m_haveAnchors = editor->m_plaintorich->lastanchor != 0;
- if (searchTextLine->text().length() != 0) {
+ if (searchTextCMB->currentText().length() != 0) {
// If there is a current search string, perform the search
m_canBeep = true;
- doSearch(searchTextLine->text(), true, false);
+ doSearch(searchTextCMB->currentText(), true, false);
} else {
// Position to the first query term
- if (m_haveAnchors) {
- QString aname =
- QString::fromUtf8(editor->m_plaintorich->termAnchorName(1).c_str());
+ if (editor->m_plaintorich->haveAnchors()) {
+ QString aname = editor->m_plaintorich->curAnchorName();
LOGDEB2(("Call movetoanchor(%s)\n", (const char *)aname.toUtf8()));
editor->scrollToAnchor(aname);
// Position the cursor approximately at the anchor (top of
// viewport) so that searches start from here
QTextCursor cursor = editor->cursorForPosition(QPoint(0, 0));
editor->setTextCursor(cursor);
- m_curAnchor = 1;
}
}
@@ -989,14 +1072,15 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
return true;
}
-PreviewTextEdit::PreviewTextEdit(QWidget* parent,const char* name, Preview *pv)
- : QTextEdit(parent), m_preview(pv), m_dspflds(false), m_docnum(-1)
+PreviewTextEdit::PreviewTextEdit(QWidget* parent, const char* nm, Preview *pv)
+ : QTextEdit(parent), m_preview(pv),
+ m_plaintorich(new PlainToRichQtPreview()),
+ m_dspflds(false), m_docnum(-1)
{
setContextMenuPolicy(Qt::CustomContextMenu);
- setObjectName(name);
+ setObjectName(nm);
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(createPopupMenu(const QPoint&)));
- m_plaintorich = new PlainToRichQtPreview();
}
PreviewTextEdit::~PreviewTextEdit()
diff --git a/src/qtgui/preview_w.h b/src/qtgui/preview_w.h
index f9b1591b..ab479376 100644
--- a/src/qtgui/preview_w.h
+++ b/src/qtgui/preview_w.h
@@ -58,22 +58,27 @@ protected:
void mouseDoubleClickEvent(QMouseEvent *);
private:
- PlainToRichQtPreview *m_plaintorich;
Preview *m_preview;
- bool m_dspflds;
+ PlainToRichQtPreview *m_plaintorich;
+
+ bool m_dspflds;
string m_url; // filename for this tab
string m_ipath; // Internal doc path inside file
int m_docnum; // Index of doc in db search results.
+
// doc out of internfile (previous fields come from the index) with
// main text erased (for space).
Rcl::Doc m_fdoc;
+
// The input doc out of the index/query list
Rcl::Doc m_dbdoc;
+
// Saved rich (or plain actually) text: the textedit seems to
// sometimes (but not always) return its text stripped of tags, so
// this is needed (for printing for example)
QString m_richtxt;
Qt::TextFormat m_format;
+
// Temporary file name (possibly, if displaying image). The
// TempFile itself is kept inside main.cpp (because that's where
// signal cleanup happens), but we use its name to ask for release
@@ -92,14 +97,14 @@ class Preview : public QWidget {
Preview(int sid, // Search Id
const HighlightData& hdata) // Search terms etc. for highlighting
- : QWidget(0), m_searchId(sid), m_hData(hdata)
+ : QWidget(0), m_searchId(sid), m_searchTextFromIndex(-1), m_hData(hdata)
{
init();
}
- ~Preview(){}
virtual void closeEvent(QCloseEvent *e );
virtual bool eventFilter(QObject *target, QEvent *event );
+
/**
* Arrange for the document to be displayed either by exposing the tab
* if already loaded, or by creating a new tab and loading it.
@@ -112,7 +117,8 @@ class Preview : public QWidget {
friend class PreviewTextEdit;
public slots:
- virtual void searchTextLine_textChanged(const QString& text);
+ virtual void searchTextChanged(const QString& text);
+ virtual void searchTextFromIndex(int);
virtual void doSearch(const QString& str, bool next, bool reverse,
bool wo = false);
virtual void nextPressed();
@@ -138,18 +144,17 @@ private:
int m_searchId;
bool m_dynSearchActive;
+ // Index value the search text comes from. -1 if text was edited
+ int m_searchTextFromIndex;
+
bool m_canBeep;
bool m_loading;
- QWidget *m_currentW;
HighlightData m_hData;
bool m_justCreated; // First tab create is different
- bool m_haveAnchors; // Search terms are marked in text
- int m_lastAnchor; // Number of last anchor. Then rewind to 1
- int m_curAnchor;
QTabWidget* pvTab;
QLabel* searchLabel;
- QLineEdit* searchTextLine;
+ QComboBox *searchTextCMB;
QPushButton* nextButton;
QPushButton* prevButton;
QPushButton* clearPB;
diff --git a/src/qtgui/reslist.cpp b/src/qtgui/reslist.cpp
index c3fc7ddb..491d93cf 100644
--- a/src/qtgui/reslist.cpp
+++ b/src/qtgui/reslist.cpp
@@ -250,12 +250,22 @@ string QtGuiResListPager::iconUrl(RclConfig *config, Rcl::Doc& doc)
class PlainToRichQtReslist : public PlainToRich {
public:
- virtual ~PlainToRichQtReslist() {}
- virtual string startMatch() {
+ virtual string startMatch(unsigned int idx)
+ {
+ if (m_hdata) {
+ string s1, s2;
+ stringsToString >(m_hdata->groups[idx], s1);
+ stringsToString >(m_hdata->ugroups[m_hdata->grpsugidx[idx]], s2);
+ LOGDEB(("Reslist startmatch: group %s user group %s\n", s1.c_str(), s2.c_str()));
+ }
+
return string("");
}
- virtual string endMatch() {return string("");}
+ virtual string endMatch()
+ {
+ return string("");
+ }
};
static PlainToRichQtReslist g_hiliter;
diff --git a/src/qtgui/ssearch_w.h b/src/qtgui/ssearch_w.h
index f1156f42..16176c39 100644
--- a/src/qtgui/ssearch_w.h
+++ b/src/qtgui/ssearch_w.h
@@ -38,7 +38,6 @@ public:
setupUi(this);
init();
}
- ~SSearch(){}
virtual void init();
virtual void setAnyTermMode();
diff --git a/src/query/plaintorich.cpp b/src/query/plaintorich.cpp
index 57e32d18..8cb45ad7 100644
--- a/src/query/plaintorich.cpp
+++ b/src/query/plaintorich.cpp
@@ -49,13 +49,22 @@ static string vecStringToString(const vector& t)
return sterms;
}
+struct MatchEntry {
+ pair offs;
+ unsigned int grpidx;
+ MatchEntry(int sta, int sto, unsigned int idx)
+ : offs(sta, sto), grpidx(idx)
+ {
+ }
+};
+
// Text splitter used to take note of the position of query terms
// inside the result text. This is then used to insert highlight tags.
class TextSplitPTR : public TextSplit {
public:
// Out: begin and end byte positions of query terms/groups in text
- vector > tboffs;
+ vector tboffs;
TextSplitPTR(const HighlightData& hdata)
: m_wcount(0), m_hdata(hdata)
@@ -67,7 +76,7 @@ class TextSplitPTR : public TextSplit {
for (vector >::const_iterator vit = hdata.groups.begin();
vit != hdata.groups.end(); vit++) {
if (vit->size() == 1) {
- m_terms.insert(vit->front());
+ m_terms[vit->front()] = vit - hdata.groups.begin();
} else if (vit->size() > 1) {
for (vector::const_iterator it = vit->begin();
it != vit->end(); it++) {
@@ -91,8 +100,9 @@ class TextSplitPTR : public TextSplit {
// pos, bts, bte));
// If this word is a search term, remember its byte-offset span.
- if (m_terms.find(dumb) != m_terms.end()) {
- tboffs.push_back(pair(bts, bte));
+ map::const_iterator it = m_terms.find(dumb);
+ if (it != m_terms.end()) {
+ tboffs.push_back(MatchEntry(bts, bte, (*it).second));
}
// If word is part of a search group, update its positions list
@@ -114,13 +124,13 @@ class TextSplitPTR : public TextSplit {
virtual bool matchGroups();
private:
- virtual bool matchGroup(const vector& terms, int dist);
+ virtual bool matchGroup(unsigned int idx);
// Word count. Used to call checkCancel from time to time.
int m_wcount;
// In: user query terms
- set m_terms;
+ map m_terms;
// m_gterms holds all the terms in m_groups, as a set for quick lookup
set m_gterms;
@@ -191,9 +201,12 @@ static bool do_proximity_test(int window, vector* >& plists,
return false;
}
-// Find NEAR matches for the input group of terms, update highlight map
-bool TextSplitPTR::matchGroup(const vector& terms, int window)
+// Find NEAR matches for one group of terms, update highlight map
+bool TextSplitPTR::matchGroup(unsigned int grpidx)
{
+ const vector& terms = m_hdata.groups[grpidx];
+ int window = m_hdata.groups[grpidx].size() + m_hdata.slacks[grpidx];
+
LOGDEB0(("TextSplitPTR::matchGroup:d %d: %s\n", window,
vecStringToString(terms).c_str()));
@@ -203,26 +216,23 @@ bool TextSplitPTR::matchGroup(const vector& terms, int window)
// A revert plist->term map. This is so that we can find who is who after
// sorting the plists by length.
map*, string> plistToTerm;
- // For traces
- vector realgroup;
- // Find the position list for each term in the group. Not all
- // necessarily exist (esp for NEAR where terms have been
- // stem-expanded: we don't know which matched)
+ // Find the position list for each term in the group. It is
+ // possible that this particular group was not actually matched by
+ // the search, so that some terms are not found.
for (vector::const_iterator it = terms.begin();
it != terms.end(); it++) {
map >::iterator pl = m_plists.find(*it);
if (pl == m_plists.end()) {
LOGDEB0(("TextSplitPTR::matchGroup: [%s] not found in m_plists\n",
(*it).c_str()));
- continue;
+ return false;
}
plists.push_back(&(pl->second));
plistToTerm[&(pl->second)] = *it;
- realgroup.push_back(*it);
}
- LOGDEB0(("TextSplitPTR::matchGroup:d %d:real group after expansion %s\n",
- window, vecStringToString(realgroup).c_str()));
+ // I think this can't actually happen, was useful when we used to
+ // prune the groups, but doesn't hurt.
if (plists.size() < 2) {
LOGDEB0(("TextSplitPTR::matchGroup: no actual groups found\n"));
return false;
@@ -261,15 +271,13 @@ bool TextSplitPTR::matchGroup(const vector& terms, int window)
SETMINMAX(pos, sta, sto);
minpos = sto+1;
// Translate the position window into a byte offset window
- int bs = 0;
map >::iterator i1 = m_gpostobytes.find(sta);
map >::iterator i2 = m_gpostobytes.find(sto);
if (i1 != m_gpostobytes.end() && i2 != m_gpostobytes.end()) {
LOGDEB0(("TextSplitPTR::matchGroup: pushing bpos %d %d\n",
i1->second.first, i2->second.second));
- tboffs.push_back(pair(i1->second.first,
- i2->second.second));
- bs = i1->second.first;
+ tboffs.push_back(MatchEntry(i1->second.first,
+ i2->second.second, grpidx));
} else {
LOGDEB(("matchGroup: no bpos found for %d or %d\n", sta, sto));
}
@@ -284,22 +292,23 @@ bool TextSplitPTR::matchGroup(const vector& terms, int window)
/** Sort integer pairs by increasing first value and decreasing width */
class PairIntCmpFirst {
public:
- bool operator()(pair a, pairb) {
- if (a.first != b.first)
- return a.first < b.first;
- return a.second > b.second;
+ bool operator()(const MatchEntry& a, const MatchEntry& b) {
+ if (a.offs.first != b.offs.first)
+ return a.offs.first < b.offs.first;
+ return a.offs.second > b.offs.second;
}
};
-// Look for matches to PHRASE and NEAR term groups. Actually, we
-// handle all groups as NEAR (ignore order).
+// Look for matches to PHRASE and NEAR term groups and finalize the
+// matched regions list (sort it by increasing start then decreasing
+// length)
+// Actually, we handle all groups as NEAR (ignore order).
bool TextSplitPTR::matchGroups()
{
for (unsigned int i = 0; i < m_hdata.groups.size(); i++) {
if (m_hdata.groups[i].size() <= 1)
continue;
- matchGroup(m_hdata.groups[i],
- m_hdata.groups[i].size() + m_hdata.slacks[i]);
+ matchGroup(i);
}
// Sort regions by increasing start and decreasing width.
@@ -324,6 +333,7 @@ bool PlainToRich::plaintorich(const string& in,
{
Chrono chron;
+ m_hdata = &hdata;
// Compute the positions for the query terms. We use the text
// splitter to break the text into words, and compare the words to
// the search terms,
@@ -346,8 +356,8 @@ bool PlainToRich::plaintorich(const string& in,
// Iterator for the list of input term positions. We use it to
// output highlight tags and to compute term positions in the
// output text
- vector >::iterator tPosIt = splitter.tboffs.begin();
- vector >::iterator tPosEnd = splitter.tboffs.end();
+ vector::iterator tPosIt = splitter.tboffs.begin();
+ vector::iterator tPosEnd = splitter.tboffs.end();
#if 0
for (vector >::const_iterator it = splitter.tboffs.begin();
@@ -365,8 +375,6 @@ bool PlainToRich::plaintorich(const string& in,
int hadcr = 0;
int inindent = 1;
- // Value for numbered anchors at each term match
- int anchoridx = 1;
// HTML state
bool intag = false, inparamvalue = false;
// My tag state
@@ -391,22 +399,20 @@ bool PlainToRich::plaintorich(const string& in,
// we are at or after a term match, mark.
if (tPosIt != tPosEnd) {
int ibyteidx = chariter.getBpos();
- if (ibyteidx == tPosIt->first) {
+ if (ibyteidx == tPosIt->offs.first) {
if (!intag && ibyteidx >= (int)headend) {
- *olit += startAnchor(anchoridx);
- *olit += startMatch();
+ *olit += startMatch(tPosIt->grpidx);
}
- anchoridx++;
inrcltag = 1;
- } else if (ibyteidx == tPosIt->second) {
+ } else if (ibyteidx == tPosIt->offs.second) {
// Output end of match region tags
if (!intag && ibyteidx > (int)headend) {
*olit += endMatch();
- *olit += endAnchor();
}
// Skip all highlight areas that would overlap this one
- int crend = tPosIt->second;
- while (tPosIt != splitter.tboffs.end() && tPosIt->first < crend)
+ int crend = tPosIt->offs.second;
+ while (tPosIt != splitter.tboffs.end() &&
+ tPosIt->offs.first < crend)
tPosIt++;
inrcltag = 0;
}
diff --git a/src/query/plaintorich.h b/src/query/plaintorich.h
index 21ddbc98..cbb13d9e 100644
--- a/src/query/plaintorich.h
+++ b/src/query/plaintorich.h
@@ -21,6 +21,7 @@
#include
#include "hldata.h"
+#include "cstr.h"
/**
* A class for highlighting search results. Overridable methods allow
@@ -31,7 +32,7 @@
class PlainToRich {
public:
PlainToRich()
- : m_inputhtml(false)
+ : m_inputhtml(false), m_eolbr(false), m_hdata(0)
{
}
@@ -71,18 +72,35 @@ public:
);
/* Overridable output methods for headers, highlighting and marking tags */
- virtual std::string header() {return snull;}
- virtual std::string startMatch() {return snull;}
- virtual std::string endMatch() {return snull;}
- virtual std::string startAnchor(int) {return snull;}
- virtual std::string endAnchor() {return snull;}
- virtual std::string startChunk() {return snull;}
+
+ virtual std::string header()
+ {
+ return cstr_null;
+ }
+
+ /** Return match prefix (e.g.: ).
+ @param groupidx the index into hdata.groups */
+ virtual std::string startMatch(unsigned int)
+ {
+ return cstr_null;
+ }
+
+ /** Return data for end of match area (e.g.: ). */
+ virtual std::string endMatch()
+ {
+ return cstr_null;
+ }
+
+ virtual std::string startChunk()
+ {
+ return cstr_null;
+ }
protected:
- const std::string snull;
bool m_inputhtml;
// Use
to break plain text lines (else caller has used a tag)
bool m_eolbr;
+ const HighlightData *m_hdata;
};
#endif /* _PLAINTORICH_H_INCLUDED_ */
diff --git a/src/query/reslistpager.cpp b/src/query/reslistpager.cpp
index 7027dd94..9718709f 100644
--- a/src/query/reslistpager.cpp
+++ b/src/query/reslistpager.cpp
@@ -40,9 +40,14 @@ static const string cstr_hlfontcolor("");
static const string cstr_hlendfont("");
class PlainToRichHtReslist : public PlainToRich {
public:
- virtual ~PlainToRichHtReslist() {}
- virtual string startMatch() {return cstr_hlfontcolor;}
- virtual string endMatch() {return cstr_hlendfont;}
+ virtual string startMatch(unsigned int)
+ {
+ return cstr_hlfontcolor;
+ }
+ virtual string endMatch()
+ {
+ return cstr_hlendfont;
+ }
};
static PlainToRichHtReslist g_hiliter;