/** Clear any styles applied to the selected text. */
  public void clearSelectionStyle() {
    if (!hasSelection()) return;
    TextLayoutHitInfo startSelTLHI;
    TextLayoutHitInfo endSelTLHI;
    if (endTLHI.compareTo(startTLHI) == -1) {
      startSelTLHI = endTLHI;
      endSelTLHI = startTLHI;
    } else {
      startSelTLHI = startTLHI;
      endSelTLHI = endTLHI;
    }
    int ss = startSelTLHI.tli.startCharIndex + startSelTLHI.thi.getInsertionIndex();
    int ee = endSelTLHI.tli.startCharIndex + endSelTLHI.thi.getInsertionIndex();
    stext.clearAttributes(ss, ee);

    // We have modified the text style so the end of the selection may have
    // moved, so it needs to be recalculated. The start will be unaffected.
    stext.getLines(buffer.g2);
    endSelTLHI.tli = stext.getTLIforCharNo(ee);
    int cn = ee - endSelTLHI.tli.startCharIndex;
    if (cn == 0) // start of line
    endSelTLHI.thi = endSelTLHI.tli.layout.getNextLeftHit(1);
    else endSelTLHI.thi = endSelTLHI.tli.layout.getNextRightHit(cn - 1);
    bufferInvalid = true;
  }
 /**
  * Move caret right by one character.
  *
  * @param currPos the current position of the caret
  * @return true if caret moved else false
  */
 protected boolean moveCaretRight(TextLayoutHitInfo currPos) {
   TextHitInfo nthi = currPos.tli.layout.getNextRightHit(currPos.thi);
   if (nthi == null) {
     return false;
   } else {
     currPos.thi = nthi;
   }
   return true;
 }
 /**
  * Move caret left by one character.
  *
  * @param currPos the current position of the caret
  * @return true if caret moved else false
  */
 protected boolean moveCaretLeft(TextLayoutHitInfo currPos) {
   TextHitInfo nthi = currPos.tli.layout.getNextLeftHit(currPos.thi);
   if (nthi == null) {
     return false;
   } else {
     // Move the caret to the left of current position
     currPos.thi = nthi;
   }
   return true;
 }
  /**
   * Load the styled string to be used by this control. <br>
   * It will also restore any text selection saved with the text.
   *
   * @param fname the name of the file to use
   * @return true if loaded successfully else false
   */
  public boolean loadText(String fname) {
    StyledString ss = StyledString.load(winApp, fname);
    if (ss == null) return false;
    setStyledText(ss);
    // Now restore any text selection
    if (stext.startIdx >= 0) { // we have a selection
      // Selection starts at ...
      startTLHI = new TextLayoutHitInfo();
      startTLHI.tli = stext.getTLIforCharNo(stext.startIdx);
      int pInLayout = stext.startIdx - startTLHI.tli.startCharIndex;
      if (pInLayout == 0) startTLHI.thi = startTLHI.tli.layout.getNextLeftHit(1);
      else startTLHI.thi = startTLHI.tli.layout.getNextRightHit(pInLayout - 1);
      // Selection ends at ...
      endTLHI = new TextLayoutHitInfo();
      endTLHI.tli = stext.getTLIforCharNo(stext.endIdx);
      pInLayout = stext.endIdx - endTLHI.tli.startCharIndex;

      if (pInLayout == 0) endTLHI.thi = endTLHI.tli.layout.getNextLeftHit(1);
      else endTLHI.thi = endTLHI.tli.layout.getNextRightHit(pInLayout - 1);
      calculateCaretPos(endTLHI);
    }
    bufferInvalid = true;
    return true;
  }
  /**
   * Determines whether this component is to have focus or not. <br>
   * Fire focus events for the GTextField and GTextArea controls
   *
   * @param focus
   */
  public void setFocus(boolean focus) {
    if (!focus) {
      loseFocus(null);
      return;
    }
    // Make sure we have some text
    if (focusIsWith != this) {
      dragging = false;
      if (stext == null || stext.length() == 0) stext = new StyledString(" ", wrapWidth);
      //			text = stext.getPlainText();
      LinkedList<TextLayoutInfo> lines = stext.getLines(buffer.g2);
      startTLHI = new TextLayoutHitInfo(lines.getFirst(), null);
      startTLHI.thi = startTLHI.tli.layout.getNextLeftHit(1);

      endTLHI = new TextLayoutHitInfo(lines.getLast(), null);
      int lastChar = endTLHI.tli.layout.getCharacterCount();
      endTLHI.thi = startTLHI.tli.layout.getNextRightHit(lastChar - 1);

      calculateCaretPos(endTLHI);
      bufferInvalid = true;
    }
    keepCursorInView = true;
    takeFocus();
  }
 /**
  * Move caret to the end of the line that has the current caret position
  *
  * @param currPos the current position of the caret
  * @return true if caret moved else false
  */
 protected boolean moveCaretEndOfLine(TextLayoutHitInfo currPos) {
   if (currPos.thi.getCharIndex() == currPos.tli.nbrChars - 1)
     return false; // already at end of line
   currPos.thi = currPos.tli.layout.getNextRightHit(currPos.tli.nbrChars - 1);
   return true;
 }
 /**
  * Move caret to home position
  *
  * @param currPos the current position of the caret
  * @return true if caret moved else false
  */
 protected boolean moveCaretStartOfLine(TextLayoutHitInfo currPos) {
   if (currPos.thi.getCharIndex() == 0) return false; // already at start of line
   currPos.thi = currPos.tli.layout.getNextLeftHit(1);
   return true;
 }