summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/lookupwidget.c64
1 files changed, 54 insertions, 10 deletions
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c
index 74f394e6..52f3d864 100644
--- a/src/ui/lookupwidget.c
+++ b/src/ui/lookupwidget.c
@@ -21,12 +21,14 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22 22
23#include "lookupwidget.h" 23#include "lookupwidget.h"
24#include "documentwidget.h"
24#include "lookup.h" 25#include "lookup.h"
25#include "listwidget.h" 26#include "listwidget.h"
26#include "inputwidget.h" 27#include "inputwidget.h"
27#include "util.h" 28#include "util.h"
28#include "command.h" 29#include "command.h"
29#include "bookmarks.h" 30#include "bookmarks.h"
31#include "history.h"
30#include "visited.h" 32#include "visited.h"
31#include "gmutil.h" 33#include "gmutil.h"
32#include "app.h" 34#include "app.h"
@@ -40,12 +42,14 @@ iDeclareType(LookupJob)
40struct Impl_LookupJob { 42struct Impl_LookupJob {
41 iRegExp *term; 43 iRegExp *term;
42 iTime now; 44 iTime now;
45 iObjectList *docs;
43 iPtrArray results; 46 iPtrArray results;
44}; 47};
45 48
46static void init_LookupJob(iLookupJob *d) { 49static void init_LookupJob(iLookupJob *d) {
47 d->term = NULL; 50 d->term = NULL;
48 initCurrent_Time(&d->now); 51 initCurrent_Time(&d->now);
52 d->docs = NULL;
49 init_PtrArray(&d->results); 53 init_PtrArray(&d->results);
50} 54}
51 55
@@ -54,6 +58,7 @@ static void deinit_LookupJob(iLookupJob *d) {
54 delete_LookupResult(i.ptr); 58 delete_LookupResult(i.ptr);
55 } 59 }
56 deinit_PtrArray(&d->results); 60 deinit_PtrArray(&d->results);
61 iRelease(d->docs);
57 iRelease(d->term); 62 iRelease(d->term);
58} 63}
59 64
@@ -125,7 +130,8 @@ struct Impl_LookupWidget {
125 iThread * work; 130 iThread * work;
126 iCondition jobAvailable; /* wakes up the work thread */ 131 iCondition jobAvailable; /* wakes up the work thread */
127 iMutex * mtx; 132 iMutex * mtx;
128 iString nextJob; 133 iString pendingTerm;
134 iObjectList *pendingDocs;
129 iLookupJob * finishedJob; 135 iLookupJob * finishedJob;
130}; 136};
131 137
@@ -200,13 +206,37 @@ static void searchVisited_LookupJob_(iLookupJob *d) {
200 } 206 }
201} 207}
202 208
209static void searchHistory_LookupJob_(iLookupJob *d) {
210 /* Note: Called in a background thread. */
211 size_t index = 0;
212 iForEach(ObjectList, i, d->docs) {
213 iConstForEach(StringArray, j,
214 searchContents_History(history_DocumentWidget(i.object), d->term)) {
215 const char *match = cstr_String(j.value);
216 const size_t matchLen = argLabel_Command(match, "len");
217 iRangecc text;
218 text.start = strstr(match, " str:") + 5;
219 text.end = text.start + matchLen;
220 const char *url = strstr(text.end, " url:") + 5;
221 iLookupResult *res = new_LookupResult();
222 res->type = content_LookupResultType;
223 res->relevance = ++index; /* most recent comes last */
224 setCStr_String(&res->label, "...");
225 appendRange_String(&res->label, text);
226 appendCStr_String(&res->label, "...");
227 setCStr_String(&res->url, url);
228 pushBack_PtrArray(&d->results, res);
229 }
230 }
231}
232
203static iThreadResult worker_LookupWidget_(iThread *thread) { 233static iThreadResult worker_LookupWidget_(iThread *thread) {
204 iLookupWidget *d = userData_Thread(thread); 234 iLookupWidget *d = userData_Thread(thread);
205 printf("[LookupWidget] worker is running\n"); fflush(stdout); 235 printf("[LookupWidget] worker is running\n"); fflush(stdout);
206 lock_Mutex(d->mtx); 236 lock_Mutex(d->mtx);
207 for (;;) { 237 for (;;) {
208 wait_Condition(&d->jobAvailable, d->mtx); 238 wait_Condition(&d->jobAvailable, d->mtx);
209 if (isEmpty_String(&d->nextJob)) { 239 if (isEmpty_String(&d->pendingTerm)) {
210 break; /* Time to quit. */ 240 break; /* Time to quit. */
211 } 241 }
212 iLookupJob *job = new_LookupJob(); 242 iLookupJob *job = new_LookupJob();
@@ -214,7 +244,7 @@ static iThreadResult worker_LookupWidget_(iThread *thread) {
214 iString *pattern = new_String(); 244 iString *pattern = new_String();
215 iRangecc word = iNullRange; 245 iRangecc word = iNullRange;
216 iBool isFirst = iTrue; 246 iBool isFirst = iTrue;
217 while (nextSplit_Rangecc(range_String(&d->nextJob), " ", &word)) { 247 while (nextSplit_Rangecc(range_String(&d->pendingTerm), " ", &word)) {
218 if (isEmpty_Range(&word)) continue; 248 if (isEmpty_Range(&word)) continue;
219 if (!isFirst) appendChar_String(pattern, '|'); 249 if (!isFirst) appendChar_String(pattern, '|');
220 for (const char *ch = word.start; ch != word.end; ch++) { 250 for (const char *ch = word.start; ch != word.end; ch++) {
@@ -230,11 +260,14 @@ static iThreadResult worker_LookupWidget_(iThread *thread) {
230 job->term = new_RegExp(cstr_String(pattern), caseInsensitive_RegExpOption); 260 job->term = new_RegExp(cstr_String(pattern), caseInsensitive_RegExpOption);
231 delete_String(pattern); 261 delete_String(pattern);
232 } 262 }
233 clear_String(&d->nextJob); 263 clear_String(&d->pendingTerm);
264 job->docs = d->pendingDocs;
265 d->pendingDocs = NULL;
234 unlock_Mutex(d->mtx); 266 unlock_Mutex(d->mtx);
235 /* Do the lookup. */ { 267 /* Do the lookup. */ {
236 searchBookmarks_LookupJob_(job); 268 searchBookmarks_LookupJob_(job);
237 searchVisited_LookupJob_(job); 269 searchVisited_LookupJob_(job);
270 searchHistory_LookupJob_(job);
238 } 271 }
239 /* Submit the result. */ 272 /* Submit the result. */
240 lock_Mutex(d->mtx); 273 lock_Mutex(d->mtx);
@@ -266,7 +299,8 @@ void init_LookupWidget(iLookupWidget *d) {
266 setUserData_Thread(d->work, d); 299 setUserData_Thread(d->work, d);
267 init_Condition(&d->jobAvailable); 300 init_Condition(&d->jobAvailable);
268 d->mtx = new_Mutex(); 301 d->mtx = new_Mutex();
269 init_String(&d->nextJob); 302 init_String(&d->pendingTerm);
303 d->pendingDocs = NULL;
270 d->finishedJob = NULL; 304 d->finishedJob = NULL;
271 start_Thread(d->work); 305 start_Thread(d->work);
272} 306}
@@ -274,23 +308,26 @@ void init_LookupWidget(iLookupWidget *d) {
274void deinit_LookupWidget(iLookupWidget *d) { 308void deinit_LookupWidget(iLookupWidget *d) {
275 /* Stop the worker. */ { 309 /* Stop the worker. */ {
276 iGuardMutex(d->mtx, { 310 iGuardMutex(d->mtx, {
277 clear_String(&d->nextJob); 311 iReleasePtr(&d->pendingDocs);
312 clear_String(&d->pendingTerm);
278 signal_Condition(&d->jobAvailable); 313 signal_Condition(&d->jobAvailable);
279 }); 314 });
280 join_Thread(d->work); 315 join_Thread(d->work);
281 iRelease(d->work); 316 iRelease(d->work);
282 } 317 }
283 delete_LookupJob(d->finishedJob); 318 delete_LookupJob(d->finishedJob);
284 deinit_String(&d->nextJob); 319 deinit_String(&d->pendingTerm);
285 delete_Mutex(d->mtx); 320 delete_Mutex(d->mtx);
286 deinit_Condition(&d->jobAvailable); 321 deinit_Condition(&d->jobAvailable);
287} 322}
288 323
289void submit_LookupWidget(iLookupWidget *d, const iString *term) { 324void submit_LookupWidget(iLookupWidget *d, const iString *term) {
290 iGuardMutex(d->mtx, { 325 iGuardMutex(d->mtx, {
291 set_String(&d->nextJob, term); 326 set_String(&d->pendingTerm, term);
292 trim_String(&d->nextJob); 327 trim_String(&d->pendingTerm);
293 if (!isEmpty_String(&d->nextJob)) { 328 iReleasePtr(&d->pendingDocs);
329 if (!isEmpty_String(&d->pendingTerm)) {
330 d->pendingDocs = listDocuments_App(); /* holds reference to all open tabs */
294 signal_Condition(&d->jobAvailable); 331 signal_Condition(&d->jobAvailable);
295 } 332 }
296 else { 333 else {
@@ -386,6 +423,13 @@ static void presentResults_LookupWidget_(iLookupWidget *d) {
386 format_String(&item->command, "open url:%s", cstr_String(&res->url)); 423 format_String(&item->command, "open url:%s", cstr_String(&res->url));
387 break; 424 break;
388 } 425 }
426 case content_LookupResultType: {
427 item->fg = uiText_ColorId;
428 item->font = uiContent_FontId;
429 format_String(&item->text, "%s \u2014 %s", cstr_String(&res->label), url);
430 format_String(&item->command, "open url:%s", cstr_String(&res->url));
431 break;
432 }
389 } 433 }
390 addItem_ListWidget(d->list, item); 434 addItem_ListWidget(d->list, item);
391 iRelease(item); 435 iRelease(item);