예제 #1
0
 /**
  * Returns the cursor coordinates.
  *
  * @return line/column
  */
 int[] pos() {
   final int hh = h;
   h = Integer.MAX_VALUE;
   final Graphics g = getGraphics();
   int col = 1;
   int line = 1;
   init(g, 0);
   boolean more = true;
   while (more(g)) {
     final int p = text.pos();
     while (text.more()) {
       more = text.pos() < text.cursor();
       if (!more) break;
       text.next();
       col++;
     }
     if (!more) break;
     text.pos(p);
     if (next()) {
       line++;
       col = 1;
     }
   }
   h = hh;
   return new int[] {line, col};
 }
예제 #2
0
  /**
   * Checks if the text has more words to print.
   *
   * @param g graphics reference
   * @return true if the text has more words
   */
  private boolean more(final Graphics g) {
    // no more words found; quit
    if (!text.moreWords()) return false;

    // calculate word width
    int ww = 0;
    final int p = text.pos();
    while (text.more()) {
      final int ch = text.next();
      // internal special codes...
      if (ch == 0x02) {
        font(bfont);
      } else if (ch == 0x03) {
        font(dfont);
      } else {
        ww += charW(g, ch);
      }
    }
    text.pos(p);

    // jump to new line
    if (x + ww > w) {
      x = off;
      y += fontH;
    }
    wordW = ww;

    // check if word has been found, and word is still visible
    return y < h;
  }
예제 #3
0
  @Override
  public void keyTyped(final KeyEvent e) {
    if (undo == null || control(e) || DELNEXT.is(e) || DELPREV.is(e) || ESCAPE.is(e)) return;

    text.pos(text.cursor());
    // string to be added
    String ch = String.valueOf(e.getKeyChar());

    // remember if marked text is to be deleted
    boolean del = true;
    final byte[] txt = text.text();
    if (TAB.is(e)) {
      if (text.marked()) {
        // check if lines are to be indented
        final int s = Math.min(text.pos(), text.start());
        final int l = Math.max(text.pos(), text.start()) - 1;
        for (int p = s; p <= l && p < txt.length; p++) del &= txt[p] != '\n';
        if (!del) {
          text.indent(s, l, e.isShiftDown());
          ch = null;
        }
      } else {
        boolean c = true;
        for (int p = text.pos() - 1; p >= 0 && c; p--) {
          final byte b = txt[p];
          c = ws(b);
          if (b == '\n') break;
        }
        if (c) ch = "  ";
      }
    }

    // delete marked text
    if (text.marked() && del) text.delete();

    if (ENTER.is(e)) {
      // adopt indentation from previous line
      final StringBuilder sb = new StringBuilder(1).append(e.getKeyChar());
      int s = 0;
      for (int p = text.pos() - 1; p >= 0; p--) {
        final byte b = txt[p];
        if (b == '\n') break;
        if (b == '\t') {
          s += 2;
        } else if (b == ' ') {
          s++;
        } else {
          s = 0;
        }
      }
      for (int p = 0; p < s; p++) sb.append(' ');
      ch = sb.toString();
    }

    if (ch != null) text.add(ch);
    text.setCaret();
    rend.calc();
    showCursor(2);
    e.consume();
  }
예제 #4
0
  /**
   * Returns true if the keyword is found.
   *
   * @return result of check
   */
  private boolean found() {
    if (keyword.isEmpty()) return false;

    final int sl = keyword.length();
    final int wl = text.length();
    if (wl < sl) return false;
    final int p = text.pos();
    int s = -1;
    while (++s != sl) {
      if (Character.toLowerCase(text.next()) != keyword.charAt(s)) break;
    }
    text.pos(p);
    return s == sl;
  }
예제 #5
0
 /** Redoes the text. */
 final void redo() {
   if (undo == null) return;
   text = new BaseXTextTokens(undo.next());
   rend.setText(text);
   text.pos(undo.cursor());
   text.setCaret();
 }
예제 #6
0
 /** Deletes the selected text. */
 final void delete() {
   if (undo == null) return;
   text.pos(text.cursor());
   undo.cursor(text.cursor());
   text.delete();
   undo.store(text.text(), text.cursor());
   text.setCaret();
 }
예제 #7
0
 /**
  * Pastes the specified string.
  *
  * @param txt string to be pasted
  * @return success flag
  */
 final boolean paste(final String txt) {
   if (txt == null || undo == null) return false;
   text.pos(text.cursor());
   undo.cursor(text.cursor());
   if (text.marked()) text.delete();
   text.add(txt);
   undo.store(text.text(), text.cursor());
   return true;
 }
예제 #8
0
 /**
  * Moves the cursor down. The current column position is remembered in {@link #lastCol} and, if
  * possible, restored.
  *
  * @param l number of lines to move cursor
  * @param mark mark flag
  */
 private void down(final int l, final boolean mark) {
   if (!mark) text.noMark();
   final int x = text.bol(mark);
   if (lastCol == -1) lastCol = x;
   for (int i = 0; i < l; ++i) {
     text.eol(mark);
     text.next(mark);
   }
   text.forward(lastCol, mark);
   if (text.pos() == text.size()) lastCol = -1;
 }
