shellmatta_escape.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
  3. *
  4. * This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  7. */
  8. /**
  9. * @file shellmatta_escape.c
  10. * @brief functions to parse and generate escape sequences
  11. * @author Stefan Strobel <stefan.strobel@shimatta.net>
  12. */
  13. /**
  14. * @addtogroup shellmatta_escape
  15. * @{
  16. */
  17. #include "shellmatta.h"
  18. #include "shellmatta_escape.h"
  19. #include "shellmatta_utils.h"
  20. #include "shellmatta_history.h"
  21. #include "shellmatta_autocomplete.h"
  22. #include <stdint.h>
  23. /**
  24. * @brief processes the excape character stream of the instance and chacks
  25. * if an arrow key was pressed
  26. * @param[in] inst pointer to a shellmatta instance
  27. * @return #SHELLMATTA_OK if an arrow key was pressed
  28. */
  29. shellmatta_retCode_t escape_processArrowKeys(shellmatta_instance_t *inst)
  30. {
  31. shellmatta_retCode_t ret = SHELLMATTA_USE_FAULT;
  32. if ('[' == inst->escapeChars[0])
  33. {
  34. ret = SHELLMATTA_OK;
  35. switch (inst->escapeChars[1])
  36. {
  37. case 'A': /* arrow up */
  38. history_storeCmd(inst);
  39. if(false == inst->historyReadUp)
  40. {
  41. history_navigate(inst, -1);
  42. }
  43. inst->historyReadUp = true;
  44. utils_clearInput(inst);
  45. history_restoreCmd(inst);
  46. history_navigate(inst, -1);
  47. break;
  48. case 'B': /* arrow down */
  49. if((inst->historyRead != inst->historyEnd))
  50. {
  51. history_storeCmd(inst);
  52. if(true == inst->historyReadUp)
  53. {
  54. history_navigate(inst, 1);
  55. }
  56. inst->historyReadUp = false;
  57. history_navigate(inst, 1);
  58. utils_clearInput(inst);
  59. history_restoreCmd(inst);
  60. }
  61. break;
  62. case 'C': /* arrow right */
  63. utils_forwardCursor(inst, 1u);
  64. break;
  65. case 'D': /* arrow left */
  66. utils_rewindCursor(inst, 1u);
  67. break;
  68. default:
  69. /** ignore unknown escape */
  70. ret = SHELLMATTA_USE_FAULT;
  71. break;
  72. }
  73. }
  74. return ret;
  75. }
  76. /**
  77. * @brief handles a ANSI escape sequence to be able to react to some
  78. * special keys
  79. * @param[in] inst pointer to a shellmatta instance
  80. * @param[in] data new received character of the escape sequence
  81. */
  82. void escape_handleSequence(shellmatta_instance_t *inst, char data)
  83. {
  84. switch (inst->escapeCounter)
  85. {
  86. case 1u:
  87. inst->escapeChars[inst->escapeCounter - 1] = data;
  88. inst->escapeCounter ++;
  89. break;
  90. case 2u:
  91. inst->escapeChars[inst->escapeCounter - 1] = data;
  92. /** -# check if an arrow key was pressed */
  93. if(SHELLMATTA_OK == escape_processArrowKeys(inst))
  94. {
  95. inst->escapeCounter = 0u;
  96. }
  97. /** -# check if end was pressed */
  98. else if ( (0x4f == inst->escapeChars[0])
  99. && (0x46 == inst->escapeChars[1]))
  100. {
  101. utils_forwardCursor(inst, inst->inputCount - inst->cursor);
  102. inst->escapeCounter = 0u;
  103. }
  104. /** -# if the highest bit is not set this is usually not the end of the
  105. * sequence - so we go on */
  106. else if(0u == (0x40 & data))
  107. {
  108. inst->escapeCounter ++;
  109. }
  110. else
  111. {
  112. inst->escapeCounter = 0u;
  113. }
  114. break;
  115. case 3u:
  116. /** -# check if delete was pressed */
  117. inst->escapeChars[inst->escapeCounter - 1] = data;
  118. if( (0x5b == inst->escapeChars[0])
  119. && (0x33 == inst->escapeChars[1])
  120. && (0x7e == inst->escapeChars[2]))
  121. {
  122. utils_removeChars(inst, 1u, false);
  123. inst->escapeCounter = 0u;
  124. }
  125. /** -# check if pos1 was pressed */
  126. else if ( (0x5bu == inst->escapeChars[0])
  127. && (0x31u == inst->escapeChars[1])
  128. && (0x7eu == inst->escapeChars[2]))
  129. {
  130. utils_rewindCursor(inst, inst->cursor);
  131. inst->escapeCounter = 0u;
  132. }
  133. else if(0u == (0x40u & data))
  134. {
  135. inst->escapeCounter ++;
  136. }
  137. else
  138. {
  139. inst->escapeCounter = 0u;
  140. }
  141. break;
  142. default:
  143. inst->escapeCounter = 0u;
  144. break;
  145. }
  146. }
  147. /**
  148. * @}
  149. */