title: How to treat 4 consecutive spaces as a single character?
body: <p>I have written a TextArea that types 4 consecutive spaces whenever I press a certain key combination (<kbd>Alt</kbd> + <kbd>C</kbd> in my case), however, I am looking for a way to make the program treat them as if they're a single character, by which I mean that:</p>
  
  <ul>
  <li>the caret's position jumps from one end of the space sequence to the other if it moves towards it</li>
  <li>I can only select all of them at once</li>
  <li>if I press backspace and the caret is in front of them, all 4 get deleted at once</li>
  </ul>
  
  <p>I've managed to complete the first two tasks by creating a caret position listener, but whenever I try to delete the 4 spaces, I get an <code>IndexOutOfBoundsException</code> error that redirects me to the listener, even though the code for that is written in a key event handler that checks if the key pressed is a backspace.</p>
  
  <p>I'm only going to include the snippets of code that are relevant to the question, as the whole program is quite long:</p>
  
  <pre><code>textarea.caretPositionProperty().addListener((ob, old1, new1) -&gt; {
              int oldi = old1.intValue();
              int newi = new1.intValue();
              if(oldi &gt; newi &amp;&amp; oldi &gt; 3 &amp;&amp; textarea.getText(oldi - 4, oldi).equals("    "))
                  textarea.positionCaret(oldi - 4);
              if(oldi &lt; newi &amp;&amp; oldi &lt; (textarea.getText().length() - 3) &amp;&amp; textarea.getText(oldi, oldi + 4).equals("    "))
                  textarea.positionCaret(oldi + 4);
          });
  
  
  textarea.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler&lt;KeyEvent&gt;() {
                 @Override
                 public void handle(KeyEvent e) {
                    int cp = textarea.getCaretPosition();
                     if(e.isAltDown() &amp;&amp; (e.getCode() == KeyCode.C)) {
                    //some other code
                    textarea.positionCaret(cp + 4);
                     }
                     if(e.getCode() == KeyCode.BACK_SPACE &amp;&amp; areat.length()&gt;3) {
                         if(areat.substring(cp-4, cp).equals("    "))
                         textarea.setText(areat.substring(0, cp-4) + areat.substring(cp));
                     }
                 }
              }
          );
  </code></pre>
  
  <p>To explain the <code>areat</code> variable: at one point, I thought that the problem might be caused by the <code>textarea.getText()</code> function, given that (presumably) it could either refer to the text before or after pressing backspace (e.g. either "Hello!" or "Hello"). Fortunately, I've already written a text property listener for a separate feature of the program, so I tried solving the problem by declaring a global variable (<code>areat</code>) and storing the old text there (which didn't work, needless to say):</p>
  
  <pre><code>textarea.textProperty().addListener((obs, old1, new1) -&gt; {
              areat = old1;
              areatn = new1;
              //some other code
          });
  </code></pre>
  
  <p>How should I proceed from here? Is there a problem with the event handler or with the caret listener? Or maybe there is a specific method that has all the features mentioned above built-in?</p>
  
  <p>Side note: I would prefer not switching to a <code>JTextArea</code>, as I've never worked with swing elements before.</p>
  
  <p>EDIT: If you're an admin, please don't mark this question as solved, because I'm still looking for better answers, BUT I've managed to fix the issue by storing the <strong>new</strong> text of the text property listener in a global variable (<code>areatn</code>) instead of the old one, which I've used in both the event handler and the caret listener. Please do let me know if you've found a solution that's less bodged-in than mine.</p>
  
  <p>EDIT 2: As @kleopatra pointed out in the comments, the TextFormatter class is much better equipped for this kind of situation than my listeners are.</p>