summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--po/en.po12
-rw-r--r--res/lang/de.binbin22448 -> 22653 bytes
-rw-r--r--res/lang/en.binbin20956 -> 21161 bytes
-rw-r--r--res/lang/es.binbin23338 -> 23543 bytes
-rw-r--r--res/lang/fi.binbin23537 -> 23742 bytes
-rw-r--r--res/lang/fr.binbin23871 -> 24076 bytes
-rw-r--r--res/lang/ia.binbin23176 -> 23381 bytes
-rw-r--r--res/lang/ie.binbin22770 -> 22975 bytes
-rw-r--r--res/lang/pl.binbin24109 -> 24314 bytes
-rw-r--r--res/lang/ru.binbin34427 -> 34632 bytes
-rw-r--r--res/lang/sr.binbin34162 -> 34367 bytes
-rw-r--r--res/lang/tok.binbin21352 -> 21557 bytes
-rw-r--r--res/lang/zh_Hans.binbin20128 -> 20333 bytes
-rw-r--r--res/lang/zh_Hant.binbin20313 -> 20518 bytes
-rw-r--r--src/app.c3
-rw-r--r--src/sitespec.c158
-rw-r--r--src/sitespec.h37
-rw-r--r--src/ui/uploadwidget.c61
19 files changed, 266 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5b5fa9cd..b4b3a9c1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -150,6 +150,8 @@ set (SOURCES
150 src/periodic.h 150 src/periodic.h
151 src/prefs.c 151 src/prefs.c
152 src/prefs.h 152 src/prefs.h
153 src/sitespec.c
154 src/sitespec.h
153 src/stb_image.h 155 src/stb_image.h
154 src/stb_image_resize.h 156 src/stb_image_resize.h
155 src/stb_truetype.h 157 src/stb_truetype.h
@@ -193,7 +195,7 @@ set (SOURCES
193 src/ui/scrollwidget.c 195 src/ui/scrollwidget.c
194 src/ui/scrollwidget.h 196 src/ui/scrollwidget.h
195 src/ui/sidebarwidget.c 197 src/ui/sidebarwidget.c
196 src/ui/sidebarwidget.h 198 src/ui/sidebarwidget.h
197 src/ui/text.c 199 src/ui/text.c
198 src/ui/text.h 200 src/ui/text.h
199 src/ui/touch.c 201 src/ui/touch.c
diff --git a/po/en.po b/po/en.po
index 31a2946e..a3306f27 100644
--- a/po/en.po
+++ b/po/en.po
@@ -897,6 +897,18 @@ msgstr "see server's instructions"
897msgid "dlg.upload.send" 897msgid "dlg.upload.send"
898msgstr "Upload" 898msgstr "Upload"
899 899
900msgid "upload.port"
901msgstr "Port…"
902
903msgid "heading.uploadport"
904msgstr "TITAN UPLOAD PORT"
905
906msgid "dlg.uploadport.msg"
907msgstr "Set the Titan server port to use for this URL.\nThe port is saved in the site-specific configuration."
908
909msgid "dlg.uploadport.set"
910msgstr "Set Port"
911
900msgid "heading.translate" 912msgid "heading.translate"
901msgstr "TRANSLATE PAGE" 913msgstr "TRANSLATE PAGE"
902 914
diff --git a/res/lang/de.bin b/res/lang/de.bin
index 512061a1..ab7b90e2 100644
--- a/res/lang/de.bin
+++ b/res/lang/de.bin
Binary files differ
diff --git a/res/lang/en.bin b/res/lang/en.bin
index 766e74d6..ae50e06a 100644
--- a/res/lang/en.bin
+++ b/res/lang/en.bin
Binary files differ
diff --git a/res/lang/es.bin b/res/lang/es.bin
index c0d45889..96c14f46 100644
--- a/res/lang/es.bin
+++ b/res/lang/es.bin
Binary files differ
diff --git a/res/lang/fi.bin b/res/lang/fi.bin
index a5c8b35d..010282fd 100644
--- a/res/lang/fi.bin
+++ b/res/lang/fi.bin
Binary files differ
diff --git a/res/lang/fr.bin b/res/lang/fr.bin
index 8fc6a8ac..b27c62fb 100644
--- a/res/lang/fr.bin
+++ b/res/lang/fr.bin
Binary files differ
diff --git a/res/lang/ia.bin b/res/lang/ia.bin
index df4123aa..fe067931 100644
--- a/res/lang/ia.bin
+++ b/res/lang/ia.bin
Binary files differ
diff --git a/res/lang/ie.bin b/res/lang/ie.bin
index 54fcadd6..8444c31a 100644
--- a/res/lang/ie.bin
+++ b/res/lang/ie.bin
Binary files differ
diff --git a/res/lang/pl.bin b/res/lang/pl.bin
index 1eebe588..a1fe6e16 100644
--- a/res/lang/pl.bin
+++ b/res/lang/pl.bin
Binary files differ
diff --git a/res/lang/ru.bin b/res/lang/ru.bin
index 4a4a99f6..41e57935 100644
--- a/res/lang/ru.bin
+++ b/res/lang/ru.bin
Binary files differ
diff --git a/res/lang/sr.bin b/res/lang/sr.bin
index 1a8843de..d84accda 100644
--- a/res/lang/sr.bin
+++ b/res/lang/sr.bin
Binary files differ
diff --git a/res/lang/tok.bin b/res/lang/tok.bin
index b459962a..b7dd34ab 100644
--- a/res/lang/tok.bin
+++ b/res/lang/tok.bin
Binary files differ
diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin
index 19d3ce5f..279a5503 100644
--- a/res/lang/zh_Hans.bin
+++ b/res/lang/zh_Hans.bin
Binary files differ
diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin
index 86be599d..82cdb583 100644
--- a/res/lang/zh_Hant.bin
+++ b/res/lang/zh_Hant.bin
Binary files differ
diff --git a/src/app.c b/src/app.c
index e5c47a17..abfd584a 100644
--- a/src/app.c
+++ b/src/app.c
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
32#include "history.h" 32#include "history.h"
33#include "ipc.h" 33#include "ipc.h"
34#include "periodic.h" 34#include "periodic.h"
35#include "sitespec.h"
35#include "ui/certimportwidget.h" 36#include "ui/certimportwidget.h"
36#include "ui/color.h" 37#include "ui/color.h"
37#include "ui/command.h" 38#include "ui/command.h"
@@ -752,6 +753,7 @@ static void init_App_(iApp *d, int argc, char **argv) {
752 } 753 }
753#endif 754#endif
754 init_Prefs(&d->prefs); 755 init_Prefs(&d->prefs);
756 init_SiteSpec(dataDir_App_());
755 setCStr_String(&d->prefs.downloadDir, downloadDir_App_()); 757 setCStr_String(&d->prefs.downloadDir, downloadDir_App_());
756 set_Atomic(&d->pendingRefresh, iFalse); 758 set_Atomic(&d->pendingRefresh, iFalse);
757 d->isRunning = iFalse; 759 d->isRunning = iFalse;
@@ -832,6 +834,7 @@ static void deinit_App(iApp *d) {
832 deinit_Feeds(); 834 deinit_Feeds();
833 save_Keys(dataDir_App_()); 835 save_Keys(dataDir_App_());
834 deinit_Keys(); 836 deinit_Keys();
837 deinit_SiteSpec();
835 savePrefs_App_(d); 838 savePrefs_App_(d);
836 deinit_Prefs(&d->prefs); 839 deinit_Prefs(&d->prefs);
837 save_Bookmarks(d->bookmarks, dataDir_App_()); 840 save_Bookmarks(d->bookmarks, dataDir_App_());
diff --git a/src/sitespec.c b/src/sitespec.c
new file mode 100644
index 00000000..4df62a9f
--- /dev/null
+++ b/src/sitespec.c
@@ -0,0 +1,158 @@
1/* Copyright 2021 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 "sitespec.h"
24
25#include <the_Foundation/file.h>
26#include <the_Foundation/path.h>
27#include <the_Foundation/stringhash.h>
28
29iDeclareClass(SiteParams)
30iDeclareObjectConstruction(SiteParams)
31
32struct Impl_SiteParams {
33 iObject object;
34 uint16_t titanPort;
35 /* TODO: theme seed, style settings */
36};
37
38void init_SiteParams(iSiteParams *d) {
39 d->titanPort = 0; /* undefined */
40}
41
42void deinit_SiteParams(iSiteParams *d) {
43 iUnused(d);
44}
45
46iDefineClass(SiteParams)
47iDefineObjectConstruction(SiteParams)
48
49/*----------------------------------------------------------------------------------------------*/
50
51struct Impl_SiteSpec {
52 iString savePath;
53 iStringHash sites;
54};
55
56static iSiteSpec siteSpec_;
57
58static void load_SiteSpec_(iSiteSpec *d) {
59 iFile *f = iClob(new_File(&d->savePath));
60 if (open_File(f, readOnly_FileMode | text_FileMode)) {
61 iString *src = collect_String(readString_File(f));
62 iRangecc split = iNullRange;
63 iString *key = collectNew_String();
64 iSiteParams *params = NULL;
65 while (nextSplit_Rangecc(range_String(src), "\n", &split)) {
66 iRangecc line = split;
67 trim_Rangecc(&line);
68 if (isEmpty_Range(&line)) {
69 continue;
70 }
71 if (startsWith_Rangecc(line, "# ")) {
72 if (params && !isEmpty_String(key)) {
73 insert_StringHash(&d->sites, key, params);
74 iReleasePtr(&params);
75 }
76 line.start += 2;
77 setRange_String(key, line);
78 params = new_SiteParams();
79 continue;
80 }
81 if (startsWith_Rangecc(line, "titanPort: ")) {
82 line.start += 11;
83 if (params) {
84 params->titanPort = atoi(cstr_Rangecc(line));
85 }
86 continue;
87 }
88 }
89 if (params && !isEmpty_String(key)) {
90 insert_StringHash(&d->sites, key, params);
91 iReleasePtr(&params);
92 }
93 }
94}
95
96static void save_SiteSpec_(iSiteSpec *d) {
97 iFile *f = new_File(&d->savePath);
98 if (open_File(f, writeOnly_FileMode | text_FileMode)) {
99 iString *buf = new_String();
100 iConstForEach(StringHash, i, &d->sites) {
101 const iBlock * key = &i.value->keyBlock;
102 const iSiteParams *params = i.value->object;
103 format_String(buf, "# %s\n", cstr_Block(key));
104 appendFormat_String(buf, "titanPort: %u\n", params->titanPort);
105 write_File(f, utf8_String(buf));
106 }
107 delete_String(buf);
108 }
109 iRelease(f);
110}
111
112void init_SiteSpec(const char *saveDir) {
113 iSiteSpec *d = &siteSpec_;
114 initCStr_String(&d->savePath, concatPath_CStr(saveDir, "sitespec.txt"));
115 init_StringHash(&d->sites);
116 load_SiteSpec_(d);
117}
118
119void deinit_SiteSpec(void) {
120 iSiteSpec *d = &siteSpec_;
121 deinit_StringHash(&d->sites);
122 deinit_String(&d->savePath);
123}
124
125void setValue_SiteSpec(const iString *site, enum iSiteSpecKey key, int value) {
126 iSiteSpec *d = &siteSpec_;
127 const iString *hashKey = collect_String(lower_String(site));
128 iSiteParams *params = value_StringHash(&d->sites, hashKey);
129 if (!params) {
130 params = new_SiteParams();
131 insert_StringHash(&d->sites, hashKey, params);
132 }
133 iBool needSave = iFalse;
134 switch (key) {
135 case titanPort_SiteSpecKey:
136 params->titanPort = iClamp(value, 0, 0xffff);
137 needSave = iTrue;
138 default:
139 break;
140 }
141 if (needSave) {
142 save_SiteSpec_(d);
143 }
144}
145
146int value_SiteSpec(const iString *site, enum iSiteSpecKey key) {
147 iSiteSpec *d = &siteSpec_;
148 const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site)));
149 if (!params) {
150 return 0;
151 }
152 switch (key) {
153 case titanPort_SiteSpecKey:
154 return params->titanPort;
155 default:
156 return 0;
157 }
158}
diff --git a/src/sitespec.h b/src/sitespec.h
new file mode 100644
index 00000000..ee08f81f
--- /dev/null
+++ b/src/sitespec.h
@@ -0,0 +1,37 @@
1/* Copyright 2021 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
27iDeclareType(SiteSpec)
28
29enum iSiteSpecKey {
30 titanPort_SiteSpecKey,
31};
32
33void init_SiteSpec (const char *saveDir);
34void deinit_SiteSpec (void);
35
36void setValue_SiteSpec (const iString *site, enum iSiteSpecKey key, int value); /* changes saved immediately */
37int value_SiteSpec (const iString *site, enum iSiteSpecKey key);
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c
index eb8039c3..22c3adf6 100644
--- a/src/ui/uploadwidget.c
+++ b/src/ui/uploadwidget.c
@@ -27,6 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
27#include "color.h" 27#include "color.h"
28#include "command.h" 28#include "command.h"
29#include "gmrequest.h" 29#include "gmrequest.h"
30#include "sitespec.h"
30#include "app.h" 31#include "app.h"
31 32
32#include <the_Foundation/file.h> 33#include <the_Foundation/file.h>
@@ -36,6 +37,7 @@ iDefineObjectConstruction(UploadWidget)
36 37
37struct Impl_UploadWidget { 38struct Impl_UploadWidget {
38 iWidget widget; 39 iWidget widget;
40 iString originalUrl;
39 iString url; 41 iString url;
40 iDocumentWidget *viewer; 42 iDocumentWidget *viewer;
41 iGmRequest * request; 43 iGmRequest * request;
@@ -65,6 +67,7 @@ void init_UploadWidget(iUploadWidget *d) {
65 init_Widget(w); 67 init_Widget(w);
66 setId_Widget(w, "upload"); 68 setId_Widget(w, "upload");
67 useSheetStyle_Widget(w); 69 useSheetStyle_Widget(w);
70 init_String(&d->originalUrl);
68 init_String(&d->url); 71 init_String(&d->url);
69 d->viewer = NULL; 72 d->viewer = NULL;
70 d->request = NULL; 73 d->request = NULL;
@@ -126,15 +129,17 @@ void init_UploadWidget(iUploadWidget *d) {
126 /* Buttons. */ { 129 /* Buttons. */ {
127 addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); 130 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
128 iWidget *buttons = 131 iWidget *buttons =
129 makeDialogButtons_Widget((iMenuItem[]){ { "${cancel}", SDLK_ESCAPE, 0, "upload.cancel" }, 132 makeDialogButtons_Widget((iMenuItem[]){ { "${upload.port}", 0, 0, "upload.setport" },
133 { "---", 0, 0, NULL },
134 { "${cancel}", SDLK_ESCAPE, 0, "upload.cancel" },
130 { uiTextAction_ColorEscape "${dlg.upload.send}", 135 { uiTextAction_ColorEscape "${dlg.upload.send}",
131 SDLK_RETURN, 136 SDLK_RETURN,
132 KMOD_PRIMARY, 137 KMOD_PRIMARY,
133 "upload.accept" } }, 138 "upload.accept" } },
134 2); 139 4);
135 setId_Widget(addChildPosFlags_Widget(buttons, 140 setId_Widget(insertChildAfterFlags_Widget(buttons,
136 iClob(d->counter = new_LabelWidget("", NULL)), 141 iClob(d->counter = new_LabelWidget("", NULL)),
137 front_WidgetAddPos, frameless_WidgetFlag), 142 0, frameless_WidgetFlag),
138 "upload.counter"); 143 "upload.counter");
139 addChild_Widget(w, iClob(buttons)); 144 addChild_Widget(w, iClob(buttons));
140 } 145 }
@@ -146,20 +151,44 @@ void init_UploadWidget(iUploadWidget *d) {
146 setBackupFileName_InputWidget(d->input, "uploadbackup.txt"); 151 setBackupFileName_InputWidget(d->input, "uploadbackup.txt");
147} 152}
148 153
149void deinit_UploadWidget(iUploadWidget *d) { 154void deinit_UploadWidget(iUploadWidget *d) {
150 deinit_String(&d->filePath); 155 deinit_String(&d->filePath);
151 deinit_String(&d->url); 156 deinit_String(&d->url);
157 deinit_String(&d->originalUrl);
152 iRelease(d->request); 158 iRelease(d->request);
153} 159}
154 160
155void setUrl_UploadWidget(iUploadWidget *d, const iString *url) { 161static uint16_t titanPortForUrl_(const iString *url) {
162 uint16_t port = 0;
163 const iString *root = collectNewRange_String(urlRoot_String(url));
156 iUrl parts; 164 iUrl parts;
157 init_Url(&parts, url); 165 init_Url(&parts, url);
166 /* If the port is not specified, use the site-specific configuration. */
167 if (isEmpty_Range(&parts.port) || equalCase_Rangecc(parts.scheme, "gemini")) {
168 port = value_SiteSpec(root, titanPort_SiteSpecKey);
169 }
170 else {
171 port = atoi(cstr_Rangecc(parts.port));
172 }
173 return port ? port : GEMINI_DEFAULT_PORT;
174}
175
176static void setUrlPort_UploadWidget_(iUploadWidget *d, const iString *url, uint16_t overridePort) {
177 set_String(&d->originalUrl, url);
178 iUrl parts;
179 const iString *root = collectNewRange_String(urlRoot_String(url));
180 init_Url(&parts, url);
158 setCStr_String(&d->url, "titan"); 181 setCStr_String(&d->url, "titan");
159 appendRange_String(&d->url, (iRangecc){ parts.scheme.end, constEnd_String(url) }); 182 appendRange_String(&d->url, (iRangecc){ parts.scheme.end, parts.host.end });
183 appendFormat_String(&d->url, ":%u", overridePort ? overridePort : titanPortForUrl_(url));
184 appendRange_String(&d->url, (iRangecc){ parts.path.start, constEnd_String(url) });
160 setText_LabelWidget(d->info, &d->url); 185 setText_LabelWidget(d->info, &d->url);
161} 186}
162 187
188void setUrl_UploadWidget(iUploadWidget *d, const iString *url) {
189 setUrlPort_UploadWidget_(d, url, 0);
190}
191
163void setResponseViewer_UploadWidget(iUploadWidget *d, iDocumentWidget *doc) { 192void setResponseViewer_UploadWidget(iUploadWidget *d, iDocumentWidget *doc) {
164 d->viewer = doc; 193 d->viewer = doc;
165} 194}
@@ -182,13 +211,29 @@ static void requestFinished_UploadWidget_(iUploadWidget *d, iGmRequest *req) {
182 211
183static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { 212static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
184 iWidget *w = as_Widget(d); 213 iWidget *w = as_Widget(d);
214 const char *cmd = command_UserEvent(ev);
185 if (isCommand_Widget(w, ev, "upload.cancel")) { 215 if (isCommand_Widget(w, ev, "upload.cancel")) {
186 /* TODO: If text has been entered, ask for confirmation. */ 216 /* TODO: If text has been entered, ask for confirmation. */
187 setupSheetTransition_Mobile(w, iFalse); 217 setupSheetTransition_Mobile(w, iFalse);
188 destroy_Widget(w); 218 destroy_Widget(w);
189 return iTrue; 219 return iTrue;
190 } 220 }
191 const char *cmd = command_UserEvent(ev); 221 if (isCommand_Widget(w, ev, "upload.setport")) {
222 if (hasLabel_Command(cmd, "value")) {
223 setValue_SiteSpec(collectNewRange_String(urlRoot_String(&d->originalUrl)),
224 titanPort_SiteSpecKey, arg_Command(cmd));
225 setUrlPort_UploadWidget_(d, &d->originalUrl, arg_Command(cmd));
226 }
227 else {
228 makeValueInput_Widget(w,
229 collectNewFormat_String("%u", titanPortForUrl_(&d->originalUrl)),
230 uiHeading_ColorEscape "${heading.uploadport}",
231 "${dlg.uploadport.msg}",
232 "${dlg.uploadport.set}",
233 format_CStr("upload.setport ptr:%p", d));
234 }
235 return iTrue;
236 }
192 if (isCommand_Widget(w, ev, "upload.accept")) { 237 if (isCommand_Widget(w, ev, "upload.accept")) {
193 iWidget * tabs = findChild_Widget(w, "upload.tabs"); 238 iWidget * tabs = findChild_Widget(w, "upload.tabs");
194 const int tabIndex = tabPageIndex_Widget(tabs, currentTabPage_Widget(tabs)); 239 const int tabIndex = tabPageIndex_Widget(tabs, currentTabPage_Widget(tabs));