public void paint(Graphics gfx)
  {
    if (Base.isMacOS()) {
      Graphics2D g2 = (Graphics2D) gfx;
      g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                          RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
    }

    tabSize = fm.charWidth(' ') * ((Integer)textArea.getDocument().getProperty(PlainDocument.tabSizeAttribute)).intValue();

    Rectangle clipRect = gfx.getClipBounds();

    gfx.setColor(getBackground());
    gfx.fillRect(clipRect.x,clipRect.y,clipRect.width,clipRect.height);

    // We don't use yToLine() here because that method doesn't
    // return lines past the end of the document
    int height = fm.getHeight();
    int firstLine = textArea.getFirstLine();
    int firstInvalid = firstLine + clipRect.y / height;
    // Because the clipRect's height is usually an even multiple
    // of the font height, we subtract 1 from it, otherwise one
    // too many lines will always be painted.
    int lastInvalid = firstLine + (clipRect.y + clipRect.height - 1) / height;

    try {
      TokenMarker tokenMarker = textArea.getDocument().getTokenMarker();
      int x = textArea.getHorizontalOffset();

      for (int line = firstInvalid; line <= lastInvalid; line++) {
        paintLine(gfx,tokenMarker,line,x);
      }

      if (tokenMarker != null && tokenMarker.isNextLineRequested()) {
        int h = clipRect.y + clipRect.height;
        repaint(0,h,getWidth(),getHeight() - h);
      }
    } catch (Exception e) {
      System.err.println("Error repainting line"
                         + " range {" + firstInvalid + ","
                         + lastInvalid + "}:");
      e.printStackTrace();
    }
  }