vi_utils.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /*
  2. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  3. */
  4. #ifndef __VI_UTILS_H__
  5. #define __VI_UTILS_H__
  6. #include <rtthread.h>
  7. #include <ctype.h>
  8. #include <fcntl.h>
  9. #include <limits.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <strings.h>
  14. #include <unistd.h>
  15. #include <poll.h>
  16. #include <sys/types.h>
  17. #include <sys/errno.h>
  18. #include <sys/stat.h>
  19. #define BB_VER "latest: 2021-08-29"
  20. #define BB_BT "Busybox vi for RT-Thread"
  21. //config:config FEATURE_VI_MAX_LEN
  22. //config: int "Maximum screen width in vi"
  23. //config: range 256 16384
  24. //config: default 4096
  25. //config: depends on VI
  26. //config: help
  27. //config: Contrary to what you may think, this is not eating much.
  28. //config: Make it smaller than 4k only if you are very limited on memory.
  29. #ifdef VI_MAX_LEN
  30. #define CONFIG_FEATURE_VI_MAX_LEN VI_MAX_LEN
  31. #else
  32. #define CONFIG_FEATURE_VI_MAX_LEN 4096
  33. #endif
  34. //config:config FEATURE_VI_ASK_TERMINAL
  35. //config: bool "Use 'tell me cursor position' ESC sequence to measure window"
  36. //config: default y
  37. //config: depends on VI
  38. //config: help
  39. //config: If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
  40. //config: this option makes vi perform a last-ditch effort to find it:
  41. //config: position cursor to 999,999 and ask terminal to report real
  42. //config: cursor position using "ESC [ 6 n" escape sequence, then read stdin.
  43. //config:
  44. //config: This is not clean but helps a lot on serial lines and such.
  45. #ifdef VI_ENABLE_VI_ASK_TERMINAL
  46. #define ENABLE_FEATURE_VI_ASK_TERMINAL 1
  47. #define IF_FEATURE_VI_ASK_TERMINAL(...) __VA_ARGS__
  48. #else
  49. #define ENABLE_FEATURE_VI_ASK_TERMINAL 0
  50. #define IF_FEATURE_VI_ASK_TERMINAL(...)
  51. #endif
  52. //config:config FEATURE_VI_COLON
  53. //config: bool "Enable \":\" colon commands (no \"ex\" mode)"
  54. //config: default y
  55. //config: depends on VI
  56. //config: help
  57. //config: Enable a limited set of colon commands for vi. This does not
  58. //config: provide an "ex" mode.
  59. #ifdef VI_ENABLE_COLON
  60. #define ENABLE_FEATURE_VI_COLON 1
  61. #define IF_FEATURE_VI_COLON(...) __VA_ARGS__
  62. #else
  63. #define ENABLE_FEATURE_VI_COLON 0
  64. #define IF_FEATURE_VI_COLON(...)
  65. #endif
  66. //config:config FEATURE_VI_COLON_EXPAND
  67. //config: bool "Expand \"%\" and \"#\" in colon commands"
  68. //config: default y
  69. //config: depends on FEATURE_VI_COLON
  70. //config: help
  71. //config: Expand the special characters \"%\" (current filename)
  72. //config: and \"#\" (alternate filename) in colon commands.
  73. #ifdef VI_ENABLE_COLON_EXPAND
  74. #define ENABLE_FEATURE_VI_COLON_EXPAND 1
  75. #else
  76. #define ENABLE_FEATURE_VI_COLON_EXPAND 0
  77. #endif
  78. //config:config FEATURE_VI_SEARCH
  79. //config: bool "Enable search and replace cmds"
  80. //config: default y
  81. //config: depends on VI
  82. //config: help
  83. //config: Select this if you wish to be able to do search and replace in
  84. //config: busybox vi.
  85. #ifdef VI_ENABLE_SEARCH
  86. #define ENABLE_FEATURE_VI_SEARCH 1
  87. #define IF_FEATURE_VI_SEARCH(...) __VA_ARGS__
  88. #else
  89. #define ENABLE_FEATURE_VI_SEARCH 0
  90. #define IF_FEATURE_VI_SEARCH(...)
  91. #endif
  92. //config:config FEATURE_VI_READONLY
  93. //config: bool "Enable -R option and \"view\" mode"
  94. //config: default y
  95. //config: depends on VI
  96. //config: help
  97. //config: Enable the read-only command line option, which allows the user to
  98. //config: open a file in read-only mode.
  99. #ifdef VI_ENABLE_READONLY
  100. #define ENABLE_FEATURE_VI_READONLY 1
  101. #define IF_FEATURE_VI_READONLY(...) __VA_ARGS__
  102. #else
  103. #define ENABLE_FEATURE_VI_READONLY 0
  104. #define IF_FEATURE_VI_READONLY(...)
  105. #endif
  106. //config:config FEATURE_VI_SET
  107. //config: bool "Support for :set"
  108. //config: default y
  109. //config: depends on VI
  110. //config: help
  111. //config: Support for ":set".
  112. #ifdef VI_ENABLE_SET
  113. #define ENABLE_FEATURE_VI_SET 1
  114. #define IF_FEATURE_VI_SET(...) __VA_ARGS__
  115. #else
  116. #define ENABLE_FEATURE_VI_SET 0
  117. #define IF_FEATURE_VI_SET(...)
  118. #endif
  119. //config:config FEATURE_VI_SETOPTS
  120. //config: bool "Enable set-able options, ai ic showmatch"
  121. //config: default y
  122. //config: depends on VI
  123. //config: help
  124. //config: Enable the editor to set some (ai, ic, showmatch) options.
  125. #ifdef VI_ENABLE_SETOPTS
  126. #define ENABLE_FEATURE_VI_SETOPTS 1
  127. #define IF_FEATURE_VI_SETOPTS(...) __VA_ARGS__
  128. #else
  129. #define ENABLE_FEATURE_VI_SETOPTS 0
  130. #define IF_FEATURE_VI_SETOPTS(...)
  131. #endif
  132. //config:
  133. //config:config FEATURE_VI_WIN_RESIZE
  134. //config: bool "Handle window resize"
  135. //config: default y
  136. //config: depends on VI
  137. //config: help
  138. //config: Make busybox vi behave nicely with terminals that get resized.
  139. #ifdef VI_ENABLE_WIN_RESIZE
  140. #define ENABLE_FEATURE_VI_WIN_RESIZE 1
  141. #define IF_FEATURE_VI_WIN_RESIZE(...) __VA_ARGS__
  142. #else
  143. #define ENABLE_FEATURE_VI_WIN_RESIZE 0
  144. #define IF_FEATURE_VI_WIN_RESIZE(...)
  145. #endif
  146. //config:config FEATURE_VI_YANKMARK
  147. //config: bool "Enable yank/put commands and mark cmds"
  148. //config: default y
  149. //config: depends on VI
  150. //config: help
  151. //config: This will enable you to use yank and put, as well as mark in
  152. //config: busybox vi.
  153. //config:
  154. #ifdef VI_ENABLE_YANKMARK
  155. #define ENABLE_FEATURE_VI_YANKMARK 1
  156. #define IF_FEATURE_VI_YANKMARK(...) __VA_ARGS__
  157. #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
  158. #else
  159. #define ENABLE_FEATURE_VI_YANKMARK 0
  160. #define IF_FEATURE_VI_YANKMARK(...)
  161. #endif
  162. //config:config FEATURE_VI_DOT_CMD
  163. //config: bool "Remember previous cmd and \".\" cmd"
  164. //config: default y
  165. //config: depends on VI
  166. //config: help
  167. //config: Make busybox vi remember the last command and be able to repeat it.
  168. #ifdef VI_ENABLE_DOT_CMD
  169. #define ENABLE_FEATURE_VI_DOT_CMD 1
  170. #define IF_FEATURE_VI_DOT_CMD(...) __VA_ARGS__
  171. #else
  172. #define ENABLE_FEATURE_VI_DOT_CMD 0
  173. #define IF_FEATURE_VI_DOT_CMD(...)
  174. #endif
  175. //config:config FEATURE_VI_UNDO
  176. //config: bool "Support undo command 'u'"
  177. //config: default y
  178. //config: depends on VI
  179. //config: help
  180. //config: Support the 'u' command to undo insertion, deletion, and replacement
  181. //config: of text.
  182. #ifdef VI_ENABLE_UNDO
  183. #define ENABLE_FEATURE_VI_UNDO 1
  184. #define IF_FEATURE_VI_UNDO(...) __VA_ARGS__
  185. #else
  186. #define ENABLE_FEATURE_VI_UNDO 0
  187. #define IF_FEATURE_VI_UNDO(...)
  188. #endif
  189. //config:config FEATURE_VI_UNDO_QUEUE
  190. //config: bool "Enable undo operation queuing"
  191. //config: default y
  192. //config: depends on FEATURE_VI_UNDO
  193. //config: help
  194. //config: The vi undo functions can use an intermediate queue to greatly lower
  195. //config: malloc() calls and overhead. When the maximum size of this queue is
  196. //config: reached, the contents of the queue are committed to the undo stack.
  197. //config: This increases the size of the undo code and allows some undo
  198. //config: operations (especially un-typing/backspacing) to be far more useful.
  199. //config:config FEATURE_VI_UNDO_QUEUE_MAX
  200. //config: int "Maximum undo character queue size"
  201. //config: default 256
  202. //config: range 32 65536
  203. //config: depends on FEATURE_VI_UNDO_QUEUE
  204. //config: help
  205. //config: This option sets the number of bytes used at runtime for the queue.
  206. //config: Smaller values will create more undo objects and reduce the amount
  207. //config: of typed or backspaced characters that are grouped into one undo
  208. //config: operation; larger values increase the potential size of each undo
  209. //config: and will generally malloc() larger objects and less frequently.
  210. //config: Unless you want more (or less) frequent "undo points" while typing,
  211. //config: you should probably leave this unchanged.
  212. #ifdef VI_ENABLE_UNDO_QUEUE
  213. #define ENABLE_FEATURE_VI_UNDO_QUEUE 1
  214. #define IF_FEATURE_VI_UNDO_QUEUE(...) __VA_ARGS__
  215. #define CONFIG_FEATURE_VI_UNDO_QUEUE_MAX VI_UNDO_QUEUE_MAX
  216. #else
  217. #define ENABLE_FEATURE_VI_UNDO_QUEUE 0
  218. #define IF_FEATURE_VI_UNDO_QUEUE(...)
  219. #endif
  220. //config:config FEATURE_VI_VERBOSE_STATUS
  221. //config: bool "Enable verbose status reporting"
  222. //config: default y
  223. //config: depends on VI
  224. //config: help
  225. //config: Enable more verbose reporting of the results of yank, change,
  226. //config: delete, undo and substitution commands.
  227. #ifdef VI_ENABLE_VERBOSE_STATUS
  228. #define ENABLE_FEATURE_VI_VERBOSE_STATUS 1
  229. #else
  230. #define ENABLE_FEATURE_VI_VERBOSE_STATUS 0
  231. #endif
  232. //config:config FEATURE_VI_REGEX_SEARCH
  233. //config: bool "Enable regex in search and replace"
  234. //config: default n # Uses GNU regex, which may be unavailable. FIXME
  235. //config: depends on FEATURE_VI_SEARCH
  236. //config: help
  237. //config: Use extended regex search.
  238. #ifdef VI_ENABLE_REGEX_SEARCH
  239. #define ENABLE_FEATURE_VI_REGEX_SEARCH 1
  240. #define IF_FEATURE_VI_REGEX_SEARCH(...) __VA_ARGS__
  241. #else
  242. #define ENABLE_FEATURE_VI_REGEX_SEARCH 0
  243. #define IF_FEATURE_VI_REGEX_SEARCH(...)
  244. #endif
  245. //config:config FEATURE_VI_8BIT
  246. //config: bool "Allow vi to display 8-bit chars (otherwise shows dots)"
  247. //config: default n
  248. //config: depends on VI
  249. //config: help
  250. //config: If your terminal can display characters with high bit set,
  251. //config: you may want to enable this. Note: vi is not Unicode-capable.
  252. //config: If your terminal combines several 8-bit bytes into one character
  253. //config: (as in Unicode mode), this will not work properly.
  254. #ifdef VI_ENABLE_8BIT
  255. #define ENABLE_FEATURE_VI_8BIT 1
  256. #define IF_FEATURE_VI_8BIT(...) __VA_ARGS__
  257. #else
  258. #define ENABLE_FEATURE_VI_8BIT 0
  259. #define IF_FEATURE_VI_8BIT(...)
  260. #endif
  261. /*----------------------------------------------------------------*/
  262. #define SET_PTR_TO_GLOBALS(x) do { \
  263. (*(struct globals**)&ptr_to_globals) = (void*)(x); \
  264. barrier(); \
  265. } while (0)
  266. /* "Keycodes" that report an escape sequence.
  267. * We use something which fits into signed char,
  268. * yet doesn't represent any valid Unicode character.
  269. * Also, -1 is reserved for error indication and we don't use it. */
  270. enum {
  271. KEYCODE_UP = -2,
  272. KEYCODE_DOWN = -3,
  273. KEYCODE_RIGHT = -4,
  274. KEYCODE_LEFT = -5,
  275. KEYCODE_HOME = -6,
  276. KEYCODE_END = -7,
  277. KEYCODE_INSERT = -8,
  278. KEYCODE_DELETE = -9,
  279. KEYCODE_PAGEUP = -10,
  280. KEYCODE_PAGEDOWN = -11,
  281. // -12 is reserved for Alt/Ctrl/Shift-TAB
  282. #if 0
  283. KEYCODE_FUN1 = -13,
  284. KEYCODE_FUN2 = -14,
  285. KEYCODE_FUN3 = -15,
  286. KEYCODE_FUN4 = -16,
  287. KEYCODE_FUN5 = -17,
  288. KEYCODE_FUN6 = -18,
  289. KEYCODE_FUN7 = -19,
  290. KEYCODE_FUN8 = -20,
  291. KEYCODE_FUN9 = -21,
  292. KEYCODE_FUN10 = -22,
  293. KEYCODE_FUN11 = -23,
  294. KEYCODE_FUN12 = -24,
  295. #endif
  296. /* Be sure that last defined value is small enough
  297. * to not interfere with Alt/Ctrl/Shift bits.
  298. * So far we do not exceed -31 (0xfff..fffe1),
  299. * which gives us three upper bits in LSB to play with.
  300. */
  301. //KEYCODE_SHIFT_TAB = (-12) & ~0x80,
  302. //KEYCODE_SHIFT_... = KEYCODE_... & ~0x80,
  303. //KEYCODE_CTRL_UP = KEYCODE_UP & ~0x40,
  304. //KEYCODE_CTRL_DOWN = KEYCODE_DOWN & ~0x40,
  305. KEYCODE_CTRL_RIGHT = KEYCODE_RIGHT & ~0x40,
  306. KEYCODE_CTRL_LEFT = KEYCODE_LEFT & ~0x40,
  307. //KEYCODE_ALT_UP = KEYCODE_UP & ~0x20,
  308. //KEYCODE_ALT_DOWN = KEYCODE_DOWN & ~0x20,
  309. KEYCODE_ALT_RIGHT = KEYCODE_RIGHT & ~0x20,
  310. KEYCODE_ALT_LEFT = KEYCODE_LEFT & ~0x20,
  311. KEYCODE_CURSOR_POS = -0x100, /* 0xfff..fff00 */
  312. /* How long is the longest ESC sequence we know?
  313. * We want it big enough to be able to contain
  314. * cursor position sequence "ESC [ 9999 ; 9999 R"
  315. */
  316. KEYCODE_BUFFER_SIZE = 16
  317. };
  318. typedef enum {FALSE = 0, TRUE = !FALSE} bool;
  319. typedef int smallint;
  320. typedef unsigned smalluint;
  321. #ifndef F_OK
  322. #define F_OK 0 /* Tests whether the file exists. */
  323. #define R_OK 4 /* Tests whether the file can be accessed for reading. */
  324. #define W_OK 2 /* Tests whether the file can be accessed for writing. */
  325. #define X_OK 1 /* Tests whether the file can be accessed for execution. */
  326. #endif
  327. #if !defined(__GNUC__)
  328. #define ALIGN1
  329. #define barrier()
  330. #else
  331. #define ALIGN1 __attribute__((aligned(1)))
  332. /* At least gcc 3.4.6 on mipsel system needs optimization barrier */
  333. #define barrier() __asm__ __volatile__("":::"memory")
  334. #endif
  335. #define vi_strtou strtoul
  336. #define fflush_all() /*fflush(NULL)*/ /*RT-Thread don't need to flush STDOUT*/
  337. unsigned char vi_mem_init(void);
  338. void vi_mem_release(void);
  339. void *vi_malloc(rt_size_t size);
  340. void *vi_realloc(void *rmem, rt_size_t newsize);
  341. void vi_free(void *ptr);
  342. void* vi_zalloc(size_t size);
  343. char *vi_strdup(const char *s);
  344. char *vi_strndup(const char *s, size_t n);
  345. int vi_putchar(int c);
  346. int64_t read_key(int fd, char *buffer, int timeout);
  347. char* xasprintf(const char *format, ...);
  348. #ifdef VI_ENABLE_COLON
  349. char* last_char_is(const char *s, int c);
  350. #endif
  351. #ifdef VI_ENABLE_SETOPTS
  352. char* skip_whitespace(const char *s);
  353. char* skip_non_whitespace(const char *s);
  354. #endif
  355. int index_in_strings(const char *strings, const char *key);
  356. int safe_read(int fd, void *buf, size_t count);
  357. int safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout);
  358. ssize_t full_write(int fd, const void *buf, size_t len);
  359. ssize_t full_read(int fd, void *buf, size_t len);
  360. #ifdef RT_USING_POSIX_TERMIOS
  361. #include <termios.h>
  362. #define TERMIOS_CLEAR_ISIG (1 << 0)
  363. #define TERMIOS_RAW_CRNL_INPUT (1 << 1)
  364. #define TERMIOS_RAW_CRNL_OUTPUT (1 << 2)
  365. #define TERMIOS_RAW_CRNL (TERMIOS_RAW_CRNL_INPUT|TERMIOS_RAW_CRNL_OUTPUT)
  366. #define TERMIOS_RAW_INPUT (1 << 3)
  367. int tcsetattr_stdin_TCSANOW(const struct termios *tp);
  368. int get_terminal_width_height(int fd, unsigned *width, unsigned *height);
  369. int set_termios_to_raw(int fd, struct termios *oldterm, int flags);
  370. #endif
  371. //config: TODO for RT-Thread
  372. //config:config FEATURE_VI_USE_SIGNALS
  373. //config: bool "Catch signals"
  374. //config: default y
  375. //config: depends on VI
  376. //config: help
  377. //config: Selecting this option will make busybox vi signal aware. This will
  378. //config: make busybox vi support SIGWINCH to deal with Window Changes, catch
  379. //config: Ctrl-Z and Ctrl-C and alarms.
  380. #endif