/** This method is called by Swing to delete text from this document. */
 @Override
 public void remove(int offset, int length) throws BadLocationException {
   if (length == 0) return;
   if (undone > 0) {
     now = now - undone;
     undone = 0;
   } // clear the REDO entries
   String string = toString().substring(offset, offset + length);
   super.remove(offset, length);
   if (now > 0 && !insert[now - 1]) { // merge with last edit if possible
     if (where[now - 1] == offset) {
       text[now - 1] += string;
       return;
     }
     if (where[now - 1] == offset + length) {
       where[now - 1] = offset;
       text[now - 1] = string + text[now - 1];
       return;
     }
   }
   if (now >= MAXUNDO) {
     arraycopy(insert, 1, insert, 0, MAXUNDO - 1);
     arraycopy(text, 1, text, 0, MAXUNDO - 1);
     arraycopy(where, 1, where, 0, MAXUNDO - 1);
     now--;
   }
   insert[now] = false;
   text[now] = string;
   where[now] = offset;
   now++;
 }
 /** This method is called by Swing to insert a String into this document. */
 @Override
 public void insertString(int offset, String string, AttributeSet attr)
     throws BadLocationException {
   if (string.length() == 0) return;
   else if (string.indexOf('\r') >= 0)
     string = Util.convertLineBreak(string); // we don't want '\r'
   if (undone > 0) {
     now = now - undone;
     undone = 0;
   } // clear the REDO entries
   super.insertString(offset, string, attr);
   if (now > 0 && insert[now - 1]) { // merge with last edit if possible
     if (where[now - 1] == offset - text[now - 1].length()) {
       text[now - 1] += string;
       return;
     }
   }
   if (now >= MAXUNDO) {
     arraycopy(insert, 1, insert, 0, MAXUNDO - 1);
     arraycopy(text, 1, text, 0, MAXUNDO - 1);
     arraycopy(where, 1, where, 0, MAXUNDO - 1);
     now--;
   }
   insert[now] = true;
   text[now] = string;
   where[now] = offset;
   now++;
 }
 /**
  * Perform undo then return where the new desired caret location should be (or return -1 if undo
  * is not possible right now)
  */
 public int do_undo() {
   if (undone >= now) return -1;
   else undone++;
   boolean insert = this.insert[now - undone];
   String text = this.text[now - undone];
   int where = this.where[now - undone];
   try {
     if (insert) {
       super.remove(where, text.length());
       return where;
     } else {
       super.insertString(where, text, attr);
       return where + text.length();
     }
   } catch (BadLocationException ex) {
     return -1;
   }
 }