OSDN Git Service

2004-05-30 Michael Koch <konqueror@gmx.de>
[pf3gnuchains/gcc-fork.git] / libjava / java / text / AttributedString.java
1 /* AttributedString.java -- Models text with attributes
2    Copyright (C) 1998, 1999, 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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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 java.text;
40
41 import java.util.Arrays;
42 import java.util.HashMap;
43 import java.util.Hashtable;
44 import java.util.Iterator;
45 import java.util.Map;
46 import java.util.Set;
47
48 /**
49   * This class models a <code>String</code> with attributes over various
50   * subranges of the string.  It allows applications to access this 
51   * information via the <code>AttributedCharcterIterator</code> interface.
52   *
53   * @version 0.0
54   *
55   * @author Aaron M. Renn (arenn@urbanophile.com)
56   */
57 public class AttributedString
58 {
59
60 /*************************************************************************/
61
62 /*
63  * Inner Classes
64  */
65
66 /**
67   * This class contains the attributes and ranges of text over which
68   * that attributes apply.
69   */
70 final class AttributeRange
71 {
72
73 /*
74  * Instance Variables
75  */
76
77 /**
78   * A Map of the attributes
79   */
80 Map attribs;
81
82 /**
83   * The beginning index of the attributes
84   */
85 int begin_index;
86
87 /**
88   * The ending index of the attributes
89   */
90 int end_index;
91
92 /*************************************************************************/
93
94 /*
95  * Constructors
96  */
97
98 AttributeRange(Map attribs, int begin_index, int end_index)
99 {
100   this.attribs = attribs;
101   this.begin_index = begin_index;
102   this.end_index = end_index;
103 }
104
105 } // Inner class AttributeRange
106
107 /*************************************************************************/
108
109 /*
110  * Instance Variables
111  */
112
113 /**
114   * This object holds the string we are representing.
115   */
116 private StringCharacterIterator sci;
117
118 /**
119   * This is the attribute information 
120   */
121 private AttributeRange[] attribs;
122
123 /*************************************************************************/
124
125 /*
126  * Constructors
127  */
128
129 /**
130   * This method initializes a new instance of <code>AttributedString</code>
131   * that represents the specified <code>String</code> with no attributes.
132   *
133   * @param str The <code>String</code> to be attributed.
134   */
135 public
136 AttributedString(String str)
137 {
138   sci = new StringCharacterIterator(str);
139   attribs = new AttributeRange[0];
140 }
141
142 /*************************************************************************/
143
144 /**
145   * This method initializes a new instance of <code>AttributedString</code>
146   * that represents that specified <code>String</code> with the specified
147   * attributes over the entire length of the <code>String</code>.
148   *
149   * @param str The <code>String</code> to be attributed.
150   * @param attributes The attribute list.
151   */
152 public
153 AttributedString(String str, Map attributes)
154 {
155   this(str);
156
157   attribs = new AttributeRange[1];
158   attribs[0] = new AttributeRange(attributes, 0, str.length());
159 }
160
161 /*************************************************************************/
162
163 /**
164   * This method initializes a new instance of <code>AttributedString</code>
165   * that will use the text and attribute information from the specified
166   * <code>AttributedCharacterIterator</code>.
167   *
168   * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information.
169   */
170 public
171 AttributedString(AttributedCharacterIterator aci)
172 {
173   this(aci, aci.getBeginIndex(), aci.getEndIndex(), null);
174 }
175
176 /*************************************************************************/
177
178 /**
179   * This method initializes a new instance of <code>AttributedString</code>
180   * that will use the text and attribute information from the specified
181   * subrange of the specified <code>AttributedCharacterIterator</code>.
182   *
183   * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information.
184   * @param begin_index The beginning index of the text subrange.
185   * @param end_index The ending index of the text subrange.
186   */
187 public
188 AttributedString(AttributedCharacterIterator aci, int begin_index,
189                  int end_index)
190 {
191   this(aci, begin_index, end_index, null);
192 }
193
194 /*************************************************************************/
195
196 /**
197   * This method initializes a new instance of <code>AttributedString</code>
198   * that will use the text and attribute information from the specified
199   * subrange of the specified <code>AttributedCharacterIterator</code>.
200   * Only attributes from the source iterator that are present in the
201   * specified array of attributes will be included in the attribute list
202   * for this object.
203   *
204   * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information.
205   * @param begin_index The beginning index of the text subrange.
206   * @param end_index The ending index of the text subrange.
207   * @param attributes A list of attributes to include from the iterator, or <code>null</code> to include all attributes.
208   */
209 public
210 AttributedString(AttributedCharacterIterator aci, int begin_index, 
211                  int end_index, AttributedCharacterIterator.Attribute[] attributes)
212 {
213   // Validate some arguments
214   if ((begin_index < 0) || (end_index < begin_index))
215     throw new IllegalArgumentException("Bad index values");
216
217   StringBuffer sb = new StringBuffer("");
218
219   // Get the valid attribute list
220   Set all_attribs = aci.getAllAttributeKeys();
221   if (attributes != null)
222     all_attribs.retainAll(Arrays.asList(attributes));
223
224   // Loop through and extract the attributes
225   char c = aci.setIndex(begin_index);
226
227   do
228     { 
229       sb.append(c);
230
231       Iterator iter = all_attribs.iterator();
232       while(iter.hasNext())
233         {
234           Object obj = iter.next();
235
236           // What should we do if this is not true?
237           if (!(obj instanceof AttributedCharacterIterator.Attribute))
238             continue;
239
240           AttributedCharacterIterator.Attribute attrib = 
241             (AttributedCharacterIterator.Attribute)obj;
242
243           // Make sure the attribute is defined.
244           int rl = aci.getRunLimit(attrib);
245           if (rl == -1)
246             continue;
247           if (rl > end_index)
248             rl = end_index;
249           rl -= begin_index;
250
251           // Check to see if we already processed this one
252           int rs = aci.getRunStart(attrib);
253           if ((rs < aci.getIndex()) && (aci.getIndex() != begin_index))
254             continue;
255
256           // If the attribute run starts before the beginning index, we
257           // need to junk it if it is an Annotation.
258           Object attrib_obj = aci.getAttribute(attrib);
259           if (rs < begin_index)
260             {
261               if (attrib_obj instanceof Annotation)
262                  continue;
263
264               rs = begin_index;
265             }
266           else
267             {
268               rs -= begin_index;
269             }
270
271           // Create a map object.  Yes this will only contain one attribute
272           Map new_map = new Hashtable();
273           new_map.put(attrib, attrib_obj);
274
275           // Add it to the attribute list.  Yes this is a bad way to do things.
276           AttributeRange[] new_list = new AttributeRange[attribs.length + 1];
277           System.arraycopy(attribs, 0, new_list, 0, attribs.length);
278           attribs = new_list;
279           attribs[attribs.length - 1] = new AttributeRange(new_map, rs, rl);
280         }
281
282       c = aci.next();
283     }
284   while(c != CharacterIterator.DONE);
285
286   sci = new StringCharacterIterator(sb.toString());
287 }
288
289 /*************************************************************************/
290
291 /*
292  * Instance Methods
293  */
294
295 /**
296   * This method adds a new attribute that will cover the entire string.
297   *
298   * @param attrib The attribute to add.
299   * @param value The value of the attribute.
300   */
301 public void
302 addAttribute(AttributedCharacterIterator.Attribute attrib, Object value)
303 {
304   addAttribute(attrib, value, 0, sci.getEndIndex());
305 }
306
307 /*************************************************************************/
308
309 /**
310   * This method adds a new attribute that will cover the specified subrange
311   * of the string.
312   *
313   * @param attrib The attribute to add.
314   * @param value The value of the attribute, which may be null.
315   * @param begin_index The beginning index of the subrange.
316   * @param end_index The ending index of the subrange.
317   *
318   * @exception IllegalArgumentException If attribute is <code>null</code> or the subrange is not valid.
319   */
320 public void
321 addAttribute(AttributedCharacterIterator.Attribute attrib, Object value,
322              int begin_index, int end_index)
323 {
324   if (attrib == null)
325     throw new IllegalArgumentException("null attribute");
326
327   HashMap hm = new HashMap();
328   hm.put(attrib, value);
329
330   addAttributes(hm, begin_index, end_index);
331 }
332
333 /*************************************************************************/
334
335 /**
336   * This method adds all of the attributes in the specified list to the
337   * specified subrange of the string.
338   *
339   * @param attributes The list of attributes.
340   * @param begin_index The beginning index.
341   * @param end_index The ending index
342   *
343   * @param IllegalArgumentException If the list is <code>null</code> or the subrange is not valid.
344   */
345 public void
346 addAttributes(Map attributes, int begin_index, int end_index)
347 {
348   if (attributes == null)
349     throw new IllegalArgumentException("null attribute");
350
351   if ((begin_index < 0) || (end_index > sci.getEndIndex()) ||
352       (end_index < begin_index))
353     throw new IllegalArgumentException("bad range");
354
355   AttributeRange[] new_list = new AttributeRange[attribs.length + 1];
356   System.arraycopy(attribs, 0, new_list, 0, attribs.length);
357   attribs = new_list;
358   attribs[attribs.length - 1] = new AttributeRange(attributes, begin_index, 
359                                                    end_index);
360
361
362 /*************************************************************************/
363
364 /**
365   * This method returns an <code>AttributedCharacterIterator</code> that 
366   * will iterate over the entire string.
367   *
368   * @return An <code>AttributedCharacterIterator</code> for the entire string.
369   */
370 public AttributedCharacterIterator
371 getIterator()
372 {
373   return(new AttributedStringIterator(sci, attribs, 0, sci.getEndIndex(), null));
374 }
375
376 /*************************************************************************/
377
378 /**
379   * This method returns an <code>AttributedCharacterIterator</code> that
380   * will iterate over the entire string.  This iterator will return information
381   * about the list of attributes in the specified array.  Attributes not in
382   * the array may or may not be returned by the iterator.  If the specified
383   * array is <code>null</code>, all attributes will be returned.
384   *
385   * @param attributes A list of attributes to include in the returned iterator.
386   *
387   * @return An <code>AttributedCharacterIterator</code> for this string.
388   */
389 public AttributedCharacterIterator
390 getIterator(AttributedCharacterIterator.Attribute[] attributes)
391 {
392   return(getIterator(attributes, 0, sci.getEndIndex()));
393 }
394
395 /*************************************************************************/
396
397 /**
398   * This method returns an <code>AttributedCharacterIterator</code> that
399   * will iterate over the specified subrange.  This iterator will return information
400   * about the list of attributes in the specified array.  Attributes not in
401   * the array may or may not be returned by the iterator.  If the specified
402   * array is <code>null</code>, all attributes will be returned.  
403   *
404   * @param attributes A list of attributes to include in the returned iterator.
405   * @param begin_index The beginning index of the subrange.
406   * @param end_index The ending index of the subrange.
407   *
408   * @return An <code>AttributedCharacterIterator</code> for this string.
409   */
410 public AttributedCharacterIterator
411 getIterator(AttributedCharacterIterator.Attribute[] attributes, 
412             int begin_index, int end_index)
413 {
414   if ((begin_index < 0) || (end_index > sci.getEndIndex()) ||
415       (end_index < begin_index))
416     throw new IllegalArgumentException("bad range");
417
418   return(new AttributedStringIterator(sci, attribs, begin_index, end_index,
419                                       attributes));
420 }
421
422 } // class AttributedString
423