Example #1
0
  public static void main(String[] args) throws PatternSyntaxException {
    Scanner in = new Scanner(System.in);
    System.out.println("Enter pattern: ");
    String patternString = in.nextLine();

    Pattern pattern = Pattern.compile(patternString);

    while (true) {
      System.out.println("Enter string to match: ");
      String input = in.nextLine();
      if (input == null || input.equals("")) return;
      Matcher matcher = pattern.matcher(input);
      if (matcher.matches()) {
        System.out.println("Match");
        int g = matcher.groupCount();
        if (g > 0) {
          for (int i = 0; i < input.length(); i++) {
            // Print any empty groups
            for (int j = 1; j <= g; j++)
              if (i == matcher.start(j) && i == matcher.end(j)) System.out.print("()");
            // Print ( for non-empty groups starting here
            for (int j = 1; j <= g; j++)
              if (i == matcher.start(j) && i != matcher.end(j)) System.out.print('(');
            System.out.print(input.charAt(i));
            // Print ) for non-empty groups ending here
            for (int j = 1; j <= g; j++)
              if (i + 1 != matcher.start(j) && i + 1 == matcher.end(j)) System.out.print(')');
          }
          System.out.println();
        }
      } else System.out.println("No match");
    }
  }
Example #2
0
 protected RichText.Part text(PState s, String text, Map<? extends Attribute, ?> attrs)
     throws IOException {
   RichText.Part ret = null;
   int p = 0;
   while (true) {
     Matcher m = urlpat.matcher(text);
     if (!m.find(p)) break;
     URL url;
     try {
       String su = text.substring(m.start(), m.end());
       if (su.indexOf(':') < 0) su = "http://" + su;
       url = new URL(su);
     } catch (java.net.MalformedURLException e) {
       p = m.end();
       continue;
     }
     RichText.Part lead = new RichText.TextPart(text.substring(0, m.start()), attrs);
     if (ret == null) ret = lead;
     else ret.append(lead);
     Map<Attribute, Object> na = new HashMap<Attribute, Object>(attrs);
     na.putAll(urlstyle);
     na.put(ChatAttribute.HYPERLINK, new FuckMeGentlyWithAChainsaw(url));
     ret.append(new RichText.TextPart(text.substring(m.start(), m.end()), na));
     p = m.end();
   }
   if (ret == null) ret = new RichText.TextPart(text, attrs);
   else ret.append(new RichText.TextPart(text.substring(p), attrs));
   return (ret);
 }
  /**
   * Strips all non-article links from the given markup; anything like [[this]] is removed unless it
   * goes to a wikipedia article, redirect, or disambiguation page.
   *
   * @param markup the text to be stripped
   * @return the stripped text
   */
  public static String stripIsolatedLinks(String markup) {

    Vector<Integer> linkStack = new Vector<Integer>();

    Pattern p = Pattern.compile("(\\[\\[|\\]\\])");
    Matcher m = p.matcher(markup);

    StringBuffer sb = new StringBuffer();
    int lastIndex = 0;

    while (m.find()) {
      String tag = markup.substring(m.start(), m.end());

      if (tag.equals("[[")) linkStack.add(m.start());
      else {
        if (!linkStack.isEmpty()) {
          int linkStart = linkStack.lastElement();
          linkStack.remove(linkStack.size() - 1);

          if (linkStack.isEmpty()) {
            sb.append(markup.substring(lastIndex, linkStart));

            // we have the whole link, with other links nested inside if it's an image
            String linkMarkup = markup.substring(linkStart + 2, m.start());

            // System.out.println(" - " + linkStart + ", " + m.end() + ", " + markup.length()) ;

            if (markup.substring(Math.max(0, linkStart - 10), linkStart).matches("(?s).*(\\W*)\n")
                && (m.end() >= markup.length() - 1
                    || markup
                        .substring(m.end(), Math.min(markup.length() - 1, m.end() + 10))
                        .matches("(?s)(\\W*)(\n.*|$)"))) {
              // discarding link
            } else {
              sb.append("[[");
              sb.append(linkMarkup);
              sb.append("]]");
            }

            lastIndex = m.end();
          }
        }
      }
    }

    if (!linkStack.isEmpty())
      System.err.println(
          "MarkupStripper | Warning: links were not well formed, so we cannot guarantee that they were stripped out correctly. ");

    sb.append(markup.substring(lastIndex));
    return sb.toString();
  }
