capacitor-dex-editor 0.0.38 → 0.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/assets/availableSyntax.json +54 -0
- package/android/src/main/assets/c.json +42 -0
- package/android/src/main/assets/colors.json +21 -0
- package/android/src/main/assets/cpp.json +79 -0
- package/android/src/main/assets/dart.json +108 -0
- package/android/src/main/assets/java.json +46 -0
- package/android/src/main/assets/js.json +54 -0
- package/android/src/main/assets/json.json +33 -0
- package/android/src/main/assets/kotlin.json +53 -0
- package/android/src/main/assets/lua.json +54 -0
- package/android/src/main/assets/php.json +69 -0
- package/android/src/main/assets/python.json +87 -0
- package/android/src/main/assets/rust.json +139 -0
- package/android/src/main/assets/smali.json +131 -0
- package/android/src/main/assets/xml.json +96 -0
- package/android/src/main/java/com/aetherlink/dexeditor/DexEditorPluginPlugin.java +48 -0
- package/android/src/main/java/com/aetherlink/dexeditor/SmaliEditorActivity.java +205 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/EditView.java +4022 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/WordWrapLayout.java +275 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/buffer/BufferCache.java +113 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/buffer/GapBuffer.java +685 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/component/ClipboardPanel.java +1380 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/component/Magnifier.java +363 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/highlight/Candidate.java +52 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/highlight/CommentDef.java +47 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/highlight/LineResult.java +49 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/highlight/MHSyntaxHighlightEngine.java +841 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/highlight/Rule.java +53 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/highlight/Token.java +48 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/listener/OnTextChangedListener.java +6 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/utils/Pair.java +80 -0
- package/android/src/main/java/com/aetherlink/dexeditor/editor/utils/ScreenUtils.java +63 -0
- package/android/src/main/res/drawable/abc_text_cursor_material.xml +9 -0
- package/android/src/main/res/drawable/abc_text_select_handle_left_mtrl.png +0 -0
- package/android/src/main/res/drawable/abc_text_select_handle_middle_mtrl.png +0 -0
- package/android/src/main/res/drawable/abc_text_select_handle_right_mtrl.png +0 -0
- package/android/src/main/res/drawable/ic_arrow_back.xml +12 -0
- package/android/src/main/res/drawable/ic_copy.xml +11 -0
- package/android/src/main/res/drawable/ic_cut.xml +10 -0
- package/android/src/main/res/drawable/ic_delete.xml +12 -0
- package/android/src/main/res/drawable/ic_edit_white_24dp.xml +10 -0
- package/android/src/main/res/drawable/ic_goto.xml +10 -0
- package/android/src/main/res/drawable/ic_launcher_background.xml +186 -0
- package/android/src/main/res/drawable/ic_look_white_24dp.xml +11 -0
- package/android/src/main/res/drawable/ic_more.xml +10 -0
- package/android/src/main/res/drawable/ic_open_link.xml +11 -0
- package/android/src/main/res/drawable/ic_paste.xml +11 -0
- package/android/src/main/res/drawable/ic_redo_white_24dp.xml +10 -0
- package/android/src/main/res/drawable/ic_select.xml +11 -0
- package/android/src/main/res/drawable/ic_select_all.xml +10 -0
- package/android/src/main/res/drawable/ic_share.xml +11 -0
- package/android/src/main/res/drawable/ic_toggle_comment.xml +12 -0
- package/android/src/main/res/drawable/ic_translate.xml +10 -0
- package/android/src/main/res/drawable/ic_undo_white_24dp.xml +11 -0
- package/android/src/main/res/drawable/magnifier_bg.xml +5 -0
- package/android/src/main/res/drawable/popup_background.xml +8 -0
- package/android/src/main/res/drawable/ripple_effect.xml +9 -0
- package/android/src/main/res/drawable/selection_menu_background.xml +5 -0
- package/android/src/main/res/layout/custom_selection_menu.xml +44 -0
- package/android/src/main/res/layout/expand_button.xml +23 -0
- package/android/src/main/res/layout/item_autocomplete.xml +25 -0
- package/android/src/main/res/layout/magnifier_popup.xml +17 -0
- package/android/src/main/res/layout/menu_item.xml +30 -0
- package/android/src/main/res/layout/text_selection_menu.xml +36 -0
- package/package.json +1 -1
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* MH-TextEditor - An Advanced and optimized TextEditor for android
|
|
3
|
+
* Copyright 2025, developer-krushna
|
|
4
|
+
*
|
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
|
6
|
+
* modification, are permitted provided that the following conditions are
|
|
7
|
+
* met:
|
|
8
|
+
*
|
|
9
|
+
* * Redistributions of source code must retain the above copyright
|
|
10
|
+
* notice, this list of conditions and the following disclaimer.
|
|
11
|
+
* * Redistributions in binary form must reproduce the above
|
|
12
|
+
* copyright notice, this list of conditions and the following disclaimer
|
|
13
|
+
* in the documentation and/or other materials provided with the
|
|
14
|
+
* distribution.
|
|
15
|
+
* * Neither the name of developer-krushna nor the names of its
|
|
16
|
+
* contributors may be used to endorse or promote products derived from
|
|
17
|
+
* this software without specific prior written permission.
|
|
18
|
+
*
|
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
20
|
+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
21
|
+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
22
|
+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
23
|
+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
24
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
25
|
+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
26
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
27
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
28
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
* Please contact Krushna by email modder-hub@zohomail.in if you need
|
|
33
|
+
* additional information or have any questions
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
package com.aetherlink.dexeditor.editor;
|
|
37
|
+
|
|
38
|
+
import android.util.Log;
|
|
39
|
+
import com.aetherlink.dexeditor.editor.EditView;
|
|
40
|
+
import com.aetherlink.dexeditor.editor.GapBuffer;
|
|
41
|
+
import java.util.ArrayList;
|
|
42
|
+
import java.util.List;
|
|
43
|
+
|
|
44
|
+
// Not ready yet
|
|
45
|
+
public class WordWrapLayout {
|
|
46
|
+
private static final String TAG = "WordWrapLayout";
|
|
47
|
+
|
|
48
|
+
private EditView mEditView;
|
|
49
|
+
private GapBuffer mGapBuffer;
|
|
50
|
+
private List<RowRegion> mRowTable;
|
|
51
|
+
private int mEditorWidth;
|
|
52
|
+
private boolean mEnabled = false;
|
|
53
|
+
|
|
54
|
+
public WordWrapLayout(EditView editView) {
|
|
55
|
+
this.mEditView = editView;
|
|
56
|
+
this.mGapBuffer = editView.getBuffer();
|
|
57
|
+
this.mRowTable = new ArrayList<>();
|
|
58
|
+
this.mEditorWidth = editView.getWidth();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public void setEnabled(boolean enabled) {
|
|
62
|
+
this.mEnabled = enabled;
|
|
63
|
+
if (enabled) {
|
|
64
|
+
breakAllLines();
|
|
65
|
+
} else {
|
|
66
|
+
mRowTable.clear();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public boolean isEnabled() {
|
|
71
|
+
return mEnabled;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public void setEditorWidth(int width) {
|
|
75
|
+
this.mEditorWidth = width;
|
|
76
|
+
if (mEnabled) {
|
|
77
|
+
breakAllLines();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private void breakAllLines() {
|
|
82
|
+
if (!mEnabled || mGapBuffer == null) return;
|
|
83
|
+
|
|
84
|
+
mRowTable.clear();
|
|
85
|
+
|
|
86
|
+
for (int line = 1; line <= mGapBuffer.getLineCount(); line++) {
|
|
87
|
+
breakLine(line);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
Log.d(TAG, "Word wrap completed. Total rows: " + mRowTable.size());
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private void breakLine(int lineNumber) {
|
|
94
|
+
if (!mEnabled) return;
|
|
95
|
+
|
|
96
|
+
String lineText = mGapBuffer.getLine(lineNumber);
|
|
97
|
+
if (lineText == null || lineText.isEmpty()) {
|
|
98
|
+
// Empty line still needs one row
|
|
99
|
+
mRowTable.add(new RowRegion(lineNumber, 0, 0));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
int lineStart = mGapBuffer.getLineOffset(lineNumber);
|
|
104
|
+
int currentPos = 0;
|
|
105
|
+
int lineLength = lineText.length();
|
|
106
|
+
|
|
107
|
+
while (currentPos < lineLength) {
|
|
108
|
+
int breakPoint = findBreakPoint(lineText, currentPos, lineLength);
|
|
109
|
+
|
|
110
|
+
if (breakPoint == currentPos) {
|
|
111
|
+
// Force break if no space found
|
|
112
|
+
breakPoint = Math.min(currentPos + 1, lineLength);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
mRowTable.add(new RowRegion(lineNumber, lineStart + currentPos, lineStart + breakPoint));
|
|
116
|
+
currentPos = breakPoint;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// If we didn't add any rows (shouldn't happen), add at least one
|
|
120
|
+
if (mRowTable.isEmpty() || mRowTable.get(mRowTable.size() - 1).line != lineNumber) {
|
|
121
|
+
mRowTable.add(new RowRegion(lineNumber, lineStart, lineStart + lineLength));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private int findBreakPoint(String text, int start, int maxLength) {
|
|
126
|
+
if (start >= maxLength) return maxLength;
|
|
127
|
+
|
|
128
|
+
int availableWidth = mEditorWidth - mEditView.getLeftSpace() - 20; // Some padding
|
|
129
|
+
int currentWidth = 0;
|
|
130
|
+
int lastBreakable = start;
|
|
131
|
+
|
|
132
|
+
for (int i = start; i < maxLength; i++) {
|
|
133
|
+
char c = text.charAt(i);
|
|
134
|
+
String charStr = String.valueOf(c);
|
|
135
|
+
int charWidth = mEditView.measureText(charStr);
|
|
136
|
+
|
|
137
|
+
// Check if adding this character would exceed available width
|
|
138
|
+
if (currentWidth + charWidth > availableWidth) {
|
|
139
|
+
if (lastBreakable > start) {
|
|
140
|
+
// Break at last breakable position
|
|
141
|
+
return lastBreakable;
|
|
142
|
+
} else {
|
|
143
|
+
// No breakable position found, break here
|
|
144
|
+
return i;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
currentWidth += charWidth;
|
|
149
|
+
|
|
150
|
+
// Mark breakable positions (spaces, punctuation)
|
|
151
|
+
if (isBreakableChar(c)) {
|
|
152
|
+
lastBreakable = i + 1; // Break after the space/punctuation
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Break at newlines
|
|
156
|
+
if (c == '\n') {
|
|
157
|
+
return i + 1;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return maxLength;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private boolean isBreakableChar(char c) {
|
|
165
|
+
return c == ' ' || c == '\t' || c == '.' || c == ',' || c == ';' || c == ':' ||
|
|
166
|
+
c == '!' || c == '?' || c == ')' || c == ']' || c == '}';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public void onTextChanged(int startLine, int endLine) {
|
|
170
|
+
if (!mEnabled) return;
|
|
171
|
+
|
|
172
|
+
// Remove affected rows
|
|
173
|
+
for (int i = mRowTable.size() - 1; i >= 0; i--) {
|
|
174
|
+
RowRegion region = mRowTable.get(i);
|
|
175
|
+
if (region.line >= startLine && region.line <= endLine) {
|
|
176
|
+
mRowTable.remove(i);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Re-break affected lines
|
|
181
|
+
for (int line = startLine; line <= endLine; line++) {
|
|
182
|
+
breakLine(line);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Update line numbers for subsequent lines
|
|
186
|
+
int delta = endLine - startLine;
|
|
187
|
+
if (delta != 0) {
|
|
188
|
+
for (int i = 0; i < mRowTable.size(); i++) {
|
|
189
|
+
RowRegion region = mRowTable.get(i);
|
|
190
|
+
if (region.line > endLine) {
|
|
191
|
+
region.line += delta;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public int getRowCount() {
|
|
198
|
+
if (!mEnabled) {
|
|
199
|
+
return mGapBuffer.getLineCount();
|
|
200
|
+
}
|
|
201
|
+
return mRowTable.size();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
public int getLineForRow(int row) {
|
|
205
|
+
if (!mEnabled || row < 0 || row >= mRowTable.size()) {
|
|
206
|
+
return Math.max(1, Math.min(row + 1, mGapBuffer.getLineCount()));
|
|
207
|
+
}
|
|
208
|
+
return mRowTable.get(row).line;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public RowRegion getRowRegion(int row) {
|
|
212
|
+
if (!mEnabled || row < 0 || row >= mRowTable.size()) {
|
|
213
|
+
int line = Math.max(1, Math.min(row + 1, mGapBuffer.getLineCount()));
|
|
214
|
+
int lineStart = mGapBuffer.getLineOffset(line);
|
|
215
|
+
int lineEnd = lineStart + mGapBuffer.getLine(line).length();
|
|
216
|
+
return new RowRegion(line, lineStart, lineEnd);
|
|
217
|
+
}
|
|
218
|
+
return mRowTable.get(row);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public int findRowForPosition(int line, int column) {
|
|
222
|
+
if (!mEnabled) {
|
|
223
|
+
return line - 1; // Convert to 0-based
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for (int row = 0; row < mRowTable.size(); row++) {
|
|
227
|
+
RowRegion region = mRowTable.get(row);
|
|
228
|
+
if (region.line == line && column >= region.start && column < region.end) {
|
|
229
|
+
return row;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Fallback: find the first row for this line
|
|
234
|
+
for (int row = 0; row < mRowTable.size(); row++) {
|
|
235
|
+
if (mRowTable.get(row).line == line) {
|
|
236
|
+
return row;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return Math.max(0, line - 1);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
public int getRowHeight() {
|
|
244
|
+
return mEditView.getLineHeight();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
public int getTotalHeight() {
|
|
248
|
+
return getRowCount() * getRowHeight();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
public class RowRegion {
|
|
252
|
+
public int line;
|
|
253
|
+
public int start;
|
|
254
|
+
public int end;
|
|
255
|
+
|
|
256
|
+
public RowRegion(int line, int start, int end) {
|
|
257
|
+
this.line = line;
|
|
258
|
+
this.start = start;
|
|
259
|
+
this.end = end;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
public boolean isFirstRow() {
|
|
263
|
+
return start == mGapBuffer.getLineOffset(line);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
public int getLength() {
|
|
267
|
+
return end - start;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
@Override
|
|
271
|
+
public String toString() {
|
|
272
|
+
return "RowRegion{line=" + line + ", start=" + start + ", end=" + end + "}";
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A LRU cache that stores the last seek line and its corresponding index so that future lookups can
|
|
3
|
+
* start from the cached position instead of the beginning of the file
|
|
4
|
+
*
|
|
5
|
+
* <p>_cache.Pair.First = line index _cache.Pair.Second = character offset of first character in
|
|
6
|
+
* that line
|
|
7
|
+
*
|
|
8
|
+
* <p>TextBufferCache always has one valid entry (0,0) signifying that in line 0, the first
|
|
9
|
+
* character is at offset 0. This is true even for an "empty" file, which is not really empty
|
|
10
|
+
* because TextBuffer inserts a EOF character in it.
|
|
11
|
+
*
|
|
12
|
+
* <p>Therefore, _cache[0] is always occupied by the entry (0,0). It is not affected by
|
|
13
|
+
* invalidateCache, cache miss, etc. operations
|
|
14
|
+
*/
|
|
15
|
+
package com.aetherlink.dexeditor.editor.buffer;
|
|
16
|
+
|
|
17
|
+
import com.aetherlink.dexeditor.editor.utils.Pair;
|
|
18
|
+
|
|
19
|
+
public class BufferCache {
|
|
20
|
+
private final int CACHE_SIZE = 4; // minimum = 1
|
|
21
|
+
private Pair<Integer, Integer>[] _cache;
|
|
22
|
+
|
|
23
|
+
public BufferCache() {
|
|
24
|
+
_cache = new Pair[CACHE_SIZE];
|
|
25
|
+
_cache[0] = new Pair<Integer, Integer>(0, 0); // invariant lineIndex and charOffset relation
|
|
26
|
+
for (int i = 1; i < CACHE_SIZE; ++i) {
|
|
27
|
+
_cache[i] = new Pair<Integer, Integer>(-1, -1);
|
|
28
|
+
// -1 line index is used implicitly in calculations in getNearestMatch
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// TODO consider extracting common parts with getNearestCharOffset(int)
|
|
33
|
+
public Pair<Integer, Integer> getNearestLine(int lineIndex) {
|
|
34
|
+
int nearestMatch = 0;
|
|
35
|
+
int nearestDistance = Integer.MAX_VALUE;
|
|
36
|
+
for (int i = 0; i < CACHE_SIZE; ++i) {
|
|
37
|
+
int distance = Math.abs(lineIndex - _cache[i].first);
|
|
38
|
+
if (distance < nearestDistance) {
|
|
39
|
+
nearestDistance = distance;
|
|
40
|
+
nearestMatch = i;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Pair<Integer, Integer> nearestEntry = _cache[nearestMatch];
|
|
45
|
+
makeHead(nearestMatch);
|
|
46
|
+
return nearestEntry;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public Pair<Integer, Integer> getNearestCharOffset(int charOffset) {
|
|
50
|
+
int nearestMatch = 0;
|
|
51
|
+
int nearestDistance = Integer.MAX_VALUE;
|
|
52
|
+
for (int i = 0; i < CACHE_SIZE; ++i) {
|
|
53
|
+
int distance = Math.abs(charOffset - _cache[i].second);
|
|
54
|
+
if (distance < nearestDistance) {
|
|
55
|
+
nearestDistance = distance;
|
|
56
|
+
nearestMatch = i;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
Pair<Integer, Integer> nearestEntry = _cache[nearestMatch];
|
|
61
|
+
makeHead(nearestMatch);
|
|
62
|
+
return nearestEntry;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Place _cache[newHead] at the top of the list */
|
|
66
|
+
private void makeHead(int newHead) {
|
|
67
|
+
if (newHead == 0) {
|
|
68
|
+
return; // nothing to do for _cache[0]
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
Pair<Integer, Integer> temp = _cache[newHead];
|
|
72
|
+
for (int i = newHead; i > 1; --i) {
|
|
73
|
+
_cache[i] = _cache[i - 1];
|
|
74
|
+
}
|
|
75
|
+
_cache[1] = temp; // _cache[0] is always occupied by (0,0)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public void updateEntry(int lineIndex, int charOffset) {
|
|
79
|
+
if (lineIndex <= 0) {
|
|
80
|
+
// lineIndex 0 always has 0 charOffset; ignore. Also ignore negative lineIndex
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!replaceEntry(lineIndex, charOffset)) {
|
|
85
|
+
insertEntry(lineIndex, charOffset);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private boolean replaceEntry(int lineIndex, int charOffset) {
|
|
90
|
+
for (int i = 1; i < CACHE_SIZE; ++i) {
|
|
91
|
+
if (_cache[i].first == lineIndex) {
|
|
92
|
+
_cache[i].second = charOffset;
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private void insertEntry(int lineIndex, int charOffset) {
|
|
100
|
+
makeHead(CACHE_SIZE - 1); // rotate right list of entries
|
|
101
|
+
// replace head (most recently used entry) with new entry
|
|
102
|
+
_cache[1] = new Pair<Integer, Integer>(lineIndex, charOffset);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Invalidate all cache entries that have char offset >= fromCharOffset */
|
|
106
|
+
public void invalidateCache(int fromCharOffset) {
|
|
107
|
+
for (int i = 1; i < CACHE_SIZE; ++i) {
|
|
108
|
+
if (_cache[i].second >= fromCharOffset) {
|
|
109
|
+
_cache[i] = new Pair<Integer, Integer>(-1, -1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|