chry_readline.c 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359
  1. /*
  2. * Copyright (c) 2022, Egahp
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdio.h>
  7. #include <stdarg.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <stdbool.h>
  11. #include "chry_readline.h"
  12. #if defined(__CC_ARM) || defined(__CLANG_ARM) || defined(__GNUC__) || defined(__ADSPBLACKFIN__)
  13. #ifndef __unused
  14. #define __unused __attribute__((unused))
  15. #endif
  16. #else
  17. #ifndef __unused
  18. #define __unused
  19. #endif
  20. #endif
  21. #define chry_readline_waitkey(__rl, __c) \
  22. do { \
  23. while (0 == (__rl)->sget((__rl), (__c), 1)) \
  24. ; \
  25. } while (0)
  26. #if defined(CONFIG_READLINE_NOBLOCK) && CONFIG_READLINE_NOBLOCK
  27. #define chry_readline_getkey(__rl, __c) \
  28. do { \
  29. (__rl)->noblock = 0 == (__rl)->sget((__rl), (__c), 1); \
  30. } while (0)
  31. #else
  32. #define chry_readline_getkey chry_readline_waitkey
  33. #endif
  34. #if defined(CONFIG_READLINE_DEBUG) && CONFIG_READLINE_DEBUG
  35. #define CHRY_READLINE_PARAM_CHECK(__expr, __ret) \
  36. do { \
  37. if (!(__expr)) { \
  38. return __ret; \
  39. } \
  40. } while (0)
  41. #define chry_readline_put(__rl, __pbuf, __size, __ret) \
  42. do { \
  43. uint16_t _size_ = (__size); \
  44. if (_size_ != (__rl)->sput((__rl), (__pbuf), _size_)) { \
  45. return __ret; \
  46. } \
  47. } while (0)
  48. #else
  49. #define CHRY_READLINE_PARAM_CHECK(__expr, __ret) ((void)0)
  50. #define chry_readline_put(__rl, __pbuf, __size, __ret) \
  51. do { \
  52. (__rl)->sput((__rl), (__pbuf), (__size)); \
  53. } while (0)
  54. #endif
  55. #define chry_readline_seqgen_ris chry_readline_seqgen_reset
  56. #define chry_readline_seqgen_cuu chry_readline_seqgen_cursor_up
  57. #define chry_readline_seqgen_cud chry_readline_seqgen_cursor_down
  58. #define chry_readline_seqgen_cuf chry_readline_seqgen_cursor_forward
  59. #define chry_readline_seqgen_cub chry_readline_seqgen_cursor_backward
  60. #define chry_readline_seqgen_cnl chry_readline_seqgen_cursor_nextline
  61. #define chry_readline_seqgen_cpl chry_readline_seqgen_cursor_prevline
  62. #define chry_readline_seqgen_cha chry_readline_seqgen_cursor_absolute
  63. #define chry_readline_seqgen_cup chry_readline_seqgen_cursor_position
  64. #define chry_readline_seqgen_ed chry_readline_seqgen_erase_display
  65. #define chry_readline_seqgen_el chry_readline_seqgen_erase_line
  66. #define chry_readline_seqgen_il chry_readline_seqgen_insert_line
  67. #define chry_readline_seqgen_dl chry_readline_seqgen_delete_line
  68. #define chry_readline_seqgen_dch chry_readline_seqgen_delete_char
  69. #define chry_readline_seqgen_ech chry_readline_seqgen_erase_char
  70. #define chry_readline_seqgen_su chry_readline_seqgen_scroll_up
  71. #define chry_readline_seqgen_sd chry_readline_seqgen_scroll_down
  72. #define chry_readline_seqgen_scp chry_readline_seqgen_save_cursor_position
  73. #define chry_readline_seqgen_rcp chry_readline_seqgen_restore_cursor_position
  74. #define chry_readline_seqgen_nsb chry_readline_seqgen_normal_screen
  75. #define chry_readline_seqgen_asb chry_readline_seqgen_alternate_screen
  76. #define chry_readline_seqgen_rss chry_readline_seqgen_report_screen_size
  77. static const uint8_t vtmap[25] = {
  78. CHRY_READLINE_EXEC_NUL, /*!< 0 */
  79. CHRY_READLINE_EXEC_MVHM, /*!< 1 home */
  80. CHRY_READLINE_EXEC_NUL, /*!< 2 insert */
  81. CHRY_READLINE_EXEC_DEL, /*!< 3 delete */
  82. CHRY_READLINE_EXEC_MVED, /*!< 4 end */
  83. CHRY_READLINE_EXEC_NUL, /*!< 5 page up */
  84. CHRY_READLINE_EXEC_NUL, /*!< 6 page dn */
  85. CHRY_READLINE_EXEC_MVHM, /*!< 7 home */
  86. CHRY_READLINE_EXEC_MVED, /*!< 8 end */
  87. CHRY_READLINE_EXEC_NUL, /*!< 9 */
  88. CHRY_READLINE_EXEC_NUL, /*!< 10 */
  89. CHRY_READLINE_EXEC_F1, /*!< 11 F1 */
  90. CHRY_READLINE_EXEC_F2, /*!< 12 F2 */
  91. CHRY_READLINE_EXEC_F3, /*!< 13 F3 */
  92. CHRY_READLINE_EXEC_F4, /*!< 14 F4 */
  93. CHRY_READLINE_EXEC_F5, /*!< 15 F5 */
  94. CHRY_READLINE_EXEC_NUL, /*!< 16 */
  95. CHRY_READLINE_EXEC_F6, /*!< 17 F6 */
  96. CHRY_READLINE_EXEC_F7, /*!< 18 F7 */
  97. CHRY_READLINE_EXEC_F8, /*!< 19 F8 */
  98. CHRY_READLINE_EXEC_F9, /*!< 20 F9 */
  99. CHRY_READLINE_EXEC_F10, /*!< 21 F10 */
  100. CHRY_READLINE_EXEC_NUL, /*!< 22 */
  101. CHRY_READLINE_EXEC_F11, /*!< 23 F11 */
  102. CHRY_READLINE_EXEC_F12, /*!< 24 F12 */
  103. };
  104. static const uint8_t xmap[20] = {
  105. CHRY_READLINE_EXEC_NUL, /*!< */
  106. CHRY_READLINE_EXEC_PRVH, /*!< A up */
  107. CHRY_READLINE_EXEC_NXTH, /*!< B down */
  108. CHRY_READLINE_EXEC_MVRT, /*!< C right */
  109. CHRY_READLINE_EXEC_MVLT, /*!< D left */
  110. CHRY_READLINE_EXEC_NUL, /*!< E */
  111. CHRY_READLINE_EXEC_MVED, /*!< F end */
  112. CHRY_READLINE_EXEC_NUL, /*!< G */
  113. CHRY_READLINE_EXEC_MVHM, /*!< H home */
  114. CHRY_READLINE_EXEC_NUL, /*!< I */
  115. CHRY_READLINE_EXEC_NUL, /*!< J */
  116. CHRY_READLINE_EXEC_NUL, /*!< K */
  117. CHRY_READLINE_EXEC_NUL, /*!< L */
  118. CHRY_READLINE_EXEC_NUL, /*!< M */
  119. CHRY_READLINE_EXEC_NUL, /*!< N */
  120. CHRY_READLINE_EXEC_NUL, /*!< O */
  121. CHRY_READLINE_EXEC_F1, /*!< P F1 */
  122. CHRY_READLINE_EXEC_F2, /*!< Q F2 */
  123. CHRY_READLINE_EXEC_F3, /*!< R F3 */
  124. CHRY_READLINE_EXEC_F4 /*!< S F4 */
  125. };
  126. #if defined(CONFIG_READLINE_CTRLMAP) && CONFIG_READLINE_CTRLMAP
  127. static const uint8_t ctrlmap[32] = {
  128. #else
  129. static uint8_t ctrlmap[32] = {
  130. #endif
  131. CHRY_READLINE_EXEC_NUL, /*!< @ NUL */
  132. CHRY_READLINE_EXEC_MVHM, /*!< A SOH */
  133. CHRY_READLINE_EXEC_MVLT, /*!< B STX */
  134. CHRY_READLINE_EXEC_SIGINT_, /*!< C ETX */
  135. CHRY_READLINE_EXEC_EOF_, /*!< D EOT */
  136. CHRY_READLINE_EXEC_MVED, /*!< E ENQ */
  137. CHRY_READLINE_EXEC_MVRT, /*!< F ACK */
  138. CHRY_READLINE_EXEC_NUL, /*!< G BEL */
  139. CHRY_READLINE_EXEC_BS, /*!< H BS */
  140. CHRY_READLINE_EXEC_CPLT, /*!< I HT */
  141. CHRY_READLINE_EXEC_NLN, /*!< J LF */
  142. CHRY_READLINE_EXEC_DELN, /*!< K VT */
  143. CHRY_READLINE_EXEC_CLR, /*!< L FF */
  144. CHRY_READLINE_EXEC_NLN, /*!< M CR */
  145. CHRY_READLINE_EXEC_NXTH, /*!< N SO */
  146. CHRY_READLINE_EXEC_NLN, /*!< O SI */
  147. CHRY_READLINE_EXEC_PRVH, /*!< P DLE */
  148. CHRY_READLINE_EXEC_SIGCONT, /*!< Q DC1 */
  149. CHRY_READLINE_EXEC_NUL, /*!< R DC2 */
  150. CHRY_READLINE_EXEC_SIGSTOP, /*!< S DC3 */
  151. CHRY_READLINE_EXEC_NUL, /*!< T DC4 */
  152. CHRY_READLINE_EXEC_DHLN, /*!< U NAK */
  153. CHRY_READLINE_EXEC_NUL, /*!< V SYN */
  154. CHRY_READLINE_EXEC_DLWD, /*!< W ETB */
  155. CHRY_READLINE_EXEC_NUL, /*!< X CAN */
  156. CHRY_READLINE_EXEC_NUL, /*!< Y EM */
  157. CHRY_READLINE_EXEC_SIGTSTP, /*!< Z SUB */
  158. CHRY_READLINE_EXEC_NUL, /*!< [ ESC */
  159. CHRY_READLINE_EXEC_SIGQUIT, /*!< \ FS */
  160. CHRY_READLINE_EXEC_NUL, /*!< ] GS */
  161. CHRY_READLINE_EXEC_SWNM, /*!< ^ RS */
  162. CHRY_READLINE_EXEC_HELP, /*!< - US */
  163. };
  164. #if defined(CONFIG_READLINE_ALTMAP) && CONFIG_READLINE_ALTMAP
  165. static const uint8_t altmap[26] = {
  166. #else
  167. static uint8_t altmap[26] = {
  168. #endif
  169. CHRY_READLINE_EXEC_NUL, /*!< A */
  170. CHRY_READLINE_EXEC_NUL, /*!< B */
  171. CHRY_READLINE_EXEC_NUL, /*!< C */
  172. CHRY_READLINE_EXEC_NUL, /*!< D */
  173. CHRY_READLINE_EXEC_NUL, /*!< E */
  174. CHRY_READLINE_EXEC_NUL, /*!< F */
  175. CHRY_READLINE_EXEC_NUL, /*!< G */
  176. CHRY_READLINE_EXEC_NUL, /*!< H */
  177. CHRY_READLINE_EXEC_NUL, /*!< I */
  178. CHRY_READLINE_EXEC_NUL, /*!< J */
  179. CHRY_READLINE_EXEC_NUL, /*!< K */
  180. CHRY_READLINE_EXEC_NUL, /*!< L */
  181. CHRY_READLINE_EXEC_NUL, /*!< M */
  182. CHRY_READLINE_EXEC_NUL, /*!< N */
  183. CHRY_READLINE_EXEC_NUL, /*!< O */
  184. CHRY_READLINE_EXEC_NUL, /*!< P */
  185. CHRY_READLINE_EXEC_NUL, /*!< Q */
  186. CHRY_READLINE_EXEC_NUL, /*!< R */
  187. CHRY_READLINE_EXEC_NUL, /*!< S */
  188. CHRY_READLINE_EXEC_NUL, /*!< T */
  189. CHRY_READLINE_EXEC_NUL, /*!< U */
  190. CHRY_READLINE_EXEC_NUL, /*!< V */
  191. CHRY_READLINE_EXEC_NUL, /*!< W */
  192. CHRY_READLINE_EXEC_NUL, /*!< X */
  193. CHRY_READLINE_EXEC_NUL, /*!< Y */
  194. CHRY_READLINE_EXEC_NUL, /*!< Z */
  195. };
  196. /*****************************************************************************
  197. * @brief print decimal integer (0 - 65535)
  198. *
  199. * @param[in] buf print buf
  200. * @param[in] idx print idx
  201. * @param[in] value 16bit unsigned integer
  202. *
  203. *****************************************************************************/
  204. static void chry_readline_print_integer(uint8_t *buf, size_t *idx, uint16_t value)
  205. {
  206. uint8_t array[5] = {0};
  207. uint8_t *intbuf = array;
  208. uint8_t *outbuf = buf + *idx;
  209. size_t count = 0;
  210. do {
  211. const uint8_t digit = (uint8_t)(value % 10);
  212. *intbuf++ = (uint8_t)('0' + digit);
  213. value /= 10;
  214. count++;
  215. } while (value);
  216. do {
  217. *outbuf++ = *--intbuf;
  218. (*idx)++;
  219. } while (--count);
  220. }
  221. /*****************************************************************************
  222. * @brief parse decimal integer (0 - 65535)
  223. *
  224. * @param[in] buf parse buf
  225. * @param[out] value 16bit unsigned integer pointer
  226. *
  227. *****************************************************************************/
  228. static void chry_readline_parse_integer(uint8_t *buf, uint16_t *value)
  229. {
  230. *value = 0;
  231. while (('0' <= *buf) && (*buf <= '9')) {
  232. *value *= 10;
  233. *value += *buf - '0';
  234. buf++;
  235. }
  236. }
  237. /*****************************************************************************
  238. * @brief Reset to Initial State
  239. *****************************************************************************/
  240. __unused static void chry_readline_seqgen_reset(uint8_t *buf, size_t *idx)
  241. {
  242. buf[*idx + 0] = '\033';
  243. buf[*idx + 1] = 'c';
  244. *idx += 2;
  245. }
  246. /*****************************************************************************
  247. * @brief output csi prefix
  248. *****************************************************************************/
  249. __unused static void chry_readline_seqgen_csi(uint8_t *buf, size_t *idx)
  250. {
  251. buf[*idx + 0] = '\033';
  252. buf[*idx + 1] = '[';
  253. *idx += 2;
  254. }
  255. /*****************************************************************************
  256. * @brief output csi 0 pn
  257. *****************************************************************************/
  258. __unused static void chry_readline_seqgen_csi0(uint8_t *buf, size_t *idx, char c)
  259. {
  260. chry_readline_seqgen_csi(buf, idx);
  261. buf[(*idx)++] = c;
  262. }
  263. /*****************************************************************************
  264. * @brief output csi 1 pn
  265. *****************************************************************************/
  266. __unused static void chry_readline_seqgen_csi1(uint8_t *buf, size_t *idx, char c, uint16_t pn)
  267. {
  268. chry_readline_seqgen_csi(buf, idx);
  269. chry_readline_print_integer(buf, idx, pn);
  270. buf[(*idx)++] = c;
  271. }
  272. /*****************************************************************************
  273. * @brief output csi 2 pn
  274. *****************************************************************************/
  275. __unused static void chry_readline_seqgen_csi2(uint8_t *buf, size_t *idx, char c, uint16_t pn, uint16_t pn2)
  276. {
  277. chry_readline_seqgen_csi(buf, idx);
  278. chry_readline_print_integer(buf, idx, pn);
  279. buf[(*idx)++] = ';';
  280. chry_readline_print_integer(buf, idx, pn2);
  281. buf[(*idx)++] = c;
  282. }
  283. /*****************************************************************************
  284. * @brief output csi 3 pn
  285. *****************************************************************************/
  286. __unused static void chry_readline_seqgen_csi3(uint8_t *buf, size_t *idx, char c, uint16_t pn, uint16_t pn2, uint16_t pn3)
  287. {
  288. chry_readline_seqgen_csi(buf, idx);
  289. chry_readline_print_integer(buf, idx, pn);
  290. buf[(*idx)++] = ';';
  291. chry_readline_print_integer(buf, idx, pn2);
  292. buf[(*idx)++] = ';';
  293. chry_readline_print_integer(buf, idx, pn3);
  294. buf[(*idx)++] = c;
  295. }
  296. /*****************************************************************************
  297. * @brief Cursor Up Pn Times (default = 1)
  298. *****************************************************************************/
  299. __unused static void chry_readline_seqgen_cursor_up(uint8_t *buf, size_t *idx, uint16_t pn)
  300. {
  301. chry_readline_seqgen_csi1(buf, idx, 'A', pn);
  302. }
  303. /*****************************************************************************
  304. * @brief Cursor Down Pn Times (default = 1)
  305. *****************************************************************************/
  306. __unused static void chry_readline_seqgen_cursor_down(uint8_t *buf, size_t *idx, uint16_t pn)
  307. {
  308. chry_readline_seqgen_csi1(buf, idx, 'B', pn);
  309. }
  310. /*****************************************************************************
  311. * @brief Cursor Forward Pn Times (default = 1)
  312. *****************************************************************************/
  313. __unused static void chry_readline_seqgen_cursor_forward(uint8_t *buf, size_t *idx, uint16_t pn)
  314. {
  315. chry_readline_seqgen_csi1(buf, idx, 'C', pn);
  316. }
  317. /*****************************************************************************
  318. * @brief Cursor Backward Pn Times (default = 1)
  319. *****************************************************************************/
  320. __unused static void chry_readline_seqgen_cursor_backward(uint8_t *buf, size_t *idx, uint16_t pn)
  321. {
  322. chry_readline_seqgen_csi1(buf, idx, 'D', pn);
  323. }
  324. /*****************************************************************************
  325. * @brief Cursor Next Line Pn Times (default = 1)
  326. *****************************************************************************/
  327. __unused static void chry_readline_seqgen_cursor_nextline(uint8_t *buf, size_t *idx, uint16_t pn)
  328. {
  329. chry_readline_seqgen_csi1(buf, idx, 'E', pn);
  330. }
  331. /*****************************************************************************
  332. * @brief Cursor Preceding Line Pn Times (default = 1)
  333. *****************************************************************************/
  334. __unused static void chry_readline_seqgen_cursor_prevline(uint8_t *buf, size_t *idx, uint16_t pn)
  335. {
  336. chry_readline_seqgen_csi1(buf, idx, 'F', pn);
  337. }
  338. /*****************************************************************************
  339. * @brief Cursor Character Absolute [column] (default = [row,1])
  340. *****************************************************************************/
  341. __unused static void chry_readline_seqgen_cursor_absolute(uint8_t *buf, size_t *idx, uint16_t pn)
  342. {
  343. chry_readline_seqgen_csi1(buf, idx, 'G', pn);
  344. }
  345. /*****************************************************************************
  346. * @brief Cursor Position [row;column] (default = [1,1])
  347. *****************************************************************************/
  348. __unused static void chry_readline_seqgen_cursor_position(uint8_t *buf, size_t *idx, uint16_t pn1, uint16_t pn2)
  349. {
  350. chry_readline_seqgen_csi2(buf, idx, 'H', pn1, pn2);
  351. }
  352. /*****************************************************************************
  353. * @brief Erase in Display
  354. * Pn = 0 → Erase Below (default)
  355. * Pn = 1 → Erase Above
  356. * Pn = 2 → Erase All
  357. * Pn = 3 → Erase Saved Lines (xterm)
  358. *****************************************************************************/
  359. __unused static void chry_readline_seqgen_erase_display(uint8_t *buf, size_t *idx, uint16_t pn)
  360. {
  361. chry_readline_seqgen_csi1(buf, idx, 'J', pn);
  362. }
  363. /*****************************************************************************
  364. * @brief Erase in Line
  365. * Pn = 0 → Erase to Right (default)
  366. * Pn = 1 → Erase to Left
  367. * Pn = 2 → Erase All
  368. *****************************************************************************/
  369. __unused static void chry_readline_seqgen_erase_line(uint8_t *buf, size_t *idx, uint16_t pn)
  370. {
  371. chry_readline_seqgen_csi1(buf, idx, 'K', pn);
  372. }
  373. /*****************************************************************************
  374. * @brief Insert Pn Line(s) (default = 1)
  375. *****************************************************************************/
  376. __unused static void chry_readline_seqgen_insert_line(uint8_t *buf, size_t *idx, uint16_t pn)
  377. {
  378. chry_readline_seqgen_csi1(buf, idx, 'L', pn);
  379. }
  380. /*****************************************************************************
  381. * @brief Delete Pn Line(s) (default = 1)
  382. *****************************************************************************/
  383. __unused static void chry_readline_seqgen_delete_line(uint8_t *buf, size_t *idx, uint16_t pn)
  384. {
  385. chry_readline_seqgen_csi1(buf, idx, 'M', pn);
  386. }
  387. /*****************************************************************************
  388. * @brief Delete Pn Character(s) (default = 1)
  389. *****************************************************************************/
  390. __unused static void chry_readline_seqgen_delete_char(uint8_t *buf, size_t *idx, uint16_t pn)
  391. {
  392. chry_readline_seqgen_csi1(buf, idx, 'P', pn);
  393. }
  394. /*****************************************************************************
  395. * @brief Erase Pn Character(s) (default = 1)
  396. *****************************************************************************/
  397. __unused static void chry_readline_seqgen_erase_char(uint8_t *buf, size_t *idx, uint16_t pn)
  398. {
  399. chry_readline_seqgen_csi1(buf, idx, 'X', pn);
  400. }
  401. /*****************************************************************************
  402. * @brief Scroll up Pn lines (default = 1)
  403. *****************************************************************************/
  404. __unused static void chry_readline_seqgen_scroll_up(uint8_t *buf, size_t *idx, uint16_t pn)
  405. {
  406. chry_readline_seqgen_csi1(buf, idx, 'S', pn);
  407. }
  408. /*****************************************************************************
  409. * @brief Scroll down Pn lines (default = 1)
  410. *****************************************************************************/
  411. __unused static void chry_readline_seqgen_scroll_down(uint8_t *buf, size_t *idx, uint16_t pn)
  412. {
  413. chry_readline_seqgen_csi1(buf, idx, 'T', pn);
  414. }
  415. /*****************************************************************************
  416. * @brief Save Current Cursor Position
  417. *****************************************************************************/
  418. __unused static void chry_readline_seqgen_save_cursor_position(uint8_t *buf, size_t *idx)
  419. {
  420. chry_readline_seqgen_csi0(buf, idx, 's');
  421. }
  422. /*****************************************************************************
  423. * @brief Restore Saved Cursor Position
  424. *****************************************************************************/
  425. __unused static void chry_readline_seqgen_restore_cursor_position(uint8_t *buf, size_t *idx)
  426. {
  427. chry_readline_seqgen_csi0(buf, idx, 'u');
  428. }
  429. /*****************************************************************************
  430. * @brief DEC Private Mode Reset use alternate screen buffer
  431. *****************************************************************************/
  432. __unused static void chry_readline_seqgen_alternate_screen(uint8_t *buf, size_t *idx)
  433. {
  434. chry_readline_seqgen_csi(buf, idx);
  435. buf[(*idx) + 0] = '?';
  436. buf[(*idx) + 1] = '4';
  437. buf[(*idx) + 2] = '7';
  438. buf[(*idx) + 3] = 'h';
  439. (*idx) += 4;
  440. }
  441. /*****************************************************************************
  442. * @brief DEC Private Mode Set use normal screen buffer
  443. *****************************************************************************/
  444. __unused static void chry_readline_seqgen_normal_screen(uint8_t *buf, size_t *idx)
  445. {
  446. chry_readline_seqgen_csi(buf, idx);
  447. buf[(*idx) + 0] = '?';
  448. buf[(*idx) + 1] = '4';
  449. buf[(*idx) + 2] = '7';
  450. buf[(*idx) + 3] = 'l';
  451. (*idx) += 4;
  452. }
  453. /*****************************************************************************
  454. * @brief Report the size of the text area in characters
  455. * as CSI 8;row;column t
  456. *****************************************************************************/
  457. __unused static void chry_readline_seqgen_report_screen_size(uint8_t *buf, size_t *idx)
  458. {
  459. chry_readline_seqgen_csi(buf, idx);
  460. buf[(*idx) + 0] = '1';
  461. buf[(*idx) + 1] = '8';
  462. buf[(*idx) + 2] = 't';
  463. (*idx) += 3;
  464. }
  465. /*****************************************************************************
  466. * @brief refresh line
  467. * @retval int 0:Success -1:Error
  468. *****************************************************************************/
  469. int chry_readline_edit_refresh(chry_readline_t *rl)
  470. {
  471. size_t idx;
  472. uint8_t seq[16];
  473. uint16_t curoff;
  474. uint16_t pptoff;
  475. uint16_t diff;
  476. char *linebuff;
  477. uint16_t linesize;
  478. linebuff = rl->ln.buff->pbuf;
  479. if (rl->ln.buff == NULL) {
  480. linesize = 0;
  481. curoff = 0;
  482. pptoff = 0;
  483. } else {
  484. linesize = rl->ln.buff->size;
  485. curoff = rl->ln.curoff;
  486. pptoff = rl->ln.pptoff;
  487. }
  488. if ((pptoff + curoff) >= rl->term.col) {
  489. diff = pptoff + curoff - rl->term.col + 1;
  490. linebuff += diff;
  491. linesize -= diff;
  492. curoff -= diff;
  493. }
  494. if ((pptoff + linesize) > rl->term.col) {
  495. linesize -= (pptoff + linesize) - rl->term.col;
  496. }
  497. linebuff[linesize] = '\0';
  498. idx = 0;
  499. #if defined(CONFIG_READLINE_REFRESH_PROMPT) && CONFIG_READLINE_REFRESH_PROMPT
  500. /*!< move to line start */
  501. chry_readline_seqgen_cursor_absolute(seq, &idx, 0);
  502. chry_readline_put(rl, seq, idx, -1);
  503. /*!< output prompt */
  504. chry_readline_put(rl, rl->prompt, rl->ln.pptlen, -1);
  505. #else
  506. /*!< move to prompt end */
  507. chry_readline_seqgen_cursor_absolute(seq, &idx, pptoff + 1);
  508. chry_readline_put(rl, seq, idx, -1);
  509. #endif
  510. if (!rl->ln.mask) {
  511. /*!< output linebuff */
  512. chry_readline_put(rl, linebuff, linesize, -1);
  513. }
  514. /*!< erase to end of display and restore cursor */
  515. idx = 0;
  516. chry_readline_seqgen_erase_display(seq, &idx, 0);
  517. chry_readline_seqgen_cursor_absolute(seq, &idx, pptoff + curoff + 1);
  518. chry_readline_put(rl, seq, idx, -1);
  519. return 0;
  520. }
  521. /*****************************************************************************
  522. * @brief erase to end of line
  523. *****************************************************************************/
  524. void chry_readline_erase_line(chry_readline_t *rl)
  525. {
  526. size_t idx;
  527. uint8_t seq[16];
  528. idx = 0;
  529. /*!< move to line start */
  530. chry_readline_seqgen_cursor_absolute(seq, &idx, 0);
  531. chry_readline_put(rl, seq, idx, );
  532. /*!< erase to end of display and restore cursor */
  533. idx = 0;
  534. chry_readline_seqgen_erase_display(seq, &idx, 0);
  535. chry_readline_seqgen_cursor_absolute(seq, &idx, 0);
  536. chry_readline_put(rl, seq, idx, );
  537. }
  538. /*****************************************************************************
  539. * @brief clear screen and refresh line
  540. * @retval int 0:Success -1:Error
  541. *****************************************************************************/
  542. int chry_readline_edit_clear(chry_readline_t *rl)
  543. {
  544. chry_readline_put(rl, "\033[2J\033[1;1H", 10, -1);
  545. #if defined(CONFIG_READLINE_REFRESH_PROMPT) && CONFIG_READLINE_REFRESH_PROMPT
  546. return chry_readline_edit_refresh(rl);
  547. #else
  548. /*!< output prompt */
  549. chry_readline_put(rl, rl->prompt, rl->ln.pptlen, -1);
  550. return chry_readline_edit_refresh(rl);
  551. #endif
  552. }
  553. /*****************************************************************************
  554. * @brief insert a character, (only support 0x20-0x7e)
  555. * @retval int 0:Success -1:Error
  556. *****************************************************************************/
  557. int chry_readline_edit_insert(chry_readline_t *rl, char c)
  558. {
  559. if (rl->ln.buff->size < rl->ln.lnmax) {
  560. if (rl->ln.buff->size != rl->ln.curoff) {
  561. memmove(rl->ln.buff->pbuf + rl->ln.curoff + 1,
  562. rl->ln.buff->pbuf + rl->ln.curoff,
  563. rl->ln.buff->size - rl->ln.curoff);
  564. }
  565. rl->ln.buff->pbuf[rl->ln.curoff++] = c;
  566. rl->ln.buff->size++;
  567. return chry_readline_edit_refresh(rl);
  568. }
  569. return 0;
  570. }
  571. /*****************************************************************************
  572. * @brief delete cursor left character
  573. * @retval int 0:Success -1:Error
  574. *****************************************************************************/
  575. int chry_readline_edit_backspace(chry_readline_t *rl)
  576. {
  577. if ((rl->ln.curoff > 0) && (rl->ln.buff->size > 0)) {
  578. memmove(rl->ln.buff->pbuf + rl->ln.curoff - 1,
  579. rl->ln.buff->pbuf + rl->ln.curoff,
  580. rl->ln.buff->size - rl->ln.curoff);
  581. rl->ln.buff->size--;
  582. rl->ln.curoff--;
  583. return chry_readline_edit_refresh(rl);
  584. }
  585. return 0;
  586. }
  587. /*****************************************************************************
  588. * @brief delete cursor right character
  589. * @retval int 0:Success -1:Error
  590. *****************************************************************************/
  591. int chry_readline_edit_delete(chry_readline_t *rl)
  592. {
  593. if ((rl->ln.curoff < rl->ln.buff->size) && (rl->ln.buff->size > 0)) {
  594. memmove(rl->ln.buff->pbuf + rl->ln.curoff,
  595. rl->ln.buff->pbuf + rl->ln.curoff + 1,
  596. rl->ln.buff->size - rl->ln.curoff - 1);
  597. rl->ln.buff->size--;
  598. return chry_readline_edit_refresh(rl);
  599. }
  600. return 0;
  601. }
  602. /*****************************************************************************
  603. * @brief move cursor to left
  604. * @retval int 0:Success -1:Error
  605. *****************************************************************************/
  606. int chry_readline_edit_moveleft(chry_readline_t *rl)
  607. {
  608. if (rl->ln.curoff > 0) {
  609. rl->ln.curoff--;
  610. return chry_readline_edit_refresh(rl);
  611. }
  612. return 0;
  613. }
  614. /*****************************************************************************
  615. * @brief move cursor to right
  616. * @retval int 0:Success -1:Error
  617. *****************************************************************************/
  618. int chry_readline_edit_moveright(chry_readline_t *rl)
  619. {
  620. if (rl->ln.curoff < rl->ln.buff->size) {
  621. rl->ln.curoff++;
  622. return chry_readline_edit_refresh(rl);
  623. }
  624. return 0;
  625. }
  626. /*****************************************************************************
  627. * @brief move cursor to start of line
  628. * @retval int 0:Success -1:Error
  629. *****************************************************************************/
  630. int chry_readline_edit_movehome(chry_readline_t *rl)
  631. {
  632. rl->ln.curoff = 0;
  633. return chry_readline_edit_refresh(rl);
  634. }
  635. /*****************************************************************************
  636. * @brief move cursor to end of line
  637. * @retval int 0:Success -1:Error
  638. *****************************************************************************/
  639. int chry_readline_edit_moveend(chry_readline_t *rl)
  640. {
  641. rl->ln.curoff = rl->ln.buff->size;
  642. return chry_readline_edit_refresh(rl);
  643. }
  644. /*****************************************************************************
  645. * @brief delete the whole line
  646. * @retval int 0:Success -1:Error
  647. *****************************************************************************/
  648. int chry_readline_edit_delline(chry_readline_t *rl)
  649. {
  650. rl->ln.buff->size = 0;
  651. rl->ln.curoff = 0;
  652. return chry_readline_edit_refresh(rl);
  653. }
  654. /*****************************************************************************
  655. * @brief delete from cursor to end of line
  656. * @retval int 0:Success -1:Error
  657. *****************************************************************************/
  658. int chry_readline_edit_delend(chry_readline_t *rl)
  659. {
  660. rl->ln.buff->size = rl->ln.curoff;
  661. return chry_readline_edit_refresh(rl);
  662. }
  663. /*****************************************************************************
  664. * @brief delete previosu word
  665. * @retval int 0:Success -1:Error
  666. *****************************************************************************/
  667. int chry_readline_edit_delword(chry_readline_t *rl)
  668. {
  669. uint16_t curoff = rl->ln.curoff;
  670. while ((curoff > 0) && (rl->ln.buff->pbuf[curoff - 1] == ' ')) {
  671. curoff--;
  672. }
  673. while ((curoff > 0) && (rl->ln.buff->pbuf[curoff - 1] != ' ')) {
  674. curoff--;
  675. }
  676. memmove(rl->ln.buff->pbuf + curoff,
  677. rl->ln.buff->pbuf + rl->ln.curoff,
  678. rl->ln.buff->size - rl->ln.curoff + 1);
  679. rl->ln.buff->size -= rl->ln.curoff - curoff;
  680. rl->ln.curoff = curoff;
  681. return chry_readline_edit_refresh(rl);
  682. }
  683. /*****************************************************************************
  684. * @brief get now word
  685. *****************************************************************************/
  686. __unused static void chry_readline_edit_getword(chry_readline_t *rl, char **pword, uint16_t *size)
  687. {
  688. uint16_t curoff = rl->ln.curoff;
  689. if ((curoff == 0) || (rl->ln.buff->pbuf[curoff - 1] == ' ')) {
  690. goto end;
  691. }
  692. while (curoff > 0) {
  693. curoff--;
  694. if (rl->ln.buff->pbuf[curoff] == ' ') {
  695. curoff++;
  696. break;
  697. }
  698. }
  699. end:
  700. *pword = &(rl->ln.buff->pbuf[curoff]);
  701. *size = rl->ln.curoff - curoff;
  702. return;
  703. }
  704. /*****************************************************************************
  705. * @brief show help
  706. * @retval int 0:Success -1:Error
  707. *****************************************************************************/
  708. static int chry_readline_help(chry_readline_t *rl)
  709. {
  710. if (sizeof(CONFIG_READLINE_HELP) - 1) {
  711. chry_readline_put(rl, CONFIG_READLINE_HELP, sizeof(CONFIG_READLINE_HELP) - 1, -1);
  712. }
  713. return 0;
  714. }
  715. /*****************************************************************************
  716. * @brief dispatch csi sequences
  717. *
  718. * @param[in] rl readline instance
  719. * @param[inout] c character for dispatch
  720. * @param[in] pns params for dispatch
  721. *
  722. * @retval int 0:Success -1:Error
  723. *****************************************************************************/
  724. static int chry_readline_dispatch_csi(chry_readline_t *rl, uint8_t *c, uint16_t *pns)
  725. {
  726. uint8_t idx;
  727. if (*c == '~') {
  728. if (pns[0] >= sizeof(vtmap)) {
  729. pns[0] = 0;
  730. }
  731. *c = vtmap[pns[0]];
  732. } else if (*c == 't') {
  733. if (pns[0] == 8) {
  734. rl->term.nsupt = 0;
  735. rl->term.row = pns[1];
  736. rl->term.col = pns[2];
  737. #if defined(CONFIG_READLINE_XTERM) && CONFIG_READLINE_XTERM
  738. /*!< 1.enter alternate screen buffer <esc>[?47h */
  739. /*!< 2.clear screen buffer <esc>[2J */
  740. /*!< 3.move cursor to (1,1) <esc>[1;1H */
  741. /*!< 4.enter normal screen buffer <esc>[?47l */
  742. chry_readline_put(rl, "\033[?47h\033[2J\033[1;1H", 16, -1);
  743. chry_readline_help(rl);
  744. chry_readline_put(rl, "\033[?47l", 6, -1);
  745. #endif
  746. }
  747. *c = CHRY_READLINE_EXEC_NUL;
  748. } else {
  749. idx = *c - 0x40;
  750. if (idx >= sizeof(xmap)) {
  751. idx = 0;
  752. }
  753. *c = xmap[idx];
  754. }
  755. return 0;
  756. }
  757. /*****************************************************************************
  758. * @brief dispatch o sequences
  759. *
  760. * @param[in] rl readline instance
  761. * @param[inout] c character for dispatch
  762. * @param[in] pns params for dispatch
  763. *
  764. * @retval int 0:Success -1:Error
  765. *****************************************************************************/
  766. static int chry_readline_dispatch_o(chry_readline_t *rl, uint8_t *c, uint16_t *pns)
  767. {
  768. (void)rl;
  769. (void)pns;
  770. switch (*c) {
  771. case 'P':
  772. *c = CHRY_READLINE_EXEC_F1;
  773. break;
  774. case 'Q':
  775. *c = CHRY_READLINE_EXEC_F2;
  776. break;
  777. case 'R':
  778. *c = CHRY_READLINE_EXEC_F3;
  779. break;
  780. case 'S':
  781. *c = CHRY_READLINE_EXEC_F4;
  782. break;
  783. default:
  784. *c = CHRY_READLINE_EXEC_NUL;
  785. break;
  786. }
  787. return 0;
  788. }
  789. /*****************************************************************************
  790. * @brief dispatch alt sequences
  791. *
  792. * @param[in] rl readline instance
  793. * @param[inout] c character for dispatch
  794. * @param[in] pns params for dispatch
  795. *
  796. * @retval int 0:Success -1:Error
  797. *****************************************************************************/
  798. static int chry_readline_dispatch_alt(chry_readline_t *rl, uint8_t *c, uint16_t *pns)
  799. {
  800. (void)rl;
  801. (void)pns;
  802. if ((*c < 'a') || ('z' < *c)) {
  803. *c = CHRY_READLINE_EXEC_NUL;
  804. return 0;
  805. }
  806. #if defined(CONFIG_READLINE_ALTMAP) && CONFIG_READLINE_ALTMAP
  807. *c = rl->altmap[*c - 'a'];
  808. #else
  809. *c = altmap[*c - 'a'];
  810. #endif
  811. return 0;
  812. }
  813. /*****************************************************************************
  814. * @brief dispatch ctrl sequences
  815. *
  816. * @param[in] rl readline instance
  817. * @param[inout] c character for dispatch
  818. * @param[in] pns params for dispatch
  819. *
  820. * @retval int 0:Success -1:Error
  821. *****************************************************************************/
  822. static int chry_readline_dispatch_ctrl(chry_readline_t *rl, uint8_t *c, uint16_t *pns)
  823. {
  824. (void)rl;
  825. (void)pns;
  826. #if defined(CONFIG_READLINE_CTRLMAP) && CONFIG_READLINE_CTRLMAP
  827. *c = rl->ctrlmap[*c];
  828. #else
  829. *c = ctrlmap[*c];
  830. #endif
  831. return 0;
  832. }
  833. /*****************************************************************************
  834. * @brief parse csi sequences
  835. *
  836. * @param[in] rl readline instance
  837. * @param[out] csiend final csi seq character
  838. * @param[out] expre extend prefix character
  839. * @param[out] pns array of number param
  840. *
  841. * @retval int 0:Success -1:Error
  842. *****************************************************************************/
  843. static int chry_readline_seqexec_pcsi(chry_readline_t *rl, uint8_t *csiend, uint8_t *expre, uint16_t *pns)
  844. {
  845. uint8_t csibuf[8];
  846. uint8_t *pbuf = csibuf;
  847. /*!< should have buffered key or it will be blocked */
  848. chry_readline_waitkey(rl, pbuf);
  849. if (('0' <= *pbuf) && (*pbuf <= '9')) {
  850. pbuf++;
  851. } else if ('?' == *pbuf) {
  852. *expre = *pbuf;
  853. } else if ((('a' <= *pbuf) && (*pbuf <= 'z')) ||
  854. (('A' <= *pbuf) && (*pbuf <= 'Z'))) {
  855. *csiend = *pbuf;
  856. return 0;
  857. }
  858. for (;;) {
  859. /*!< should have buffered key or it will be blocked */
  860. chry_readline_waitkey(rl, pbuf);
  861. if (('0' <= *pbuf) && (*pbuf <= '9')) {
  862. pbuf++;
  863. } else if (*pbuf == ';') {
  864. pbuf = csibuf;
  865. chry_readline_parse_integer(csibuf, pns++);
  866. } else if ((*pbuf == '~') ||
  867. (('a' <= *pbuf) && (*pbuf <= 'z')) ||
  868. (('A' <= *pbuf) && (*pbuf <= 'Z'))) {
  869. *csiend = *pbuf;
  870. chry_readline_parse_integer(csibuf, pns++);
  871. return 0;
  872. } else {
  873. return -1;
  874. }
  875. }
  876. }
  877. /*****************************************************************************
  878. * @brief execute CSI sequences
  879. *
  880. * @param[in] rl readline instance
  881. * @param[out] c character for dispatch
  882. * @param[out] pns array of number param
  883. *
  884. * @retval int 0:Success -1:Error
  885. *****************************************************************************/
  886. static int chry_readline_seqexec_csi(chry_readline_t *rl, uint8_t *c, uint16_t *pns)
  887. {
  888. uint8_t expre = 0;
  889. if (chry_readline_seqexec_pcsi(rl, c, &expre, pns)) {
  890. return -1;
  891. }
  892. if (expre) {
  893. *c = CHRY_READLINE_C0_NUL;
  894. }
  895. return chry_readline_dispatch_csi(rl, c, pns);
  896. }
  897. /*****************************************************************************
  898. * @brief execute ALT sequences
  899. *
  900. * @param[in] rl readline instance
  901. * @param[inout] c character for dispatch
  902. * @param[out] pns array of number param
  903. *
  904. * @retval int 0:Success -1:Error
  905. *****************************************************************************/
  906. static int chry_readline_seqexec_alt(chry_readline_t *rl, uint8_t *c, uint16_t *pns)
  907. {
  908. return chry_readline_dispatch_alt(rl, c, pns);
  909. }
  910. /*****************************************************************************
  911. * @brief execute O sequences
  912. *
  913. * @param[in] rl readline instance
  914. * @param[out] c character for dispatch
  915. * @param[out] pns array of number param
  916. *
  917. * @retval int 0:Success -1:Error
  918. *****************************************************************************/
  919. static int chry_readline_seqexec_o(chry_readline_t *rl, uint8_t *c, uint16_t *pns)
  920. {
  921. /*!< should have buffered key or it will be blocked */
  922. chry_readline_waitkey(rl, c);
  923. return chry_readline_dispatch_o(rl, c, pns);
  924. }
  925. /*****************************************************************************
  926. * @brief execute sequences
  927. *
  928. * @param[in] rl readline instance
  929. * @param[inout] c character for dispatch
  930. * @param[out] pns array of number param
  931. *
  932. * @retval int 0:Success -1:Error
  933. *****************************************************************************/
  934. static int chry_readline_seqexec(chry_readline_t *rl, uint8_t *c, uint16_t *pns)
  935. {
  936. /*!< should have buffered key or it will be blocked */
  937. chry_readline_waitkey(rl, c);
  938. switch (*c) {
  939. case 'O':
  940. return chry_readline_seqexec_o(rl, c, pns);
  941. case '[':
  942. return chry_readline_seqexec_csi(rl, c, pns);
  943. default:
  944. return chry_readline_seqexec_alt(rl, c, pns);
  945. }
  946. return 0;
  947. }
  948. #if defined(CONFIG_READLINE_HISTORY) && CONFIG_READLINE_HISTORY
  949. /*****************************************************************************
  950. * @brief reverse memcpy 2byte align
  951. *
  952. * @param[in] dst
  953. * @param[in] src
  954. * @param[in] n byte
  955. *
  956. *****************************************************************************/
  957. static void chry_readline_rvsememcpy2(void *dst, const void *src, size_t n)
  958. {
  959. uint16_t *pout = dst;
  960. uint16_t *pin = (uint16_t *)src - 1;
  961. for (; n > 0; n -= 2) {
  962. *pout++ = *pin--;
  963. }
  964. }
  965. /*****************************************************************************
  966. * @brief align 2 up
  967. *
  968. * @param[in] size size
  969. *
  970. * @retval align size
  971. *****************************************************************************/
  972. static uint32_t chry_readline_align2(uint32_t size)
  973. {
  974. if (size & 0x1) {
  975. return (size & ~0x1) + 2;
  976. } else {
  977. return size;
  978. }
  979. }
  980. /*****************************************************************************
  981. * @brief cache linbuff to history list
  982. *
  983. * @param[in] rl readline instance
  984. *
  985. *****************************************************************************/
  986. static void chry_readline_history_cache(chry_readline_t *rl)
  987. {
  988. uint16_t unused;
  989. uint16_t offset;
  990. uint16_t remain;
  991. uint16_t lnsize;
  992. uint8_t *dst;
  993. /*!< fifo unused size */
  994. unused = rl->hist.size - (rl->hist.cache - rl->hist.out);
  995. /*!< line and size total size, alignup 2 */
  996. lnsize = chry_readline_align2(rl->ln.buff->size + 2);
  997. /*!< free the oldest history */
  998. if (lnsize > unused) {
  999. rl->hist.out += lnsize - unused;
  1000. }
  1001. /*!< fifo write offset */
  1002. offset = rl->hist.cache & rl->hist.mask;
  1003. /*!< unused size before ringloop */
  1004. remain = rl->hist.size - offset;
  1005. remain = remain > lnsize ? lnsize : remain;
  1006. dst = (uint8_t *)(rl->ln.buff) + lnsize;
  1007. chry_readline_rvsememcpy2(rl->hist.pbuf + offset, dst, remain);
  1008. chry_readline_rvsememcpy2(rl->hist.pbuf, dst - remain, lnsize - remain);
  1009. rl->hist.in = rl->hist.cache + lnsize;
  1010. }
  1011. /*****************************************************************************
  1012. * @brief store linebuff to history list
  1013. *
  1014. * @param[in] rl readline instance
  1015. *
  1016. *****************************************************************************/
  1017. static void chry_readline_history_store(chry_readline_t *rl)
  1018. {
  1019. if (rl->ln.buff->size > 0) {
  1020. chry_readline_history_cache(rl);
  1021. /*!< update cache index */
  1022. rl->hist.cache = rl->hist.in;
  1023. }
  1024. }
  1025. /*****************************************************************************
  1026. * @brief load special index history to linebuff
  1027. *
  1028. * @param[in] rl readline instance
  1029. * @param[in] index history index
  1030. *
  1031. * @retval 0:Success -1:Error
  1032. *****************************************************************************/
  1033. static int chry_readline_history_load(chry_readline_t *rl, uint16_t index)
  1034. {
  1035. uint16_t used;
  1036. uint16_t offset;
  1037. uint16_t remain;
  1038. uint16_t lnsize;
  1039. uint16_t histin;
  1040. uint16_t count;
  1041. uint16_t prevused;
  1042. if (rl->hist.index == 0) {
  1043. chry_readline_history_cache(rl);
  1044. }
  1045. lnsize = 0;
  1046. count = index;
  1047. histin = rl->hist.in;
  1048. prevused = rl->hist.in - rl->hist.out;
  1049. do {
  1050. histin -= lnsize;
  1051. /*!< fifo used size */
  1052. used = histin - rl->hist.out;
  1053. if ((used == 0) || (used > prevused)) {
  1054. return 0;
  1055. }
  1056. prevused = used;
  1057. /*!< fifo read offset */
  1058. offset = (histin - 2) & rl->hist.mask;
  1059. /*!< read fisrt 2byte and alignup 2 */
  1060. lnsize = chry_readline_align2(((uint32_t *)(rl->hist.pbuf + offset))[0] + 2);
  1061. if (lnsize > used) {
  1062. return 0;
  1063. }
  1064. } while (count--);
  1065. offset = (histin - lnsize) & rl->hist.mask;
  1066. /*!< unused size before ringloop */
  1067. remain = rl->hist.size - offset;
  1068. remain = remain > lnsize ? lnsize : remain;
  1069. /*!< temp value */
  1070. lnsize = lnsize - remain;
  1071. chry_readline_rvsememcpy2((uint8_t *)(rl->ln.buff) + lnsize,
  1072. rl->hist.pbuf + offset + remain, remain);
  1073. chry_readline_rvsememcpy2(rl->ln.buff, rl->hist.pbuf + lnsize, lnsize);
  1074. rl->ln.curoff = rl->ln.buff->size;
  1075. rl->hist.index = index;
  1076. return chry_readline_edit_refresh(rl);
  1077. }
  1078. /*****************************************************************************
  1079. * @brief load prev history to linebuff
  1080. *
  1081. * @param[in] rl readline instance
  1082. *
  1083. * @retval 0:Success -1:Error
  1084. *****************************************************************************/
  1085. static int chry_readline_history_loadprev(chry_readline_t *rl)
  1086. {
  1087. uint16_t lnhist = rl->hist.index + 1;
  1088. return chry_readline_history_load(rl, lnhist);
  1089. }
  1090. /*****************************************************************************
  1091. * @brief load next history to linebuff
  1092. *
  1093. * @param[in] rl readline instance
  1094. *
  1095. * @retval 0:Success -1:Error
  1096. *****************************************************************************/
  1097. static int chry_readline_history_loadnext(chry_readline_t *rl)
  1098. {
  1099. uint16_t lnhist = rl->hist.index > 0 ? rl->hist.index - 1 : 0;
  1100. return chry_readline_history_load(rl, lnhist);
  1101. }
  1102. #endif
  1103. /*****************************************************************************
  1104. * @brief auto completion
  1105. *
  1106. * @param[in] rl readline instance
  1107. *
  1108. * @retval int 0:Success -1:Error 1:Restart
  1109. *****************************************************************************/
  1110. int chry_readline_complete(chry_readline_t *rl)
  1111. {
  1112. #if defined(CONFIG_READLINE_COMPLETION) && CONFIG_READLINE_COMPLETION
  1113. uint8_t count;
  1114. char *pre;
  1115. uint16_t word_size;
  1116. const char *argv[CONFIG_READLINE_MAX_COMPLETION];
  1117. uint8_t argl[CONFIG_READLINE_MAX_COMPLETION];
  1118. if (rl->cplt.acb) {
  1119. chry_readline_edit_getword(rl, &pre, &word_size);
  1120. if ((count = rl->cplt.acb(rl, pre, &word_size, argv, argl, CONFIG_READLINE_MAX_COMPLETION)) == 0) {
  1121. /*!< if no completions, return */
  1122. return 0;
  1123. }
  1124. uint16_t match_size = 0;
  1125. uint16_t extend_size;
  1126. if (count == 1) {
  1127. match_size = argl[0];
  1128. } else {
  1129. bool flag = true;
  1130. while (flag) {
  1131. for (uint16_t i = 0; i < count - 1; i++) {
  1132. char c1 = argv[i + 0][match_size];
  1133. char c2 = argv[i + 1][match_size];
  1134. if ((0 == c1) || (0 == c2) || (c1 != c2)) {
  1135. flag = false;
  1136. break;
  1137. }
  1138. }
  1139. if (flag) {
  1140. match_size++;
  1141. }
  1142. }
  1143. }
  1144. if (match_size > word_size) {
  1145. uint16_t free_size = rl->ln.lnmax - rl->ln.buff->size;
  1146. extend_size = match_size - word_size;
  1147. extend_size = extend_size < free_size ? extend_size : free_size;
  1148. if (0 == extend_size) {
  1149. return 0;
  1150. }
  1151. if (rl->ln.buff->size != rl->ln.curoff) {
  1152. memmove(rl->ln.buff->pbuf + rl->ln.curoff + extend_size,
  1153. rl->ln.buff->pbuf + rl->ln.curoff,
  1154. rl->ln.buff->size - rl->ln.curoff);
  1155. }
  1156. memcpy(&(rl->ln.buff->pbuf[rl->ln.curoff]), &argv[0][word_size], extend_size);
  1157. rl->ln.curoff += extend_size;
  1158. rl->ln.buff->size += extend_size;
  1159. return chry_readline_edit_refresh(rl);
  1160. }
  1161. uint16_t longest_size = 0;
  1162. for (uint16_t i = 0; i < count; i++) {
  1163. uint16_t cplt_size = argl[i];
  1164. if (cplt_size > longest_size) {
  1165. longest_size = cplt_size;
  1166. }
  1167. }
  1168. longest_size += 2;
  1169. uint8_t col_count = rl->term.col / longest_size;
  1170. if (col_count < 1) {
  1171. col_count = 1;
  1172. }
  1173. uint16_t row_count = (count + col_count - 1) / col_count;
  1174. for (uint16_t row = 0; row < row_count; row++) {
  1175. chry_readline_put(rl, CONFIG_READLINE_NEWLINE, sizeof(CONFIG_READLINE_NEWLINE) ? sizeof(CONFIG_READLINE_NEWLINE) - 1 : 0, -1);
  1176. for (int col = 0; col < col_count; col++) {
  1177. int idx = (col * row_count) + row;
  1178. if (idx < count) {
  1179. uint16_t cplt_size = argl[idx];
  1180. chry_readline_put(rl, (void *)argv[idx], cplt_size, -1);
  1181. if (((col + 1) * row_count) + row < count) {
  1182. for (int k = cplt_size; k < longest_size; k++) {
  1183. chry_readline_put(rl, " ", 1, -1);
  1184. }
  1185. }
  1186. }
  1187. }
  1188. }
  1189. }
  1190. chry_readline_put(rl, CONFIG_READLINE_NEWLINE, sizeof(CONFIG_READLINE_NEWLINE) ? sizeof(CONFIG_READLINE_NEWLINE) - 1 : 0, -1);
  1191. return 1;
  1192. #else
  1193. (void)rl;
  1194. return 0;
  1195. #endif
  1196. }
  1197. /*****************************************************************************
  1198. * @brief calculate prompt strlen and cursor offset
  1199. *****************************************************************************/
  1200. static void chry_readline_calculate_prompt(chry_readline_t *rl)
  1201. {
  1202. char c;
  1203. uint8_t flag;
  1204. flag = 0;
  1205. rl->ln.pptlen = 0;
  1206. rl->ln.pptoff = 0;
  1207. while (1) {
  1208. c = rl->prompt[rl->ln.pptlen];
  1209. if (c == '\0') {
  1210. return;
  1211. } else if (c == '\r') {
  1212. rl->ln.pptoff = 0;
  1213. } else if (c == '\033') {
  1214. flag = 1;
  1215. } else if ((flag == 0) && (c != '\n')) {
  1216. rl->ln.pptoff++;
  1217. } else if ((flag == 1) && (c == 'm')) {
  1218. flag = 0;
  1219. }
  1220. rl->ln.pptlen++;
  1221. if (rl->ln.pptlen >= rl->ln.pptsize) {
  1222. rl->ln.pptlen = 0;
  1223. rl->ln.pptoff = 0;
  1224. return;
  1225. }
  1226. }
  1227. }
  1228. /*****************************************************************************
  1229. * @brief wait switch to altscreen
  1230. * @retval int 0:Success -1:Error
  1231. *****************************************************************************/
  1232. __unused static int chry_readline_wait_altscreen(chry_readline_t *rl)
  1233. {
  1234. uint32_t c = 0;
  1235. for (;;) {
  1236. chry_readline_waitkey(rl, &c);
  1237. if ((c == CHRY_READLINE_C0_CR) || (c == CHRY_READLINE_C0_LF)) {
  1238. chry_readline_altscreen(rl, 1);
  1239. return 0;
  1240. }
  1241. }
  1242. }
  1243. /*****************************************************************************
  1244. * @brief readline internal
  1245. *
  1246. * @param[in] rl readline instance
  1247. *
  1248. * @retval char* line pointer
  1249. *****************************************************************************/
  1250. static char *chry_readline_inernal(chry_readline_t *rl)
  1251. {
  1252. #if defined(CONFIG_READLINE_NOBLOCK) && CONFIG_READLINE_NOBLOCK
  1253. if (rl->noblock && !rl->block) {
  1254. goto restore;
  1255. }
  1256. #endif
  1257. #if defined(CONFIG_READLINE_XTERM) && CONFIG_READLINE_XTERM
  1258. /*!< wait switch to altscreen */
  1259. if (rl->term.altnsupt == 0) {
  1260. chry_readline_wait_altscreen(rl);
  1261. }
  1262. #endif
  1263. restart:
  1264. if (rl->auto_refresh) {
  1265. #if defined(CONFIG_READLINE_REFRESH_PROMPT) && CONFIG_READLINE_REFRESH_PROMPT
  1266. if (chry_readline_edit_refresh(rl)) {
  1267. return NULL;
  1268. }
  1269. #else
  1270. /*!< output prompt */
  1271. chry_readline_put(rl, rl->prompt, rl->ln.pptlen, NULL);
  1272. if (chry_readline_edit_refresh(rl)) {
  1273. return NULL;
  1274. }
  1275. #endif
  1276. }
  1277. while (1) {
  1278. uint8_t c = 0;
  1279. uint16_t pn[4];
  1280. #if defined(CONFIG_READLINE_XTERM) && CONFIG_READLINE_XTERM
  1281. /*!< wait switch to altscreen */
  1282. if (rl->term.altnsupt == 0) {
  1283. chry_readline_wait_altscreen(rl);
  1284. }
  1285. #endif
  1286. #if defined(CONFIG_READLINE_NOBLOCK) && CONFIG_READLINE_NOBLOCK
  1287. restore:
  1288. #endif
  1289. /*!< get a key */
  1290. chry_readline_getkey(rl, &c);
  1291. #if defined(CONFIG_READLINE_NOBLOCK) && CONFIG_READLINE_NOBLOCK
  1292. if (rl->noblock && !rl->block) {
  1293. return NULL;
  1294. }
  1295. #endif
  1296. if (c & 0x80) {
  1297. /*!< not support 8bit code */
  1298. continue;
  1299. }
  1300. if (CHRY_READLINE_G0_BEG <= c) {
  1301. if (c <= CHRY_READLINE_G0_END) {
  1302. if (rl->ignore) {
  1303. continue;
  1304. }
  1305. /*!< printable characters */
  1306. if (chry_readline_edit_insert(rl, c)) {
  1307. return NULL;
  1308. }
  1309. continue;
  1310. } else {
  1311. /*!< delete */
  1312. c = CHRY_READLINE_EXEC_BS;
  1313. }
  1314. } else if (CHRY_READLINE_C0_ESC == c) {
  1315. if (chry_readline_seqexec(rl, &c, pn)) {
  1316. return NULL;
  1317. }
  1318. } else {
  1319. if (chry_readline_dispatch_ctrl(rl, &c, pn)) {
  1320. return NULL;
  1321. }
  1322. }
  1323. if (rl->ignore) {
  1324. if (c == CHRY_READLINE_EXEC_SIGINT_) {
  1325. c = CHRY_READLINE_EXEC_SIGINT;
  1326. }
  1327. if (c < CHRY_READLINE_EXEC_SIGINT || CHRY_READLINE_EXEC_SIGTSTP < c) {
  1328. continue;
  1329. }
  1330. }
  1331. rehandle:
  1332. /*!< hanlde control */
  1333. switch (c) {
  1334. /*!< ignore */
  1335. case CHRY_READLINE_EXEC_NUL:
  1336. break;
  1337. /*!< clear screen and refresh line */
  1338. case CHRY_READLINE_EXEC_CLR:
  1339. if (chry_readline_edit_clear(rl)) {
  1340. return NULL;
  1341. }
  1342. break;
  1343. /*!< newline */
  1344. case CHRY_READLINE_EXEC_NLN:
  1345. #if defined(CONFIG_READLINE_HISTORY) && CONFIG_READLINE_HISTORY
  1346. if (!rl->ln.mask) {
  1347. chry_readline_history_store(rl);
  1348. }
  1349. #endif
  1350. return rl->ln.buff->pbuf;
  1351. /*!< abortline */
  1352. case CHRY_READLINE_EXEC_ALN:
  1353. rl->ln.buff->size = 0;
  1354. return rl->ln.buff->pbuf;
  1355. /*!< delete */
  1356. case CHRY_READLINE_EXEC_DEL:
  1357. if (chry_readline_edit_delete(rl)) {
  1358. return NULL;
  1359. }
  1360. break;
  1361. /*!< backspace */
  1362. case CHRY_READLINE_EXEC_BS:
  1363. if (chry_readline_edit_backspace(rl)) {
  1364. return NULL;
  1365. }
  1366. break;
  1367. /*!< move right */
  1368. case CHRY_READLINE_EXEC_MVRT:
  1369. if (chry_readline_edit_moveright(rl)) {
  1370. return NULL;
  1371. }
  1372. break;
  1373. /*!< move left */
  1374. case CHRY_READLINE_EXEC_MVLT:
  1375. if (chry_readline_edit_moveleft(rl)) {
  1376. return NULL;
  1377. }
  1378. break;
  1379. /*!< move end */
  1380. case CHRY_READLINE_EXEC_MVED:
  1381. if (chry_readline_edit_moveend(rl)) {
  1382. return NULL;
  1383. }
  1384. break;
  1385. /*!< move home */
  1386. case CHRY_READLINE_EXEC_MVHM:
  1387. if (chry_readline_edit_movehome(rl)) {
  1388. return NULL;
  1389. }
  1390. break;
  1391. /*!< fetch next history */
  1392. case CHRY_READLINE_EXEC_NXTH:
  1393. #if defined(CONFIG_READLINE_HISTORY) && CONFIG_READLINE_HISTORY
  1394. if (!rl->ln.mask) {
  1395. if (chry_readline_history_loadnext(rl)) {
  1396. return NULL;
  1397. }
  1398. }
  1399. #endif
  1400. break;
  1401. /*!< fetch prev history */
  1402. case CHRY_READLINE_EXEC_PRVH:
  1403. #if defined(CONFIG_READLINE_HISTORY) && CONFIG_READLINE_HISTORY
  1404. if (!rl->ln.mask) {
  1405. if (chry_readline_history_loadprev(rl)) {
  1406. return NULL;
  1407. }
  1408. }
  1409. #endif
  1410. break;
  1411. /*!< delete prev word */
  1412. case CHRY_READLINE_EXEC_DLWD:
  1413. if (chry_readline_edit_delword(rl)) {
  1414. return NULL;
  1415. }
  1416. break;
  1417. /*!< delete whole line */
  1418. case CHRY_READLINE_EXEC_DHLN:
  1419. if (chry_readline_edit_delline(rl)) {
  1420. return NULL;
  1421. }
  1422. break;
  1423. /*!< delete cursor to end */
  1424. case CHRY_READLINE_EXEC_DELN:
  1425. if (chry_readline_edit_delend(rl)) {
  1426. return NULL;
  1427. }
  1428. break;
  1429. /*!< auto complete */
  1430. case CHRY_READLINE_EXEC_CPLT:
  1431. #if defined(CONFIG_READLINE_COMPLETION) && CONFIG_READLINE_COMPLETION
  1432. {
  1433. /*!< disable completion in mask mode */
  1434. if (rl->ln.mask) {
  1435. break;
  1436. }
  1437. int ret = chry_readline_complete(rl);
  1438. if (ret < 0) {
  1439. return NULL;
  1440. } else if (ret == 0) {
  1441. break;
  1442. } else {
  1443. goto restart;
  1444. }
  1445. }
  1446. #else
  1447. break;
  1448. #endif
  1449. case CHRY_READLINE_EXEC_ACPLT: {
  1450. /*!< if cursor left char is space */
  1451. if ((rl->ln.curoff == 0) || (rl->ln.buff->pbuf[rl->ln.curoff - 1] == ' ')) {
  1452. int spcnt = CONFIG_READLINE_SPACE - (rl->ln.curoff % CONFIG_READLINE_SPACE);
  1453. for (uint8_t i = 0; i < spcnt; i++) {
  1454. chry_readline_edit_insert(rl, ' ');
  1455. }
  1456. break;
  1457. } else {
  1458. /*!< disable completion in mask mode */
  1459. if (rl->ln.mask) {
  1460. break;
  1461. }
  1462. int ret = chry_readline_complete(rl);
  1463. if (ret < 0) {
  1464. return NULL;
  1465. } else if (ret == 0) {
  1466. break;
  1467. } else {
  1468. goto restart;
  1469. }
  1470. }
  1471. }
  1472. /*!< switch to normal screen */
  1473. case CHRY_READLINE_EXEC_SWNM:
  1474. chry_readline_altscreen(rl, 0);
  1475. break;
  1476. case CHRY_READLINE_EXEC_HELP:
  1477. if (chry_readline_help(rl)) {
  1478. return NULL;
  1479. }
  1480. rl->ln.buff->size = 0;
  1481. return rl->ln.buff->pbuf;
  1482. case CHRY_READLINE_EXEC_EOF_:
  1483. if (rl->ln.buff->size == 0) {
  1484. c = CHRY_READLINE_EXEC_EOF;
  1485. goto rehandle;
  1486. }
  1487. if (chry_readline_edit_delete(rl)) {
  1488. return NULL;
  1489. }
  1490. break;
  1491. case CHRY_READLINE_EXEC_SIGINT_:
  1492. if (rl->ln.buff->size == 0) {
  1493. c = CHRY_READLINE_EXEC_SIGINT;
  1494. goto rehandle;
  1495. } else {
  1496. rl->ln.buff->size = 0;
  1497. return rl->ln.buff->pbuf;
  1498. }
  1499. break;
  1500. case CHRY_READLINE_EXEC_EOF:
  1501. case CHRY_READLINE_EXEC_SIGINT:
  1502. case CHRY_READLINE_EXEC_SIGQUIT:
  1503. case CHRY_READLINE_EXEC_SIGCONT:
  1504. case CHRY_READLINE_EXEC_SIGSTOP:
  1505. case CHRY_READLINE_EXEC_SIGTSTP:
  1506. case CHRY_READLINE_EXEC_F1:
  1507. case CHRY_READLINE_EXEC_F2:
  1508. case CHRY_READLINE_EXEC_F3:
  1509. case CHRY_READLINE_EXEC_F4:
  1510. case CHRY_READLINE_EXEC_F5:
  1511. case CHRY_READLINE_EXEC_F6:
  1512. case CHRY_READLINE_EXEC_F7:
  1513. case CHRY_READLINE_EXEC_F8:
  1514. case CHRY_READLINE_EXEC_F9:
  1515. case CHRY_READLINE_EXEC_F10:
  1516. case CHRY_READLINE_EXEC_F11:
  1517. case CHRY_READLINE_EXEC_F12:
  1518. default:
  1519. if (rl->ucb) {
  1520. int ret = rl->ucb(rl, c);
  1521. if (ret == 0) {
  1522. goto restart;
  1523. } else if (ret < 0) {
  1524. return NULL;
  1525. } else {
  1526. break;
  1527. }
  1528. } else {
  1529. break;
  1530. }
  1531. }
  1532. }
  1533. }
  1534. /*****************************************************************************
  1535. * @brief enable or disable altscreen buffer (xterm only)
  1536. *
  1537. * @param[in] rl readline instance
  1538. * @param[in] enable altscreen enable
  1539. *
  1540. * @retval int 0:Success -1:Error
  1541. *****************************************************************************/
  1542. int chry_readline_altscreen(chry_readline_t *rl, uint8_t enable)
  1543. {
  1544. (void)enable;
  1545. if (rl->term.nsupt) {
  1546. return -1;
  1547. }
  1548. #if defined(CONFIG_READLINE_XTERM) && CONFIG_READLINE_XTERM
  1549. if (enable) {
  1550. chry_readline_put(rl, "\033[?47h", 6, );
  1551. rl->term.alt = 1;
  1552. } else {
  1553. chry_readline_put(rl, "\033[?47l", 6, );
  1554. rl->term.alt = 0;
  1555. }
  1556. #endif
  1557. return 0;
  1558. }
  1559. /*****************************************************************************
  1560. * @brief Fill Character Attributes SGR set to sgrraw
  1561. *
  1562. * @param[in] buf buffer for fill, max 17byte
  1563. * @param[in] sgrraw sgr attributes, 0 to reset
  1564. *
  1565. *****************************************************************************/
  1566. __unused static uint8_t chry_readline_sgrset(char *buf, uint16_t sgrraw)
  1567. {
  1568. chry_readline_sgr_t sgr = { .raw = sgrraw };
  1569. size_t idx = 0;
  1570. chry_readline_seqgen_csi((void *)buf, &idx);
  1571. if (sgrraw == 0) {
  1572. buf[idx++] = 'm';
  1573. buf[idx] = '\0';
  1574. return idx;
  1575. }
  1576. if (sgr.bold) {
  1577. buf[idx + 0] = '1';
  1578. buf[idx + 1] = ';';
  1579. idx += 2;
  1580. }
  1581. if (sgr.underline) {
  1582. buf[idx + 0] = '4';
  1583. buf[idx + 1] = ';';
  1584. idx += 2;
  1585. }
  1586. if (sgr.blink) {
  1587. buf[idx + 0] = '5';
  1588. buf[idx + 1] = ';';
  1589. idx += 2;
  1590. }
  1591. if (sgr.inverse) {
  1592. buf[idx + 0] = '8';
  1593. buf[idx + 1] = ';';
  1594. idx += 2;
  1595. }
  1596. if (sgr.foreground) {
  1597. buf[idx + 0] = '3';
  1598. buf[idx + 1] = '0' + (sgr.foreground - 1);
  1599. buf[idx + 2] = ';';
  1600. idx += 3;
  1601. }
  1602. if (sgr.background) {
  1603. buf[idx + 0] = '4';
  1604. buf[idx + 1] = '0' + (sgr.background - 1);
  1605. buf[idx + 2] = ';';
  1606. idx += 3;
  1607. }
  1608. buf[idx - 1] = 'm';
  1609. buf[idx] = '\0';
  1610. return idx;
  1611. }
  1612. /*****************************************************************************
  1613. * @brief output CONFIG_READLINE_NEWLINE
  1614. *
  1615. * @param[in] rl readline instance
  1616. *
  1617. *****************************************************************************/
  1618. void chry_readline_newline(chry_readline_t *rl)
  1619. {
  1620. chry_readline_put(rl, CONFIG_READLINE_NEWLINE, sizeof(CONFIG_READLINE_NEWLINE) ? sizeof(CONFIG_READLINE_NEWLINE) - 1 : 0, );
  1621. }
  1622. /*****************************************************************************
  1623. * @brief clear screen and refresh line
  1624. *
  1625. * @param[in] rl readline instance
  1626. *
  1627. *****************************************************************************/
  1628. void chry_readline_clear(chry_readline_t *rl)
  1629. {
  1630. CHRY_READLINE_PARAM_CHECK(NULL != rl, );
  1631. chry_readline_edit_clear(rl);
  1632. }
  1633. /*****************************************************************************
  1634. * @brief enable or disable block mode
  1635. *
  1636. * @param[in] rl readline instance
  1637. * @param[in] enable block enable
  1638. *
  1639. *****************************************************************************/
  1640. void chry_readline_block(chry_readline_t *rl, uint8_t enable)
  1641. {
  1642. CHRY_READLINE_PARAM_CHECK(NULL != rl, );
  1643. #if defined(CONFIG_READLINE_NOBLOCK) && CONFIG_READLINE_NOBLOCK
  1644. rl->block = enable ? 1 : 0;
  1645. #else
  1646. (void)rl;
  1647. (void)enable;
  1648. #endif
  1649. }
  1650. /*****************************************************************************
  1651. * @brief enable or disable ignore mode
  1652. *
  1653. * @param[in] rl readline instance
  1654. * @param[in] enable ignore enable
  1655. *
  1656. *****************************************************************************/
  1657. void chry_readline_ignore(chry_readline_t *rl, uint8_t enable)
  1658. {
  1659. CHRY_READLINE_PARAM_CHECK(NULL != rl, );
  1660. rl->ignore = enable ? 1 : 0;
  1661. }
  1662. /*****************************************************************************
  1663. * @brief enable or disable ignore mode
  1664. *
  1665. * @param[in] rl readline instance
  1666. * @param[in] enable ignore enable
  1667. *
  1668. *****************************************************************************/
  1669. void chry_readline_auto_refresh(chry_readline_t *rl, uint8_t enable)
  1670. {
  1671. CHRY_READLINE_PARAM_CHECK(NULL != rl, );
  1672. rl->auto_refresh = enable ? 1 : 0;
  1673. }
  1674. /*****************************************************************************
  1675. * @brief enable or disable mask mode
  1676. *
  1677. * @param[in] rl readline instance
  1678. * @param[in] enable mask enable
  1679. *
  1680. *****************************************************************************/
  1681. void chry_readline_mask(chry_readline_t *rl, uint8_t enable)
  1682. {
  1683. CHRY_READLINE_PARAM_CHECK(NULL != rl, );
  1684. rl->ln.mask = enable ? 1 : 0;
  1685. if (NULL != rl->ln.buff) {
  1686. chry_readline_edit_refresh(rl);
  1687. }
  1688. }
  1689. /*****************************************************************************
  1690. * @brief readline
  1691. *
  1692. * @param[in] rl readline instance
  1693. * @param[in] linebuff linebuff pointer
  1694. * @param[in] buffsize linebuff size
  1695. * @param[in] linesize readline size (set NULL to ignore)
  1696. *
  1697. * @retval char* line pointer
  1698. *****************************************************************************/
  1699. char *chry_readline(chry_readline_t *rl, char *linebuff, uint16_t buffsize, uint16_t *linesize)
  1700. {
  1701. char *ret;
  1702. CHRY_READLINE_PARAM_CHECK(NULL != rl, NULL);
  1703. CHRY_READLINE_PARAM_CHECK(NULL != linebuff, NULL);
  1704. if (buffsize <= 3) {
  1705. return NULL;
  1706. }
  1707. #if defined(CONFIG_READLINE_NOBLOCK) && CONFIG_READLINE_NOBLOCK
  1708. if (rl->noblock && !rl->block) {
  1709. goto restore;
  1710. }
  1711. #endif
  1712. rl->ln.buff = (void *)linebuff;
  1713. rl->ln.buff->size = 0;
  1714. rl->ln.lnmax = buffsize - 3; /*!< reserved for \0 and size */
  1715. rl->ln.curoff = 0;
  1716. #if defined(CONFIG_READLINE_HISTORY) && CONFIG_READLINE_HISTORY
  1717. rl->hist.index = 0;
  1718. #endif
  1719. /*!< calculate prompt offset and size */
  1720. chry_readline_calculate_prompt(rl);
  1721. #if defined(CONFIG_READLINE_NOBLOCK) && CONFIG_READLINE_NOBLOCK
  1722. restore:
  1723. #endif
  1724. ret = chry_readline_inernal(rl);
  1725. #if defined(CONFIG_READLINE_NOBLOCK) && CONFIG_READLINE_NOBLOCK
  1726. if (rl->noblock && !rl->block) {
  1727. return (void *)-1;
  1728. }
  1729. #endif
  1730. /*!< new line */
  1731. chry_readline_put(rl, CONFIG_READLINE_NEWLINE, sizeof(CONFIG_READLINE_NEWLINE) ? sizeof(CONFIG_READLINE_NEWLINE) - 1 : 0, NULL);
  1732. if (NULL != linesize) {
  1733. *linesize = rl->ln.buff->size;
  1734. }
  1735. rl->ln.buff->pbuf[rl->ln.buff->size] = '\0';
  1736. rl->ln.buff = NULL;
  1737. return ret;
  1738. }
  1739. /*****************************************************************************
  1740. * @brief init readline
  1741. *
  1742. * @param[in] rl readline instance
  1743. * @param[in] init init param
  1744. *
  1745. * @retval int 0:Success -1:Error
  1746. *****************************************************************************/
  1747. int chry_readline_init(chry_readline_t *rl, chry_readline_init_t *init)
  1748. {
  1749. CHRY_READLINE_PARAM_CHECK(NULL != rl, -1);
  1750. CHRY_READLINE_PARAM_CHECK(NULL != init, -1);
  1751. CHRY_READLINE_PARAM_CHECK(NULL != init->sget, -1);
  1752. CHRY_READLINE_PARAM_CHECK(NULL != init->sput, -1);
  1753. CHRY_READLINE_PARAM_CHECK(NULL != init->prompt, -1);
  1754. #if defined(CONFIG_READLINE_HISTORY) && CONFIG_READLINE_HISTORY
  1755. CHRY_READLINE_PARAM_CHECK(NULL != init->history, -1);
  1756. #endif
  1757. if ((init->histsize < 2) || (init->histsize & (init->histsize - 1))) {
  1758. return -1;
  1759. }
  1760. rl->prompt = init->prompt;
  1761. rl->sget = init->sget;
  1762. rl->sput = init->sput;
  1763. #if defined(CONFIG_READLINE_HISTORY) && CONFIG_READLINE_HISTORY
  1764. rl->hist.pbuf = init->history;
  1765. rl->hist.in = 0;
  1766. rl->hist.out = 0;
  1767. rl->hist.mask = init->histsize - 1;
  1768. rl->hist.size = init->histsize;
  1769. rl->hist.cache = 0;
  1770. #endif
  1771. #if defined(CONFIG_READLINE_COMPLETION) && CONFIG_READLINE_COMPLETION
  1772. rl->cplt.acb = NULL;
  1773. #endif
  1774. #if defined(CONFIG_READLINE_PROMPTEDIT) && CONFIG_READLINE_PROMPTEDIT
  1775. memset(rl->pptseglen, 0, CONFIG_READLINE_PROMPTSEG + 1);
  1776. #endif
  1777. rl->term.nsupt = 1;
  1778. rl->term.alt = 0;
  1779. rl->term.row = CONFIG_READLINE_DFTROW;
  1780. rl->term.col = CONFIG_READLINE_DFTCOL;
  1781. rl->ln.buff = NULL;
  1782. rl->ln.mask = 0;
  1783. rl->ln.pptsize = init->pptsize;
  1784. rl->ucb = NULL;
  1785. rl->ignore = false;
  1786. rl->auto_refresh = true;
  1787. #if defined(CONFIG_READLINE_CTRLMAP) && CONFIG_READLINE_CTRLMAP
  1788. memcpy(rl->ctrlmap, ctrlmap, sizeof(ctrlmap));
  1789. #endif
  1790. #if defined(CONFIG_READLINE_ALTMAP) && CONFIG_READLINE_ALTMAP
  1791. memcpy(rl->altmap, altmap, sizeof(altmap));
  1792. #endif
  1793. #if defined(CONFIG_READLINE_NOBLOCK) && CONFIG_READLINE_NOBLOCK
  1794. rl->noblock = false;
  1795. rl->block = false;
  1796. #endif
  1797. return 0;
  1798. }
  1799. /*****************************************************************************
  1800. * @brief detects if it is xterm, result will be processed automatically
  1801. * if not xterm it will be blocked on next character
  1802. *
  1803. * @param[in] rl readline instance
  1804. *****************************************************************************/
  1805. void chry_readline_detect(chry_readline_t *rl)
  1806. {
  1807. uint8_t c;
  1808. uint16_t pn[4];
  1809. /*!< test sput and get screen size */
  1810. if (5 != rl->sput(rl, "\033[18t", 5)) {
  1811. return;
  1812. }
  1813. chry_readline_waitkey(rl, &c);
  1814. if (c == CHRY_READLINE_C0_ESC) {
  1815. /*!< execute sequence */
  1816. chry_readline_seqexec(rl, &c, pn);
  1817. }
  1818. }
  1819. /*****************************************************************************
  1820. * @brief set auto complete callback
  1821. *
  1822. * @param[in] rl readline instance
  1823. * @param[in] acb callback
  1824. *
  1825. *****************************************************************************/
  1826. void chry_readline_set_completion_cb(chry_readline_t *rl, uint8_t (*acb)(chry_readline_t *rl, char *pre, uint16_t *size, const char **argv, uint8_t *argl, uint8_t argcmax))
  1827. {
  1828. (void)rl;
  1829. (void)acb;
  1830. #if defined(CONFIG_READLINE_COMPLETION) && CONFIG_READLINE_COMPLETION
  1831. rl->cplt.acb = acb;
  1832. #endif
  1833. }
  1834. /*****************************************************************************
  1835. * @brief set user event exec callback
  1836. *
  1837. * @param[in] rl readline instance
  1838. * @param[in] ucb callback
  1839. *
  1840. *****************************************************************************/
  1841. void chry_readline_set_user_cb(chry_readline_t *rl, int (*ucb)(chry_readline_t *rl, uint8_t exec))
  1842. {
  1843. rl->ucb = ucb;
  1844. }
  1845. /*****************************************************************************
  1846. * @brief set ctrl mapping
  1847. *
  1848. * @param[in] rl readline instance
  1849. * @param[in] mapidx map index
  1850. * @param[in] exec exec code
  1851. *
  1852. *****************************************************************************/
  1853. void chry_readline_set_ctrlmap(chry_readline_t *rl, uint8_t mapidx, uint8_t exec)
  1854. {
  1855. (void)rl;
  1856. #if defined(CONFIG_READLINE_CTRLMAP) && CONFIG_READLINE_CTRLMAP
  1857. rl->ctrlmap[mapidx] = exec;
  1858. #else
  1859. ctrlmap[mapidx] = exec;
  1860. #endif
  1861. }
  1862. /*****************************************************************************
  1863. * @brief set alt mapping
  1864. *
  1865. * @param[in] rl readline instance
  1866. * @param[in] mapidx map index
  1867. * @param[in] exec exec code
  1868. *
  1869. *****************************************************************************/
  1870. void chry_readline_set_altmap(chry_readline_t *rl, uint8_t mapidx, uint8_t exec)
  1871. {
  1872. (void)rl;
  1873. #if defined(CONFIG_READLINE_ALTMAP) && CONFIG_READLINE_ALTMAP
  1874. rl->altmap[mapidx] = exec;
  1875. #else
  1876. altmap[mapidx] = exec;
  1877. #endif
  1878. }
  1879. #if defined(CONFIG_READLINE_DEBUG) && CONFIG_READLINE_DEBUG
  1880. /*****************************************************************************
  1881. * @brief debug for keycode test
  1882. *
  1883. * @param[in] rl readline instance
  1884. *
  1885. *****************************************************************************/
  1886. void chry_readline_debug(chry_readline_t *rl)
  1887. {
  1888. chry_readline_put(rl, "debug keycodes mode\r\n", 22, );
  1889. char fifo[5] = { 0 };
  1890. while (1) {
  1891. int8_t len;
  1892. uint8_t c = 0;
  1893. char buf[32];
  1894. /*!< get a key */
  1895. chry_readline_waitkey(rl, &c);
  1896. if (c < CHRY_READLINE_G0_BEG) {
  1897. len = snprintf(buf, 32, "'^%c' %02x (%3d) /exit to break\r\n", c + 0x40, c, c);
  1898. chry_readline_put(rl, buf, len, );
  1899. } else if ((CHRY_READLINE_G0_BEG <= c) && (c <= CHRY_READLINE_G0_END)) {
  1900. /*!< printable characters */
  1901. len = snprintf(buf, 32, " '%c' %02x (%3d) /exit to break\r\n", c, c, c);
  1902. chry_readline_put(rl, buf, len, );
  1903. } else {
  1904. len = snprintf(buf, 32, " '?' %02x (%3d) /exit to break\r\n", c, c);
  1905. chry_readline_put(rl, buf, len, );
  1906. }
  1907. fifo[4] = fifo[3];
  1908. fifo[3] = fifo[2];
  1909. fifo[2] = fifo[1];
  1910. fifo[1] = fifo[0];
  1911. fifo[0] = c;
  1912. if (memcmp(fifo, "tixe/", 5) == 0) {
  1913. break;
  1914. }
  1915. }
  1916. }
  1917. #endif
  1918. /*****************************************************************************
  1919. * @brief edit the specified segment of the prompt,
  1920. * segment will be create at first edit
  1921. *
  1922. * @param[in] rl readline instance
  1923. * @param[in] secidx segment index, < PPTSEG
  1924. * @param[in] sgrraw sgr sequense raw data
  1925. * @param[in] format string end with \0
  1926. * @param[in] ... params
  1927. *
  1928. * @retval int 0:Success -1:Error -2:No space
  1929. *****************************************************************************/
  1930. int chry_readline_prompt_edit(chry_readline_t *rl, uint8_t segidx, uint16_t sgrraw, const char *format, ...)
  1931. {
  1932. #if defined(CONFIG_READLINE_PROMPTEDIT) && CONFIG_READLINE_PROMPTEDIT
  1933. va_list ap;
  1934. char sgrbuf[17];
  1935. uint16_t pptlen;
  1936. int freelen;
  1937. int seglen;
  1938. uint16_t segoff = 0;
  1939. uint8_t sgrlen;
  1940. if (segidx >= CONFIG_READLINE_PROMPTSEG) {
  1941. return -1;
  1942. }
  1943. /*!< not allowed any free seg exists before this seg */
  1944. for (uint8_t i = 0; i < segidx; i++) {
  1945. segoff += rl->pptseglen[i];
  1946. if (rl->pptseglen[i] == 0) {
  1947. return -1;
  1948. }
  1949. }
  1950. /*!< calculate total prompt len */
  1951. pptlen = 0;
  1952. for (uint8_t i = 0; i < CONFIG_READLINE_PROMPTSEG; i++) {
  1953. if (i == segidx) {
  1954. continue;
  1955. }
  1956. pptlen += rl->pptseglen[i];
  1957. }
  1958. /*!< freelen reserved 1 for \0, 3 for \e[m */
  1959. freelen = rl->ln.pptsize - 1 - 3 - pptlen;
  1960. /*!< output sgr sequence and get len */
  1961. sgrlen = chry_readline_sgrset(sgrbuf, sgrraw);
  1962. if (freelen < (int)sgrlen) {
  1963. return -2;
  1964. }
  1965. /*!< if next segment is not used */
  1966. if (rl->pptseglen[segidx + 1] == 0) {
  1967. /*!< copy sgrbuff to prompt */
  1968. memcpy(&(rl->prompt[segoff]), sgrbuf, sgrlen);
  1969. freelen -= sgrlen;
  1970. /*!< output format to prompt */
  1971. va_start(ap, format);
  1972. seglen = vsnprintf(&(rl->prompt[segoff + sgrlen]), freelen + 1, format, ap);
  1973. va_end(ap);
  1974. if (seglen > freelen) {
  1975. /*!< set segment len */
  1976. rl->pptseglen[segidx] = sgrlen + freelen;
  1977. /*!< end with \e0m\0 */
  1978. memcpy(&(rl->prompt[segoff + sgrlen + freelen]), "\033[m", 5);
  1979. return -2;
  1980. } else {
  1981. /*!< set segment len */
  1982. rl->pptseglen[segidx] = sgrlen + seglen;
  1983. /*!< end with \e0m\0 */
  1984. memcpy(&(rl->prompt[segoff + sgrlen + seglen]), "\033[m", 5);
  1985. return 0;
  1986. }
  1987. }
  1988. /*!< get the seg len */
  1989. va_start(ap, format);
  1990. seglen = vsnprintf(NULL, 0, format, ap);
  1991. va_end(ap);
  1992. int actlen = sgrlen + seglen;
  1993. actlen = freelen > actlen ? actlen : freelen;
  1994. memmove(
  1995. &(rl->prompt[segoff + actlen]),
  1996. &(rl->prompt[segoff + rl->pptseglen[segidx]]),
  1997. pptlen - segoff);
  1998. /*!< copy sgrbuff to prompt */
  1999. memcpy(&(rl->prompt[segoff]), sgrbuf, sgrlen);
  2000. freelen -= sgrlen;
  2001. /*!< backup vsnprintf overwrite char */
  2002. char bakc = rl->prompt[segoff + actlen];
  2003. /*!< output format to prompt */
  2004. va_start(ap, format);
  2005. seglen = vsnprintf(&(rl->prompt[segoff + sgrlen]), freelen + 1, format, ap);
  2006. va_end(ap);
  2007. rl->prompt[segoff + actlen] = bakc;
  2008. /*!< set segment len */
  2009. rl->pptseglen[segidx] = actlen;
  2010. /*!< end with \e0m\0 */
  2011. memcpy(&(rl->prompt[pptlen + actlen]), "\033[m", 5);
  2012. if (seglen > freelen) {
  2013. return -2;
  2014. } else {
  2015. return 0;
  2016. }
  2017. #else
  2018. (void)rl;
  2019. (void)segidx;
  2020. (void)sgrraw;
  2021. (void)format;
  2022. return 0;
  2023. #endif
  2024. }
  2025. /*****************************************************************************
  2026. * @brief clear all seglen, next edit is first
  2027. *
  2028. * @param[in] rl readline instance
  2029. *
  2030. *****************************************************************************/
  2031. void chry_readline_prompt_clear(chry_readline_t *rl)
  2032. {
  2033. #if defined(CONFIG_READLINE_PROMPTEDIT) && CONFIG_READLINE_PROMPTEDIT
  2034. memset(rl->pptseglen, 0, CONFIG_READLINE_PROMPTSEG + 1);
  2035. #else
  2036. (void)rl;
  2037. #endif
  2038. }