Example #4
0
  public URLFinder(String text) {
    Matcher matcher = dfPattern.matcher(text);
    urls = new ArrayList<String>();
    locations = new ArrayList<Integer[]>();

    while (matcher.find()) {
      urls.add(matcher.group(1));
      locations.add(new Integer[] {matcher.start(1), matcher.end(1)});
    }
  }
  /**
   * Strips all links from the given markup; anything like [[this]] is replaced. If it is a link to
   * a wikipedia article, then it is replaced with its anchor text. Only links to images are treated
   * differently: they are discarded entirely.
   *
   * <p>You may want to first strip non-article links, isolated links, category links etc before
   * calling this method.
   *
   * @param markup the text to be stripped
   * @return the stripped text
   */
  public static String stripLinks(String markup) {

    HashSet<String> discardPrefixes = new HashSet<String>();
    discardPrefixes.add("image");

    Vector<Integer> linkStack = new Vector<Integer>();

    Pattern p = Pattern.compile("(\\[\\[|\\]\\])");
    Matcher m = p.matcher(markup);

    StringBuffer sb = new StringBuffer();
    int lastIndex = 0;

    while (m.find()) {
      String tag = markup.substring(m.start(), m.end());

      if (tag.equals("[[")) linkStack.add(m.start());
      else {
        if (!linkStack.isEmpty()) {
          int linkStart = linkStack.lastElement();
          linkStack.remove(linkStack.size() - 1);

          if (linkStack.isEmpty()) {
            sb.append(markup.substring(lastIndex, linkStart));

            // we have the whole link, with other links nested inside if it's an image
            String linkMarkup = markup.substring(linkStart + 2, m.start());
            sb.append(stripLink(linkMarkup, discardPrefixes, false));

            lastIndex = m.end();
          }
        }
      }
    }

    if (!linkStack.isEmpty()) {
      System.err.println(
          "MarkupStripper | Warning: links were not well formed, so we cannot guarantee that they were stripped out correctly. ");
    }

    sb.append(markup.substring(lastIndex));
    return sb.toString();
  }
  /**
   * Removes all sections (both header and content) with the given sectionName
   *
   * @param sectionName the name of the section (case insensitive) to remove.
   * @param markup the markup to be stripped
   * @return the stripped markup
   */
  public static String stripSection(String markup, String sectionName) {

    Pattern p =
        Pattern.compile(
            "(={2,})\\s*" + sectionName + "\\s*\\1.*?([^=]\\1[^=])",
            Pattern.CASE_INSENSITIVE + Pattern.DOTALL);
    Matcher m = p.matcher(markup);

    StringBuffer sb = new StringBuffer();
    int lastIndex = 0;

    while (m.find()) {
      sb.append(markup.substring(lastIndex, m.start()));
      sb.append(m.group(2));
      lastIndex = m.end();
    }

    sb.append(markup.substring(lastIndex));
    markup = sb.toString();

    // if this was the last section in the doc, then it won't be discarded because we can't tell
    // where it ends.
    // best we can do is delete the title and the paragraph below it.

    p =
        Pattern.compile(
            "(={2,})\\s*" + sectionName + "\\s*\\1\\W*.*?\n\n",
            Pattern.CASE_INSENSITIVE + Pattern.DOTALL);
    m = p.matcher(markup);

    sb = new StringBuffer();
    lastIndex = 0;

    while (m.find()) {
      sb.append(markup.substring(lastIndex, m.start()));
      lastIndex = m.end() - 2;
    }

    sb.append(markup.substring(lastIndex));
    return sb.toString();
  }
  /**
   * Strips all templates from the given markup; anything like {{this}}.
   *
   * @param markup the text to be stripped
   * @return the stripped text
   */
  public static String stripTemplates(String markup) {

    Vector<Integer> templateStack = new Vector<Integer>();

    Pattern p = Pattern.compile("(\\{\\{|\\}\\})");
    Matcher m = p.matcher(markup);

    StringBuffer sb = new StringBuffer();
    int lastIndex = 0;

    while (m.find()) {

      String tag = markup.substring(m.start(), m.end());

      if (tag.equals("{{")) templateStack.add(m.start());
      else {
        if (!templateStack.isEmpty()) {
          int templateStart = templateStack.lastElement();
          templateStack.remove(templateStack.size() - 1);

          if (templateStack.isEmpty()) {
            sb.append(markup.substring(lastIndex, templateStart));

            // TODO: here is where we would resolve a template, instead of just removing it.
            // sb.append(stripTemplate(markup.substring(templateStart+2, m.start()))) ;

            // we have the whole template, with other templates nested inside
            lastIndex = m.end();
          }
        }
      }
    }

    if (!templateStack.isEmpty())
      System.err.println(
          "MarkupStripper | Warning: templates were not well formed, so we cannot guarantee that they were stripped out correctly. ");

    sb.append(markup.substring(lastIndex));
    return sb.toString();
  }
  private static List<String> findQuotedArguments(String command) {
    List<String> arguments = new ArrayList<>();

    Pattern pattern = Pattern.compile("\".*?\"");
    Matcher matcher = pattern.matcher(command);

    while (matcher.find()) {
      String argument = command.substring(matcher.start(), matcher.end());
      argument = unquote(argument);
      argument = argument.trim();
      arguments.add(argument);
    }
    return arguments;
  }
  /**
   * Removes all section headers.
   *
   * @param markup the text to be stripped
   * @return the stripped markup
   */
  public static String stripHeadings(String markup) {
    Pattern p = Pattern.compile("(={2,})([^=]+)(\\1)");
    Matcher m = p.matcher(markup);

    StringBuffer sb = new StringBuffer();
    int lastIndex = 0;

    while (m.find()) {
      sb.append(markup.substring(lastIndex, m.start()));
      lastIndex = m.end();
    }

    sb.append(markup.substring(lastIndex));
    return sb.toString();
  }
 public synchronized String format(String message) {
   Matcher matcher = variablePattern.matcher(message);
   while (matcher.find()) {
     String variable = matcher.group();
     variable = variable.substring(1);
     if (variable.startsWith("{") && variable.endsWith("}"))
       variable = variable.substring(1, variable.length() - 1);
     String value = variables.get(variable);
     if (value == null) value = "";
     message =
         message.replaceFirst(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value));
   }
   matcher = colorPattern.matcher(message);
   while (matcher.find())
     message =
         message.substring(0, matcher.start()) + "\247" + message.substring(matcher.end() - 1);
   return message;
 }
  /**
   * Removes anything at the start of the markup that is indented. Normally this indicates notes
   * that the author should have used a template for, such as a "For other uses, see ****" note.
   *
   * @param markup the text to be stripped
   * @return the stripped markup
   */
  public static String stripIndentedStart(String markup) {

    Pattern p = Pattern.compile("(.*?)\n", Pattern.DOTALL);
    Matcher m = p.matcher(markup);

    StringBuffer sb = new StringBuffer();
    int newStart = 0;

    while (m.find()) {
      // System.out.println(" - \"" + m.group() + "\"\n\n") ;

      if (m.group().matches("(?s)([\\s\\W]*)([\\:\\*]+)(.*)") || m.group().matches("\\W*"))
        newStart = m.end();
      else break;
    }

    sb.append(markup.substring(newStart));
    return sb.toString();
  }
