@@ -390,11 +390,32 @@ public void setText(String what) {
390390 // its absolute position (number of characters from the start), which isn't
391391 // always perfect, but the best we can do without making a diff of the old
392392 // and new text and some guesswork.
393+ // Note that we cannot use textarea.setText() here, since that first removes
394+ // text and then inserts the new text. Even with NEVER_UPDATE, the caret
395+ // always makes sure to stay valid, so first removing all text makes it
396+ // reset to 0. Also note that simply saving and restoring the caret position
397+ // will work, but then the scroll position might change in response to the
398+ // caret position.
393399 DefaultCaret caret = (DefaultCaret ) textarea .getCaret ();
394400 int policy = caret .getUpdatePolicy ();
395401 caret .setUpdatePolicy (DefaultCaret .NEVER_UPDATE );
396- textarea .setText (what );
397- caret .setUpdatePolicy (policy );
402+ try {
403+ RSyntaxDocument doc = (RSyntaxDocument )textarea .getDocument ();
404+ int oldLength = doc .getLength ();
405+ // The undo manager already seems to group the insert and remove together
406+ // automatically, but better be explicit about it.
407+ textarea .getUndoManager ().beginInternalAtomicEdit ();
408+ try {
409+ doc .insertString (oldLength , what , null );
410+ doc .remove (0 , oldLength );
411+ } catch (BadLocationException e ) {
412+ System .err .println ("Unexpected failure replacing text" );
413+ } finally {
414+ textarea .getUndoManager ().endInternalAtomicEdit ();
415+ }
416+ } finally {
417+ caret .setUpdatePolicy (policy );
418+ }
398419 }
399420
400421 /**
0 commit comments