예제 #9
0
  /**
   * Selects the text at the specified position.
   *
   * @param pos current text position
   * @param p mouse position
   * @param finish states if selection is in progress
   */
  void select(final int pos, final Point p, final boolean finish) {
    if (!finish) text.noMark();
    p.y -= 3;

    final Graphics g = getGraphics();
    init(g, pos);
    if (p.y > y - fontH) {
      int s = text.pos();
      while (true) {
        // end of line
        if (p.x > x && p.y < y - fontH) {
          text.pos(s);
          break;
        }
        // end of text - skip last characters
        if (!more(g)) {
          while (text.more()) text.next();
          break;
        }
        // beginning of line
        if (p.x <= x && p.y < y) break;
        // middle of line
        if (p.x > x && p.x <= x + wordW && p.y > y - fontH && p.y <= y) {
          while (text.more()) {
            final int ww = charW(g, text.curr());
            if (p.x < x + ww) break;
            x += ww;
            text.next();
          }
          break;
        }
        s = text.pos();
        next();
      }

      if (!finish) text.startMark();
      else text.endMark();
      text.setCaret();
    }
    repaint();
  }
예제 #10
0
 /**
  * Moves the cursor up.
  *
  * @param l number of lines to move cursor
  * @param mark mark flag
  */
 private void up(final int l, final boolean mark) {
   if (!mark) text.noMark();
   final int x = text.bol(mark);
   if (lastCol == -1) lastCol = x;
   if (text.pos() == 0) {
     lastCol = -1;
     return;
   }
   for (int i = 0; i < l; ++i) {
     text.prev(mark);
     text.bol(mark);
   }
   text.forward(lastCol, mark);
 }
예제 #11
0
  /**
   * Finds the current keyword and returns the text position.
   *
   * @param forward backward browsing
   * @param same string is the same as last time
   * @return new position
   */
  int find(final boolean forward, final boolean same) {
    if (keyword.isEmpty()) return 0;

    while (true) {
      final int hh = h;
      int lp = 0;
      int ly = 0;
      int cp = text.cursor();

      h = Integer.MAX_VALUE;
      final Graphics g = getGraphics();
      for (init(g, 0); more(g); next()) {
        if (!found()) continue;

        final int np = text.pos();
        final int ny = y - fontH;
        if (np >= cp && (np > cp || !same || !forward)) {
          if (forward || lp != 0) {
            h = hh;
            text.setCaret(forward ? np : lp);
            return forward ? ny : ly;
          }
          cp = Integer.MAX_VALUE;
        }
        lp = np;
        ly = ny;
      }

      h = hh;
      if (cp == 0 || cp == Integer.MAX_VALUE) {
        text.setCaret(lp);
        return ly;
      }
      text.setCaret(0);
    }
  }
예제 #12
0
  /**
   * Writes the current string to the graphics reference.
   *
   * @param g graphics reference
   */
  private void write(final Graphics g) {
    if (high) {
      high = false;
    } else {
      color = isEnabled() ? syntax.getColor(text) : Color.gray;
    }

    final int ch = text.curr();
    if (y > 0 && y < h) {
      if (ch == TokenBuilder.MARK) {
        color = GUIConstants.GREEN;
        high = true;
      }

      // mark error
      if (text.erroneous()) {
        g.setColor(GUIConstants.LRED);
        g.fillRect(x, y - fontH + 4, wordW, fontH);
      }

      // mark text
      int xx = x;
      if (text.markStart()) {
        final int p = text.pos();
        while (text.more()) {
          final int cw = charW(g, text.curr());
          if (text.inMark()) {
            g.setColor(GUIConstants.color(3));
            g.fillRect(xx, y - fontH + 4, cw, fontH);
          }
          xx += cw;
          text.next();
        }
        text.pos(p);
      }
      if (found()) {
        int cw = 0;
        for (int c = 0; c < keyword.length(); ++c) {
          cw += charW(g, keyword.charAt(c));
        }
        g.setColor(GUIConstants.color(text.cursor() == text.pos() ? 5 : 2));
        g.fillRect(x, y - fontH + 4, cw, fontH);
      }

      // don't write whitespaces
      if (ch > ' ') {
        g.setColor(color);
        String n = text.nextWord();
        int ww = w - x;
        if (x + wordW > ww) {
          // shorten string if it cannot be completely shown (saves memory)
          int c = 0;
          for (final int nl = n.length(); c < nl && ww > 0; c++) {
            ww -= charW(g, n.charAt(c));
          }
          n = n.substring(0, c);
        }
        g.drawString(n, x, y);
      } else if (ch <= TokenBuilder.MARK) {
        g.setFont(font);
      }

      // show cursor
      if (cursor && text.edited()) {
        xx = x;
        final int p = text.pos();
        while (text.more()) {
          if (text.cursor() == text.pos()) {
            cursor(g, xx);
            break;
          }
          xx += charW(g, text.next());
        }
        text.pos(p);
      }
    }
    next();
  }