Example #12
0
 /**
  * Replace occurrences of "%ab" with the character represented by the hex value. Strings of
  * escaped characters are treated as UTF-8 byte sequences and decoded appropriately.
  */
 private static String decode(String s) {
   int length = s.length();
   StringBuilder str = new StringBuilder(length);
   Matcher matcher = PATTERN.matcher(s);
   int offset = 0;
   byte[] bb = null;
   while (matcher.find(offset)) {
     int count = matcher.groupCount();
     for (int i = 0; i < count; i++) {
       String match = matcher.group(0);
       int num = match.length() / 3;
       if (bb == null || bb.length < num) {
         bb = new byte[num];
       }
       for (int j = 0; j < num; j++) {
         int head = j * 3 + 1;
         int tail = head + 2;
         bb[j] = (byte) Integer.parseInt(match.substring(head, tail), 16);
       }
       try {
         String text = new String(bb, "UTF-8");
         str.append(s.substring(offset, matcher.start()));
         str.append(text);
       } catch (UnsupportedEncodingException e) {
         // NOTE: This should *never* be thrown because all
         //       JVMs are required to support UTF-8. I mean,
         //       the strings in the .class file are all in
         //       a modified UTF-8, for pete's sake! :)
       }
     }
     offset = matcher.end();
   }
   if (offset < length) {
     str.append(s.substring(offset));
   }
   return str.toString();
 }
