001: //This is free software; for terms and warranty disclaimer see ./COPYING.
002:
003: package gnu.jemacs.swt;
004:
005: import gnu.lists.Consumer;
006:
007: import java.io.IOException;
008: import java.io.Reader;
009: import java.io.Writer;
010: import java.util.HashSet;
011: import java.util.Iterator;
012: import java.util.Set;
013:
014: import gnu.lists.CharSeq;
015:
016: import org.eclipse.swt.custom.StyledTextContent;
017: import org.eclipse.swt.custom.TextChangeListener;
018: import org.eclipse.swt.custom.TextChangedEvent;
019: import org.eclipse.swt.custom.TextChangingEvent;
020:
021: /**
022: * @author Christian Surlykke
023: * 12-07-2004
024: */
025: public class BufferContent extends SwtCharBuffer implements
026: StyledTextContent, CharSeq {
027: public BufferContent() {
028: this (1000);
029: }
030:
031: /**
032: * @param initialSize
033: */
034: public BufferContent(int initialSize) {
035: super (initialSize);
036: }
037:
038: private Set textChangeListeners = new HashSet();
039:
040: /**
041: * @see org.eclipse.swt.custom.StyledTextContent#addTextChangeListener(org.eclipse.swt.custom.TextChangeListener)
042: */
043: public void addTextChangeListener(
044: TextChangeListener textChangeListener) {
045: if (textChangeListener != null) {
046: textChangeListeners.add(textChangeListener);
047: }
048:
049: }
050:
051: /**
052: * @see org.eclipse.swt.custom.StyledTextContent#removeTextChangeListener(org.eclipse.swt.custom.TextChangeListener)
053: */
054: public void removeTextChangeListener(
055: TextChangeListener textChangeListener) {
056: textChangeListeners.remove(textChangeListener);
057: }
058:
059: /**
060: * @see org.eclipse.swt.custom.StyledTextContent#getCharCount()
061: */
062: public int getCharCount() {
063: return size();
064: }
065:
066: /**
067: * @see org.eclipse.swt.custom.StyledTextContent#getLine(int)
068: */
069: public String getLine(int lineIndex) {
070: int startPos = offset2pos(lineOffsets.index2offset(lineIndex));
071: int endPos;
072: if (lineIndex + 1 == lineOffsets.size()) {
073: endPos = size();
074: } else {
075: endPos = offset2pos(lineOffsets.index2offset(lineIndex + 1));
076: // Strip linedelimiters
077: while (endPos > startPos
078: && lineOffsets.isLineDelimiter(charAt(endPos - 1))) {
079: endPos--;
080: }
081: }
082:
083: char[] tmp = new char[endPos - startPos];
084: getChars(startPos, endPos, tmp, 0);
085: return new String(tmp);
086: }
087:
088: /**
089: * @see org.eclipse.swt.custom.StyledTextContent#getLineAtOffset(int)
090: */
091: public int getLineAtOffset(int pos) {
092: return (lineOffsets.offset2index(pos2offset(pos)));
093: }
094:
095: /**
096: * @see org.eclipse.swt.custom.StyledTextContent#getLineCount()
097: */
098: public int getLineCount() {
099: return lineOffsets.size();
100: }
101:
102: /**
103: * @see org.eclipse.swt.custom.StyledTextContent#getLineDelimiter()
104: */
105: public String getLineDelimiter() {
106: return "\n";
107: }
108:
109: /**
110: * @see org.eclipse.swt.custom.StyledTextContent#getOffsetAtLine(int)
111: */
112: public int getOffsetAtLine(int lineIndex) {
113: int result = offset2pos(lineOffsets.index2offset(lineIndex));
114: return result;
115: }
116:
117: /**
118: * @see org.eclipse.swt.custom.StyledTextContent#getTextRange(int, int)
119: */
120: public String getTextRange(int start, int length) {
121: char[] tmp = new char[length];
122: getChars(start, start + length, tmp, 0);
123: return new String(tmp);
124: }
125:
126: /**
127: * @see org.eclipse.swt.custom.StyledTextContent#replaceTextRange(int, int, java.lang.String)
128: */
129: public void replaceTextRange(int start, int length, String newText) {
130: newText = newText == null ? "" : newText;
131: notifyListeners(makeTextChangingEvent(start, length, newText));
132: delete(start, length);
133: insert(start, newText);
134: notifyListeners(new TextChangedEvent(this ));
135: }
136:
137: private void show(TextChangingEvent changingEvent) {
138: System.out.println("start: " + changingEvent.start + "\n"
139: + "newCharCount: " + changingEvent.newCharCount + "\n"
140: + "newLineCount: " + changingEvent.newLineCount + "\n"
141: + "replaceCharCount: " + changingEvent.replaceCharCount
142: + "\n" + "replaceLineCount: "
143: + changingEvent.replaceLineCount + "\n" + "text: "
144: + printable(changingEvent.newText) + "\n");
145: }
146:
147: /**
148: * @param start
149: * @param length
150: * @param newText
151: * @return
152: */
153: private TextChangingEvent makeTextChangingEvent(int start,
154: int length, String newText) {
155: TextChangingEvent result = new TextChangingEvent(this );
156: result.start = start;
157: result.newCharCount = newText.length();
158: result.newLineCount = lineOffsets.countLines(newText);
159: result.newText = newText;
160: result.replaceCharCount = length;
161: result.replaceLineCount = lineOffsets.linesInRange(
162: pos2offset(start), pos2offset(start + length));
163:
164: return result;
165: }
166:
167: /**
168: * @see org.eclipse.swt.custom.StyledTextContent#setText(java.lang.String)
169: */
170: public void setText(String newText) {
171: delete(0, size());
172: insert(0, newText);
173: TextChangedEvent evt = new TextChangedEvent(this );
174: for (Iterator iter = textChangeListeners.iterator(); iter
175: .hasNext();) {
176: ((TextChangeListener) iter.next()).textSet(evt);
177: }
178: }
179:
180: /**
181: * @param changedEvent
182: */
183: private void notifyListeners(TextChangedEvent changedEvent) {
184: for (Iterator iter = textChangeListeners.iterator(); iter
185: .hasNext();) {
186: TextChangeListener element = (TextChangeListener) iter
187: .next();
188: element.textChanged(changedEvent);
189: }
190:
191: }
192:
193: /**
194: * @param changingEvent
195: */
196: private void notifyListeners(TextChangingEvent changingEvent) {
197: for (Iterator iter = textChangeListeners.iterator(); iter
198: .hasNext();) {
199: TextChangeListener element = (TextChangeListener) iter
200: .next();
201: element.textChanging(changingEvent);
202: }
203:
204: }
205:
206: /**
207: * For testing purposes
208: * @param args
209: */
210: public static void main(String[] args) {
211: }
212:
213: public int lineStartPos(int pos) {
214: int offset = pos2offset(pos);
215: int lineStartOffset = lineOffsets.index2offset(lineOffsets
216: .offset2index(offset));
217: return offset2pos(lineStartOffset);
218: }
219:
220: /**
221: * @param start
222: * @param count
223: * @param out
224: */
225: public void consume(int start, int count, Consumer out) {
226: // TODO Auto-generated method stub
227:
228: }
229:
230: /**
231: * @param in
232: * @throws IOException
233: */
234: public void insertFile(Reader in, int pos) throws IOException {
235: char[] buf = new char[65536];
236: for (;;) {
237: int charsRead = in.read(buf);
238: if (charsRead < 0) {
239: break;
240: }
241: replaceTextRange(pos, 0, new String(buf, 0, charsRead));
242: }
243: }
244:
245: public void setCharAt(int index, char value) {
246: char[] arr = { value };
247: replaceTextRange(index, index + 1, new String(arr));
248: }
249:
250: public void fill(char value) {
251: fill(0, size(), value);
252: }
253:
254: public void fill(int fromIndex, int toIndex, char value) {
255: for (int i = fromIndex; i < toIndex; i++)
256: setCharAt(i, value);
257: }
258:
259: /* #ifdef use:java.lang.CharSequence */
260: public CharSequence subSequence(int start, int end) {
261: throw new UnsupportedOperationException(
262: "subSequence not implemented");
263: }
264:
265: /* #endif */
266:
267: /* #ifdef JAVA5 */
268: // public void writeTo(int start, int count, Appendable dest)
269: // throws java.io.IOException
270: // {
271: // dest.append(this, start, start+count);
272: // }
273: // public void writeTo(Appendable dest)
274: // throws java.io.IOException
275: // {
276: // dest.append(this, 0, size());
277: // }
278: /* #else */
279: public void writeTo(int start, int count, java.io.Writer dest)
280: throws java.io.IOException {
281: while (--count >= 0)
282: dest.write(charAt(start++));
283: }
284:
285: public void writeTo(java.io.Writer dest) throws java.io.IOException {
286: writeTo(0, size(), dest);
287: }
288:
289: /* #endif */
290:
291: /**
292: * @param out
293: * @throws IOException
294: */
295: public void save(Writer out) throws IOException {
296: out.write(chars.data, 0, gapStart);
297: out.write(chars.data, gapEnd, chars.data.length - gapEnd);
298: }
299: }
|