Clover coverage report -
Coverage timestamp: Sun Apr 18 2004 21:32:30 EDT
file stats: LOC: 1,066   Methods: 37
NCLOC: 603   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Util.java 51.7% 59.3% 75.7% 58.7%
coverage coverage
 1   
 /*
 2   
  * SimplyHTML, a word processor based on Java, HTML and CSS
 3   
  * Copyright (C) 2002 Ulrich Hilger
 4   
  *
 5   
  * This program is free software; you can redistribute it and/or
 6   
  * modify it under the terms of the GNU General Public License
 7   
  * as published by the Free Software Foundation; either version 2
 8   
  * of the License, or (at your option) any later version.
 9   
  *
 10   
  * This program is distributed in the hope that it will be useful,
 11   
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12   
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13   
  * GNU General Public License for more details.
 14   
  *
 15   
  * You should have received a copy of the GNU General Public License
 16   
  * along with this program; if not, write to the Free Software
 17   
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 18   
  */
 19   
 
 20   
 import java.net.URL;
 21   
 import java.awt.Component;
 22   
 import javax.swing.JOptionPane;
 23   
 import java.awt.Dimension;
 24   
 import java.awt.Point;
 25   
 import java.awt.Frame;
 26   
 import javax.swing.text.AttributeSet;
 27   
 import javax.swing.text.SimpleAttributeSet;
 28   
 import javax.swing.text.html.CSS;
 29   
 import javax.swing.text.html.StyleSheet;
 30   
 import javax.swing.text.Element;
 31   
 import java.awt.GridBagLayout;
 32   
 import java.awt.GridBagConstraints;
 33   
 import javax.swing.JComponent;
 34   
 import java.awt.Insets;
 35   
 import java.util.Vector;
 36   
 import javax.swing.text.ElementIterator;
 37   
 import java.util.Enumeration;
 38   
 import javax.swing.text.html.HTML;
 39   
 import java.util.StringTokenizer;
 40   
 import java.io.File;
 41   
 import java.io.FileNotFoundException;
 42   
 import java.io.IOException;
 43   
 import java.io.RandomAccessFile;
 44   
 import javax.swing.text.StyleConstants;
 45   
 
 46   
 /**
 47   
  * Utility methods for application SimplyHTML.
 48   
  *
 49   
  * @author Ulrich Hilger
 50   
  * @author Light Development
 51   
  * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
 52   
  * @author <a href="mailto:info@lightdev.com">info@lightdev.com</a>
 53   
  * @author published under the terms and conditions of the
 54   
  *      GNU General Public License,
 55   
  *      for details see file gpl.txt in the distribution
 56   
  *      package of this software
 57   
  *
 58   
  * @version stage 11, April 27, 2003
 59   
  */
 60   
 
 61   
 public class Util {
 62   
 
 63   
   /* some constants */
 64   
   public static final String JAR_PREFIX = "jar:";
 65   
   public static final String JAR_EXTENSION = ".jar";
 66   
   public static final String FILE_PREFIX = "file:";
 67   
   public static final String CLASS_EXT = ".class";
 68   
   public static final String JAR_SEPARATOR = "!/";
 69   
   public static final String URL_SEPARATOR = "/";
 70   
   public static final char URL_SEPARATOR_CHAR = '/';
 71   
   public static final String CLASS_SEPARATOR = ".";
 72   
   public static final char CLASS_SEPARATOR_CHAR = '.';
 73   
   public static final String DIR_UP_INDICATOR = "..";
 74   
   public static final String RELATIVE_PREFIX = "../";
 75   
   public static final String PROTOCOL_SEPARATOR = ":";
 76   
   public static final String ANCHOR_SEPARATOR = "#";
 77   
   public static final String pct = "%";
 78   
   public static final String pt = "pt";
 79   
   public static final String px = "px";
 80   
 
 81   
   /** the default block size in bytes for file operations */
 82   
   private static int blockSize = 1024;
 83   
 
 84   
   private static Vector startTimes = new Vector();
 85   
 
 86   
   private static final String ERR_TITLE = "Error";
 87   
 
 88   
   private static String unit = "";
 89   
 
 90   
   /** a style sheet instanciated once for access to its utility methods */
 91   
   private static StyleSheet s = new StyleSheet();
 92   
 
 93   
   /* CSS Attribute constants */
 94   
   public static final String CSS_ATTRIBUTE_NORMAL = "normal";
 95   
   public static final String CSS_ATTRIBUTE_UNDERLINE = "underline";
 96   
   public static final String CSS_ATTRIBUTE_LINE_THROUGH = "line-through";
 97   
   public static final String CSS_ATTRIBUTE_NONE = "none";
 98   
   public static final String CSS_ATTRIBUTE_ALIGN_LEFT = "left";
 99   
   public static final String CSS_ATTRIBUTE_ALIGN_CENTER = "center";
 100   
   public static final String CSS_ATTRIBUTE_ALIGN_RIGHT = "right";
 101   
 
 102  3
   public Util() {
 103   
   }
 104   
 
 105   
   /**
 106   
    * rename a file to have a given extension
 107   
    *
 108   
    * @param from  the file to rename
 109   
    * @param newExt  the new extension the file shall have
 110   
    *
 111   
    * @return the renamed file
 112   
    */
 113  1
   public static File renameFile(File from, String newExt) {
 114  1
     String fileName = Util.removeExtension(from.getName());
 115  1
     String saveFileName = from.getParentFile().getAbsolutePath() + File.separator + fileName + newExt;
 116  1
     File newFile = new File(saveFileName);
 117  1
     from.renameTo(newFile);
 118  1
     return newFile;
 119   
   }
 120   
 
 121   
   /**
 122   
    * find the next link attribute from a given element upwards
 123   
    * through the element hierarchy
 124   
    *
 125   
    * @param elem  the element to start looking at
 126   
    *
 127   
    * @return the link attribute found, or null, if none was found
 128   
    */
 129  0
   public static Object findLinkUp(Element elem) {
 130  0
     Element e = null;
 131   
     //Element elem = ((SHTMLDocument) doc).getCharacterElement(selStart);
 132  0
     Object linkAttr = null; //elem.getAttributes().getAttribute(HTML.Tag.A);
 133  0
     Object href = null;
 134  0
     while((elem != null) && (linkAttr == null)) {
 135  0
       e = elem;
 136  0
       linkAttr = elem.getAttributes().getAttribute(HTML.Tag.A);
 137  0
       if(linkAttr != null) {
 138  0
         href = ((AttributeSet) linkAttr).getAttribute(HTML.Attribute.HREF);
 139   
       }
 140  0
       elem = elem.getParentElement();
 141   
     }
 142  0
     if(linkAttr != null && href != null) {
 143  0
       return linkAttr;
 144   
     }
 145   
     else {
 146  0
       return null;
 147   
     }
 148   
   }
 149   
 
 150   
   /**
 151   
    * remove the extension from a file name
 152   
    *
 153   
    * @param  fileName  the file name to remove the extension from
 154   
    *
 155   
    * @return the file name without extension
 156   
    */
 157  2
   public static String removeExtension(String fileName) {
 158  2
     String newName = fileName;
 159  2
     int pos = newName.lastIndexOf(".");
 160  2
     if(pos > -1) {
 161  2
       newName = fileName.substring(0,pos);
 162   
     }
 163  2
     return newName;
 164   
   }
 165   
 
 166   
   /**
 167   
    * find the next link attribute from a given element upwards
 168   
    * through the element hierarchy
 169   
    *
 170   
    * @param elem  the element to start looking at
 171   
    *
 172   
    * @return the link attribute found, or null, if none was found
 173   
    */
 174  118
   public static Element findLinkElementUp(Element elem) {
 175  118
     Element e = null;
 176   
     //Element elem = ((SHTMLDocument) doc).getCharacterElement(selStart);
 177  118
     Object linkAttr = null; //elem.getAttributes().getAttribute(HTML.Tag.A);
 178  118
     Object href = null;
 179  118
     while((elem != null) && (linkAttr == null)) {
 180  478
       e = elem;
 181  478
       linkAttr = elem.getAttributes().getAttribute(HTML.Tag.A);
 182  478
       if(linkAttr != null) {
 183  0
         href = ((AttributeSet) linkAttr).getAttribute(HTML.Attribute.HREF);
 184   
       }
 185  478
       elem = elem.getParentElement();
 186   
     }
 187  118
     if(linkAttr != null && href != null) {
 188  0
       return e;
 189   
     }
 190   
     else {
 191  118
       return null;
 192   
     }
 193   
   }
 194   
 
 195   
   /**
 196   
    * resolve sets of attributes that are recursively stored in each other
 197   
    *
 198   
    * @param style  the set of attributes containing other sets of attributes
 199   
    */
 200  317
   public static AttributeSet resolveAttributes(AttributeSet style) {
 201  317
     SimpleAttributeSet set = new SimpleAttributeSet();
 202  317
     if(style != null) {
 203  317
       Enumeration names = style.getAttributeNames();
 204  317
       Object value;
 205  317
       Object key;
 206  317
       while(names.hasMoreElements()) {
 207  509
         key = names.nextElement();
 208   
         //System.out.println("Util resolveAttributes key=" + key);
 209  509
         value = style.getAttribute(key);
 210   
         //System.out.println("Util resolveAttributes value=" + value);
 211  509
         if( (!key.equals(StyleConstants.NameAttribute)) &&
 212   
             (!key.equals(StyleConstants.ResolveAttribute)) &&
 213   
             (!key.equals(AttributeSet.ResolveAttribute)) &&
 214   
             (!key.equals(AttributeSet.NameAttribute)))
 215   
         {
 216  183
           set.addAttribute(key, value);
 217   
         }
 218   
         else {
 219  326
           if(key.equals(StyleConstants.ResolveAttribute) ||
 220   
              key.equals(AttributeSet.ResolveAttribute)) {
 221   
             //System.out.println("Util resolveAttributes resolving key=" + key);
 222  43
             set.addAttributes(resolveAttributes((AttributeSet) value));
 223   
           }
 224   
         }
 225   
       }
 226   
     }
 227  317
     return set;
 228   
   }
 229   
 
 230   
   /**
 231   
    * get a name by asking from the user
 232   
    *
 233   
    * <p>Wrapper for JOptionPane with I18N support</p>
 234   
    *
 235   
    * @param initialName  the name initially shown in option pane
 236   
    * @param title  the title to be shown in the option pane
 237   
    * @param text  the text to be shown in the option pane
 238   
    *
 239   
    * @return the entered name or null if action was cancelled
 240   
    */
 241  4
   public static String nameInput(Frame parent, String initialName, String title,
 242   
                                       String text)
 243   
   {
 244  4
     JOptionPane op = new JOptionPane();
 245  4
     Object input = op.showInputDialog(
 246   
         null,
 247   
         FrmMain.dynRes.getResourceString(FrmMain.resources, text),
 248   
         FrmMain.dynRes.getResourceString(FrmMain.resources, title),
 249   
         JOptionPane.QUESTION_MESSAGE,
 250   
         null,
 251   
         null,
 252   
         initialName);
 253  4
     if(input != null) {
 254  4
       return input.toString();
 255   
     }
 256   
     else {
 257  0
       return null;
 258   
     }
 259   
   }
 260   
 
 261   
   /**
 262   
    * Show a message with options to choose from
 263   
    *
 264   
    * <p>Wrapper for JOptionPane with I18N support</p>
 265   
    *
 266   
    * @param options  the options to be shown in the dialog
 267   
    * @param title  the title to be shown in the dialog
 268   
    * @param msg  the message to be shown in the dialog
 269   
    * @param item  a variable part to be shown before msg
 270   
    * @param sep  a separator for msg and item (return or blank etc.)
 271   
    *
 272   
    * @return the choice
 273   
    */
 274  3
   public static int msgChoice(int options, String title, String msg,
 275   
                             String item, String sep)
 276   
   {
 277  3
     String message = item + sep + FrmMain.dynRes.getResourceString(
 278   
         FrmMain.resources, msg);
 279  3
     return JOptionPane.showConfirmDialog(
 280   
           null,
 281   
           message,
 282   
           FrmMain.dynRes.getResourceString(FrmMain.resources, title),
 283   
           options,
 284   
           JOptionPane.QUESTION_MESSAGE);
 285   
   }
 286   
 
 287   
   /**
 288   
    * Show a message with options to choose from
 289   
    *
 290   
    * <p>Wrapper for JOptionPane with I18N support</p>
 291   
    *
 292   
    * @param options  the options to be shown in the dialog
 293   
    * @param title  the title to be shown in the dialog
 294   
    * @param msg  the message to be shown in the dialog
 295   
    * @param item  a variable part to be shown before msg
 296   
    * @param sep  a separator for msg and item (return or blank etc.)
 297   
    *
 298   
    * @return true, if YES was chosen, false if not
 299   
    */
 300  3
   public static boolean msg(int options, String title, String msg,
 301   
                             String item, String sep)
 302   
   {
 303  3
     return (msgChoice(options, title, msg, item, sep) == JOptionPane.YES_OPTION);
 304   
   }
 305   
 
 306   
   /**
 307   
    * get names of all styles for a given tag
 308   
    *
 309   
    * @param styles  the style sheet to look for style names
 310   
    * @param tag  the tag to find style names for
 311   
    *
 312   
    * @return a Vector with all style names found
 313   
    */
 314  81
   public static Vector getStyleNamesForTag(StyleSheet styles, String tag) {
 315  81
     return getStyleClassVector(tag, styles.getStyleNames());
 316   
   }
 317   
 
 318   
   /**
 319   
    * get names of all styles for a given tag
 320   
    *
 321   
    * @param styles  the style sheet to look for style names
 322   
    * @param tag  the tag to find style names for
 323   
    *
 324   
    * @return a Vector with all style names found
 325   
    */
 326  0
   public static Vector getStyleNamesForTag(AttributeSet styles, String tag) {
 327  0
     return getStyleClassVector(tag, styles.getAttributeNames());
 328   
   }
 329   
 
 330  81
   private static Vector getStyleClassVector(String tag, Enumeration e) {
 331  81
     String name;
 332  81
     Vector v = new Vector(0);
 333  81
     while (e.hasMoreElements()) {
 334  4941
       name = (String) e.nextElement();
 335  4941
       if(name.toLowerCase().startsWith(tag + ".")) {
 336   
         //System.out.println("getStyleClassVector adding name '" + name + "'");
 337  0
         v.addElement(name.substring(2));
 338   
       }
 339   
     }
 340  81
     return v;
 341   
   }
 342   
 
 343   
   /**
 344   
    * get the names of all styles found in a given StyleSheet
 345   
    *
 346   
    * @param styles  the StyleSheet to look for style names
 347   
    *
 348   
    * @return a Vector with all names found
 349   
    */
 350  0
   public static Vector getStyleNames(StyleSheet styles) {
 351  0
     Vector styleNames = new Vector(0);
 352  0
     try {
 353  0
       String name;
 354  0
       Enumeration rules = styles.getStyleNames();
 355  0
       while (rules.hasMoreElements()) {
 356  0
         styleNames.addElement((String) rules.nextElement());
 357   
       }
 358   
     }
 359   
     catch (Exception ee) {
 360  0
       Util.errMsg(null, ee.getMessage(), ee);
 361   
     }
 362  0
     return styleNames;
 363   
   }
 364   
 
 365   
   /**
 366   
    * delete a directory with all its contents
 367   
    *
 368   
    * <p>CAUTION: This method deletes all content of the given
 369   
    * directory including all subdirectories and their conent</p>
 370   
    *
 371   
    * @param dir the directory to delete
 372   
    */
 373  10
   public static void deleteDir(File dir) {
 374  10
     if(dir.exists()) {
 375  10
       File[] list = dir.listFiles();
 376  10
       for(int i = 0; i < list.length; i++) {
 377  0
         if(list[i].isDirectory()) {
 378  0
           deleteDir(list[i]);
 379   
         }
 380   
         else {
 381  0
           list[i].delete();
 382   
         }
 383   
       }
 384  10
       dir.delete();
 385   
     }
 386   
   }
 387   
 
 388   
   /**
 389   
    * copies a single file.
 390   
    *
 391   
    * <p>If destFile already exists or if both files are the same
 392   
    * the method does nothing. The complete destination path will be
 393   
    * created before copying, if necessary.</p>
 394   
    *
 395   
    * @param srcFile   the file to copy from
 396   
    * @param destFile  the file to copy to
 397   
    */
 398  3
   public static void copyFile(File srcFile, File destFile)
 399   
               throws FileNotFoundException, IOException
 400   
   {
 401  3
     if(!srcFile.toString().equals(destFile.toString())) {
 402  1
       if(!destFile.exists()) {
 403  1
         RandomAccessFile src;
 404  1
         RandomAccessFile dest;
 405  1
         File destDir;
 406  1
         byte[] buf = new byte[blockSize];
 407  1
         int bytesRead = 0;
 408  1
         src = new RandomAccessFile(srcFile.getPath(),"r");
 409  1
         destDir = new File(destFile.getParent());
 410  1
         destDir.mkdirs();
 411  1
         dest = new RandomAccessFile(destFile.getPath(),"rw");
 412  1
         bytesRead = src.read(buf);
 413  1
         while(bytesRead > -1) {
 414  33
           dest.write(buf,0,bytesRead);
 415  33
           bytesRead = src.read(buf);
 416   
         }
 417  1
         src.close();
 418  1
         dest.close();
 419   
       }
 420  1
       Debug.print("copyFile did nothing 1");
 421   
     }
 422  3
     Debug.print("copyFile did nothing 1");
 423   
   }
 424   
 
 425   
   /**
 426   
    * get the index of a given element in the list of its parents elements.
 427   
    *
 428   
    * @param elem  the element to get the index number for
 429   
    * @return the index of the given element
 430   
    */
 431  1
   public static int getElementIndex(Element elem) {
 432  1
     int i = 0;
 433  1
     Element parent = elem.getParentElement();
 434  1
     if(parent != null) {
 435  1
       int last = parent.getElementCount() - 1;
 436  1
       Element anElem = parent.getElement(i);
 437  1
       if(anElem != elem) {
 438  0
         while((i < last) && (anElem != elem)) {
 439  0
           anElem = parent.getElement(++i);
 440   
         }
 441   
       }
 442   
     }
 443  1
     return i;
 444   
   }
 445   
   /**
 446   
    * Get the path of the class file for a given class.
 447   
    *
 448   
    * <p>This is either a directory of a class file or a directory of
 449   
    * a JAR file. Thus, this class must reside in the same place as
 450   
    * the application in question, not in a separate library
 451   
    * for instance.</p>
 452   
    *
 453   
    * @param cls  the class to get the path for
 454   
    *
 455   
    * @return the path of this class file or the path of the JAR file this class
 456   
    *      file resides in, whatever applies
 457   
    */
 458  75
   public static String getClassFilePath(Class cls)
 459   
   {
 460  75
     int end = 0;
 461  75
     String urlStr = null;
 462  75
     String clsName = cls.getName();
 463  75
     int clsNameLen = clsName.length() + CLASS_EXT.length();
 464  75
     int pos = clsName.lastIndexOf(CLASS_SEPARATOR);
 465  75
     if(pos > -1) {
 466  0
       clsName = clsName.substring(pos + 1);
 467   
     }
 468  75
     clsName = clsName  + CLASS_EXT;
 469  75
     URL url = cls.getResource(clsName);
 470  75
     if(url != null) {
 471  75
       urlStr = url.toString();
 472  75
       pos = urlStr.indexOf(JAR_SEPARATOR);
 473  75
       if(pos > -1) {
 474  0
         urlStr = urlStr.substring(0, pos);
 475  0
         end = urlStr.lastIndexOf(URL_SEPARATOR) + 1;
 476   
       }
 477   
       else {
 478  75
         end = urlStr.length() - clsNameLen;
 479   
       }
 480  75
       pos = urlStr.lastIndexOf(FILE_PREFIX);
 481  75
       if(pos > -1) {
 482  75
         pos +=  FILE_PREFIX.length() + 1;
 483   
       }
 484   
       else {
 485  0
         pos = 0;
 486   
       }
 487  75
       urlStr = urlStr.substring(pos, end);
 488  75
       urlStr = urlStr.replaceAll("%20", " ");
 489   
     }
 490  75
     return urlStr;
 491   
   }
 492   
 
 493   
   /**
 494   
    * quick hack for getting the point value from an attribute value string
 495   
    * (needs to be refined and consolidated with length value)
 496   
    *
 497   
    * @param valStr  the attribute value string to get the point size for
 498   
    *
 499   
    * @return the point size from the given attribute value
 500   
    */
 501  12
   public static float getPtValue(String valStr) {
 502  12
     float len = 0;
 503  12
     int pos = valStr.indexOf(pt);
 504  12
     if(pos > -1) {
 505  11
       unit = pt;
 506  11
       valStr = valStr.substring(0, pos);
 507  11
       len = Float.valueOf(valStr).floatValue();
 508   
     }
 509   
     else {
 510  1
       pos = valStr.indexOf(px);
 511  1
       if(pos > -1) {
 512  0
         unit = px;
 513  0
         valStr = valStr.substring(0, pos);
 514  0
         len = Float.valueOf(valStr).floatValue() * 1.3f;
 515   
       }
 516   
       else {
 517  1
         pos = valStr.indexOf(pct);
 518  1
         if(pos > -1) {
 519  0
           unit = pct;
 520  0
           valStr = valStr.substring(0, pos);
 521   
           //System.out.println("Util.getPtValue valStr=" + valStr);
 522  0
           len = Float.valueOf(valStr).floatValue() / 100f;
 523   
           //System.out.println("Util.getPtValue len=" + len);
 524   
         }
 525   
         else {
 526   
           // assume relative value 1 .. 6
 527  1
           try {
 528  1
             len = Float.valueOf(valStr).floatValue();
 529  1
             unit = pt;
 530   
             /*
 531   
             switch((int) len) {
 532   
               case 1:
 533   
                 len = 8;
 534   
                 break;
 535   
               case 2:
 536   
                 len = 10;
 537   
                 break;
 538   
               case 3:
 539   
                 len = 12;
 540   
                 break;
 541   
               case 4:
 542   
                 len = 14;
 543   
                 break;
 544   
               case 5:
 545   
                 len = 18;
 546   
                 break;
 547   
               case 6:
 548   
                 len = 24;
 549   
                 break;
 550   
               default:
 551   
                 len = len;
 552   
                 break;
 553   
             }
 554   
             */
 555   
           }
 556   
           catch(Exception e) {
 557   
             // unsupported number format (em ex, etc.)
 558   
           }
 559   
         }
 560   
       }
 561   
     }
 562  12
     return len;
 563   
   }
 564   
 
 565   
   /**
 566   
    * get the relative size matching a given point size
 567   
    *
 568   
    * @param valStr  the string with the value attribute
 569   
    * to get the relative size for
 570   
    *
 571   
    * @return the relative size
 572   
    */
 573  4
   public static int getRelativeSize(String valStr) {
 574  4
     float len = 3;
 575  4
     if(valStr.startsWith("+") || valStr.startsWith("-")) {
 576  0
       valStr = valStr.substring(1);
 577   
     }
 578  4
     int pos = valStr.indexOf(pt);
 579  4
     if(pos > -1) {
 580  0
       unit = pt;
 581  0
       valStr = valStr.substring(0, pos);
 582   
     }
 583   
     else {
 584  4
       try {
 585  4
         len = Float.valueOf(valStr).floatValue();
 586   
       }
 587   
       catch(Exception e) {
 588   
         // unsupported number format (em ex, etc.)
 589   
       }
 590   
     }
 591  4
     switch(Integer.parseInt(valStr)) {
 592  0
       case 8:
 593  0
         len = 1;
 594  0
         break;
 595  0
       case 9:
 596  0
         len = 1;
 597  0
         break;
 598  0
       case 10:
 599  0
         len = 2;
 600  0
         break;
 601  0
       case 11:
 602  0
         len = 2;
 603  0
         break;
 604  0
       case 12:
 605  0
         len = 3;
 606  0
         break;
 607  0
       case 13:
 608  0
         len = 3;
 609  0
         break;
 610  4
       case 14:
 611  4
         len = 4;
 612  4
         break;
 613  0
       case 15:
 614  0
         len = 4;
 615  0
         break;
 616  0
       case 16:
 617  0
         len = 4;
 618  0
         break;
 619  0
       case 17:
 620  0
         len = 4;
 621  0
         break;
 622  0
       case 18:
 623  0
         len = 5;
 624  0
         break;
 625  0
       case 19:
 626  0
         len = 5;
 627  0
         break;
 628  0
       case 20:
 629  0
         len = 5;
 630  0
         break;
 631  0
       case 21:
 632  0
         len = 5;
 633  0
         break;
 634  0
       case 22:
 635  0
         len = 5;
 636  0
         break;
 637  0
       case 23:
 638  0
         len = 5;
 639  0
         break;
 640  0
       case 24:
 641  0
         len = 6;
 642  0
         break;
 643   
     }
 644  4
     return (int) len;
 645   
   }
 646   
 
 647   
   /**
 648   
    * get the unit string from the last attribute object which was
 649   
    * converted to a numerical value
 650   
    *
 651   
    * @return the unit string from the last attribute object
 652   
    */
 653  35
   public static String getLastAttrUnit() {
 654  35
     return unit;
 655   
   }
 656   
 
 657   
   /**
 658   
    * get the numerical value for an attribute object
 659   
    *
 660   
    * @param attr  the attribute to get the value from
 661   
    *
 662   
    * @return  the numerical value
 663   
    */
 664  12
   public static float getAttrValue(Object attr) {
 665  12
     float val = -1;
 666  12
     if(attr != null) {
 667  12
       val = getPtValue(attr.toString());
 668   
       //System.out.println("Util.getAttrValue val=" + val);
 669   
     }
 670  12
     return val;
 671   
   }
 672   
 
 673   
   /**
 674   
    * get the absolute value of an attribute
 675   
    *
 676   
    * @param attr  the attribute to get the value from
 677   
    *
 678   
    * @return the absolute numerical value
 679   
    */
 680  35
   public static float getAbsoluteAttrVal(Object attr) {
 681  35
     String valStr = null;
 682  35
     if(attr != null) {
 683  35
       valStr = attr.toString();
 684  35
       int pos = valStr.indexOf(pt);
 685  35
       unit = pt;
 686  35
       if(pos < 0) {
 687  31
         pos = valStr.indexOf(pct);
 688  31
         unit = pct;
 689  31
         if(pos < 0) {
 690  28
           pos = valStr.indexOf(px);
 691   
         }
 692   
       }
 693  35
       if(pos > -1) {
 694  7
         valStr = valStr.substring(0, pos);
 695  7
         return Float.valueOf(valStr).floatValue();
 696   
       }
 697   
       else {
 698  28
         unit = "";
 699   
       }
 700   
     }
 701  28
     try {
 702  28
       return Float.valueOf(valStr).floatValue();
 703   
     }
 704   
     catch(Exception e) {
 705   
       // unsupported number format (em ex, etc.)
 706  0
       return 0f;
 707   
     }
 708   
   }
 709   
 
 710   
   /**
 711   
    * get the row index for a given table cell
 712   
    *
 713   
    * @param cell  the cell element to get the row index for
 714   
    *
 715   
    * @return the row index of the given cell element
 716   
    */
 717  1
   public static int getRowIndex(Element cell) {
 718  1
     Element thisRow = cell.getParentElement();
 719  1
     Element table = thisRow.getParentElement();
 720  1
     int index = 0;
 721  1
     int count = table.getElementCount();
 722  1
     Element elem = table.getElement(index);
 723  1
     while(!elem.equals(thisRow) && index < count) {
 724  0
       elem = table.getElement(++index);
 725   
     }
 726  1
     return index;
 727   
   }
 728   
 
 729   
   /**
 730   
    * Get an arry of strings from a given string having several entries
 731   
    * delimited by blanks.
 732   
    *
 733   
    * <p>In the resource file of SimplyHTML for instance menu bar and menu
 734   
    * definitions are contained as strings having a key for each item.
 735   
    * The keys are delimited with blanks.</p>
 736   
    *
 737   
    * <p>A string "file edit help" from the resource file for instance
 738   
    * would be broken into an array of strings looking as follows</p>
 739   
    *
 740   
    * <p>
 741   
    * String[0]="file"<br>
 742   
    * String[1]="edit"<br>
 743   
    * String[2]="help"
 744   
    * </p>
 745   
    *
 746   
    * @param input  the string to transform into a string array
 747   
    * @return the resulting string array
 748   
    */
 749  901
   public static String[] tokenize(String input, String delim) {
 750  901
     Vector v = new Vector();
 751  901
     StringTokenizer t = new StringTokenizer(input, delim);
 752  901
     String result[];
 753  901
     while (t.hasMoreTokens()) {
 754  9001
       v.addElement(t.nextToken());
 755   
     }
 756  901
     result = new String[v.size()];
 757  901
     for (int i = 0; i < result.length; i++) {
 758  9001
       result[i] = (String) v.elementAt(i);
 759   
     }
 760  901
     return result;
 761   
   }
 762   
 
 763   
   /**
 764   
    * write a message with a time stamp to System.out and remember
 765   
    * the time stamp in a LIFO Vector
 766   
    */
 767  0
   public static void msgStart(String startMsg) {
 768  0
     long startTime = System.currentTimeMillis();
 769  0
     startTimes.addElement(new Long(startTime));
 770   
     //System.out.println(startMsg + " startTime=" + startTime);
 771   
   }
 772   
 
 773   
   /**
 774   
    * find the first occurrence of an <code>Element</code> in the
 775   
    * element tree above a given <code>Element</code>
 776   
    *
 777   
    * @param name the name of the <code>Element</code> to search for
 778   
    * @param parent the <code>Element</code> to start looking
 779   
    *
 780   
    * @return the found <code>Element</code> or null if none is found
 781   
    */
 782  1384
   public static Element findElementUp(String name, Element start) {
 783  1384
     Element elem = start;
 784  1384
     while((elem != null) && (!elem.getName().equalsIgnoreCase(name))) {
 785  5482
       elem = elem.getParentElement();
 786   
     }
 787  1384
     return elem;
 788   
   }
 789   
 
 790   
   /**
 791   
    * find the first occurrence of an <code>Element</code> in the
 792   
    * element tree below a given <code>Element</code>
 793   
    *
 794   
    * @param name the name of the <code>Element</code> to search for
 795   
    * @param parent the <code>Element</code> to start looking
 796   
    *
 797   
    * @return the found <code>Element</code> or null if none is found
 798   
    */
 799  163
   public static Element findElementDown(String name, Element parent) {
 800  163
     Element foundElement = null;
 801  163
     ElementIterator eli = new ElementIterator(parent);
 802  163
     Element thisElement = eli.first();
 803  163
     while(thisElement != null && foundElement == null) {
 804  930
       if(thisElement.getName().equalsIgnoreCase(name)) {
 805  5
         foundElement = thisElement;
 806   
       }
 807  930
       thisElement = eli.next();
 808   
     }
 809  163
     return foundElement;
 810   
   }
 811   
 
 812   
   /**
 813   
    * convenience method for adding a component to a container
 814   
    * layed out by a GridBagLayout
 815   
    *
 816   
    * @param container  the container to add a component to
 817   
    * @param comp  the component to add to container
 818   
    * @param g  the GridBagLayout associated with container
 819   
    * @param c  the GridBagConstraints to use
 820   
    * @param gx  the value to use for GridBagConstraints.gridx
 821   
    * @param gy  the value to use for GridBagConstraints.gridy
 822   
    * @param a  the value to use for GridBagConstraints.anchor
 823   
    */
 824  127
   public static void addGridBagComponent(JComponent container, JComponent comp,
 825   
         GridBagLayout g, GridBagConstraints c, int gx, int gy, int a)
 826   
   {
 827   
     /*
 828   
     c.gridx = gx;
 829   
     c.gridy = gy;
 830   
     c.anchor = a;
 831   
     c.insets = new Insets(2, 2, 2, 2);
 832   
     c.ipadx = 2;
 833   
     c.ipady = 2;
 834   
     g.setConstraints(comp, c);
 835   
     container.add(comp);
 836   
     */
 837  127
     addGridBagComponent(container, comp, g, c, gx, gy, a, 1, 1, GridBagConstraints.NONE, 0, 0);
 838   
   }
 839   
 
 840   
   /**
 841   
    * convenience method for adding a component to a container
 842   
    * layed out by a GridBagLayout
 843   
    *
 844   
    * @param container  the container to add a component to
 845   
    * @param comp  the component to add to container
 846   
    * @param g  the GridBagLayout associated with container
 847   
    * @param c  the GridBagConstraints to use
 848   
    * @param gx  the value to use for GridBagConstraints.gridx
 849   
    * @param gy  the value to use for GridBagConstraints.gridy
 850   
    * @param a  the value to use for GridBagConstraints.anchor
 851   
    * @param gw  the value to use for GridBagConstraints.gridwidth
 852   
    * @param gh  teh value to use for GridBagConstraints.gridheight
 853   
    */
 854  0
   public static void addGridBagComponent(JComponent container, JComponent comp,
 855   
         GridBagLayout g, GridBagConstraints c, int gx, int gy, int a, int gw, int gh)
 856   
   {
 857  0
     addGridBagComponent(container, comp, g, c, gx, gy, a, gw, gh, GridBagConstraints.NONE, 0, 0);
 858   
   }
 859   
 
 860   
   /**
 861   
    * convenience method for adding a component to a container
 862   
    * layed out by a GridBagLayout
 863   
    *
 864   
    * @param container  the container to add a component to
 865   
    * @param comp  the component to add to container
 866   
    * @param g  the GridBagLayout associated with container
 867   
    * @param c  the GridBagConstraints to use
 868   
    * @param gx  the value to use for GridBagConstraints.gridx
 869   
    * @param gy  the value to use for GridBagConstraints.gridy
 870   
    * @param a  the value to use for GridBagConstraints.anchor
 871   
    * @param gw  the value to use for GridBagConstraints.gridwidth
 872   
    * @param gh  teh value to use for GridBagConstraints.gridheight
 873   
    * @param f  the value to use for GridBagConstraints.fill
 874   
    */
 875  0
   public static void addGridBagComponent(JComponent container, JComponent comp,
 876   
         GridBagLayout g, GridBagConstraints c, int gx, int gy, int a, int gw, int gh, int f)
 877   
   {
 878  0
     addGridBagComponent(container, comp, g, c, gx, gy, a, gw, gh, GridBagConstraints.NONE, 0, 0);
 879   
   }
 880   
 
 881   
   /**
 882   
    * convenience method for adding a component to a container
 883   
    * layed out by a GridBagLayout
 884   
    *
 885   
    * @param container  the container to add a component to
 886   
    * @param comp  the component to add to container
 887   
    * @param g  the GridBagLayout associated with container
 888   
    * @param c  the GridBagConstraints to use
 889   
    * @param gx  the value to use for GridBagConstraints.gridx
 890   
    * @param gy  the value to use for GridBagConstraints.gridy
 891   
    * @param a  the value to use for GridBagConstraints.anchor
 892   
    * @param gw  the value to use for GridBagConstraints.gridwidth
 893   
    * @param gh  teh value to use for GridBagConstraints.gridheight
 894   
    * @param f  the value to use for GridBagConstraints.fill
 895   
    * @param wx  the value to use for GridBagConstraints.weightx
 896   
    * @param wy  the value to use for GridBagConstraints.weighty
 897   
    */
 898  131
   public static void addGridBagComponent(JComponent container, JComponent comp,GridBagLayout g,
 899   
       GridBagConstraints c, int gx, int gy, int a, int gw, int gh, int f, double wx, double wy)
 900   
   {
 901  131
     c.gridx = gx;
 902  131
     c.gridy = gy;
 903  131
     c.anchor = a;
 904  131
     c.insets = new Insets(2, 2, 2, 2);
 905  131
     c.ipadx = 2;
 906  131
     c.ipady = 2;
 907  131
     c.gridwidth = gw;
 908  131
     c.gridheight = gh;
 909  131
     c.fill = f;
 910  131
     c.weightx = wx;
 911  131
     c.weighty = wy;
 912  131
     g.setConstraints(comp, c);
 913  131
     container.add(comp);
 914   
   }
 915   
   /**
 916   
    * resolve a relative URL string against an absolute URL string.
 917   
    *
 918   
    * <p>the absolute URL string is the start point for the
 919   
    * relative path.</p>
 920   
    *
 921   
    * <p><b>Example:</b></p>
 922   
    * <pre>
 923   
    *   absolute path:  file:/d:/eigene dateien/eigene bilder/
 924   
    *   relative path:  ../images/test.jpg
 925   
    *   result:         file:/d:/eigene dateien/images/test.jpg
 926   
    * </pre>
 927   
    *
 928   
    * @param relPath  the relative URL string to resolve
 929   
    * @param absPath  the absolute URL string to start at
 930   
    *
 931   
    * @return the absolute URL string resulting from resolving relPath
 932   
    *    against absPath
 933   
    */
 934  0
   public static String resolveRelativePath(String relPath, String absPath) {
 935  0
     String newAbsPath = absPath;
 936  0
     String newRelPath = relPath;
 937  0
     if(absPath.endsWith(URL_SEPARATOR)) {
 938  0
       newAbsPath = absPath.substring(0, absPath.length()-1);
 939   
     }
 940  0
     int relPos = newRelPath.indexOf(RELATIVE_PREFIX);
 941  0
     while(relPos > -1) {
 942  0
       newRelPath = newRelPath.substring(relPos + RELATIVE_PREFIX.length());
 943  0
       newAbsPath = newAbsPath.substring(0, newAbsPath.lastIndexOf(URL_SEPARATOR));
 944  0
       relPos = newRelPath.indexOf(RELATIVE_PREFIX);
 945   
     }
 946  0
     if(newRelPath.startsWith(URL_SEPARATOR)) {
 947  0
       return newAbsPath + newRelPath;
 948   
     } else {
 949  0
       return newAbsPath + URL_SEPARATOR + newRelPath;
 950   
     }
 951   
   }
 952   
 
 953   
   /**
 954   
    * get the path to a given file relative to a given directory
 955   
    *
 956   
    * @param fromDir  the directory having the file from which the link refers
 957   
    * @param toDir  the directory to which a link refers
 958   
    *
 959   
    * @return the relative path
 960   
    */
 961  0
   public static String getRelativePath(File fromDir, File toFile) {
 962  0
     String fromStr = fromDir.getAbsolutePath();
 963  0
     if(!fromStr.endsWith(File.separator)) {
 964  0
       fromStr = fromStr + File.separator;
 965   
     }
 966  0
     String toStr = toFile.getAbsolutePath();
 967  0
     int pos = fromStr.indexOf(File.separator);
 968  0
     int fromLen = fromStr.length();
 969  0
     int toLen = toStr.length();
 970  0
     int oldPos = pos;
 971  0
     while( (pos > -1) &&
 972   
            (pos < fromLen) &&
 973   
            (pos < toLen) &&
 974   
            (fromStr.substring(0, pos).equalsIgnoreCase(toStr.substring(0, pos)))  )
 975   
     {
 976  0
       oldPos = pos + 1;
 977  0
       pos = fromStr.indexOf(File.separator, oldPos);
 978   
     }
 979  0
     int samePos = oldPos;
 980   
 
 981  0
     int level = 0;
 982  0
     while(pos > -1) {
 983  0
       ++level;
 984  0
       oldPos = pos + 1;
 985  0
       pos = fromStr.indexOf(File.separator, oldPos);
 986   
     }
 987  0
     StringBuffer relPath = new StringBuffer();
 988  0
     if(level > 0) {
 989  0
       for(int i = 0; i < level; i++) {
 990  0
         relPath.append("..");
 991  0
         relPath.append(File.separator);
 992   
       }
 993   
     }
 994  0
     relPath.append(toStr.substring(samePos));
 995  0
     return relPath.toString().replace(File.separatorChar, URL_SEPARATOR_CHAR);
 996   
   }
 997   
 
 998   
   /**
 999   
    * show an error message and print a stack trace to the console if
 1000   
    * in development mode (DEV_MODE = true)
 1001   
    *
 1002   
    * @param owner the owner of the message, or null
 1003   
    * @param msg the message to display, or null
 1004   
    * @param e the exception object describing the error, or null
 1005   
    */
 1006  0
   public static void errMsg(Component owner, String msg, Exception e) {
 1007  0
     if(msg != null) {
 1008  0
       JOptionPane.showMessageDialog(owner, msg, ERR_TITLE, JOptionPane.ERROR_MESSAGE);
 1009   
     }
 1010  0
     if(e != null) {
 1011  0
       e.printStackTrace();
 1012   
     }
 1013   
   }
 1014   
 
 1015   
   /**
 1016   
    * center a <code>Component</code> relative to
 1017   
    * another <code>Component</code>.
 1018   
    *
 1019   
    * @param parent  the <code>Component</code> to be used as the
 1020   
    *                  basis for centering
 1021   
    * @param comp  the <code>Component</code> to be centered within parent
 1022   
    *
 1023   
    */
 1024  10
   public static void center(Component parent, Component comp) {
 1025  10
     Dimension cSize = comp.getPreferredSize();
 1026  10
     Dimension fSize = parent.getSize();
 1027  10
     Point loc = parent.getLocation();
 1028  10
     comp.setLocation((fSize.width - cSize.width) / 2 + loc.x,
 1029   
                             (fSize.height - cSize.height) / 2 + loc.y);
 1030   
   }
 1031   
 
 1032   
   /**
 1033   
    * get a StyleSheet object for using its utility methods
 1034   
    */
 1035  48
   public static StyleSheet styleSheet() {
 1036  48
     return s;
 1037   
   }
 1038   
 
 1039   
   /**
 1040   
    * remove all occurrences of a given char from a given string
 1041   
    *
 1042   
    * @param src the string to remove from
 1043   
    * @param c  the char to remove
 1044   
    *
 1045   
    * @return a string copy of src with all occurrences of c removed
 1046   
    */
 1047  3
   public static String removeChar(String src, char c) {
 1048  3
     StringBuffer buf = new StringBuffer();
 1049  3
     int start = 0;
 1050  3
     int pos = src.indexOf(c);
 1051  3
     while((pos > -1) && (start < src.length())) {
 1052  6
       pos = src.indexOf(c, start);
 1053  6
       if((pos > -1) && (start < src.length())) {
 1054  3
         buf.append(src.substring(start, pos));
 1055  3
         start = pos + 1;
 1056   
       }
 1057   
     }
 1058  3
     if(start < src.length()) {
 1059  3
       buf.append(src.substring(start));
 1060   
     }
 1061  3
     if(buf.length() == 0) {
 1062  0
       buf.append(src);
 1063   
     }
 1064  3
     return buf.toString();
 1065   
   }
 1066   
 }