From e16dcb7e9d8b85f56d724692a0281811549079e4 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sat, 27 Mar 2021 11:20:33 +0200 Subject: 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. --- src/gmdocument.c | 23 ++++++++++++++++------- src/gmdocument.h | 4 ++-- 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) { return last; } -const char *findLoc_GmDocument(const iGmDocument *d, iInt2 pos) { +iRangecc findLoc_GmDocument(const iGmDocument *d, iInt2 pos) { const iGmRun *run = findRun_GmDocument(d, pos); if (run) { return findLoc_GmRun(run, pos); } - return NULL; + return iNullRange; } const iGmRun *findRunAtLoc_GmDocument(const iGmDocument *d, const char *textCStr) { @@ -1662,16 +1662,25 @@ iChar siteIcon_GmDocument(const iGmDocument *d) { return d->siteIcon; } -const char *findLoc_GmRun(const iGmRun *d, iInt2 pos) { +iRangecc findLoc_GmRun(const iGmRun *d, iInt2 pos) { if (pos.y < top_Rect(d->bounds)) { - return d->text.start; + return (iRangecc){ d->text.start, d->text.start }; } const int x = pos.x - left_Rect(d->bounds); if (x <= 0) { - return d->text.start; + return (iRangecc){ d->text.start, d->text.start }; + } + iRangecc loc; + tryAdvanceNoWrap_Text(d->font, d->text, x, &loc.start); + loc.end = loc.start; + iChar ch; + if (d->text.end != loc.start) { + int chLen = decodeBytes_MultibyteChar(loc.start, d->text.end - loc.start, &ch); + if (chLen > 0) { + /* End after the character. */ + loc.end += chLen; + } } - const char *loc; - tryAdvanceNoWrap_Text(d->font, d->text, x, &loc); return loc; } 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 { const iGmRun *end; }; -const char * findLoc_GmRun (const iGmRun *, iInt2 pos); +iRangecc findLoc_GmRun (const iGmRun *, iInt2 pos); iDeclareClass(GmDocument) iDeclareObjectConstruction(GmDocument) @@ -181,7 +181,7 @@ enum iGmLinkPart { }; const iGmRun * findRun_GmDocument (const iGmDocument *, iInt2 pos); -const char * findLoc_GmDocument (const iGmDocument *, iInt2 pos); +iRangecc findLoc_GmDocument (const iGmDocument *, iInt2 pos); const iGmRun * findRunAtLoc_GmDocument (const iGmDocument *, const char *loc); const iString * linkUrl_GmDocument (const iGmDocument *, iGmLinkId linkId); 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 { setHoverViaKeys_DocumentWidgetFlag = iBit(4), newTabViaHomeKeys_DocumentWidgetFlag = iBit(5), centerVertically_DocumentWidgetFlag = iBit(6), + selectWords_DocumentWidgetFlag = iBit(7), + selectLines_DocumentWidgetFlag = iBit(8), }; enum iDocumentLinkOrdinalMode { @@ -1295,7 +1297,7 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) { unlockResponse_GmRequest(d->request); } -static const char *sourceLoc_DocumentWidget_(const iDocumentWidget *d, iInt2 pos) { +static iRangecc sourceLoc_DocumentWidget_(const iDocumentWidget *d, iInt2 pos) { return findLoc_GmDocument(d->doc, documentPos_DocumentWidget_(d, pos)); } @@ -2591,6 +2593,16 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e return iTrue; } /* The left mouse button. */ + if (/*d->flags & selecting_DocumentWidgetFlag &&*/ ev->type == SDL_MOUSEBUTTONDOWN && + ev->button.button == SDL_BUTTON_LEFT) { + if (ev->button.clicks == 2) { + printf("double click\n"); + } + else if (ev->button.clicks == 3) { + printf("triple click\n"); + } + fflush(stdout); + } switch (processEvent_Click(&d->click, ev)) { case started_ClickResult: iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iFalse); @@ -2612,16 +2624,15 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e invalidateWideRunsWithNonzeroOffset_DocumentWidget_(d); resetWideRuns_DocumentWidget_(d); /* Selections don't support horizontal scrolling. */ iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iTrue); - d->selectMark.start = d->selectMark.end = - sourceLoc_DocumentWidget_(d, d->click.startPos); + d->selectMark = sourceLoc_DocumentWidget_(d, d->click.startPos); refresh_Widget(w); } - const char *loc = sourceLoc_DocumentWidget_(d, pos_Click(&d->click)); + iRangecc loc = sourceLoc_DocumentWidget_(d, pos_Click(&d->click)); if (!d->selectMark.start) { - d->selectMark.start = d->selectMark.end = loc; + d->selectMark = loc; } - else if (loc) { - d->selectMark.end = loc; + else if (loc.end) { + d->selectMark.end = (d->selectMark.end > d->selectMark.start ? loc.end : loc.start); } // printf("mark %zu ... %zu\n", d->selectMark.start - cstr_String(source_GmDocument(d->doc)), // d->selectMark.end - cstr_String(source_GmDocument(d->doc))); @@ -2736,6 +2747,8 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e } return iTrue; case double_ClickResult: + printf("double_ClickResult\n"); fflush(stdout); + return iTrue; case aborted_ClickResult: if (d->grabbedPlayer) { setGrabbedPlayer_DocumentWidget_(d, NULL); -- cgit v1.2.3