/* * Copyright (c) 2019 Stefan Strobel * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /** * @file shellmatta_escape.c * @brief functions to parse and generate escape sequences * @author Stefan Strobel */ /** * @addtogroup shellmatta_escape * @{ */ #include "shellmatta.h" #include "shellmatta_escape.h" #include "shellmatta_utils.h" #include "shellmatta_history.h" #include "shellmatta_autocomplete.h" #include /** * @brief processes the excape character stream of the instance and chacks * if an arrow key was pressed * @param[in] inst pointer to a shellmatta instance * @return #SHELLMATTA_OK if an arrow key was pressed */ shellmatta_retCode_t escape_processArrowKeys(shellmatta_instance_t *inst) { shellmatta_retCode_t ret = SHELLMATTA_USE_FAULT; if ('[' == inst->escapeChars[0]) { ret = SHELLMATTA_OK; switch (inst->escapeChars[1]) { case 'A': /* arrow up */ history_storeCmd(inst); if(false == inst->historyReadUp) { history_navigate(inst, -1); } inst->historyReadUp = true; utils_clearInput(inst); history_restoreCmd(inst); history_navigate(inst, -1); break; case 'B': /* arrow down */ if((inst->historyRead != inst->historyEnd)) { history_storeCmd(inst); if(true == inst->historyReadUp) { history_navigate(inst, 1); } inst->historyReadUp = false; history_navigate(inst, 1); utils_clearInput(inst); history_restoreCmd(inst); } break; case 'C': /* arrow right */ utils_forwardCursor(inst, 1u); break; case 'D': /* arrow left */ utils_rewindCursor(inst, 1u); break; default: /** ignore unknown escape */ ret = SHELLMATTA_USE_FAULT; break; } } return ret; } /** * @brief handles a ANSI escape sequence to be able to react to some * special keys * @param[in] inst pointer to a shellmatta instance * @param[in] data new received character of the escape sequence */ void escape_handleSequence(shellmatta_instance_t *inst, char data) { switch (inst->escapeCounter) { case 1u: inst->escapeChars[inst->escapeCounter - 1] = data; inst->escapeCounter ++; break; case 2u: inst->escapeChars[inst->escapeCounter - 1] = data; /** -# check if an arrow key was pressed */ if(SHELLMATTA_OK == escape_processArrowKeys(inst)) { inst->escapeCounter = 0u; } /** -# check if end was pressed */ else if ( (0x4f == inst->escapeChars[0]) && (0x46 == inst->escapeChars[1])) { utils_forwardCursor(inst, inst->inputCount - inst->cursor); inst->escapeCounter = 0u; } /** -# if the highest bit is not set this is usually not the end of the * sequence - so we go on */ else if(0u == (0x40 & data)) { inst->escapeCounter ++; } else { inst->escapeCounter = 0u; } break; case 3u: /** -# check if delete was pressed */ inst->escapeChars[inst->escapeCounter - 1] = data; if( (0x5b == inst->escapeChars[0]) && (0x33 == inst->escapeChars[1]) && (0x7e == inst->escapeChars[2])) { utils_removeChars(inst, 1u, false); inst->escapeCounter = 0u; } /** -# check if pos1 was pressed */ else if ( (0x5bu == inst->escapeChars[0]) && (0x31u == inst->escapeChars[1]) && (0x7eu == inst->escapeChars[2])) { utils_rewindCursor(inst, inst->cursor); inst->escapeCounter = 0u; } else if(0u == (0x40u & data)) { inst->escapeCounter ++; } else { inst->escapeCounter = 0u; } break; default: inst->escapeCounter = 0u; break; } } /** * @} */