001: package gnu.jemacs.swing;
002:
003: import gnu.jemacs.buffer.*;
004: import javax.swing.text.*;
005: import javax.swing.undo.*;
006: import gnu.lists.*;
007:
008: /** A Content class that supports Emacs-style Markers.
009: * The standard GapContent is close, but unfortunately it only
010: * supports inserting *before* marks, which is not the Emacs default.
011: * This provides a superset of the Position functionality (except for undo).
012: */
013:
014: public class BufferContent extends gnu.kawa.swingviews.SwingContent {
015: public BufferContent() {
016: this (100);
017: }
018:
019: public BufferContent(int initialSize) {
020: super (initialSize);
021: }
022:
023: public static int indexOf(char[] buffer, int start, int limit,
024: char ch) {
025: for (int i = start; i < limit; i++) {
026: if (buffer[i] == ch)
027: return i;
028: }
029: return -1;
030: }
031:
032: /** Search for the last occurrence of a character
033: * in buffer[limit..start]. */
034: public static int lastIndexOf(char[] buffer, int start, int limit,
035: char ch) {
036: for (int i = start; i >= limit; i--) {
037: if (buffer[i] == ch)
038: return i;
039: }
040: return -1;
041: }
042:
043: /** Search in BUF for COUNT instances of the character TARGET between START and END.
044: * If COUNT is positive, search forwards; END must be >= START.
045: * If COUNT is negative, search backwards for the -COUNTth instance;
046: * END must be <= START.
047: * If COUNT is zero, do anything you please; run rogue, for all I care.
048: *
049: * If we find COUNT instances, SHORTAGE is zero, and return the
050: * position after the COUNTth match. Note that for reverse motion
051: * this is not the same as the usual convention for Emacs motion commands.
052:
053: * If we don't find COUNT instances before reaching END, set SHORTAGE
054: * to the number of TARGETs left unfound, and return (shortage<<32|END).
055: * @return (SHORTAGE<<32|POS)
056: */
057:
058: public final long scan(char target, int start, int end, int count,
059: boolean allowQuit) {
060: CharBuffer b = buffer;
061: int limit = end > b.gapStart ? end + b.gapEnd - b.gapStart
062: : end;
063: if (start > b.gapStart)
064: start += b.gapEnd - b.gapStart;
065: if (count > 0) {
066: while (start < limit && count > 0) {
067: int ceil;
068: if (start == b.gapStart)
069: start = b.gapEnd;
070: if (start < b.gapStart && limit > b.gapStart)
071: ceil = b.gapStart;
072: else {
073: ceil = limit;
074: }
075: if (allowQuit) {
076: if (ceil - start > 5000)
077: ceil = start + 5000;
078: Signal.checkQuit();
079: }
080: int i = indexOf(b.getArray(), start, ceil, target);
081: if (i >= 0) {
082: count--;
083: start = i + 1;
084: } else
085: start = ceil;
086: }
087: if (start > b.gapEnd)
088: start -= b.gapEnd - b.gapStart;
089: return ((long) count << 32) | start;
090: } else {
091: while (start > limit && count < 0) {
092: if (start == b.gapEnd)
093: start = b.gapStart;
094: int floor;
095: if (start <= b.gapStart || limit >= b.gapEnd)
096: floor = limit;
097: else
098: floor = b.gapEnd;
099: if (allowQuit) {
100: if (start - floor > 5000)
101: floor = start - 5000;
102: Signal.checkQuit();
103: }
104: int i = lastIndexOf(b.getArray(), start - 1, floor,
105: target);
106: if (i >= 0) {
107: count++;
108: start = i;
109: } else
110: start = floor;
111: }
112:
113: if (start >= b.gapEnd)
114: start -= b.gapEnd - b.gapStart;
115: if (count != 0)
116: return ((long) (-count) << 32) | start;
117: else {
118: // We found the character we were looking for; we have to return
119: // the position *after* it due to the strange way that the return
120: // value is defined.
121: return start + 1;
122: }
123: }
124: }
125: }
|