001    /* CSS.java -- Provides CSS attributes
002       Copyright (C) 2005 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    package javax.swing.text.html;
039    
040    import gnu.javax.swing.text.html.css.BorderStyle;
041    import gnu.javax.swing.text.html.css.BorderWidth;
042    import gnu.javax.swing.text.html.css.CSSColor;
043    import gnu.javax.swing.text.html.css.FontSize;
044    import gnu.javax.swing.text.html.css.FontStyle;
045    import gnu.javax.swing.text.html.css.FontWeight;
046    import gnu.javax.swing.text.html.css.Length;
047    
048    import java.io.Serializable;
049    import java.util.HashMap;
050    import java.util.StringTokenizer;
051    
052    import javax.swing.text.MutableAttributeSet;
053    
054    /**
055     * Provides CSS attributes to be used by the HTML view classes. The constants
056     * defined here are used as keys for text attributes for use in
057     * {@link javax.swing.text.AttributeSet}s of {@link javax.swing.text.Element}s.
058     *
059     * @author Roman Kennke (kennke@aicas.com)
060     */
061    public class CSS implements Serializable
062    {
063      /**
064       * Returns an array of all CSS attributes.
065       *
066       * @return All available CSS.Attribute objects.
067       */
068      public static CSS.Attribute[] getAllAttributeKeys()
069      {
070        Object[] src = Attribute.attributeMap.values().toArray();
071        CSS.Attribute[] dst = new CSS.Attribute[ src.length ];
072        System.arraycopy(src, 0, dst, 0, src.length);
073        return dst;
074      }
075    
076      /**
077       * Returns an a given CSS attribute.
078       *
079       * @param name - The name of the attribute.
080       * @return The CSS attribute with the given name, or <code>null</code> if
081       * no attribute with that name exists.
082       */
083      public static CSS.Attribute getAttribute(String name)
084      {
085        return (CSS.Attribute)Attribute.attributeMap.get( name );
086      }
087    
088      public static final class Attribute
089      {
090        /**
091         * The CSS attribute 'background'.
092         */
093        public static final Attribute BACKGROUND =
094          new Attribute("background", false, null);
095    
096        /**
097         * The CSS attribute 'background-attachment'.
098         */
099        public static final Attribute BACKGROUND_ATTACHMENT =
100          new Attribute("background-attachment", false, "scroll");
101    
102        /**
103         * The CSS attribute 'background-color'.
104         */
105        public static final Attribute BACKGROUND_COLOR =
106          new Attribute("background-color", false, "transparent");
107    
108        /**
109         * The CSS attribute 'background-image'.
110         */
111        public static final Attribute BACKGROUND_IMAGE =
112          new Attribute("background-image", false, "none");
113    
114        /**
115         * The CSS attribute 'background-position'.
116         */
117        public static final Attribute BACKGROUND_POSITION =
118          new Attribute("background-position", false, null);
119    
120        /**
121         * The CSS attribute 'background-repeat'.
122         */
123        public static final Attribute BACKGROUND_REPEAT =
124          new Attribute("background-repeat", false, "repeat");
125    
126        /**
127         * The CSS attribute 'border'.
128         */
129        public static final Attribute BORDER = new Attribute("border", false, null);
130    
131        /**
132         * The CSS attribute 'border-bottom'.
133         */
134        public static final Attribute BORDER_BOTTOM =
135          new Attribute("border-bottom", false, null);
136    
137        /**
138         * The CSS attribute 'border-bottom-width'.
139         */
140        public static final Attribute BORDER_BOTTOM_WIDTH =
141          new Attribute("border-bottom-width", false, "medium");
142    
143        /**
144         * The CSS attribute 'border-color'.
145         */
146        public static final Attribute BORDER_COLOR =
147          new Attribute("border-color", false, "black");
148    
149        /**
150         * The CSS attribute 'border-left'.
151         */
152        public static final Attribute BORDER_LEFT =
153          new Attribute("border-left", false, null);
154    
155        /**
156         * The CSS attribute 'border-left-width'.
157         */
158        public static final Attribute BORDER_LEFT_WIDTH =
159          new Attribute("border-left-width", false, "medium");
160    
161        /**
162         * The CSS attribute 'border-right'.
163         */
164        public static final Attribute BORDER_RIGHT =
165          new Attribute("border-right", false, null);
166    
167        /**
168         * The CSS attribute 'border-right-width'.
169         */
170        public static final Attribute BORDER_RIGHT_WIDTH =
171          new Attribute("border-right-width", false, "medium");
172    
173        /**
174         * The CSS attribute 'border-style'.
175         */
176        public static final Attribute BORDER_STYLE =
177          new Attribute("border-style", false, "none");
178    
179        /**
180         * The CSS attribute 'border-top'.
181         */
182        public static final Attribute BORDER_TOP =
183          new Attribute("border-top", false, null);
184    
185        /**
186         * The CSS attribute 'border-top-width'.
187         */
188        public static final Attribute BORDER_TOP_WIDTH =
189          new Attribute("border-top-width", false, "medium");
190    
191        /**
192         * The CSS attribute 'border-width'.
193         */
194        public static final Attribute BORDER_WIDTH =
195          new Attribute("border-width", false, "medium");
196    
197        /**
198         * The CSS attribute 'clear'.
199         */
200        public static final Attribute CLEAR = new Attribute("clear", false, "none");
201    
202        /**
203         * The CSS attribute 'color'.
204         */
205        public static final Attribute COLOR = new Attribute("color", true, "black");
206    
207        /**
208         * The CSS attribute 'display'.
209         */
210        public static final Attribute DISPLAY =
211          new Attribute("display", false, "block");
212    
213        /**
214         * The CSS attribute 'float'.
215         */
216        public static final Attribute FLOAT = new Attribute("float", false, "none");
217    
218        /**
219         * The CSS attribute 'font'.
220         */
221        public static final Attribute FONT = new Attribute("font", true, null);
222    
223        /**
224         * The CSS attribute 'font-family'.
225         */
226        public static final Attribute FONT_FAMILY =
227          new Attribute("font-family", true, null);
228    
229        /**
230         * The CSS attribute 'font-size'.
231         */
232        public static final Attribute FONT_SIZE =
233          new Attribute("font-size", true, "medium");
234    
235        /**
236         * The CSS attribute 'font-style'.
237         */
238        public static final Attribute FONT_STYLE =
239          new Attribute("font-style", true, "normal");
240    
241        /**
242         * The CSS attribute 'font-variant'.
243         */
244        public static final Attribute FONT_VARIANT =
245          new Attribute("font-variant", true, "normal");
246    
247        /**
248         * The CSS attribute 'font-weight'.
249         */
250        public static final Attribute FONT_WEIGHT =
251          new Attribute("font-weight", true, "normal");
252    
253        /**
254         * The CSS attribute 'height'.
255         */
256        public static final Attribute HEIGHT =
257          new Attribute("height", false, "auto");
258    
259        /**
260         * The CSS attribute 'letter-spacing'.
261         */
262        public static final Attribute LETTER_SPACING =
263          new Attribute("letter-spacing", true, "normal");
264    
265        /**
266         * The CSS attribute 'line-height'.
267         */
268        public static final Attribute LINE_HEIGHT =
269          new Attribute("line-height", true, "normal");
270    
271        /**
272         * The CSS attribute 'list-style'.
273         */
274        public static final Attribute LIST_STYLE =
275          new Attribute("list-style", true, null);
276    
277        /**
278         * The CSS attribute 'list-style-image'.
279         */
280        public static final Attribute LIST_STYLE_IMAGE =
281          new Attribute("list-style-image", true, "none");
282    
283        /**
284         * The CSS attribute 'list-style-position'.
285         */
286        public static final Attribute LIST_STYLE_POSITION =
287          new Attribute("list-style-position", true, "outside");
288    
289        /**
290         * The CSS attribute 'list-style-type'.
291         */
292        public static final Attribute LIST_STYLE_TYPE =
293          new Attribute("list-style-type", true, "disc");
294    
295        /**
296         * The CSS attribute 'margin'.
297         */
298        public static final Attribute MARGIN = new Attribute("margin", false, null);
299    
300        /**
301         * The CSS attribute 'margin-bottom'.
302         */
303        public static final Attribute MARGIN_BOTTOM =
304          new Attribute("margin-bottom", false, "0");
305    
306        /**
307         * The CSS attribute 'margin-left'.
308         */
309        public static final Attribute MARGIN_LEFT =
310          new Attribute("margin-left", false, "0");
311    
312        /**
313         * The CSS attribute 'margin-right'.
314         */
315        public static final Attribute MARGIN_RIGHT =
316          new Attribute("margin-right", false, "0");
317    
318        /**
319         * The CSS attribute 'margin-top'.
320         */
321        public static final Attribute MARGIN_TOP =
322          new Attribute("margin-top", false, "0");
323    
324        /**
325         * The CSS attribute 'padding'.
326         */
327        public static final Attribute PADDING =
328          new Attribute("padding", false, null);
329    
330        /**
331         * The CSS attribute 'padding-bottom'.
332         */
333        public static final Attribute PADDING_BOTTOM =
334          new Attribute("padding-bottom", false, "0");
335    
336        /**
337         * The CSS attribute 'padding-left'.
338         */
339        public static final Attribute PADDING_LEFT =
340          new Attribute("padding-left", false, "0");
341    
342        /**
343         * The CSS attribute 'padding-right'.
344         */
345        public static final Attribute PADDING_RIGHT =
346          new Attribute("padding-right", false, "0");
347    
348        /**
349         * The CSS attribute 'padding-top'.
350         */
351        public static final Attribute PADDING_TOP =
352          new Attribute("padding-top", false, "0");
353    
354        /**
355         * The CSS attribute 'text-align'.
356         */
357        public static final Attribute TEXT_ALIGN =
358          new Attribute("text-align", true, null);
359    
360        /**
361         * The CSS attribute 'text-decoration'.
362         */
363        public static final Attribute TEXT_DECORATION =
364          new Attribute("text-decoration", true, "none");
365    
366        /**
367         * The CSS attribute 'text-indent'.
368         */
369        public static final Attribute TEXT_INDENT =
370          new Attribute("text-indent", true, "0");
371    
372        /**
373         * The CSS attribute 'text-transform'.
374         */
375        public static final Attribute TEXT_TRANSFORM =
376          new Attribute("text-transform", true, "none");
377    
378        /**
379         * The CSS attribute 'vertical-align'.
380         */
381        public static final Attribute VERTICAL_ALIGN =
382          new Attribute("vertical-align", false, "baseline");
383    
384        /**
385         * The CSS attribute 'white-space'.
386         */
387        public static final Attribute WHITE_SPACE =
388          new Attribute("white-space", true, "normal");
389    
390        /**
391         * The CSS attribute 'width'.
392         */
393        public static final Attribute WIDTH =
394          new Attribute("width", false, "auto");
395    
396        /**
397         * The CSS attribute 'word-spacing'.
398         */
399        public static final Attribute WORD_SPACING =
400          new Attribute("word-spacing", true, "normal");
401    
402        // Some GNU Classpath specific extensions.
403        static final Attribute BORDER_TOP_STYLE =
404          new Attribute("border-top-style", false, null);
405        static final Attribute BORDER_BOTTOM_STYLE =
406          new Attribute("border-bottom-style", false, null);
407        static final Attribute BORDER_LEFT_STYLE =
408          new Attribute("border-left-style", false, null);
409        static final Attribute BORDER_RIGHT_STYLE =
410          new Attribute("border-right-style", false, null);
411        static final Attribute BORDER_TOP_COLOR =
412          new Attribute("border-top-color", false, null);
413        static final Attribute BORDER_BOTTOM_COLOR =
414          new Attribute("border-bottom-color", false, null);
415        static final Attribute BORDER_LEFT_COLOR =
416          new Attribute("border-left-color", false, null);
417        static final Attribute BORDER_RIGHT_COLOR =
418          new Attribute("border-right-color", false, null);
419        static final Attribute BORDER_SPACING =
420          new Attribute("border-spacing", false, null);
421        static final Attribute POSITION =
422          new Attribute("position", false, null);
423        static final Attribute LEFT =
424          new Attribute("left", false, null);
425        static final Attribute RIGHT =
426          new Attribute("right", false, null);
427        static final Attribute TOP =
428          new Attribute("top", false, null);
429        static final Attribute BOTTOM =
430          new Attribute("bottom", false, null);
431    
432        /**
433         * The attribute string.
434         */
435        String attStr;
436    
437        /**
438         * Indicates if this attribute should be inherited from it's parent or
439         * not.
440         */
441        boolean isInherited;
442    
443        /**
444         * A default value for this attribute if one exists, otherwise null.
445         */
446        String defaultValue;
447    
448        /**
449         * A HashMap of all attributes.
450         */
451        static HashMap attributeMap;
452    
453        /**
454         * Creates a new Attribute instance with the specified values.
455         *
456         * @param attr the attribute string
457         * @param inherited if the attribute should be inherited or not
458         * @param def a default value; may be <code>null</code>
459         */
460        Attribute(String attr, boolean inherited, String def)
461        {
462          attStr = attr;
463          isInherited = inherited;
464          defaultValue = def;
465          if( attributeMap == null)
466            attributeMap = new HashMap();
467          attributeMap.put( attr, this );
468        }
469    
470        /**
471         * Returns the string representation of this attribute as specified
472         * in the CSS specification.
473         */
474        public String toString()
475        {
476          return attStr;
477        }
478    
479        /**
480         * Returns <code>true</code> if the attribute should be inherited from
481         * the parent, <code>false</code> otherwise.
482         *
483         * @return <code>true</code> if the attribute should be inherited from
484         *         the parent, <code>false</code> otherwise
485         */
486        public boolean isInherited()
487        {
488          return isInherited;
489        }
490    
491        /**
492         * Returns the default value of this attribute if one exists,
493         * <code>null</code> otherwise.
494         *
495         * @return the default value of this attribute if one exists,
496         *         <code>null</code> otherwise
497         */
498        public String getDefaultValue()
499        {
500          return defaultValue;
501        }
502      }
503    
504      /**
505       * Maps attribute values (String) to some converter class, based on the
506       * key.
507       *
508       * @param att the key
509       * @param v the value
510       *
511       * @return the wrapped value
512       */
513      static Object getValue(Attribute att, String v)
514      {
515        Object o;
516        if (att == Attribute.FONT_SIZE)
517          o = new FontSize(v);
518        else if (att == Attribute.FONT_WEIGHT)
519          o = new FontWeight(v);
520        else if (att == Attribute.FONT_STYLE)
521          o = new FontStyle(v);
522        else if (att == Attribute.COLOR || att == Attribute.BACKGROUND_COLOR
523                 || att == Attribute.BORDER_COLOR
524                 || att == Attribute.BORDER_TOP_COLOR
525                 || att == Attribute.BORDER_BOTTOM_COLOR
526                 || att == Attribute.BORDER_LEFT_COLOR
527                 || att == Attribute.BORDER_RIGHT_COLOR)
528          o = new CSSColor(v);
529        else if (att == Attribute.MARGIN || att == Attribute.MARGIN_BOTTOM
530                 || att == Attribute.MARGIN_LEFT || att == Attribute.MARGIN_RIGHT
531                 || att == Attribute.MARGIN_TOP || att == Attribute.WIDTH
532                 || att == Attribute.HEIGHT
533                 || att == Attribute.PADDING || att == Attribute.PADDING_BOTTOM
534                 || att == Attribute.PADDING_LEFT || att == Attribute.PADDING_RIGHT
535                 || att == Attribute.PADDING_TOP
536                 || att == Attribute.LEFT || att == Attribute.RIGHT
537                 || att == Attribute.TOP || att == Attribute.BOTTOM)
538          o = new Length(v);
539        else if (att == Attribute.BORDER_WIDTH || att == Attribute.BORDER_TOP_WIDTH
540                 || att == Attribute.BORDER_LEFT_WIDTH
541                 || att == Attribute.BORDER_RIGHT_WIDTH
542                 || att == Attribute.BORDER_BOTTOM_WIDTH)
543          o = new BorderWidth(v);
544        else
545          o = v;
546        return o;
547      }
548    
549      static void addInternal(MutableAttributeSet atts, Attribute a, String v)
550      {
551        if (a == Attribute.BACKGROUND)
552          parseBackgroundShorthand(atts, v);
553        else if (a == Attribute.PADDING)
554          parsePaddingShorthand(atts, v);
555        else if (a == Attribute.MARGIN)
556          parseMarginShorthand(atts, v);
557        else if (a == Attribute.BORDER || a == Attribute.BORDER_LEFT
558                 || a == Attribute.BORDER_RIGHT || a == Attribute.BORDER_TOP
559                 || a == Attribute.BORDER_BOTTOM)
560          parseBorderShorthand(atts, v, a);
561      }
562    
563      /**
564       * Parses the background shorthand and translates it to more specific
565       * background attributes.
566       *
567       * @param atts the attributes
568       * @param v the value
569       */
570      private static void parseBackgroundShorthand(MutableAttributeSet atts,
571                                                   String v)
572      {
573        StringTokenizer tokens = new StringTokenizer(v, " ");
574        while (tokens.hasMoreElements())
575          {
576            String token = tokens.nextToken();
577            if (CSSColor.isValidColor(token))
578              atts.addAttribute(Attribute.BACKGROUND_COLOR,
579                                new CSSColor(token));
580          }
581      }
582    
583      /**
584       * Parses the padding shorthand and translates to the specific padding
585       * values.
586       *
587       * @param atts the attributes
588       * @param v the actual value
589       */
590      private static void parsePaddingShorthand(MutableAttributeSet atts, String v)
591      {
592        StringTokenizer tokens = new StringTokenizer(v, " ");
593        int numTokens = tokens.countTokens();
594        if (numTokens == 1)
595          {
596            Length l = new Length(tokens.nextToken());
597            atts.addAttribute(Attribute.PADDING_BOTTOM, l);
598            atts.addAttribute(Attribute.PADDING_LEFT, l);
599            atts.addAttribute(Attribute.PADDING_RIGHT, l);
600            atts.addAttribute(Attribute.PADDING_TOP, l);
601          }
602        else if (numTokens == 2)
603          {
604            Length l1 = new Length(tokens.nextToken());
605            Length l2 = new Length(tokens.nextToken());
606            atts.addAttribute(Attribute.PADDING_BOTTOM, l1);
607            atts.addAttribute(Attribute.PADDING_TOP, l1);
608            atts.addAttribute(Attribute.PADDING_LEFT, l2);
609            atts.addAttribute(Attribute.PADDING_RIGHT, l2);
610          }
611        else if (numTokens == 3)
612          {
613            Length l1 = new Length(tokens.nextToken());
614            Length l2 = new Length(tokens.nextToken());
615            Length l3 = new Length(tokens.nextToken());
616            atts.addAttribute(Attribute.PADDING_TOP, l1);
617            atts.addAttribute(Attribute.PADDING_LEFT, l2);
618            atts.addAttribute(Attribute.PADDING_RIGHT, l2);
619            atts.addAttribute(Attribute.PADDING_BOTTOM, l3);
620          }
621        else
622          {
623            Length l1 = new Length(tokens.nextToken());
624            Length l2 = new Length(tokens.nextToken());
625            Length l3 = new Length(tokens.nextToken());
626            Length l4 = new Length(tokens.nextToken());
627            atts.addAttribute(Attribute.PADDING_TOP, l1);
628            atts.addAttribute(Attribute.PADDING_RIGHT, l2);
629            atts.addAttribute(Attribute.PADDING_BOTTOM, l3);
630            atts.addAttribute(Attribute.PADDING_LEFT, l4);
631          }
632      }
633    
634      /**
635       * Parses the margin shorthand and translates to the specific margin
636       * values.
637       *
638       * @param atts the attributes
639       * @param v the actual value
640       */
641      private static void parseMarginShorthand(MutableAttributeSet atts, String v)
642      {
643        StringTokenizer tokens = new StringTokenizer(v, " ");
644        int numTokens = tokens.countTokens();
645        if (numTokens == 1)
646          {
647            Length l = new Length(tokens.nextToken());
648            atts.addAttribute(Attribute.MARGIN_BOTTOM, l);
649            atts.addAttribute(Attribute.MARGIN_LEFT, l);
650            atts.addAttribute(Attribute.MARGIN_RIGHT, l);
651            atts.addAttribute(Attribute.MARGIN_TOP, l);
652          }
653        else if (numTokens == 2)
654          {
655            Length l1 = new Length(tokens.nextToken());
656            Length l2 = new Length(tokens.nextToken());
657            atts.addAttribute(Attribute.MARGIN_BOTTOM, l1);
658            atts.addAttribute(Attribute.MARGIN_TOP, l1);
659            atts.addAttribute(Attribute.MARGIN_LEFT, l2);
660            atts.addAttribute(Attribute.MARGIN_RIGHT, l2);
661          }
662        else if (numTokens == 3)
663          {
664            Length l1 = new Length(tokens.nextToken());
665            Length l2 = new Length(tokens.nextToken());
666            Length l3 = new Length(tokens.nextToken());
667            atts.addAttribute(Attribute.MARGIN_TOP, l1);
668            atts.addAttribute(Attribute.MARGIN_LEFT, l2);
669            atts.addAttribute(Attribute.MARGIN_RIGHT, l2);
670            atts.addAttribute(Attribute.MARGIN_BOTTOM, l3);
671          }
672        else
673          {
674            Length l1 = new Length(tokens.nextToken());
675            Length l2 = new Length(tokens.nextToken());
676            Length l3 = new Length(tokens.nextToken());
677            Length l4 = new Length(tokens.nextToken());
678            atts.addAttribute(Attribute.MARGIN_TOP, l1);
679            atts.addAttribute(Attribute.MARGIN_RIGHT, l2);
680            atts.addAttribute(Attribute.MARGIN_BOTTOM, l3);
681            atts.addAttribute(Attribute.MARGIN_LEFT, l4);
682          }
683      }
684    
685      /**
686       * Parses the CSS border shorthand attribute and translates it to the
687       * more specific border attributes.
688       *
689       * @param atts the attribute
690       * @param value the value
691       */
692      private static void parseBorderShorthand(MutableAttributeSet atts,
693                                               String value, Attribute cssAtt)
694      {
695        StringTokenizer tokens = new StringTokenizer(value, " ");
696        while (tokens.hasMoreTokens())
697          {
698            String token = tokens.nextToken();
699            if (BorderStyle.isValidStyle(token))
700              {
701                if (cssAtt == Attribute.BORDER_LEFT || cssAtt == Attribute.BORDER)
702                  atts.addAttribute(Attribute.BORDER_LEFT_STYLE, token);
703                if (cssAtt == Attribute.BORDER_RIGHT || cssAtt == Attribute.BORDER)
704                  atts.addAttribute(Attribute.BORDER_RIGHT_STYLE, token);
705                if (cssAtt == Attribute.BORDER_BOTTOM || cssAtt == Attribute.BORDER)
706                  atts.addAttribute(Attribute.BORDER_BOTTOM_STYLE, token);
707                if (cssAtt == Attribute.BORDER_TOP || cssAtt == Attribute.BORDER)
708                  atts.addAttribute(Attribute.BORDER_TOP_STYLE, token);
709              }
710            else if (BorderWidth.isValid(token))
711              {
712                BorderWidth w = new BorderWidth(token);
713                if (cssAtt == Attribute.BORDER_LEFT || cssAtt == Attribute.BORDER)
714                  atts.addAttribute(Attribute.BORDER_LEFT_WIDTH, w);
715                if (cssAtt == Attribute.BORDER_RIGHT || cssAtt == Attribute.BORDER)
716                  atts.addAttribute(Attribute.BORDER_RIGHT_WIDTH, w);
717                if (cssAtt == Attribute.BORDER_BOTTOM || cssAtt == Attribute.BORDER)
718                  atts.addAttribute(Attribute.BORDER_BOTTOM_WIDTH, w);
719                if (cssAtt == Attribute.BORDER_TOP || cssAtt == Attribute.BORDER)
720                  atts.addAttribute(Attribute.BORDER_TOP_WIDTH, w);
721              }
722            else if (CSSColor.isValidColor(token))
723              {
724                CSSColor c = new CSSColor(token);
725                if (cssAtt == Attribute.BORDER_LEFT || cssAtt == Attribute.BORDER)
726                  atts.addAttribute(Attribute.BORDER_LEFT_COLOR, c);
727                if (cssAtt == Attribute.BORDER_RIGHT || cssAtt == Attribute.BORDER)
728                  atts.addAttribute(Attribute.BORDER_RIGHT_COLOR, c);
729                if (cssAtt == Attribute.BORDER_BOTTOM || cssAtt == Attribute.BORDER)
730                  atts.addAttribute(Attribute.BORDER_BOTTOM_COLOR, c);
731                if (cssAtt == Attribute.BORDER_TOP || cssAtt == Attribute.BORDER)
732                  atts.addAttribute(Attribute.BORDER_TOP_COLOR, c);
733              }
734          }
735      }
736    }