public ExtendedTextField() {
    setFullScreenMode(true);

    setCommandListener(this);

    exit = new Command("Exit", Command.EXIT, 1);
    open = new Command("Open", Command.ITEM, 1);
    newFile = new Command("New", Command.ITEM, 2);
    save = new Command("Save", Command.ITEM, 3);
    saveAs = new Command("Save As", Command.ITEM, 4);
    eval = new Command("Eval", Command.ITEM, 5);
    output = new Command("Output", Command.ITEM, 6);
    cls = new Command("Clear", Command.ITEM, 7);

    addCommand(exit);
    addCommand(newFile);
    addCommand(open);
    addCommand(save);
    addCommand(saveAs);
    addCommand(eval);
    addCommand(output);
    addCommand(cls);

    new Thread(this).start();

    // TODO: change font size?
    inputFont = Font.getDefaultFont();
    inputWidth = getWidth();
    inputHeight = inputFont.getHeight();
    linesOnScreen = getHeight() / inputHeight;

    addNewLine(0);
  }
  void displayCharacterMap(Graphics g) {
    if (currentChars != null) {
      g.setColor(0xffffff);
      g.fillRect(0, getHeight() - inputHeight - 2, getWidth(), inputHeight + 2);
      g.setColor(0x000000);
      g.drawLine(0, getHeight() - inputHeight - 2, getWidth(), getHeight() - inputHeight - 2);
      for (int i = 0; i < currentChars.length; i++) {
        char ch = currentChars[i];
        if (isUppercase) {
          ch = String.valueOf(currentChars[i]).toUpperCase().charAt(0);
        }

        // TODO: if i*12 > getWidth() ?

        g.drawChar(ch, i * 12, getHeight() - inputHeight, Graphics.LEFT | Graphics.TOP);
        if (currentChars[currentKeyStep] == currentChars[i]) {
          g.drawRect(
              i * 12 - 2,
              getHeight() - inputHeight - 2,
              inputFont.charWidth(ch) + 4,
              inputHeight + 4);
        }
      }
    }
  }
  void displayLines(Graphics g, int yStart) {
    // (1 + 2, depends on font size)

    if (isSelection && (xStartSelection != xEndSelection || yStartSelection != yEndSelection)) {
      for (int y = Math.max(0, yStart);
          y < Math.min(yStart + linesOnScreen + 1 + 2, vectorLines.size());
          y++) {
        String currentLine = vectorLines.elementAt(y).toString();
        int width = 0;

        for (int x = 0; x < currentLine.length(); x++) {
          int previousWidth = (x == 0) ? 0 : inputFont.charWidth(currentLine.charAt(x - 1));
          width += previousWidth;

          if (isSelected(x, y)) {
            g.setColor(0x000000);
            g.fillRect(
                width, y * inputHeight, inputFont.charWidth(currentLine.charAt(x)), inputHeight);

            g.setColor(0xffffff);
            g.drawChar(currentLine.charAt(x), width, y * inputHeight, Graphics.LEFT | Graphics.TOP);
          } else {
            g.setColor(0x000000);
            g.drawChar(currentLine.charAt(x), width, y * inputHeight, Graphics.LEFT | Graphics.TOP);
          }
        }

        if (currentLine.length() == 0) {
          if (isSelected(0, y)) {
            g.setColor(0x000000);
            g.fillRect(0, y * inputHeight, 5, inputHeight);
          }
        }
      }
    } else {
      for (int y = Math.max(0, yStart);
          y < Math.min(yStart + linesOnScreen + 1 + 2, vectorLines.size());
          y++) {
        g.drawString(
            vectorLines.elementAt(y).toString(), 0, y * inputHeight, Graphics.LEFT | Graphics.TOP);
      }
    }
  }
  void updateCaretPosition() {
    int x = getCursorX();
    int y = getCursorY();

    caretLeft = inputFont.substringWidth(vectorLines.elementAt(y).toString(), 0, x);
  }