diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-11-21 14:35:32 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-11-21 14:35:32 +0200 |
commit | c58985ed3105ff7fc29fc0d53ba81ba55882e05e (patch) | |
tree | 0dd4e254645ce7478a8fc6e01d7f7fa1e51784e4 | |
parent | 67f1a5b152ca90fd8346bd39957905edaf3fb1cc (diff) |
Site-specific Titan upload identity
The identity to be used for uploads is now in sitespec.ini, so it applies to an entire site root. This should match actual use cases better than having URL-specific identities.
Also fixed an issue with native menus. Replacing the items with new ones was not implemented.
IssueID #379
-rw-r--r-- | res/about/version.gmi | 2 | ||||
-rw-r--r-- | src/gmcerts.c | 6 | ||||
-rw-r--r-- | src/sitespec.c | 51 | ||||
-rw-r--r-- | src/sitespec.h | 9 | ||||
-rw-r--r-- | src/ui/uploadwidget.c | 45 | ||||
-rw-r--r-- | src/ui/util.c | 50 | ||||
-rw-r--r-- | src/ui/util.h | 1 |
7 files changed, 129 insertions, 35 deletions
diff --git a/res/about/version.gmi b/res/about/version.gmi index 020373e4..b5750c8c 100644 --- a/res/about/version.gmi +++ b/res/about/version.gmi | |||
@@ -8,6 +8,8 @@ | |||
8 | 8 | ||
9 | ## 1.8.3 | 9 | ## 1.8.3 |
10 | * Fixed clicking on UI elements that are over the page top banner. The banner would always get clicked instead. | 10 | * Fixed clicking on UI elements that are over the page top banner. The banner would always get clicked instead. |
11 | * Titan upload identity is remembered as a site-specific setting. It is no longer affected by selections in the Identities sidebar. | ||
12 | * macOS: Fixed updating items in native menus, e.g., upload identity selection. | ||
11 | 13 | ||
12 | ## 1.8.2 | 14 | ## 1.8.2 |
13 | * Fixed encoding of `+` characters in URLs as per RFC 3986. | 15 | * Fixed encoding of `+` characters in URLs as per RFC 3986. |
diff --git a/src/gmcerts.c b/src/gmcerts.c index 36fd7d55..f95fea7d 100644 --- a/src/gmcerts.c +++ b/src/gmcerts.c | |||
@@ -295,6 +295,9 @@ static void loadIdentities_GmCerts_(iGmCerts *d) { | |||
295 | } | 295 | } |
296 | 296 | ||
297 | iGmIdentity *findIdentity_GmCerts(iGmCerts *d, const iBlock *fingerprint) { | 297 | iGmIdentity *findIdentity_GmCerts(iGmCerts *d, const iBlock *fingerprint) { |
298 | if (isEmpty_Block(fingerprint)) { | ||
299 | return NULL; | ||
300 | } | ||
298 | iForEach(PtrArray, i, &d->idents) { | 301 | iForEach(PtrArray, i, &d->idents) { |
299 | iGmIdentity *ident = i.ptr; | 302 | iGmIdentity *ident = i.ptr; |
300 | if (cmp_Block(fingerprint, &ident->fingerprint) == 0) { /* TODO: could use a hash */ | 303 | if (cmp_Block(fingerprint, &ident->fingerprint) == 0) { /* TODO: could use a hash */ |
@@ -549,6 +552,9 @@ const iGmIdentity *constIdentity_GmCerts(const iGmCerts *d, unsigned int id) { | |||
549 | } | 552 | } |
550 | 553 | ||
551 | const iGmIdentity *identityForUrl_GmCerts(const iGmCerts *d, const iString *url) { | 554 | const iGmIdentity *identityForUrl_GmCerts(const iGmCerts *d, const iString *url) { |
555 | if (isEmpty_String(url)) { | ||
556 | return NULL; | ||
557 | } | ||
552 | lock_Mutex(d->mtx); | 558 | lock_Mutex(d->mtx); |
553 | const iGmIdentity *found = NULL; | 559 | const iGmIdentity *found = NULL; |
554 | iConstForEach(PtrArray, i, &d->idents) { | 560 | iConstForEach(PtrArray, i, &d->idents) { |
diff --git a/src/sitespec.c b/src/sitespec.c index 0332af2d..6f4546f0 100644 --- a/src/sitespec.c +++ b/src/sitespec.c | |||
@@ -33,17 +33,19 @@ iDeclareObjectConstruction(SiteParams) | |||
33 | struct Impl_SiteParams { | 33 | struct Impl_SiteParams { |
34 | iObject object; | 34 | iObject object; |
35 | uint16_t titanPort; | 35 | uint16_t titanPort; |
36 | iString titanIdentity; /* fingerprint */ | ||
36 | int dismissWarnings; | 37 | int dismissWarnings; |
37 | /* TODO: theme seed, style settings */ | 38 | /* TODO: theme seed, style settings */ |
38 | }; | 39 | }; |
39 | 40 | ||
40 | void init_SiteParams(iSiteParams *d) { | 41 | void init_SiteParams(iSiteParams *d) { |
41 | d->titanPort = 0; /* undefined */ | 42 | d->titanPort = 0; /* undefined */ |
43 | init_String(&d->titanIdentity); | ||
42 | d->dismissWarnings = 0; | 44 | d->dismissWarnings = 0; |
43 | } | 45 | } |
44 | 46 | ||
45 | void deinit_SiteParams(iSiteParams *d) { | 47 | void deinit_SiteParams(iSiteParams *d) { |
46 | iUnused(d); | 48 | deinit_String(&d->titanIdentity); |
47 | } | 49 | } |
48 | 50 | ||
49 | iDefineClass(SiteParams) | 51 | iDefineClass(SiteParams) |
@@ -122,6 +124,9 @@ static void handleIniKeyValue_SiteSpec_(void *context, const iString *table, con | |||
122 | if (!cmp_String(key, "titanPort")) { | 124 | if (!cmp_String(key, "titanPort")) { |
123 | d->loadParams->titanPort = number_TomlValue(value); | 125 | d->loadParams->titanPort = number_TomlValue(value); |
124 | } | 126 | } |
127 | else if (!cmp_String(key, "titanIdentity") && value->type == string_TomlType) { | ||
128 | set_String(&d->loadParams->titanIdentity, value->value.string); | ||
129 | } | ||
125 | else if (!cmp_String(key, "dismissWarnings") && value->type == int64_TomlType) { | 130 | else if (!cmp_String(key, "dismissWarnings") && value->type == int64_TomlType) { |
126 | d->loadParams->dismissWarnings = value->value.int64; | 131 | d->loadParams->dismissWarnings = value->value.int64; |
127 | } | 132 | } |
@@ -152,6 +157,10 @@ static void save_SiteSpec_(iSiteSpec *d) { | |||
152 | if (params->titanPort) { | 157 | if (params->titanPort) { |
153 | appendFormat_String(buf, "titanPort = %u\n", params->titanPort); | 158 | appendFormat_String(buf, "titanPort = %u\n", params->titanPort); |
154 | } | 159 | } |
160 | if (!isEmpty_String(¶ms->titanIdentity)) { | ||
161 | appendFormat_String( | ||
162 | buf, "titanIdentity = \"%s\"\n", cstr_String(¶ms->titanIdentity)); | ||
163 | } | ||
155 | if (params->dismissWarnings) { | 164 | if (params->dismissWarnings) { |
156 | appendFormat_String(buf, "dismissWarnings = 0x%x\n", params->dismissWarnings); | 165 | appendFormat_String(buf, "dismissWarnings = 0x%x\n", params->dismissWarnings); |
157 | } | 166 | } |
@@ -205,6 +214,30 @@ void setValue_SiteSpec(const iString *site, enum iSiteSpecKey key, int value) { | |||
205 | } | 214 | } |
206 | } | 215 | } |
207 | 216 | ||
217 | void setValueString_SiteSpec(const iString *site, enum iSiteSpecKey key, const iString *value) { | ||
218 | iSiteSpec *d = &siteSpec_; | ||
219 | const iString *hashKey = collect_String(lower_String(site)); | ||
220 | iSiteParams *params = value_StringHash(&d->sites, hashKey); | ||
221 | if (!params) { | ||
222 | params = new_SiteParams(); | ||
223 | insert_StringHash(&d->sites, hashKey, params); | ||
224 | } | ||
225 | iBool needSave = iFalse; | ||
226 | switch (key) { | ||
227 | case titanIdentity_SiteSpecKey: | ||
228 | if (!equal_String(¶ms->titanIdentity, value)) { | ||
229 | needSave = iTrue; | ||
230 | set_String(¶ms->titanIdentity, value); | ||
231 | } | ||
232 | break; | ||
233 | default: | ||
234 | break; | ||
235 | } | ||
236 | if (needSave) { | ||
237 | save_SiteSpec_(d); | ||
238 | } | ||
239 | } | ||
240 | |||
208 | int value_SiteSpec(const iString *site, enum iSiteSpecKey key) { | 241 | int value_SiteSpec(const iString *site, enum iSiteSpecKey key) { |
209 | iSiteSpec *d = &siteSpec_; | 242 | iSiteSpec *d = &siteSpec_; |
210 | const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site))); | 243 | const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site))); |
@@ -220,3 +253,17 @@ int value_SiteSpec(const iString *site, enum iSiteSpecKey key) { | |||
220 | return 0; | 253 | return 0; |
221 | } | 254 | } |
222 | } | 255 | } |
256 | |||
257 | const iString *valueString_SiteSpec(const iString *site, enum iSiteSpecKey key) { | ||
258 | iSiteSpec *d = &siteSpec_; | ||
259 | const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site))); | ||
260 | if (!params) { | ||
261 | return 0; | ||
262 | } | ||
263 | switch (key) { | ||
264 | case titanIdentity_SiteSpecKey: | ||
265 | return ¶ms->titanIdentity; | ||
266 | default: | ||
267 | return collectNew_String(); | ||
268 | } | ||
269 | } | ||
diff --git a/src/sitespec.h b/src/sitespec.h index 6b64f073..5adaeb8c 100644 --- a/src/sitespec.h +++ b/src/sitespec.h | |||
@@ -28,11 +28,16 @@ iDeclareType(SiteSpec) | |||
28 | 28 | ||
29 | enum iSiteSpecKey { | 29 | enum iSiteSpecKey { |
30 | titanPort_SiteSpecKey, | 30 | titanPort_SiteSpecKey, |
31 | titanIdentity_SiteSpecKey, | ||
31 | dismissWarnings_SiteSpecKey, | 32 | dismissWarnings_SiteSpecKey, |
32 | }; | 33 | }; |
33 | 34 | ||
34 | void init_SiteSpec (const char *saveDir); | 35 | void init_SiteSpec (const char *saveDir); |
35 | void deinit_SiteSpec (void); | 36 | void deinit_SiteSpec (void); |
36 | 37 | ||
37 | void setValue_SiteSpec (const iString *site, enum iSiteSpecKey key, int value); /* changes saved immediately */ | 38 | /* changes saved immediately */ |
38 | int value_SiteSpec (const iString *site, enum iSiteSpecKey key); | 39 | void setValue_SiteSpec (const iString *site, enum iSiteSpecKey key, int value); |
40 | void setValueString_SiteSpec (const iString *site, enum iSiteSpecKey key, const iString *value); | ||
41 | |||
42 | int value_SiteSpec (const iString *site, enum iSiteSpecKey key); | ||
43 | const iString * valueString_SiteSpec (const iString *site, enum iSiteSpecKey key); | ||
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c index 90df1958..bad00071 100644 --- a/src/ui/uploadwidget.c +++ b/src/ui/uploadwidget.c | |||
@@ -45,7 +45,7 @@ iDefineObjectConstruction(UploadWidget) | |||
45 | 45 | ||
46 | enum iUploadIdentity { | 46 | enum iUploadIdentity { |
47 | none_UploadIdentity, | 47 | none_UploadIdentity, |
48 | defaultForUrl_UploadIdentity, | 48 | defaultForSite_UploadIdentity, |
49 | dropdown_UploadIdentity, | 49 | dropdown_UploadIdentity, |
50 | }; | 50 | }; |
51 | 51 | ||
@@ -104,9 +104,16 @@ static void updateInputMaxHeight_UploadWidget_(iUploadWidget *d) { | |||
104 | (avail - inputPos.y) / lineHeight_Text(font_InputWidget(d->input)))); | 104 | (avail - inputPos.y) / lineHeight_Text(font_InputWidget(d->input)))); |
105 | } | 105 | } |
106 | 106 | ||
107 | static const iGmIdentity *titanIdentityForUrl_(const iString *url) { | ||
108 | return findIdentity_GmCerts( | ||
109 | certs_App(), | ||
110 | collect_Block(hexDecode_Rangecc(range_String(valueString_SiteSpec( | ||
111 | collectNewRange_String(urlRoot_String(url)), titanIdentity_SiteSpecKey))))); | ||
112 | } | ||
113 | |||
107 | static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) { | 114 | static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) { |
108 | iArray *items = collectNew_Array(sizeof(iMenuItem)); | 115 | iArray *items = collectNew_Array(sizeof(iMenuItem)); |
109 | const iGmIdentity *urlId = identityForUrl_GmCerts(certs_App(), &d->url); | 116 | const iGmIdentity *urlId = titanIdentityForUrl_(&d->url); |
110 | pushBack_Array(items, | 117 | pushBack_Array(items, |
111 | &(iMenuItem){ format_CStr("${dlg.upload.id.default} (%s)", | 118 | &(iMenuItem){ format_CStr("${dlg.upload.id.default} (%s)", |
112 | urlId ? cstr_String(name_GmIdentity(urlId)) | 119 | urlId ? cstr_String(name_GmIdentity(urlId)) |
@@ -147,7 +154,7 @@ void init_UploadWidget(iUploadWidget *d) { | |||
147 | d->request = NULL; | 154 | d->request = NULL; |
148 | init_String(&d->filePath); | 155 | init_String(&d->filePath); |
149 | d->fileSize = 0; | 156 | d->fileSize = 0; |
150 | d->idMode = defaultForUrl_UploadIdentity; | 157 | d->idMode = defaultForSite_UploadIdentity; |
151 | init_Block(&d->idFingerprint, 0); | 158 | init_Block(&d->idFingerprint, 0); |
152 | const iMenuItem actions[] = { | 159 | const iMenuItem actions[] = { |
153 | { "${upload.port}", 0, 0, "upload.setport" }, | 160 | { "${upload.port}", 0, 0, "upload.setport" }, |
@@ -289,16 +296,22 @@ void deinit_UploadWidget(iUploadWidget *d) { | |||
289 | 296 | ||
290 | static void remakeIdentityItems_UploadWidget_(iUploadWidget *d) { | 297 | static void remakeIdentityItems_UploadWidget_(iUploadWidget *d) { |
291 | iWidget *dropMenu = findChild_Widget(findChild_Widget(as_Widget(d), "upload.id"), "menu"); | 298 | iWidget *dropMenu = findChild_Widget(findChild_Widget(as_Widget(d), "upload.id"), "menu"); |
292 | releaseChildren_Widget(dropMenu); | ||
293 | const iArray *items = makeIdentityItems_UploadWidget_(d); | 299 | const iArray *items = makeIdentityItems_UploadWidget_(d); |
294 | makeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items)); | 300 | /* TODO: Make the following a utility method. */ |
301 | if (flags_Widget(dropMenu) & nativeMenu_WidgetFlag) { | ||
302 | setNativeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items)); | ||
303 | } | ||
304 | else { | ||
305 | releaseChildren_Widget(dropMenu); | ||
306 | makeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items)); | ||
307 | } | ||
295 | } | 308 | } |
296 | 309 | ||
297 | static void updateIdentityDropdown_UploadWidget_(iUploadWidget *d) { | 310 | static void updateIdentityDropdown_UploadWidget_(iUploadWidget *d) { |
298 | updateDropdownSelection_LabelWidget( | 311 | updateDropdownSelection_LabelWidget( |
299 | findChild_Widget(as_Widget(d), "upload.id"), | 312 | findChild_Widget(as_Widget(d), "upload.id"), |
300 | d->idMode == none_UploadIdentity ? " arg:0" | 313 | d->idMode == none_UploadIdentity ? " arg:0" |
301 | : d->idMode == defaultForUrl_UploadIdentity | 314 | : d->idMode == defaultForSite_UploadIdentity |
302 | ? " arg:1" | 315 | ? " arg:1" |
303 | : format_CStr(" fp:%s", cstrCollect_String(hexEncode_Block(&d->idFingerprint)))); | 316 | : format_CStr(" fp:%s", cstrCollect_String(hexEncode_Block(&d->idFingerprint)))); |
304 | } | 317 | } |
@@ -422,7 +435,7 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { | |||
422 | } | 435 | } |
423 | else if (arg_Command(cmd)) { | 436 | else if (arg_Command(cmd)) { |
424 | clear_Block(&d->idFingerprint); | 437 | clear_Block(&d->idFingerprint); |
425 | d->idMode = defaultForUrl_UploadIdentity; | 438 | d->idMode = defaultForSite_UploadIdentity; |
426 | } | 439 | } |
427 | else { | 440 | else { |
428 | clear_Block(&d->idFingerprint); | 441 | clear_Block(&d->idFingerprint); |
@@ -452,19 +465,27 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { | |||
452 | setSendProgressFunc_GmRequest(d->request, updateProgress_UploadWidget_); | 465 | setSendProgressFunc_GmRequest(d->request, updateProgress_UploadWidget_); |
453 | setUserData_Object(d->request, d); | 466 | setUserData_Object(d->request, d); |
454 | setUrl_GmRequest(d->request, &d->url); | 467 | setUrl_GmRequest(d->request, &d->url); |
468 | const iString *site = collectNewRange_String(urlRoot_String(&d->url)); | ||
455 | switch (d->idMode) { | 469 | switch (d->idMode) { |
456 | case defaultForUrl_UploadIdentity: | ||
457 | break; /* GmRequest handles it */ | ||
458 | case none_UploadIdentity: | 470 | case none_UploadIdentity: |
459 | setIdentity_GmRequest(d->request, NULL); | 471 | /* Ensure no identity will be used for this specific URL. */ |
460 | signOut_GmCerts(certs_App(), url_GmRequest(d->request)); | 472 | signOut_GmCerts(certs_App(), url_GmRequest(d->request)); |
473 | setValueString_SiteSpec(site, titanIdentity_SiteSpecKey, collectNew_String()); | ||
461 | break; | 474 | break; |
462 | case dropdown_UploadIdentity: { | 475 | case dropdown_UploadIdentity: { |
463 | iGmIdentity *ident = findIdentity_GmCerts(certs_App(), &d->idFingerprint); | 476 | iGmIdentity *ident = findIdentity_GmCerts(certs_App(), &d->idFingerprint); |
464 | setIdentity_GmRequest(d->request, ident); | 477 | if (ident) { |
465 | signIn_GmCerts(certs_App(), ident, url_GmRequest(d->request)); | 478 | setValueString_SiteSpec(site, |
479 | titanIdentity_SiteSpecKey, | ||
480 | collect_String(hexEncode_Block(&ident->fingerprint))); | ||
481 | } | ||
466 | break; | 482 | break; |
467 | } | 483 | } |
484 | default: | ||
485 | break; | ||
486 | } | ||
487 | if (d->idMode != none_UploadIdentity) { | ||
488 | setIdentity_GmRequest(d->request, titanIdentityForUrl_(&d->url)); | ||
468 | } | 489 | } |
469 | if (isText) { | 490 | if (isText) { |
470 | /* Uploading text. */ | 491 | /* Uploading text. */ |
diff --git a/src/ui/util.c b/src/ui/util.c index 2624bf2b..0a9dde0c 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -809,14 +809,27 @@ static void deleteMenuItems_(iArray *items) { | |||
809 | delete_Array(items); | 809 | delete_Array(items); |
810 | } | 810 | } |
811 | 811 | ||
812 | iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { | 812 | void releaseNativeMenu_Widget(iWidget *d) { |
813 | iWidget *menu = new_Widget(); | ||
814 | #if defined (iHaveNativeContextMenus) | 813 | #if defined (iHaveNativeContextMenus) |
815 | setFlags_Widget(menu, hidden_WidgetFlag | nativeMenu_WidgetFlag, iTrue); | 814 | iArray *items = userData_Object(d); |
815 | if (items) { | ||
816 | iAssert(flags_Widget(d) & nativeMenu_WidgetFlag); | ||
817 | iAssert(items); | ||
818 | deleteMenuItems_(items); | ||
819 | setUserData_Object(d, NULL); | ||
820 | } | ||
821 | #else | ||
822 | iUnused(d); | ||
823 | #endif | ||
824 | } | ||
825 | |||
826 | void setNativeMenuItems_Widget(iWidget *menu, const iMenuItem *items, size_t n) { | ||
827 | #if defined (iHaveNativeContextMenus) | ||
828 | iAssert(flags_Widget(menu) & nativeMenu_WidgetFlag); | ||
829 | releaseNativeMenu_Widget(menu); | ||
816 | setUserData_Object(menu, deepCopyMenuItems_(menu, items, n)); | 830 | setUserData_Object(menu, deepCopyMenuItems_(menu, items, n)); |
817 | addChild_Widget(parent, menu); | ||
818 | iRelease(menu); /* owned by parent now */ | ||
819 | /* Keyboard shortcuts still need to triggerable via the menu, although the items don't exist. */ { | 831 | /* Keyboard shortcuts still need to triggerable via the menu, although the items don't exist. */ { |
832 | releaseChildren_Widget(menu); | ||
820 | for (size_t i = 0; i < n; i++) { | 833 | for (size_t i = 0; i < n; i++) { |
821 | const iMenuItem *item = &items[i]; | 834 | const iMenuItem *item = &items[i]; |
822 | if (item->key) { | 835 | if (item->key) { |
@@ -824,6 +837,17 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { | |||
824 | } | 837 | } |
825 | } | 838 | } |
826 | } | 839 | } |
840 | #endif | ||
841 | } | ||
842 | |||
843 | iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { | ||
844 | iWidget *menu = new_Widget(); | ||
845 | #if defined (iHaveNativeContextMenus) | ||
846 | setFlags_Widget(menu, hidden_WidgetFlag | nativeMenu_WidgetFlag, iTrue); | ||
847 | addChild_Widget(parent, menu); | ||
848 | iRelease(menu); /* owned by parent now */ | ||
849 | setUserData_Object(menu, NULL); | ||
850 | setNativeMenuItems_Widget(menu, items, n); | ||
827 | #else | 851 | #else |
828 | /* Non-native custom popup menu. This may still be displayed inside a separate window. */ | 852 | /* Non-native custom popup menu. This may still be displayed inside a separate window. */ |
829 | setDrawBufferEnabled_Widget(menu, iTrue); | 853 | setDrawBufferEnabled_Widget(menu, iTrue); |
@@ -990,18 +1014,6 @@ iLocalDef iBool isUsingMenuPopupWindows_(void) { | |||
990 | #endif | 1014 | #endif |
991 | } | 1015 | } |
992 | 1016 | ||
993 | void releaseNativeMenu_Widget(iWidget *d) { | ||
994 | #if defined (iHaveNativeContextMenus) | ||
995 | iArray *items = userData_Object(d); | ||
996 | iAssert(flags_Widget(d) & nativeMenu_WidgetFlag); | ||
997 | iAssert(items); | ||
998 | deleteMenuItems_(items); | ||
999 | setUserData_Object(d, NULL); | ||
1000 | #else | ||
1001 | iUnused(d); | ||
1002 | #endif | ||
1003 | } | ||
1004 | |||
1005 | void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) { | 1017 | void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) { |
1006 | const iBool postCommands = (menuOpenFlags & postCommands_MenuOpenFlags) != 0; | 1018 | const iBool postCommands = (menuOpenFlags & postCommands_MenuOpenFlags) != 0; |
1007 | #if defined (iHaveNativeContextMenus) | 1019 | #if defined (iHaveNativeContextMenus) |
@@ -1263,8 +1275,8 @@ void updateDropdownSelection_LabelWidget(iLabelWidget *dropButton, const char *s | |||
1263 | iMenuItem *item = findNativeMenuItem_Widget(menu, selectedCommand); | 1275 | iMenuItem *item = findNativeMenuItem_Widget(menu, selectedCommand); |
1264 | if (item) { | 1276 | if (item) { |
1265 | setSelected_NativeMenuItem(item, iTrue); | 1277 | setSelected_NativeMenuItem(item, iTrue); |
1266 | updateText_LabelWidget(dropButton, | 1278 | updateText_LabelWidget( |
1267 | removeMenuItemLabelPrefixes_String(collectNewCStr_String(item->label))); | 1279 | dropButton, removeMenuItemLabelPrefixes_String(collectNewCStr_String(item->label))); |
1268 | } | 1280 | } |
1269 | return; | 1281 | return; |
1270 | } | 1282 | } |
diff --git a/src/ui/util.h b/src/ui/util.h index cf96dfe4..52b3a692 100644 --- a/src/ui/util.h +++ b/src/ui/util.h | |||
@@ -249,6 +249,7 @@ void setMenuItemDisabled_Widget (iWidget *menu, const char *comm | |||
249 | void setMenuItemDisabledByIndex_Widget(iWidget *menu, size_t index, iBool disable); | 249 | void setMenuItemDisabledByIndex_Widget(iWidget *menu, size_t index, iBool disable); |
250 | void setMenuItemLabel_Widget (iWidget *menu, const char *command, const char *newLabel); | 250 | void setMenuItemLabel_Widget (iWidget *menu, const char *command, const char *newLabel); |
251 | void setMenuItemLabelByIndex_Widget (iWidget *menu, size_t index, const char *newLabel); | 251 | void setMenuItemLabelByIndex_Widget (iWidget *menu, size_t index, const char *newLabel); |
252 | void setNativeMenuItems_Widget (iWidget *, const iMenuItem *items, size_t n); | ||
252 | 253 | ||
253 | int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */ | 254 | int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */ |
254 | 255 | ||