diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-08 07:49:08 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-08 07:49:08 +0300 |
commit | 5ae35b010cfb44d3930cfc900bc71ff2449d39f7 (patch) | |
tree | d126e1cb97194ebcc1ea4e136c3a39ddb90798c8 | |
parent | 92efe35c6b1ef4bea6aa1e43faf42610c1597340 (diff) |
LookupWidget: Identities lookup and commands
-rw-r--r-- | src/app.c | 21 | ||||
-rw-r--r-- | src/gmcerts.c | 10 | ||||
-rw-r--r-- | src/gmcerts.h | 1 | ||||
-rw-r--r-- | src/history.c | 16 | ||||
-rw-r--r-- | src/ui/command.c | 8 | ||||
-rw-r--r-- | src/ui/command.h | 2 | ||||
-rw-r--r-- | src/ui/lookupwidget.c | 56 |
7 files changed, 94 insertions, 20 deletions
@@ -830,6 +830,27 @@ iBool handleCommand_App(const char *cmd) { | |||
830 | setCommandHandler_Widget(dlg, handleIdentityCreationCommands_); | 830 | setCommandHandler_Widget(dlg, handleIdentityCreationCommands_); |
831 | return iTrue; | 831 | return iTrue; |
832 | } | 832 | } |
833 | else if (equal_Command(cmd, "ident.signin")) { | ||
834 | const iString *url = collect_String(suffix_Command(cmd, "url")); | ||
835 | signIn_GmCerts( | ||
836 | d->certs, | ||
837 | findIdentity_GmCerts(d->certs, collect_Block(hexDecode_Rangecc(range_Command(cmd, "ident")))), | ||
838 | url); | ||
839 | postCommand_App("idents.changed"); | ||
840 | return iTrue; | ||
841 | } | ||
842 | else if (equal_Command(cmd, "ident.signout")) { | ||
843 | iGmIdentity *ident = findIdentity_GmCerts( | ||
844 | d->certs, collect_Block(hexDecode_Rangecc(range_Command(cmd, "ident")))); | ||
845 | if (arg_Command(cmd)) { | ||
846 | clearUse_GmIdentity(ident); | ||
847 | } | ||
848 | else { | ||
849 | setUse_GmIdentity(ident, collect_String(suffix_Command(cmd, "url")), iFalse); | ||
850 | } | ||
851 | postCommand_App("idents.changed"); | ||
852 | return iTrue; | ||
853 | } | ||
833 | else if (equal_Command(cmd, "theme.set")) { | 854 | else if (equal_Command(cmd, "theme.set")) { |
834 | const int isAuto = argLabel_Command(cmd, "auto"); | 855 | const int isAuto = argLabel_Command(cmd, "auto"); |
835 | d->theme = arg_Command(cmd); | 856 | d->theme = arg_Command(cmd); |
diff --git a/src/gmcerts.c b/src/gmcerts.c index 0dc52041..addd75d3 100644 --- a/src/gmcerts.c +++ b/src/gmcerts.c | |||
@@ -253,7 +253,7 @@ static void loadIdentities_GmCerts_(iGmCerts *d) { | |||
253 | } | 253 | } |
254 | } | 254 | } |
255 | 255 | ||
256 | static iGmIdentity *findIdentity_GmCerts_(iGmCerts *d, const iBlock *fingerprint) { | 256 | iGmIdentity *findIdentity_GmCerts(iGmCerts *d, const iBlock *fingerprint) { |
257 | iForEach(PtrArray, i, &d->idents) { | 257 | iForEach(PtrArray, i, &d->idents) { |
258 | iGmIdentity *ident = i.ptr; | 258 | iGmIdentity *ident = i.ptr; |
259 | if (cmp_Block(fingerprint, &ident->fingerprint) == 0) { /* TODO: could use a hash */ | 259 | if (cmp_Block(fingerprint, &ident->fingerprint) == 0) { /* TODO: could use a hash */ |
@@ -273,7 +273,7 @@ static void loadIdentityFromCertificate_GmCerts_(iGmCerts *d, const iString *crt | |||
273 | } | 273 | } |
274 | iTlsCertificate *cert = newPemKey_TlsCertificate(readFile_(crtPath), readFile_(keyPath)); | 274 | iTlsCertificate *cert = newPemKey_TlsCertificate(readFile_(crtPath), readFile_(keyPath)); |
275 | iBlock *finger = fingerprint_TlsCertificate(cert); | 275 | iBlock *finger = fingerprint_TlsCertificate(cert); |
276 | iGmIdentity *ident = findIdentity_GmCerts_(d, finger); | 276 | iGmIdentity *ident = findIdentity_GmCerts(d, finger); |
277 | if (!ident) { | 277 | if (!ident) { |
278 | /* User-provided certificate. */ | 278 | /* User-provided certificate. */ |
279 | ident = new_GmIdentity(); | 279 | ident = new_GmIdentity(); |
@@ -497,8 +497,10 @@ const iPtrArray *identities_GmCerts(const iGmCerts *d) { | |||
497 | } | 497 | } |
498 | 498 | ||
499 | void signIn_GmCerts(iGmCerts *d, iGmIdentity *identity, const iString *url) { | 499 | void signIn_GmCerts(iGmCerts *d, iGmIdentity *identity, const iString *url) { |
500 | signOut_GmCerts(d, url); | 500 | if (identity) { |
501 | setUse_GmIdentity(identity, url, iTrue); | 501 | signOut_GmCerts(d, url); |
502 | setUse_GmIdentity(identity, url, iTrue); | ||
503 | } | ||
502 | } | 504 | } |
503 | 505 | ||
504 | void signOut_GmCerts(iGmCerts *d, const iString *url) { | 506 | void signOut_GmCerts(iGmCerts *d, const iString *url) { |
diff --git a/src/gmcerts.h b/src/gmcerts.h index 2ab4396e..f0ed37b5 100644 --- a/src/gmcerts.h +++ b/src/gmcerts.h | |||
@@ -82,6 +82,7 @@ void deleteIdentity_GmCerts (iGmCerts *, iGmIdentity *identity); | |||
82 | const iString * certificatePath_GmCerts (const iGmCerts *, const iGmIdentity *identity); | 82 | const iString * certificatePath_GmCerts (const iGmCerts *, const iGmIdentity *identity); |
83 | 83 | ||
84 | iGmIdentity * identity_GmCerts (iGmCerts *, unsigned int id); | 84 | iGmIdentity * identity_GmCerts (iGmCerts *, unsigned int id); |
85 | iGmIdentity * findIdentity_GmCerts (iGmCerts *, const iBlock *fingerprint); | ||
85 | const iGmIdentity * constIdentity_GmCerts (const iGmCerts *, unsigned int id); | 86 | const iGmIdentity * constIdentity_GmCerts (const iGmCerts *, unsigned int id); |
86 | const iGmIdentity * identityForUrl_GmCerts (const iGmCerts *, const iString *url); | 87 | const iGmIdentity * identityForUrl_GmCerts (const iGmCerts *, const iString *url); |
87 | const iPtrArray * identities_GmCerts (const iGmCerts *); | 88 | const iPtrArray * identities_GmCerts (const iGmCerts *); |
diff --git a/src/history.c b/src/history.c index 10de5b9a..562c23bf 100644 --- a/src/history.c +++ b/src/history.c | |||
@@ -271,19 +271,25 @@ const iStringArray *searchContents_History(const iHistory *d, const iRegExp *pat | |||
271 | iString entry; | 271 | iString entry; |
272 | init_String(&entry); | 272 | init_String(&entry); |
273 | iRangei cap = m.range; | 273 | iRangei cap = m.range; |
274 | cap.start = iMax(cap.start - 15, 0); | 274 | const int prefix = iMin(10, cap.start); |
275 | cap.end = iMin(cap.end + 15, (int) size_Block(&resp->body)); | 275 | cap.start = cap.start - prefix; |
276 | cap.end = iMin(cap.end + 30, (int) size_Block(&resp->body)); | ||
277 | const size_t maxLen = 60; | ||
278 | if (size_Range(&cap) > maxLen) { | ||
279 | cap.end = cap.start + maxLen; | ||
280 | } | ||
276 | iString content; | 281 | iString content; |
277 | initRange_String(&content, (iRangecc){ m.subject + cap.start, m.subject + cap.end }); | 282 | initRange_String(&content, (iRangecc){ m.subject + cap.start, m.subject + cap.end }); |
278 | /* This needs cleaning up; highlight the matched word. */ | 283 | /* This needs cleaning up; highlight the matched word. */ |
279 | replace_Block(&content.chars, '\n', ' '); | 284 | replace_Block(&content.chars, '\n', ' '); |
280 | replace_Block(&content.chars, '\r', ' '); | 285 | replace_Block(&content.chars, '\r', ' '); |
281 | // insertData_Block(&content.chars, 10, uiTextStrong_ColorEscape, 2); | 286 | if (prefix + size_Range(&m.range) < size_String(&content)) { |
282 | // insertData_Block(&content.chars, size_String(&content) - 10, uiText_ColorEscape, 2); | 287 | insertData_Block(&content.chars, prefix + size_Range(&m.range), uiText_ColorEscape, 2); |
288 | } | ||
289 | insertData_Block(&content.chars, prefix, uiTextStrong_ColorEscape, 2); | ||
283 | format_String( | 290 | format_String( |
284 | &entry, "match len:%zu str:%s", size_String(&content), cstr_String(&content)); | 291 | &entry, "match len:%zu str:%s", size_String(&content), cstr_String(&content)); |
285 | deinit_String(&content); | 292 | deinit_String(&content); |
286 | //appendRange_String(&entry, ); | ||
287 | appendFormat_String(&entry, " url:%s", cstr_String(&url->url)); | 293 | appendFormat_String(&entry, " url:%s", cstr_String(&url->url)); |
288 | if (!contains_StringSet(&inserted, &url->url)) { | 294 | if (!contains_StringSet(&inserted, &url->url)) { |
289 | pushFront_StringArray(urls, &entry); | 295 | pushFront_StringArray(urls, &entry); |
diff --git a/src/ui/command.c b/src/ui/command.c index cf8c7032..44e66121 100644 --- a/src/ui/command.c +++ b/src/ui/command.c | |||
@@ -96,12 +96,16 @@ iString *suffix_Command(const char *cmd, const char *label) { | |||
96 | } | 96 | } |
97 | 97 | ||
98 | const iString *string_Command(const char *cmd, const char *label) { | 98 | const iString *string_Command(const char *cmd, const char *label) { |
99 | return collect_String(newRange_String(range_Command(cmd, label))); | ||
100 | } | ||
101 | |||
102 | iRangecc range_Command(const char *cmd, const char *label) { | ||
99 | iRangecc val = { suffixPtr_Command(cmd, label), NULL }; | 103 | iRangecc val = { suffixPtr_Command(cmd, label), NULL }; |
100 | if (val.start) { | 104 | if (val.start) { |
101 | for (val.end = val.start; *val.end && !isspace(*val.end); val.end++) {} | 105 | for (val.end = val.start; *val.end && !isspace(*val.end); val.end++) {} |
102 | return collect_String(newRange_String(val)); | 106 | return val; |
103 | } | 107 | } |
104 | return collectNew_String(); | 108 | return iNullRange; |
105 | } | 109 | } |
106 | 110 | ||
107 | iInt2 dir_Command(const char *cmd) { | 111 | iInt2 dir_Command(const char *cmd) { |
diff --git a/src/ui/command.h b/src/ui/command.h index 4798baa6..43992b8e 100644 --- a/src/ui/command.h +++ b/src/ui/command.h | |||
@@ -22,6 +22,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
22 | 22 | ||
23 | #pragma once | 23 | #pragma once |
24 | 24 | ||
25 | #include <the_Foundation/range.h> | ||
25 | #include <the_Foundation/vec2.h> | 26 | #include <the_Foundation/vec2.h> |
26 | 27 | ||
27 | iBool equal_Command (const char *commandWithArgs, const char *command); | 28 | iBool equal_Command (const char *commandWithArgs, const char *command); |
@@ -36,5 +37,6 @@ iInt2 coord_Command (const char *); | |||
36 | iInt2 dir_Command (const char *); | 37 | iInt2 dir_Command (const char *); |
37 | 38 | ||
38 | const iString * string_Command (const char *, const char *label); /* space-delimited */ | 39 | const iString * string_Command (const char *, const char *label); /* space-delimited */ |
40 | iRangecc range_Command (const char *, const char *label); /* space-delimited */ | ||
39 | const char * suffixPtr_Command (const char *, const char *label); /* until end-of-command */ | 41 | const char * suffixPtr_Command (const char *, const char *label); /* until end-of-command */ |
40 | iString * suffix_Command (const char *, const char *label); /* until end-of-command */ | 42 | iString * suffix_Command (const char *, const char *label); /* until end-of-command */ |
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c index dbe734bf..676f8678 100644 --- a/src/ui/lookupwidget.c +++ b/src/ui/lookupwidget.c | |||
@@ -422,6 +422,8 @@ static void presentResults_LookupWidget_(iLookupWidget *d) { | |||
422 | clear_ListWidget(d->list); | 422 | clear_ListWidget(d->list); |
423 | sort_Array(&job->results, cmpPtr_LookupResult_); | 423 | sort_Array(&job->results, cmpPtr_LookupResult_); |
424 | enum iLookupResultType lastType = none_LookupResultType; | 424 | enum iLookupResultType lastType = none_LookupResultType; |
425 | const size_t maxPerType = 10; /* TODO: Setting? */ | ||
426 | size_t perType = 0; | ||
425 | iConstForEach(PtrArray, i, &job->results) { | 427 | iConstForEach(PtrArray, i, &job->results) { |
426 | const iLookupResult *res = i.ptr; | 428 | const iLookupResult *res = i.ptr; |
427 | if (lastType != res->type) { | 429 | if (lastType != res->type) { |
@@ -434,6 +436,42 @@ static void presentResults_LookupWidget_(iLookupWidget *d) { | |||
434 | addItem_ListWidget(d->list, item); | 436 | addItem_ListWidget(d->list, item); |
435 | iRelease(item); | 437 | iRelease(item); |
436 | lastType = res->type; | 438 | lastType = res->type; |
439 | perType = 0; | ||
440 | } | ||
441 | if (perType > maxPerType) { | ||
442 | continue; | ||
443 | } | ||
444 | if (res->type == identity_LookupResultType) { | ||
445 | const iString *docUrl = url_DocumentWidget(document_App()); | ||
446 | iBlock *finger = hexDecode_Rangecc(range_String(&res->meta)); | ||
447 | const iGmIdentity *ident = findIdentity_GmCerts(certs_App(), finger); | ||
448 | /* Sign in/out. */ { | ||
449 | const iBool isUsed = isUsedOn_GmIdentity(ident, docUrl); | ||
450 | iLookupItem *item = new_LookupItem(res); | ||
451 | item->fg = uiText_ColorId; | ||
452 | item->font = uiContent_FontId; | ||
453 | format_String(&item->text, | ||
454 | "%s \u2014 " uiTextStrong_ColorEscape "%s on this page", | ||
455 | cstr_String(&res->label), | ||
456 | isUsed ? "Stop using" : "Use"); | ||
457 | format_String(&item->command, "ident.sign%s ident:%s url:%s", | ||
458 | isUsed ? "out arg:0" : "in", cstr_String(&res->meta), cstr_String(docUrl)); | ||
459 | addItem_ListWidget(d->list, item); | ||
460 | iRelease(item); | ||
461 | } | ||
462 | if (isUsed_GmIdentity(ident)) { | ||
463 | iLookupItem *item = new_LookupItem(res); | ||
464 | item->fg = uiText_ColorId; | ||
465 | item->font = uiContent_FontId; | ||
466 | format_String(&item->text, | ||
467 | "%s \u2014 " uiTextStrong_ColorEscape "Stop using everywhere", | ||
468 | cstr_String(&res->label)); | ||
469 | format_String(&item->command, "ident.signout arg:1 ident:%s", cstr_String(&res->meta)); | ||
470 | addItem_ListWidget(d->list, item); | ||
471 | iRelease(item); | ||
472 | } | ||
473 | delete_Block(finger); | ||
474 | continue; | ||
437 | } | 475 | } |
438 | iLookupItem *item = new_LookupItem(res); | 476 | iLookupItem *item = new_LookupItem(res); |
439 | const char *url = cstr_String(&res->url); | 477 | const char *url = cstr_String(&res->url); |
@@ -463,19 +501,16 @@ static void presentResults_LookupWidget_(iLookupWidget *d) { | |||
463 | case content_LookupResultType: { | 501 | case content_LookupResultType: { |
464 | item->fg = uiText_ColorId; | 502 | item->fg = uiText_ColorId; |
465 | item->font = uiContent_FontId; | 503 | item->font = uiContent_FontId; |
466 | format_String(&item->text, "%s \u2014 %s", cstr_String(&res->label), url); | 504 | format_String(&item->text, "%s \u2014 pe%s", url, cstr_String(&res->label)); |
467 | format_String(&item->command, "open url:%s", cstr_String(&res->url)); | 505 | format_String(&item->command, "open url:%s", cstr_String(&res->url)); |
468 | break; | 506 | break; |
469 | } | 507 | } |
470 | case identity_LookupResultType: { | 508 | default: |
471 | item->fg = uiText_ColorId; | ||
472 | item->font = uiContent_FontId; | ||
473 | format_String(&item->text, "%s", cstr_String(&res->label)); | ||
474 | break; | 509 | break; |
475 | } | ||
476 | } | 510 | } |
477 | addItem_ListWidget(d->list, item); | 511 | addItem_ListWidget(d->list, item); |
478 | iRelease(item); | 512 | iRelease(item); |
513 | perType++; | ||
479 | } | 514 | } |
480 | delete_LookupJob(job); | 515 | delete_LookupJob(job); |
481 | /* Re-select the item at the cursor. */ | 516 | /* Re-select the item at the cursor. */ |
@@ -483,6 +518,7 @@ static void presentResults_LookupWidget_(iLookupWidget *d) { | |||
483 | d->cursor = iMin(d->cursor, numItems_ListWidget(d->list) - 1); | 518 | d->cursor = iMin(d->cursor, numItems_ListWidget(d->list) - 1); |
484 | ((iListItem *) item_ListWidget(d->list, d->cursor))->isSelected = iTrue; | 519 | ((iListItem *) item_ListWidget(d->list, d->cursor))->isSelected = iTrue; |
485 | } | 520 | } |
521 | scrollOffset_ListWidget(d->list, 0); | ||
486 | updateVisible_ListWidget(d->list); | 522 | updateVisible_ListWidget(d->list); |
487 | invalidate_ListWidget(d->list); | 523 | invalidate_ListWidget(d->list); |
488 | setFlags_Widget(as_Widget(d), hidden_WidgetFlag, numItems_ListWidget(d->list) == 0); | 524 | setFlags_Widget(as_Widget(d), hidden_WidgetFlag, numItems_ListWidget(d->list) == 0); |
@@ -557,13 +593,15 @@ static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) { | |||
557 | } | 593 | } |
558 | } | 594 | } |
559 | if (isCommand_Widget(w, ev, "list.clicked")) { | 595 | if (isCommand_Widget(w, ev, "list.clicked")) { |
560 | setTextCStr_InputWidget(findWidget_App("url"), ""); | 596 | iInputWidget *url = findWidget_App("url"); |
597 | // setTextCStr_InputWidget(findWidget_App("url"), ""); | ||
561 | const iLookupItem *item = constItem_ListWidget(d->list, arg_Command(cmd)); | 598 | const iLookupItem *item = constItem_ListWidget(d->list, arg_Command(cmd)); |
562 | if (item && !isEmpty_String(&item->command)) { | 599 | if (item && !isEmpty_String(&item->command)) { |
563 | postCommandString_App(&item->command); | 600 | setText_InputWidget(url, url_DocumentWidget(document_App())); |
601 | setFocus_Widget(NULL); | ||
564 | setFlags_Widget(w, hidden_WidgetFlag, iTrue); | 602 | setFlags_Widget(w, hidden_WidgetFlag, iTrue); |
565 | setCursor_LookupWidget_(d, iInvalidPos); | 603 | setCursor_LookupWidget_(d, iInvalidPos); |
566 | setFocus_Widget(NULL); | 604 | postCommandString_App(&item->command); |
567 | } | 605 | } |
568 | return iTrue; | 606 | return iTrue; |
569 | } | 607 | } |