Example #13
0
  /** Performs the subsequent ReTrace operations. */
  public void execute() throws IOException {
    // Read the mapping file.
    MappingReader mappingReader = new MappingReader(mappingFile);
    mappingReader.pump(this);

    StringBuffer expressionBuffer = new StringBuffer(regularExpression.length() + 32);
    char[] expressionTypes = new char[32];
    int expressionTypeCount = 0;
    int index = 0;
    while (true) {
      int nextIndex = regularExpression.indexOf('%', index);
      if (nextIndex < 0
          || nextIndex == regularExpression.length() - 1
          || expressionTypeCount == expressionTypes.length) {
        break;
      }

      expressionBuffer.append(regularExpression.substring(index, nextIndex));
      expressionBuffer.append('(');

      char expressionType = regularExpression.charAt(nextIndex + 1);
      switch (expressionType) {
        case 'c':
          expressionBuffer.append(REGEX_CLASS);
          break;

        case 'C':
          expressionBuffer.append(REGEX_CLASS_SLASH);
          break;

        case 'l':
          expressionBuffer.append(REGEX_LINE_NUMBER);
          break;

        case 't':
          expressionBuffer.append(REGEX_TYPE);
          break;

        case 'f':
          expressionBuffer.append(REGEX_MEMBER);
          break;

        case 'm':
          expressionBuffer.append(REGEX_MEMBER);
          break;

        case 'a':
          expressionBuffer.append(REGEX_ARGUMENTS);
          break;
      }

      expressionBuffer.append(')');

      expressionTypes[expressionTypeCount++] = expressionType;

      index = nextIndex + 2;
    }

    expressionBuffer.append(regularExpression.substring(index));

    Pattern pattern = Pattern.compile(expressionBuffer.toString());

    // Read the stack trace file.
    LineNumberReader reader =
        new LineNumberReader(
            stackTraceFile == null
                ? (Reader) new InputStreamReader(System.in)
                : (Reader) new BufferedReader(new FileReader(stackTraceFile)));

    try {
      StringBuffer outLine = new StringBuffer(256);
      List extraOutLines = new ArrayList();

      String className = null;

      // Read the line in the stack trace.
      while (true) {
        String line = reader.readLine();
        if (line == null) {
          break;
        }

        Matcher matcher = pattern.matcher(line);

        if (matcher.matches()) {
          int lineNumber = 0;
          String type = null;
          String arguments = null;

          // Figure out a class name, line number, type, and
          // arguments beforehand.
          for (int expressionTypeIndex = 0;
              expressionTypeIndex < expressionTypeCount;
              expressionTypeIndex++) {
            int startIndex = matcher.start(expressionTypeIndex + 1);
            if (startIndex >= 0) {
              String match = matcher.group(expressionTypeIndex + 1);

              char expressionType = expressionTypes[expressionTypeIndex];
              switch (expressionType) {
                case 'c':
                  className = originalClassName(match);
                  break;

                case 'C':
                  className = originalClassName(ClassUtil.externalClassName(match));
                  break;

                case 'l':
                  lineNumber = Integer.parseInt(match);
                  break;

                case 't':
                  type = originalType(match);
                  break;

                case 'a':
                  arguments = originalArguments(match);
                  break;
              }
            }
          }

          // Actually construct the output line.
          int lineIndex = 0;

          outLine.setLength(0);
          extraOutLines.clear();

          for (int expressionTypeIndex = 0;
              expressionTypeIndex < expressionTypeCount;
              expressionTypeIndex++) {
            int startIndex = matcher.start(expressionTypeIndex + 1);
            if (startIndex >= 0) {
              int endIndex = matcher.end(expressionTypeIndex + 1);
              String match = matcher.group(expressionTypeIndex + 1);

              // Copy a literal piece of input line.
              outLine.append(line.substring(lineIndex, startIndex));

              char expressionType = expressionTypes[expressionTypeIndex];
              switch (expressionType) {
                case 'c':
                  className = originalClassName(match);
                  outLine.append(className);
                  break;

                case 'C':
                  className = originalClassName(ClassUtil.externalClassName(match));
                  outLine.append(ClassUtil.internalClassName(className));
                  break;

                case 'l':
                  lineNumber = Integer.parseInt(match);
                  outLine.append(match);
                  break;

                case 't':
                  type = originalType(match);
                  outLine.append(type);
                  break;

                case 'f':
                  originalFieldName(className, match, type, outLine, extraOutLines);
                  break;

                case 'm':
                  originalMethodName(
                      className, match, lineNumber, type, arguments, outLine, extraOutLines);
                  break;

                case 'a':
                  arguments = originalArguments(match);
                  outLine.append(arguments);
                  break;
              }

              // Skip the original element whose processed version
              // has just been appended.
              lineIndex = endIndex;
            }
          }

          // Copy the last literal piece of input line.
          outLine.append(line.substring(lineIndex));

          // Print out the main line.
          System.out.println(outLine);

          // Print out any additional lines.
          for (int extraLineIndex = 0; extraLineIndex < extraOutLines.size(); extraLineIndex++) {
            System.out.println(extraOutLines.get(extraLineIndex));
          }
        } else {
          // Print out the original line.
          System.out.println(line);
        }
      }
    } catch (IOException ex) {
      throw new IOException("Can't read stack trace (" + ex.getMessage() + ")");
    } finally {
      if (stackTraceFile != null) {
        try {
          reader.close();
        } catch (IOException ex) {
          // This shouldn't happen.
        }
      }
    }
  }
