1:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47:
48:
59: public class FormatCharacterIterator implements AttributedCharacterIterator
60: {
61: private String formattedString;
62: private int charIndex;
63: private int attributeIndex;
64: private int[] ranges;
65: private HashMap[] attributes;
66: private static final boolean DEBUG = false;
67:
68:
73: public FormatCharacterIterator()
74: {
75: formattedString = "";
76: ranges = new int[0];
77: attributes = new HashMap[0];
78: }
79:
80:
95: public FormatCharacterIterator (String s, int[] ranges, HashMap[] attributes)
96: {
97: formattedString = s;
98: this.ranges = ranges;
99: this.attributes = attributes;
100: }
101:
102:
106:
107: public Set getAllAttributeKeys()
108: {
109: if (attributes != null && attributes[attributeIndex] != null)
110: return attributes[attributeIndex].keySet();
111: else
112: return new HashSet();
113: }
114:
115: public Map getAttributes()
116: {
117: if (attributes != null && attributes[attributeIndex] != null)
118: return attributes[attributeIndex];
119: else
120: return new HashMap();
121: }
122:
123: public Object getAttribute (AttributedCharacterIterator.Attribute attrib)
124: {
125: if (attributes != null && attributes[attributeIndex] != null)
126: return attributes[attributeIndex].get (attrib);
127: else
128: return null;
129: }
130:
131: public int getRunLimit(Set reqAttrs)
132: {
133: if (attributes == null)
134: return formattedString.length();
135:
136: int currentAttrIndex = attributeIndex;
137: Set newKeys;
138:
139: do
140: {
141: currentAttrIndex++;
142: if (currentAttrIndex == attributes.length)
143: return formattedString.length();
144: if (attributes[currentAttrIndex] == null)
145: break;
146: newKeys = attributes[currentAttrIndex].keySet();
147: }
148: while (newKeys.containsAll (reqAttrs));
149:
150: return ranges[currentAttrIndex-1];
151: }
152:
153: public int getRunLimit (AttributedCharacterIterator.Attribute attribute)
154: {
155: Set s = new HashSet();
156:
157: s.add (attribute);
158: return getRunLimit (s);
159: }
160:
161: public int getRunLimit()
162: {
163: if (attributes == null)
164: return formattedString.length();
165: if (attributes[attributeIndex] == null)
166: {
167: for (int i=attributeIndex+1;i<attributes.length;i++)
168: if (attributes[i] != null)
169: return ranges[i-1];
170: return formattedString.length();
171: }
172:
173: return getRunLimit (attributes[attributeIndex].keySet());
174: }
175:
176: public int getRunStart (Set reqAttrs)
177: {
178: if (attributes == null)
179: return formattedString.length();
180:
181: int currentAttrIndex = attributeIndex;
182: Set newKeys = null;
183:
184: do
185: {
186: if (currentAttrIndex == 0)
187: return 0;
188:
189: currentAttrIndex--;
190: if (attributes[currentAttrIndex] == null)
191: break;
192: newKeys = attributes[currentAttrIndex].keySet();
193: }
194: while (newKeys.containsAll (reqAttrs));
195:
196: return (currentAttrIndex > 0) ? ranges[currentAttrIndex-1] : 0;
197: }
198:
199: public int getRunStart()
200: {
201: if (attributes == null)
202: return 0;
203:
204: if (attributes[attributeIndex] == null)
205: {
206: for (int i=attributeIndex;i>0;i--)
207: if (attributes[i] != null)
208: return ranges[attributeIndex-1];
209: return 0;
210: }
211:
212: return getRunStart (attributes[attributeIndex].keySet());
213: }
214:
215: public int getRunStart (AttributedCharacterIterator.Attribute attribute)
216: {
217: Set s = new HashSet();
218:
219: s.add (attribute);
220: return getRunStart (s);
221: }
222:
223: public Object clone()
224: {
225: return new FormatCharacterIterator (formattedString, ranges, attributes);
226: }
227:
228:
232:
233: public char current()
234: {
235: return formattedString.charAt (charIndex);
236: }
237:
238: public char first()
239: {
240: charIndex = 0;
241: attributeIndex = 0;
242: return formattedString.charAt (0);
243: }
244:
245: public int getBeginIndex()
246: {
247: return 0;
248: }
249:
250: public int getEndIndex()
251: {
252: return formattedString.length();
253: }
254:
255: public int getIndex()
256: {
257: return charIndex;
258: }
259:
260: public char last()
261: {
262: charIndex = formattedString.length()-1;
263: if (attributes != null)
264: attributeIndex = attributes.length-1;
265: return formattedString.charAt (charIndex);
266: }
267:
268: public char next()
269: {
270: charIndex++;
271: if (charIndex >= formattedString.length())
272: {
273: charIndex = getEndIndex();
274: return DONE;
275: }
276: if (attributes != null)
277: {
278: if (charIndex >= ranges[attributeIndex])
279: attributeIndex++;
280: }
281: return formattedString.charAt (charIndex);
282: }
283:
284: public char previous()
285: {
286: charIndex--;
287: if (charIndex < 0)
288: {
289: charIndex = 0;
290: return DONE;
291: }
292:
293: if (attributes != null)
294: {
295: if (charIndex < ranges[attributeIndex])
296: attributeIndex--;
297: }
298: return formattedString.charAt (charIndex);
299: }
300:
301: public char setIndex (int position)
302: {
303: if (position < 0 || position > formattedString.length())
304: throw new IllegalArgumentException ("position is out of range");
305:
306: charIndex = position;
307: if (attributes != null)
308: {
309: for (attributeIndex=0;attributeIndex<attributes.length;
310: attributeIndex++)
311: if (ranges[attributeIndex] > charIndex)
312: break;
313: attributeIndex--;
314: }
315: if (charIndex == formattedString.length())
316: return DONE;
317: else
318: return formattedString.charAt (charIndex);
319: }
320:
321:
330: public void mergeAttributes (HashMap[] attributes, int[] ranges)
331: {
332: Vector new_ranges = new Vector();
333: Vector new_attributes = new Vector();
334: int i = 0, j = 0;
335:
336: debug("merging " + attributes.length + " attrs");
337:
338: while (i < this.ranges.length && j < ranges.length)
339: {
340: if (this.attributes[i] != null)
341: {
342: new_attributes.add (this.attributes[i]);
343: if (attributes[j] != null)
344: this.attributes[i].putAll (attributes[j]);
345: }
346: else
347: {
348: new_attributes.add (attributes[j]);
349: }
350: if (this.ranges[i] == ranges[j])
351: {
352: new_ranges.add (new Integer (ranges[j]));
353: i++;
354: j++;
355: }
356: else if (this.ranges[i] < ranges[j])
357: {
358: new_ranges.add (new Integer (this.ranges[i]));
359: i++;
360: }
361: else
362: {
363: new_ranges.add (new Integer (ranges[j]));
364: j++;
365: }
366: }
367:
368: if (i != this.ranges.length)
369: {
370: for (;i<this.ranges.length;i++)
371: {
372: new_attributes.add (this.attributes[i]);
373: new_ranges.add (new Integer (this.ranges[i]));
374: }
375: }
376: if (j != ranges.length)
377: {
378: for (;j<ranges.length;j++)
379: {
380: new_attributes.add (attributes[j]);
381: new_ranges.add (new Integer (ranges[j]));
382: }
383: }
384:
385: this.attributes = new HashMap[new_attributes.size()];
386: this.ranges = new int[new_ranges.size()];
387: System.arraycopy (new_attributes.toArray(), 0, this.attributes,
388: 0, this.attributes.length);
389:
390: for (i=0;i<new_ranges.size();i++)
391: {
392: this.ranges[i] = ((Integer)new_ranges.elementAt (i)).intValue();
393: }
394:
395: dumpTable();
396: }
397:
398:
405: public void append (AttributedCharacterIterator iterator)
406: {
407: char c = iterator.first();
408: Vector more_ranges = new Vector();
409: Vector more_attributes = new Vector();
410:
411: do
412: {
413: formattedString = formattedString + String.valueOf (c);
414:
415: more_attributes.add (iterator.getAttributes());
416: more_ranges.add (new Integer (formattedString.length()));
417:
418: c = iterator.next();
419: }
420: while (c != DONE);
421:
422: HashMap[] new_attributes = new HashMap[attributes.length
423: + more_attributes.size()];
424: int[] new_ranges = new int[ranges.length + more_ranges.size()];
425:
426: System.arraycopy (attributes, 0, new_attributes, 0, attributes.length);
427: System.arraycopy (more_attributes.toArray(), 0, new_attributes,
428: attributes.length, more_attributes.size());
429:
430: System.arraycopy (ranges, 0, new_ranges, 0, ranges.length);
431: Object[] new_ranges_array = more_ranges.toArray();
432: for (int i = 0; i < more_ranges.size();i++)
433: new_ranges[i+ranges.length] = ((Integer) new_ranges_array[i]).intValue();
434:
435: attributes = new_attributes;
436: ranges = new_ranges;
437: }
438:
439:
448: public void append (String text, HashMap local_attributes)
449: {
450: int[] new_ranges = new int[ranges.length+1];
451: HashMap[] new_attributes = new HashMap[attributes.length+1];
452:
453: formattedString += text;
454: System.arraycopy (attributes, 0, new_attributes, 0, attributes.length);
455: System.arraycopy (ranges, 0, new_ranges, 0, ranges.length);
456: new_ranges[ranges.length] = formattedString.length();
457: new_attributes[attributes.length] = local_attributes;
458:
459: ranges = new_ranges;
460: attributes = new_attributes;
461: }
462:
463:
470: public void append (String text)
471: {
472: append (text, null);
473: }
474:
475:
488: public void addAttributes(HashMap attributes, int range_start, int range_end)
489: {
490: if (range_start == 0)
491: mergeAttributes(new HashMap[] { attributes }, new int[] { range_end });
492: else
493: mergeAttributes(new HashMap[] { null, attributes }, new int[] { range_start, range_end });
494: }
495:
496: private void debug(String s)
497: {
498: if (DEBUG)
499: System.out.println(s);
500: }
501:
502: private void dumpTable()
503: {
504: int start_range = 0;
505:
506: if (!DEBUG)
507: return;
508:
509: System.out.println("Dumping internal table:");
510: for (int i = 0; i < ranges.length; i++)
511: {
512: System.out.print("\t" + start_range + " => " + ranges[i] + ":");
513: if (attributes[i] == null)
514: System.out.println("null");
515: else
516: {
517: Set keyset = attributes[i].keySet();
518: if (keyset != null)
519: {
520: Iterator keys = keyset.iterator();
521:
522: while (keys.hasNext())
523: System.out.print(" " + keys.next());
524: }
525: else
526: System.out.println("keySet null");
527: System.out.println();
528: }
529: }
530: System.out.println();
531: System.out.flush();
532: }
533: }