@Override public void replace(FilterBypass fb,
                                          int          offset,
                                          int          length,
                                          String       text,
                                          AttributeSet attrs)
                                   throws BadLocationException {
                if (!userUpdate) {
                    // content set from outside, go with it
                    super.replace(fb, offset, length, text, attrs);
                    return;
                }

                String buffer = getText();
                String begin = buffer.substring(0, offset) + text;
                String newContent = begin + buffer.substring(offset + length);
                ChoiceMatch match = getBestMatch(newContent);
                String proposal = null;
                if (match.exact) {
                    proposal = match.content.toString();
                } else {
                    // why this part? Imagine having text "se|cond" with the
                    // cursor at "|". Nothing is selected. if the user presses
                    // now 'c', the code above would imply getting "seccond",
                    // which is probably wrong, so we try now to get a proposal
                    // starting at 'sec' ['sec|ond']
                    ChoiceMatch match2 = getBestMatch(begin);
                    if (match2.exact) {
                        match = match2;
                        proposal = match.content.toString();
                    } else if (match.content == null) {
                        return;
                    } else {
                        proposal = match.content.toString();
                        // on text content, the string comparator cannot
                        // be null
                        if (proposal.length() < begin.length()) {
                            return;
                        }

                        Comparator<String> cst = popup.getStringComparator();
                        String prpBegin = proposal.substring(0, begin.length());
                        if (0 != cst.compare(begin, prpBegin)) {
                            return;
                        }
                    }
                }

                int caret = 1
                        + Math.min(getCaret().getDot(), getCaret().getMark());

                super.replace(fb, 0, buffer.length(), proposal, attrs);

                int len = proposal.length();
                setCaretPosition(len);
                moveCaretPosition(Math.min(len, caret));
                deactivateCustomDecoration();

                if (instantFiltering) {
                    match.exact = true;
                    updateFilter(proposal, match, true);
                }
            }
@Override public void replace(FilterBypass fb,
                                          int          offset,
                                          int          length,
                                          String       text,
                                          AttributeSet attrs)