diff options
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 83 |
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 | ||
2329 | static 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 | |||
2328 | static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) { | 2338 | static 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 { |