OSDN Git Service

Imported GNU Classpath 0.20
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / text / PlainDocument.java
1 /* PlainDocument.java --
2    Copyright (C) 2002, 2004  Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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)
9 any later version.
10
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.
15
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
19 02110-1301 USA.
20
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
24 combination.
25
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. */
37
38
39 package javax.swing.text;
40
41 import java.util.ArrayList;
42
43 public class PlainDocument extends AbstractDocument
44 {
45   private static final long serialVersionUID = 4758290289196893664L;
46     
47   public static final String lineLimitAttribute = "lineLimit";
48   public static final String tabSizeAttribute = "tabSize";
49
50   private BranchElement rootElement;
51   private int tabSize;
52   
53   public PlainDocument()
54   {
55     this(new GapContent());
56   }
57
58   public PlainDocument(AbstractDocument.Content content)
59   {
60     super(content);
61     tabSize = 8;
62     rootElement = (BranchElement) createDefaultRoot();
63   }
64
65   private void reindex()
66   {
67     Element[] lines;
68     try 
69       {
70         String str = content.getString(0, content.length());
71
72         ArrayList elts = new ArrayList();
73         int j = 0;
74         for (int i = str.indexOf('\n', 0); i != -1; i = str.indexOf('\n', i + 1))
75           {
76             elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, i + 1));
77             j = i + 1;
78           }
79         
80         if (j < content.length())
81           elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, content.length()));
82         
83         lines = new Element[elts.size()];
84         for (int i = 0; i < elts.size(); ++i)
85           lines[i] = (Element) elts.get(i);
86       }
87     catch (BadLocationException e)
88       {
89         lines = new Element[1];
90         lines[0] = createLeafElement(rootElement, SimpleAttributeSet.EMPTY, 0, 1);
91       }
92
93     ((BranchElement) rootElement).replace(0, rootElement.getElementCount(), lines);
94   }
95
96   protected AbstractDocument.AbstractElement createDefaultRoot()
97   {
98     BranchElement root =
99       (BranchElement) createBranchElement(null, SimpleAttributeSet.EMPTY);
100
101     Element[] array = new Element[1];
102     array[0] = createLeafElement(root, SimpleAttributeSet.EMPTY, 0, 1);
103     root.replace(0, 0, array);
104     
105     return root;
106   }
107
108   protected void insertUpdate(DefaultDocumentEvent event,
109                               AttributeSet attributes)
110   {
111     int offset = event.getOffset();
112     int end = offset + event.getLength();
113     int elementIndex = rootElement.getElementIndex(offset);
114     Element firstElement = rootElement.getElement(elementIndex);
115     
116     // If we're inserting immediately after a newline we have to fix the 
117     // Element structure.
118     if (offset > 0)
119       {
120         try
121         {
122           String s = getText(offset - 1, 1);
123           if (s.equals("\n"))
124             {
125               int newEl2EndOffset = end;
126               boolean replaceNext = false;
127               if (rootElement.getElementCount() > elementIndex + 1)
128                 {
129                   replaceNext = true;
130                   newEl2EndOffset = 
131                     rootElement.getElement(elementIndex + 1).getEndOffset();
132                 }
133               Element newEl1 = 
134                 createLeafElement(rootElement, firstElement.getAttributes(), 
135                                   firstElement.getStartOffset(), offset);
136               Element newEl2 = 
137                 createLeafElement (rootElement, firstElement.getAttributes(), 
138                                    offset, newEl2EndOffset);
139               if (replaceNext)
140                 rootElement.replace(elementIndex, 2, new Element[] { newEl1, newEl2 });
141               else
142                 rootElement.replace(elementIndex, 1, new Element[] { newEl1, newEl2 });
143               firstElement = newEl2;
144               elementIndex ++;
145             }
146         }
147         catch (BadLocationException ble)
148         {          
149           // This shouldn't happen.
150           AssertionError ae = new AssertionError();
151           ae.initCause(ble);
152           throw ae;
153         }        
154       }
155
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];
159     Element[] added;
160     try 
161       {
162         String str = content.getString(0, content.length());
163         ArrayList elts = new ArrayList();
164
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)
170           {            
171             // For each new line, create a new element
172             elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY,
173                                        j, i + 1));
174             j = i + 1;
175             if (j >= str.length())
176               break;
177             i = str.indexOf('\n', j);
178           }
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)
183           {
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;
190             
191             // Now create and add the ElementEdit
192             ElementEdit e = new ElementEdit(rootElement, elementIndex, removed,
193                                             added);
194             event.addEdit(e);
195             
196             // And call replace to actually make the changes
197             ((BranchElement) rootElement).replace(elementIndex, 1, added);
198           }
199       }
200     catch (BadLocationException e)
201       {
202         // This shouldn't happen so we throw an AssertionError
203         AssertionError ae = new AssertionError();
204         ae.initCause(e);
205         throw ae;
206       }
207     super.insertUpdate(event, attributes);
208   }
209
210   protected void removeUpdate(DefaultDocumentEvent event)
211   {
212     super.removeUpdate(event);
213
214     // added and removed are Element arrays used to add an ElementEdit
215     // to the DocumentEvent if there were entire lines added or removed
216     // from the Document
217     Element[] added = new Element[1];
218     Element[] removed;
219     int p0 = event.getOffset();
220
221     // check if we must collapse some elements
222     int i1 = rootElement.getElementIndex(p0);
223     int i2 = rootElement.getElementIndex(p0 + event.getLength());
224     if (i1 != i2)
225       {
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);
232         
233         int start = rootElement.getElement(i1).getStartOffset();
234         int end = rootElement.getElement(i2).getEndOffset();        
235         added[0] = createLeafElement(rootElement,
236                                           SimpleAttributeSet.EMPTY,
237                                           start, end);
238
239         // Now create and add the ElementEdit
240         ElementEdit e = new ElementEdit(rootElement, i1, removed, added);
241         event.addEdit(e);
242
243         // collapse elements if the removal spans more than 1 line
244         rootElement.replace(i1, i2 - i1 + 1, added);
245       }
246   }
247
248   public Element getDefaultRootElement()
249   {
250     return rootElement;
251   }
252
253   public Element getParagraphElement(int pos)
254   {
255     Element root = getDefaultRootElement();
256     return root.getElement(root.getElementIndex(pos));
257   }
258
259   /**
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.
264    *
265    * Inserting content causes a write lock to be acquired during this method
266    * call.
267    *
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
271    *
272    * @throws BadLocationException
273    */
274   public void insertString(int offs, String str, AttributeSet atts)
275     throws BadLocationException
276   {
277     String string = str;
278     if (str != null && Boolean.TRUE.equals(getProperty("filterNewlines")))
279       string = str.replaceAll("\n", " ");
280     super.insertString(offs, string, atts);
281   }
282 }