Example #14
0
  private Map<String, com.sun.jdi.connect.Connector.Argument> parseConnectorArgs(
      Connector connector, String argString) {
    Map<String, com.sun.jdi.connect.Connector.Argument> arguments = connector.defaultArguments();

    /*
     * We are parsing strings of the form:
     *    name1=value1,[name2=value2,...]
     * However, the value1...valuen substrings may contain
     * embedded comma(s), so make provision for quoting inside
     * the value substrings. (Bug ID 4285874)
     */
    String regexPattern =
        "(quote=[^,]+,)|"
            + // special case for quote=.,
            "(\\w+=)"
            + // name=
            "(((\"[^\"]*\")|"
            + //   ( "l , ue"
            "('[^']*')|"
            + //     'l , ue'
            "([^,'\"]+))+,)"; //     v a l u e )+ ,
    Pattern p = Pattern.compile(regexPattern);
    Matcher m = p.matcher(argString);
    while (m.find()) {
      int startPosition = m.start();
      int endPosition = m.end();
      if (startPosition > 0) {
        /*
         * It is an error if parsing skips over any part of argString.
         */
        throw new IllegalArgumentException(
            MessageOutput.format("Illegal connector argument", argString));
      }

      String token = argString.substring(startPosition, endPosition);
      int index = token.indexOf('=');
      String name = token.substring(0, index);
      String value = token.substring(index + 1, token.length() - 1); // Remove comma delimiter

      /*
       * for values enclosed in quotes (single and/or double quotes)
       * strip off enclosing quote chars
       * needed for quote enclosed delimited substrings
       */
      if (name.equals("options")) {
        StringBuilder sb = new StringBuilder();
        for (String s : splitStringAtNonEnclosedWhiteSpace(value)) {
          while (isEnclosed(s, "\"") || isEnclosed(s, "'")) {
            s = s.substring(1, s.length() - 1);
          }
          sb.append(s);
          sb.append(" ");
        }
        value = sb.toString();
      }

      Connector.Argument argument = arguments.get(name);
      if (argument == null) {
        throw new IllegalArgumentException(
            MessageOutput.format(
                "Argument is not defined for connector:", new Object[] {name, connector.name()}));
      }
      argument.setValue(value);

      argString = argString.substring(endPosition); // Remove what was just parsed...
      m = p.matcher(argString); //    and parse again on what is left.
    }
    if ((!argString.equals(",")) && (argString.length() > 0)) {
      /*
       * It is an error if any part of argString is left over,
       * unless it was empty to begin with.
       */
      throw new IllegalArgumentException(
          MessageOutput.format("Illegal connector argument", argString));
    }
    return arguments;
  }
