summaryrefslogtreecommitdiff
path: root/src/ui/documentwidget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r--src/ui/documentwidget.c83
1 files changed, 60 insertions, 23 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index b3508b8d..6bb16a93 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -198,6 +198,7 @@ struct Impl_DocumentWidget {
198 iString * certSubject; 198 iString * certSubject;
199 int redirectCount; 199 int redirectCount;
200 iRangecc selectMark; 200 iRangecc selectMark;
201 iRangecc initialSelectMark; /* for word/line selection */
201 iRangecc foundMark; 202 iRangecc foundMark;
202 int pageMargin; 203 int pageMargin;
203 iPtrArray visibleLinks; 204 iPtrArray visibleLinks;
@@ -2325,6 +2326,15 @@ static iChar linkOrdinalChar_DocumentWidget_(const iDocumentWidget *d, size_t or
2325 return 0; 2326 return 0;
2326} 2327}
2327 2328
2329static void beginMarkingSelection_DocumentWidget_(iDocumentWidget *d, iInt2 pos) {
2330 setFocus_Widget(NULL); /* TODO: Focus this document? */
2331 invalidateWideRunsWithNonzeroOffset_DocumentWidget_(d);
2332 resetWideRuns_DocumentWidget_(d); /* Selections don't support horizontal scrolling. */
2333 iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iTrue);
2334 d->selectMark = sourceLoc_DocumentWidget_(d, pos);
2335 refresh_Widget(as_Widget(d));
2336}
2337
2328static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) { 2338static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) {
2329 iWidget *w = as_Widget(d); 2339 iWidget *w = as_Widget(d);
2330 if (isMetricsChange_UserEvent(ev)) { 2340 if (isMetricsChange_UserEvent(ev)) {
@@ -2593,19 +2603,28 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
2593 return iTrue; 2603 return iTrue;
2594 } 2604 }
2595 /* The left mouse button. */ 2605 /* 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 }
2606 switch (processEvent_Click(&d->click, ev)) { 2606 switch (processEvent_Click(&d->click, ev)) {
2607 case started_ClickResult: 2607 case started_ClickResult:
2608 if (d->grabbedPlayer) {
2609 return iTrue;
2610 }
2608 iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iFalse); 2611 iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iFalse);
2612 iChangeFlags(d->flags, selectWords_DocumentWidgetFlag, d->click.count == 2);
2613 iChangeFlags(d->flags, selectLines_DocumentWidgetFlag, d->click.count >= 3);
2614 /* Double/triple clicks marks the selection immediately. */
2615 if (d->click.count >= 2) {
2616 beginMarkingSelection_DocumentWidget_(d, d->click.startPos);
2617 extendRange_Rangecc(
2618 &d->selectMark,
2619 range_String(source_GmDocument(d->doc)),
2620 bothStartAndEnd_RangeExtension |
2621 (d->click.count == 2 ? word_RangeExtension : line_RangeExtension));
2622 d->initialSelectMark = d->selectMark;
2623 refresh_Widget(w);
2624 }
2625 else {
2626 d->initialSelectMark = iNullRange;
2627 }
2609 return iTrue; 2628 return iTrue;
2610 case drag_ClickResult: { 2629 case drag_ClickResult: {
2611 if (d->grabbedPlayer) { 2630 if (d->grabbedPlayer) {
@@ -2620,12 +2639,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
2620 } 2639 }
2621 /* Begin selecting a range of text. */ 2640 /* Begin selecting a range of text. */
2622 if (~d->flags & selecting_DocumentWidgetFlag) { 2641 if (~d->flags & selecting_DocumentWidgetFlag) {
2623 setFocus_Widget(NULL); /* TODO: Focus this document? */ 2642 beginMarkingSelection_DocumentWidget_(d, d->click.startPos);
2624 invalidateWideRunsWithNonzeroOffset_DocumentWidget_(d);
2625 resetWideRuns_DocumentWidget_(d); /* Selections don't support horizontal scrolling. */
2626 iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iTrue);
2627 d->selectMark = sourceLoc_DocumentWidget_(d, d->click.startPos);
2628 refresh_Widget(w);
2629 } 2643 }
2630 iRangecc loc = sourceLoc_DocumentWidget_(d, pos_Click(&d->click)); 2644 iRangecc loc = sourceLoc_DocumentWidget_(d, pos_Click(&d->click));
2631 if (!d->selectMark.start) { 2645 if (!d->selectMark.start) {
@@ -2634,6 +2648,23 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
2634 else if (loc.end) { 2648 else if (loc.end) {
2635 d->selectMark.end = (d->selectMark.end > d->selectMark.start ? loc.end : loc.start); 2649 d->selectMark.end = (d->selectMark.end > d->selectMark.start ? loc.end : loc.start);
2636 } 2650 }
2651 iAssert((!d->selectMark.start && !d->selectMark.end) ||
2652 ( d->selectMark.start && d->selectMark.end));
2653 /* Extend the selection when double/triple clicking. */
2654 if (d->flags & (selectWords_DocumentWidgetFlag | selectLines_DocumentWidgetFlag)) {
2655 extendRange_Rangecc(
2656 &d->selectMark,
2657 range_String(source_GmDocument(d->doc)),
2658 d->click.count == 2 ? word_RangeExtension : line_RangeExtension);
2659 if (!isEmpty_Range(&d->initialSelectMark)) {
2660 if (d->selectMark.end > d->selectMark.start) {
2661 d->selectMark.start = d->initialSelectMark.start;
2662 }
2663 else if (d->selectMark.end < d->selectMark.start) {
2664 d->selectMark.start = d->initialSelectMark.end;
2665 }
2666 }
2667 }
2637// printf("mark %zu ... %zu\n", d->selectMark.start - cstr_String(source_GmDocument(d->doc)), 2668// printf("mark %zu ... %zu\n", d->selectMark.start - cstr_String(source_GmDocument(d->doc)),
2638// d->selectMark.end - cstr_String(source_GmDocument(d->doc))); 2669// d->selectMark.end - cstr_String(source_GmDocument(d->doc)));
2639// fflush(stdout); 2670// fflush(stdout);
@@ -2727,7 +2758,8 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
2727 2); 2758 2);
2728 } 2759 }
2729 } 2760 }
2730 if (d->selectMark.start) { 2761 if (d->selectMark.start && !(d->flags & (selectLines_DocumentWidgetFlag |
2762 selectWords_DocumentWidgetFlag))) {
2731 d->selectMark = iNullRange; 2763 d->selectMark = iNullRange;
2732 refresh_Widget(w); 2764 refresh_Widget(w);
2733 } 2765 }
@@ -2776,16 +2808,21 @@ static void fillRange_DrawContext_(iDrawContext *d, const iGmRun *run, enum iCol
2776 /* Selection may be done in either direction. */ 2808 /* Selection may be done in either direction. */
2777 iSwap(const char *, mark.start, mark.end); 2809 iSwap(const char *, mark.start, mark.end);
2778 } 2810 }
2779 if ((!*isInside && (contains_Range(&run->text, mark.start) || mark.start == run->text.end)) || 2811 if (*isInside || (contains_Range(&run->text, mark.start) ||
2780 *isInside) { 2812 contains_Range(&mark, run->text.start))) {
2781 int x = 0; 2813 int x = 0;
2782 if (!*isInside) { 2814 if (!*isInside) {
2783 x = advanceRange_Text(run->font, (iRangecc){ run->text.start, mark.start }).x; 2815 x = advanceRange_Text(run->font,
2816 (iRangecc){ run->text.start, iMax(run->text.start, mark.start) })
2817 .x;
2784 } 2818 }
2785 int w = width_Rect(run->visBounds) - x; 2819 int w = width_Rect(run->visBounds) - x;
2786 if (contains_Range(&run->text, mark.end) || run->text.end == mark.end) { 2820 if (contains_Range(&run->text, mark.end) || mark.end < run->text.start) {
2787 w = advanceRange_Text(run->font, 2821 w = advanceRange_Text(
2788 !*isInside ? mark : (iRangecc){ run->text.start, mark.end }).x; 2822 run->font,
2823 !*isInside ? mark
2824 : (iRangecc){ run->text.start, iMax(run->text.start, mark.end) })
2825 .x;
2789 *isInside = iFalse; 2826 *isInside = iFalse;
2790 } 2827 }
2791 else { 2828 else {