fun processKey()

in vim-engine/src/main/kotlin/com/maddyhome/idea/vim/common/DigraphSequence.kt [51:199]


  fun processKey(key: KeyStroke, editor: VimEditor): DigraphResult {
    return when (digraphState) {
      DigraphState.DIG_STATE_PENDING -> {
        logger.debug("DIG_STATE_PENDING")
        if (key.keyCode == KeyEvent.VK_BACK_SPACE && injector.options(editor).digraph) {
          digraphState = DigraphState.DIG_STATE_BACK_SPACE
        } else if (key.keyChar != KeyEvent.CHAR_UNDEFINED) {
          digraphChar = key.keyChar
        }
        DigraphResult.Unhandled
      }

      DigraphState.DIG_STATE_BACK_SPACE -> {
        logger.debug("DIG_STATE_BACK_SPACE")
        digraphState = DigraphState.DIG_STATE_PENDING
        if (key.keyChar != KeyEvent.CHAR_UNDEFINED) {
          val codepoint = injector.digraphGroup.getCharacterForDigraph(digraphChar, key.keyChar)
          digraphChar = 0.toChar()
          return done(codepoint)
        }
        DigraphResult.Unhandled
      }

      DigraphState.DIG_STATE_DIG_ONE -> {
        logger.debug("DIG_STATE_DIG_ONE")
        if (key.keyChar != KeyEvent.CHAR_UNDEFINED) {
          digraphChar = key.keyChar
          digraphState = DigraphState.DIG_STATE_DIG_TWO
          return handled(digraphChar)
        }
        digraphState = DigraphState.DIG_STATE_PENDING
        DigraphResult.Bad
      }

      DigraphState.DIG_STATE_DIG_TWO -> {
        logger.debug("DIG_STATE_DIG_TWO")
        digraphState = DigraphState.DIG_STATE_PENDING
        if (key.keyChar != KeyEvent.CHAR_UNDEFINED) {
          val codepoint = injector.digraphGroup.getCharacterForDigraph(digraphChar, key.keyChar)
          return done(codepoint)
        }
        DigraphResult.Bad
      }

      DigraphState.DIG_STATE_CODE_START -> {
        logger.debug("DIG_STATE_CODE_START")
        when (key.keyChar) {
          'o', 'O' -> {
            codeMax = 3
            digraphState = DigraphState.DIG_STATE_CODE_CHAR
            codeType = 8
            logger.debug("Octal")
            DigraphResult.HandledLiteral
          }

          'x', 'X' -> {
            codeMax = 2
            digraphState = DigraphState.DIG_STATE_CODE_CHAR
            codeType = 16
            logger.debug("hex2")
            DigraphResult.HandledLiteral
          }

          'u' -> {
            codeMax = 4
            digraphState = DigraphState.DIG_STATE_CODE_CHAR
            codeType = 16
            logger.debug("hex4")
            DigraphResult.HandledLiteral
          }

          'U' -> {
            codeMax = 8
            digraphState = DigraphState.DIG_STATE_CODE_CHAR
            codeType = 16
            logger.debug("hex8")
            DigraphResult.HandledLiteral
          }

          '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> {
            codeMax = 3
            digraphState = DigraphState.DIG_STATE_CODE_CHAR
            codeType = 10
            codeChars[codeCnt++] = key.keyChar
            logger.debug("decimal")
            DigraphResult.HandledLiteral
          }

          else -> {
            digraphState = DigraphState.DIG_STATE_PENDING
            if (key.keyCode == KeyEvent.VK_TAB) {
              return done('\t'.code)
            }
            val codepoint = specialKeyToCodepoint(key)
            if (codepoint != null) {
              return done(codepoint)
            }
            logger.debug("unknown")
            done(key.keyChar.code)
          }
        }
      }

      DigraphState.DIG_STATE_CODE_CHAR -> {
        logger.debug("DIG_STATE_CODE_CHAR")
        var valid = false
        when (codeType) {
          10 -> if (key.keyChar in '0'..'9') {
            valid = true
          }

          8 -> if (key.keyChar in '0'..'7') {
            valid = true
          }

          16 -> if (key.keyChar in '0'..'9' || key.keyChar in 'a'..'f' || key.keyChar in 'A'..'F') {
            valid = true
          }
        }
        if (valid) {
          logger.debug("valid")
          codeChars[codeCnt++] = key.keyChar
          return if (codeCnt == codeMax) {
            digraphState = DigraphState.DIG_STATE_PENDING
            val digits = String(codeChars, 0, codeCnt)
            val codepoint = digits.toInt(codeType)
            done(codepoint)
          } else {
            DigraphResult.HandledLiteral
          }
        } else if (codeCnt > 0) {
          logger.debug("invalid")
          digraphState = DigraphState.DIG_STATE_PENDING
          val digits = String(codeChars, 0, codeCnt)
          val codepoint = digits.toInt(codeType)
          if (!injector.application.isUnitTest()) {
            // The key we received isn't part of the literal, so post it to be handled after we've handled the literal.
            // This requires swing, so we can't run it in tests.
            injector.application.postKey(key, editor)
          }
          return done(codepoint)
        } else if (codeCnt == 0) {
          digraphState = DigraphState.DIG_STATE_PENDING
          return specialKeyToCodepoint(key)?.let { done(it) } ?: done(key.keyChar.code)
        }
        DigraphResult.Bad
      }
    }
  }