summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--src/history.c27
-rw-r--r--src/lookup.c39
-rw-r--r--src/lookup.h46
-rw-r--r--src/ui/listwidget.c9
-rw-r--r--src/ui/lookupwidget.c134
-rw-r--r--src/ui/lookupwidget.h30
-rw-r--r--src/ui/sidebarwidget.c2
-rw-r--r--src/ui/window.c3
9 files changed, 289 insertions, 5 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 789e32f9..2018c4c1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,6 +61,8 @@ set (SOURCES
61 src/gmutil.h 61 src/gmutil.h
62 src/history.c 62 src/history.c
63 src/history.h 63 src/history.h
64 src/lookup.c
65 src/lookup.h
64 src/stb_image.h 66 src/stb_image.h
65 src/stb_truetype.h 67 src/stb_truetype.h
66 src/visited.c 68 src/visited.c
@@ -74,6 +76,8 @@ set (SOURCES
74 src/ui/documentwidget.h 76 src/ui/documentwidget.h
75 src/ui/listwidget.c 77 src/ui/listwidget.c
76 src/ui/listwidget.h 78 src/ui/listwidget.h
79 src/ui/lookupwidget.c
80 src/ui/lookupwidget.h
77 src/ui/metrics.c 81 src/ui/metrics.c
78 src/ui/metrics.h 82 src/ui/metrics.h
79 src/ui/paint.c 83 src/ui/paint.c
diff --git a/src/history.c b/src/history.c
index 6e985903..63fa1104 100644
--- a/src/history.c
+++ b/src/history.c
@@ -24,6 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
24#include "app.h" 24#include "app.h"
25 25
26#include <the_Foundation/file.h> 26#include <the_Foundation/file.h>
27#include <the_Foundation/mutex.h>
27#include <the_Foundation/path.h> 28#include <the_Foundation/path.h>
28 29
29static const size_t maxStack_History_ = 50; /* back/forward navigable items */ 30static const size_t maxStack_History_ = 50; /* back/forward navigable items */
@@ -52,6 +53,7 @@ iRecentUrl *copy_RecentUrl(const iRecentUrl *d) {
52/*----------------------------------------------------------------------------------------------*/ 53/*----------------------------------------------------------------------------------------------*/
53 54
54struct Impl_History { 55struct Impl_History {
56 iMutex *mtx;
55 iArray recent; /* TODO: should be specific to a DocumentWidget */ 57 iArray recent; /* TODO: should be specific to a DocumentWidget */
56 size_t recentPos; /* zero at the latest item */ 58 size_t recentPos; /* zero at the latest item */
57}; 59};
@@ -59,6 +61,7 @@ struct Impl_History {
59iDefineTypeConstruction(History) 61iDefineTypeConstruction(History)
60 62
61void init_History(iHistory *d) { 63void init_History(iHistory *d) {
64 d->mtx = new_Mutex();
62 init_Array(&d->recent, sizeof(iRecentUrl)); 65 init_Array(&d->recent, sizeof(iRecentUrl));
63 d->recentPos = 0; 66 d->recentPos = 0;
64} 67}
@@ -66,18 +69,22 @@ void init_History(iHistory *d) {
66void deinit_History(iHistory *d) { 69void deinit_History(iHistory *d) {
67 clear_History(d); 70 clear_History(d);
68 deinit_Array(&d->recent); 71 deinit_Array(&d->recent);
72 delete_Mutex(d->mtx);
69} 73}
70 74
71iHistory *copy_History(const iHistory *d) { 75iHistory *copy_History(const iHistory *d) {
76 lock_Mutex(d->mtx);
72 iHistory *copy = new_History(); 77 iHistory *copy = new_History();
73 iConstForEach(Array, i, &d->recent) { 78 iConstForEach(Array, i, &d->recent) {
74 pushBack_Array(&copy->recent, copy_RecentUrl(i.value)); 79 pushBack_Array(&copy->recent, copy_RecentUrl(i.value));
75 } 80 }
76 copy->recentPos = d->recentPos; 81 copy->recentPos = d->recentPos;
82 unlock_Mutex(d->mtx);
77 return copy; 83 return copy;
78} 84}
79 85
80void serialize_History(const iHistory *d, iStream *outs) { 86void serialize_History(const iHistory *d, iStream *outs) {
87 lock_Mutex(d->mtx);
81 writeU16_Stream(outs, d->recentPos); 88 writeU16_Stream(outs, d->recentPos);
82 writeU16_Stream(outs, size_Array(&d->recent)); 89 writeU16_Stream(outs, size_Array(&d->recent));
83 iConstForEach(Array, i, &d->recent) { 90 iConstForEach(Array, i, &d->recent) {
@@ -92,10 +99,12 @@ void serialize_History(const iHistory *d, iStream *outs) {
92 write8_Stream(outs, 0); 99 write8_Stream(outs, 0);
93 } 100 }
94 } 101 }
102 unlock_Mutex(d->mtx);
95} 103}
96 104
97void deserialize_History(iHistory *d, iStream *ins) { 105void deserialize_History(iHistory *d, iStream *ins) {
98 clear_History(d); 106 clear_History(d);
107 lock_Mutex(d->mtx);
99 d->recentPos = readU16_Stream(ins); 108 d->recentPos = readU16_Stream(ins);
100 size_t count = readU16_Stream(ins); 109 size_t count = readU16_Stream(ins);
101 while (count--) { 110 while (count--) {
@@ -109,13 +118,16 @@ void deserialize_History(iHistory *d, iStream *ins) {
109 } 118 }
110 pushBack_Array(&d->recent, &item); 119 pushBack_Array(&d->recent, &item);
111 } 120 }
121 unlock_Mutex(d->mtx);
112} 122}
113 123
114void clear_History(iHistory *d) { 124void clear_History(iHistory *d) {
125 lock_Mutex(d->mtx);
115 iForEach(Array, s, &d->recent) { 126 iForEach(Array, s, &d->recent) {
116 deinit_RecentUrl(s.value); 127 deinit_RecentUrl(s.value);
117 } 128 }
118 clear_Array(&d->recent); 129 clear_Array(&d->recent);
130 unlock_Mutex(d->mtx);
119} 131}
120 132
121iRecentUrl *recentUrl_History(iHistory *d, size_t pos) { 133iRecentUrl *recentUrl_History(iHistory *d, size_t pos) {
@@ -145,23 +157,29 @@ const iString *url_History(const iHistory *d, size_t pos) {
145} 157}
146 158
147iRecentUrl *findUrl_History(iHistory *d, const iString *url) { 159iRecentUrl *findUrl_History(iHistory *d, const iString *url) {
160 lock_Mutex(d->mtx);
148 iReverseForEach(Array, i, &d->recent) { 161 iReverseForEach(Array, i, &d->recent) {
149 if (cmpStringCase_String(url, &((iRecentUrl *) i.value)->url) == 0) { 162 if (cmpStringCase_String(url, &((iRecentUrl *) i.value)->url) == 0) {
163 unlock_Mutex(d->mtx);
150 return i.value; 164 return i.value;
151 } 165 }
152 } 166 }
167 unlock_Mutex(d->mtx);
153 return NULL; 168 return NULL;
154} 169}
155 170
156void replace_History(iHistory *d, const iString *url) { 171void replace_History(iHistory *d, const iString *url) {
172 lock_Mutex(d->mtx);
157 /* Update in the history. */ 173 /* Update in the history. */
158 iRecentUrl *item = mostRecentUrl_History(d); 174 iRecentUrl *item = mostRecentUrl_History(d);
159 if (item) { 175 if (item) {
160 set_String(&item->url, url); 176 set_String(&item->url, url);
161 } 177 }
178 unlock_Mutex(d->mtx);
162} 179}
163 180
164void add_History(iHistory *d, const iString *url ){ 181void add_History(iHistory *d, const iString *url ){
182 lock_Mutex(d->mtx);
165 /* Cut the trailing history items. */ 183 /* Cut the trailing history items. */
166 if (d->recentPos > 0) { 184 if (d->recentPos > 0) {
167 for (size_t i = 0; i < d->recentPos - 1; i++) { 185 for (size_t i = 0; i < d->recentPos - 1; i++) {
@@ -183,27 +201,34 @@ void add_History(iHistory *d, const iString *url ){
183 remove_Array(&d->recent, 0); 201 remove_Array(&d->recent, 0);
184 } 202 }
185 } 203 }
204 unlock_Mutex(d->mtx);
186} 205}
187 206
188iBool goBack_History(iHistory *d) { 207iBool goBack_History(iHistory *d) {
208 lock_Mutex(d->mtx);
189 if (d->recentPos < size_Array(&d->recent) - 1) { 209 if (d->recentPos < size_Array(&d->recent) - 1) {
190 d->recentPos++; 210 d->recentPos++;
191 postCommandf_App("open history:1 scroll:%f url:%s", 211 postCommandf_App("open history:1 scroll:%f url:%s",
192 mostRecentUrl_History(d)->normScrollY, 212 mostRecentUrl_History(d)->normScrollY,
193 cstr_String(url_History(d, d->recentPos))); 213 cstr_String(url_History(d, d->recentPos)));
214 unlock_Mutex(d->mtx);
194 return iTrue; 215 return iTrue;
195 } 216 }
217 unlock_Mutex(d->mtx);
196 return iFalse; 218 return iFalse;
197} 219}
198 220
199iBool goForward_History(iHistory *d) { 221iBool goForward_History(iHistory *d) {
222 lock_Mutex(d->mtx);
200 if (d->recentPos > 0) { 223 if (d->recentPos > 0) {
201 d->recentPos--; 224 d->recentPos--;
202 postCommandf_App("open history:1 scroll:%f url:%s", 225 postCommandf_App("open history:1 scroll:%f url:%s",
203 mostRecentUrl_History(d)->normScrollY, 226 mostRecentUrl_History(d)->normScrollY,
204 cstr_String(url_History(d, d->recentPos))); 227 cstr_String(url_History(d, d->recentPos)));
228 unlock_Mutex(d->mtx);
205 return iTrue; 229 return iTrue;
206 } 230 }
231 unlock_Mutex(d->mtx);
207 return iFalse; 232 return iFalse;
208} 233}
209 234
@@ -213,6 +238,7 @@ const iGmResponse *cachedResponse_History(const iHistory *d) {
213} 238}
214 239
215void setCachedResponse_History(iHistory *d, const iGmResponse *response) { 240void setCachedResponse_History(iHistory *d, const iGmResponse *response) {
241 lock_Mutex(d->mtx);
216 iRecentUrl *item = mostRecentUrl_History(d); 242 iRecentUrl *item = mostRecentUrl_History(d);
217 if (item) { 243 if (item) {
218 delete_GmResponse(item->cachedResponse); 244 delete_GmResponse(item->cachedResponse);
@@ -221,4 +247,5 @@ void setCachedResponse_History(iHistory *d, const iGmResponse *response) {
221 item->cachedResponse = copy_GmResponse(response); 247 item->cachedResponse = copy_GmResponse(response);
222 } 248 }
223 } 249 }
250 unlock_Mutex(d->mtx);
224} 251}
diff --git a/src/lookup.c b/src/lookup.c
new file mode 100644
index 00000000..4f00a66a
--- /dev/null
+++ b/src/lookup.c
@@ -0,0 +1,39 @@
1/* Copyright 2020 Jaakko Keränen <jaakko.keranen@iki.fi>
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are met:
5
61. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
82. Redistributions in binary form must reproduce the above copyright notice,
9 this list of conditions and the following disclaimer in the documentation
10 and/or other materials provided with the distribution.
11
12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23#include "lookup.h"
24
25iDefineTypeConstruction(LookupResult)
26
27void init_LookupResult(iLookupResult *d) {
28 d->type = none_LookupResultType;
29 init_String(&d->label);
30 init_String(&d->url);
31 init_String(&d->meta);
32 iZap(d->when);
33}
34
35void deinit_LookupResult(iLookupResult *d) {
36 deinit_String(&d->meta);
37 deinit_String(&d->url);
38 deinit_String(&d->label);
39}
diff --git a/src/lookup.h b/src/lookup.h
new file mode 100644
index 00000000..ecbe0036
--- /dev/null
+++ b/src/lookup.h
@@ -0,0 +1,46 @@
1/* Copyright 2020 Jaakko Keränen <jaakko.keranen@iki.fi>
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are met:
5
61. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
82. Redistributions in binary form must reproduce the above copyright notice,
9 this list of conditions and the following disclaimer in the documentation
10 and/or other materials provided with the distribution.
11
12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23#pragma once
24
25#include <the_Foundation/string.h>
26#include <the_Foundation/time.h>
27
28iDeclareType(LookupResult)
29
30enum iLookupResultType {
31 none_LookupResultType,
32 bookmark_LookupResultType,
33 history_LookupResultType, /* visited URLs */
34 content_LookupResultType, /* one of the pages in history, including current page */
35 identity_LookupResultType,
36};
37
38struct Impl_LookupResult {
39 enum iLookupResultType type;
40 iString label;
41 iString url;
42 iString meta;
43 iTime when;
44};
45
46iDeclareTypeConstruction(LookupResult)
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c
index 64e509ef..3c061bdc 100644
--- a/src/ui/listwidget.c
+++ b/src/ui/listwidget.c
@@ -62,7 +62,6 @@ struct Impl_ListWidget {
62 SDL_Texture *visBuffer[2]; 62 SDL_Texture *visBuffer[2];
63 int visBufferIndex; 63 int visBufferIndex;
64 int visBufferScrollY; 64 int visBufferScrollY;
65// iBool visBufferValid;
66 enum iBufferValidity visBufferValid; 65 enum iBufferValidity visBufferValid;
67}; 66};
68 67
@@ -70,6 +69,7 @@ void init_ListWidget(iListWidget *d) {
70 iWidget *w = as_Widget(d); 69 iWidget *w = as_Widget(d);
71 init_Widget(w); 70 init_Widget(w);
72 setId_Widget(w, "list"); 71 setId_Widget(w, "list");
72 setBackgroundColor_Widget(w, uiBackground_ColorId); /* needed for filling visbuffer */
73 setFlags_Widget(w, hover_WidgetFlag, iTrue); 73 setFlags_Widget(w, hover_WidgetFlag, iTrue);
74 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); 74 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget()));
75 setThumb_ScrollWidget(d->scroll, 0, 0); 75 setThumb_ScrollWidget(d->scroll, 0, 0);
@@ -150,7 +150,6 @@ int scrollPos_ListWidget(const iListWidget *d) {
150void setScrollPos_ListWidget(iListWidget *d, int pos) { 150void setScrollPos_ListWidget(iListWidget *d, int pos) {
151 d->scrollY = pos; 151 d->scrollY = pos;
152 d->hoverItem = iInvalidPos; 152 d->hoverItem = iInvalidPos;
153// invalidate_ListWidget(d);
154 d->visBufferValid = partial_BufferValidity; 153 d->visBufferValid = partial_BufferValidity;
155 refresh_Widget(as_Widget(d)); 154 refresh_Widget(as_Widget(d));
156} 155}
@@ -166,7 +165,6 @@ void scrollOffset_ListWidget(iListWidget *d, int offset) {
166 if (oldScroll != d->scrollY) { 165 if (oldScroll != d->scrollY) {
167 d->hoverItem = iInvalidPos; 166 d->hoverItem = iInvalidPos;
168 updateVisible_ListWidget(d); 167 updateVisible_ListWidget(d);
169 //invalidate_ListWidget(d);
170 d->visBufferValid = partial_BufferValidity; 168 d->visBufferValid = partial_BufferValidity;
171 refresh_Widget(as_Widget(d)); 169 refresh_Widget(as_Widget(d));
172 } 170 }
@@ -178,6 +176,9 @@ static int visCount_ListWidget_(const iListWidget *d) {
178} 176}
179 177
180static iRanges visRange_ListWidget_(const iListWidget *d) { 178static iRanges visRange_ListWidget_(const iListWidget *d) {
179 if (d->itemHeight == 0) {
180 return (iRanges){ 0, 0 };
181 }
181 iRanges vis = { d->scrollY / d->itemHeight, 0 }; 182 iRanges vis = { d->scrollY / d->itemHeight, 0 };
182 vis.end = iMin(size_PtrArray(&d->items), vis.start + visCount_ListWidget_(d)); 183 vis.end = iMin(size_PtrArray(&d->items), vis.start + visCount_ListWidget_(d));
183 return vis; 184 return vis;
@@ -186,7 +187,7 @@ static iRanges visRange_ListWidget_(const iListWidget *d) {
186size_t itemIndex_ListWidget(const iListWidget *d, iInt2 pos) { 187size_t itemIndex_ListWidget(const iListWidget *d, iInt2 pos) {
187 const iRect bounds = innerBounds_Widget(constAs_Widget(d)); 188 const iRect bounds = innerBounds_Widget(constAs_Widget(d));
188 pos.y -= top_Rect(bounds) - d->scrollY; 189 pos.y -= top_Rect(bounds) - d->scrollY;
189 if (pos.y < 0) return iInvalidPos; 190 if (pos.y < 0 || !d->itemHeight) return iInvalidPos;
190 size_t index = pos.y / d->itemHeight; 191 size_t index = pos.y / d->itemHeight;
191 if (index >= size_Array(&d->items)) return iInvalidPos; 192 if (index >= size_Array(&d->items)) return iInvalidPos;
192 return index; 193 return index;
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c
new file mode 100644
index 00000000..d2550c16
--- /dev/null
+++ b/src/ui/lookupwidget.c
@@ -0,0 +1,134 @@
1/* Copyright 2020 Jaakko Keränen <jaakko.keranen@iki.fi>
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are met:
5
61. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
82. Redistributions in binary form must reproduce the above copyright notice,
9 this list of conditions and the following disclaimer in the documentation
10 and/or other materials provided with the distribution.
11
12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23#include "lookupwidget.h"
24#include "lookup.h"
25#include "listwidget.h"
26
27#include <the_Foundation/mutex.h>
28#include <the_Foundation/thread.h>
29
30iDeclareType(LookupJob)
31
32struct Impl_LookupJob {
33 iString term;
34 iPtrArray results;
35};
36
37static void init_LookupJob(iLookupJob *d) {
38 init_String(&d->term);
39 init_PtrArray(&d->results);
40}
41
42static void deinit_LookupJob(iLookupJob *d) {
43 iForEach(PtrArray, i, &d->results) {
44 delete_LookupResult(i.ptr);
45 }
46 deinit_PtrArray(&d->results);
47 deinit_String(&d->term);
48}
49
50iDefineTypeConstruction(LookupJob)
51
52struct Impl_LookupWidget {
53 iWidget widget;
54 iListWidget *list;
55 iThread *work;
56 iCondition jobAvailable; /* wakes up the work thread */
57 iMutex *mtx;
58 iString nextJob;
59 iLookupJob *finishedJob;
60};
61
62static iThreadResult worker_LookupWidget_(iThread *thread) {
63 iLookupWidget *d = userData_Thread(thread);
64 lock_Mutex(d->mtx);
65 for (;;) {
66 wait_Condition(&d->jobAvailable, d->mtx);
67 if (isEmpty_String(&d->nextJob)) {
68 break; /* Time to quit. */
69 }
70 iLookupJob *job = new_LookupJob();
71 set_String(&job->term, &d->nextJob);
72 clear_String(&d->nextJob);
73 unlock_Mutex(d->mtx);
74 /* Do the lookup. */ {
75
76 }
77 /* Submit the result. */
78 lock_Mutex(d->mtx);
79 if (d->finishedJob) {
80 /* Previous results haven't been taken yet. */
81 delete_LookupJob(d->finishedJob);
82 }
83 d->finishedJob = job;
84 }
85 unlock_Mutex(d->mtx);
86 printf("[LookupWidget] worker has quit\n"); fflush(stdout);
87 return 0;
88}
89
90iDefineObjectConstruction(LookupWidget)
91
92void init_LookupWidget(iLookupWidget *d) {
93 iWidget *w = as_Widget(d);
94 init_Widget(w);
95 setId_Widget(w, "lookup");
96 setFlags_Widget(w, resizeChildren_WidgetFlag, iTrue);
97 d->list = addChild_Widget(w, iClob(new_ListWidget()));
98 d->work = new_Thread(worker_LookupWidget_);
99 setUserData_Thread(d->work, d);
100 init_Condition(&d->jobAvailable);
101 d->mtx = new_Mutex();
102 init_String(&d->nextJob);
103 d->finishedJob = NULL;
104}
105
106void deinit_LookupWidget(iLookupWidget *d) {
107 /* Stop the worker. */ {
108 iGuardMutex(d->mtx, {
109 clear_String(&d->nextJob);
110 signal_Condition(&d->jobAvailable);
111 });
112 join_Thread(d->work);
113 iRelease(d->work);
114 }
115 delete_LookupJob(d->finishedJob);
116 deinit_String(&d->nextJob);
117 delete_Mutex(d->mtx);
118 deinit_Condition(&d->jobAvailable);
119}
120
121static void draw_LookupWidget_(const iLookupWidget *d) {
122 const iWidget *w = constAs_Widget(d);
123 draw_Widget(w);
124}
125
126static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) {
127 iWidget *w = as_Widget(d);
128 return processEvent_Widget(w, ev);
129}
130
131iBeginDefineSubclass(LookupWidget, Widget)
132 .draw = (iAny *) draw_LookupWidget_,
133 .processEvent = (iAny *) processEvent_LookupWidget_,
134iEndDefineSubclass(LookupWidget)
diff --git a/src/ui/lookupwidget.h b/src/ui/lookupwidget.h
new file mode 100644
index 00000000..31bcbcb9
--- /dev/null
+++ b/src/ui/lookupwidget.h
@@ -0,0 +1,30 @@
1/* Copyright 2020 Jaakko Keränen <jaakko.keranen@iki.fi>
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are met:
5
61. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
82. Redistributions in binary form must reproduce the above copyright notice,
9 this list of conditions and the following disclaimer in the documentation
10 and/or other materials provided with the distribution.
11
12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23#pragma once
24
25#include "widget.h"
26
27iDeclareWidgetClass(LookupWidget)
28iDeclareObjectConstruction(LookupWidget)
29
30
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 50b8ef9b..e84967cc 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -503,7 +503,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
503 const iBool wasChanged = setMode_SidebarWidget(d, arg_Command(cmd)); 503 const iBool wasChanged = setMode_SidebarWidget(d, arg_Command(cmd));
504 updateItems_SidebarWidget_(d); 504 updateItems_SidebarWidget_(d);
505 if ((argLabel_Command(cmd, "show") && !isVisible_Widget(w)) || 505 if ((argLabel_Command(cmd, "show") && !isVisible_Widget(w)) ||
506 (argLabel_Command(cmd, "toggle") && !wasChanged)) { 506 (argLabel_Command(cmd, "toggle") && (!isVisible_Widget(w) || !wasChanged))) {
507 postCommand_App("sidebar.toggle"); 507 postCommand_App("sidebar.toggle");
508 } 508 }
509 scrollOffset_ListWidget(d->list, 0); 509 scrollOffset_ListWidget(d->list, 0);
diff --git a/src/ui/window.c b/src/ui/window.c
index dabf80de..78567bb5 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -26,6 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
26#include "inputwidget.h" 26#include "inputwidget.h"
27#include "documentwidget.h" 27#include "documentwidget.h"
28#include "sidebarwidget.h" 28#include "sidebarwidget.h"
29#include "lookupwidget.h"
29#include "embedded.h" 30#include "embedded.h"
30#include "command.h" 31#include "command.h"
31#include "paint.h" 32#include "paint.h"
@@ -404,6 +405,8 @@ static void setupUserInterface_Window(iWindow *d) {
404 addChild_Widget(searchBar, iClob(newIcon_LabelWidget(" \u2b9d ", 'g', KMOD_PRIMARY | KMOD_SHIFT, "find.prev"))); 405 addChild_Widget(searchBar, iClob(newIcon_LabelWidget(" \u2b9d ", 'g', KMOD_PRIMARY | KMOD_SHIFT, "find.prev")));
405 addChild_Widget(searchBar, iClob(newIcon_LabelWidget("\u2a2f", SDLK_ESCAPE, 0, "find.close"))); 406 addChild_Widget(searchBar, iClob(newIcon_LabelWidget("\u2a2f", SDLK_ESCAPE, 0, "find.close")));
406 } 407 }
408 iLookupWidget *lookup = new_LookupWidget();
409 addChildFlags_Widget(d->root, iClob(lookup), hidden_WidgetFlag);
407 iWidget *tabsMenu = makeMenu_Widget(d->root, 410 iWidget *tabsMenu = makeMenu_Widget(d->root,
408 (iMenuItem[]){ 411 (iMenuItem[]){
409 { "Close Tab", 0, 0, "tabs.close" }, 412 { "Close Tab", 0, 0, "tabs.close" },