--- a/src/qtgui/plaintorich.cpp
+++ b/src/qtgui/plaintorich.cpp
@@ -1,5 +1,5 @@
#ifndef lint
-static char rcsid[] = "@(#$Id: plaintorich.cpp,v 1.17 2006-11-18 12:56:16 dockes Exp $ (C) 2005 J.F.Dockes";
+static char rcsid[] = "@(#$Id: plaintorich.cpp,v 1.18 2006-11-30 13:38:44 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@@ -62,6 +62,8 @@
// Out: first query term found in text
string firstTerm;
int firstTermOcc;
+ int m_firstTermPos;
+ int m_firstTermBPos;
// Out: begin and end byte positions of query terms/groups in text
vector<pair<int, int> > tboffs;
@@ -96,6 +98,7 @@
if (firstTerm.empty()) {
firstTerm = term;
m_firstTermPos = pos;
+ m_firstTermBPos = bts;
}
}
@@ -117,7 +120,6 @@
virtual bool matchGroup(const vector<string>& terms, int dist);
int m_wcount;
- int m_firstTermPos;
// In: user query terms
set<string> m_terms;
@@ -239,6 +241,20 @@
LOGDEB0(("myTextSplitCB::matchGroup: MATCH [%d,%d]\n", sta, sto));
+ // Translate the position window into a byte offset window
+ int bs = 0;
+ map<int, pair<int, int> >::iterator i1 = m_gpostobytes.find(sta);
+ map<int, pair<int, int> >::iterator i2 = m_gpostobytes.find(sto);
+ if (i1 != m_gpostobytes.end() && i2 != m_gpostobytes.end()) {
+ LOGDEB1(("myTextSplitCB::matchGroup: pushing %d %d\n",
+ i1->second.first, i2->second.second));
+ tboffs.push_back(pair<int, int>(i1->second.first, i2->second.second));
+ bs = i1->second.first;
+ } else {
+ LOGDEB(("myTextSplitCB::matchGroup: no bpos found for %d or %d\n",
+ sta, sto));
+ }
+
if (firstTerm.empty() || m_firstTermPos > sta) {
// firsTerm is used to try an position the preview window over
// the match. As it's difficult to divine byte/word positions
@@ -252,31 +268,24 @@
firstTerm = it->second;
LOGDEB(("myTextSplitCB:: best group term %s, firstTermOcc %d\n",
firstTerm.c_str(), firstTermOcc));
- }
-
- // Translate the position window into a byte offset window
- map<int, pair<int, int> >::iterator i1 = m_gpostobytes.find(sta);
- map<int, pair<int, int> >::iterator i2 = m_gpostobytes.find(sto);
- if (i1 != m_gpostobytes.end() && i2 != m_gpostobytes.end()) {
- LOGDEB1(("myTextSplitCB::matchGroup: pushing %d %d\n",
- i1->second.first, i2->second.second));
- tboffs.push_back(pair<int, int>(i1->second.first, i2->second.second));
- } else {
- LOGDEB(("myTextSplitCB::matchGroup: no bpos found for %d or %d\n",
- sta, sto));
+ m_firstTermPos = sta;
+ m_firstTermBPos = bs;
}
return true;
}
-/** Sort integer pairs by their first value */
+/** Sort integer pairs by increasing first value and decreasing width */
class PairIntCmpFirst {
public:
bool operator()(pair<int,int> a, pair<int, int>b) {
- return a.first < b.first;
+ if (a.first != b.first)
+ return a.first < b.first;
+ return a.second > b.second;
}
};
+// Do the phrase match thing, then merge the highlight lists
bool myTextSplitCB::matchGroups()
{
vector<vector<string> >::const_iterator vit = m_groups.begin();
@@ -285,9 +294,17 @@
matchGroup(*vit, *sit + (*vit).size());
}
+ // Sort by start and end offsets. The merging of overlapping entries
+ // will be handled during output.
std::sort(tboffs.begin(), tboffs.end(), PairIntCmpFirst());
return true;
}
+
+const char *firstTermAnchorName = "FIRSTTERM";
+
+#ifdef QT_SCROLL_TO_ANCHOR_BUG
+const char *firstTermBeacon = "\xe2\xa0\x91\xe2\x96\x9f\x20\x01\x9a";
+#endif
// Fix result text for display inside the gui text window.
//
@@ -300,9 +317,7 @@
// editor's find() function to position on it
bool plaintorich(const string& in, string& out,
RefCntr<Rcl::SearchData> sdata,
- string *firstTerm,
- int *firstTermOcc,
- bool noHeader)
+ bool noHeader, bool fft)
{
Chrono chron;
out.erase();
@@ -338,11 +353,6 @@
cb.matchGroups();
- if (firstTerm)
- *firstTerm = cb.firstTerm;
- if (firstTermOcc)
- *firstTermOcc = cb.firstTermOcc;
-
// Rich text output
if (noHeader)
out = "";
@@ -376,12 +386,24 @@
// If we still have terms positions, check (byte) position
if (tPosIt != tboffsend) {
int ibyteidx = chariter.getBpos();
+
+ if (fft && ibyteidx == cb.m_firstTermBPos) {
+ out += string("<a name=\"") + firstTermAnchorName + "\"> "
+#ifdef QT_SCROLL_TO_ANCHOR_BUG
+ + "<font color=\"white\"> " + firstTermBeacon + " </font> "
+#endif
+ + "</a>";
+ }
+
if (ibyteidx == tPosIt->first) {
out += "<termtag>";
} else if (ibyteidx == tPosIt->second) {
- if (tPosIt != cb.tboffs.end())
+ // Output end tag, then skip all highlight areas that
+ // would overlap this one
+ out += "</termtag>";
+ int crend = tPosIt->second;
+ while (tPosIt != cb.tboffs.end() && tPosIt->first < crend)
tPosIt++;
- out += "</termtag>";
}
}
switch(*chariter) {
@@ -414,7 +436,7 @@
}
#if 0
{
- FILE *fp = fopen("/tmp/debugplaintorich", "w");
+ FILE *fp = fopen("/tmp/debugplaintorich", "a");
fprintf(fp, "%s\n", out.c_str());
fclose(fp);
}