1 /* PlainDocument.java --
2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing.text;
41 import java.util.ArrayList;
43 public class PlainDocument extends AbstractDocument
45 private static final long serialVersionUID = 4758290289196893664L;
47 public static final String lineLimitAttribute = "lineLimit";
48 public static final String tabSizeAttribute = "tabSize";
50 private BranchElement rootElement;
53 public PlainDocument()
55 this(new GapContent());
58 public PlainDocument(AbstractDocument.Content content)
62 rootElement = (BranchElement) createDefaultRoot();
65 private void reindex()
70 String str = content.getString(0, content.length());
72 ArrayList elts = new ArrayList();
74 for (int i = str.indexOf('\n', 0); i != -1; i = str.indexOf('\n', i + 1))
76 elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, i + 1));
80 if (j < content.length())
81 elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, content.length()));
83 lines = new Element[elts.size()];
84 for (int i = 0; i < elts.size(); ++i)
85 lines[i] = (Element) elts.get(i);
87 catch (BadLocationException e)
89 lines = new Element[1];
90 lines[0] = createLeafElement(rootElement, SimpleAttributeSet.EMPTY, 0, 1);
93 ((BranchElement) rootElement).replace(0, rootElement.getElementCount(), lines);
96 protected AbstractDocument.AbstractElement createDefaultRoot()
99 (BranchElement) createBranchElement(null, SimpleAttributeSet.EMPTY);
101 Element[] array = new Element[1];
102 array[0] = createLeafElement(root, SimpleAttributeSet.EMPTY, 0, 1);
103 root.replace(0, 0, array);
108 protected void insertUpdate(DefaultDocumentEvent event,
109 AttributeSet attributes)
111 int offset = event.getOffset();
112 int end = offset + event.getLength();
113 int elementIndex = rootElement.getElementIndex(offset);
114 Element firstElement = rootElement.getElement(elementIndex);
116 // If we're inserting immediately after a newline we have to fix the
117 // Element structure.
122 String s = getText(offset - 1, 1);
125 int newEl2EndOffset = end;
126 boolean replaceNext = false;
127 if (rootElement.getElementCount() > elementIndex + 1)
131 rootElement.getElement(elementIndex + 1).getEndOffset();
134 createLeafElement(rootElement, firstElement.getAttributes(),
135 firstElement.getStartOffset(), offset);
137 createLeafElement (rootElement, firstElement.getAttributes(),
138 offset, newEl2EndOffset);
140 rootElement.replace(elementIndex, 2, new Element[] { newEl1, newEl2 });
142 rootElement.replace(elementIndex, 1, new Element[] { newEl1, newEl2 });
143 firstElement = newEl2;
147 catch (BadLocationException ble)
149 // This shouldn't happen.
150 AssertionError ae = new AssertionError();
156 // added and removed are Element arrays used to add an ElementEdit
157 // to the DocumentEvent if there were entire lines added or removed.
158 Element[] removed = new Element[1];
162 String str = content.getString(0, content.length());
163 ArrayList elts = new ArrayList();
165 // Determine how many NEW lines were added by finding the newline
166 // characters within the newly inserted text
167 int j = firstElement.getStartOffset();
168 int i = str.indexOf('\n', offset);
169 while (i != -1 && i <= end)
171 // For each new line, create a new element
172 elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY,
175 if (j >= str.length())
177 i = str.indexOf('\n', j);
179 // If there were new lines added we have to add an ElementEdit to
180 // the DocumentEvent and we have to call rootElement.replace to
181 // insert the new lines
182 if (elts.size() != 0)
184 // Set up the ElementEdit by filling the added and removed
185 // arrays with the proper Elements
186 added = new Element[elts.size()];
187 for (int k = 0; k < elts.size(); ++k)
188 added[k] = (Element) elts.get(k);
189 removed[0] = firstElement;
191 // Now create and add the ElementEdit
192 ElementEdit e = new ElementEdit(rootElement, elementIndex, removed,
196 // And call replace to actually make the changes
197 ((BranchElement) rootElement).replace(elementIndex, 1, added);
200 catch (BadLocationException e)
202 // This shouldn't happen so we throw an AssertionError
203 AssertionError ae = new AssertionError();
207 super.insertUpdate(event, attributes);
210 protected void removeUpdate(DefaultDocumentEvent event)
212 super.removeUpdate(event);
214 // added and removed are Element arrays used to add an ElementEdit
215 // to the DocumentEvent if there were entire lines added or removed
217 Element[] added = new Element[1];
219 int p0 = event.getOffset();
221 // check if we must collapse some elements
222 int i1 = rootElement.getElementIndex(p0);
223 int i2 = rootElement.getElementIndex(p0 + event.getLength());
226 // If there were lines removed then we have to add an ElementEdit
227 // to the DocumentEvent so we set it up now by filling the Element
228 // arrays "removed" and "added" appropriately
229 removed = new Element [i2 - i1 + 1];
230 for (int i = i1; i <= i2; i++)
231 removed[i-i1] = rootElement.getElement(i);
233 int start = rootElement.getElement(i1).getStartOffset();
234 int end = rootElement.getElement(i2).getEndOffset();
235 added[0] = createLeafElement(rootElement,
236 SimpleAttributeSet.EMPTY,
239 // Now create and add the ElementEdit
240 ElementEdit e = new ElementEdit(rootElement, i1, removed, added);
243 // collapse elements if the removal spans more than 1 line
244 rootElement.replace(i1, i2 - i1 + 1, added);
248 public Element getDefaultRootElement()
253 public Element getParagraphElement(int pos)
255 Element root = getDefaultRootElement();
256 return root.getElement(root.getElementIndex(pos));
260 * Inserts a string into the document. If the document property
261 * '<code>filterNewLines</code>' is set to <code>Boolean.TRUE</code>, then
262 * all newlines in the inserted string are replaced by space characters,
263 * otherwise the superclasses behaviour is executed.
265 * Inserting content causes a write lock to be acquired during this method
268 * @param offs the offset at which to insert the string
269 * @param str the string to be inserted
270 * @param atts the text attributes of the string to be inserted
272 * @throws BadLocationException
274 public void insertString(int offs, String str, AttributeSet atts)
275 throws BadLocationException
278 if (str != null && Boolean.TRUE.equals(getProperty("filterNewlines")))
279 string = str.replaceAll("\n", " ");
280 super.insertString(offs, string, atts);