From ffd832d9908334fcbc0c8c0ec2e93ee8888d8672 Mon Sep 17 00:00:00 2001
From: Alex Plate <aleksei.plate@jetbrains.com>
Date: Fri, 28 Jun 2024 17:01:30 +0300
Subject: [PATCH] Get rid of RegExp class

---
 ThirdPartyLicenses.md                         |    1 -
 .../com/maddyhome/idea/vim/regexp/RegExp.kt   | 4105 -----------------
 .../idea/vim/ui/ex/ExEntryPanel.java          |    2 -
 3 files changed, 4108 deletions(-)
 delete mode 100644 src/main/java/com/maddyhome/idea/vim/regexp/RegExp.kt

diff --git a/ThirdPartyLicenses.md b/ThirdPartyLicenses.md
index bf1784094..7ef958a94 100644
--- a/ThirdPartyLicenses.md
+++ b/ThirdPartyLicenses.md
@@ -1,6 +1,5 @@
 IdeaVim project is licensed under MIT license except the following parts of it:
 
-* File [RegExp.kt](src/main/java/com/maddyhome/idea/vim/regexp/RegExp.kt) is licensed under Vim License.  
 * File [ScrollViewHelper.kt](com/maddyhome/idea/vim/helper/ScrollViewHelper.kt) is licensed under Vim License.
 * File [Tutor.kt](src/main/java/com/maddyhome/idea/vim/ui/Tutor.kt) is licensed under Vim License.
 
