Element root = getDefaultRootElement();
  public void setCharacterAttributes(int offset, int length,                                     AttributeSet attributes, boolean replace)  {    // Exit early if length is 0, so no DocumentEvent is created or fired.    if (length == 0)      return;    try      {        // Must obtain a write lock for this method.  writeLock() and        // writeUnlock() should always be in try/finally block to make        // sure that locking happens in a balanced manner.        writeLock();        DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,                                   length, 			       DocumentEvent.EventType.CHANGE);        // Modify the element structure so that the interval begins at an        // element    // start and ends at an element end.    buffer.change(offset, length, ev);    Element root = getDefaultRootElement();    // Visit all paragraph elements within the specified interval        int end = offset + length;        Element curr;        for (int pos = offset; pos < end;)          {            // Get the CharacterElement at offset pos.            curr = getCharacterElement(pos);            if (pos == curr.getEndOffset())              break;            MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes();            ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace));            // If replace is true, remove all the old attributes.		if (replace)              a.removeAttributes(a);            // Add all the new attributes.            a.addAttributes(attributes);            // Increment pos so we can check the next CharacterElement.            pos = curr.getEndOffset();	      }        fireChangedUpdate(ev);        fireUndoableEditUpdate(new UndoableEditEvent(this, ev));	  }    finally      {        writeUnlock();      }  }