diff --git a/.hgignore b/.hgignore
index 39713dc7..eb520974 100644
--- a/.hgignore
+++ b/.hgignore
@@ -7,6 +7,7 @@ syntax: glob
src/Makefile
src/autom4te.cache
src/bincimapmime/alldeps
+src/common/alldeps
src/common/autoconfig.h
src/common/rclversion.h
src/config.log
@@ -19,20 +20,19 @@ src/desktop/unity-lens-recoll/config.status
src/desktop/unity-lens-recoll/data/recoll.lens
src/desktop/unity-lens-recoll/data/unity-lens-recoll.service
src/doc/user/HTML.manifest
-src/doc/user/index.html
src/doc/user/RCL.INDEXING.CONFIG.html
-src/doc/user/RCL.INDEXING.html
src/doc/user/RCL.INDEXING.MONITOR.html
src/doc/user/RCL.INDEXING.PERIODIC.html
src/doc/user/RCL.INDEXING.STORAGE.html
src/doc/user/RCL.INDEXING.WEBQUEUE.html
+src/doc/user/RCL.INDEXING.html
src/doc/user/RCL.INSTALL.BUILDING.html
src/doc/user/RCL.INSTALL.CONFIG.html
src/doc/user/RCL.INSTALL.EXTERNAL.html
src/doc/user/RCL.INSTALL.html
-src/doc/user/RCL.INTRODUCTION.html
src/doc/user/RCL.INTRODUCTION.RECOLL.html
src/doc/user/RCL.INTRODUCTION.SEARCH.html
+src/doc/user/RCL.INTRODUCTION.html
src/doc/user/RCL.KICKER-APPLET.html
src/doc/user/RCL.PROGRAM.API.html
src/doc/user/RCL.PROGRAM.FIELDS.html
@@ -44,7 +44,6 @@ src/doc/user/RCL.SEARCH.COMPLEX.html
src/doc/user/RCL.SEARCH.CUSTOM.html
src/doc/user/RCL.SEARCH.DESKTOP.html
src/doc/user/RCL.SEARCH.HISTORY.html
-src/doc/user/RCL.SEARCH.html
src/doc/user/RCL.SEARCH.KIO.html
src/doc/user/RCL.SEARCH.LANG.html
src/doc/user/RCL.SEARCH.MULTIDB.html
@@ -54,9 +53,11 @@ src/doc/user/RCL.SEARCH.SORT.html
src/doc/user/RCL.SEARCH.TERMEXPLORER.html
src/doc/user/RCL.SEARCH.TIPS.html
src/doc/user/RCL.SEARCH.WILDCARDS.html
+src/doc/user/RCL.SEARCH.html
src/doc/user/RCL.SEARCHKCL.html
-src/doc/user/RCL.SEARCHKIO.html
src/doc/user/RCL.SEARCHKIO.SEARCHABLEDOCS.html
+src/doc/user/RCL.SEARCHKIO.html
+src/doc/user/index.html
src/doc/user/usermanual-xml.html
src/doc/user/usermanual.aux
src/doc/user/usermanual.html
@@ -73,6 +74,7 @@ src/filters/rcllatinclass.pyc
src/index/alldeps
src/index/alldeps.stamp
src/index/recollindex
+src/internfile/alldeps
src/kde/kioslave/kio_recoll/builddir
src/lib/alldeps
src/lib/librecoll.a
@@ -98,6 +100,7 @@ src/query/xadump
src/recollinstall
src/sampleconf/rclmon.sh
src/sampleconf/recoll.conf
+src/utils/alldeps
tests/config/aspdict.en.rws
tests/config/history
tests/config/idxstatus.txt
diff --git a/src/python/recoll/pyrecoll.cpp b/src/python/recoll/pyrecoll.cpp
index b83879f8..c10b47dc 100644
--- a/src/python/recoll/pyrecoll.cpp
+++ b/src/python/recoll/pyrecoll.cpp
@@ -206,7 +206,8 @@ SearchData_addclause(recoll_SearchDataObject* self, PyObject *args,
case 'E':
if (strcasecmp(tp, "excl"))
goto defaultcase;
- cl = new Rcl::SearchDataClauseSimple(Rcl::SCLT_EXCL, qs, fld?fld:"");
+ cl = new Rcl::SearchDataClauseSimple(Rcl::SCLT_OR, qs, fld?fld:"");
+ cl->setexclude(true);
break;
case 'n':
case 'N':
diff --git a/src/qtgui/advshist.cpp b/src/qtgui/advshist.cpp
index 9703c030..5f08d18f 100644
--- a/src/qtgui/advshist.cpp
+++ b/src/qtgui/advshist.cpp
@@ -57,6 +57,7 @@ private:
slack = 0;
d = m = y = di.d1 = di.m1 = di.y1 = di.d2 = di.m2 = di.y2 = 0;
hasdates = false;
+ exclude = false;
}
// Temporary data while parsing.
@@ -67,6 +68,7 @@ private:
int d, m, y;
DateInterval di;
bool hasdates;
+ bool exclude;
};
bool SDHXMLHandler::startElement(const QString & /* namespaceURI */,
@@ -101,6 +103,8 @@ bool SDHXMLHandler::endElement(const QString & /* namespaceURI */,
}
} else if (qName == "CT") {
whatclause = currentText.trimmed();
+ } else if (qName == "NEG") {
+ exclude = true;
} else if (qName == "F") {
field = base64_decode(qs2utf8s(currentText.trimmed()));
} else if (qName == "T") {
@@ -111,16 +115,24 @@ bool SDHXMLHandler::endElement(const QString & /* namespaceURI */,
SearchDataClause *c;
if (whatclause == "AND" || whatclause.isEmpty()) {
c = new SearchDataClauseSimple(SCLT_AND, text, field);
+ c->setexclude(exclude);
} else if (whatclause == "OR") {
c = new SearchDataClauseSimple(SCLT_OR, text, field);
+ c->setexclude(exclude);
} else if (whatclause == "EX") {
- c = new SearchDataClauseSimple(SCLT_EXCL, text, field);
+ // Compat with old hist. We don't generete EX (SCLT_EXCL) anymore
+ // it's replaced with OR + exclude flag
+ c = new SearchDataClauseSimple(SCLT_OR, text, field);
+ c->setexclude(true);
} else if (whatclause == "FN") {
c = new SearchDataClauseFilename(text);
+ c->setexclude(exclude);
} else if (whatclause == "PH") {
c = new SearchDataClauseDist(SCLT_PHRASE, text, slack, field);
+ c->setexclude(exclude);
} else if (whatclause == "NE") {
c = new SearchDataClauseDist(SCLT_NEAR, text, slack, field);
+ c->setexclude(exclude);
} else {
LOGERR(("Bad clause type [%s]\n", qs2utf8s(whatclause).c_str()));
return false;
@@ -130,6 +142,7 @@ bool SDHXMLHandler::endElement(const QString & /* namespaceURI */,
text.clear();
field.clear();
slack = 0;
+ exclude = false;
} else if (qName == "D") {
d = atoi((const char *)currentText.toAscii());
} else if (qName == "M") {
diff --git a/src/qtgui/searchclause_w.cpp b/src/qtgui/searchclause_w.cpp
index 4fb90a44..c7999c31 100644
--- a/src/qtgui/searchclause_w.cpp
+++ b/src/qtgui/searchclause_w.cpp
@@ -119,7 +119,12 @@ SearchDataClause *SearchClauseW::getClause()
case 1:
return new SearchDataClauseSimple(SCLT_AND, text, field);
case 2:
- return new SearchDataClauseSimple(SCLT_EXCL, text, field);
+ {
+ SearchDataClauseSimple *cl =
+ new SearchDataClauseSimple(SCLT_OR, text, field);
+ cl->setexclude(true);
+ return cl;
+ }
case 3:
return new SearchDataClauseDist(SCLT_PHRASE, text,
proxSlackSB->value(), field);
@@ -139,9 +144,8 @@ void SearchClauseW::setFromClause(SearchDataClauseSimple *cl)
{
LOGDEB(("SearchClauseW::setFromClause\n"));
switch(cl->getTp()) {
- case SCLT_OR: tpChange(0); break;
+ case SCLT_OR: if (cl->getexclude()) tpChange(2); else tpChange(0); break;
case SCLT_AND: tpChange(1); break;
- case SCLT_EXCL: tpChange(2); break;
case SCLT_PHRASE: tpChange(3); break;
case SCLT_NEAR: tpChange(4); break;
case SCLT_FILENAME: tpChange(5); break;
@@ -154,7 +158,7 @@ void SearchClauseW::setFromClause(SearchDataClauseSimple *cl)
QString field = QString::fromUtf8(cl->getfield().c_str());
switch(cl->getTp()) {
- case SCLT_OR: case SCLT_AND: case SCLT_EXCL:
+ case SCLT_OR: case SCLT_AND:
case SCLT_PHRASE: case SCLT_NEAR:
if (!field.isEmpty()) {
int idx = fldCMB->findText(field);
diff --git a/src/query/recollq.cpp b/src/query/recollq.cpp
index 22a9da63..d16b3e73 100644
--- a/src/query/recollq.cpp
+++ b/src/query/recollq.cpp
@@ -168,6 +168,9 @@ int recollq(RclConfig **cfp, int argc, char **argv)
Usage();
while (**argv)
switch (*(*argv)++) {
+ case '-':
+ // -- : end of options
+ goto endopts;
case 'A': op_flags |= OPT_A; break;
case 'a': op_flags |= OPT_a; break;
case 'b': op_flags |= OPT_b; break;
@@ -216,6 +219,7 @@ int recollq(RclConfig **cfp, int argc, char **argv)
}
b1: argc--; argv++;
}
+endopts:
string reason;
*cfp = recollinit(0, 0, reason, &a_config);
diff --git a/src/query/wasatorcl.cpp b/src/query/wasatorcl.cpp
index a418d265..35edf380 100644
--- a/src/query/wasatorcl.cpp
+++ b/src/query/wasatorcl.cpp
@@ -195,39 +195,32 @@ static Rcl::SearchData *wasaQueryToRcl(const RclConfig *config,
// dir filtering special case
nclause = new Rcl::SearchDataClausePath((*it)->m_value,
(*it)->m_exclude);
- } else if ((*it)->m_exclude) {
- if (wasa->m_op != WasaQuery::OP_AND) {
+ } else {
+ if ((*it)->m_exclude && wasa->m_op != WasaQuery::OP_AND) {
LOGERR(("wasaQueryToRcl: excl clause inside OR list!\n"));
continue;
}
- // Note: have to add dquotes which will be translated to
- // phrase if there are several words in there. Not pretty
- // but should work. If there is actually a single
- // word, it will not be taken as a phrase, and
- // stem-expansion will work normally
- // Have to do this because searchdata has nothing like and_not
- nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_EXCL,
- string("\"") +
- (*it)->m_value + "\"",
- (*it)->m_fieldspec);
- } else {
// I'm not sure I understand the phrase/near detection
// thereafter anymore, maybe it would be better to have an
// explicit flag. Mods can only be set after a double
// quote.
if (TextSplit::hasVisibleWhite((*it)->m_value) || mods) {
- Rcl::SClType tp = Rcl::SCLT_PHRASE;
- if (mods & WasaQuery::WQM_PROX) {
- tp = Rcl::SCLT_NEAR;
- }
+
+ Rcl::SClType tp = (mods & WasaQuery::WQM_PROX) ?
+ Rcl::SCLT_NEAR :
+ Rcl::SCLT_PHRASE;
nclause = new Rcl::SearchDataClauseDist(tp, (*it)->m_value,
(*it)->m_slack,
(*it)->m_fieldspec);
} else {
- nclause = new Rcl::SearchDataClauseSimple(Rcl::SCLT_AND,
- (*it)->m_value,
- (*it)->m_fieldspec);
+ Rcl::SClType tp = (*it)->m_exclude ?
+ Rcl::SCLT_OR:
+ Rcl::SCLT_AND;
+ nclause =
+ new Rcl::SearchDataClauseSimple(tp, (*it)->m_value,
+ (*it)->m_fieldspec);
}
+ nclause->setexclude((*it)->m_exclude);
}
if (nclause == 0) {
diff --git a/src/rcldb/searchdata.cpp b/src/rcldb/searchdata.cpp
index 01f2a282..694aab2d 100644
--- a/src/rcldb/searchdata.cpp
+++ b/src/rcldb/searchdata.cpp
@@ -128,7 +128,7 @@ bool SearchData::clausesToQuery(Rcl::Db &db, SClType tp,
// addClause())
Xapian::Query::op op;
if (tp == SCLT_AND) {
- if ((*it)->m_tp == SCLT_EXCL || (*it)->getexclude()) {
+ if ((*it)->getexclude()) {
op = Xapian::Query::OP_AND_NOT;
} else {
op = Xapian::Query::OP_AND;
@@ -388,7 +388,7 @@ bool SearchData::maybeAddAutoPhrase(Rcl::Db& db, double freqThreshold)
// Add clause to current list. OR lists cant have EXCL clauses.
bool SearchData::addClause(SearchDataClause* cl)
{
- if (m_tp == SCLT_OR && (cl->m_tp == SCLT_EXCL || cl->getexclude())) {
+ if (m_tp == SCLT_OR && cl->getexclude()) {
LOGERR(("SearchData::addClause: cant add EXCL to OR list\n"));
m_reason = "No Negative (AND_NOT) clauses allowed in OR queries";
return false;
@@ -1075,7 +1075,7 @@ bool SearchDataClauseSimple::processUserString(Rcl::Db &db, const string &iq,
return true;
}
-// Translate a simple OR, AND, or EXCL search clause.
+// Translate a simple OR or AND search clause.
bool SearchDataClauseSimple::toNativeQuery(Rcl::Db &db, void *p)
{
LOGDEB2(("SearchDataClauseSimple::toNativeQuery: stemlang [%s]\n",
@@ -1087,9 +1087,7 @@ bool SearchDataClauseSimple::toNativeQuery(Rcl::Db &db, void *p)
Xapian::Query::op op;
switch (m_tp) {
case SCLT_AND: op = Xapian::Query::OP_AND; break;
- // EXCL will be set with AND_NOT in the list. So it's an OR list here
- case SCLT_OR:
- case SCLT_EXCL: op = Xapian::Query::OP_OR; break;
+ case SCLT_OR: op = Xapian::Query::OP_OR; break;
default:
LOGERR(("SearchDataClauseSimple: bad m_tp %d\n", m_tp));
return false;
diff --git a/src/rcldb/searchdata.h b/src/rcldb/searchdata.h
index 258a8ca1..b3dc7b80 100644
--- a/src/rcldb/searchdata.h
+++ b/src/rcldb/searchdata.h
@@ -41,7 +41,7 @@ namespace Rcl {
/** Search clause types */
enum SClType {
SCLT_AND,
- SCLT_OR, SCLT_EXCL, SCLT_FILENAME, SCLT_PHRASE, SCLT_NEAR, SCLT_PATH,
+ SCLT_OR, SCLT_FILENAME, SCLT_PHRASE, SCLT_NEAR, SCLT_PATH,
SCLT_SUB
};
@@ -283,6 +283,10 @@ public:
{
return m_exclude;
}
+ virtual void setexclude(bool onoff)
+ {
+ m_exclude = onoff;
+ }
friend class SearchData;
protected:
diff --git a/src/rcldb/searchdataxml.cpp b/src/rcldb/searchdataxml.cpp
index d7841d5b..f2d90641 100644
--- a/src/rcldb/searchdataxml.cpp
+++ b/src/rcldb/searchdataxml.cpp
@@ -38,7 +38,6 @@ static string tpToString(SClType tp)
switch (tp) {
case SCLT_AND: return "AND";
case SCLT_OR: return "OR";
- case SCLT_EXCL: return "EX";
case SCLT_FILENAME: return "FN";
case SCLT_PHRASE: return "PH";
case SCLT_NEAR: return "NE";
@@ -65,8 +64,8 @@ string SearchData::asXML()
LOGERR(("SearchData::asXML: can't do subclauses !\n"));
continue;
}
- //if (c->getexclude())
- // os << "" << endl;
+ if (c->getexclude())
+ os << "" << endl;
if (c->getTp() == SCLT_PATH) {
// Keep these apart, for compat with the older history format
SearchDataClausePath *cl =