Example #15
0
    @Override
    protected int drawUnselectedText(Graphics graphics, int x, int y, int p0, int p1)
        throws BadLocationException {
      try {

        Document doc = getDocument();
        String text = doc.getText(p0, p1 - p0);

        Segment segment = getLineBuffer();
        int initialXpos = x;

        SortedMap<Integer, Integer> startMap = new TreeMap<Integer, Integer>();
        SortedMap<Integer, Color> colorMap = new TreeMap<Integer, Color>();

        // Match all regexes on this snippet, store positions
        for (Map.Entry<Pattern, Color> entry : patternColors.entrySet()) {

          Matcher matcher = entry.getKey().matcher(text);

          while (matcher.find()) {
            startMap.put(matcher.start(1), matcher.end(1));
            colorMap.put(matcher.start(1), entry.getValue());
          }
        }

        // TODO: check the map for overlapping parts

        int i = 0;
        // add tag highlighted background colors
        if (!TAG_HIGHLIGHTED.isEmpty()) {
          Matcher highlightMatcher = Pattern.compile(TAG_HIGHLIGHTED).matcher(text);
          while (highlightMatcher.find()) {
            int start = highlightMatcher.start(1);
            int end = highlightMatcher.end(1);
            if (i < start) {
              graphics.setColor(Color.black);
              doc.getText(p0 + i, start - i, segment);
              x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
            }
            graphics.setColor(TAG_HIGHLIGHTED_COLOR);
            i = end;
            doc.getText(p0 + start, i - start, segment);
            int width =
                Utilities.getTabbedTextWidth(
                    segment, graphics.getFontMetrics(), x, this, p0 + start);
            // graphics.drawLine(x, y, width, y);graphics.getFontMetrics()
            graphics.fillRect(
                x,
                y - graphics.getFontMetrics().getHeight() + 2,
                width,
                graphics.getFontMetrics().getHeight());
            graphics.setColor(Color.black);
            doc.getText(p0 + start, i - start, segment);
            x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
          }
        }
        x = initialXpos;
        i = 0;
        // add highlighted background colors based on position
        // String textx = doc.getText(p0, p1 - p0);
        if ((HIGHLIGHTED_START < p1 && HIGHLIGHTED_START >= p0)
            || (HIGHLIGHTED_END <= p1 && HIGHLIGHTED_END > p0)
            || (HIGHLIGHTED_START < p1 && HIGHLIGHTED_END > p0)) {
          // select whole line
          int start = 0;
          int end = text.length();
          // test to see if only partial line is needed.
          if (HIGHLIGHTED_START > p0) start = HIGHLIGHTED_START - p0;
          if (HIGHLIGHTED_END < p1) end -= p1 - HIGHLIGHTED_END;
          if (i < start) { // fill in normal color if start highlight isn't at the beginning
            graphics.setColor(Color.black);
            doc.getText(p0 + i, start - i, segment);
            x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
          }
          graphics.setColor(HIGHLIGHTED_COLOR); // fill in the highlight color
          i = end;
          if (i - start > 0) {
            doc.getText(p0 + start, i - start, segment);
            int width =
                Utilities.getTabbedTextWidth(
                    segment, graphics.getFontMetrics(), x, this, p0 + start);
            // graphics.drawLine(x, y, width, y);graphics.getFontMetrics()
            graphics.fillRect(
                x,
                y - graphics.getFontMetrics().getHeight() + 2,
                width,
                graphics.getFontMetrics().getHeight());
            graphics.setColor(Color.black);
            doc.getText(p0 + start, i - start, segment);
            x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
          }
          // else
          //	System.out.println("invalid highlighting " + (i - start) + " is <= 0 (" +  p0 + "-" +
          // p1 + "=" + (p1 - p0) +") " + start + ", " + end + " len=" + text.length());
        }

        x = initialXpos;
        i = 0;
        // Color the parts of xml foreground font
        for (Map.Entry<Integer, Integer> entry : startMap.entrySet()) {
          int start = entry.getKey();
          int end = entry.getValue();

          if (i < start) {
            graphics.setColor(Color.black);
            doc.getText(p0 + i, start - i, segment);
            x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
          }

          graphics.setColor(colorMap.get(start));
          i = end;
          doc.getText(p0 + start, i - start, segment);
          x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
        }

        // Paint possible remaining text black
        if (i < text.length()) {
          graphics.setColor(Color.black);
          doc.getText(p0 + i, text.length() - i, segment);
          x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
      return x;
    }
 /**
  * Parses the files passed into the <CODE>setTemplateFiles</CODE> method. The data extracted from
  * the template files is returned.
  */
 public void parse() {
   setMessage("Parsing Files");
   templates.clear();
   importedFieldCount = 0;
   importedMacroCount = 0;
   File[] templateFiles = getTemplateFiles();
   resetParseCanceled();
   int totalFileSize = 0;
   for (int i = 0; i < templateFiles.length; i++)
     if (templateFiles[i].exists()) totalFileSize += (int) templateFiles[i].length();
   setProgressMaximum(totalFileSize);
   int progress = 0;
   setProgressValue(0);
   setProgressIndeterminate(false);
   for (int i = 0; i < templateFiles.length; i++) {
     String currentFilePath = templateFiles[i].getAbsolutePath();
     Timestamp modifiedDate = new Timestamp(templateFiles[i].lastModified());
     Template currentTemplate = new Template(currentFilePath, modifiedDate);
     String[] nameParts = templateFiles[i].getName().split("\\.");
     if (nameParts != null && nameParts.length > 0) currentTemplate.setID(nameParts[0]);
     templates.add(currentTemplate);
     try {
       BufferedReader iStream = new BufferedReader(new FileReader(templateFiles[i]));
       try {
         String currentLine = iStream.readLine();
         Signal currentSignal = null, archiveTag = null;
         ArchiveRequest request = null;
         ArchiveGroup group = null;
         HashMap archiveSignals = new HashMap();
         int lineNumber = 0;
         int braceCount = 0;
         while (currentLine != null) // null indicates EOF
         {
           lineNumber++;
           if (currentLine.trim().startsWith("#")) // Comments start with #
           {
             // Comments start with #. Archive information is embedded in comments.
             ArchiveGroup newGroup = parseArchiveGroupTag(currentLine, currentTemplate);
             if (newGroup != null) group = newGroup;
             else {
               ArchiveRequest newRequest =
                   parseArchiveRequestTag(currentLine, group, currentTemplate);
               if (newRequest != null) request = newRequest;
               else {
                 Signal newArchiveTag = parseArchiveTag(currentLine);
                 if (newArchiveTag != null) {
                   if (archiveTag != null) // Tag was not used in request. Use for defaults.
                   archiveSignals.put(archiveTag.getID(), archiveTag);
                   archiveTag = newArchiveTag;
                 }
               }
             }
           } else {
             Matcher macroMatcher = macroPattern.matcher(currentLine);
             if (macroMatcher.find()) {
               String macro = macroMatcher.group(1);
               if (!currentTemplate.containsMacro(macro)) {
                 importedMacroCount++;
                 currentTemplate.addMacro(macro);
               }
             }
             int linePosition = 0;
             int lineLength = currentLine.length();
             while (linePosition < lineLength) {
               int openBracePosition = currentLine.indexOf('{', linePosition);
               int closeBracePosition = currentLine.indexOf('}', linePosition);
               if (currentSignal == null || braceCount == 0) {
                 // Got no signal or the brace was never opened...
                 Matcher recordMatcher = recordPattern.matcher(currentLine);
                 if (recordMatcher.find(linePosition))
                   if (openBracePosition < 0 || recordMatcher.start() < openBracePosition) {
                     linePosition = recordMatcher.end();
                     SignalType currentSignalType = new SignalType();
                     String recordType = recordMatcher.group(1);
                     currentSignalType.setRecordType(new EpicsRecordType(recordType));
                     String signalID = recordMatcher.group(2);
                     currentSignal = new Signal(signalID);
                     currentSignal.setType(currentSignalType);
                     if (archiveTag != null)
                       archiveSignals.put(archiveTag.getID(), archiveTag); // Use as defaults.
                     archiveTag = (Signal) archiveSignals.get(signalID);
                     if (archiveTag != null) {
                       currentSignal.setArchiveIndicator("Y");
                       currentSignal.setArchiveType(archiveTag.getArchiveType());
                       currentSignal.setArchiveFrequency(archiveTag.getArchiveFrequency());
                       // Must use a new instance of signal since each request has different
                       // values for type, frequency, etc.
                       if (request != null && request.getSignal(signalID) == null)
                         request.addSignal(new Signal(signalID));
                       currentSignal.setArchiveIndicator("Y");
                       currentSignal.setArchiveType(archiveTag.getArchiveType());
                       currentSignal.setArchiveFrequency(archiveTag.getArchiveFrequency());
                     }
                     currentTemplate.addSignal(currentSignal);
                     archiveTag = null; // Reset so is not used twice.
                     continue; // Go back and check the line position against length.
                   }
               }
               if (braceCount == 0 && currentSignal != null && openBracePosition >= linePosition) {
                 // Got the signal, need the open brace.
                 linePosition = openBracePosition + 1;
                 braceCount++;
                 continue; // Go back and check the line position against length.
               }
               if (braceCount > 0) {
                 // Looking for fields or the close brace.
                 Matcher fieldMatcher = fieldPattern.matcher(currentLine);
                 if (fieldMatcher.find(linePosition))
                   if (closeBracePosition < 0 || fieldMatcher.start() < closeBracePosition) {
                     // Found a field...
                     linePosition = fieldMatcher.end();
                     SignalField currentField = new SignalField();
                     String currentFieldID = fieldMatcher.group(1);
                     currentField.setType(new SignalFieldType(currentFieldID));
                     currentField.setValue(fieldMatcher.group(2));
                     currentSignal.addField(currentField);
                     importedFieldCount++;
                     continue;
                   }
                 if (closeBracePosition >= 0) {
                   // Found end of current signal.
                   braceCount--;
                   linePosition = closeBracePosition + 1;
                   currentSignal = null;
                   continue;
                 }
               }
               linePosition = lineLength;
               if (isParseCanceled()) break;
             }
           }
           progress += currentLine.length() + 1;
           setProgressValue(progress);
           currentLine = iStream.readLine();
           if (isParseCanceled()) break;
         }
       } finally {
         iStream.close();
       }
     } catch (java.io.FileNotFoundException ex) {
       StringBuffer errorMessage = new StringBuffer("<HTML><FONT COLOR=RED>Unable to open file '");
       errorMessage.append(templateFiles[i].getAbsoluteFile());
       errorMessage.append("'.</FONT></HTML>");
       addMessage(errorMessage.toString());
     } catch (java.io.IOException ex) {
       ex.printStackTrace();
       StringBuffer errorMessage = new StringBuffer("<HTML><FONT COLOR=RED>IO Error: ");
       errorMessage.append(ex.getMessage());
       errorMessage.append("</FONT></HTML>");
       addMessage(errorMessage.toString());
     }
     if (isParseCanceled()) break;
   }
 }