001: package gnu.jemacs.buffer;
002:
003: import gnu.lists.*;
004: import gnu.mapping.*;
005:
006: public final class Marker extends SeqPosition {
007: Buffer buffer;
008:
009: /** Is this the special point marker? */
010: public final boolean isPoint() {
011: return buffer != null && sequence == null;
012: }
013:
014: public Marker() {
015: }
016:
017: public Marker(Marker marker) {
018: buffer = marker.buffer;
019: if (buffer != null) {
020: if (marker.isPoint())
021: set(buffer, buffer.getDot(), true);
022: else
023: set(marker);
024: }
025: }
026:
027: public Marker(Buffer buffer, int offset, boolean isAfter) {
028: super (buffer, offset, isAfter);
029: this .buffer = buffer;
030: }
031:
032: public int getOffset() {
033: if (buffer == null)
034: return -1;
035: else if (isPoint())
036: return buffer.getDot();
037: return nextIndex();
038: }
039:
040: public int getPoint() {
041: return 1 + getOffset();
042: }
043:
044: public Buffer getBuffer() {
045: return buffer;
046: }
047:
048: public void setDot(int newPosition) {
049: set(buffer, newPosition);
050: }
051:
052: public void set(Buffer newBuffer, int newPosition) {
053: if (isPoint()) {
054: if (newBuffer != buffer) {
055: String msg;
056: if (newBuffer == null)
057: msg = "Can't make point-marker point nowhere: ";
058: else
059: msg = "Can't change buffer of point-marker: ";
060: throw new Error(msg + this );
061: }
062: buffer.setDot(newPosition);
063: } else {
064: if (sequence != null)
065: release();
066: sequence = null;
067: if (newBuffer == null) {
068: buffer = null;
069: return;
070: }
071:
072: if (newPosition < 0)
073: newPosition = 0;
074: else {
075: int newLength = newBuffer.length();
076: if (newPosition > newLength)
077: newPosition = newLength;
078: }
079: set(newBuffer, newPosition, false);
080: }
081: }
082:
083: public void removeChar(int count) {
084: if (isPoint())
085: buffer.removeChar(count);
086: else
087: buffer.removePos(ipos, count);
088: }
089:
090: public void insert(char[] data, int off, int len, Object style) {
091: int point = getOffset();
092: buffer.insert(data, off, len, style, ipos);
093: point += len;
094: setDot(point);
095: }
096:
097: public void insert(String string, Object style) {
098: int point = getOffset();
099: if (isPoint())
100: buffer.insert(string, style);
101: else
102: buffer.insert(string, style, ipos);
103: point += string.length();
104: setDot(point);
105: }
106:
107: /** Insert count copies of ch at the current position. */
108: public void insert(char ch, int count, Object style) {
109: if (count < 0)
110: return;
111: int n = count > 500 ? 500 : count;
112: StringBuffer sbuf = new StringBuffer(n);
113: for (int i = n; --i >= 0;)
114: sbuf.append(ch);
115: String str = sbuf.toString();
116: for (;;) {
117: insert(str, style);
118: count -= n;
119: if (count == 0)
120: break;
121: if (count < 500) {
122: n = count;
123: sbuf.setLength(n);
124: str = sbuf.toString();
125: }
126: }
127: }
128:
129: public void forwardChar(int i) {
130: int point = getOffset();
131: int max = buffer.maxDot();
132: if (point + i > max) {
133: point = max;
134: Signal.signal("End of buffer");
135: }
136: point += i;
137: setDot(point);
138: }
139:
140: public void backwardChar(int i) {
141: int point = getOffset();
142: if (point < i) {
143: point = 0;
144: Signal.signal("Beginning of buffer");
145: }
146: point -= i;
147: setDot(point);
148: }
149:
150: public int currentColumn() {
151: return buffer.currentColumn(getOffset());
152: }
153:
154: // force is currently ignored FIXME
155: public int moveToColumn(int column, boolean force) {
156: int lineStart = buffer.lineStartOffset(getOffset());
157: InPort port = buffer.openReader(lineStart, buffer.maxDot()
158: - lineStart);
159: int resultColumn = 0;
160: try {
161: int offset = lineStart;
162: for (;;) {
163: int ch = port.read();
164: if (ch < 0 || ch == '\n') {
165: if (force) {
166: // FIXME
167: }
168: break;
169: }
170: int width = buffer.charWidth((char) ch, resultColumn);
171: offset++;
172: resultColumn += width;
173: if (resultColumn >= column) {
174: if (resultColumn > column && force) {
175: // FIXME
176: }
177: break;
178: }
179: }
180: setDot(offset);
181: return resultColumn;
182: } catch (java.io.IOException ex) {
183: throw new WrappedException(ex);
184: }
185: }
186:
187: public int forwardLine(int lines) {
188: long value = buffer.forwardLine(lines, getOffset());
189: setDot((int) value);
190: return (int) (value >> 32);
191: }
192:
193: /** Move to start of frame line COUNTs down.
194: * Assume window width is WIDTH.
195: * If LINES is negative, this is moving up. */
196:
197: /*
198: public int verticalMotion(int count, int width)
199: {
200: if (count == 0)
201: {
202: moveToColumn ((currentColumn() / width) * width, false);
203: return 0;
204: }
205: if (count > 0)
206: {
207: int todo = count + currentColumn() / width;
208: endOfLine();
209: // The loop iterates over buffer lines;
210: // H is the number of screen lines in the current line, i.e.
211: // the ceiling of dividing the buffer line width by width.
212: for (;;)
213: {
214: int h = (currentColumn() + width - 1) / width;
215: if (h <= 0) h = 1;
216: if (h > todo)
217: break;
218: if (eobp())
219: break;
220: todo -= h;
221: forwardChar(1); // move past '\n'.
222: endOfLine(); // and on to the end of the next line.
223: }
224: if (todo >= h && todo > 0)
225: return count - todo + h - 1; // Hit end of buffer.
226: }
227: else // count > 0 -- Similar algorithm, but for upward motion.
228: {
229: int todo = - count;
230: for (;;)
231: {
232: int h = (currentColumn() + width - 1) / width;
233: if (h <= 0) h = 1;
234: if (h > todo)
235: break;
236: beginningOfLine();
237: if (bobp())
238: break;
239: todo -= h;
240: backwardChar(1); // Move to end of previous line
241: }
242: if (todo >= h && todo > 0)
243: return count + todo - 1 + h; // Hit beginning of buffer.
244: todo = h - todo - 1;
245: }
246: moveToColumn(todo * width, false);
247: return count;
248: }
249: */
250:
251: public boolean isBeginningOfLine() {
252: int offset = getOffset();
253: return offset == 0 || buffer.charAt(offset - 1) == '\n';
254: }
255:
256: public boolean isEndOfLine() {
257: int offset = getOffset();
258: return offset == buffer.length()
259: || buffer.charAt(offset) == '\n';
260: }
261:
262: public int hashCode() {
263: if (buffer == null)
264: return 0;
265: return buffer.hashCode() ^ getOffset();
266: }
267:
268: public boolean equals(Object other) {
269: if (!(other instanceof Marker))
270: return false;
271: Marker m2 = (Marker) other;
272: return buffer == m2.buffer && getOffset() == m2.getOffset();
273: }
274:
275: public String toString() {
276: if (buffer == null)
277: return "#<marker in no buffer>";
278: StringBuffer sbuf = new StringBuffer(80);
279: sbuf.append("#<marker at ");
280: sbuf.append(getPoint());
281: sbuf.append(" in ");
282: sbuf.append(buffer.getName());
283: sbuf.append('>');
284: return sbuf.toString();
285: }
286: }
|