History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/text/StringContent.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/text/StringContent.java+498−0
@@ -0,0 +1,498 @@
1+/*
2+ * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+package javax.swing.text;
26+
27+import java.util.Vector;
28+import java.io.Serializable;
29+import javax.swing.undo.*;
30+import javax.swing.SwingUtilities;
31+
32+/**
33+ * An implementation of the AbstractDocument.Content interface that is
34+ * a brute force implementation that is useful for relatively small
35+ * documents and/or debugging. It manages the character content
36+ * as a simple character array. It is also quite inefficient.
37+ * <p>
38+ * It is generally recommended that the gap buffer or piece table
39+ * implementations be used instead. This buffer does not scale up
40+ * to large sizes.
41+ * <p>
42+ * <strong>Warning:</strong>
43+ * Serialized objects of this class will not be compatible with
44+ * future Swing releases. The current serialization support is
45+ * appropriate for short term storage or RMI between applications running
46+ * the same version of Swing. As of 1.4, support for long term storage
47+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
48+ * has been added to the <code>java.beans</code> package.
49+ * Please see {@link java.beans.XMLEncoder}.
50+ *
51+ * @author Timothy Prinzing
52+ */
53+public final class StringContent implements AbstractDocument.Content, Serializable {
54+
55+ /**
56+ * Creates a new StringContent object. Initial size defaults to 10.
57+ */
58+ public StringContent() {
59+ this(10);
60+ }
61+
62+ /**
63+ * Creates a new StringContent object, with the initial
64+ * size specified. If the length is < 1, a size of 1 is used.
65+ *
66+ * @param initialLength the initial size
67+ */
68+ public StringContent(int initialLength) {
69+ if (initialLength < 1) {
70+ initialLength = 1;
71+ }
72+ data = new char[initialLength];
73+ data[0] = '\n';
74+ count = 1;
75+ }
76+
77+ /**
78+ * Returns the length of the content.
79+ *
80+ * @return the length >= 1
81+ * @see AbstractDocument.Content#length
82+ */
83+ public int length() {
84+ return count;
85+ }
86+
87+ /**
88+ * Inserts a string into the content.
89+ *
90+ * @param where the starting position >= 0 && < length()
91+ * @param str the non-null string to insert
92+ * @return an UndoableEdit object for undoing
93+ * @exception BadLocationException if the specified position is invalid
94+ * @see AbstractDocument.Content#insertString
95+ */
96+ public UndoableEdit insertString(int where, String str) throws BadLocationException {
97+ if (where >= count || where < 0) {
98+ throw new BadLocationException("Invalid location", count);
99+ }
100+ char[] chars = str.toCharArray();
101+ replace(where, 0, chars, 0, chars.length);
102+ if (marks != null) {
103+ updateMarksForInsert(where, str.length());
104+ }
105+ return new InsertUndo(where, str.length());
106+ }
107+
108+ /**
109+ * Removes part of the content. where + nitems must be < length().
110+ *
111+ * @param where the starting position >= 0
112+ * @param nitems the number of characters to remove >= 0
113+ * @return an UndoableEdit object for undoing
114+ * @exception BadLocationException if the specified position is invalid
115+ * @see AbstractDocument.Content#remove
116+ */
117+ public UndoableEdit remove(int where, int nitems) throws BadLocationException {
118+ if (where + nitems >= count) {
119+ throw new BadLocationException("Invalid range", count);
120+ }
121+ String removedString = getString(where, nitems);
122+ UndoableEdit edit = new RemoveUndo(where, removedString);
123+ replace(where, nitems, empty, 0, 0);
124+ if (marks != null) {
125+ updateMarksForRemove(where, nitems);
126+ }
127+ return edit;
128+
129+ }
130+
131+ /**
132+ * Retrieves a portion of the content. where + len must be <= length().
133+ *
134+ * @param where the starting position >= 0
135+ * @param len the length to retrieve >= 0
136+ * @return a string representing the content; may be empty
137+ * @exception BadLocationException if the specified position is invalid
138+ * @see AbstractDocument.Content#getString
139+ */
140+ public String getString(int where, int len) throws BadLocationException {
141+ if (where + len > count) {
142+ throw new BadLocationException("Invalid range", count);
143+ }
144+ return new String(data, where, len);
145+ }
146+
147+ /**
148+ * Retrieves a portion of the content. where + len must be <= length()
149+ *
150+ * @param where the starting position >= 0
151+ * @param len the number of characters to retrieve >= 0
152+ * @param chars the Segment object to return the characters in
153+ * @exception BadLocationException if the specified position is invalid
154+ * @see AbstractDocument.Content#getChars
155+ */
156+ public void getChars(int where, int len, Segment chars) throws BadLocationException {
157+ if (where + len > count) {
158+ throw new BadLocationException("Invalid location", count);
159+ }
160+ chars.array = data;
161+ chars.offset = where;
162+ chars.count = len;
163+ }
164+
165+ /**
166+ * Creates a position within the content that will
167+ * track change as the content is mutated.
168+ *
169+ * @param offset the offset to create a position for >= 0
170+ * @return the position
171+ * @exception BadLocationException if the specified position is invalid
172+ */
173+ public Position createPosition(int offset) throws BadLocationException {
174+ // some small documents won't have any sticky positions
175+ // at all, so the buffer is created lazily.
176+ if (marks == null) {
177+ marks = new Vector<PosRec>();
178+ }
179+ return new StickyPosition(offset);
180+ }
181+
182+ // --- local methods ---------------------------------------
183+
184+ /**
185+ * Replaces some of the characters in the array
186+ * @param offset offset into the array to start the replace
187+ * @param length number of characters to remove
188+ * @param replArray replacement array
189+ * @param replOffset offset into the replacement array
190+ * @param replLength number of character to use from the
191+ * replacement array.
192+ */
193+ void replace(int offset, int length,
194+ char[] replArray, int replOffset, int replLength) {
195+ int delta = replLength - length;
196+ int src = offset + length;
197+ int nmove = count - src;
198+ int dest = src + delta;
199+ if ((count + delta) >= data.length) {
200+ // need to grow the array
201+ int newLength = Math.max(2*data.length, count + delta);
202+ char[] newData = new char[newLength];
203+ System.arraycopy(data, 0, newData, 0, offset);
204+ System.arraycopy(replArray, replOffset, newData, offset, replLength);
205+ System.arraycopy(data, src, newData, dest, nmove);
206+ data = newData;
207+ } else {
208+ // patch the existing array
209+ System.arraycopy(data, src, data, dest, nmove);
210+ System.arraycopy(replArray, replOffset, data, offset, replLength);
211+ }
212+ count = count + delta;
213+ }
214+
215+ void resize(int ncount) {
216+ char[] ndata = new char[ncount];
217+ System.arraycopy(data, 0, ndata, 0, Math.min(ncount, count));
218+ data = ndata;
219+ }
220+
221+ synchronized void updateMarksForInsert(int offset, int length) {
222+ if (offset == 0) {
223+ // zero is a special case where we update only
224+ // marks after it.
225+ offset = 1;
226+ }
227+ int n = marks.size();
228+ for (int i = 0; i < n; i++) {
229+ PosRec mark = marks.elementAt(i);
230+ if (mark.unused) {
231+ // this record is no longer used, get rid of it
232+ marks.removeElementAt(i);
233+ i -= 1;
234+ n -= 1;
235+ } else if (mark.offset >= offset) {
236+ mark.offset += length;
237+ }
238+ }
239+ }
240+
241+ synchronized void updateMarksForRemove(int offset, int length) {
242+ int n = marks.size();
243+ for (int i = 0; i < n; i++) {
244+ PosRec mark = marks.elementAt(i);
245+ if (mark.unused) {
246+ // this record is no longer used, get rid of it
247+ marks.removeElementAt(i);
248+ i -= 1;
249+ n -= 1;
250+ } else if (mark.offset >= (offset + length)) {
251+ mark.offset -= length;
252+ } else if (mark.offset >= offset) {
253+ mark.offset = offset;
254+ }
255+ }
256+ }
257+
258+ /**
259+ * Returns a Vector containing instances of UndoPosRef for the
260+ * Positions in the range
261+ * <code>offset</code> to <code>offset</code> + <code>length</code>.
262+ * If <code>v</code> is not null the matching Positions are placed in
263+ * there. The vector with the resulting Positions are returned.
264+ * <p>
265+ * This is meant for internal usage, and is generally not of interest
266+ * to subclasses.
267+ *
268+ * @param v the Vector to use, with a new one created on null
269+ * @param offset the starting offset >= 0
270+ * @param length the length >= 0
271+ * @return the set of instances
272+ */
273+ protected Vector getPositionsInRange(Vector v, int offset,
274+ int length) {
275+ int n = marks.size();
276+ int end = offset + length;
277+ Vector placeIn = (v == null) ? new Vector() : v;
278+ for (int i = 0; i < n; i++) {
279+ PosRec mark = marks.elementAt(i);
280+ if (mark.unused) {
281+ // this record is no longer used, get rid of it
282+ marks.removeElementAt(i);
283+ i -= 1;
284+ n -= 1;
285+ } else if(mark.offset >= offset && mark.offset <= end)
286+ placeIn.addElement(new UndoPosRef(mark));
287+ }
288+ return placeIn;
289+ }
290+
291+ /**
292+ * Resets the location for all the UndoPosRef instances
293+ * in <code>positions</code>.
294+ * <p>
295+ * This is meant for internal usage, and is generally not of interest
296+ * to subclasses.
297+ *
298+ * @param positions the positions of the instances
299+ */
300+ protected void updateUndoPositions(Vector positions) {
301+ for(int counter = positions.size() - 1; counter >= 0; counter--) {
302+ UndoPosRef ref = (UndoPosRef)positions.elementAt(counter);
303+ // Check if the Position is still valid.
304+ if(ref.rec.unused) {
305+ positions.removeElementAt(counter);
306+ }
307+ else
308+ ref.resetLocation();
309+ }
310+ }
311+
312+ private static final char[] empty = new char[0];
313+ private char[] data;
314+ private int count;
315+ transient Vector<PosRec> marks;
316+
317+ /**
318+ * holds the data for a mark... separately from
319+ * the real mark so that the real mark can be
320+ * collected if there are no more references to
321+ * it.... the update table holds only a reference
322+ * to this grungy thing.
323+ */
324+ final class PosRec {
325+
326+ PosRec(int offset) {
327+ this.offset = offset;
328+ }
329+
330+ int offset;
331+ boolean unused;
332+ }
333+
334+ /**
335+ * This really wants to be a weak reference but
336+ * in 1.1 we don't have a 100% pure solution for
337+ * this... so this class trys to hack a solution
338+ * to causing the marks to be collected.
339+ */
340+ final class StickyPosition implements Position {
341+
342+ StickyPosition(int offset) {
343+ rec = new PosRec(offset);
344+ marks.addElement(rec);
345+ }
346+
347+ public int getOffset() {
348+ return rec.offset;
349+ }
350+
351+ protected void finalize() throws Throwable {
352+ // schedule the record to be removed later
353+ // on another thread.
354+ rec.unused = true;
355+ }
356+
357+ public String toString() {
358+ return Integer.toString(getOffset());
359+ }
360+
361+ PosRec rec;
362+ }
363+
364+ /**
365+ * Used to hold a reference to a Position that is being reset as the
366+ * result of removing from the content.
367+ */
368+ final class UndoPosRef {
369+ UndoPosRef(PosRec rec) {
370+ this.rec = rec;
371+ this.undoLocation = rec.offset;
372+ }
373+
374+ /**
375+ * Resets the location of the Position to the offset when the
376+ * receiver was instantiated.
377+ */
378+ protected void resetLocation() {
379+ rec.offset = undoLocation;
380+ }
381+
382+ /** Location to reset to when resetLocatino is invoked. */
383+ protected int undoLocation;
384+ /** Position to reset offset. */
385+ protected PosRec rec;
386+ }
387+
388+ /**
389+ * UnoableEdit created for inserts.
390+ */
391+ class InsertUndo extends AbstractUndoableEdit {
392+ protected InsertUndo(int offset, int length) {
393+ super();
394+ this.offset = offset;
395+ this.length = length;
396+ }
397+
398+ public void undo() throws CannotUndoException {
399+ super.undo();
400+ try {
401+ synchronized(StringContent.this) {
402+ // Get the Positions in the range being removed.
403+ if(marks != null)
404+ posRefs = getPositionsInRange(null, offset, length);
405+ string = getString(offset, length);
406+ remove(offset, length);
407+ }
408+ } catch (BadLocationException bl) {
409+ throw new CannotUndoException();
410+ }
411+ }
412+
413+ public void redo() throws CannotRedoException {
414+ super.redo();
415+ try {
416+ synchronized(StringContent.this) {
417+ insertString(offset, string);
418+ string = null;
419+ // Update the Positions that were in the range removed.
420+ if(posRefs != null) {
421+ updateUndoPositions(posRefs);
422+ posRefs = null;
423+ }
424+ }
425+ } catch (BadLocationException bl) {
426+ throw new CannotRedoException();
427+ }
428+ }
429+
430+ // Where the string goes.
431+ protected int offset;
432+ // Length of the string.
433+ protected int length;
434+ // The string that was inserted. To cut down on space needed this
435+ // will only be valid after an undo.
436+ protected String string;
437+ // An array of instances of UndoPosRef for the Positions in the
438+ // range that was removed, valid after undo.
439+ protected Vector posRefs;
440+ }
441+
442+
443+ /**
444+ * UndoableEdit created for removes.
445+ */
446+ class RemoveUndo extends AbstractUndoableEdit {
447+ protected RemoveUndo(int offset, String string) {
448+ super();
449+ this.offset = offset;
450+ this.string = string;
451+ this.length = string.length();
452+ if(marks != null)
453+ posRefs = getPositionsInRange(null, offset, length);
454+ }
455+
456+ public void undo() throws CannotUndoException {
457+ super.undo();
458+ try {
459+ synchronized(StringContent.this) {
460+ insertString(offset, string);
461+ // Update the Positions that were in the range removed.
462+ if(posRefs != null) {
463+ updateUndoPositions(posRefs);
464+ posRefs = null;
465+ }
466+ string = null;
467+ }
468+ } catch (BadLocationException bl) {
469+ throw new CannotUndoException();
470+ }
471+ }
472+
473+ public void redo() throws CannotRedoException {
474+ super.redo();
475+ try {
476+ synchronized(StringContent.this) {
477+ string = getString(offset, length);
478+ // Get the Positions in the range being removed.
479+ if(marks != null)
480+ posRefs = getPositionsInRange(null, offset, length);
481+ remove(offset, length);
482+ }
483+ } catch (BadLocationException bl) {
484+ throw new CannotRedoException();
485+ }
486+ }
487+
488+ // Where the string goes.
489+ protected int offset;
490+ // Length of the string.
491+ protected int length;
492+ // The string that was inserted. This will be null after an undo.
493+ protected String string;
494+ // An array of instances of UndoPosRef for the Positions in the
495+ // range that was removed, valid before undo.
496+ protected Vector posRefs;
497+ }
498+}