예제 #13
0
 /** Cuts the selected text to the clipboard. */
 final void cut() {
   text.pos(text.cursor());
   if (copy()) delete();
 }
예제 #14
0
  @Override
  public void keyPressed(final KeyEvent e) {
    if (modifier(e)) return;

    // operations that change the focus are put first..
    if (PREVTAB.is(e)) {
      transferFocusBackward();
      return;
    }
    if (NEXTTAB.is(e)) {
      transferFocus();
      return;
    }
    if (FIND.is(e)) {
      if (find != null) find.requestFocusInWindow();
      return;
    }

    // re-animate cursor
    cursor(true);

    // operations without cursor movement...
    final int fh = rend.fontH();
    if (SCROLLDOWN.is(e)) {
      scroll.pos(scroll.pos() + fh);
      return;
    }
    if (SCROLLUP.is(e)) {
      scroll.pos(scroll.pos() - fh);
      return;
    }
    if (COPY1.is(e) || COPY2.is(e)) {
      copy();
      return;
    }

    // set cursor position and reset last column
    text.pos(text.cursor());
    if (!PREVLINE.is(e) && !NEXTLINE.is(e)) lastCol = -1;

    if (FINDNEXT.is(e) || FINDNEXT2.is(e)) {
      scroll(rend.find(true, true));
      return;
    }
    if (FINDPREV.is(e) || FINDPREV2.is(e)) {
      scroll(rend.find(false, true));
      return;
    }
    if (SELECTALL.is(e)) {
      selectAll();
      return;
    }

    // necessary on Macs as the shift button is pressed for REDO
    final boolean marking =
        e.isShiftDown()
            && !DELNEXT.is(e)
            && !DELPREV.is(e)
            && !PASTE2.is(e)
            && !COMMENT.is(e)
            && !DELLINE.is(e)
            && !REDOSTEP.is(e);
    final boolean nomark = !text.marked();
    if (marking && nomark) text.startMark();
    boolean down = true;
    boolean consumed = true;

    // operations that consider the last text mark..
    final byte[] txt = text.text();
    if (NEXTWORD.is(e)) {
      text.nextToken(marking);
    } else if (PREVWORD.is(e)) {
      text.prevToken(marking);
      down = false;
    } else if (TEXTSTART.is(e)) {
      if (!marking) text.noMark();
      text.pos(0);
      down = false;
    } else if (TEXTEND.is(e)) {
      if (!marking) text.noMark();
      text.pos(text.size());
    } else if (LINESTART.is(e)) {
      text.bol(marking);
      down = false;
    } else if (LINEEND.is(e)) {
      text.eol(marking);
    } else if (NEXTPAGE.is(e)) {
      down(getHeight() / fh, marking);
    } else if (PREVPAGE.is(e)) {
      up(getHeight() / fh, marking);
      down = false;
    } else if (NEXT.is(e)) {
      text.next(marking);
    } else if (PREV.is(e)) {
      text.prev(marking);
      down = false;
    } else if (PREVLINE.is(e)) {
      up(1, marking);
      down = false;
    } else if (NEXTLINE.is(e)) {
      down(1, marking);
    } else if (FINDERROR.is(e)) {
      final int p = text.error();
      if (p != -1) setCaret(p);
    } else {
      consumed = false;
    }

    if (marking) {
      // refresh scroll position
      text.endMark();
      text.checkMark();
    } else if (undo != null) {
      // edit operations...
      if (CUT1.is(e) || CUT2.is(e)) {
        cut();
      } else if (PASTE1.is(e) || PASTE2.is(e)) {
        paste();
      } else if (UNDOSTEP.is(e)) {
        undo();
      } else if (REDOSTEP.is(e)) {
        redo();
      } else if (COMMENT.is(e)) {
        text.comment(rend.getSyntax());
      } else if (DELLINE.is(e)) {
        text.deleteLine();
      } else if (DELLINEEND.is(e) || DELNEXTWORD.is(e) || DELNEXT.is(e)) {
        if (nomark) {
          if (text.pos() == text.size()) return;
          text.startMark();
          if (DELNEXTWORD.is(e)) {
            text.nextToken(true);
          } else if (DELLINEEND.is(e)) {
            text.eol(true);
          } else {
            text.next(true);
          }
          text.endMark();
        }
        undo.cursor(text.cursor());
        text.delete();
      } else if (DELLINESTART.is(e) || DELPREVWORD.is(e) || DELPREV.is(e)) {
        if (nomark) {
          if (text.pos() == 0) return;
          text.startMark();
          if (DELPREVWORD.is(e)) {
            text.prevToken(true);
          } else if (DELLINESTART.is(e)) {
            text.bol(true);
          } else {
            text.prev();
          }
          text.endMark();
        }
        undo.cursor(text.cursor());
        text.delete();
        down = false;
      } else {
        consumed = false;
      }
    }
    if (consumed) e.consume();

    text.setCaret();
    if (txt != text.text()) rend.calc();
    showCursor(down ? 2 : 0);
  }