summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-27 11:20:33 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-27 11:20:33 +0200
commite16dcb7e9d8b85f56d724692a0281811549079e4 (patch)
treebba25e250eb6cda54734a63ce7158d591ad70c7b
parentd75ad4213c81e588358aee4786ad13ca08c80d0c (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.c23
-rw-r--r--src/gmdocument.h4
-rw-r--r--src/ui/documentwidget.c27
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
1531const char *findLoc_GmDocument(const iGmDocument *d, iInt2 pos) { 1531iRangecc 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
1539const iGmRun *findRunAtLoc_GmDocument(const iGmDocument *d, const char *textCStr) { 1539const 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
1665const char *findLoc_GmRun(const iGmRun *d, iInt2 pos) { 1665iRangecc 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
129const char * findLoc_GmRun (const iGmRun *, iInt2 pos); 129iRangecc findLoc_GmRun (const iGmRun *, iInt2 pos);
130 130
131iDeclareClass(GmDocument) 131iDeclareClass(GmDocument)
132iDeclareObjectConstruction(GmDocument) 132iDeclareObjectConstruction(GmDocument)
@@ -181,7 +181,7 @@ enum iGmLinkPart {
181}; 181};
182 182
183const iGmRun * findRun_GmDocument (const iGmDocument *, iInt2 pos); 183const iGmRun * findRun_GmDocument (const iGmDocument *, iInt2 pos);
184const char * findLoc_GmDocument (const iGmDocument *, iInt2 pos); 184iRangecc findLoc_GmDocument (const iGmDocument *, iInt2 pos);
185const iGmRun * findRunAtLoc_GmDocument (const iGmDocument *, const char *loc); 185const iGmRun * findRunAtLoc_GmDocument (const iGmDocument *, const char *loc);
186const iString * linkUrl_GmDocument (const iGmDocument *, iGmLinkId linkId); 186const iString * linkUrl_GmDocument (const iGmDocument *, iGmLinkId linkId);
187iRangecc linkUrlRange_GmDocument (const iGmDocument *, iGmLinkId linkId); 187iRangecc 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
171enum iDocumentLinkOrdinalMode { 173enum 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
1298static const char *sourceLoc_DocumentWidget_(const iDocumentWidget *d, iInt2 pos) { 1300static 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);