diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-27 11:20:33 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-27 11:20:33 +0200 |
commit | e16dcb7e9d8b85f56d724692a0281811549079e4 (patch) | |
tree | bba25e250eb6cda54734a63ce7158d591ad70c7b | |
parent | d75ad4213c81e588358aee4786ad13ca08c80d0c (diff) |
GmDocument: Finding position in source
The returned position at a source location is now a range, pointing to the left and right edges of the contacted character.
-rw-r--r-- | src/gmdocument.c | 23 | ||||
-rw-r--r-- | src/gmdocument.h | 4 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 27 |
3 files changed, 38 insertions, 16 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c index 3cf00a4b..30f5169a 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -1528,12 +1528,12 @@ const iGmRun *findRun_GmDocument(const iGmDocument *d, iInt2 pos) { | |||
1528 | return last; | 1528 | return last; |
1529 | } | 1529 | } |
1530 | 1530 | ||
1531 | const char *findLoc_GmDocument(const iGmDocument *d, iInt2 pos) { | 1531 | iRangecc findLoc_GmDocument(const iGmDocument *d, iInt2 pos) { |
1532 | const iGmRun *run = findRun_GmDocument(d, pos); | 1532 | const iGmRun *run = findRun_GmDocument(d, pos); |
1533 | if (run) { | 1533 | if (run) { |
1534 | return findLoc_GmRun(run, pos); | 1534 | return findLoc_GmRun(run, pos); |
1535 | } | 1535 | } |
1536 | return NULL; | 1536 | return iNullRange; |
1537 | } | 1537 | } |
1538 | 1538 | ||
1539 | const iGmRun *findRunAtLoc_GmDocument(const iGmDocument *d, const char *textCStr) { | 1539 | const iGmRun *findRunAtLoc_GmDocument(const iGmDocument *d, const char *textCStr) { |
@@ -1662,16 +1662,25 @@ iChar siteIcon_GmDocument(const iGmDocument *d) { | |||
1662 | return d->siteIcon; | 1662 | return d->siteIcon; |
1663 | } | 1663 | } |
1664 | 1664 | ||
1665 | const char *findLoc_GmRun(const iGmRun *d, iInt2 pos) { | 1665 | iRangecc findLoc_GmRun(const iGmRun *d, iInt2 pos) { |
1666 | if (pos.y < top_Rect(d->bounds)) { | 1666 | if (pos.y < top_Rect(d->bounds)) { |
1667 | return d->text.start; | 1667 | return (iRangecc){ d->text.start, d->text.start }; |
1668 | } | 1668 | } |
1669 | const int x = pos.x - left_Rect(d->bounds); | 1669 | const int x = pos.x - left_Rect(d->bounds); |
1670 | if (x <= 0) { | 1670 | if (x <= 0) { |
1671 | return d->text.start; | 1671 | return (iRangecc){ d->text.start, d->text.start }; |
1672 | } | ||
1673 | iRangecc loc; | ||
1674 | tryAdvanceNoWrap_Text(d->font, d->text, x, &loc.start); | ||
1675 | loc.end = loc.start; | ||
1676 | iChar ch; | ||
1677 | if (d->text.end != loc.start) { | ||
1678 | int chLen = decodeBytes_MultibyteChar(loc.start, d->text.end - loc.start, &ch); | ||
1679 | if (chLen > 0) { | ||
1680 | /* End after the character. */ | ||
1681 | loc.end += chLen; | ||
1682 | } | ||
1672 | } | 1683 | } |
1673 | const char *loc; | ||
1674 | tryAdvanceNoWrap_Text(d->font, d->text, x, &loc); | ||
1675 | return loc; | 1684 | return loc; |
1676 | } | 1685 | } |
1677 | 1686 | ||
diff --git a/src/gmdocument.h b/src/gmdocument.h index 840cf929..57c19e9a 100644 --- a/src/gmdocument.h +++ b/src/gmdocument.h | |||
@@ -126,7 +126,7 @@ struct Impl_GmRunRange { | |||
126 | const iGmRun *end; | 126 | const iGmRun *end; |
127 | }; | 127 | }; |
128 | 128 | ||
129 | const char * findLoc_GmRun (const iGmRun *, iInt2 pos); | 129 | iRangecc findLoc_GmRun (const iGmRun *, iInt2 pos); |
130 | 130 | ||
131 | iDeclareClass(GmDocument) | 131 | iDeclareClass(GmDocument) |
132 | iDeclareObjectConstruction(GmDocument) | 132 | iDeclareObjectConstruction(GmDocument) |
@@ -181,7 +181,7 @@ enum iGmLinkPart { | |||
181 | }; | 181 | }; |
182 | 182 | ||
183 | const iGmRun * findRun_GmDocument (const iGmDocument *, iInt2 pos); | 183 | const iGmRun * findRun_GmDocument (const iGmDocument *, iInt2 pos); |
184 | const char * findLoc_GmDocument (const iGmDocument *, iInt2 pos); | 184 | iRangecc findLoc_GmDocument (const iGmDocument *, iInt2 pos); |
185 | const iGmRun * findRunAtLoc_GmDocument (const iGmDocument *, const char *loc); | 185 | const iGmRun * findRunAtLoc_GmDocument (const iGmDocument *, const char *loc); |
186 | const iString * linkUrl_GmDocument (const iGmDocument *, iGmLinkId linkId); | 186 | const iString * linkUrl_GmDocument (const iGmDocument *, iGmLinkId linkId); |
187 | iRangecc linkUrlRange_GmDocument (const iGmDocument *, iGmLinkId linkId); | 187 | iRangecc linkUrlRange_GmDocument (const iGmDocument *, iGmLinkId linkId); |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 67cefc9b..57f87ef9 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -166,6 +166,8 @@ enum iDocumentWidgetFlag { | |||
166 | setHoverViaKeys_DocumentWidgetFlag = iBit(4), | 166 | setHoverViaKeys_DocumentWidgetFlag = iBit(4), |
167 | newTabViaHomeKeys_DocumentWidgetFlag = iBit(5), | 167 | newTabViaHomeKeys_DocumentWidgetFlag = iBit(5), |
168 | centerVertically_DocumentWidgetFlag = iBit(6), | 168 | centerVertically_DocumentWidgetFlag = iBit(6), |
169 | selectWords_DocumentWidgetFlag = iBit(7), | ||
170 | selectLines_DocumentWidgetFlag = iBit(8), | ||
169 | }; | 171 | }; |
170 | 172 | ||
171 | enum iDocumentLinkOrdinalMode { | 173 | enum iDocumentLinkOrdinalMode { |
@@ -1295,7 +1297,7 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | |||
1295 | unlockResponse_GmRequest(d->request); | 1297 | unlockResponse_GmRequest(d->request); |
1296 | } | 1298 | } |
1297 | 1299 | ||
1298 | static const char *sourceLoc_DocumentWidget_(const iDocumentWidget *d, iInt2 pos) { | 1300 | static iRangecc sourceLoc_DocumentWidget_(const iDocumentWidget *d, iInt2 pos) { |
1299 | return findLoc_GmDocument(d->doc, documentPos_DocumentWidget_(d, pos)); | 1301 | return findLoc_GmDocument(d->doc, documentPos_DocumentWidget_(d, pos)); |
1300 | } | 1302 | } |
1301 | 1303 | ||
@@ -2591,6 +2593,16 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
2591 | return iTrue; | 2593 | return iTrue; |
2592 | } | 2594 | } |
2593 | /* The left mouse button. */ | 2595 | /* The left mouse button. */ |
2596 | if (/*d->flags & selecting_DocumentWidgetFlag &&*/ ev->type == SDL_MOUSEBUTTONDOWN && | ||
2597 | ev->button.button == SDL_BUTTON_LEFT) { | ||
2598 | if (ev->button.clicks == 2) { | ||
2599 | printf("double click\n"); | ||
2600 | } | ||
2601 | else if (ev->button.clicks == 3) { | ||
2602 | printf("triple click\n"); | ||
2603 | } | ||
2604 | fflush(stdout); | ||
2605 | } | ||
2594 | switch (processEvent_Click(&d->click, ev)) { | 2606 | switch (processEvent_Click(&d->click, ev)) { |
2595 | case started_ClickResult: | 2607 | case started_ClickResult: |
2596 | iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iFalse); | 2608 | iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iFalse); |
@@ -2612,16 +2624,15 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
2612 | invalidateWideRunsWithNonzeroOffset_DocumentWidget_(d); | 2624 | invalidateWideRunsWithNonzeroOffset_DocumentWidget_(d); |
2613 | resetWideRuns_DocumentWidget_(d); /* Selections don't support horizontal scrolling. */ | 2625 | resetWideRuns_DocumentWidget_(d); /* Selections don't support horizontal scrolling. */ |
2614 | iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iTrue); | 2626 | iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iTrue); |
2615 | d->selectMark.start = d->selectMark.end = | 2627 | d->selectMark = sourceLoc_DocumentWidget_(d, d->click.startPos); |
2616 | sourceLoc_DocumentWidget_(d, d->click.startPos); | ||
2617 | refresh_Widget(w); | 2628 | refresh_Widget(w); |
2618 | } | 2629 | } |
2619 | const char *loc = sourceLoc_DocumentWidget_(d, pos_Click(&d->click)); | 2630 | iRangecc loc = sourceLoc_DocumentWidget_(d, pos_Click(&d->click)); |
2620 | if (!d->selectMark.start) { | 2631 | if (!d->selectMark.start) { |
2621 | d->selectMark.start = d->selectMark.end = loc; | 2632 | d->selectMark = loc; |
2622 | } | 2633 | } |
2623 | else if (loc) { | 2634 | else if (loc.end) { |
2624 | d->selectMark.end = loc; | 2635 | d->selectMark.end = (d->selectMark.end > d->selectMark.start ? loc.end : loc.start); |
2625 | } | 2636 | } |
2626 | // printf("mark %zu ... %zu\n", d->selectMark.start - cstr_String(source_GmDocument(d->doc)), | 2637 | // printf("mark %zu ... %zu\n", d->selectMark.start - cstr_String(source_GmDocument(d->doc)), |
2627 | // d->selectMark.end - cstr_String(source_GmDocument(d->doc))); | 2638 | // d->selectMark.end - cstr_String(source_GmDocument(d->doc))); |
@@ -2736,6 +2747,8 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
2736 | } | 2747 | } |
2737 | return iTrue; | 2748 | return iTrue; |
2738 | case double_ClickResult: | 2749 | case double_ClickResult: |
2750 | printf("double_ClickResult\n"); fflush(stdout); | ||
2751 | return iTrue; | ||
2739 | case aborted_ClickResult: | 2752 | case aborted_ClickResult: |
2740 | if (d->grabbedPlayer) { | 2753 | if (d->grabbedPlayer) { |
2741 | setGrabbedPlayer_DocumentWidget_(d, NULL); | 2754 | setGrabbedPlayer_DocumentWidget_(d, NULL); |