1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html#License
3/*
4 *******************************************************************************
5 * Copyright (C) 1996-2010, International Business Machines Corporation and    *
6 * others. All Rights Reserved.                                                *
7 *******************************************************************************
8 */
9package com.ibm.icu.dev.demo.impl;
10import java.text.BreakIterator;
11
12public final class Selection {
13
14    public int anchor;
15    public int caret;
16    public boolean clickAfter;
17
18    public int getStart() {
19        return anchor < caret ? anchor : caret;
20    }
21
22    public int getEnd() {
23        return anchor > caret ? anchor : caret;
24    }
25
26    public boolean isCaret() {
27        return anchor == caret;
28    }
29
30    public Selection set(Selection other) {
31        anchor = other.anchor;
32        caret = other.caret;
33        clickAfter = other.clickAfter;
34        return this;
35    }
36
37    public Selection set(int anchor, int caret, boolean clickAfter) {
38        this.anchor = anchor;
39        this.caret = caret;
40        this.clickAfter = clickAfter;
41        return this;
42    }
43
44    public boolean equals(Object other) {
45        Selection other2 = (Selection)other;
46        return anchor == other2.anchor
47          && caret == other2.caret
48          && clickAfter == other2.clickAfter;
49    }
50
51    public boolean isLessThan(Selection other) {
52        return getStart() < other.getEnd();
53    }
54
55    public Selection pin(String text) {
56        if (anchor > text.length()) {
57            anchor = text.length();
58        } else if (anchor < 0) {
59            anchor = 0;
60        }
61        if (caret > text.length()) {
62            caret = text.length();
63            clickAfter = true;
64        } else if (caret < 0) {
65            caret = 0;
66            clickAfter = false;
67        }
68        return this;
69    }
70
71    public Selection swap(Selection after) {
72        int temp = anchor;
73        anchor = after.anchor;
74        after.anchor = temp;
75        temp = caret;
76        caret = after.caret;
77        after.caret = temp;
78        boolean b = clickAfter;
79        clickAfter = after.clickAfter;
80        after.clickAfter = b;
81        return this;
82    }
83
84    public Selection fixAfterReplace(int start, int end, int len) {
85        if (anchor >= start) {
86            if (anchor < end) anchor = end;
87            anchor = start + len + anchor - end;
88        }
89        if (caret >= start) {
90            if (caret < end) caret = end;
91            caret = start + len + caret - end;
92        }
93        return this;
94    }
95
96        // Mac & Windows considerably different
97        // Mac: end++. If start!=end, start=end
98        //  SHIFT: move end right
99        //  CTL: no different
100        // Windows:
101        //  UNSHIFTED: if start!=end, start = end, else start=end=end+1;
102        //       anchor = tip = start
103        //  SHIFT: tip++
104        //  CTL: if start!=end, start = end = nextbound(end-1),
105        //   else start=end=nextbound(end)
106        //       anchor = tip = start
107        //  CTL/SHIFT: tip = nextbound(tip)
108
109    public Selection nextBound(BreakIterator breaker,
110      int direction, boolean extend) {
111        if (!extend && anchor != caret) caret -= direction;
112        caret = next(caret, breaker, direction, true);
113        if (!extend) anchor = caret;
114        clickAfter = false;
115        return this;
116    }
117
118    // expand start and end to word breaks--if they are not already on one
119    public void expand(BreakIterator breaker) {
120        if (anchor <= caret) {
121            anchor = next(anchor,breaker,-1,false);
122            caret = next(caret,breaker,1,false);
123            /*
124            try {
125                breaker.following(anchor);
126                anchor = breaker.previous();
127            } catch (Exception e) {}
128            try {
129                caret = breaker.following(caret-1);
130            } catch (Exception e) {}
131            */
132        } else {
133            anchor = next(anchor,breaker,1,false);
134            caret = next(caret,breaker,-1,false);
135            /*
136            try {
137                breaker.following(caret);
138                caret = breaker.previous();
139            } catch (Exception e) {}
140            try {
141                anchor = breaker.following(anchor-1);
142            } catch (Exception e) {}
143            */
144        }
145    }
146
147    // different = false - move to next boundary, unless on one
148    // true - move to next boundary, even if on one
149    public static int next(int position, BreakIterator breaker,
150      int direction, boolean different) {
151        if (!different) position -= direction;
152        try {
153            if (direction > 0) {
154                position = breaker.following(position);
155            } else {
156                breaker.following(position-1);
157                position = breaker.previous();
158            }
159        } catch (Exception e) {}
160        return position;
161    }
162}
163
164