diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/lookupwidget.c | 64 |
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 | |||
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | 21 | SOFTWARE, 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) | |||
40 | struct Impl_LookupJob { | 42 | struct 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 | ||
46 | static void init_LookupJob(iLookupJob *d) { | 49 | static 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 | ||
209 | static 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 | |||
203 | static iThreadResult worker_LookupWidget_(iThread *thread) { | 233 | static 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) { | |||
274 | void deinit_LookupWidget(iLookupWidget *d) { | 308 | void 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 | ||
289 | void submit_LookupWidget(iLookupWidget *d, const iString *term) { | 324 | void 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); |