diff --git a/src/main/java/com/maddyhome/idea/vim/regexp/RegExp.kt b/src/main/java/com/maddyhome/idea/vim/regexp/RegExp.kt
deleted file mode 100644
index 1b37a3ac9..000000000
--- a/src/main/java/com/maddyhome/idea/vim/regexp/RegExp.kt
+++ /dev/null
@@ -1,4105 +0,0 @@
-package com.maddyhome.idea.vim.regexp
-
-import com.maddyhome.idea.vim.api.VimEditor
-import com.maddyhome.idea.vim.api.getLineBuffer
-import com.maddyhome.idea.vim.api.injector
-import com.maddyhome.idea.vim.diagnostic.VimLogger
-import com.maddyhome.idea.vim.helper.Msg
-import org.jetbrains.annotations.NonNls
-import java.util.*
-
-@Deprecated("Please use VimRegex class instead")
-internal class RegExp {
-    /*
-     * The first byte of the regexp internal "program" is actually this magic
-     * number; the start node begins in the second byte.  It's used to catch the
-     * most severe mutilation of the program by the caller.
-     */
-    /*
-     * Opcode notes:
-     *
-     * BRANCH       The set of branches constituting a single choice are hooked
-     *              together with their "next" pointers, since precedence prevents
-     *              anything being concatenated to any individual branch.  The
-     *              "next" pointer of the last BRANCH in a choice points to the
-     *              thing following the whole choice.  This is also where the
-     *              final "next" pointer of each individual branch points; each
-     *              branch starts with the operand node of a BRANCH node.
-     *
-     * BACK         Normal "next" pointers all implicitly point forward; BACK
-     *              exists to make loop structures possible.
-     *
-     * STAR,PLUS    '=', and complex '*' and '+', are implemented as circular
-     *              BRANCH structures using BACK.  Simple cases (one character
-     *              per match) are implemented with STAR and PLUS for speed
-     *              and to minimize recursive plunges.
-     *
-     * BRACE_LIMITS This is always followed by a BRACE_SIMPLE or BRACE_COMPLEX
-     *              node, and defines the min and max limits to be used for that
-     *              node.
-     *
-     * MOPEN,MCLOSE ...are numbered at compile time.
-     * ZOPEN,ZCLOSE ...ditto
-     */
-    /*
-     * A node is one char of opcode followed by two chars of "next" pointer.
-     * "Next" pointers are stored as two 8-bit bytes, high order first.  The
-     * value is a positive offset from the opcode of the node containing it.
-     * An operand, if any, simply follows the node.  (Note that much of the
-     * code generation knows about this implicit relationship.)
-     *
-     * Using two bytes for the "next" pointer is vast overkill for most things,
-     * but allows patterns to get big without disasters.
-     */
-  //    #define OP(p)           ((int)*(p))
-  //    #define NEXT(p)         (((*((p) + 1) & 0377) << 8) + (*((p) + 2) & 0377))
-  //    #define OPERAND(p)      ((p) + 3)
-  /* Obtain an operand that was stored as four bytes, MSB first. */ //    #define OPERAND_MIN(p)  (((long)(p)[3] << 24) + ((long)(p)[4] << 16) \
-  //    + ((long)(p)[5] << 8) + (long)(p)[6])
-  /* Obtain a second operand stored as four bytes. */ //    #define OPERAND_MAX(p)  OPERAND_MIN((p) + 4)
-  /* Obtain a second single-byte operand stored after a four bytes operand. */ //    #define OPERAND_CMP(p)  (p)[7]
-    /*
-     * Utility definitions.
-     */
-  //    #define UCHARAT(p)      ((int)*(char_u *)(p))
-  /* Used for an error (down from) vim_regcomp(): give the error message, set rc_did_emsg and return null */ /*
-    #define EMSG_RET_null(m)
-    {
-        EMSG(_(m));
-        rc_did_emsg = true;
-        return null;
-    }
-    #define EMSG_M_RET_null(m, c)
-    {
-        EMSG2(_(m), c ? "" : "\\");
-        rc_did_emsg = true;
-        return null;
-    }
-    #define EMSG_RET_FAIL(m)
-    {
-        EMSG(_(m));
-        rc_did_emsg = true;
-        return FAIL;
-    }
-    #define EMSG_ONE_RET_null
-    */
-  // EMSG_M_RET_null("E369: invalid item in %s%%[]", reg_magic == MAGIC_ALL)
-  private fun EMSG_RET_null(key: String) {
-    injector.messages.showStatusBarMessage(null, injector.messages.message(key))
-  }
-
-  private fun EMSG_M_RET_null(key: String, isMagic: Boolean) {
-    val `val` = if (isMagic) "" else "\\"
-    injector.messages.showStatusBarMessage(null, injector.messages.message(key, `val`))
-  }
-
-  private fun EMSG_ONE_RET_null() {
-    EMSG_M_RET_null(Msg.E369, reg_magic == MAGIC_ALL)
-  }
-
-    /*
-     * Return NOT_MULTI if c is not a "multi" operator.
-     * Return MULTI_ONE if c is a single "multi" operator.
-     * Return MULTI_MULT if c is a multi "multi" operator.
-     */
-  private fun re_multi_type(c: Int): Int {
-    if (c == Magic.AT || c == Magic.EQUAL || c == Magic.QUESTION) {
-      return MULTI_ONE
-    }
-    return if (c == Magic.STAR || c == Magic.PLUS || c == Magic.LCURLY) {
-      MULTI_MULT
-    } else {
-      NOT_MULTI
-    }
-  }
-
-    /*
-     * Translate '\x' to its control character, except "\n", which is Magic.
-     */
-  private fun backslash_trans(c: Int): Int {
-    when (c) {
-      'r'.code -> return '\r'.code
-      't'.code -> return '\t'.code
-      'e'.code -> return 0x1b
-      'b'.code -> return '\b'.code
-    }
-    return c
-  }
-
-    /*
-     * Return true if compiled regular expression "prog" can match a line break.
-     */
-  fun re_multiline(prog: regprog_T): Int {
-    return prog.regflags and RF_HASNL
-  }
-
-    /*
-     * vim_regcomp - compile a regular expression into internal code
-     *
-     * We can't allocate space until we know how big the compiled form will be,
-     * but we can't compile it (and thus know how big it is) until we've got a
-     * place to put the code.  So we cheat:  we compile it twice, once with code
-     * generation turned off and size counting turned on, and once "for real".
-     * This also means that we don't allocate space until we are sure that the
-     * thing really will compile successfully, and we never have to move the
-     * code and thus invalidate pointers into it.  (Note that it has to be in
-     * one piece because vim_free() must be able to free it all.)
-     *
-     * Whether upper/lower case is to be ignored is decided when executing the
-     * program, it does not matter here.
-     *
-     * Beware that the optimization-preparation code in here knows about some
-     * of the structure of the compiled regexp.
-     */
-  fun vim_regcomp(expr: String?, magic: Int): regprog_T? {
-    val r: regprog_T
-    var scan: CharPointer
-    var longest: CharPointer?
-    var len: Int
-    val flags = Flags()
-    if (expr == null) {
-      injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_null))
-      return null
-    }
-    r = regprog_T()
-
-        /*
-         * Second pass: emit code.
-         */regcomp_start(expr, magic)
-    regcode = CharPointer(r.program)
-    regc(REGMAGIC)
-    if (reg(REG_NOPAREN, flags) == null) {
-      return null
-    }
-
-    /* Dig out information for optimizations. */r.regstart = 0.toChar() /* Worst-case defaults. */
-    r.reganch = 0.toChar()
-    r.regmust = null
-    r.regmlen = 0
-    r.regflags = regflags
-    if (flags.isSet(HASNL)) {
-      r.regflags = r.regflags or RF_HASNL
-    }
-    /* Remember whether this pattern has any \z specials in it. */r.reghasz = re_has_z
-    scan = CharPointer(r.program).ref(1) /* First BRANCH. */
-    if (regnext(scan)!!.OP() == END) /* Only one top-level choice. */ {
-      scan = scan.OPERAND()
-
-      /* Starting-point info. */if (scan.OP() == BOL || scan.OP() == RE_BOF) {
-        r.reganch++
-        scan = regnext(scan)!!
-      }
-      if (scan.OP() == EXACTLY) {
-        r.regstart = scan.OPERAND().charAt()
-      } else if ((scan.OP() == BOW || scan.OP() == EOW || scan.OP() == NOTHING || scan.OP() == MOPEN || scan.OP() == NOPEN || scan.OP() == MCLOSE || scan.OP() == NCLOSE) &&
-        regnext(scan)!!.OP() == EXACTLY
-      ) {
-        r.regstart = regnext(scan)!!.OPERAND().charAt()
-      }
-
-            /*
-             * If there's something expensive in the r.e., find the longest
-             * literal string that must appear and make it the regmust.  Resolve
-             * ties in favor of later strings, since the regstart check works
-             * with the beginning of the r.e. and avoiding duplication
-             * strengthens checking.  Not a strong reason, but sufficient in the
-             * absence of others.
-             */
-            /*
-             * When the r.e. starts with BOW, it is faster to look for a regmust
-             * first. Used a lot for "#" and "*" commands. (Added by mool).
-             */if ((flags.isSet(SPSTART) || scan.OP() == BOW || scan.OP() == EOW) &&
-        !flags.isSet(HASNL)
-      ) {
-        longest = null
-        len = 0
-        while (scan != null) {
-          val so = scan.OPERAND()
-          if (scan.OP() == EXACTLY && so.strlen() >= len) {
-            longest = so.ref(0)
-            len = so.strlen()
-          }
-          scan = regnext(scan)!!
-        }
-        if (longest != null) {
-          r.regmust = longest.ref(0)
-        }
-        r.regmlen = len
-      }
-    }
-    if (logger.isDebug()) logger.debug(regdump(expr, r))
-    return r
-  }
-
-    /*
-     * Setup to parse the regexp.  Used once to get the length and once to do it.
-     */
-  private fun regcomp_start(expr: String, magic: Int) {
-    initchr(expr)
-    reg_magic = if (magic != 0) {
-      MAGIC_ON
-    } else {
-      MAGIC_OFF
-    }
-    num_complex_braces = 0
-    regnpar = 1
-    Arrays.fill(had_endbrace, false)
-    regnzpar = 1
-    re_has_z = 0.toChar()
-    regflags = 0
-    had_eol = false
-  }
-
-    /*
-     * Check if during the previous call to vim_regcomp the EOL item "$" has been
-     * found.  This is messy, but it works fine.
-     */
-  fun vim_regcomp_had_eol(): Boolean {
-    return had_eol
-  }
-
-    /*
-     * reg - regular expression, i.e. main body or parenthesized thing
-     *
-     * Caller must absorb opening parenthesis.
-     *
-     * Combining parenthesis handling with the base level of regular expression
-     * is a trifle forced, but the need to tie the tails of the branches to what
-     * follows makes it hard to avoid.
-     */
-  private fun reg(paren: Int, flagp: Flags): CharPointer? {
-    var ret: CharPointer?
-    var br: CharPointer?
-    val ender: CharPointer
-    var parno = 0
-    val flags = Flags()
-    flagp.init(HASWIDTH) /* Tentatively. */
-    if (paren == REG_ZPAREN) {
-      /* Make a ZOPEN node. */
-      if (regnzpar >= NSUBEXP) {
-        injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E50))
-        return null
-      }
-      parno = regnzpar
-      regnzpar++
-      ret = regnode(ZOPEN + parno)
-    } else if (paren == REG_PAREN) {
-      /* Make a MOPEN node. */
-      if (regnpar >= NSUBEXP) {
-        EMSG_M_RET_null(Msg.E51, reg_magic == MAGIC_ALL)
-        return null
-      }
-      parno = regnpar
-      ++regnpar
-      ret = regnode(MOPEN + parno)
-    } else if (paren == REG_NPAREN) {
-      /* Make a NOPEN node. */
-      ret = regnode(NOPEN)
-    } else {
-      ret = null
-    }
-
-    /* Pick up the branches, linking them together. */br = regbranch(flags)
-    if (br == null) {
-      return null
-    }
-    if (ret != null) {
-      regtail(ret, br) /* [MZ]OPEN -> first. */
-    } else {
-      ret = br.ref(0)
-    }
-        /* If one of the branches can be zero-width, the whole thing can.
-         * If one of the branches has * at start or matches a line-break, the
-         * whole thing can. */if (!flags.isSet(HASWIDTH)) {
-      flagp.unset(HASWIDTH)
-    }
-    flagp.set(flags.get() and (SPSTART or HASNL))
-    while (peekchr() == Magic.PIPE) {
-      skipchr()
-      br = regbranch(flags)
-      if (br == null) {
-        return null
-      }
-      regtail(ret, br) /* BRANCH -> BRANCH. */
-      if (!flags.isSet(HASWIDTH)) {
-        flagp.unset(HASWIDTH)
-      }
-      flagp.set(flags.get() and (SPSTART or HASNL))
-    }
-
-    /* Make a closing node, and hook it on the end. */ender =
-      regnode(if (paren == REG_ZPAREN) ZCLOSE + parno else if (paren == REG_PAREN) MCLOSE + parno else if (paren == REG_NPAREN) NCLOSE else END)
-    regtail(ret, ender)
-
-    /* Hook the tails of the branches to the closing node. */br = ret.ref(0)
-    while (br != null) {
-      regoptail(br, ender)
-      br = regnext(br)
-    }
-
-    /* Check for proper termination. */if (paren != REG_NOPAREN && getchr() != Magic.RPAREN) {
-      return if (paren == REG_ZPAREN) {
-        injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E52))
-        null
-      } else if (paren == REG_NPAREN) {
-        EMSG_M_RET_null(Msg.E53, reg_magic == MAGIC_ALL)
-        null
-      } else {
-        EMSG_M_RET_null(Msg.E54, reg_magic == MAGIC_ALL)
-        null
-      }
-    } else if (paren == REG_NOPAREN && peekchr() != '\u0000'.code) {
-      return if (curchr == Magic.LPAREN) {
-        EMSG_M_RET_null(Msg.E55, reg_magic == MAGIC_ALL)
-        null
-      } else {
-        injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_trailing))
-        null
-      }
-      /* NOTREACHED */
-    }
-        /*
-         * Here we set the flag allowing back references to this set of
-         * parentheses.
-         */if (paren == REG_PAREN) {
-      had_endbrace[parno] = true /* have seen the close paren */
-    }
-    return ret
-  }
-
-    /*
-     * regbranch - one alternative of an | operator
-     *
-     * Implements the & operator.
-     */
-  private fun regbranch(flagp: Flags): CharPointer? {
-    val ret: CharPointer
-    var chain: CharPointer? = null
-    var latest: CharPointer?
-    val flags = Flags()
-    flagp.init(WORST or HASNL) /* Tentatively. */
-    ret = regnode(BRANCH)
-    while (true) {
-      latest = regconcat(flags)
-      if (latest == null) {
-        return null
-      }
-
-            /* If one of the branches has width, the whole thing has.  If one of
-             * the branches anchors at start-of-line, the whole thing does. */flagp.set(flags.get() and (HASWIDTH or SPSTART))
-            /* If one of the branches doesn't match a line-break, the whole thing
-             * doesn't. */flagp.set(flagp.get() and (HASNL.inv() or (flags.get() and HASNL)))
-      chain?.let { regtail(it, latest) }
-      if (peekchr() != Magic.AMP) {
-        break
-      }
-      skipchr()
-      regtail(latest, regnode(END)) /* operand ends */
-      reginsert(MATCH, latest.ref(0))
-      chain = latest.ref(0)
-    }
-    return ret
-  }
-
-    /*
-     * regbranch - one alternative of an | or & operator
-     *
-     * Implements the concatenation operator.
-     */
-  private fun regconcat(flagp: Flags): CharPointer? {
-    var first: CharPointer? = null
-    var chain: CharPointer? = null
-    var latest: CharPointer?
-    val flags = Flags()
-    var cont = true
-    flagp.init(WORST) /* Tentatively. */
-    while (cont) {
-      when (peekchr()) {
-        '\u0000'.code, Magic.PIPE, Magic.AMP, Magic.RPAREN -> cont = false
-        Magic.c -> {
-          regflags = regflags or RF_ICASE
-          skipchr_keepstart()
-        }
-        Magic.C -> {
-          regflags = regflags or RF_NOICASE
-          skipchr_keepstart()
-        }
-        Magic.v -> {
-          reg_magic = MAGIC_ALL
-          skipchr_keepstart()
-          curchr = -1
-        }
-        Magic.m -> {
-          reg_magic = MAGIC_ON
-          skipchr_keepstart()
-          curchr = -1
-        }
-        Magic.M -> {
-          reg_magic = MAGIC_OFF
-          skipchr_keepstart()
-          curchr = -1
-        }
-        Magic.V -> {
-          reg_magic = MAGIC_NONE
-          skipchr_keepstart()
-          curchr = -1
-        }
-        else -> {
-          latest = regpiece(flags)
-          if (latest == null) {
-            return null
-          }
-          flagp.set(flags.get() and (HASWIDTH or HASNL))
-          chain /* First piece. */?.let { regtail(it, latest) }
-            ?: flagp.set(flags.get() and SPSTART)
-          chain = latest.ref(0)
-          if (first == null) {
-            first = latest.ref(0)
-          }
-        }
-      }
-    }
-    if (first == null) /* Loop ran zero times. */ {
-      first = regnode(NOTHING)
-    }
-    return first
-  }
-
-    /*
-     * regpiece - something followed by possible [*+=]
-     *
-     * Note that the branching code sequences used for = and the general cases
-     * of * and + are somewhat optimized:  they use the same NOTHING node as
-     * both the endmarker for their branch list and the body of the last branch.
-     * It might seem that this node could be dispensed with entirely, but the
-     * endmarker role is not redundant.
-     */
-  private fun regpiece(flagp: Flags): CharPointer? {
-    val ret: CharPointer?
-    val op: Int
-    val next: CharPointer
-    val flags = Flags()
-    ret = regatom(flags)
-    if (ret == null) {
-      return null
-    }
-    op = peekchr()
-    if (re_multi_type(op) == NOT_MULTI) {
-      flagp.init(flags.get())
-      return ret
-    }
-    if (!flags.isSet(HASWIDTH) && re_multi_type(op) == MULTI_MULT) {
-      if (op == Magic.STAR) {
-        EMSG_M_RET_null(Msg.E56, reg_magic >= MAGIC_ON)
-        return null
-      }
-      if (op == Magic.PLUS) {
-        EMSG_M_RET_null(Msg.E57, reg_magic == MAGIC_ALL)
-        return null
-      }
-      /* "\{}" is checked below, it's allowed when there is an upper limit */
-    }
-    flagp.init(WORST or SPSTART or (flags.get() and HASNL)) /* default flags */
-    skipchr()
-    when (op) {
-      Magic.STAR -> if (flags.isSet(SIMPLE)) {
-        reginsert(STAR, ret.ref(0))
-      } else {
-        /* Emit x* as (x&|), where & means "self". */
-        reginsert(BRANCH, ret.ref(0)) /* Either x */
-        regoptail(ret, regnode(BACK)) /* and loop */
-        regoptail(ret, ret) /* back */
-        regtail(ret, regnode(BRANCH)) /* or */
-        regtail(ret, regnode(NOTHING)) /* null. */
-      }
-      Magic.PLUS -> {
-        if (flags.isSet(SIMPLE)) {
-          reginsert(PLUS, ret.ref(0))
-        } else {
-          /* Emit x+ as x(&|), where & means "self". */
-          next = regnode(BRANCH) /* Either */
-          regtail(ret, next)
-          regtail(regnode(BACK), ret) /* loop back */
-          regtail(next, regnode(BRANCH)) /* or */
-          regtail(ret, regnode(NOTHING)) /* null. */
-        }
-        flagp.init(WORST or HASWIDTH or (flags.get() and HASNL))
-      }
-      Magic.AT -> {
-        var lop = END
-        when (Magic.no_Magic(getchr())) {
-          '='.code -> lop = MATCH
-          '!'.code -> lop = NOMATCH
-          '>'.code -> lop = SUBPAT
-          '<'.code -> when (Magic.no_Magic(getchr())) {
-            '='.code -> lop = BEHIND
-            '!'.code -> lop = NOBEHIND
-          }
-        }
-        if (lop == END) {
-          EMSG_M_RET_null(Msg.E59, reg_magic == MAGIC_ALL)
-          return null
-        }
-        /* Look behind must match with behind_pos. */if (lop == BEHIND || lop == NOBEHIND) {
-          regtail(ret, regnode(BHPOS))
-        }
-        regtail(ret, regnode(END)) /* operand ends */
-        reginsert(lop, ret.ref(0))
-      }
-      Magic.QUESTION, Magic.EQUAL -> {
-        /* Emit x= as (x|) */reginsert(BRANCH, ret.ref(0)) /* Either x */
-        regtail(ret, regnode(BRANCH)) /* or */
-        next = regnode(NOTHING) /* null. */
-        regtail(ret, next)
-        regoptail(ret, next)
-      }
-      Magic.LCURLY -> {
-        val limits = read_limits() ?: return null
-        val maxval = limits.maxvalue
-        val minval = limits.minvalue
-        if (!flags.isSet(HASWIDTH) && (if (maxval > minval) maxval >= MAX_LIMIT else minval >= MAX_LIMIT)) {
-          EMSG_M_RET_null(Msg.E58, reg_magic == MAGIC_ALL)
-          return null
-        }
-        if (flags.isSet(SIMPLE)) {
-          reginsert(BRACE_SIMPLE, ret.ref(0))
-          reginsert_limits(BRACE_LIMITS, minval, maxval, ret.ref(0))
-        } else {
-          if (num_complex_braces >= 10) {
-            EMSG_M_RET_null(Msg.E60, reg_magic == MAGIC_ALL)
-            return null
-          }
-          reginsert(BRACE_COMPLEX + num_complex_braces, ret.ref(0))
-          regoptail(ret, regnode(BACK))
-          regoptail(ret, ret)
-          reginsert_limits(BRACE_LIMITS, minval, maxval, ret.ref(0))
-          ++num_complex_braces
-        }
-        if (minval > 0 && maxval > 0) {
-          flagp.init(HASWIDTH or (flags.get() and HASNL))
-        }
-      }
-    }
-    if (re_multi_type(peekchr()) != NOT_MULTI) {
-      /* Can't have a multi follow a multi. */
-      if (peekchr() == Magic.STAR) {
-        val `val` = if (reg_magic >= MAGIC_ON) "" else "\\"
-        injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E61, `val`))
-      } else {
-        val `val` = if (reg_magic >= MAGIC_ON) "" else "\\"
-        injector.messages.showStatusBarMessage(
-          null,
-          injector.messages.message(
-            Msg.E62,
-            `val`,
-            Character.toString(Magic.no_Magic(peekchr()).toChar()),
-          ),
-        )
-      }
-      return null
-    }
-    return ret
-  }
-
-    /*
-     * regatom - the lowest level
-     *
-     * Optimization:  gobbles an entire sequence of ordinary characters so that
-     * it can turn them into a single node, which is smaller to store and
-     * faster to run.  Don't do this when one_exactly is set.
-     */
-  private fun regatom(flagp: Flags): CharPointer? {
-    var ret: CharPointer? = null
-    val flags = Flags()
-    val cpo_lit = false /* 'cpoptions' contains 'l' flag */
-    var c: Int
-    val classchars = ".iIkKfFpPsSdDxXoOwWhHaAlLuU"
-    val classcodes = intArrayOf(
-      ANY, IDENT, SIDENT, KWORD, SKWORD,
-      FNAME, SFNAME, PRINT, SPRINT,
-      WHITE, NWHITE, DIGIT, NDIGIT,
-      HEX, NHEX, OCTAL, NOCTAL,
-      WORD, NWORD, HEAD, NHEAD,
-      ALPHA, NALPHA, LOWER, NLOWER,
-      UPPER, NUPPER,
-    )
-    val p: CharPointer
-    var extra = 0
-    flagp.init(WORST) /* Tentatively. */
-    c = getchr()
-    var doCollection = false
-    var doDefault = false
-    when (c) {
-      Magic.HAT -> ret = regnode(BOL)
-      Magic.DOLLAR -> {
-        ret = regnode(EOL)
-        had_eol = true
-      }
-      Magic.LESS -> ret = regnode(BOW)
-      Magic.GREATER -> ret = regnode(EOW)
-      Magic.UNDER -> {
-        c = Magic.no_Magic(getchr())
-        if (c == '^'.code) /* "\_^" is start-of-line */ {
-          ret = regnode(BOL)
-        }
-        if (c == '$'.code) /* "\_$" is end-of-line */ {
-          ret = regnode(EOL)
-          had_eol = true
-        }
-        extra = ADD_NL
-        flagp.set(HASNL)
-
-        /* "\_[" is character range plus newline */if (c == '['.code) {
-          // goto collection;
-          doCollection = true
-        }
-        val i = classchars.indexOf(Magic.no_Magic(c).toChar())
-        if (i == -1) {
-          injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E63))
-          return null
-        }
-        ret = regnode(classcodes[i] + extra)
-        flagp.set(HASWIDTH or SIMPLE)
-      }
-      Magic.DOT, Magic.i, Magic.I, Magic.k, Magic.K, Magic.f, Magic.F, Magic.p, Magic.P, Magic.s, Magic.S, Magic.d, Magic.D, Magic.x, Magic.X, Magic.o, Magic.O, Magic.w, Magic.W, Magic.h, Magic.H, Magic.a, Magic.A, Magic.l, Magic.L, Magic.u, Magic.U -> {
-        val i = classchars.indexOf(Magic.no_Magic(c).toChar())
-        if (i == -1) {
-          injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E63))
-          return null
-        }
-        ret = regnode(classcodes[i] + extra)
-        flagp.set(HASWIDTH or SIMPLE)
-      }
-      Magic.n -> {
-        ret = regnode(NEWL)
-        flagp.set(HASWIDTH or HASNL)
-      }
-      Magic.LPAREN -> {
-        if (one_exactly) {
-          EMSG_ONE_RET_null()
-          return null
-        }
-        ret = reg(REG_PAREN, flags)
-        if (ret == null) {
-          return null
-        }
-        flagp.set(flags.get() and (HASWIDTH or SPSTART or HASNL))
-      }
-      '\u0000'.code, Magic.PIPE, Magic.AMP, Magic.RPAREN -> {
-        EMSG_RET_null(Msg.e_internal) /* Supposed to be caught earlier. */
-        return null
-      }
-      Magic.EQUAL, Magic.QUESTION, Magic.PLUS, Magic.AT, Magic.LCURLY, Magic.STAR -> {
-        c = Magic.no_Magic(c)
-        val `val` = if (if (c == '*'.code) reg_magic >= MAGIC_ON else reg_magic == MAGIC_ALL) "" else "\\"
-        injector.messages.showStatusBarMessage(
-          null,
-          injector.messages.message(
-            Msg.E64,
-            `val`,
-            Character.toString(c.toChar()),
-          ),
-        )
-        return null
-      }
-      Magic.TILDE -> if (reg_prev_sub != null) {
-        val lp: CharPointer
-        ret = regnode(EXACTLY)
-        lp = reg_prev_sub.ref(0)
-        while (!lp.isNul) {
-          regc(lp.charAt().code)
-        }
-        lp.inc()
-        regc('\u0000'.code)
-        if (!reg_prev_sub.isNul) {
-          flagp.set(HASWIDTH)
-          if (lp.pointer() - reg_prev_sub.pointer() == 1) {
-            flagp.set(SIMPLE)
-          }
-        }
-      } else {
-        injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_nopresub))
-        return null
-      }
-      Magic.N1, Magic.N2, Magic.N3, Magic.N4, Magic.N5, Magic.N6, Magic.N7, Magic.N8, Magic.N9 -> {
-        val refnum: Int
-        refnum = c - Magic.N0
-                /*
-                     * Check if the back reference is legal. We must have seen the
-                     * close brace.
-                     * TODO: Should also check that we don't refer to something
-                     * that is repeated (+*=): what instance of the repetition
-                     * should we match?
-                     */if (!had_endbrace[refnum]) {
-                    /* Trick: check if "@<=" or "@<!" follows, in which case
-                         * the \1 can appear before the referenced match. */
-          p = regparse!!.ref(0)
-          while (!p.isNul) {
-            if (p.charAt(0) == '@' && p.charAt(1) == '<' && (p.charAt(2) == '!' || p.charAt(2) == '=')) {
-              break
-            }
-            p.inc()
-          }
-          if (p.isNul) {
-            EMSG_RET_null(Msg.E65)
-            return null
-          }
-        }
-        ret = regnode(BACKREF + refnum)
-      }
-      Magic.z -> {
-        c = Magic.no_Magic(getchr())
-        when (c) {
-          '('.code -> {
-            if (reg_do_extmatch != REX_SET) {
-              injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E66))
-              return null
-            }
-            if (one_exactly) {
-              EMSG_ONE_RET_null()
-              return null
-            }
-            ret = reg(REG_ZPAREN, flags)
-            if (ret == null) {
-              return null
-            }
-            flagp.set(flags.get() and (HASWIDTH or SPSTART or HASNL))
-            re_has_z = REX_SET.toChar()
-          }
-          '1'.code, '2'.code, '3'.code, '4'.code, '5'.code, '6'.code, '7'.code, '8'.code, '9'.code -> {
-            if (reg_do_extmatch != REX_USE) {
-              injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E67))
-              return null
-            }
-            ret = regnode(ZREF + c - '0'.code)
-            re_has_z = REX_USE.toChar()
-          }
-          's'.code -> ret = regnode(MOPEN)
-          'e'.code -> ret = regnode(MCLOSE)
-          else -> {
-            injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E68))
-            return null
-          }
-        }
-      }
-      Magic.PERCENT -> {
-        c = Magic.no_Magic(getchr())
-        when (c) {
-          '('.code -> {
-            if (one_exactly) {
-              EMSG_ONE_RET_null()
-              return null
-            }
-            ret = reg(REG_NPAREN, flags)
-            if (ret == null) {
-              return null
-            }
-            flagp.set(flags.get() and (HASWIDTH or SPSTART or HASNL))
-          }
-          '^'.code -> ret = regnode(RE_BOF)
-          '$'.code -> ret = regnode(RE_EOF)
-          '#'.code -> ret = regnode(CURSOR)
-          '['.code -> if (one_exactly) /* doesn't nest */ {
-            EMSG_ONE_RET_null()
-            return null
-          } else {
-            val lastbranch: CharPointer
-            var lastnode: CharPointer? = null
-            var br: CharPointer?
-            ret = null
-            while (getchr().also { c = it } != ']'.code) {
-              if (c == '\u0000'.code) {
-                EMSG_M_RET_null(Msg.E69, reg_magic == MAGIC_ALL)
-                return null
-              }
-              br = regnode(BRANCH)
-              if (ret == null) {
-                ret = br.ref(0)
-              } else {
-                regtail(lastnode!!, br)
-              }
-              ungetchr()
-              one_exactly = true
-              lastnode = regatom(flagp)
-              one_exactly = false
-              if (lastnode == null) {
-                return null
-              }
-            }
-            if (ret == null) {
-              EMSG_M_RET_null(Msg.E70, reg_magic == MAGIC_ALL)
-              return null
-            }
-            lastbranch = regnode(BRANCH)
-            br = regnode(NOTHING)
-            regtail(lastnode!!, br)
-            regtail(lastbranch, br)
-                        /* connect all branches to the NOTHING
-                                 * branch at the end */br = ret.ref(0)
-            while (br !== lastnode) {
-              br = if (br!!.OP() == BRANCH) {
-                regtail(br, lastbranch)
-                br.OPERAND()
-              } else {
-                regnext(br)
-              }
-            }
-            flagp.unset(HASWIDTH)
-          }
-          else -> {
-            if (Character.isDigit(c.toChar()) || c == '<'.code || c == '>'.code) {
-              var n = 0
-              val cmp: Int
-              cmp = c
-              if (cmp == '<'.code || cmp == '>'.code) {
-                c = getchr()
-              }
-              while (Character.isDigit(c.toChar())) {
-                n = n * 10 + (c - '0'.code)
-                c = getchr()
-              }
-              if (c == 'l'.code || c == 'c'.code || c == 'v'.code) {
-                ret = if (c == 'l'.code) {
-                  regnode(RE_LNUM)
-                } else if (c == 'c'.code) {
-                  regnode(RE_COL)
-                } else {
-                  regnode(RE_VCOL)
-                }
-
-                                /* put the number and the optional
-                                     * comparator after the opcode */regcode = re_put_long(regcode!!.ref(0), n)
-                regcode!!.set(cmp.toChar()).inc()
-              }
-            }
-            EMSG_M_RET_null(Msg.E71, reg_magic == MAGIC_ALL)
-            return null
-          }
-        }
-      }
-      Magic.LBRACE -> doCollection = true
-      else -> doDefault = true
-    }
-    if (doCollection) {
-      val lp: CharPointer
-
-            /*
-            * If there is no matching ']', we assume the '[' is a normal
-            * character.  This makes 'incsearch' and ":help [" work.
-            */lp = skip_anyof(regparse!!.ref(0))
-      if (lp.charAt() == ']') /* there is a matching ']' */ {
-        var startc = -1 /* > 0 when next '-' is a range */
-        var endc: Int
-
-                /*
-                * In a character class, different parsing rules apply.
-                * Not even \ is special anymore, nothing is.
-                */if (regparse!!.charAt() == '^') /* Complement of range. */ {
-          ret = regnode(ANYBUT + extra)
-          regparse!!.inc()
-        } else {
-          ret = regnode(ANYOF + extra)
-        }
-
-        /* At the start ']' and '-' mean the literal character. */if (regparse!!.charAt() == ']' || regparse!!.charAt() == '-') {
-          regc(regparse!!.charAt().code)
-          regparse!!.inc()
-        }
-        while (!regparse!!.isNul && regparse!!.charAt() != ']') {
-          if (regparse!!.charAt() == '-') {
-            regparse!!.inc()
-                        /* The '-' is not used for a range at the end and
-                        * after or before a '\n'. */if (regparse!!.isNul || regparse!!.charAt() == ']' || startc == -1 ||
-              regparse!!.charAt(0) == '\\' && regparse!!.charAt(1) == 'n'
-            ) {
-              regc('-'.code)
-              startc = '-'.code /* [--x] is a range */
-            } else {
-              // endc = *regparse++;
-              endc = regparse!!.charAt().code
-              regparse!!.inc()
-              if (startc > endc) {
-                injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_invrange))
-                return null
-              }
-              while (++startc <= endc) {
-                regc(startc)
-              }
-              startc = -1
-            }
-          } else if (regparse!!.charAt() == '\\' &&
-            (
-              REGEXP_INRANGE.indexOf(regparse!!.charAt(1)) != -1 || !cpo_lit &&
-                REGEXP_ABBR.indexOf(regparse!!.charAt(1)) != -1
-              )
-          ) {
-            regparse!!.inc()
-            if (regparse!!.charAt() == 'n') {
-              /* '\n' in range: also match NL */
-              if (ret.charAt().code == ANYBUT) {
-                ret.set((ANYBUT + ADD_NL).toChar())
-              } else if (ret.charAt().code == ANYOF) {
-                ret.set((ANYOF + ADD_NL).toChar())
-              }
-              /* else: must have had a \n already */flagp.set(HASNL)
-              regparse!!.inc()
-              startc = -1
-            } else {
-              startc = backslash_trans(regparse!!.charAt().code)
-              regparse!!.inc()
-              regc(startc)
-            }
-          } else if (regparse!!.charAt() == '[') {
-            var c_class: Int
-            var cu: Int
-            c_class = skip_class_name(regparse!!)
-            startc = -1
-            when (c_class) {
-              CharacterClasses.CLASS_NONE -> {
-                /* literal '[', allow [[-x] as a range */startc = regparse!!.charAt().code
-                regparse!!.inc()
-                regc(startc)
-              }
-              CharacterClasses.CLASS_ALNUM -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (Character.isLetterOrDigit(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_ALPHA -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (Character.isLetter(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_BLANK -> {
-                regc(' '.code)
-                regc('\t'.code)
-              }
-              CharacterClasses.CLASS_CNTRL -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (Character.isISOControl(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_DIGIT -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (Character.isDigit(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_GRAPH -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (CharacterClasses.isGraph(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_LOWER -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (Character.isLowerCase(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_PRINT -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (CharacterClasses.isPrint(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_PUNCT -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (CharacterClasses.isPunct(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_SPACE -> {
-                cu = 9
-                while (cu <= 13) {
-                  regc(cu)
-                  cu++
-                }
-                regc(' '.code)
-              }
-              CharacterClasses.CLASS_UPPER -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (Character.isUpperCase(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_XDIGIT -> {
-                cu = 1
-                while (cu <= 255) {
-                  if (CharacterClasses.isHex(cu.toChar())) {
-                    regc(cu)
-                  }
-                  cu++
-                }
-              }
-              CharacterClasses.CLASS_TAB -> regc('\t'.code)
-              CharacterClasses.CLASS_RETURN -> regc('\r'.code)
-              CharacterClasses.CLASS_BACKSPACE -> regc('\b'.code)
-              CharacterClasses.CLASS_ESCAPE -> regc('\u001b'.code)
-            }
-          } else {
-            startc = regparse!!.charAt().code
-            regparse!!.inc()
-            regc(startc)
-          }
-        }
-        regc('\u0000'.code)
-        prevchr_len = 1 /* last char was the ']' */
-        if (regparse!!.charAt() != ']') {
-          injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_toomsbra))
-          return null
-        }
-        skipchr() /* let's be friends with the lexer again */
-        flagp.set(HASWIDTH or SIMPLE)
-      } else {
-        doDefault = true
-      }
-    }
-    /* FALLTHROUGH */if (doDefault) {
-      var len: Int
-      ret = regnode(EXACTLY)
-
-            /*
-            * Append characters as long as:
-            * - there is no following multi, we then need the character in
-            *   front of it as a single character operand
-            * - not running into a Magic character
-            * - "one_exactly" is not set
-            * But always emit at least one character.  Might be a Multi,
-            * e.g., a "[" without matching "]".
-            */len = 0
-      while (c != '\u0000'.code && (
-          len == 0 || re_multi_type(peekchr()) == NOT_MULTI &&
-            !one_exactly && !Magic.is_Magic(c)
-          )
-      ) {
-        c = Magic.no_Magic(c)
-        regc(c)
-        c = getchr()
-        ++len
-      }
-      ungetchr()
-      regc('\u0000'.code)
-      flagp.set(HASWIDTH)
-      if (len == 1) {
-        flagp.set(SIMPLE)
-      }
-    }
-    return ret
-  }
-
-    /*
-     * emit a node
-     * Return pointer to generated code.
-     */
-  private fun regnode(op: Int): CharPointer {
-    val ret: CharPointer
-    ret = regcode!!.ref(0)
-    regcode!!.set(op.toChar()).inc()
-    regcode!!.set('\u0000').inc() /* Null "next" pointer. */
-    regcode!!.set('\u0000').inc()
-    return ret
-  }
-
-    /*
-     * Emit (if appropriate) a byte of code
-     */
-  private fun regc(b: Int) {
-    regcode!!.set(b.toChar()).inc()
-  }
-
-    /*
-     * reginsert - insert an operator in front of already-emitted operand
-     *
-     * Means relocating the operand.
-     */
-  private fun reginsert(op: Int, opnd: CharPointer) {
-    val src: CharPointer
-    val dst: CharPointer
-    val place: CharPointer
-    src = regcode!!.ref(0)
-    regcode!!.inc(3)
-    dst = regcode!!.ref(0)
-    while (src.pointer() > opnd.pointer()) {
-      // *--dst = *--src;
-      dst.dec().set(src.dec().charAt())
-    }
-    place = opnd.ref(0) /* Op node, where operand used to be. */
-    place.set(op.toChar()).inc()
-    place.set('\u0000').inc()
-    place.set('\u0000')
-  }
-
-    /*
-     * reginsert_limits - insert an operator in front of already-emitted operand.
-     * The operator has the given limit values as operands.  Also set next pointer.
-     *
-     * Means relocating the operand.
-     */
-  private fun reginsert_limits(op: Int, minval: Int, maxval: Int, opnd: CharPointer) {
-    val src: CharPointer
-    val dst: CharPointer
-    var place: CharPointer
-    src = regcode!!.ref(0)
-    regcode!!.inc(11)
-    dst = regcode!!.ref(0)
-    while (src.pointer() > opnd.pointer()) {
-      // *--dst = *--src;
-      dst.dec().set(src.dec().charAt())
-    }
-    place = opnd.ref(0) /* Op node, where operand used to be. */
-    place.set(op.toChar()).inc()
-    place.set('\u0000').inc()
-    place.set('\u0000').inc()
-    place = re_put_long(place.ref(0), minval)
-    place = re_put_long(place.ref(0), maxval)
-    regtail(opnd, place)
-  }
-
-    /*
-     * Write a long as four bytes at "p" and return pointer to the next char.
-     */
-  private fun re_put_long(p: CharPointer, `val`: Int): CharPointer {
-    p.set((`val` shr 24 and 0xff).toChar()).inc()
-    p.set((`val` shr 16 and 0xff).toChar()).inc()
-    p.set((`val` shr 8 and 0xff).toChar()).inc()
-    p.set((`val` and 0xff).toChar()).inc()
-    return p
-  }
-
-    /*
-     * regtail - set the next-pointer at the end of a node chain
-     */
-  private fun regtail(p: CharPointer, `val`: CharPointer) {
-    var scan: CharPointer
-    val offset: Int
-
-    /* Find last node. */scan = p.ref(0)
-    while (true) {
-      val temp = regnext(scan) ?: break
-      scan = temp
-    }
-    offset = if (scan.OP() == BACK) {
-      scan.pointer() - `val`.pointer()
-    } else {
-      `val`.pointer() - scan.pointer()
-    }
-    scan.ref(1).set((offset.toChar().code shr 8 and 0xff).toChar())
-    scan.ref(2).set((offset and 0xff).toChar())
-  }
-
-    /*
-     * regoptail - regtail on item after a BRANCH; nop if none
-     */
-  private fun regoptail(p: CharPointer?, `val`: CharPointer) {
-    /* When op is neither BRANCH nor BRACE_COMPLEX0-9, it is "operandless" */
-    if (p == null || p.OP() != BRANCH && (p.OP() < BRACE_COMPLEX || p.OP() > BRACE_COMPLEX + 9)) {
-      return
-    }
-    regtail(p.OPERAND(), `val`)
-  }
-
-  private fun initchr(str: String) {
-    regparse = CharPointer(str)
-    prevchr_len = 0
-    nextchr = -1
-    prevchr = nextchr
-    prevprevchr = prevchr
-    curchr = prevprevchr
-    at_start = true
-    prev_at_start = false
-  }
-
-  private fun peekchr(): Int {
-    if (curchr == -1) {
-      when (regparse!!.charAt(0).also { curchr = it.code }) {
-        '.', '[', '~' -> /* magic when 'magic' is on */if (reg_magic >= MAGIC_ON) {
-          curchr = Magic.magic(curchr)
-        }
-        '(', ')', '{', '%', '+', '=', '?', '@', '!', '&', '|', '<', '>', '#', '"', '\'', ',', '-', ':', ';', '`', '/' -> /* magic only after "\v" */if (reg_magic == MAGIC_ALL) {
-          curchr = Magic.magic(curchr)
-        }
-        '*' -> /* * is not magic as the very first character, eg "?*ptr" and when
-                     * after '^', eg "/^*ptr" */if (reg_magic >= MAGIC_ON && !at_start && !(prev_at_start && prevchr == Magic.HAT)) {
-          curchr = Magic.STAR
-        }
-        '^' -> /* '^' is only magic as the very first character and if it's after
-                     * "\(", "\|", "\&' or "\n" */if (reg_magic >= MAGIC_OFF &&
-          (
-            at_start || reg_magic == MAGIC_ALL || prevchr == Magic.LPAREN || prevchr == Magic.PIPE || prevchr == Magic.AMP || prevchr == Magic.n || Magic.no_Magic(
-              prevchr,
-            ) == '('.code &&
-              prevprevchr == Magic.PERCENT
-            )
-        ) {
-          curchr = Magic.HAT
-          at_start = true
-          prev_at_start = false
-        }
-        '$' -> /* '$' is only magic as the very last char and if it's in front of
-                     * either "\|", "\)", "\&", or "\n" */if (reg_magic >= MAGIC_OFF) {
-          val p = regparse!!.ref(1)
-
-          /* ignore \c \C \m and \M after '$' */while (p.charAt(0) == '\\' && (
-              p.charAt(1) == 'c' || p.charAt(
-                1,
-              ) == 'C' || p.charAt(1) == 'm' || p.charAt(1) == 'M'
-              )
-          ) {
-            p.inc(2)
-          }
-          if (p.charAt(0) == '\u0000' || p.charAt(0) == '\\' &&
-            (p.charAt(1) == '|' || p.charAt(1) == '&' || p.charAt(1) == ')' || p.charAt(1) == 'n') || reg_magic == MAGIC_ALL
-          ) {
-            curchr = Magic.DOLLAR
-          }
-        }
-        '\\' -> {
-          val c = regparse!!.charAt(1).code
-          if (c == '\u0000'.code) {
-            curchr = '\\'.code /* trailing '\' */
-          } else if (c <= '~'.code && META_flags[c] != 0) {
-                        /*
-                             * META contains everything that may be magic sometimes,
-                             * except ^ and $ ("\^" and "\$" are only magic after
-                             * "\v").  We now fetch the next character and toggle its
-                             * magicness.  Therefore, \ is so meta-magic that it is
-                             * not in META.
-                             */
-            curchr = -1
-            prev_at_start = at_start
-            at_start = false /* be able to say "/\*ptr" */
-            regparse!!.inc()
-            peekchr()
-            regparse!!.dec()
-            curchr = Magic.toggle_Magic(curchr)
-          } else if (REGEXP_ABBR.indexOf(c.toChar()) != -1) {
-                        /*
-                             * Handle abbreviations, like "\t" for TAB -- webb
-                             */
-            curchr = backslash_trans(c)
-          } else if (reg_magic == MAGIC_NONE && (c == '$'.code || c == '^'.code)) {
-            curchr = Magic.toggle_Magic(c)
-          } else {
-                        /*
-                             * Next character can never be (made) magic?
-                             * Then backslashing it won't do anything.
-                             */
-            curchr = c
-          }
-        }
-      }
-    }
-    return curchr
-  }
-
-    /*
-     * Eat one lexed character.  Do this in a way that we can undo it.
-     */
-  private fun skipchr() {
-    /* peekchr() eats a backslash, do the same here */
-    prevchr_len = if (regparse!!.charAt() == '\\') {
-      1
-    } else {
-      0
-    }
-    if (regparse!!.charAt(prevchr_len) != '\u0000') {
-      ++prevchr_len
-    }
-    regparse!!.inc(prevchr_len)
-    prev_at_start = at_start
-    at_start = false
-    prevprevchr = prevchr
-    prevchr = curchr
-    curchr = nextchr /* use previously unget char, or -1 */
-    nextchr = -1
-  }
-
-    /*
-     * Skip a character while keeping the value of prev_at_start for at_start.
-     * prevchr and prevprevchr are also kept.
-     */
-  private fun skipchr_keepstart() {
-    val `as` = prev_at_start
-    val pr = prevchr
-    val prpr = prevprevchr
-    skipchr()
-    at_start = `as`
-    prevchr = pr
-    prevprevchr = prpr
-  }
-
-  private fun getchr(): Int {
-    val chr = peekchr()
-    skipchr()
-    return chr
-  }
-
-    /*
-     * put character back.  Works only once!
-     */
-  private fun ungetchr() {
-    nextchr = curchr
-    curchr = prevchr
-    prevchr = prevprevchr
-    at_start = prev_at_start
-    prev_at_start = false
-
-        /* Backup regparse, so that it's at the same position as before the
-         * getchr(). */regparse!!.dec(prevchr_len)
-  }
-
-    /*
-     * read_limits - Read two integers to be taken as a minimum and maximum.
-     * If the first character is '-', then the range is reversed.
-     * Should end with 'end'.  If minval is missing, zero is default, if maxval is
-     * missing, a very big number is the default.
-     */
-  private fun read_limits(): MinMax? {
-    var reverse = false
-    val first_char: CharPointer
-    var minval: Int
-    var maxval: Int
-    if (regparse!!.charAt() == '-') {
-      /* Starts with '-', so reverse the range later */
-      regparse!!.inc()
-      reverse = true
-    }
-    first_char = regparse!!.ref(0)
-    minval = getdigits(regparse!!)
-    maxval = if (regparse!!.charAt() == ',') /* There is a comma */ {
-      if (Character.isDigit(regparse!!.inc().charAt())) {
-        getdigits(regparse!!)
-      } else {
-        MAX_LIMIT
-      }
-    } else if (Character.isDigit(first_char.charAt())) {
-      minval /* It was \{n} or \{-n} */
-    } else {
-      MAX_LIMIT /* It was \{} or \{-} */
-    }
-    if (regparse!!.charAt() == '\\') {
-      regparse!!.inc() /* Allow either \{...} or \{...\} */
-    }
-    if (regparse!!.charAt() != '}' || maxval == 0 && minval == 0) {
-      val `val` = if (reg_magic == MAGIC_ALL) "" else "\\"
-      injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.synerror, `val`))
-      return null
-    }
-
-        /*
-         * Reverse the range if there was a '-', or make sure it is in the right
-         * order otherwise.
-         */if (!reverse && minval > maxval || reverse && minval < maxval) {
-      val tmp = minval
-      minval = maxval
-      maxval = tmp
-    }
-    skipchr() /* let's be friends with the lexer again */
-    val res = MinMax()
-    res.maxvalue = maxval
-    res.minvalue = minval
-    return res
-  }
-
-  private fun getdigits(p: CharPointer): Int {
-    var res = 0
-    var neg = false
-    if (p.charAt() == '-') {
-      neg = true
-      p.inc()
-    }
-    while (Character.isDigit(p.charAt())) {
-      res = res * 10 + p.charAt().digitToIntOrNull()!! ?: -1
-      p.inc()
-    }
-    if (neg) {
-      res = -res
-    }
-    return res
-  }
-
-    /*
-     * vim_regexec and friends
-     */
-    /*
-     * Get pointer to the line "lnum", which is relative to "reg_firstlnum".
-     */
-  private fun reg_getline(lnum: Int): CharPointer? {
-        /* when looking behind for a match/no-match lnum is negative.  But we
-         * can't go before line 1 */
-    return if (reg_firstlnum + lnum < 0) {
-      null
-    } else if (reg_firstlnum + lnum >= reg_buf!!.lineCount()) {
-      // Must have matched the "\n" in the last line.
-      CharPointer("")
-    } else {
-      CharPointer(
-        reg_buf!!.getLineBuffer(reg_firstlnum + lnum),
-      )
-    }
-
-    // return ml_get_buf(reg_buf, reg_firstlnum + lnum, false);
-  }
-
-    /*
-     * Match a regexp against a string.
-     * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
-     * Uses curbuf for line count and 'iskeyword'.
-     *
-     * Return true if there is a match, false if not.
-     */
-  fun vim_regexec(rmp: regmatch_T, line: CharPointer?, col: Int): Boolean {
-    reg_match = rmp
-    reg_mmatch = null
-    reg_maxline = 0
-    // reg_win = null;
-    ireg_ic = rmp.rm_ic
-    return vim_regexec_both(line, col) != 0
-  }
-
-    /*
-     * Match a regexp against multiple lines.
-     * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
-     * Uses curbuf for line count and 'iskeyword'.
-     *
-     * Return zero if there is no match.  Return number of lines contained in the
-     * match otherwise.
-     */
-  fun vim_regexec_multi(
-    rmp: regmmatch_T, /*win_T win,*/
-    buf: VimEditor?,
-    lcount: Int,
-    lnum: Int,
-    col: Int,
-  ): Int /* window in which to search or null */ /* buffer in which to search */ /* nr of line to start looking for match */ /* column to start looking for match */ {
-    val r: Int
-    // VimEditor save_curbuf = curbuf;
-    reg_match = null
-    reg_mmatch = rmp
-    reg_buf = buf
-    // reg_win = win;
-    reg_firstlnum = lnum
-    reg_maxline = lcount - lnum - 1 // Remember, lnum is 0-based, while in Vim, it's 1-based
-    ireg_ic = rmp.rmm_ic
-
-    /* Need to switch to buffer "buf" to make vim_iswordc() work. */
-    // curbuf = buf;
-    r = vim_regexec_both(null, col)
-    // curbuf = save_curbuf;
-    return r
-  }
-
-  fun vim_string_contains_regexp(rmp: regmmatch_T, string: String): Boolean {
-    reg_match = null
-    reg_mmatch = rmp
-    ireg_ic = rmp.rmm_ic
-    val prog: regprog_T?
-    var s: CharPointer
-    var retval = 0
-    reg_tofree = null
-    prog = reg_mmatch!!.regprog
-    val line = CharPointer(string)
-    reg_startpos = reg_mmatch!!.startpos
-    reg_endpos = reg_mmatch!!.endpos
-
-    /* Be paranoid... */if (prog == null) {
-      injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_null))
-      return false
-    }
-
-    /* Check validity of program. */if (prog_magic_wrong()) {
-      return false
-    }
-
-    /* If pattern contains "\c" or "\C": overrule value of ireg_ic */if (prog.regflags and RF_ICASE != 0) {
-      ireg_ic = true
-    } else if (prog.regflags and RF_NOICASE != 0) {
-      ireg_ic = false
-    }
-
-    /* If there is a "must appear" string, look for it. */if (prog.regmust != null) {
-      val c: Char
-      c = prog.regmust!!.charAt()
-      s = line
-      while (cstrchr(s, c).also { s = it!! } != null) {
-        if (cstrncmp(s, prog.regmust!!, prog.regmlen) == 0) {
-          break /* Found it. */
-        }
-        s.inc()
-      }
-      if (s == null) /* Not present. */ {
-        // goto the end;
-        return false
-      }
-    }
-    regline = line.ref(0)
-    reglnum = 0
-    out_of_stack = false
-    val col = 0
-    /* Simplest case: Anchored match need be tried only once. */
-    val c: Char
-    c = regline!!.charAt(col)
-    if (prog.regstart == '\u0000' || prog.regstart == c ||
-      ireg_ic && prog.regstart.lowercaseChar() == c.lowercaseChar()
-    ) {
-      retval = regtry(prog, col)
-    }
-    if (out_of_stack) {
-      injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E363))
-    }
-    return retval > 0
-  }
-
-    /*
-     * Match a regexp against a string ("line" points to the string) or multiple
-     * lines ("line" is null, use reg_getline()).
-     */
-  private fun vim_regexec_both(line: CharPointer?, col: Int): Int /* column to start looking for match */ {
-    var line = line
-    var col = col
-    val prog: regprog_T?
-    var s: CharPointer?
-    var retval: Int
-    reg_tofree = null
-    retval = 0
-    if (reg_match == null) {
-      prog = reg_mmatch!!.regprog
-      line = reg_getline(0)
-      reg_startpos = reg_mmatch!!.startpos
-      reg_endpos = reg_mmatch!!.endpos
-    } else {
-      prog = reg_match!!.regprog
-      reg_startp = reg_match!!.startp
-      reg_endp = reg_match!!.endp
-    }
-
-    /* Be paranoid... */if (prog == null || line == null) {
-      injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_null))
-      return retval
-    }
-
-    /* Check validity of program. */if (prog_magic_wrong()) {
-      return retval
-    }
-
-    /* If pattern contains "\c" or "\C": overrule value of ireg_ic */if (prog.regflags and RF_ICASE != 0) {
-      ireg_ic = true
-    } else if (prog.regflags and RF_NOICASE != 0) {
-      ireg_ic = false
-    }
-
-    /* If there is a "must appear" string, look for it. */if (prog.regmust != null) {
-      val c: Char
-      c = prog.regmust!!.charAt()
-      s = line.ref(col)
-      while (cstrchr(s!!, c).also { s = it } != null) {
-        if (cstrncmp(s!!, prog.regmust!!, prog.regmlen) == 0) {
-          break /* Found it. */
-        }
-        s!!.inc()
-      }
-      if (s == null) /* Not present. */ {
-        // goto theend;
-        return retval
-      }
-    }
-    regline = line.ref(0)
-    reglnum = 0
-    out_of_stack = false
-
-    /* Simplest case: Anchored match need be tried only once. */if (prog.reganch.code != 0) {
-      val c: Char
-      c = regline!!.charAt(col)
-      retval = if (prog.regstart == '\u0000' || prog.regstart == c ||
-        ireg_ic && prog.regstart.lowercaseChar() == c.lowercaseChar()
-      ) {
-        regtry(prog, col)
-      } else {
-        0
-      }
-    } else {
-      /* Messy cases:  unanchored match. */
-      while (!got_int && !out_of_stack) {
-        if (prog.regstart != '\u0000') {
-          /* Skip until the char we know it must start with. */
-          s = cstrchr(regline!!.ref(col), prog.regstart)
-          if (s == null) {
-            retval = 0
-            break
-          }
-          col = s!!.pointer() - regline!!.pointer()
-        }
-        retval = regtry(prog, col)
-        if (retval > 0) {
-          break
-        }
-
-        /* if not currently on the first line, get it again */if (reglnum != 0) {
-          regline = reg_getline(0)
-          reglnum = 0
-        }
-        if (regline!!.charAt(col) == '\u0000') {
-          break
-        }
-        ++col
-      }
-    }
-    if (out_of_stack) {
-      injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.E363))
-    }
-
-    /* Didn't find a match. */
-    // vim_free(reg_tofree);
-    return retval
-  }
-
-  class reg_extmatch_T {
-    var matches = arrayOfNulls<String>(NSUBEXP)
-  }
-
-    /*
-     * Create a new extmatch and mark it as referenced once.
-     */
-  private fun make_extmatch(): reg_extmatch_T {
-    return reg_extmatch_T()
-  }
-
-    /*
-     * Add a reference to an extmatch.
-     */
-    /*
-    private reg_extmatch_T ref_extmatch(reg_extmatch_T em)
-    {
-        return em;
-    }
-    */
-    /*
-     * Remove a reference to an extmatch.  If there are no references left, free
-     * the info.
-     */
-    /*
-    private void unref_extmatch(reg_extmatch_T em)
-    {
-    }
-    */
-    /*
-     * regtry - try match of "prog" with at regline["col"].
-     * Returns 0 for failure, number of lines contained in the match otherwise.
-     */
-  private fun regtry(prog: regprog_T, col: Int): Int {
-    reginput = regline!!.ref(col)
-    need_clear_subexpr = true
-    /* Clear the external match subpointers if necessary. */if (prog.reghasz.code == REX_SET) {
-      need_clear_zsubexpr = true
-    }
-    if (regmatch(CharPointer(prog.program).ref(1))) {
-      cleanup_subexpr()
-      if (reg_match == null) {
-        if (reg_startpos[0]!!.lnum < 0) {
-          reg_startpos[0]!!.lnum = 0
-          reg_startpos[0]!!.col = col
-        }
-        if (reg_endpos[0]!!.lnum < 0) {
-          reg_endpos[0]!!.lnum = reglnum
-          reg_endpos[0]!!.col = reginput!!.pointer() - regline!!.pointer()
-        }
-      } else {
-        if (reg_startp[0] == null) {
-          reg_startp[0] = regline!!.ref(col)
-        }
-        if (reg_endp[0] == null) {
-          reg_endp[0] = reginput
-        }
-      }
-      /* Package any found \z(...\) matches for export. Default is none. */
-      // unref_extmatch(re_extmatch_out);
-      re_extmatch_out = null
-      if (prog.reghasz.code == REX_SET) {
-        var i: Int
-        cleanup_zsubexpr()
-        re_extmatch_out = make_extmatch()
-        i = 0
-        while (i < NSUBEXP) {
-          if (reg_match == null) {
-            /* Only accept single line matches. */
-            if (reg_startzpos[i]!!.lnum >= 0 && reg_endzpos[i]!!.lnum == reg_startzpos[i]!!.lnum) {
-              re_extmatch_out!!.matches[i] = reg_getline(
-                reg_startzpos[i]!!.lnum,
-              )!!.ref(reg_startzpos[i]!!.col).substring(
-                reg_endzpos[i]!!.col - reg_startzpos[i]!!.col,
-              )
-            }
-          } else {
-            if (reg_startzp[i] != null && reg_endzp[i] != null) {
-              re_extmatch_out!!.matches[i] = reg_startzp[i]!!
-                .substring(reg_endzp[i]!!.pointer() - reg_startzp[i]!!.pointer())
-            }
-          }
-          i++
-        }
-      }
-      return 1 + reglnum
-    }
-    return 0
-  }
-
-    /*
-     * regmatch - main matching routine
-     *
-     * Conceptually the strategy is simple: Check to see whether the current
-     * node matches, call self recursively to see whether the rest matches,
-     * and then act accordingly.  In practice we make some effort to avoid
-     * recursion, in particular by going through "ordinary" nodes (that don't
-     * need to know whether the rest of the match failed) by a loop instead of
-     * by recursion.
-     *
-     * Returns true when there is a match.  Leaves reginput and reglnum just after
-     * the last matched character.
-     * Returns false when there is no match.  Leaves reginput and reglnum in an
-     * undefined state!
-     */
-  private fun regmatch(scan: CharPointer?): Boolean {
-    var scan = scan
-    var next: CharPointer? /* Next node. */
-    var op: Int
-    var c: Char
-
-        /* Some patterns my cause a long time to match, even though they are not
-         * illegal.  E.g., "\([a-z]\+\)\+Q".  Allow breaking them with CTRL-C. */
-    // fast_breakcheck(); - TODO
-    while (scan != null) {
-      if (got_int || out_of_stack) {
-        return false
-      }
-      next = regnext(scan)
-      op = scan.OP()
-      /* Check for character class with NL added. */if (WITH_NL(op) && reginput!!.isNul && reglnum < reg_maxline) {
-        reg_nextline()
-      } else {
-        if (WITH_NL(op)) {
-          op -= ADD_NL
-        }
-        c = reginput!!.charAt()
-        when (op) {
-          BOL -> if (!reginput!!.equals(regline)) {
-            return false
-          }
-          EOL -> if (c != '\u0000') {
-            return false
-          }
-          RE_BOF -> /* Passing -1 to the getline() function provided for the search
-                         * should always return null if the current line is the first
-                         * line of the file. */if (reglnum != 0 || !reginput!!.equals(regline) || reg_match == null && reg_getline(
-              -1,
-            ) != null
-          ) {
-            return false
-          }
-          RE_EOF -> if (reglnum != reg_maxline || c != '\u0000') {
-            return false
-          }
-          CURSOR -> {
-                        /* Check if the buffer is in a window and compare the
-                         * reg_win->w_cursor position to the match position. */
-            val curpos = reg_buf!!.currentCaret().getBufferPosition()
-            if (reglnum + reg_firstlnum != curpos.line ||
-              reginput!!.pointer() - regline!!.pointer() != curpos.column
-            ) {
-              return false
-            }
-          }
-          RE_LNUM -> if (reg_match != null || !re_num_cmp(
-              reglnum + reg_firstlnum,
-              scan,
-            )
-          ) {
-            return false
-          }
-          RE_COL -> if (!re_num_cmp(reginput!!.pointer() - regline!!.pointer() + 1, scan)) {
-            return false
-          }
-          RE_VCOL -> {}
-          BOW -> if (c == '\u0000') /* Can't match at end of line */ {
-            return false
-          } else {
-            if (!CharacterClasses.isWord(c) || reginput!!.pointer() > regline!!.pointer() &&
-              CharacterClasses.isWord(reginput!!.charAt(-1))
-            ) {
-              return false
-            }
-          }
-          EOW -> {
-            if (reginput!!.equals(regline)) /* Can't match at start of line */ {
-              return false
-            }
-            if (!CharacterClasses.isWord(reginput!!.charAt(-1))) {
-              return false
-            }
-            if (!reginput!!.isNul && CharacterClasses.isWord(c)) {
-              return false
-            }
-          }
-          ANY -> {
-            if (c == '\u0000') {
-              return false
-            }
-            reginput!!.inc()
-          }
-          IDENT -> {
-            // Character.isJavaIdentifier treats '\0' as a valid identifier!
-            // Also, this should really be using 'isident' instead of Character.isJavaIdentifierPart
-            if (c == '\u0000' || !Character.isJavaIdentifierPart(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          SIDENT -> {
-            if (Character.isDigit(reginput!!.charAt()) || !Character.isJavaIdentifierPart(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          KWORD -> {
-            if (!CharacterClasses.isWord(reginput!!.charAt())) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          SKWORD -> {
-            if (Character.isDigit(reginput!!.charAt()) || !CharacterClasses.isWord(reginput!!.charAt())) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          FNAME -> {
-            if (!CharacterClasses.isFile(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          SFNAME -> {
-            if (Character.isDigit(reginput!!.charAt()) || !CharacterClasses.isFile(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          PRINT -> {
-            if (!CharacterClasses.isPrint(reginput!!.charAt())) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          SPRINT -> {
-            if (Character.isDigit(reginput!!.charAt()) || !CharacterClasses.isPrint(reginput!!.charAt())) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          WHITE -> {
-            if (!CharacterClasses.isWhite(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NWHITE -> {
-            if (c == '\u0000' || CharacterClasses.isWhite(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          DIGIT -> {
-            if (!Character.isDigit(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NDIGIT -> {
-            if (c == '\u0000' || Character.isDigit(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          HEX -> {
-            if (!CharacterClasses.isHex(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NHEX -> {
-            if (c == '\u0000' || CharacterClasses.isHex(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          OCTAL -> {
-            if (!CharacterClasses.isOctal(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NOCTAL -> {
-            if (c == '\u0000' || CharacterClasses.isOctal(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          WORD -> {
-            if (!CharacterClasses.isWord(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NWORD -> {
-            if (c == '\u0000' || CharacterClasses.isWord(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          HEAD -> {
-            if (!CharacterClasses.isHead(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NHEAD -> {
-            if (c == '\u0000' || CharacterClasses.isHead(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          ALPHA -> {
-            if (!CharacterClasses.isAlpha(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NALPHA -> {
-            if (c == '\u0000' || CharacterClasses.isAlpha(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          LOWER -> {
-            if (!CharacterClasses.isLower(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NLOWER -> {
-            if (c == '\u0000' || CharacterClasses.isLower(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          UPPER -> {
-            if (!CharacterClasses.isUpper(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NUPPER -> {
-            if (c == '\u0000' || CharacterClasses.isUpper(c)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          EXACTLY -> {
-            var len: Int
-            var opnd: CharPointer
-            opnd = scan.OPERAND()
-            /* Inline the first byte, for speed. */if (opnd.charAt() != reginput!!.charAt() && (
-                !ireg_ic ||
-                  opnd.charAt().lowercaseChar() != reginput!!.charAt().lowercaseChar()
-                )
-            ) {
-              return false
-            }
-            if (opnd.charAt(1) == '\u0000') {
-              reginput!!.inc() /* matched a single char */
-            } else {
-              len = opnd.strlen()
-              /* Need to match first byte again for multi-byte. */if (cstrncmp(
-                  opnd,
-                  reginput!!,
-                  len,
-                ) != 0
-              ) {
-                return false
-              }
-              reginput!!.inc(len)
-            }
-          }
-          ANYOF, ANYBUT -> {
-            if (c == '\u0000') {
-              return false
-            }
-            if (cstrchr(scan.OPERAND(), c) == null == (op == ANYOF)) {
-              return false
-            }
-            reginput!!.inc()
-          }
-          NOTHING -> {}
-          BACK -> {}
-          MOPEN, MOPEN + 1, MOPEN + 2, MOPEN + 3, MOPEN + 4, MOPEN + 5, MOPEN + 6, MOPEN + 7, MOPEN + 8, MOPEN + 9 -> {
-            val no: Int
-            val save = save_se_T()
-            no = op - MOPEN
-            cleanup_subexpr()
-            save_se(save, reg_startpos[no]!!, reg_startp[no])
-            if (regmatch(next)) {
-              return true
-            }
-            restore_se(save, reg_startpos[no]!!, reg_startp[no])
-            return false
-          }
-          NOPEN, NCLOSE -> return regmatch(next)
-          ZOPEN + 1, ZOPEN + 2, ZOPEN + 3, ZOPEN + 4, ZOPEN + 5, ZOPEN + 6, ZOPEN + 7, ZOPEN + 8, ZOPEN + 9 -> {
-            val no: Int
-            val save = save_se_T()
-            no = op - ZOPEN
-            cleanup_zsubexpr()
-            save_se(save, reg_startzpos[no]!!, reg_startzp[no])
-            if (regmatch(next)) {
-              return true
-            }
-            restore_se(save, reg_startzpos[no]!!, reg_startzp[no])
-            return false
-          }
-          MCLOSE, MCLOSE + 1, MCLOSE + 2, MCLOSE + 3, MCLOSE + 4, MCLOSE + 5, MCLOSE + 6, MCLOSE + 7, MCLOSE + 8, MCLOSE + 9 -> {
-            val no: Int
-            val save = save_se_T()
-            no = op - MCLOSE
-            cleanup_subexpr()
-            save_se(save, reg_endpos[no]!!, reg_endp[no])
-            if (regmatch(next)) {
-              return true
-            }
-            restore_se(save, reg_endpos[no]!!, reg_endp[no])
-            return false
-          }
-          ZCLOSE + 1, ZCLOSE + 2, ZCLOSE + 3, ZCLOSE + 4, ZCLOSE + 5, ZCLOSE + 6, ZCLOSE + 7, ZCLOSE + 8, ZCLOSE + 9 -> {
-            val no: Int
-            val save = save_se_T()
-            no = op - ZCLOSE
-            cleanup_zsubexpr()
-            save_se(save, reg_endzpos[no]!!, reg_endzp[no])
-            if (regmatch(next)) {
-              return true
-            }
-            restore_se(save, reg_endzpos[no]!!, reg_endzp[no])
-            return false
-          }
-          BACKREF + 1, BACKREF + 2, BACKREF + 3, BACKREF + 4, BACKREF + 5, BACKREF + 6, BACKREF + 7, BACKREF + 8, BACKREF + 9 -> {
-            var no: Int
-            var len: Int
-            var clnum: Int
-            var ccol: Int
-            var p: CharPointer?
-            no = op - BACKREF
-            cleanup_subexpr()
-            if (reg_match != null) /* Single-line regexp */ {
-              if (reg_endp[no] == null) {
-                /* Backref was not set: Match an empty string. */
-                len = 0
-              } else {
-                                /* Compare current input with back-ref in the same
-                                     * line. */
-                len = reg_endp[no]!!.pointer() - reg_startp[no]!!.pointer()
-                if (cstrncmp(reg_startp[no]!!, reginput!!, len) != 0) {
-                  return false
-                }
-              }
-            } else /* Multi-line regexp */ {
-              if (reg_endpos[no]!!.lnum < 0) {
-                /* Backref was not set: Match an empty string. */
-                len = 0
-              } else {
-                if (reg_startpos[no]!!.lnum == reglnum &&
-                  reg_endpos[no]!!.lnum == reglnum
-                ) {
-                  /* Compare back-ref within the current line. */
-                  len = reg_endpos[no]!!.col - reg_startpos[no]!!.col
-                  if (cstrncmp(regline!!.ref(reg_startpos[no]!!.col), reginput!!, len) != 0) {
-                    return false
-                  }
-                } else {
-                                    /* Messy situation: Need to compare between two
-                                         * lines. */
-                  ccol = reg_startpos[no]!!.col
-                  clnum = reg_startpos[no]!!.lnum
-                  while (true) {
-                                        /* Since getting one line may invalidate
-                                             * the other, need to make copy.  Slow! */if (!regline!!.equals(reg_tofree)) {
-                      reg_tofree = regline!!.ref(0)
-                      reginput = reg_tofree!!.ref(reginput!!.pointer() - regline!!.pointer())
-                      regline = reg_tofree!!.ref(0)
-                    }
-
-                    /* Get the line to compare with. */p = reg_getline(clnum)
-                    len = if (clnum == reg_endpos[no]!!.lnum) {
-                      reg_endpos[no]!!.col - ccol
-                    } else {
-                      p!!.ref(ccol).strlen()
-                    }
-                    if (cstrncmp(p!!.ref(ccol), reginput!!, len) != 0) {
-                      return false /* doesn't match */
-                    }
-                    if (clnum == reg_endpos[no]!!.lnum) {
-                      break /* match and at end! */
-                    }
-                    if (reglnum == reg_maxline) {
-                      return false /* text too short */
-                    }
-
-                    /* Advance to next line. */reg_nextline()
-                    ++clnum
-                    ccol = 0
-                    if (got_int || out_of_stack) {
-                      return false
-                    }
-                  }
-
-                                    /* found a match!  Note that regline may now point
-                                         * to a copy of the line, that should not matter. */
-                }
-              }
-            }
-
-            /* Matched the backref, skip over it. */reginput!!.inc(len)
-          }
-          ZREF + 1, ZREF + 2, ZREF + 3, ZREF + 4, ZREF + 5, ZREF + 6, ZREF + 7, ZREF + 8, ZREF + 9 -> {
-            var no: Int
-            var len: Int
-            cleanup_zsubexpr()
-            no = op - ZREF
-            val match = re_extmatch_in!!.matches[no]
-            if (re_extmatch_in != null && match != null) {
-              len = match.length
-              if (cstrncmp(CharPointer(match), reginput!!, len) != 0) {
-                return false
-              }
-              reginput!!.inc(len)
-            } else {
-              /* Backref was not set: Match an empty string. */
-            }
-          }
-          BRANCH -> {
-            if (next!!.OP() != BRANCH) /* No choice. */ {
-              next = scan.OPERAND() /* Avoid recursion. */
-            } else {
-              val save = regsave_T()
-              do {
-                reg_save(save)
-                if (regmatch(scan!!.OPERAND())) {
-                  return true
-                }
-                reg_restore(save)
-                scan = regnext(scan)
-              } while (scan != null && scan.OP() == BRANCH)
-              return false
-              /* NOTREACHED */
-            }
-          }
-          BRACE_LIMITS -> {
-            var no: Int
-            if (next!!.OP() == BRACE_SIMPLE) {
-              bl_minval = scan.OPERAND_MIN()
-              bl_maxval = scan.OPERAND_MAX()
-            } else if (next.OP() >= BRACE_COMPLEX &&
-              next.OP() < BRACE_COMPLEX + 10
-            ) {
-              no = next.OP() - BRACE_COMPLEX
-              brace_min[no] = scan.OPERAND_MIN()
-              brace_max[no] = scan.OPERAND_MAX()
-              brace_count[no] = 0
-            } else {
-              injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_internal))
-              return false
-            }
-          }
-          BRACE_COMPLEX, BRACE_COMPLEX + 1, BRACE_COMPLEX + 2, BRACE_COMPLEX + 3, BRACE_COMPLEX + 4, BRACE_COMPLEX + 5, BRACE_COMPLEX + 6, BRACE_COMPLEX + 7, BRACE_COMPLEX + 8, BRACE_COMPLEX + 9 -> {
-            var no: Int
-            val save = regsave_T()
-            no = op - BRACE_COMPLEX
-            ++brace_count[no]
-
-            /* If not matched enough times yet, try one more */if (brace_count[no] <= (if (brace_min[no] <= brace_max[no]) brace_min[no] else brace_max[no])) {
-              reg_save(save)
-              if (regmatch(scan.OPERAND())) {
-                return true
-              }
-              reg_restore(save)
-              --brace_count[no] /* failed, decrement match count */
-              return false
-            }
-
-            /* If matched enough times, may try matching some more */if (brace_min[no] <= brace_max[no]) {
-              /* Range is the normal way around, use longest match */
-              if (brace_count[no] <= brace_max[no]) {
-                reg_save(save)
-                if (regmatch(scan.OPERAND())) {
-                  return true /* matched some more times */
-                }
-                reg_restore(save)
-                --brace_count[no] /* matched just enough times */
-                /* continue with the items after \{} */
-              }
-            } else {
-              /* Range is backwards, use shortest match first */
-              if (brace_count[no] <= brace_min[no]) {
-                reg_save(save)
-                if (regmatch(next)) {
-                  return true
-                }
-                reg_restore(save)
-                next = scan.OPERAND()
-                /* must try to match one more item */
-              }
-            }
-          }
-          BRACE_SIMPLE, STAR, PLUS -> {
-            val nextb: Char /* next byte */
-            val nextb_ic: Char /* next byte reverse case */
-            var count: Int
-            val save = regsave_T()
-            val minval: Int
-            val maxval: Int
-
-                        /*
-                             * Lookahead to avoid useless match attempts when we know
-                             * what character comes next.
-                             */if (next!!.OP() == EXACTLY) {
-              nextb = next.OPERAND().charAt()
-              nextb_ic = if (ireg_ic) {
-                if (Character.isUpperCase(nextb)) {
-                  nextb.lowercaseChar()
-                } else {
-                  nextb.uppercaseChar()
-                }
-              } else {
-                nextb
-              }
-            } else {
-              nextb = '\u0000'
-              nextb_ic = '\u0000'
-            }
-            if (op != BRACE_SIMPLE) {
-              minval = if (op == STAR) 0 else 1
-              maxval = MAX_LIMIT
-            } else {
-              minval = bl_minval
-              maxval = bl_maxval
-            }
-
-                        /*
-                             * When maxval > minval, try matching as much as possible, up
-                             * to maxval.  When maxval < minval, try matching at least the
-                             * minimal number (since the range is backwards, that's also
-                             * maxval!).
-                             */count = regrepeat(scan.OPERAND(), maxval)
-            if (got_int) {
-              return false
-            }
-            if (minval <= maxval) {
-              /* Range is the normal way around, use longest match */
-              while (count >= minval) {
-                /* If it could match, try it. */
-                if (nextb == '\u0000' || reginput!!.charAt() == nextb || reginput!!.charAt() == nextb_ic) {
-                  reg_save(save)
-                  if (regmatch(next)) {
-                    return true
-                  }
-                  reg_restore(save)
-                }
-                /* Couldn't or didn't match -- back up one char. */if (--count < minval) {
-                  break
-                }
-                if (reginput!!.equals(regline)) {
-                  /* backup to last char of previous line */
-                  --reglnum
-                  regline = reg_getline(reglnum)
-                  /* Just in case regrepeat() didn't count right. */if (regline == null) {
-                    return false
-                  }
-                  reginput = regline!!.ref(regline!!.strlen())
-                  // fast_breakcheck(); - TOOD
-                  if (got_int || out_of_stack) {
-                    return false
-                  }
-                } else {
-                  reginput!!.dec()
-                }
-              }
-            } else {
-                            /* Range is backwards, use shortest match first.
-                                 * Careful: maxval and minval are exchanged! */
-              if (count < maxval) {
-                return false
-              }
-              while (true) {
-                /* If it could work, try it. */if (nextb == '\u0000' || reginput!!.charAt() == nextb || reginput!!.charAt() == nextb_ic) {
-                  reg_save(save)
-                  if (regmatch(next)) {
-                    return true
-                  }
-                  reg_restore(save)
-                }
-                /* Couldn't or didn't match: try advancing one char. */if (count == minval || regrepeat(
-                    scan.OPERAND(),
-                    1,
-                  ) == 0
-                ) {
-                  break
-                }
-                ++count
-                if (got_int || out_of_stack) {
-                  return false
-                }
-              }
-            }
-            return false
-          }
-          NOMATCH -> {
-            val save = regsave_T()
-
-                        /* If the operand matches, we fail.  Otherwise backup and
-                             * continue with the next item. */reg_save(save)
-            if (regmatch(scan.OPERAND())) {
-              return false
-            }
-            reg_restore(save)
-          }
-          MATCH, SUBPAT -> {
-            val save = regsave_T()
-
-                        /* If the operand doesn't match, we fail.  Otherwise backup
-                             * and continue with the next item. */reg_save(save)
-            if (!regmatch(scan.OPERAND())) {
-              return false
-            }
-            if (op == MATCH) /* zero-width */ {
-              reg_restore(save)
-            }
-          }
-          BEHIND, NOBEHIND -> {
-            val save_after = regsave_T()
-            val save_start = regsave_T()
-            val save_behind_pos: regsave_T?
-            val needmatch = op == BEHIND
-
-                        /*
-                             * Look back in the input of the operand matches or not. This
-                             * must be done at every position in the input and checking if
-                             * the match ends at the current position.
-                             * First check if the next item matches, that's probably
-                             * faster.
-                             */reg_save(save_start)
-            if (regmatch(next)) {
-              /* save the position after the found match for next */
-              reg_save(save_after)
-
-                            /* start looking for a match with operand at the current
-                                 * postion.  Go back one character until we find the
-                                 * result, hitting the start of the line or the previous
-                                 * line (for multi-line matching).
-                                 * Set behind_pos to where the match should end, BHPOS
-                                 * will match it. */save_behind_pos = if (behind_pos == null) {
-                null
-              } else {
-                regsave_T(
-                  behind_pos!!,
-                )
-              }
-              behind_pos = regsave_T(save_start)
-              while (true) {
-                reg_restore(save_start)
-                if (regmatch(scan.OPERAND()) && reg_save_equal(behind_pos!!)) {
-                  behind_pos = save_behind_pos
-                  /* found a match that ends where "next" started */if (needmatch) {
-                    reg_restore(save_after)
-                    return true
-                  }
-                  return false
-                }
-                                /*
-                                     * No match: Go back one character.  May go to
-                                     * previous line once.
-                                     */if (reg_match == null) {
-                  if (save_start.pos.col == 0) {
-                    if (save_start.pos.lnum < behind_pos!!.pos.lnum ||
-                      reg_getline(--save_start.pos.lnum) == null
-                    ) {
-                      break
-                    }
-                    reg_restore(save_start)
-                    save_start.pos.col = regline!!.strlen()
-                  } else {
-                    --save_start.pos.col
-                  }
-                } else {
-                  if (save_start.ptr === regline) {
-                    break
-                  }
-                  save_start.ptr!!.dec()
-                }
-              }
-
-              /* NOBEHIND succeeds when no match was found */behind_pos = save_behind_pos
-              if (!needmatch) {
-                reg_restore(save_after)
-                return true
-              }
-            }
-            return false
-          }
-          BHPOS -> if (reg_match == null) {
-            if (behind_pos!!.pos.col != reginput!!.pointer() - regline!!.pointer() ||
-              behind_pos!!.pos.lnum != reglnum
-            ) {
-              return false
-            }
-          } else if (behind_pos!!.ptr !== reginput) {
-            return false
-          }
-          NEWL -> {
-            if (c != '\u0000' || reglnum > reg_maxline) {
-              return false
-            }
-            reg_nextline()
-          }
-          END -> return true /* Success! */
-          else -> {
-            injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_re_corr))
-            return false
-          }
-        }
-      }
-      scan = next
-    }
-
-        /*
-         * We get here only if there's trouble -- normally "case END" is the
-         * terminating point.
-         */injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_re_corr))
-    return false
-  }
-
-    /*
-     * regrepeat - repeatedly match something simple, return how many.
-     * Advances reginput (and reglnum) to just after the matched chars.
-     */
-  private fun regrepeat(p: CharPointer, maxcount: Int): Int {
-    var count = 0
-    var scan: CharPointer
-    val opnd: CharPointer
-    var mask = 0
-    var testval = 0
-    scan = reginput!!.ref(0) /* Make local copy of reginput for speed. */
-    opnd = p.OPERAND()
-    when (p.OP()) {
-      ANY, ANY + ADD_NL -> while (count < maxcount) {
-                /* Matching anything means we continue until end-of-line (or
-                     * end-of-file for ANY + ADD_NL), only limited by maxcount. */
-        while (!scan.isNul && count < maxcount) {
-          ++count
-          scan.inc()
-        }
-        if (!WITH_NL(p.OP()) || reglnum > reg_maxline || count == maxcount) {
-          break
-        }
-        ++count /* count the line-break */
-        reg_nextline()
-        scan = reginput!!.ref(0)
-        if (got_int) {
-          break
-        }
-      }
-      IDENT, IDENT + ADD_NL -> {
-        testval = 1
-        while (count < maxcount) {
-          if (Character.isJavaIdentifierPart(scan.charAt()) &&
-            (testval == 1 || !Character.isDigit(scan.charAt()))
-          ) {
-            scan.inc()
-          } else if (scan.isNul) {
-            if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-              break
-            }
-            reg_nextline()
-            scan = reginput!!.ref(0)
-            if (got_int) {
-              break
-            }
-          } else {
-            break
-          }
-          ++count
-        }
-      }
-      SIDENT, SIDENT + ADD_NL -> while (count < maxcount) {
-        if (Character.isJavaIdentifierPart(scan.charAt()) &&
-          (testval == 1 || !Character.isDigit(scan.charAt()))
-        ) {
-          scan.inc()
-        } else if (scan.isNul) {
-          if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-            break
-          }
-          reg_nextline()
-          scan = reginput!!.ref(0)
-          if (got_int) {
-            break
-          }
-        } else {
-          break
-        }
-        ++count
-      }
-      KWORD, KWORD + ADD_NL -> {
-        testval = 1
-        while (count < maxcount) {
-          if (CharacterClasses.isWord(scan.charAt()) && (testval == 1 || !Character.isDigit(scan.charAt()))) {
-            scan.inc()
-          } else if (scan.isNul) {
-            if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-              break
-            }
-            reg_nextline()
-            scan = reginput!!.ref(0)
-            if (got_int) {
-              break
-            }
-          } else {
-            break
-          }
-          ++count
-        }
-      }
-      SKWORD, SKWORD + ADD_NL -> while (count < maxcount) {
-        if (CharacterClasses.isWord(scan.charAt()) && (testval == 1 || !Character.isDigit(scan.charAt()))) {
-          scan.inc()
-        } else if (scan.isNul) {
-          if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-            break
-          }
-          reg_nextline()
-          scan = reginput!!.ref(0)
-          if (got_int) {
-            break
-          }
-        } else {
-          break
-        }
-        ++count
-      }
-      FNAME, FNAME + ADD_NL -> {
-        testval = 1
-        while (count < maxcount) {
-          if (CharacterClasses.isFile(scan.charAt()) && (testval == 1 || !Character.isDigit(scan.charAt()))) {
-            scan.inc()
-          } else if (scan.isNul) {
-            if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-              break
-            }
-            reg_nextline()
-            scan = reginput!!.ref(0)
-            if (got_int) {
-              break
-            }
-          } else {
-            break
-          }
-          ++count
-        }
-      }
-      SFNAME, SFNAME + ADD_NL -> while (count < maxcount) {
-        if (CharacterClasses.isFile(scan.charAt()) && (testval == 1 || !Character.isDigit(scan.charAt()))) {
-          scan.inc()
-        } else if (scan.isNul) {
-          if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-            break
-          }
-          reg_nextline()
-          scan = reginput!!.ref(0)
-          if (got_int) {
-            break
-          }
-        } else {
-          break
-        }
-        ++count
-      }
-      PRINT, PRINT + ADD_NL -> {
-        testval = 1
-        while (count < maxcount) {
-          if (scan.isNul) {
-            if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-              break
-            }
-            reg_nextline()
-            scan = reginput!!.ref(0)
-            if (got_int) {
-              break
-            }
-          } else if (CharacterClasses.isPrint(scan.charAt()) &&
-            (testval == 1 || !Character.isDigit(scan.charAt()))
-          ) {
-            scan.inc()
-          } else {
-            break
-          }
-          ++count
-        }
-      }
-      SPRINT, SPRINT + ADD_NL -> while (count < maxcount) {
-        if (scan.isNul) {
-          if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-            break
-          }
-          reg_nextline()
-          scan = reginput!!.ref(0)
-          if (got_int) {
-            break
-          }
-        } else if (CharacterClasses.isPrint(scan.charAt()) &&
-          (testval == 1 || !Character.isDigit(scan.charAt()))
-        ) {
-          scan.inc()
-        } else {
-          break
-        }
-        ++count
-      }
-      WHITE, WHITE + ADD_NL -> {
-        mask = CharacterClasses.RI_WHITE
-        testval = mask
-      }
-      NWHITE, NWHITE + ADD_NL -> mask = CharacterClasses.RI_WHITE
-      DIGIT, DIGIT + ADD_NL -> {
-        mask = CharacterClasses.RI_DIGIT
-        testval = mask
-      }
-      NDIGIT, NDIGIT + ADD_NL -> mask = CharacterClasses.RI_DIGIT
-      HEX, HEX + ADD_NL -> {
-        mask = CharacterClasses.RI_HEX
-        testval = mask
-      }
-      NHEX, NHEX + ADD_NL -> mask = CharacterClasses.RI_HEX
-      OCTAL, OCTAL + ADD_NL -> {
-        mask = CharacterClasses.RI_OCTAL
-        testval = mask
-      }
-      NOCTAL, NOCTAL + ADD_NL -> mask = CharacterClasses.RI_OCTAL
-      WORD, WORD + ADD_NL -> {
-        mask = CharacterClasses.RI_WORD
-        testval = mask
-      }
-      NWORD, NWORD + ADD_NL -> mask = CharacterClasses.RI_WORD
-      HEAD, HEAD + ADD_NL -> {
-        mask = CharacterClasses.RI_HEAD
-        testval = mask
-      }
-      NHEAD, NHEAD + ADD_NL -> mask = CharacterClasses.RI_HEAD
-      ALPHA, ALPHA + ADD_NL -> {
-        mask = CharacterClasses.RI_ALPHA
-        testval = mask
-      }
-      NALPHA, NALPHA + ADD_NL -> mask = CharacterClasses.RI_ALPHA
-      LOWER, LOWER + ADD_NL -> {
-        mask = CharacterClasses.RI_LOWER
-        testval = mask
-      }
-      NLOWER, NLOWER + ADD_NL -> mask = CharacterClasses.RI_LOWER
-      UPPER, UPPER + ADD_NL -> {
-        mask = CharacterClasses.RI_UPPER
-        testval = mask
-      }
-      NUPPER, NUPPER + ADD_NL -> mask = CharacterClasses.RI_UPPER
-      EXACTLY -> {
-        val cu: Char
-        val cl: Char
-
-                /* This doesn't do a multi-byte character, because a MULTIBYTECODE
-                     * would have been used for it. */if (ireg_ic) {
-          cu = opnd.charAt().uppercaseChar()
-          cl = opnd.charAt().lowercaseChar()
-          while (count < maxcount && (scan.charAt() == cu || scan.charAt() == cl)) {
-            count++
-            scan.inc()
-          }
-        } else {
-          cu = opnd.charAt()
-          while (count < maxcount && scan.charAt() == cu) {
-            count++
-            scan.inc()
-          }
-        }
-      }
-      ANYOF, ANYOF + ADD_NL -> {
-        testval = 1
-        while (count < maxcount) {
-          if (scan.isNul) {
-            if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-              break
-            }
-            reg_nextline()
-            scan = reginput!!.ref(0)
-            if (got_int) {
-              break
-            }
-          } else {
-            if (cstrchr(opnd, scan.charAt()) == null == (testval == 1)) {
-              break
-            }
-            scan.inc()
-          }
-          ++count
-        }
-      }
-      ANYBUT, ANYBUT + ADD_NL -> while (count < maxcount) {
-        if (scan.isNul) {
-          if (!WITH_NL(p.OP()) || reglnum > reg_maxline) {
-            break
-          }
-          reg_nextline()
-          scan = reginput!!.ref(0)
-          if (got_int) {
-            break
-          }
-        } else {
-          if (cstrchr(opnd, scan.charAt()) == null == (testval == 1)) {
-            break
-          }
-          scan.inc()
-        }
-        ++count
-      }
-      NEWL -> while (count < maxcount && scan.isNul && reglnum <= reg_maxline) {
-        count++
-        reg_nextline()
-        scan = reginput!!.ref(0)
-        if (got_int) {
-          break
-        }
-      }
-      else -> injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_re_corr))
-    }
-    if (mask != 0) {
-      while (count < maxcount) {
-        if (scan.isNul) {
-          if (!WITH_NL(p.OP()) || reglnum < reg_maxline) {
-            break
-          }
-          reg_nextline()
-          scan = reginput!!.ref(0)
-          if (got_int) {
-            break
-          }
-        } else if (CharacterClasses.isMask(scan.charAt(), mask, testval)) {
-          scan.inc()
-        } else {
-          break
-        }
-        ++count
-      }
-    }
-    reginput = scan.ref(0)
-    return count
-  }
-
-    /*
-     * regnext - dig the "next" pointer out of a node
-     */
-  private fun regnext(p: CharPointer): CharPointer? {
-    val offset: Int
-    offset = p.NEXT()
-    if (offset == 0) {
-      return null
-    }
-    return if (p.OP() == BACK) {
-      p.ref(-offset)
-    } else {
-      p.ref(offset)
-    }
-  }
-
-    /*
-     * Check the regexp program for its magic number.
-     * Return true if it's wrong.
-     */
-  private fun prog_magic_wrong(): Boolean {
-    if ((if (reg_match == null) reg_mmatch!!.regprog!!.program else reg_match!!.regprog!!.program)[0].code != REGMAGIC) {
-      injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_re_corr))
-      return true
-    }
-    return false
-  }
-
-    /*
-     * Cleanup the subexpressions, if this wasn't done yet.
-     * This construction is used to clear the subexpressions only when they are
-     * used (to increase speed).
-     */
-  private fun cleanup_subexpr() {
-    if (need_clear_subexpr) {
-      if (reg_match == null) {
-        /* Use 0xff to set lnum to -1 */
-        for (i in 0 until NSUBEXP) {
-          reg_startpos[i]!!.col = -1
-          reg_startpos[i]!!.lnum = -1
-          reg_endpos[i]!!.col = -1
-          reg_endpos[i]!!.lnum = -1
-        }
-      } else {
-        for (i in 0 until NSUBEXP) {
-          reg_startp[i] = null
-          reg_endp[i] = null
-        }
-      }
-      need_clear_subexpr = false
-    }
-  }
-
-  private fun cleanup_zsubexpr() {
-    if (need_clear_zsubexpr) {
-      if (reg_match == null) {
-        /* Use 0xff to set lnum to -1 */
-        for (i in 0 until NSUBEXP) {
-          reg_startzpos[i]!!.col = -1
-          reg_startzpos[i]!!.lnum = -1
-          reg_endzpos[i]!!.col = -1
-          reg_endzpos[i]!!.lnum = -1
-        }
-      } else {
-        for (i in 0 until NSUBEXP) {
-          reg_startzp[i] = null
-          reg_endzp[i] = null
-        }
-      }
-      need_clear_zsubexpr = false
-    }
-  }
-
-    /*
-     * Advance reglnum, regline and reginput to the next line.
-     */
-  private fun reg_nextline() {
-    regline = reg_getline(++reglnum)
-    reginput = regline!!.ref(0)
-    // fast_breakcheck(); TODO
-  }
-
-    /*
-     * Save the input line and position in a regsave_T.
-     */
-  private fun reg_save(save: regsave_T) {
-    if (reg_match == null) {
-      save.pos.col = reginput!!.pointer() - regline!!.pointer()
-      save.pos.lnum = reglnum
-    } else {
-      save.ptr = reginput!!.ref(0)
-    }
-  }
-
-    /*
-     * Restore the input line and position from a regsave_T.
-     */
-  private fun reg_restore(save: regsave_T) {
-    if (reg_match == null) {
-      if (reglnum != save.pos.lnum) {
-                /* only call reg_getline() when the line number changed to save
-                 * a bit of time */
-        reglnum = save.pos.lnum
-        regline = reg_getline(reglnum)
-      }
-      reginput = regline!!.ref(save.pos.col)
-    } else {
-      reginput = save.ptr!!.ref(0)
-    }
-  }
-
-    /*
-     * Return true if current position is equal to saved position.
-     */
-  private fun reg_save_equal(save: regsave_T): Boolean {
-    return if (reg_match == null) {
-      reglnum == save.pos.lnum && reginput!!.equals(regline!!.ref(save.pos.col))
-    } else {
-      reginput!!.equals(save.ptr)
-    }
-  }
-
-    /*
-     * Tentatively set the sub-expression start to the current position (after
-     * calling regmatch() they will have changed).  Need to save the existing
-     * values for when there is no match.
-     * Use pointer or position, depending on reg_match == null.
-     */
-  private fun save_se(savep: save_se_T, posp: lpos_T, pp: CharPointer?) {
-    if (reg_match == null) {
-      savep.pos.lnum = posp.lnum
-      savep.pos.col = posp.col
-      posp.lnum = reglnum
-      posp.col = reginput!!.pointer() - regline!!.pointer()
-    } else if (pp != null) {
-      savep.ptr = pp.ref(0)
-      pp.assign(reginput!!)
-    }
-  }
-
-    /*
-     * We were wrong, restore the sub-expressions.
-     */
-  private fun restore_se(savep: save_se_T, posp: lpos_T, pp: CharPointer?) {
-    if (reg_match == null) {
-      posp.col = savep.pos.col
-      posp.lnum = savep.pos.lnum
-    } else {
-      pp?.assign(savep.ptr!!)
-    }
-  }
-
-    /*
-     * Compare a number with the operand of RE_LNUM, RE_COL or RE_VCOL.
-     */
-  private fun re_num_cmp(`val`: Int, scan: CharPointer): Boolean {
-    val n = scan.OPERAND_MIN()
-    if (scan.OPERAND_CMP() == '>') {
-      return `val` > n
-    }
-    return if (scan.OPERAND_CMP() == '<') {
-      `val` < n
-    } else {
-      `val` == n
-    }
-  }
-
-    /*
-     * Compare two strings, ignore case if ireg_ic set.
-     * Return 0 if strings match, non-zero otherwise.
-     */
-  private fun cstrncmp(s1: CharPointer, s2: CharPointer, n: Int): Int {
-    return s1.strncmp(s2, n, ireg_ic)
-  }
-
-    /*
-     * cstrchr: This function is used a lot for simple searches, keep it fast!
-     */
-  private fun cstrchr(s: CharPointer, c: Char): CharPointer? {
-    return if (!ireg_ic) {
-      s.strchr(c)
-    } else {
-      s.istrchr(c)
-    }
-
-        /* tolower() and toupper() can be slow, comparing twice should be a lot
-         * faster (esp. when using MS Visual C++!).
-         * For UTF-8 need to use folded case. */
-        /* was 1,173ms
-        int cc;
-        if (CharacterClasses.isUpper(c))
-        {
-            cc = Character.toLowerCase(c);
-        }
-        else if (CharacterClasses.isLower(c))
-        {
-            cc = Character.toUpperCase(c);
-        }
-        else
-        {
-            return s.strchr(c);
-        }
-        */
-
-    /* Faster version for when there are no multi-byte characters. */
-        /*
-        CharPointer p = s.ref(0);
-        char ch;
-        while ((ch = p.charAt()) != '\u0000')
-        {
-            if (ch == c || ch == cc)
-            {
-                return p;
-            }
-
-            p.inc();
-        }
-        */
-
-        /* was 2,053ms
-        for (p = s.ref(0); !p.isNul(); p.inc())
-        {
-            char ch = p.charAt();
-            if (ch == c || ch == cc)
-            {
-                return p;
-            }
-        }
-        */
-
-    // return null;
-  }
-  /***************************************************************
-   * regsub stuff                             *
-   */
-    /*
-     * regtilde(): Replace tildes in the pattern by the old pattern.
-     *
-     * Short explanation of the tilde: It stands for the previous replacement
-     * pattern.  If that previous pattern also contains a ~ we should go back a
-     * step further...  But we insert the previous pattern into the current one
-     * and remember that.
-     * This still does not handle the case where "magic" changes. TODO?
-     *
-     * The tildes are parsed once before the first call to vim_regsub().
-     */
-  // public CharPointer regtilde(CharPointer source, boolean magic)
-  // {
-  //    CharPointer newsub = source.ref(0);
-  //    CharPointer tmpsub;
-  //    CharPointer p;
-  //    int len;
-  //    int prevlen;
-  //
-  //    for (p = newsub.ref(0); !p.isNul(); p.inc())
-  //    {
-  //        if ((p.charAt() == '~' && magic != 0) || (p.charAt() == '\\' && p.charAt(1) == '~' && magic == 0))
-  //        {
-  //            if (reg_prev_sub != null)
-  //            {
-  //                /* length = len(newsub) - 1 + len(prev_sub) + 1 */
-  //                prevlen = reg_prev_sub.strlen();
-  //                tmpsub = alloc((unsigned)(STRLEN(newsub) + prevlen));
-  //                if (tmpsub != null)
-  //                {
-  //                    /* copy prefix */
-  //                    len = (int)(p - newsub);    /* not including ~ */
-  //                    mch_memmove(tmpsub, newsub, (size_t)len);
-  //                    /* interpretate tilde */
-  //                    mch_memmove(tmpsub + len, reg_prev_sub, (size_t)prevlen);
-  //                    /* copy postfix */
-  //                    if (!magic)
-  //                        ++p;                    /* back off \ */
-  //                    STRCPY(tmpsub + len + prevlen, p + 1);
-  //
-  //                    if (newsub != source)       /* already allocated newsub */
-  //                        vim_free(newsub);
-  //                    newsub = tmpsub;
-  //                    p = newsub + len + prevlen;
-  //                }
-  //            }
-  //            else if (magic)
-  //                STRCPY(p, p + 1);               /* remove '~' */
-  //            else
-  //                STRCPY(p, p + 2);               /* remove '\~' */
-  //            --p;
-  //        }
-  //        else if (*p == '\\' && p[1])            /* skip escaped characters */
-  //        ++p;
-  //    }
-  //
-  //    vim_free(reg_prev_sub);
-  //    if (newsub != source)       /* newsub was allocated, just keep it */
-  //        reg_prev_sub = newsub;
-  //    else                        /* no ~ found, need to save newsub  */
-  //        reg_prev_sub = vim_strsave(newsub);
-  //    return newsub;
-  // }
-  /**
-   * vim_regsub() - perform substitutions after a vim_regexec() or
-   * vim_regexec_multi() match.
-   *
-   *
-   * If "copy" is true really copy into "dest".
-   * If "copy" is false nothing is copied, this is just to find out the length
-   * of the result.
-   *
-   *
-   * If "backslash" is true, a backslash will be removed later, need to double
-   * them to keep them, and insert a backslash before a CR to avoid it being
-   * replaced with a line break later.
-   *
-   *
-   * Note: The matched text must not change between the call of
-   * vim_regexec()/vim_regexec_multi() and vim_regsub()!  It would make the back
-   * references invalid!
-   *
-   *
-   * Returns the size of the replacement, including terminating '\u0000'.
-   */
-  fun vim_regsub(rmp: regmatch_T?, source: CharPointer?, magic: Int, backslash: Boolean): String? {
-    reg_match = rmp
-    reg_mmatch = null
-    reg_maxline = 0
-    return vim_regsub_both(source, magic, backslash)
-  }
-
-  fun vim_regsub_multi(rmp: regmmatch_T?, lnum: Int, source: CharPointer?, magic: Int, backslash: Boolean): String? {
-    reg_match = null
-    reg_mmatch = rmp
-    // reg_buf = curbuf;           /* always works on the current buffer! */
-    reg_firstlnum = lnum
-    reg_maxline = reg_buf!!.lineCount() - lnum - 1 // lnum is 0-based, so make sure maxline is too
-    return vim_regsub_both(source, magic, backslash)
-  }
-
-  private fun subappend(mode: Int, dst: StringBuffer, c: Char): Int {
-    var mode = mode
-    when (mode) {
-      'u'.code -> {
-        mode = 0
-        dst.append(c.uppercaseChar())
-      }
-      'U'.code -> dst.append(c.uppercaseChar())
-      'l'.code -> {
-        mode = 0
-        dst.append(c.lowercaseChar())
-      }
-      'L'.code -> dst.append(c.lowercaseChar())
-      else -> dst.append(c)
-    }
-    return mode
-  }
-
-  private fun vim_regsub_both(source: CharPointer?, magic: Int, backslash: Boolean): String? {
-    val src: CharPointer
-    val dst = StringBuffer()
-    var s: CharPointer?
-    var c: Char
-    var no = -1
-    var clnum = 0 /* init for GCC */
-    var len = 0 /* init for GCC */
-    // CharPointer eval_result = null;
-    var mode = 0
-
-    /* Be paranoid... */if (source == null) {
-      injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_null))
-      return null
-    }
-    if (prog_magic_wrong()) {
-      return null
-    }
-    src = source.ref(0)
-
-        /*
-         * When the substitute part starts with "\=" evaluate it as an expression.
-         */if (source.charAt(0) == '\\' && source.charAt(1) == '=') {
-    } else {
-      while (src.charAt().also { c = it } != '\u0000') {
-        src.inc()
-        if (c == '&' && magic != 0) {
-          no = 0
-        } else if (c == '\\' && !src.isNul) {
-          if (src.charAt() == '&' && magic == 0) {
-            src.inc()
-            no = 0
-          } else if ('0' <= src.charAt() && src.charAt() <= '9') {
-            no = src.charAt() - '0'
-            src.inc()
-          } else if ("uUlLeE".indexOf(src.charAt()) != -1) {
-            when (src.charAtInc()) {
-              'u' -> {
-                mode = 'u'.code
-                continue
-              }
-              'U' -> {
-                mode = 'U'.code
-                continue
-              }
-              'l' -> {
-                mode = 'l'.code
-                continue
-              }
-              'L' -> {
-                mode = 'L'.code
-                continue
-              }
-              'e', 'E' -> {
-                mode = 0
-                continue
-              }
-            }
-          }
-        }
-        if (no < 0) /* Ordinary character. */ {
-          if (c == '\\' && !src.isNul) {
-            /* Check for abbreviations -- webb */
-            // In vim '\u0000' is represented in memory as '\n', and '\n' as '\r', see :help NL-used-for-Nul
-            when (src.charAt()) {
-              'r' -> {
-                c = '\n'
-                src.inc()
-              }
-              'n' -> {
-                c = '\u0000'
-                src.inc()
-              }
-              't' -> {
-                c = '\t'
-                src.inc()
-              }
-              'b' -> {
-                c = '\b'
-                src.inc()
-              }
-              else -> {
-                if (backslash) {
-                  dst.append('\\')
-                }
-                c = src.charAt()
-                src.inc()
-              }
-            }
-          }
-
-          /* Write to buffer, if copy is set. */mode = subappend(mode, dst, c)
-        } else {
-          if (reg_match == null) {
-            clnum = reg_mmatch!!.startpos[no]!!.lnum
-            if (clnum < 0 || reg_mmatch!!.endpos[no]!!.lnum < 0) {
-              s = null
-            } else {
-              s = reg_getline(clnum)!!.ref(reg_mmatch!!.startpos[no]!!.col)
-              len = if (reg_mmatch!!.endpos[no]!!.lnum == clnum) {
-                reg_mmatch!!.endpos[no]!!.col - reg_mmatch!!.startpos[no]!!.col
-              } else {
-                s.strlen()
-              }
-            }
-          } else {
-            s = reg_match!!.startp[no]
-            if (reg_match!!.endp[no] == null) {
-              s = null
-            } else {
-              len = reg_match!!.endp[no]!!.pointer() - s!!.pointer()
-            }
-          }
-          if (s != null) {
-            while (true) {
-              if (len == 0) {
-                if (reg_match == null) {
-                  if (reg_mmatch!!.endpos[no]!!.lnum == clnum) {
-                    break
-                  }
-                  dst.append('\n')
-                  s = reg_getline(++clnum)
-                  len = if (reg_mmatch!!.endpos[no]!!.lnum == clnum) {
-                    reg_mmatch!!.endpos[no]!!.col
-                  } else {
-                    s!!.strlen()
-                  }
-                } else {
-                  break
-                }
-              } else if (s!!.isNul) /* we hit '\u0000'. */ {
-                injector.messages.showStatusBarMessage(null, injector.messages.message(Msg.e_re_damg))
-                return dst.toString()
-              } else {
-                if (backslash && (s.charAt() == '\r' || s.charAt() == '\\')) {
-                                    /*
-                                     * Insert a backslash in front of a CR, otherwise
-                                     * it will be replaced by a line break.
-                                     * Number of backslashes will be halved later,
-                                     * double them here.
-                                     */
-                  dst.append('\\')
-                  dst.append(s.charAt())
-                } else {
-                  mode = subappend(mode, dst, s.charAt())
-                }
-                s.inc()
-                --len
-              }
-            }
-          }
-          no = -1
-        }
-      }
-    }
-    return dst.toString()
-  }
-
-    /*
-     * Used for the submatch() function: get the string from tne n'th submatch in
-     * allocated memory.
-     * Returns null when not in a ":s" command and for a non-existing submatch.
-     */
-    /*
-    public String reg_submatch(int no)
-    {
-        StringBuffer retval = null;
-        CharPointer s;
-        int len;
-        int round;
-        int lnum;
-
-        if (!can_f_submatch)
-            return null;
-
-        if (submatch_match == null)
-        {
-            // First round: compute the length and allocate memory.
-            // Second round: copy the text.
-            for (round = 1; round <= 2; ++round)
-            {
-                lnum = submatch_mmatch.startpos[no].lnum;
-                if (lnum < 0 || submatch_mmatch.endpos[no].lnum < 0)
-                {
-                    return null;
-                }
-
-                s = reg_getline(lnum).ref(submatch_mmatch.startpos[no].col);
-                if (s == null)  // anti-crash check, cannot happen?
-                {
-                    break;
-                }
-                if (submatch_mmatch.endpos[no].lnum == lnum)
-                {
-                    // Within one line: take form start to end col.
-                    len = submatch_mmatch.endpos[no].col - submatch_mmatch.startpos[no].col;
-                    if (round == 2)
-                    {
-                        retval.append(s.substring(len));
-                    }
-                    ++len;
-                }
-                else
-                {
-                    // Multiple lines: take start line from start col, middle
-                    // lines completely and end line up to end col.
-                    len = s.strlen();
-                    if (round == 2)
-                    {
-                        retval.append(s.substring(len));
-                    }
-                    ++len;
-                    ++lnum;
-                    while (lnum < submatch_mmatch.endpos[no].lnum)
-                    {
-                        s = reg_getline(lnum++);
-                        if (round == 2)
-                        {
-                            retval.append(s.substring(s.strlen()));
-                        }
-                        len += s.strlen();
-                        if (round == 2)
-                        {
-                            retval.append('\n');
-                        }
-                        ++len;
-                    }
-                    if (round == 2)
-                    {
-                        retval.append(reg_getline(lnum).substring(submatch_mmatch.endpos[no].col));
-                    }
-                    len += submatch_mmatch.endpos[no].col;
-                    if (round == 2)
-                    {
-                        //retval[len] = '\u0000';
-                    }
-                    ++len;
-                }
-
-                if (round == 1)
-                {
-                    retval = new StringBuffer();
-                    if (s == null)
-                        return null;
-                }
-            }
-        }
-        else
-        {
-            if (submatch_match.endp[no] == null)
-            {
-                retval = null;
-            }
-            else
-            {
-                s = submatch_match.startp[no];
-                retval = new StringBuffer(s.substring(submatch_match.endp[no].pointer() - s.pointer()));
-            }
-        }
-
-        return retval == null ? null : retval.toString();
-    }
-    */
-    /*
-     * regdump - dump a regexp onto stdout in vaguely comprehensible form
-     */
-  private fun regdump(pattern: String, r: regprog_T): String {
-    val start: CharPointer
-    val s: CharPointer
-    var op = EXACTLY /* Arbitrary non-END op. */
-    var next: CharPointer?
-    var end: CharPointer? = null
-    val res = StringBuilder()
-    res.append("\nregcomp(").append(pattern).append("):\n")
-    start = CharPointer(r.program)
-    s = start.ref(1)
-        /*
-        * Loop until we find the END that isn't before a referred next (an END
-        * can also appear in a NOMATCH operand).
-        */while (op != END || !s.end()) {
-      op = s.OP()
-      res.append(s.pointer() - start.pointer())
-      res.append(regprop(s))
-      next = regnext(s)
-      if (next == null) /* Next ptr. */ {
-        res.append("(0)")
-      } else {
-        res.append("(").append(s.pointer() - start.pointer() + (next.pointer() - s.pointer())).append(")")
-      }
-      if (end == null || next != null && end.pointer() < next.pointer()) {
-        end = next
-      }
-      if (op == BRACE_LIMITS) {
-        /* Two short ints */
-        res.append(" minval ")
-        res.append(s.OPERAND_MIN())
-        res.append(", maxval ")
-        res.append(s.OPERAND_MAX())
-        s.inc(8)
-      }
-      s.inc(3)
-      if (op == ANYOF || op == ANYOF + ADD_NL || op == ANYBUT || op == ANYBUT + ADD_NL || op == EXACTLY) {
-        /* Literal string, where present. */
-        while (!s.isNul) {
-          res.append(s.charAt())
-          s.inc()
-        }
-        s.inc()
-      }
-      res.append("\n")
-    }
-
-    /* Header fields of interest. */if (r.regstart != '\u0000') {
-      res.append("start `")
-      if (r.regstart < ' ') {
-        res.append("^").append('@' + r.regstart.code)
-      } else {
-        res.append(r.regstart)
-      }
-      res.append("' ")
-      res.append(Integer.toString(r.regstart.code, 16))
-    }
-    if (r.reganch.code != 0) {
-      res.append("anchored: ")
-    }
-    if (r.regmust != null) {
-      res.append("must have \"").append(r.regmust!!.substring(r.regmust!!.strlen())).append("\"")
-    }
-    res.append("\n")
-    return res.toString()
-  }
-
-    /*
-* regprop - printable representation of opcode
-*/
-  private fun regprop(op: CharPointer): @NonNls String {
-    val p: @NonNls String?
-    val buf = StringBuilder()
-    buf.append(':')
-    p = when (op.OP()) {
-      BOL -> "BOL"
-      EOL -> "EOL"
-      RE_BOF -> "BOF"
-      RE_EOF -> "EOF"
-      CURSOR -> "CURSOR"
-      RE_LNUM -> "RE_LNUM"
-      RE_COL -> "RE_COL"
-      RE_VCOL -> "RE_VCOL"
-      BOW -> "BOW"
-      EOW -> "EOW"
-      ANY -> "ANY"
-      ANY + ADD_NL -> "ANY+NL"
-      ANYOF -> "ANYOF"
-      ANYOF + ADD_NL -> "ANYOF+NL"
-      ANYBUT -> "ANYBUT"
-      ANYBUT + ADD_NL -> "ANYBUT+NL"
-      IDENT -> "IDENT"
-      IDENT + ADD_NL -> "IDENT+NL"
-      SIDENT -> "SIDENT"
-      SIDENT + ADD_NL -> "SIDENT+NL"
-      KWORD -> "KWORD"
-      KWORD + ADD_NL -> "KWORD+NL"
-      SKWORD -> "SKWORD"
-      SKWORD + ADD_NL -> "SKWORD+NL"
-      FNAME -> "FNAME"
-      FNAME + ADD_NL -> "FNAME+NL"
-      SFNAME -> "SFNAME"
-      SFNAME + ADD_NL -> "SFNAME+NL"
-      PRINT -> "PRINT"
-      PRINT + ADD_NL -> "PRINT+NL"
-      SPRINT -> "SPRINT"
-      SPRINT + ADD_NL -> "SPRINT+NL"
-      WHITE -> "WHITE"
-      WHITE + ADD_NL -> "WHITE+NL"
-      NWHITE -> "NWHITE"
-      NWHITE + ADD_NL -> "NWHITE+NL"
-      DIGIT -> "DIGIT"
-      DIGIT + ADD_NL -> "DIGIT+NL"
-      NDIGIT -> "NDIGIT"
-      NDIGIT + ADD_NL -> "NDIGIT+NL"
-      HEX -> "HEX"
-      HEX + ADD_NL -> "HEX+NL"
-      NHEX -> "NHEX"
-      NHEX + ADD_NL -> "NHEX+NL"
-      OCTAL -> "OCTAL"
-      OCTAL + ADD_NL -> "OCTAL+NL"
-      NOCTAL -> "NOCTAL"
-      NOCTAL + ADD_NL -> "NOCTAL+NL"
-      WORD -> "WORD"
-      WORD + ADD_NL -> "WORD+NL"
-      NWORD -> "NWORD"
-      NWORD + ADD_NL -> "NWORD+NL"
-      HEAD -> "HEAD"
-      HEAD + ADD_NL -> "HEAD+NL"
-      NHEAD -> "NHEAD"
-      NHEAD + ADD_NL -> "NHEAD+NL"
-      ALPHA -> "ALPHA"
-      ALPHA + ADD_NL -> "ALPHA+NL"
-      NALPHA -> "NALPHA"
-      NALPHA + ADD_NL -> "NALPHA+NL"
-      LOWER -> "LOWER"
-      LOWER + ADD_NL -> "LOWER+NL"
-      NLOWER -> "NLOWER"
-      NLOWER + ADD_NL -> "NLOWER+NL"
-      UPPER -> "UPPER"
-      UPPER + ADD_NL -> "UPPER+NL"
-      NUPPER -> "NUPPER"
-      NUPPER + ADD_NL -> "NUPPER+NL"
-      BRANCH -> "BRANCH"
-      EXACTLY -> "EXACTLY"
-      NOTHING -> "NOTHING"
-      BACK -> "BACK"
-      END -> "END"
-      MOPEN -> "MATCH START"
-      MOPEN + 1, MOPEN + 2, MOPEN + 3, MOPEN + 4, MOPEN + 5, MOPEN + 6, MOPEN + 7, MOPEN + 8, MOPEN + 9 -> {
-        buf.append("MOPEN").append(op.OP() - MOPEN)
-        null
-      }
-      MCLOSE -> "MATCH END"
-      MCLOSE + 1, MCLOSE + 2, MCLOSE + 3, MCLOSE + 4, MCLOSE + 5, MCLOSE + 6, MCLOSE + 7, MCLOSE + 8, MCLOSE + 9 -> {
-        buf.append("MCLOSE").append(op.OP() - MCLOSE)
-        null
-      }
-      BACKREF + 1, BACKREF + 2, BACKREF + 3, BACKREF + 4, BACKREF + 5, BACKREF + 6, BACKREF + 7, BACKREF + 8, BACKREF + 9 -> {
-        buf.append("BACKREF").append(op.OP() - BACKREF)
-        null
-      }
-      NOPEN -> "NOPEN"
-      NCLOSE -> "NCLOSE"
-      ZOPEN + 1, ZOPEN + 2, ZOPEN + 3, ZOPEN + 4, ZOPEN + 5, ZOPEN + 6, ZOPEN + 7, ZOPEN + 8, ZOPEN + 9 -> {
-        buf.append("ZOPEN").append(op.OP() - ZOPEN)
-        null
-      }
-      ZCLOSE + 1, ZCLOSE + 2, ZCLOSE + 3, ZCLOSE + 4, ZCLOSE + 5, ZCLOSE + 6, ZCLOSE + 7, ZCLOSE + 8, ZCLOSE + 9 -> {
-        buf.append("ZCLOSE").append(op.OP() - ZCLOSE)
-        null
-      }
-      ZREF + 1, ZREF + 2, ZREF + 3, ZREF + 4, ZREF + 5, ZREF + 6, ZREF + 7, ZREF + 8, ZREF + 9 -> {
-        buf.append("ZREF").append(op.OP() - ZREF)
-        null
-      }
-      STAR -> "STAR"
-      PLUS -> "PLUS"
-      NOMATCH -> "NOMATCH"
-      MATCH -> "MATCH"
-      BEHIND -> "BEHIND"
-      NOBEHIND -> "NOBEHIND"
-      SUBPAT -> "SUBPAT"
-      BRACE_LIMITS -> "BRACE_LIMITS"
-      BRACE_SIMPLE -> "BRACE_SIMPLE"
-      BRACE_COMPLEX, BRACE_COMPLEX + 1, BRACE_COMPLEX + 2, BRACE_COMPLEX + 3, BRACE_COMPLEX + 4, BRACE_COMPLEX + 5, BRACE_COMPLEX + 6, BRACE_COMPLEX + 7, BRACE_COMPLEX + 8, BRACE_COMPLEX + 9 -> {
-        buf.append("BRACE_COMPLEX").append(op.OP() - BRACE_COMPLEX)
-        null
-      }
-      NEWL -> "NEWL"
-      else -> {
-        buf.append("corrupt ").append(op.OP())
-        null
-      }
-    }
-    if (p != null) {
-      buf.append(p)
-    }
-    return buf.toString()
-  }
-
-  class regprog_T {
-    var regstart = 0.toChar()
-    var reganch = 0.toChar()
-    var regmust: CharPointer? = null
-    var regmlen = 0
-    var regflags = 0
-    var reghasz = 0.toChar()
-    var program = StringBuffer()
-  }
-
-  private class MinMax {
-    var minvalue = 0
-    var maxvalue = 0
-  }
-
-  class lpos_T {
-    constructor(pos: lpos_T) {
-      lnum = pos.lnum
-      col = pos.col
-    }
-
-    constructor() {}
-
-    @JvmField
-    var lnum = 0
-
-    @JvmField
-    var col = 0
-    override fun toString(): String {
-      return "lpos: ($lnum, $col)"
-    }
-  }
-
-    /*
-    * Structure used to save the current input state, when it needs to be
-    * restored after trying a match.  Used by reg_save() and reg_restore().
-    */
-  private class regsave_T {
-    var ptr /* reginput pointer, for single-line regexp */: CharPointer? = null
-    var pos = lpos_T() /* reginput pos, for multi-line regexp */
-
-    constructor() {}
-    constructor(rhs: regsave_T) {
-      ptr = if (rhs.ptr == null) null else CharPointer("").assign(rhs.ptr!!)
-      pos = lpos_T(rhs.pos)
-    }
-  }
-
-  /* struct to save start/end pointer/position in for \(\) */
-  private class save_se_T {
-    var ptr: CharPointer? = null
-    var pos = lpos_T()
-  }
-
-  class regmatch_T {
-    var regprog: regprog_T? = null
-    var startp = arrayOfNulls<CharPointer>(NSUBEXP)
-    var endp = arrayOfNulls<CharPointer>(NSUBEXP)
-    var rm_ic = false
-  }
-
-  class regmmatch_T {
-    @JvmField
-    var regprog: regprog_T? = null
-
-    @JvmField
-    var startpos = arrayOfNulls<lpos_T>(NSUBEXP)
-
-    @JvmField
-    var endpos = arrayOfNulls<lpos_T>(NSUBEXP)
-
-    @JvmField
-    var rmm_ic = false
-
-    init {
-      for (i in 0 until NSUBEXP) {
-        startpos[i] = lpos_T()
-        endpos[i] = lpos_T()
-      }
-    }
-  }
-
-  private val reg_do_extmatch = 0
-  private val reg_prev_sub: CharPointer? = null
-  private var regparse /* Input-scan pointer. */: CharPointer? = null
-  private var prevchr_len /* byte length of previous char */ = 0
-  private var num_complex_braces /* Complex \{...} count */ = 0
-  private var regnpar /* () count. */ = 0
-  private var regnzpar /* \z() count. */ = 0
-  private var re_has_z /* \z item detected */ = 0.toChar()
-  private var regcode /* Code-emit pointer */: CharPointer? = null
-  private val had_endbrace = BooleanArray(NSUBEXP) /* flags, true if end of () found */
-  private var regflags /* RF_ flags for prog */ = 0
-  private val brace_min = IntArray(10) /* Minimums for complex brace repeats */
-  private val brace_max = IntArray(10) /* Maximums for complex brace repeats */
-  private val brace_count = IntArray(10) /* Current counts for complex brace repeats */
-  private var had_eol /* true when EOL found by vim_regcomp() */ = false
-  private var one_exactly = false /* only do one char for EXACTLY */
-  private var reg_magic /* magicness of the pattern: */ = 0
-  private var curchr = 0
-
-    /*
-    * getchr() - get the next character from the pattern. We know about
-    * magic and such, so therefore we need a lexical analyzer.
-    */
-  /* static int       curchr; */
-  private var prevprevchr = 0
-  private var prevchr = 0
-  private var nextchr /* used for ungetchr() */ = 0
-
-    /*
-    * Note: prevchr is sometimes -1 when we are not at the start,
-    * eg in /[ ^I]^ the pattern was never found even if it existed, because ^ was
-    * taken to be magic -- webb
-    */
-  private var at_start /* True when on the first character */ = false
-  private var prev_at_start /* True when on the second character */ = false
-
-    /*
-    * Global work variables for vim_regexec().
-    */
-  /* The current match-position is remembered with these variables: */
-  private var reglnum /* line number, relative to first line */ = 0
-  private var regline /* start of current line */: CharPointer? = null
-  private var reginput /* current input, points into "regline" */: CharPointer? = null
-  private var need_clear_subexpr /* subexpressions still need to be
-    * cleared */ = false
-  private var need_clear_zsubexpr = false /* extmatch subexpressions
-    * still need to be cleared */
-  private var out_of_stack /* true when ran out of stack space */ = false
-
-    /*
-    * Internal copy of 'ignorecase'.  It is set at each call to vim_regexec().
-    * Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern
-    * contains '\c' or '\C' the value is overruled.
-    */
-  private var ireg_ic = false
-
-    /*
-    * Sometimes need to save a copy of a line.  Since alloc()/free() is very
-    * slow, we keep one allocated piece of memory and only re-allocate it when
-    * it's too small.  It's freed in vim_regexec_both() when finished.
-    */
-  private var reg_tofree: CharPointer? = null
-
-  // private int reg_tofreelen;
-    /*
-    * These variables are set when executing a regexp to speed up the execution.
-    * Which ones are set depends on whethere a single-line or multi-line match is
-    * done:
-    *                      single-line             multi-line
-    * reg_match            &regmatch_T             null
-    * reg_mmatch           null                    &regmmatch_T
-    * reg_startp           reg_match->startp       <invalid>
-    * reg_endp             reg_match->endp         <invalid>
-    * reg_startpos         <invalid>               reg_mmatch->startpos
-    * reg_endpos           <invalid>               reg_mmatch->endpos
-    * reg_win              null                    window in which to search
-    * reg_buf              <invalid>               buffer in which to search
-    * reg_firstlnum        <invalid>               first line in which to search
-    * reg_maxline          0                       last line nr
-    */
-  private var reg_match: regmatch_T? = null
-  private var reg_mmatch: regmmatch_T? = null
-  private var reg_startp = arrayOfNulls<CharPointer>(NSUBEXP)
-  private var reg_endp = arrayOfNulls<CharPointer>(NSUBEXP)
-  private var reg_startpos = arrayOfNulls<lpos_T>(NSUBEXP)
-  private var reg_endpos = arrayOfNulls<lpos_T>(NSUBEXP)
-
-  // static win_T            *reg_win;
-  private var reg_buf: VimEditor? = null
-  private var reg_firstlnum = 0
-  private var reg_maxline = 0
-  private var behind_pos: regsave_T? = null
-  private val reg_startzp = arrayOfNulls<CharPointer>(NSUBEXP) /* Workspace to mark beginning */
-  private val reg_endzp = arrayOfNulls<CharPointer>(NSUBEXP) /*   and end of \z(...\) matches */
-  private val reg_startzpos = arrayOfNulls<lpos_T>(NSUBEXP) /* idem, beginning pos */
-  private val reg_endzpos = arrayOfNulls<lpos_T>(NSUBEXP) /* idem, end pos */
-  private val got_int = false
-
-    /*
-    * The arguments from BRACE_LIMITS are stored here.  They are actually local
-    * to regmatch(), but they are here to reduce the amount of stack space used
-    * (it can be called recursively many times).
-    */
-  private var bl_minval = 0
-  private var bl_maxval = 0
-
-  companion object {
-    var re_extmatch_out: reg_extmatch_T? = null
-    var re_extmatch_in: reg_extmatch_T? = null
-
-        /*
-     * The opcodes are:
-     */
-    /* definition                   number             opnd?    meaning */
-    private const val END = 0 /*      End of program or NOMATCH operand. */
-    private const val BOL = 1 /*      Match "" at beginning of line. */
-    private const val EOL = 2 /*      Match "" at end of line. */
-    private const val BRANCH = 3 /* node Match this alternative, or the next... */
-    private const val BACK = 4 /*      Match "", "next" ptr points backward. */
-    private const val EXACTLY = 5 /* str  Match this string. */
-    private const val NOTHING = 6 /*      Match empty string. */
-    private const val STAR = 7 /* node Match this (simple) thing 0 or more times. */
-    private const val PLUS = 8 /* node Match this (simple) thing 1 or more times. */
-    private const val MATCH = 9 /* node match the operand zero-width */
-    private const val NOMATCH = 10 /* node check for no match with operand */
-    private const val BEHIND = 11 /* node look behind for a match with operand */
-    private const val NOBEHIND = 12 /* node look behind for no match with operand */
-    private const val SUBPAT = 13 /* node match the operand here */
-    private const val BRACE_SIMPLE = 14 /* node Match this (simple) thing between m and
-                                                  *      n times (\{m,n\}). */
-    private const val BOW = 15 /*      Match "" after [^a-zA-Z0-9_] */
-    private const val EOW = 16 /*      Match "" at    [^a-zA-Z0-9_] */
-    private const val BRACE_LIMITS = 17 /* nr nr  define the min & max for BRACE_SIMPLE
-                                                  *      and BRACE_COMPLEX. */
-    private const val NEWL = 18 /*      Match line-break */
-    private const val BHPOS = 19 /*      End position for BEHIND or NOBEHIND */
-
-    /* character classes: 20-48 normal, 50-78 include a line-break */
-    private const val ADD_NL = 30
-    private const val ANY = 20 /*      Match any one character. */
-    private const val FIRST_NL = ANY + ADD_NL
-    private const val ANYOF = 21 /* str  Match any character in this string. */
-    private const val ANYBUT = 22 /* str  Match any character not in this
-                                                  *      string. */
-    private const val IDENT = 23 /*      Match identifier char */
-    private const val SIDENT = 24 /*      Match identifier char but no digit */
-    private const val KWORD = 25 /*      Match keyword char */
-    private const val SKWORD = 26 /*      Match word char but no digit */
-    private const val FNAME = 27 /*      Match file name char */
-    private const val SFNAME = 28 /*      Match file name char but no digit */
-    private const val PRINT = 29 /*      Match printable char */
-    private const val SPRINT = 30 /*      Match printable char but no digit */
-    private const val WHITE = 31 /*      Match whitespace char */
-    private const val NWHITE = 32 /*      Match non-whitespace char */
-    private const val DIGIT = 33 /*      Match digit char */
-    private const val NDIGIT = 34 /*      Match non-digit char */
-    private const val HEX = 35 /*      Match hex char */
-    private const val NHEX = 36 /*      Match non-hex char */
-    private const val OCTAL = 37 /*      Match octal char */
-    private const val NOCTAL = 38 /*      Match non-octal char */
-    private const val WORD = 39 /*      Match word char */
-    private const val NWORD = 40 /*      Match non-word char */
-    private const val HEAD = 41 /*      Match head char */
-    private const val NHEAD = 42 /*      Match non-head char */
-    private const val ALPHA = 43 /*      Match alpha char */
-    private const val NALPHA = 44 /*      Match non-alpha char */
-    private const val LOWER = 45 /*      Match lowercase char */
-    private const val NLOWER = 46 /*      Match non-lowercase char */
-    private const val UPPER = 47 /*      Match uppercase char */
-    private const val NUPPER = 48 /*      Match non-uppercase char */
-    private const val LAST_NL = NUPPER + ADD_NL
-    private const val MOPEN = 80 /* -89       Mark this point in input as start of
-                                                 *       \( subexpr.  MOPEN + 0 marks start of
-                                                 *       match. */
-    private const val MCLOSE = 90 /* -99       Analogous to MOPEN.  MCLOSE + 0 marks
-                                                 *       end of match. */
-    private const val BACKREF = 100 /* -109 node Match same string again \1-\9 */
-    private const val ZOPEN = 110 /* -119      Mark this point in input as start of
-                                                 *       \z( subexpr. */
-    private const val ZCLOSE = 120 /* -129      Analogous to ZOPEN. */
-    private const val ZREF = 130 /* -139 node Match external submatch \z1-\z9 */
-    private const val BRACE_COMPLEX = 140 /* -149 node Match nodes between m & n times */
-    private const val NOPEN = 150 /*      Mark this point in input as start of
-                                                        \%( subexpr. */
-    private const val NCLOSE = 151 /*      Analogous to NOPEN. */
-    private const val RE_BOF = 201 /*      Match "" at beginning of file. */
-    private const val RE_EOF = 202 /*      Match "" at end of file. */
-    private const val CURSOR = 203 /*      Match location of cursor. */
-    private const val RE_LNUM = 204 /* nr cmp  Match line number */
-    private const val RE_COL = 205 /* nr cmp  Match column number */
-    private const val RE_VCOL = 206 /* nr cmp  Match virtual column number */
-    private const val REGMAGIC = 156
-    private const val REX_SET = 1
-    private const val REX_USE = 2
-    private const val MAX_LIMIT = Int.MAX_VALUE
-    private const val NOT_MULTI = 0
-    private const val MULTI_ONE = 1
-    private const val MULTI_MULT = 2
-
-        /*
-    * Flags to be passed up and down.
-    */
-    private const val HASWIDTH = 0x1 /* Known never to match null string. */
-    private const val SIMPLE = 0x2 /* Simple enough to be STAR/PLUS operand. */
-    private const val SPSTART = 0x4 /* Starts with * or +. */
-    private const val HASNL = 0x8 /* Contains some \n. */
-    private const val WORST = 0 /* Worst case. */
-
-        /*
-    * REGEXP_INRANGE contains all characters which are always special in a []
-    * range after '\'.
-    * REGEXP_ABBR contains all characters which act as abbreviations after '\'.
-    * These are:
-    *  \n  - New line (NL).
-    *  \r  - Carriage Return (CR).
-    *  \t  - Tab (TAB).
-    *  \e  - Escape (ESC).
-    *  \b  - Backspace (Ctrl_H).
-    */
-    private const val REGEXP_INRANGE = "]^-n\\"
-    private const val REGEXP_ABBR = "nrteb"
-
-    /* flags for regflags */
-    private const val RF_ICASE = 1 /* ignore case */
-    private const val RF_NOICASE = 2 /* don't ignore case */
-    private const val RF_HASNL = 4 /* can match a NL */
-
-        /*
-     * Global work variables for vim_regcomp().
-     */
-    private const val NSUBEXP = 10
-    private const val MAGIC_NONE = 1 /* "\V" very unmagic */
-    private const val MAGIC_OFF = 2 /* "\M" or 'magic' off */
-    private const val MAGIC_ON = 3 /* "\m" or 'magic' */
-    private const val MAGIC_ALL = 4 /* "\v" very magic */
-
-        /*
-     * META contains all characters that may be magic, except '^' and '$'.
-     */
-    /* META[] is used often enough to justify turning it into a table. */
-    private val META_flags = intArrayOf(
-      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*                 %  &     (  )  *  +        .    */
-      0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, /*     1  2  3  4  5  6  7  8  9        <  =  >  ? */
-      0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, /*  @  A     C  D     F     H  I     K  L  M     O */
-      1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*  P        S     U  V  W  X        [           _ */
-      1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, /*     a     c  d     f     h  i     k  l  m  n  o */
-      0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, /*  p        s     u  v  w  x     z  {  |     ~    */
-      1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,
-    )
-
-    /* arguments for reg() */
-    private const val REG_NOPAREN = 0 /* toplevel reg() */
-    private const val REG_PAREN = 1 /* \(\) */
-    private const val REG_ZPAREN = 2 /* \z(\) */
-    private const val REG_NPAREN = 3 /* \%(\) */
-    private fun WITH_NL(op: Int): Boolean {
-      return op >= FIRST_NL && op <= LAST_NL
-    }
-
-        /*
-     * Check for a character class name.  "pp" points to the '['.
-     * Returns one of the CLASS_ items. CLASS_NONE means that no item was
-     * recognized.  Otherwise "pp" is advanced to after the item.
-     */
-    private fun skip_class_name(pp: CharPointer): Int {
-      var i: Int
-      if (pp.charAt(1) == ':') {
-        i = 0
-        while (i < (CharacterClasses.CLASS_NAMES?.size ?: 0)) {
-          if (pp.ref(2)
-              .strncmp(CharacterClasses.CLASS_NAMES!![i], CharacterClasses.CLASS_NAMES[i].length) == 0
-          ) {
-            pp.inc(CharacterClasses.CLASS_NAMES[i].length + 2)
-            return i
-          }
-          ++i
-        }
-      }
-      return CharacterClasses.CLASS_NONE
-    }
-
-        /*
-     * Skip over a "[]" range.
-     * "p" must point to the character after the '['.
-     * The returned pointer is on the matching ']', or the terminating NUL.
-     */
-    private fun skip_anyof(p: CharPointer): CharPointer {
-      if (p.charAt() == '^') /* Complement of range. */ {
-        p.inc()
-      }
-      if (p.charAt() == ']' || p.charAt() == '-') {
-        p.inc()
-      }
-      while (!p.end() && p.charAt() != ']') {
-        if (p.charAt() == '-') {
-          p.inc()
-          if (!p.end() && p.charAt() != ']') {
-            p.inc()
-          }
-        } else if (p.charAt() == '\\' &&
-          (REGEXP_INRANGE.indexOf(p.charAt(1)) != -1 || REGEXP_ABBR.indexOf(p.charAt(1)) != -1)
-        ) {
-          p.inc(2)
-        } else if (p.charAt() == '[') {
-          if (skip_class_name(p) == CharacterClasses.CLASS_NONE) {
-            p.inc() /* It was not a class name */
-          }
-        } else {
-          p.inc()
-        }
-      }
-      return p
-    }
-
-        /*
-     * Skip past regular expression.
-     * Stop at end of 'p' of where 'dirc' is found ('/', '?', etc).
-     * Take care of characters with a backslash in front of it.
-     * Skip strings inside [ and ].
-     */
-    @JvmStatic
-    fun skip_regexp(p: CharPointer, dirc: Char, magic: Boolean): CharPointer {
-      var p = p
-      var mymagic: Int
-      mymagic = if (magic) {
-        MAGIC_ON
-      } else {
-        MAGIC_OFF
-      }
-      while (!p.end()) {
-        if (p.charAt() == dirc) /* found end of regexp */ {
-          break
-        }
-        if (p.charAt() == '[' && mymagic >= MAGIC_ON ||
-          p.charAt() == '\\' && p.charAt(1) == '[' && mymagic <= MAGIC_OFF
-        ) {
-          p = skip_anyof(p.ref(1))
-          if (p.end()) {
-            break
-          }
-        } else if (p.charAt() == '\\' && p.charAt(1) != '\u0000') {
-          p.inc() /* skip next character */
-          if (p.charAt() == 'v') {
-            mymagic = MAGIC_ALL
-          } else if (p.charAt() == 'V') {
-            mymagic = MAGIC_NONE
-          }
-        }
-        p.inc()
-      }
-      return p
-    }
-
-    // private boolean can_f_submatch = false;      /* true when submatch() can be used */
-        /* These pointers are used instead of reg_match and reg_mmatch for
-    * reg_submatch().  Needed for when the substitution string is an expression
-    * that contains a call to substitute() and submatch(). */
-    // private regmatch_T       submatch_match;
-    // private regmmatch_T      submatch_mmatch;
-    private val logger: VimLogger = injector.getLogger<RegExp>(RegExp::class.java)
-  }
-}
diff --git a/src/main/java/com/maddyhome/idea/vim/ui/ex/ExEntryPanel.java b/src/main/java/com/maddyhome/idea/vim/ui/ex/ExEntryPanel.java
index 4ce35385b..a64d56b8f 100644
--- a/src/main/java/com/maddyhome/idea/vim/ui/ex/ExEntryPanel.java
+++ b/src/main/java/com/maddyhome/idea/vim/ui/ex/ExEntryPanel.java
@@ -31,8 +31,6 @@ import com.maddyhome.idea.vim.helper.SearchHighlightsHelper;
 import com.maddyhome.idea.vim.helper.UiHelper;
 import com.maddyhome.idea.vim.newapi.IjVimCaret;
 import com.maddyhome.idea.vim.newapi.IjVimEditor;
-import com.maddyhome.idea.vim.regexp.CharPointer;
-import com.maddyhome.idea.vim.regexp.RegExp;
 import com.maddyhome.idea.vim.ui.ExPanelBorder;
 import com.maddyhome.idea.vim.vimscript.model.commands.Command;
 import com.maddyhome.idea.vim.vimscript.model.commands.GlobalCommand;