1#ifndef _WIN32
2/*
3 * You can find the latest source code at:
4 *
5 * http://github.com/ericcurtin/linenoise.cpp
6 *
7 * Does a number of crazy assumptions that happen to be true in 99.9999% of
8 * the 2010 UNIX computers around.
9 *
10 * ------------------------------------------------------------------------
11 *
12 * Copyright (c) 2010-2023, Salvatore Sanfilippo <antirez at gmail dot com>
13 * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
14 * Copyright (c) 2025, Eric Curtin <ericcurtin17 at gmail dot com>
15 *
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met:
21 *
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * ------------------------------------------------------------------------
42 *
43 * References:
44 * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
45 * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
46 *
47 * Todo list:
48 * - Filter bogus Ctrl+<char> combinations.
49 * - Win32 support
50 *
51 * Bloat:
52 * - History search like Ctrl+r in readline?
53 *
54 * List of escape sequences used by this program, we do everything just
55 * with three sequences. In order to be so cheap we may have some
56 * flickering effect with some slow terminal, but the lesser sequences
57 * the more compatible.
58 *
59 * EL (Erase Line)
60 * Sequence: ESC [ n K
61 * Effect: if n is 0 or missing, clear from cursor to end of line
62 * Effect: if n is 1, clear from beginning of line to cursor
63 * Effect: if n is 2, clear entire line
64 *
65 * CUF (CUrsor Forward)
66 * Sequence: ESC [ n C
67 * Effect: moves cursor forward n chars
68 *
69 * CUB (CUrsor Backward)
70 * Sequence: ESC [ n D
71 * Effect: moves cursor backward n chars
72 *
73 * The following is used to get the terminal width if getting
74 * the width with the TIOCGWINSZ ioctl fails
75 *
76 * DSR (Device Status Report)
77 * Sequence: ESC [ 6 n
78 * Effect: reports the current cursor position as ESC [ n ; m R
79 * where n is the row and m is the column
80 *
81 * When multi line mode is enabled, we also use an additional escape
82 * sequence. However multi line editing is disabled by default.
83 *
84 * CUU (Cursor Up)
85 * Sequence: ESC [ n A
86 * Effect: moves cursor up of n chars.
87 *
88 * CUD (Cursor Down)
89 * Sequence: ESC [ n B
90 * Effect: moves cursor down of n chars.
91 *
92 * When linenoiseClearScreen() is called, two additional escape sequences
93 * are used in order to clear the screen and position the cursor at home
94 * position.
95 *
96 * CUP (Cursor position)
97 * Sequence: ESC [ H
98 * Effect: moves the cursor to upper left corner
99 *
100 * ED (Erase display)
101 * Sequence: ESC [ 2 J
102 * Effect: clear the whole screen
103 *
104 */
105
106# include "linenoise.h"
107
108# include <ctype.h>
109# include <errno.h>
110# include <poll.h>
111# include <stdio.h>
112# include <string.h>
113# include <sys/file.h>
114# include <sys/ioctl.h>
115# include <sys/stat.h>
116# include <sys/types.h>
117# include <termios.h>
118# include <unistd.h>
119
120# include <memory>
121# include <string>
122# include <vector>
123
124# define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
125# define LINENOISE_MAX_LINE 4096
126static std::vector<const char *> unsupported_term = { "dumb", "cons25", "emacs" };
127static linenoiseCompletionCallback *completionCallback = NULL;
128static linenoiseHintsCallback *hintsCallback = NULL;
129static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
130static char *linenoiseNoTTY(void);
131static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseCompletions *lc, int flags);
132static void refreshLineWithFlags(struct linenoiseState *l, int flags);
133
134static struct termios orig_termios; /* In order to restore at exit.*/
135static int maskmode = 0; /* Show "***" instead of input. For passwords. */
136static int rawmode = 0; /* For atexit() function to check if restore is needed*/
137static int mlmode = 0; /* Multi line mode. Default is single line. */
138static int atexit_registered = 0; /* Register atexit just 1 time. */
139static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
140static int history_len = 0;
141static char **history = NULL;
142
143enum KEY_ACTION{
144 KEY_NULL = 0, /* NULL */
145 CTRL_A = 1, /* Ctrl+a */
146 CTRL_B = 2, /* Ctrl-b */
147 CTRL_C = 3, /* Ctrl-c */
148 CTRL_D = 4, /* Ctrl-d */
149 CTRL_E = 5, /* Ctrl-e */
150 CTRL_F = 6, /* Ctrl-f */
151 CTRL_H = 8, /* Ctrl-h */
152 TAB = 9, /* Tab */
153 CTRL_K = 11, /* Ctrl+k */
154 CTRL_L = 12, /* Ctrl+l */
155 ENTER = 13, /* Enter */
156 CTRL_N = 14, /* Ctrl-n */
157 CTRL_P = 16, /* Ctrl-p */
158 CTRL_T = 20, /* Ctrl-t */
159 CTRL_U = 21, /* Ctrl+u */
160 CTRL_W = 23, /* Ctrl+w */
161 ESC = 27, /* Escape */
162 BACKSPACE = 127 /* Backspace */
163};
164
165static void linenoiseAtExit(void);
166int linenoiseHistoryAdd(const char *line);
167#define REFRESH_CLEAN (1<<0) // Clean the old prompt from the screen
168#define REFRESH_WRITE (1<<1) // Rewrite the prompt on the screen.
169#define REFRESH_ALL (REFRESH_CLEAN|REFRESH_WRITE) // Do both.
170static void refreshLine(struct linenoiseState *l);
171
172class File {
173 public:
174 FILE * file = nullptr;
175
176 FILE * open(const std::string & filename, const char * mode) {
177 file = fopen(filename: filename.c_str(), modes: mode);
178
179 return file;
180 }
181
182 int lock() {
183 if (file) {
184 fd = fileno(stream: file);
185 if (flock(fd: fd, LOCK_EX | LOCK_NB) != 0) {
186 fd = -1;
187
188 return 1;
189 }
190 }
191
192 return 0;
193 }
194
195 ~File() {
196 if (fd >= 0) {
197 flock(fd: fd, LOCK_UN);
198 }
199
200 if (file) {
201 fclose(stream: file);
202 }
203 }
204
205 private:
206 int fd = -1;
207};
208
209#if 0
210/* Debugging function. */
211__attribute__((format(printf, 1, 2)))
212static void lndebug(const char *fmt, ...) {
213 static File file;
214 if (file.file == nullptr) {
215 file.open("/tmp/lndebug.txt", "a");
216 }
217
218 if (file.file != nullptr) {
219 va_list args;
220 va_start(args, fmt);
221 vfprintf(file.file, fmt, args);
222 va_end(args);
223 fflush(file.file);
224 }
225}
226#endif
227
228/* ========================== Encoding functions ============================= */
229
230/* Get length of previous UTF8 codepoint */
231static size_t prevUtf8CodePointLen(const char * buf, int pos) {
232 int end = pos--;
233 while (pos >= 0 && ((unsigned char) buf[pos] & 0xC0) == 0x80) {
234 pos--;
235 }
236 return end - pos;
237}
238
239/* Convert UTF8 to Unicode code point */
240static size_t utf8BytesToCodePoint(const char * buf, size_t len, int * cp) {
241 if (len) {
242 unsigned char byte = buf[0];
243 if ((byte & 0x80) == 0) {
244 *cp = byte;
245 return 1;
246 } else if ((byte & 0xE0) == 0xC0) {
247 if (len >= 2) {
248 *cp = (((unsigned long) (buf[0] & 0x1F)) << 6) | ((unsigned long) (buf[1] & 0x3F));
249 return 2;
250 }
251 } else if ((byte & 0xF0) == 0xE0) {
252 if (len >= 3) {
253 *cp = (((unsigned long) (buf[0] & 0x0F)) << 12) | (((unsigned long) (buf[1] & 0x3F)) << 6) |
254 ((unsigned long) (buf[2] & 0x3F));
255 return 3;
256 }
257 } else if ((byte & 0xF8) == 0xF0) {
258 if (len >= 4) {
259 *cp = (((unsigned long) (buf[0] & 0x07)) << 18) | (((unsigned long) (buf[1] & 0x3F)) << 12) |
260 (((unsigned long) (buf[2] & 0x3F)) << 6) | ((unsigned long) (buf[3] & 0x3F));
261 return 4;
262 }
263 }
264 }
265 return 0;
266}
267
268/* Check if the code is a wide character */
269static const unsigned long wideCharTable[][2] = {
270 /* BEGIN: WIDE CHAR TABLE */
271 { 0x1100, 0x115F },
272 { 0x231A, 0x231B },
273 { 0x2329, 0x232A },
274 { 0x23E9, 0x23EC },
275 { 0x23F0, 0x23F0 },
276 { 0x23F3, 0x23F3 },
277 { 0x25FD, 0x25FE },
278 { 0x2614, 0x2615 },
279 { 0x2630, 0x2637 },
280 { 0x2648, 0x2653 },
281 { 0x267F, 0x267F },
282 { 0x268A, 0x268F },
283 { 0x2693, 0x2693 },
284 { 0x26A1, 0x26A1 },
285 { 0x26AA, 0x26AB },
286 { 0x26BD, 0x26BE },
287 { 0x26C4, 0x26C5 },
288 { 0x26CE, 0x26CE },
289 { 0x26D4, 0x26D4 },
290 { 0x26EA, 0x26EA },
291 { 0x26F2, 0x26F3 },
292 { 0x26F5, 0x26F5 },
293 { 0x26FA, 0x26FA },
294 { 0x26FD, 0x26FD },
295 { 0x2705, 0x2705 },
296 { 0x270A, 0x270B },
297 { 0x2728, 0x2728 },
298 { 0x274C, 0x274C },
299 { 0x274E, 0x274E },
300 { 0x2753, 0x2755 },
301 { 0x2757, 0x2757 },
302 { 0x2795, 0x2797 },
303 { 0x27B0, 0x27B0 },
304 { 0x27BF, 0x27BF },
305 { 0x2B1B, 0x2B1C },
306 { 0x2B50, 0x2B50 },
307 { 0x2B55, 0x2B55 },
308 { 0x2E80, 0x2E99 },
309 { 0x2E9B, 0x2EF3 },
310 { 0x2F00, 0x2FD5 },
311 { 0x2FF0, 0x303E },
312 { 0x3041, 0x3096 },
313 { 0x3099, 0x30FF },
314 { 0x3105, 0x312F },
315 { 0x3131, 0x318E },
316 { 0x3190, 0x31E5 },
317 { 0x31EF, 0x321E },
318 { 0x3220, 0x3247 },
319 { 0x3250, 0xA48C },
320 { 0xA490, 0xA4C6 },
321 { 0xA960, 0xA97C },
322 { 0xAC00, 0xD7A3 },
323 { 0xF900, 0xFAFF },
324 { 0xFE10, 0xFE19 },
325 { 0xFE30, 0xFE52 },
326 { 0xFE54, 0xFE66 },
327 { 0xFE68, 0xFE6B },
328 { 0xFF01, 0xFF60 },
329 { 0xFFE0, 0xFFE6 },
330 { 0x16FE0, 0x16FE4 },
331 { 0x16FF0, 0x16FF1 },
332 { 0x17000, 0x187F7 },
333 { 0x18800, 0x18CD5 },
334 { 0x18CFF, 0x18D08 },
335 { 0x1AFF0, 0x1AFF3 },
336 { 0x1AFF5, 0x1AFFB },
337 { 0x1AFFD, 0x1AFFE },
338 { 0x1B000, 0x1B122 },
339 { 0x1B132, 0x1B132 },
340 { 0x1B150, 0x1B152 },
341 { 0x1B155, 0x1B155 },
342 { 0x1B164, 0x1B167 },
343 { 0x1B170, 0x1B2FB },
344 { 0x1D300, 0x1D356 },
345 { 0x1D360, 0x1D376 },
346 { 0x1F004, 0x1F004 },
347 { 0x1F0CF, 0x1F0CF },
348 { 0x1F18E, 0x1F18E },
349 { 0x1F191, 0x1F19A },
350 { 0x1F200, 0x1F202 },
351 { 0x1F210, 0x1F23B },
352 { 0x1F240, 0x1F248 },
353 { 0x1F250, 0x1F251 },
354 { 0x1F260, 0x1F265 },
355 { 0x1F300, 0x1F320 },
356 { 0x1F32D, 0x1F335 },
357 { 0x1F337, 0x1F37C },
358 { 0x1F37E, 0x1F393 },
359 { 0x1F3A0, 0x1F3CA },
360 { 0x1F3CF, 0x1F3D3 },
361 { 0x1F3E0, 0x1F3F0 },
362 { 0x1F3F4, 0x1F3F4 },
363 { 0x1F3F8, 0x1F43E },
364 { 0x1F440, 0x1F440 },
365 { 0x1F442, 0x1F4FC },
366 { 0x1F4FF, 0x1F53D },
367 { 0x1F54B, 0x1F54E },
368 { 0x1F550, 0x1F567 },
369 { 0x1F57A, 0x1F57A },
370 { 0x1F595, 0x1F596 },
371 { 0x1F5A4, 0x1F5A4 },
372 { 0x1F5FB, 0x1F64F },
373 { 0x1F680, 0x1F6C5 },
374 { 0x1F6CC, 0x1F6CC },
375 { 0x1F6D0, 0x1F6D2 },
376 { 0x1F6D5, 0x1F6D7 },
377 { 0x1F6DC, 0x1F6DF },
378 { 0x1F6EB, 0x1F6EC },
379 { 0x1F6F4, 0x1F6FC },
380 { 0x1F7E0, 0x1F7EB },
381 { 0x1F7F0, 0x1F7F0 },
382 { 0x1F90C, 0x1F93A },
383 { 0x1F93C, 0x1F945 },
384 { 0x1F947, 0x1F9FF },
385 { 0x1FA70, 0x1FA7C },
386 { 0x1FA80, 0x1FA89 },
387 { 0x1FA8F, 0x1FAC6 },
388 { 0x1FACE, 0x1FADC },
389 { 0x1FADF, 0x1FAE9 },
390 { 0x1FAF0, 0x1FAF8 },
391 { 0x20000, 0x2FFFD },
392 { 0x30000, 0x3FFFD }
393 /* END: WIDE CHAR TABLE */
394};
395
396static const size_t wideCharTableSize = sizeof(wideCharTable) / sizeof(wideCharTable[0]);
397
398static bool isWideChar(unsigned long cp) {
399 for (size_t i = 0; i < wideCharTableSize; i++) {
400 auto first_code = wideCharTable[i][0];
401 auto last_code = wideCharTable[i][1];
402 if (first_code > cp) {
403 return false;
404 }
405 if (first_code <= cp && cp <= last_code) {
406 return true;
407 }
408 }
409 return false;
410}
411
412/* Check if the code is a combining character */
413static const unsigned long combiningCharTable[] = {
414 /* BEGIN: COMBINING CHAR TABLE */
415 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C,
416 0x030D, 0x030E, 0x030F, 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, 0x0318, 0x0319,
417 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326,
418 0x0327, 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, 0x0330, 0x0331, 0x0332, 0x0333,
419 0x0334, 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, 0x0340,
420 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D,
421 0x034E, 0x034F, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035A,
422 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
423 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
424 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D,
425 0x059E, 0x059F, 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, 0x05A8, 0x05A9, 0x05AA,
426 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
427 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BF, 0x05C1, 0x05C2, 0x05C4, 0x05C5, 0x05C7, 0x0610,
428 0x0611, 0x0612, 0x0613, 0x0614, 0x0615, 0x0616, 0x0617, 0x0618, 0x0619, 0x061A, 0x064B, 0x064C, 0x064D,
429 0x064E, 0x064F, 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0656, 0x0657, 0x0658, 0x0659, 0x065A,
430 0x065B, 0x065C, 0x065D, 0x065E, 0x065F, 0x0670, 0x06D6, 0x06D7, 0x06D8, 0x06D9, 0x06DA, 0x06DB, 0x06DC,
431 0x06DF, 0x06E0, 0x06E1, 0x06E2, 0x06E3, 0x06E4, 0x06E7, 0x06E8, 0x06EA, 0x06EB, 0x06EC, 0x06ED, 0x0711,
432 0x0730, 0x0731, 0x0732, 0x0733, 0x0734, 0x0735, 0x0736, 0x0737, 0x0738, 0x0739, 0x073A, 0x073B, 0x073C,
433 0x073D, 0x073E, 0x073F, 0x0740, 0x0741, 0x0742, 0x0743, 0x0744, 0x0745, 0x0746, 0x0747, 0x0748, 0x0749,
434 0x074A, 0x07A6, 0x07A7, 0x07A8, 0x07A9, 0x07AA, 0x07AB, 0x07AC, 0x07AD, 0x07AE, 0x07AF, 0x07B0, 0x07EB,
435 0x07EC, 0x07ED, 0x07EE, 0x07EF, 0x07F0, 0x07F1, 0x07F2, 0x07F3, 0x07FD, 0x0816, 0x0817, 0x0818, 0x0819,
436 0x081B, 0x081C, 0x081D, 0x081E, 0x081F, 0x0820, 0x0821, 0x0822, 0x0823, 0x0825, 0x0826, 0x0827, 0x0829,
437 0x082A, 0x082B, 0x082C, 0x082D, 0x0859, 0x085A, 0x085B, 0x0897, 0x0898, 0x0899, 0x089A, 0x089B, 0x089C,
438 0x089D, 0x089E, 0x089F, 0x08CA, 0x08CB, 0x08CC, 0x08CD, 0x08CE, 0x08CF, 0x08D0, 0x08D1, 0x08D2, 0x08D3,
439 0x08D4, 0x08D5, 0x08D6, 0x08D7, 0x08D8, 0x08D9, 0x08DA, 0x08DB, 0x08DC, 0x08DD, 0x08DE, 0x08DF, 0x08E0,
440 0x08E1, 0x08E3, 0x08E4, 0x08E5, 0x08E6, 0x08E7, 0x08E8, 0x08E9, 0x08EA, 0x08EB, 0x08EC, 0x08ED, 0x08EE,
441 0x08EF, 0x08F0, 0x08F1, 0x08F2, 0x08F3, 0x08F4, 0x08F5, 0x08F6, 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB,
442 0x08FC, 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, 0x093A, 0x093C, 0x0941, 0x0942, 0x0943, 0x0944,
443 0x0945, 0x0946, 0x0947, 0x0948, 0x094D, 0x0951, 0x0952, 0x0953, 0x0954, 0x0955, 0x0956, 0x0957, 0x0962,
444 0x0963, 0x0981, 0x09BC, 0x09C1, 0x09C2, 0x09C3, 0x09C4, 0x09CD, 0x09E2, 0x09E3, 0x09FE, 0x0A01, 0x0A02,
445 0x0A3C, 0x0A41, 0x0A42, 0x0A47, 0x0A48, 0x0A4B, 0x0A4C, 0x0A4D, 0x0A51, 0x0A70, 0x0A71, 0x0A75, 0x0A81,
446 0x0A82, 0x0ABC, 0x0AC1, 0x0AC2, 0x0AC3, 0x0AC4, 0x0AC5, 0x0AC7, 0x0AC8, 0x0ACD, 0x0AE2, 0x0AE3, 0x0AFA,
447 0x0AFB, 0x0AFC, 0x0AFD, 0x0AFE, 0x0AFF, 0x0B01, 0x0B3C, 0x0B3F, 0x0B41, 0x0B42, 0x0B43, 0x0B44, 0x0B4D,
448 0x0B55, 0x0B56, 0x0B62, 0x0B63, 0x0B82, 0x0BC0, 0x0BCD, 0x0C00, 0x0C04, 0x0C3C, 0x0C3E, 0x0C3F, 0x0C40,
449 0x0C46, 0x0C47, 0x0C48, 0x0C4A, 0x0C4B, 0x0C4C, 0x0C4D, 0x0C55, 0x0C56, 0x0C62, 0x0C63, 0x0C81, 0x0CBC,
450 0x0CBF, 0x0CC6, 0x0CCC, 0x0CCD, 0x0CE2, 0x0CE3, 0x0D00, 0x0D01, 0x0D3B, 0x0D3C, 0x0D41, 0x0D42, 0x0D43,
451 0x0D44, 0x0D4D, 0x0D62, 0x0D63, 0x0D81, 0x0DCA, 0x0DD2, 0x0DD3, 0x0DD4, 0x0DD6, 0x0E31, 0x0E34, 0x0E35,
452 0x0E36, 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E,
453 0x0EB1, 0x0EB4, 0x0EB5, 0x0EB6, 0x0EB7, 0x0EB8, 0x0EB9, 0x0EBA, 0x0EBB, 0x0EBC, 0x0EC8, 0x0EC9, 0x0ECA,
454 0x0ECB, 0x0ECC, 0x0ECD, 0x0ECE, 0x0F18, 0x0F19, 0x0F35, 0x0F37, 0x0F39, 0x0F71, 0x0F72, 0x0F73, 0x0F74,
455 0x0F75, 0x0F76, 0x0F77, 0x0F78, 0x0F79, 0x0F7A, 0x0F7B, 0x0F7C, 0x0F7D, 0x0F7E, 0x0F80, 0x0F81, 0x0F82,
456 0x0F83, 0x0F84, 0x0F86, 0x0F87, 0x0F8D, 0x0F8E, 0x0F8F, 0x0F90, 0x0F91, 0x0F92, 0x0F93, 0x0F94, 0x0F95,
457 0x0F96, 0x0F97, 0x0F99, 0x0F9A, 0x0F9B, 0x0F9C, 0x0F9D, 0x0F9E, 0x0F9F, 0x0FA0, 0x0FA1, 0x0FA2, 0x0FA3,
458 0x0FA4, 0x0FA5, 0x0FA6, 0x0FA7, 0x0FA8, 0x0FA9, 0x0FAA, 0x0FAB, 0x0FAC, 0x0FAD, 0x0FAE, 0x0FAF, 0x0FB0,
459 0x0FB1, 0x0FB2, 0x0FB3, 0x0FB4, 0x0FB5, 0x0FB6, 0x0FB7, 0x0FB8, 0x0FB9, 0x0FBA, 0x0FBB, 0x0FBC, 0x0FC6,
460 0x102D, 0x102E, 0x102F, 0x1030, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, 0x1039, 0x103A, 0x103D,
461 0x103E, 0x1058, 0x1059, 0x105E, 0x105F, 0x1060, 0x1071, 0x1072, 0x1073, 0x1074, 0x1082, 0x1085, 0x1086,
462 0x108D, 0x109D, 0x135D, 0x135E, 0x135F, 0x1712, 0x1713, 0x1714, 0x1732, 0x1733, 0x1752, 0x1753, 0x1772,
463 0x1773, 0x17B4, 0x17B5, 0x17B7, 0x17B8, 0x17B9, 0x17BA, 0x17BB, 0x17BC, 0x17BD, 0x17C6, 0x17C9, 0x17CA,
464 0x17CB, 0x17CC, 0x17CD, 0x17CE, 0x17CF, 0x17D0, 0x17D1, 0x17D2, 0x17D3, 0x17DD, 0x180B, 0x180C, 0x180D,
465 0x180F, 0x1885, 0x1886, 0x18A9, 0x1920, 0x1921, 0x1922, 0x1927, 0x1928, 0x1932, 0x1939, 0x193A, 0x193B,
466 0x1A17, 0x1A18, 0x1A1B, 0x1A56, 0x1A58, 0x1A59, 0x1A5A, 0x1A5B, 0x1A5C, 0x1A5D, 0x1A5E, 0x1A60, 0x1A62,
467 0x1A65, 0x1A66, 0x1A67, 0x1A68, 0x1A69, 0x1A6A, 0x1A6B, 0x1A6C, 0x1A73, 0x1A74, 0x1A75, 0x1A76, 0x1A77,
468 0x1A78, 0x1A79, 0x1A7A, 0x1A7B, 0x1A7C, 0x1A7F, 0x1AB0, 0x1AB1, 0x1AB2, 0x1AB3, 0x1AB4, 0x1AB5, 0x1AB6,
469 0x1AB7, 0x1AB8, 0x1AB9, 0x1ABA, 0x1ABB, 0x1ABC, 0x1ABD, 0x1ABF, 0x1AC0, 0x1AC1, 0x1AC2, 0x1AC3, 0x1AC4,
470 0x1AC5, 0x1AC6, 0x1AC7, 0x1AC8, 0x1AC9, 0x1ACA, 0x1ACB, 0x1ACC, 0x1ACD, 0x1ACE, 0x1B00, 0x1B01, 0x1B02,
471 0x1B03, 0x1B34, 0x1B36, 0x1B37, 0x1B38, 0x1B39, 0x1B3A, 0x1B3C, 0x1B42, 0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E,
472 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73, 0x1B80, 0x1B81, 0x1BA2, 0x1BA3, 0x1BA4, 0x1BA5, 0x1BA8, 0x1BA9,
473 0x1BAB, 0x1BAC, 0x1BAD, 0x1BE6, 0x1BE8, 0x1BE9, 0x1BED, 0x1BEF, 0x1BF0, 0x1BF1, 0x1C2C, 0x1C2D, 0x1C2E,
474 0x1C2F, 0x1C30, 0x1C31, 0x1C32, 0x1C33, 0x1C36, 0x1C37, 0x1CD0, 0x1CD1, 0x1CD2, 0x1CD4, 0x1CD5, 0x1CD6,
475 0x1CD7, 0x1CD8, 0x1CD9, 0x1CDA, 0x1CDB, 0x1CDC, 0x1CDD, 0x1CDE, 0x1CDF, 0x1CE0, 0x1CE2, 0x1CE3, 0x1CE4,
476 0x1CE5, 0x1CE6, 0x1CE7, 0x1CE8, 0x1CED, 0x1CF4, 0x1CF8, 0x1CF9, 0x1DC0, 0x1DC1, 0x1DC2, 0x1DC3, 0x1DC4,
477 0x1DC5, 0x1DC6, 0x1DC7, 0x1DC8, 0x1DC9, 0x1DCA, 0x1DCB, 0x1DCC, 0x1DCD, 0x1DCE, 0x1DCF, 0x1DD0, 0x1DD1,
478 0x1DD2, 0x1DD3, 0x1DD4, 0x1DD5, 0x1DD6, 0x1DD7, 0x1DD8, 0x1DD9, 0x1DDA, 0x1DDB, 0x1DDC, 0x1DDD, 0x1DDE,
479 0x1DDF, 0x1DE0, 0x1DE1, 0x1DE2, 0x1DE3, 0x1DE4, 0x1DE5, 0x1DE6, 0x1DE7, 0x1DE8, 0x1DE9, 0x1DEA, 0x1DEB,
480 0x1DEC, 0x1DED, 0x1DEE, 0x1DEF, 0x1DF0, 0x1DF1, 0x1DF2, 0x1DF3, 0x1DF4, 0x1DF5, 0x1DF6, 0x1DF7, 0x1DF8,
481 0x1DF9, 0x1DFA, 0x1DFB, 0x1DFC, 0x1DFD, 0x1DFE, 0x1DFF, 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5,
482 0x20D6, 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20E1, 0x20E5, 0x20E6, 0x20E7, 0x20E8, 0x20E9,
483 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF, 0x20F0, 0x2CEF, 0x2CF0, 0x2CF1, 0x2D7F, 0x2DE0, 0x2DE1,
484 0x2DE2, 0x2DE3, 0x2DE4, 0x2DE5, 0x2DE6, 0x2DE7, 0x2DE8, 0x2DE9, 0x2DEA, 0x2DEB, 0x2DEC, 0x2DED, 0x2DEE,
485 0x2DEF, 0x2DF0, 0x2DF1, 0x2DF2, 0x2DF3, 0x2DF4, 0x2DF5, 0x2DF6, 0x2DF7, 0x2DF8, 0x2DF9, 0x2DFA, 0x2DFB,
486 0x2DFC, 0x2DFD, 0x2DFE, 0x2DFF, 0x302A, 0x302B, 0x302C, 0x302D, 0x3099, 0x309A, 0xA66F, 0xA674, 0xA675,
487 0xA676, 0xA677, 0xA678, 0xA679, 0xA67A, 0xA67B, 0xA67C, 0xA67D, 0xA69E, 0xA69F, 0xA6F0, 0xA6F1, 0xA802,
488 0xA806, 0xA80B, 0xA825, 0xA826, 0xA82C, 0xA8C4, 0xA8C5, 0xA8E0, 0xA8E1, 0xA8E2, 0xA8E3, 0xA8E4, 0xA8E5,
489 0xA8E6, 0xA8E7, 0xA8E8, 0xA8E9, 0xA8EA, 0xA8EB, 0xA8EC, 0xA8ED, 0xA8EE, 0xA8EF, 0xA8F0, 0xA8F1, 0xA8FF,
490 0xA926, 0xA927, 0xA928, 0xA929, 0xA92A, 0xA92B, 0xA92C, 0xA92D, 0xA947, 0xA948, 0xA949, 0xA94A, 0xA94B,
491 0xA94C, 0xA94D, 0xA94E, 0xA94F, 0xA950, 0xA951, 0xA980, 0xA981, 0xA982, 0xA9B3, 0xA9B6, 0xA9B7, 0xA9B8,
492 0xA9B9, 0xA9BC, 0xA9BD, 0xA9E5, 0xAA29, 0xAA2A, 0xAA2B, 0xAA2C, 0xAA2D, 0xAA2E, 0xAA31, 0xAA32, 0xAA35,
493 0xAA36, 0xAA43, 0xAA4C, 0xAA7C, 0xAAB0, 0xAAB2, 0xAAB3, 0xAAB4, 0xAAB7, 0xAAB8, 0xAABE, 0xAABF, 0xAAC1,
494 0xAAEC, 0xAAED, 0xAAF6, 0xABE5, 0xABE8, 0xABED, 0xFB1E, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05,
495 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFE20, 0xFE21, 0xFE22,
496 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27, 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F,
497 0x101FD, 0x102E0, 0x10376, 0x10377, 0x10378, 0x10379, 0x1037A, 0x10A01, 0x10A02, 0x10A03, 0x10A05, 0x10A06, 0x10A0C,
498 0x10A0D, 0x10A0E, 0x10A0F, 0x10A38, 0x10A39, 0x10A3A, 0x10A3F, 0x10AE5, 0x10AE6, 0x10D24, 0x10D25, 0x10D26, 0x10D27,
499 0x10D69, 0x10D6A, 0x10D6B, 0x10D6C, 0x10D6D, 0x10EAB, 0x10EAC, 0x10EFC, 0x10EFD, 0x10EFE, 0x10EFF, 0x10F46, 0x10F47,
500 0x10F48, 0x10F49, 0x10F4A, 0x10F4B, 0x10F4C, 0x10F4D, 0x10F4E, 0x10F4F, 0x10F50, 0x10F82, 0x10F83, 0x10F84, 0x10F85,
501 0x11001, 0x11038, 0x11039, 0x1103A, 0x1103B, 0x1103C, 0x1103D, 0x1103E, 0x1103F, 0x11040, 0x11041, 0x11042, 0x11043,
502 0x11044, 0x11045, 0x11046, 0x11070, 0x11073, 0x11074, 0x1107F, 0x11080, 0x11081, 0x110B3, 0x110B4, 0x110B5, 0x110B6,
503 0x110B9, 0x110BA, 0x110C2, 0x11100, 0x11101, 0x11102, 0x11127, 0x11128, 0x11129, 0x1112A, 0x1112B, 0x1112D, 0x1112E,
504 0x1112F, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11173, 0x11180, 0x11181, 0x111B6, 0x111B7, 0x111B8, 0x111B9,
505 0x111BA, 0x111BB, 0x111BC, 0x111BD, 0x111BE, 0x111C9, 0x111CA, 0x111CB, 0x111CC, 0x111CF, 0x1122F, 0x11230, 0x11231,
506 0x11234, 0x11236, 0x11237, 0x1123E, 0x11241, 0x112DF, 0x112E3, 0x112E4, 0x112E5, 0x112E6, 0x112E7, 0x112E8, 0x112E9,
507 0x112EA, 0x11300, 0x11301, 0x1133B, 0x1133C, 0x11340, 0x11366, 0x11367, 0x11368, 0x11369, 0x1136A, 0x1136B, 0x1136C,
508 0x11370, 0x11371, 0x11372, 0x11373, 0x11374, 0x113BB, 0x113BC, 0x113BD, 0x113BE, 0x113BF, 0x113C0, 0x113CE, 0x113D0,
509 0x113D2, 0x113E1, 0x113E2, 0x11438, 0x11439, 0x1143A, 0x1143B, 0x1143C, 0x1143D, 0x1143E, 0x1143F, 0x11442, 0x11443,
510 0x11444, 0x11446, 0x1145E, 0x114B3, 0x114B4, 0x114B5, 0x114B6, 0x114B7, 0x114B8, 0x114BA, 0x114BF, 0x114C0, 0x114C2,
511 0x114C3, 0x115B2, 0x115B3, 0x115B4, 0x115B5, 0x115BC, 0x115BD, 0x115BF, 0x115C0, 0x115DC, 0x115DD, 0x11633, 0x11634,
512 0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163A, 0x1163D, 0x1163F, 0x11640, 0x116AB, 0x116AD, 0x116B0, 0x116B1,
513 0x116B2, 0x116B3, 0x116B4, 0x116B5, 0x116B7, 0x1171D, 0x1171F, 0x11722, 0x11723, 0x11724, 0x11725, 0x11727, 0x11728,
514 0x11729, 0x1172A, 0x1172B, 0x1182F, 0x11830, 0x11831, 0x11832, 0x11833, 0x11834, 0x11835, 0x11836, 0x11837, 0x11839,
515 0x1183A, 0x1193B, 0x1193C, 0x1193E, 0x11943, 0x119D4, 0x119D5, 0x119D6, 0x119D7, 0x119DA, 0x119DB, 0x119E0, 0x11A01,
516 0x11A02, 0x11A03, 0x11A04, 0x11A05, 0x11A06, 0x11A07, 0x11A08, 0x11A09, 0x11A0A, 0x11A33, 0x11A34, 0x11A35, 0x11A36,
517 0x11A37, 0x11A38, 0x11A3B, 0x11A3C, 0x11A3D, 0x11A3E, 0x11A47, 0x11A51, 0x11A52, 0x11A53, 0x11A54, 0x11A55, 0x11A56,
518 0x11A59, 0x11A5A, 0x11A5B, 0x11A8A, 0x11A8B, 0x11A8C, 0x11A8D, 0x11A8E, 0x11A8F, 0x11A90, 0x11A91, 0x11A92, 0x11A93,
519 0x11A94, 0x11A95, 0x11A96, 0x11A98, 0x11A99, 0x11C30, 0x11C31, 0x11C32, 0x11C33, 0x11C34, 0x11C35, 0x11C36, 0x11C38,
520 0x11C39, 0x11C3A, 0x11C3B, 0x11C3C, 0x11C3D, 0x11C3F, 0x11C92, 0x11C93, 0x11C94, 0x11C95, 0x11C96, 0x11C97, 0x11C98,
521 0x11C99, 0x11C9A, 0x11C9B, 0x11C9C, 0x11C9D, 0x11C9E, 0x11C9F, 0x11CA0, 0x11CA1, 0x11CA2, 0x11CA3, 0x11CA4, 0x11CA5,
522 0x11CA6, 0x11CA7, 0x11CAA, 0x11CAB, 0x11CAC, 0x11CAD, 0x11CAE, 0x11CAF, 0x11CB0, 0x11CB2, 0x11CB3, 0x11CB5, 0x11CB6,
523 0x11D31, 0x11D32, 0x11D33, 0x11D34, 0x11D35, 0x11D36, 0x11D3A, 0x11D3C, 0x11D3D, 0x11D3F, 0x11D40, 0x11D41, 0x11D42,
524 0x11D43, 0x11D44, 0x11D45, 0x11D47, 0x11D90, 0x11D91, 0x11D95, 0x11D97, 0x11EF3, 0x11EF4, 0x11F00, 0x11F01, 0x11F36,
525 0x11F37, 0x11F38, 0x11F39, 0x11F3A, 0x11F40, 0x11F42, 0x11F5A, 0x13440, 0x13447, 0x13448, 0x13449, 0x1344A, 0x1344B,
526 0x1344C, 0x1344D, 0x1344E, 0x1344F, 0x13450, 0x13451, 0x13452, 0x13453, 0x13454, 0x13455, 0x1611E, 0x1611F, 0x16120,
527 0x16121, 0x16122, 0x16123, 0x16124, 0x16125, 0x16126, 0x16127, 0x16128, 0x16129, 0x1612D, 0x1612E, 0x1612F, 0x16AF0,
528 0x16AF1, 0x16AF2, 0x16AF3, 0x16AF4, 0x16B30, 0x16B31, 0x16B32, 0x16B33, 0x16B34, 0x16B35, 0x16B36, 0x16F4F, 0x16F8F,
529 0x16F90, 0x16F91, 0x16F92, 0x16FE4, 0x1BC9D, 0x1BC9E, 0x1CF00, 0x1CF01, 0x1CF02, 0x1CF03, 0x1CF04, 0x1CF05, 0x1CF06,
530 0x1CF07, 0x1CF08, 0x1CF09, 0x1CF0A, 0x1CF0B, 0x1CF0C, 0x1CF0D, 0x1CF0E, 0x1CF0F, 0x1CF10, 0x1CF11, 0x1CF12, 0x1CF13,
531 0x1CF14, 0x1CF15, 0x1CF16, 0x1CF17, 0x1CF18, 0x1CF19, 0x1CF1A, 0x1CF1B, 0x1CF1C, 0x1CF1D, 0x1CF1E, 0x1CF1F, 0x1CF20,
532 0x1CF21, 0x1CF22, 0x1CF23, 0x1CF24, 0x1CF25, 0x1CF26, 0x1CF27, 0x1CF28, 0x1CF29, 0x1CF2A, 0x1CF2B, 0x1CF2C, 0x1CF2D,
533 0x1CF30, 0x1CF31, 0x1CF32, 0x1CF33, 0x1CF34, 0x1CF35, 0x1CF36, 0x1CF37, 0x1CF38, 0x1CF39, 0x1CF3A, 0x1CF3B, 0x1CF3C,
534 0x1CF3D, 0x1CF3E, 0x1CF3F, 0x1CF40, 0x1CF41, 0x1CF42, 0x1CF43, 0x1CF44, 0x1CF45, 0x1CF46, 0x1D167, 0x1D168, 0x1D169,
535 0x1D17B, 0x1D17C, 0x1D17D, 0x1D17E, 0x1D17F, 0x1D180, 0x1D181, 0x1D182, 0x1D185, 0x1D186, 0x1D187, 0x1D188, 0x1D189,
536 0x1D18A, 0x1D18B, 0x1D1AA, 0x1D1AB, 0x1D1AC, 0x1D1AD, 0x1D242, 0x1D243, 0x1D244, 0x1DA00, 0x1DA01, 0x1DA02, 0x1DA03,
537 0x1DA04, 0x1DA05, 0x1DA06, 0x1DA07, 0x1DA08, 0x1DA09, 0x1DA0A, 0x1DA0B, 0x1DA0C, 0x1DA0D, 0x1DA0E, 0x1DA0F, 0x1DA10,
538 0x1DA11, 0x1DA12, 0x1DA13, 0x1DA14, 0x1DA15, 0x1DA16, 0x1DA17, 0x1DA18, 0x1DA19, 0x1DA1A, 0x1DA1B, 0x1DA1C, 0x1DA1D,
539 0x1DA1E, 0x1DA1F, 0x1DA20, 0x1DA21, 0x1DA22, 0x1DA23, 0x1DA24, 0x1DA25, 0x1DA26, 0x1DA27, 0x1DA28, 0x1DA29, 0x1DA2A,
540 0x1DA2B, 0x1DA2C, 0x1DA2D, 0x1DA2E, 0x1DA2F, 0x1DA30, 0x1DA31, 0x1DA32, 0x1DA33, 0x1DA34, 0x1DA35, 0x1DA36, 0x1DA3B,
541 0x1DA3C, 0x1DA3D, 0x1DA3E, 0x1DA3F, 0x1DA40, 0x1DA41, 0x1DA42, 0x1DA43, 0x1DA44, 0x1DA45, 0x1DA46, 0x1DA47, 0x1DA48,
542 0x1DA49, 0x1DA4A, 0x1DA4B, 0x1DA4C, 0x1DA4D, 0x1DA4E, 0x1DA4F, 0x1DA50, 0x1DA51, 0x1DA52, 0x1DA53, 0x1DA54, 0x1DA55,
543 0x1DA56, 0x1DA57, 0x1DA58, 0x1DA59, 0x1DA5A, 0x1DA5B, 0x1DA5C, 0x1DA5D, 0x1DA5E, 0x1DA5F, 0x1DA60, 0x1DA61, 0x1DA62,
544 0x1DA63, 0x1DA64, 0x1DA65, 0x1DA66, 0x1DA67, 0x1DA68, 0x1DA69, 0x1DA6A, 0x1DA6B, 0x1DA6C, 0x1DA75, 0x1DA84, 0x1DA9B,
545 0x1DA9C, 0x1DA9D, 0x1DA9E, 0x1DA9F, 0x1DAA1, 0x1DAA2, 0x1DAA3, 0x1DAA4, 0x1DAA5, 0x1DAA6, 0x1DAA7, 0x1DAA8, 0x1DAA9,
546 0x1DAAA, 0x1DAAB, 0x1DAAC, 0x1DAAD, 0x1DAAE, 0x1DAAF, 0x1E000, 0x1E001, 0x1E002, 0x1E003, 0x1E004, 0x1E005, 0x1E006,
547 0x1E008, 0x1E009, 0x1E00A, 0x1E00B, 0x1E00C, 0x1E00D, 0x1E00E, 0x1E00F, 0x1E010, 0x1E011, 0x1E012, 0x1E013, 0x1E014,
548 0x1E015, 0x1E016, 0x1E017, 0x1E018, 0x1E01B, 0x1E01C, 0x1E01D, 0x1E01E, 0x1E01F, 0x1E020, 0x1E021, 0x1E023, 0x1E024,
549 0x1E026, 0x1E027, 0x1E028, 0x1E029, 0x1E02A, 0x1E08F, 0x1E130, 0x1E131, 0x1E132, 0x1E133, 0x1E134, 0x1E135, 0x1E136,
550 0x1E2AE, 0x1E2EC, 0x1E2ED, 0x1E2EE, 0x1E2EF, 0x1E4EC, 0x1E4ED, 0x1E4EE, 0x1E4EF, 0x1E5EE, 0x1E5EF, 0x1E8D0, 0x1E8D1,
551 0x1E8D2, 0x1E8D3, 0x1E8D4, 0x1E8D5, 0x1E8D6, 0x1E944, 0x1E945, 0x1E946, 0x1E947, 0x1E948, 0x1E949, 0x1E94A, 0xE0100,
552 0xE0101, 0xE0102, 0xE0103, 0xE0104, 0xE0105, 0xE0106, 0xE0107, 0xE0108, 0xE0109, 0xE010A, 0xE010B, 0xE010C, 0xE010D,
553 0xE010E, 0xE010F, 0xE0110, 0xE0111, 0xE0112, 0xE0113, 0xE0114, 0xE0115, 0xE0116, 0xE0117, 0xE0118, 0xE0119, 0xE011A,
554 0xE011B, 0xE011C, 0xE011D, 0xE011E, 0xE011F, 0xE0120, 0xE0121, 0xE0122, 0xE0123, 0xE0124, 0xE0125, 0xE0126, 0xE0127,
555 0xE0128, 0xE0129, 0xE012A, 0xE012B, 0xE012C, 0xE012D, 0xE012E, 0xE012F, 0xE0130, 0xE0131, 0xE0132, 0xE0133, 0xE0134,
556 0xE0135, 0xE0136, 0xE0137, 0xE0138, 0xE0139, 0xE013A, 0xE013B, 0xE013C, 0xE013D, 0xE013E, 0xE013F, 0xE0140, 0xE0141,
557 0xE0142, 0xE0143, 0xE0144, 0xE0145, 0xE0146, 0xE0147, 0xE0148, 0xE0149, 0xE014A, 0xE014B, 0xE014C, 0xE014D, 0xE014E,
558 0xE014F, 0xE0150, 0xE0151, 0xE0152, 0xE0153, 0xE0154, 0xE0155, 0xE0156, 0xE0157, 0xE0158, 0xE0159, 0xE015A, 0xE015B,
559 0xE015C, 0xE015D, 0xE015E, 0xE015F, 0xE0160, 0xE0161, 0xE0162, 0xE0163, 0xE0164, 0xE0165, 0xE0166, 0xE0167, 0xE0168,
560 0xE0169, 0xE016A, 0xE016B, 0xE016C, 0xE016D, 0xE016E, 0xE016F, 0xE0170, 0xE0171, 0xE0172, 0xE0173, 0xE0174, 0xE0175,
561 0xE0176, 0xE0177, 0xE0178, 0xE0179, 0xE017A, 0xE017B, 0xE017C, 0xE017D, 0xE017E, 0xE017F, 0xE0180, 0xE0181, 0xE0182,
562 0xE0183, 0xE0184, 0xE0185, 0xE0186, 0xE0187, 0xE0188, 0xE0189, 0xE018A, 0xE018B, 0xE018C, 0xE018D, 0xE018E, 0xE018F,
563 0xE0190, 0xE0191, 0xE0192, 0xE0193, 0xE0194, 0xE0195, 0xE0196, 0xE0197, 0xE0198, 0xE0199, 0xE019A, 0xE019B, 0xE019C,
564 0xE019D, 0xE019E, 0xE019F, 0xE01A0, 0xE01A1, 0xE01A2, 0xE01A3, 0xE01A4, 0xE01A5, 0xE01A6, 0xE01A7, 0xE01A8, 0xE01A9,
565 0xE01AA, 0xE01AB, 0xE01AC, 0xE01AD, 0xE01AE, 0xE01AF, 0xE01B0, 0xE01B1, 0xE01B2, 0xE01B3, 0xE01B4, 0xE01B5, 0xE01B6,
566 0xE01B7, 0xE01B8, 0xE01B9, 0xE01BA, 0xE01BB, 0xE01BC, 0xE01BD, 0xE01BE, 0xE01BF, 0xE01C0, 0xE01C1, 0xE01C2, 0xE01C3,
567 0xE01C4, 0xE01C5, 0xE01C6, 0xE01C7, 0xE01C8, 0xE01C9, 0xE01CA, 0xE01CB, 0xE01CC, 0xE01CD, 0xE01CE, 0xE01CF, 0xE01D0,
568 0xE01D1, 0xE01D2, 0xE01D3, 0xE01D4, 0xE01D5, 0xE01D6, 0xE01D7, 0xE01D8, 0xE01D9, 0xE01DA, 0xE01DB, 0xE01DC, 0xE01DD,
569 0xE01DE, 0xE01DF, 0xE01E0, 0xE01E1, 0xE01E2, 0xE01E3, 0xE01E4, 0xE01E5, 0xE01E6, 0xE01E7, 0xE01E8, 0xE01E9, 0xE01EA,
570 0xE01EB, 0xE01EC, 0xE01ED, 0xE01EE, 0xE01EF
571 /* END: COMBINING CHAR TABLE */
572};
573
574static const unsigned long combiningCharTableSize = sizeof(combiningCharTable) / sizeof(combiningCharTable[0]);
575
576static bool isCombiningChar(unsigned long cp) {
577 for (size_t i = 0; i < combiningCharTableSize; i++) {
578 auto code = combiningCharTable[i];
579 if (code > cp) {
580 return false;
581 }
582 if (code == cp) {
583 return true;
584 }
585 }
586 return false;
587}
588
589/* Get length of previous grapheme */
590static size_t defaultPrevCharLen(const char * buf, size_t /*buf_len*/, size_t pos, size_t * col_len) {
591 size_t end = pos;
592 while (pos > 0) {
593 size_t len = prevUtf8CodePointLen(buf, pos);
594 pos -= len;
595 int cp;
596 utf8BytesToCodePoint(buf: buf + pos, len, cp: &cp);
597 if (!isCombiningChar(cp)) {
598 if (col_len != NULL) {
599 *col_len = isWideChar(cp) ? 2 : 1;
600 }
601 return end - pos;
602 }
603 }
604 /* NOTREACHED */
605 return 0;
606}
607
608/* Get length of next grapheme */
609static size_t defaultNextCharLen(const char * buf, size_t buf_len, size_t pos, size_t * col_len) {
610 size_t beg = pos;
611 int cp;
612 size_t len = utf8BytesToCodePoint(buf: buf + pos, len: buf_len - pos, cp: &cp);
613 if (isCombiningChar(cp)) {
614 /* NOTREACHED */
615 return 0;
616 }
617 if (col_len != NULL) {
618 *col_len = isWideChar(cp) ? 2 : 1;
619 }
620 pos += len;
621 while (pos < buf_len) {
622 int cp;
623 len = utf8BytesToCodePoint(buf: buf + pos, len: buf_len - pos, cp: &cp);
624 if (!isCombiningChar(cp)) {
625 return pos - beg;
626 }
627 pos += len;
628 }
629 return pos - beg;
630}
631
632/* Read a Unicode from file. */
633static size_t defaultReadCode(int fd, char * buf, size_t buf_len, int * cp) {
634 if (buf_len < 1) {
635 return -1;
636 }
637 size_t nread = read(fd: fd, buf: &buf[0], nbytes: 1);
638 if (nread <= 0) {
639 return nread;
640 }
641
642 unsigned char byte = buf[0];
643 if ((byte & 0x80) == 0) {
644 ;
645 } else if ((byte & 0xE0) == 0xC0) {
646 if (buf_len < 2) {
647 return -1;
648 }
649 nread = read(fd: fd, buf: &buf[1], nbytes: 1);
650 if (nread <= 0) {
651 return nread;
652 }
653 } else if ((byte & 0xF0) == 0xE0) {
654 if (buf_len < 3) {
655 return -1;
656 }
657 nread = read(fd: fd, buf: &buf[1], nbytes: 2);
658 if (nread <= 0) {
659 return nread;
660 }
661 } else if ((byte & 0xF8) == 0xF0) {
662 if (buf_len < 3) {
663 return -1;
664 }
665 nread = read(fd: fd, buf: &buf[1], nbytes: 3);
666 if (nread <= 0) {
667 return nread;
668 }
669 } else {
670 return -1;
671 }
672
673 return utf8BytesToCodePoint(buf, len: buf_len, cp);
674}
675
676/* Set default encoding functions */
677static linenoisePrevCharLen * prevCharLen = defaultPrevCharLen;
678static linenoiseNextCharLen * nextCharLen = defaultNextCharLen;
679static linenoiseReadCode * readCode = defaultReadCode;
680
681/* Set used defined encoding functions */
682void linenoiseSetEncodingFunctions(linenoisePrevCharLen * prevCharLenFunc, linenoiseNextCharLen * nextCharLenFunc,
683 linenoiseReadCode * readCodeFunc) {
684 prevCharLen = prevCharLenFunc;
685 nextCharLen = nextCharLenFunc;
686 readCode = readCodeFunc;
687}
688
689/* ======================= Low level terminal handling ====================== */
690
691/* Enable "mask mode". When it is enabled, instead of the input that
692 * the user is typing, the terminal will just display a corresponding
693 * number of asterisks, like "****". This is useful for passwords and other
694 * secrets that should not be displayed. */
695void linenoiseMaskModeEnable(void) {
696 maskmode = 1;
697}
698
699/* Disable mask mode. */
700void linenoiseMaskModeDisable(void) {
701 maskmode = 0;
702}
703
704/* Set if to use or not the multi line mode. */
705void linenoiseSetMultiLine(int ml) {
706 mlmode = ml;
707}
708
709/* Return true if the terminal name is in the list of terminals we know are
710 * not able to understand basic escape sequences. */
711static int isUnsupportedTerm(void) {
712 char *term = getenv(name: "TERM");
713 if (term == NULL) return 0;
714 for (size_t j = 0; j < unsupported_term.size(); ++j) {
715 if (!strcasecmp(s1: term, s2: unsupported_term[j])) {
716 return 1;
717 }
718 }
719 return 0;
720}
721
722/* Raw mode: 1960 magic shit. */
723static int enableRawMode(int fd) {
724 struct termios raw;
725
726 if (!isatty(STDIN_FILENO)) goto fatal;
727 if (!atexit_registered) {
728 atexit(func: linenoiseAtExit);
729 atexit_registered = 1;
730 }
731 if (tcgetattr(fd: fd,termios_p: &orig_termios) == -1) goto fatal;
732
733 raw = orig_termios; /* modify the original mode */
734 /* input modes: no break, no CR to NL, no parity check, no strip char,
735 * no start/stop output control. */
736 raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
737 /* output modes - disable post processing */
738 raw.c_oflag &= ~(OPOST);
739 /* control modes - set 8 bit chars */
740 raw.c_cflag |= (CS8);
741 /* local modes - choing off, canonical off, no extended functions,
742 * no signal chars (^Z,^C) */
743 raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
744 /* control chars - set return condition: min number of bytes and timer.
745 * We want read to return every single byte, without timeout. */
746 raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
747
748 /* put terminal in raw mode after flushing */
749 if (tcsetattr(fd: fd,TCSAFLUSH,termios_p: &raw) < 0) goto fatal;
750 rawmode = 1;
751 return 0;
752
753fatal:
754 errno = ENOTTY;
755 return -1;
756}
757
758static void disableRawMode(int fd) {
759 /* Don't even check the return value as it's too late. */
760 if (rawmode && tcsetattr(fd: fd,TCSAFLUSH,termios_p: &orig_termios) != -1)
761 rawmode = 0;
762}
763
764/* Use the ESC [6n escape sequence to query the horizontal cursor position
765 * and return it. On error -1 is returned, on success the position of the
766 * cursor. */
767static int getCursorPosition(int ifd, int ofd) {
768 char buf[32];
769 int cols, rows;
770 unsigned int i = 0;
771
772 /* Report cursor location */
773 if (write(fd: ofd, buf: "\x1b[6n", n: 4) != 4) return -1;
774
775 /* Read the response: ESC [ rows ; cols R */
776 while (i < sizeof(buf)-1) {
777 if (read(fd: ifd,buf: buf+i,nbytes: 1) != 1) break;
778 if (buf[i] == 'R') break;
779 i++;
780 }
781 buf[i] = '\0';
782
783 /* Parse it. */
784 if (buf[0] != ESC || buf[1] != '[') return -1;
785 if (sscanf(s: buf+2,format: "%d;%d",&rows,&cols) != 2) return -1;
786 return cols;
787}
788
789/* Try to get the number of columns in the current terminal, or assume 80
790 * if it fails. */
791static int getColumns(int ifd, int ofd) {
792 struct winsize ws;
793
794 if (ioctl(fd: 1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
795 /* ioctl() failed. Try to query the terminal itself. */
796 int start, cols;
797
798 /* Get the initial position so we can restore it later. */
799 start = getCursorPosition(ifd,ofd);
800 if (start == -1) goto failed;
801
802 /* Go to right margin and get position. */
803 if (write(fd: ofd,buf: "\x1b[999C",n: 6) != 6) goto failed;
804 cols = getCursorPosition(ifd,ofd);
805 if (cols == -1) goto failed;
806
807 /* Restore position. */
808 if (cols > start) {
809 char seq[32];
810 snprintf(s: seq,maxlen: 32,format: "\x1b[%dD",cols-start);
811 if (write(fd: ofd,buf: seq,n: strlen(s: seq)) == -1) {
812 /* Can't recover... */
813 }
814 }
815 return cols;
816 } else {
817 return ws.ws_col;
818 }
819
820failed:
821 return 80;
822}
823
824/* Clear the screen. Used to handle ctrl+l */
825void linenoiseClearScreen(void) {
826 if (write(STDOUT_FILENO,buf: "\x1b[H\x1b[2J",n: 7) <= 0) {
827 /* nothing to do, just to avoid warning. */
828 }
829}
830
831/* Beep, used for completion when there is nothing to complete or when all
832 * the choices were already shown. */
833static void linenoiseBeep(void) {
834 fprintf(stderr, format: "\x7");
835 fflush(stderr);
836}
837
838/* Called by completeLine() and linenoiseShow() to render the current
839 * edited line with the proposed completion. If the current completion table
840 * is already available, it is passed as second argument, otherwise the
841 * function will use the callback to obtain it.
842 *
843 * Flags are the same as refreshLine*(), that is REFRESH_* macros. */
844static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseCompletions *lc, int flags) {
845 /* Obtain the table of completions if the caller didn't provide one. */
846 linenoiseCompletions ctable;
847 if (lc == NULL) {
848 completionCallback(ls->buf, &ctable);
849 lc = &ctable;
850 }
851
852 /* Show the edited line with completion if possible, or just refresh. */
853 if (ls->completion_idx < lc->len) {
854 struct linenoiseState saved = *ls;
855 ls->len = ls->pos = strlen(s: lc->cvec[ls->completion_idx]);
856 ls->buf = lc->cvec[ls->completion_idx];
857 refreshLineWithFlags(l: ls, flags);
858 ls->len = saved.len;
859 ls->pos = saved.pos;
860 ls->buf = saved.buf;
861 } else {
862 refreshLineWithFlags(l: ls, flags);
863 }
864
865 if (lc == &ctable) {
866 ctable.to_free = false;
867 }
868}
869
870enum ESC_TYPE { ESC_NULL = 0, ESC_DELETE, ESC_UP, ESC_DOWN, ESC_RIGHT, ESC_LEFT, ESC_HOME, ESC_END };
871
872static ESC_TYPE readEscapeSequence(struct linenoiseState * l) {
873 /* Check if the file input has additional data. */
874 struct pollfd pfd;
875 pfd.fd = l->ifd;
876 pfd.events = POLLIN;
877
878 auto ret = poll(fds: &pfd, nfds: 1, timeout: 1); // 1 millisecond timeout
879 if (ret <= 0) { // -1: error, 0: timeout
880 return ESC_NULL;
881 }
882
883 /* Read the next two bytes representing the escape sequence.
884 * Use two calls to handle slow terminals returning the two
885 * chars at different times. */
886 char seq[3];
887 if (read(fd: l->ifd, buf: seq, nbytes: 1) == -1) {
888 return ESC_NULL;
889 }
890 if (read(fd: l->ifd, buf: seq + 1, nbytes: 1) == -1) {
891 return ESC_NULL;
892 }
893
894 /* ESC [ sequences. */
895 if (seq[0] == '[') {
896 if (seq[1] >= '0' && seq[1] <= '9') {
897 /* Extended escape, read additional byte. */
898 if (read(fd: l->ifd, buf: seq + 2, nbytes: 1) == -1) {
899 return ESC_NULL;
900 }
901 if (seq[2] == '~') {
902 switch (seq[1]) {
903 case '3':
904 return ESC_DELETE;
905 }
906 }
907 } else {
908 switch (seq[1]) {
909 case 'A':
910 return ESC_UP;
911 case 'B':
912 return ESC_DOWN;
913 case 'C':
914 return ESC_RIGHT;
915 case 'D':
916 return ESC_LEFT;
917 case 'H':
918 return ESC_HOME;
919 case 'F':
920 return ESC_END;
921 }
922 }
923 }
924
925 /* ESC O sequences. */
926 else if (seq[0] == 'O') {
927 switch (seq[1]) {
928 case 'H':
929 return ESC_HOME;
930 case 'F':
931 return ESC_END;
932 }
933 }
934 return ESC_NULL;
935}
936
937/* This is an helper function for linenoiseEdit*() and is called when the
938 * user types the <tab> key in order to complete the string currently in the
939 * input.
940 *
941 * The state of the editing is encapsulated into the pointed linenoiseState
942 * structure as described in the structure definition.
943 *
944 * If the function returns non-zero, the caller should handle the
945 * returned value as a byte read from the standard input, and process
946 * it as usually: this basically means that the function may return a byte
947 * read from the terminal but not processed. Otherwise, if zero is returned,
948 * the input was consumed by the completeLine() function to navigate the
949 * possible completions, and the caller should read for the next characters
950 * from stdin. */
951static int completeLine(struct linenoiseState * ls, int keypressed, ESC_TYPE esc_type) {
952 linenoiseCompletions lc;
953 int nwritten;
954 char c = keypressed;
955
956 completionCallback(ls->buf, &lc);
957 if (lc.len == 0) {
958 linenoiseBeep();
959 ls->in_completion = 0;
960 } else {
961 if (c == TAB) {
962 if (ls->in_completion == 0) {
963 ls->in_completion = 1;
964 ls->completion_idx = 0;
965 } else {
966 ls->completion_idx = (ls->completion_idx + 1) % (lc.len + 1);
967 if (ls->completion_idx == lc.len) {
968 linenoiseBeep();
969 }
970 }
971 c = 0;
972 } else if (c == ESC && esc_type == ESC_NULL) {
973 /* Re-show original buffer */
974 if (ls->completion_idx < lc.len) {
975 refreshLine(l: ls);
976 }
977 ls->in_completion = 0;
978 c = 0;
979 } else {
980 /* Update buffer and return */
981 if (ls->completion_idx < lc.len) {
982 nwritten = snprintf(s: ls->buf, maxlen: ls->buflen, format: "%s", lc.cvec[ls->completion_idx]);
983 ls->len = ls->pos = nwritten;
984 }
985 ls->in_completion = 0;
986 }
987
988 /* Show completion or original buffer */
989 if (ls->in_completion && ls->completion_idx < lc.len) {
990 refreshLineWithCompletion(ls, lc: &lc, REFRESH_ALL);
991 } else {
992 refreshLine(l: ls);
993 }
994 }
995
996 return c; /* Return last read character */
997}
998
999/* Register a callback function to be called for tab-completion. */
1000void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
1001 completionCallback = fn;
1002}
1003
1004/* Register a hits function to be called to show hits to the user at the
1005 * right of the prompt. */
1006void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) {
1007 hintsCallback = fn;
1008}
1009
1010/* Register a function to free the hints returned by the hints callback
1011 * registered with linenoiseSetHintsCallback(). */
1012void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {
1013 freeHintsCallback = fn;
1014}
1015
1016/* This function is used by the callback function registered by the user
1017 * in order to add completion options given the input string when the
1018 * user typed <tab>. See the example.c source code for a very easy to
1019 * understand example. */
1020void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
1021 const size_t len = strlen(s: str);
1022 auto copy = std::make_unique<char[]>(num: len + 1);
1023 if (!copy) {
1024 return;
1025 }
1026
1027 memcpy(dest: copy.get(), src: str, n: len + 1);
1028 char ** cvec = static_cast<char **>(std::realloc(ptr: lc->cvec, size: sizeof(char *) * (lc->len + 1)));
1029 if (cvec == nullptr) {
1030 return;
1031 }
1032
1033 lc->cvec = cvec;
1034 lc->cvec[lc->len++] = copy.release();
1035}
1036
1037/* Get column length from begining of buffer to current byte position */
1038static size_t columnPos(const char * buf, size_t buf_len, size_t pos) {
1039 size_t ret = 0;
1040 size_t off = 0;
1041 while (off < pos) {
1042 size_t col_len;
1043 size_t len = nextCharLen(buf, buf_len, off, &col_len);
1044 off += len;
1045 ret += col_len;
1046 }
1047 return ret;
1048}
1049
1050/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
1051 * to the right of the prompt. */
1052static void refreshShowHints(std::string & ab, struct linenoiseState * l, int pcollen) {
1053 char seq[64];
1054 size_t collen = pcollen + columnPos(buf: l->buf, buf_len: l->len, pos: l->len);
1055 if (hintsCallback && collen < l->cols) {
1056 int color = -1, bold = 0;
1057 const char *hint = hintsCallback(l->buf,&color,&bold);
1058 if (hint) {
1059 int hintlen = strlen(s: hint);
1060 int hintmaxlen = l->cols - collen;
1061 if (hintlen > hintmaxlen) hintlen = hintmaxlen;
1062 if (bold == 1 && color == -1) color = 37;
1063 if (color != -1 || bold != 0)
1064 snprintf(s: seq,maxlen: 64,format: "\033[%d;%d;49m",bold,color);
1065 else
1066 seq[0] = '\0';
1067 ab.append(s: seq);
1068 ab.append(s: hint, n: hintlen);
1069 if (color != -1 || bold != 0)
1070 ab.append(s: "\033[0m");
1071
1072 /* Call the function to free the hint returned. */
1073 if (freeHintsCallback) freeHintsCallback(hint);
1074 }
1075 }
1076}
1077
1078/* Check if text is an ANSI escape sequence */
1079static int isAnsiEscape(const char * buf, size_t buf_len, size_t * len) {
1080 if (buf_len > 2 && !memcmp(s1: "\033[", s2: buf, n: 2)) {
1081 size_t off = 2;
1082 while (off < buf_len) {
1083 switch (buf[off++]) {
1084 case 'A':
1085 case 'B':
1086 case 'C':
1087 case 'D':
1088 case 'E':
1089 case 'F':
1090 case 'G':
1091 case 'H':
1092 case 'J':
1093 case 'K':
1094 case 'S':
1095 case 'T':
1096 case 'f':
1097 case 'm':
1098 *len = off;
1099 return 1;
1100 }
1101 }
1102 }
1103 return 0;
1104}
1105
1106/* Get column length of prompt text */
1107static size_t promptTextColumnLen(const char * prompt, size_t plen) {
1108 char buf[LINENOISE_MAX_LINE];
1109 size_t buf_len = 0;
1110 size_t off = 0;
1111 while (off < plen) {
1112 size_t len;
1113 if (isAnsiEscape(buf: prompt + off, buf_len: plen - off, len: &len)) {
1114 off += len;
1115 continue;
1116 }
1117 buf[buf_len++] = prompt[off++];
1118 }
1119 return columnPos(buf, buf_len, pos: buf_len);
1120}
1121
1122/* Single line low level line refresh.
1123 *
1124 * Rewrite the currently edited line accordingly to the buffer content,
1125 * cursor position, and number of columns of the terminal.
1126 *
1127 * Flags is REFRESH_* macros. The function can just remove the old
1128 * prompt, just write it, or both. */
1129static void refreshSingleLine(struct linenoiseState *l, int flags) {
1130 char seq[64];
1131 size_t pcollen = promptTextColumnLen(prompt: l->prompt, plen: strlen(s: l->prompt));
1132 int fd = l->ofd;
1133 char *buf = l->buf;
1134 size_t len = l->len;
1135 size_t pos = l->pos;
1136 std::string ab;
1137
1138 while ((pcollen + columnPos(buf, buf_len: len, pos)) >= l->cols) {
1139 int chlen = nextCharLen(buf, len, 0, NULL);
1140 buf += chlen;
1141 len -= chlen;
1142 pos -= chlen;
1143 }
1144 while (pcollen + columnPos(buf, buf_len: len, pos: len) > l->cols) {
1145 len -= prevCharLen(buf, len, len, NULL);
1146 }
1147
1148 /* Cursor to left edge */
1149 snprintf(s: seq,maxlen: sizeof(seq),format: "\r");
1150 ab.append(s: seq);
1151
1152 if (flags & REFRESH_WRITE) {
1153 /* Write the prompt and the current buffer content */
1154 ab.append(s: l->prompt);
1155 if (maskmode == 1) {
1156 while (len--) {
1157 ab.append(s: "*");
1158 }
1159 } else {
1160 ab.append(s: buf, n: len);
1161 }
1162 /* Show hits if any. */
1163 refreshShowHints(ab, l, pcollen);
1164 }
1165
1166 /* Erase to right */
1167 snprintf(s: seq,maxlen: sizeof(seq),format: "\x1b[0K");
1168 ab.append(s: seq);
1169 if (flags & REFRESH_WRITE) {
1170 /* Move cursor to original position. */
1171 snprintf(s: seq, maxlen: sizeof(seq), format: "\r\x1b[%dC", (int) (columnPos(buf, buf_len: len, pos) + pcollen));
1172 ab.append(s: seq);
1173 }
1174
1175 (void) !write(fd: fd, buf: ab.c_str(), n: ab.size()); /* Can't recover from write error. */
1176}
1177
1178/* Get column length from begining of buffer to current byte position for multiline mode*/
1179static size_t columnPosForMultiLine(const char * buf, size_t buf_len, size_t pos, size_t cols, size_t ini_pos) {
1180 size_t ret = 0;
1181 size_t colwid = ini_pos;
1182
1183 size_t off = 0;
1184 while (off < buf_len) {
1185 size_t col_len;
1186 size_t len = nextCharLen(buf, buf_len, off, &col_len);
1187
1188 int dif = (int) (colwid + col_len) - (int) cols;
1189 if (dif > 0) {
1190 ret += dif;
1191 colwid = col_len;
1192 } else if (dif == 0) {
1193 colwid = 0;
1194 } else {
1195 colwid += col_len;
1196 }
1197
1198 if (off >= pos) {
1199 break;
1200 }
1201 off += len;
1202 ret += col_len;
1203 }
1204
1205 return ret;
1206}
1207
1208/* Multi line low level line refresh.
1209 *
1210 * Rewrite the currently edited line accordingly to the buffer content,
1211 * cursor position, and number of columns of the terminal.
1212 *
1213 * Flags is REFRESH_* macros. The function can just remove the old
1214 * prompt, just write it, or both. */
1215static void refreshMultiLine(struct linenoiseState *l, int flags) {
1216 char seq[64];
1217 size_t pcollen = promptTextColumnLen(prompt: l->prompt, plen: strlen(s: l->prompt));
1218 int colpos = columnPosForMultiLine(buf: l->buf, buf_len: l->len, pos: l->len, cols: l->cols, ini_pos: pcollen);
1219 int colpos2; /* cursor column position. */
1220 int rows = (pcollen + colpos + l->cols - 1) / l->cols; /* rows used by current buf. */
1221 int rpos = (pcollen + l->oldcolpos + l->cols) / l->cols; /* cursor relative row. */
1222 int rpos2; /* rpos after refresh. */
1223 int col; /* column position, zero-based. */
1224 int old_rows = l->oldrows;
1225 int fd = l->ofd, j;
1226 std::string ab;
1227 l->oldrows = rows;
1228
1229 /* First step: clear all the lines used before. To do so start by
1230 * going to the last row. */
1231 if (flags & REFRESH_CLEAN) {
1232 if (old_rows - rpos > 0) {
1233 snprintf(s: seq,maxlen: 64,format: "\x1b[%dB", old_rows-rpos);
1234 ab.append(s: seq);
1235 }
1236
1237 /* Now for every row clear it, go up. */
1238 for (j = 0; j < old_rows - 1; j++) {
1239 snprintf(s: seq,maxlen: 64,format: "\r\x1b[0K\x1b[1A");
1240 ab.append(s: seq);
1241 }
1242 }
1243
1244 if (flags & REFRESH_ALL) {
1245 /* Clean the top line. */
1246 snprintf(s: seq,maxlen: 64,format: "\r\x1b[0K");
1247 ab.append(s: seq);
1248 }
1249
1250 /* Get column length to cursor position */
1251 colpos2 = columnPosForMultiLine(buf: l->buf, buf_len: l->len, pos: l->pos, cols: l->cols, ini_pos: pcollen);
1252
1253 if (flags & REFRESH_WRITE) {
1254 /* Write the prompt and the current buffer content */
1255 ab.append(s: l->prompt);
1256 if (maskmode == 1) {
1257 for (unsigned int i = 0; i < l->len; ++i) {
1258 ab.append(s: "*");
1259 }
1260 } else {
1261 ab.append(s: l->buf, n: l->len);
1262 }
1263
1264 /* Show hits if any. */
1265 refreshShowHints(ab, l, pcollen);
1266
1267 /* If we are at the very end of the screen with our prompt, we need to
1268 * emit a newline and move the prompt to the first column. */
1269 if (l->pos && l->pos == l->len && (colpos2 + pcollen) % l->cols == 0) {
1270 ab.append(s: "\n");
1271 snprintf(s: seq,maxlen: 64,format: "\r");
1272 ab.append(s: seq);
1273 rows++;
1274 if (rows > (int)l->oldrows) l->oldrows = rows;
1275 }
1276
1277 /* Move cursor to right position. */
1278 rpos2 = (pcollen + colpos2 + l->cols) / l->cols; /* Current cursor relative row */
1279
1280 /* Go up till we reach the expected position. */
1281 if (rows - rpos2 > 0) {
1282 snprintf(s: seq,maxlen: 64,format: "\x1b[%dA", rows-rpos2);
1283 ab.append(s: seq);
1284 }
1285
1286 /* Set column. */
1287 col = (pcollen + colpos2) % l->cols;
1288 if (col)
1289 snprintf(s: seq,maxlen: 64,format: "\r\x1b[%dC", col);
1290 else
1291 snprintf(s: seq,maxlen: 64,format: "\r");
1292 ab.append(s: seq);
1293 }
1294
1295 l->oldcolpos = colpos2;
1296
1297 (void) !write(fd: fd, buf: ab.c_str(), n: ab.size()); /* Can't recover from write error. */
1298}
1299
1300/* Calls the two low level functions refreshSingleLine() or
1301 * refreshMultiLine() according to the selected mode. */
1302static void refreshLineWithFlags(struct linenoiseState *l, int flags) {
1303 if (mlmode)
1304 refreshMultiLine(l,flags);
1305 else
1306 refreshSingleLine(l,flags);
1307}
1308
1309/* Utility function to avoid specifying REFRESH_ALL all the times. */
1310static void refreshLine(struct linenoiseState *l) {
1311 refreshLineWithFlags(l,REFRESH_ALL);
1312}
1313
1314/* Hide the current line, when using the multiplexing API. */
1315void linenoiseHide(struct linenoiseState *l) {
1316 if (mlmode)
1317 refreshMultiLine(l,REFRESH_CLEAN);
1318 else
1319 refreshSingleLine(l,REFRESH_CLEAN);
1320}
1321
1322/* Show the current line, when using the multiplexing API. */
1323void linenoiseShow(struct linenoiseState *l) {
1324 if (l->in_completion) {
1325 refreshLineWithCompletion(ls: l,NULL,REFRESH_WRITE);
1326 } else {
1327 refreshLineWithFlags(l,REFRESH_WRITE);
1328 }
1329}
1330
1331/* Insert the character 'c' at cursor current position.
1332 *
1333 * On error writing to the terminal -1 is returned, otherwise 0. */
1334static int linenoiseEditInsert(struct linenoiseState * l, const char * cbuf, int clen) {
1335 if (l->len + clen <= l->buflen) {
1336 if (l->len == l->pos) {
1337 memcpy(dest: &l->buf[l->pos], src: cbuf, n: clen);
1338 l->pos += clen;
1339 l->len += clen;
1340 ;
1341 l->buf[l->len] = '\0';
1342 if ((!mlmode && promptTextColumnLen(prompt: l->prompt, plen: l->plen) + columnPos(buf: l->buf, buf_len: l->len, pos: l->len) < l->cols &&
1343 !hintsCallback)) {
1344 /* Avoid a full update of the line in the
1345 * trivial case. */
1346 if (maskmode == 1) {
1347 static const char d = '*';
1348 if (write(fd: l->ofd, buf: &d, n: 1) == -1) {
1349 return -1;
1350 }
1351 } else {
1352 if (write(fd: l->ofd, buf: cbuf, n: clen) == -1) {
1353 return -1;
1354 }
1355 }
1356 } else {
1357 refreshLine(l);
1358 }
1359 } else {
1360 memmove(dest: l->buf + l->pos + clen, src: l->buf + l->pos, n: l->len - l->pos);
1361 memcpy(dest: &l->buf[l->pos], src: cbuf, n: clen);
1362 l->pos += clen;
1363 l->len += clen;
1364 l->buf[l->len] = '\0';
1365 refreshLine(l);
1366 }
1367 }
1368 return 0;
1369}
1370
1371/* Move cursor on the left. */
1372static void linenoiseEditMoveLeft(struct linenoiseState * l) {
1373 if (l->pos > 0) {
1374 l->pos -= prevCharLen(l->buf, l->len, l->pos, NULL);
1375 refreshLine(l);
1376 }
1377}
1378
1379/* Move cursor on the right. */
1380static void linenoiseEditMoveRight(struct linenoiseState * l) {
1381 if (l->pos != l->len) {
1382 l->pos += nextCharLen(l->buf, l->len, l->pos, NULL);
1383 refreshLine(l);
1384 }
1385}
1386
1387/* Move cursor to the start of the line. */
1388static void linenoiseEditMoveHome(struct linenoiseState * l) {
1389 if (l->pos != 0) {
1390 l->pos = 0;
1391 refreshLine(l);
1392 }
1393}
1394
1395/* Move cursor to the end of the line. */
1396static void linenoiseEditMoveEnd(struct linenoiseState * l) {
1397 if (l->pos != l->len) {
1398 l->pos = l->len;
1399 refreshLine(l);
1400 }
1401}
1402
1403/* Substitute the currently edited line with the next or previous history
1404 * entry as specified by 'dir'. */
1405#define LINENOISE_HISTORY_NEXT 0
1406#define LINENOISE_HISTORY_PREV 1
1407
1408static void linenoiseEditHistoryNext(struct linenoiseState * l, int dir) {
1409 if (history_len > 1) {
1410 /* Update the current history entry before to
1411 * overwrite it with the next one. */
1412 free(ptr: history[history_len - 1 - l->history_index]);
1413 history[history_len - 1 - l->history_index] = strdup(s: l->buf);
1414 /* Show the new entry */
1415 l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1;
1416 if (l->history_index < 0) {
1417 l->history_index = 0;
1418 return;
1419 } else if (l->history_index >= history_len) {
1420 l->history_index = history_len-1;
1421 return;
1422 }
1423 strncpy(dest: l->buf,src: history[history_len - 1 - l->history_index],n: l->buflen);
1424 l->buf[l->buflen-1] = '\0';
1425 l->len = l->pos = strlen(s: l->buf);
1426 refreshLine(l);
1427 }
1428}
1429
1430/* Delete the character at the right of the cursor without altering the cursor
1431 * position. Basically this is what happens with the "Delete" keyboard key. */
1432static void linenoiseEditDelete(struct linenoiseState * l) {
1433 if (l->len > 0 && l->pos < l->len) {
1434 int chlen = nextCharLen(l->buf, l->len, l->pos, NULL);
1435 memmove(dest: l->buf + l->pos, src: l->buf + l->pos + chlen, n: l->len - l->pos - chlen);
1436 l->len -= chlen;
1437 l->buf[l->len] = '\0';
1438 refreshLine(l);
1439 }
1440}
1441
1442/* Backspace implementation. */
1443static void linenoiseEditBackspace(struct linenoiseState * l) {
1444 if (l->pos > 0 && l->len > 0) {
1445 int chlen = prevCharLen(l->buf, l->len, l->pos, NULL);
1446 memmove(dest: l->buf + l->pos - chlen, src: l->buf + l->pos, n: l->len - l->pos);
1447 l->pos -= chlen;
1448 l->len -= chlen;
1449 l->buf[l->len] = '\0';
1450 refreshLine(l);
1451 }
1452}
1453
1454/* Delete the previous word, maintaining the cursor at the start of the
1455 * current word. */
1456static void linenoiseEditDeletePrevWord(struct linenoiseState * l) {
1457 size_t old_pos = l->pos;
1458 size_t diff;
1459
1460 while (l->pos > 0 && l->buf[l->pos-1] == ' ')
1461 l->pos--;
1462 while (l->pos > 0 && l->buf[l->pos-1] != ' ')
1463 l->pos--;
1464 diff = old_pos - l->pos;
1465 memmove(dest: l->buf+l->pos,src: l->buf+old_pos,n: l->len-old_pos+1);
1466 l->len -= diff;
1467 refreshLine(l);
1468}
1469
1470/* This function is part of the multiplexed API of Linenoise, that is used
1471 * in order to implement the blocking variant of the API but can also be
1472 * called by the user directly in an event driven program. It will:
1473 *
1474 * 1. Initialize the linenoise state passed by the user.
1475 * 2. Put the terminal in RAW mode.
1476 * 3. Show the prompt.
1477 * 4. Return control to the user, that will have to call linenoiseEditFeed()
1478 * each time there is some data arriving in the standard input.
1479 *
1480 * The user can also call linenoiseEditHide() and linenoiseEditShow() if it
1481 * is required to show some input arriving asynchronously, without mixing
1482 * it with the currently edited line.
1483 *
1484 * When linenoiseEditFeed() returns non-NULL, the user finished with the
1485 * line editing session (pressed enter CTRL-D/C): in this case the caller
1486 * needs to call linenoiseEditStop() to put back the terminal in normal
1487 * mode. This will not destroy the buffer, as long as the linenoiseState
1488 * is still valid in the context of the caller.
1489 *
1490 * The function returns 0 on success, or -1 if writing to standard output
1491 * fails. If stdin_fd or stdout_fd are set to -1, the default is to use
1492 * STDIN_FILENO and STDOUT_FILENO.
1493 */
1494int linenoiseEditStart(struct linenoiseState *l, int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) {
1495 /* Populate the linenoise state that we pass to functions implementing
1496 * specific editing functionalities. */
1497 l->in_completion = 0;
1498 l->ifd = stdin_fd != -1 ? stdin_fd : STDIN_FILENO;
1499 l->ofd = stdout_fd != -1 ? stdout_fd : STDOUT_FILENO;
1500 l->buf = buf;
1501 l->buflen = buflen;
1502 l->prompt = prompt;
1503 l->plen = strlen(s: prompt);
1504 l->oldcolpos = l->pos = 0;
1505 l->len = 0;
1506
1507 /* Enter raw mode. */
1508 if (enableRawMode(fd: l->ifd) == -1) return -1;
1509
1510 l->cols = getColumns(ifd: stdin_fd, ofd: stdout_fd);
1511 l->oldrows = 0;
1512 l->history_index = 0;
1513
1514 /* Buffer starts empty. */
1515 l->buf[0] = '\0';
1516 l->buflen--; /* Make sure there is always space for the nullterm */
1517
1518 /* If stdin is not a tty, stop here with the initialization. We
1519 * will actually just read a line from standard input in blocking
1520 * mode later, in linenoiseEditFeed(). */
1521 if (!isatty(fd: l->ifd)) return 0;
1522
1523 /* The latest history entry is always our current buffer, that
1524 * initially is just an empty string. */
1525 linenoiseHistoryAdd(line: "");
1526
1527 if (write(fd: l->ofd,buf: prompt,n: l->plen) == -1) return -1;
1528 return 0;
1529}
1530
1531const char* linenoiseEditMore = "If you see this, you are misusing the API: when linenoiseEditFeed() is called, if it returns linenoiseEditMore the user is yet editing the line. See the README file for more information.";
1532
1533static const char * handleEnterKey(struct linenoiseState * l) {
1534 --history_len;
1535 free(ptr: history[history_len]);
1536 if (mlmode) {
1537 linenoiseEditMoveEnd(l);
1538 }
1539 if (hintsCallback) {
1540 /* Force a refresh without hints to leave the previous
1541 * line as the user typed it after a newline. */
1542 linenoiseHintsCallback * hc = hintsCallback;
1543 hintsCallback = NULL;
1544 refreshLine(l);
1545 hintsCallback = hc;
1546 }
1547
1548 return strdup(s: l->buf);
1549}
1550
1551static const char * handleCtrlCKey() {
1552 errno = EAGAIN;
1553 return NULL;
1554}
1555
1556static const char * handleCtrlDKey(struct linenoiseState * l) {
1557 if (l->len > 0) {
1558 linenoiseEditDelete(l);
1559 return linenoiseEditMore;
1560 }
1561
1562 --history_len;
1563 free(ptr: history[history_len]);
1564 errno = ENOENT;
1565 return NULL;
1566}
1567
1568static void handleCtrlTKey(struct linenoiseState * l) {
1569 if (l->pos > 0 && l->pos < l->len) {
1570 auto prev_chlen = prevCharLen(l->buf, l->len, l->pos, NULL);
1571 auto curr_chlen = nextCharLen(l->buf, l->len, l->pos, NULL);
1572
1573 std::string prev_char(prev_chlen, 0);
1574 memcpy(dest: prev_char.data(), src: l->buf + l->pos - prev_chlen, n: prev_chlen);
1575 memmove(dest: l->buf + l->pos - prev_chlen, src: l->buf + l->pos, n: curr_chlen);
1576 memmove(dest: l->buf + l->pos - prev_chlen + curr_chlen, src: prev_char.data(), n: prev_chlen);
1577
1578 l->pos = l->pos - prev_chlen + curr_chlen;
1579 if (l->pos + prev_chlen != l->len) {
1580 l->pos += prev_chlen;
1581 }
1582
1583 refreshLine(l);
1584 }
1585}
1586
1587static void handleEscapeSequence(struct linenoiseState * l, int esc_type) {
1588 switch (esc_type) {
1589 case ESC_NULL:
1590 break;
1591 case ESC_DELETE:
1592 linenoiseEditDelete(l);
1593 break;
1594 case ESC_UP:
1595 linenoiseEditHistoryNext(l, LINENOISE_HISTORY_PREV);
1596 break;
1597 case ESC_DOWN:
1598 linenoiseEditHistoryNext(l, LINENOISE_HISTORY_NEXT);
1599 break;
1600 case ESC_RIGHT:
1601 linenoiseEditMoveRight(l);
1602 break;
1603 case ESC_LEFT:
1604 linenoiseEditMoveLeft(l);
1605 break;
1606 case ESC_HOME:
1607 linenoiseEditMoveHome(l);
1608 break;
1609 case ESC_END:
1610 linenoiseEditMoveEnd(l);
1611 break;
1612 }
1613}
1614
1615static void handleCtrlUKey(struct linenoiseState * l) {
1616 l->buf[0] = '\0';
1617 l->pos = l->len = 0;
1618 refreshLine(l);
1619}
1620
1621static void handleCtrlKKey(struct linenoiseState * l) {
1622 l->buf[l->pos] = '\0';
1623 l->len = l->pos;
1624 refreshLine(l);
1625}
1626
1627static const char * processInputCharacter(struct linenoiseState * l, int c, char * cbuf, int nread, int esc_type) {
1628 switch (c) {
1629 case ENTER:
1630 return handleEnterKey(l);
1631 case CTRL_C:
1632 return handleCtrlCKey();
1633 case BACKSPACE:
1634 case CTRL_H:
1635 linenoiseEditBackspace(l);
1636 break;
1637 case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the
1638 line is empty, act as end-of-file. */
1639 return handleCtrlDKey(l);
1640 case CTRL_T:
1641 handleCtrlTKey(l);
1642 break;
1643 case CTRL_B:
1644 linenoiseEditMoveLeft(l);
1645 break;
1646 case CTRL_F:
1647 linenoiseEditMoveRight(l);
1648 break;
1649 case CTRL_P:
1650 linenoiseEditHistoryNext(l, LINENOISE_HISTORY_PREV);
1651 break;
1652 case CTRL_N:
1653 linenoiseEditHistoryNext(l, LINENOISE_HISTORY_NEXT);
1654 break;
1655 case ESC:
1656 handleEscapeSequence(l, esc_type);
1657 break;
1658 default:
1659 if (linenoiseEditInsert(l, cbuf, clen: nread)) {
1660 return NULL;
1661 }
1662 break;
1663 case CTRL_U: /* Ctrl+u, delete the whole line. */
1664 handleCtrlUKey(l);
1665 break;
1666 case CTRL_K: /* Ctrl+k, delete from current to end of line. */
1667 handleCtrlKKey(l);
1668 break;
1669 case CTRL_A: /* Ctrl+a, go to the start of the line */
1670 linenoiseEditMoveHome(l);
1671 break;
1672 case CTRL_E: /* ctrl+e, go to the end of the line */
1673 linenoiseEditMoveEnd(l);
1674 break;
1675 case CTRL_L: /* ctrl+l, clear screen */
1676 linenoiseClearScreen();
1677 refreshLine(l);
1678 break;
1679 case CTRL_W: /* ctrl+w, delete previous word */
1680 linenoiseEditDeletePrevWord(l);
1681 break;
1682 }
1683 return linenoiseEditMore;
1684}
1685
1686/* This function is part of the multiplexed API of linenoise, see the top
1687 * comment on linenoiseEditStart() for more information. Call this function
1688 * each time there is some data to read from the standard input file
1689 * descriptor. In the case of blocking operations, this function can just be
1690 * called in a loop, and block.
1691 *
1692 * The function returns linenoiseEditMore to signal that line editing is still
1693 * in progress, that is, the user didn't yet pressed enter / CTRL-D. Otherwise
1694 * the function returns the pointer to the heap-allocated buffer with the
1695 * edited line, that the user should free with linenoiseFree().
1696 *
1697 * On special conditions, NULL is returned and errno is populated:
1698 *
1699 * EAGAIN if the user pressed Ctrl-C
1700 * ENOENT if the user pressed Ctrl-D
1701 *
1702 * Some other errno: I/O error.
1703 */
1704const char * linenoiseEditFeed(struct linenoiseState * l) {
1705 /* Not a TTY, pass control to line reading without character count
1706 * limits. */
1707 if (!isatty(fd: l->ifd)) return linenoiseNoTTY();
1708
1709 int c;
1710 int nread;
1711 char cbuf[32];
1712
1713 nread = readCode(l->ifd, cbuf, sizeof(cbuf), &c);
1714 if (nread <= 0) return NULL;
1715
1716 auto esc_type = ESC_NULL;
1717 if (c == ESC) {
1718 esc_type = readEscapeSequence(l);
1719 }
1720
1721 /* Only autocomplete when the callback is set. It returns < 0 when
1722 * there was an error reading from fd. Otherwise it will return the
1723 * character that should be handled next. */
1724 if ((l->in_completion || c == 9) && completionCallback != NULL) {
1725 c = completeLine(ls: l, keypressed: c, esc_type);
1726 /* Read next character when 0 */
1727 if (c == 0) return linenoiseEditMore;
1728 }
1729
1730 return processInputCharacter(l, c, cbuf, nread, esc_type);
1731}
1732
1733/* This is part of the multiplexed linenoise API. See linenoiseEditStart()
1734 * for more information. This function is called when linenoiseEditFeed()
1735 * returns something different than NULL. At this point the user input
1736 * is in the buffer, and we can restore the terminal in normal mode. */
1737void linenoiseEditStop(struct linenoiseState *l) {
1738 if (!isatty(fd: l->ifd)) return;
1739 disableRawMode(fd: l->ifd);
1740 printf(format: "\n");
1741}
1742
1743/* This just implements a blocking loop for the multiplexed API.
1744 * In many applications that are not event-driven, we can just call
1745 * the blocking linenoise API, wait for the user to complete the editing
1746 * and return the buffer. */
1747static const char *linenoiseBlockingEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt)
1748{
1749 struct linenoiseState l;
1750
1751 /* Editing without a buffer is invalid. */
1752 if (buflen == 0) {
1753 errno = EINVAL;
1754 return NULL;
1755 }
1756
1757 linenoiseEditStart(l: &l,stdin_fd,stdout_fd,buf,buflen,prompt);
1758 const char *res;
1759 while((res = linenoiseEditFeed(l: &l)) == linenoiseEditMore);
1760 linenoiseEditStop(l: &l);
1761 return res;
1762}
1763
1764/* This special mode is used by linenoise in order to print scan codes
1765 * on screen for debugging / development purposes. It is implemented
1766 * by the linenoise_example program using the --keycodes option. */
1767void linenoisePrintKeyCodes(void) {
1768 char quit[4];
1769
1770 printf(format: "Linenoise key codes debugging mode.\n"
1771 "Press keys to see scan codes. Type 'quit' at any time to exit.\n");
1772 if (enableRawMode(STDIN_FILENO) == -1) return;
1773 memset(s: quit,c: ' ',n: 4);
1774 while(1) {
1775 char c;
1776 int nread;
1777
1778 nread = read(STDIN_FILENO,buf: &c,nbytes: 1);
1779 if (nread <= 0) continue;
1780 memmove(dest: quit,src: quit+1,n: sizeof(quit)-1); /* shift string to left. */
1781 quit[sizeof(quit)-1] = c; /* Insert current char on the right. */
1782 if (memcmp(s1: quit,s2: "quit",n: sizeof(quit)) == 0) break;
1783
1784 printf(format: "'%c' %02x (%d) (type quit to exit)\n", isprint((int) c) ? c : '?', (int) c, (int) c);
1785 printf(format: "\r"); /* Go left edge manually, we are in raw mode. */
1786 fflush(stdout);
1787 }
1788 disableRawMode(STDIN_FILENO);
1789}
1790
1791/* This function is called when linenoise() is called with the standard
1792 * input file descriptor not attached to a TTY. So for example when the
1793 * program using linenoise is called in pipe or with a file redirected
1794 * to its standard input. In this case, we want to be able to return the
1795 * line regardless of its length (by default we are limited to 4k). */
1796static char *linenoiseNoTTY(void) {
1797 char *line = NULL;
1798 size_t len = 0, maxlen = 0;
1799
1800 while(1) {
1801 if (len == maxlen) {
1802 if (maxlen == 0) maxlen = 16;
1803 maxlen *= 2;
1804 char *oldval = line;
1805 line = (char*) realloc(ptr: line,size: maxlen);
1806 if (line == NULL) {
1807 if (oldval) free(ptr: oldval);
1808 return NULL;
1809 }
1810 }
1811 int c = fgetc(stdin);
1812 if (c == EOF || c == '\n') {
1813 if (c == EOF && len == 0) {
1814 free(ptr: line);
1815 return NULL;
1816 } else {
1817 line[len] = '\0';
1818 return line;
1819 }
1820 } else {
1821 line[len] = c;
1822 len++;
1823 }
1824 }
1825}
1826
1827/* The high level function that is the main API of the linenoise library.
1828 * This function checks if the terminal has basic capabilities, just checking
1829 * for a blacklist of stupid terminals, and later either calls the line
1830 * editing function or uses dummy fgets() so that you will be able to type
1831 * something even in the most desperate of the conditions. */
1832const char *linenoise(const char *prompt) {
1833 char buf[LINENOISE_MAX_LINE];
1834
1835 if (!isatty(STDIN_FILENO)) {
1836 /* Not a tty: read from file / pipe. In this mode we don't want any
1837 * limit to the line size, so we call a function to handle that. */
1838 return linenoiseNoTTY();
1839 } else if (isUnsupportedTerm()) {
1840 size_t len;
1841
1842 printf(format: "%s",prompt);
1843 fflush(stdout);
1844 if (fgets(s: buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;
1845 len = strlen(s: buf);
1846 while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
1847 len--;
1848 buf[len] = '\0';
1849 }
1850 return strdup(s: buf);
1851 } else {
1852 const char *retval = linenoiseBlockingEdit(STDIN_FILENO,STDOUT_FILENO,buf,LINENOISE_MAX_LINE,prompt);
1853 return retval;
1854 }
1855}
1856
1857/* This is just a wrapper the user may want to call in order to make sure
1858 * the linenoise returned buffer is freed with the same allocator it was
1859 * created with. Useful when the main program is using an alternative
1860 * allocator. */
1861void linenoiseFree(void *ptr) {
1862 if (ptr == linenoiseEditMore) return; // Protect from API misuse.
1863 free(ptr: ptr);
1864}
1865
1866/* ================================ History ================================= */
1867
1868/* Free the history, but does not reset it. Only used when we have to
1869 * exit() to avoid memory leaks are reported by valgrind & co. */
1870static void freeHistory(void) {
1871 if (history) {
1872 int j;
1873
1874 for (j = 0; j < history_len; j++)
1875 free(ptr: history[j]);
1876 free(ptr: history);
1877 }
1878}
1879
1880/* At exit we'll try to fix the terminal to the initial conditions. */
1881static void linenoiseAtExit(void) {
1882 disableRawMode(STDIN_FILENO);
1883 freeHistory();
1884}
1885
1886/* This is the API call to add a new entry in the linenoise history.
1887 * It uses a fixed array of char pointers that are shifted (memmoved)
1888 * when the history max length is reached in order to remove the older
1889 * entry and make room for the new one, so it is not exactly suitable for huge
1890 * histories, but will work well for a few hundred of entries.
1891 *
1892 * Using a circular buffer is smarter, but a bit more complex to handle. */
1893int linenoiseHistoryAdd(const char *line) {
1894 char *linecopy;
1895
1896 if (history_max_len == 0) return 0;
1897
1898 /* Initialization on first call. */
1899 if (history == NULL) {
1900 history = (char**) malloc(size: sizeof(char*)*history_max_len);
1901 if (history == NULL) return 0;
1902 memset(s: history,c: 0,n: (sizeof(char*)*history_max_len));
1903 }
1904
1905 /* Don't add duplicated lines. */
1906 if (history_len && !strcmp(s1: history[history_len-1], s2: line)) return 0;
1907
1908 /* Add an heap allocated copy of the line in the history.
1909 * If we reached the max length, remove the older line. */
1910 linecopy = strdup(s: line);
1911 if (!linecopy) return 0;
1912 if (history_len == history_max_len) {
1913 free(ptr: history[0]);
1914 memmove(dest: history,src: history+1,n: sizeof(char*)*(history_max_len-1));
1915 history_len--;
1916 }
1917 history[history_len] = linecopy;
1918 history_len++;
1919 return 1;
1920}
1921
1922/* Set the maximum length for the history. This function can be called even
1923 * if there is already some history, the function will make sure to retain
1924 * just the latest 'len' elements if the new history length value is smaller
1925 * than the amount of items already inside the history. */
1926int linenoiseHistorySetMaxLen(int len) {
1927 char **new_ptr;
1928
1929 if (len < 1) return 0;
1930 if (history) {
1931 int tocopy = history_len;
1932
1933 new_ptr = (char**) malloc(size: sizeof(char*)*len);
1934 if (new_ptr == NULL) return 0;
1935
1936 /* If we can't copy everything, free the elements we'll not use. */
1937 if (len < tocopy) {
1938 int j;
1939
1940 for (j = 0; j < tocopy-len; j++) free(ptr: history[j]);
1941 tocopy = len;
1942 }
1943 memset(s: new_ptr,c: 0,n: sizeof(char*)*len);
1944 memcpy(dest: new_ptr,src: history+(history_len-tocopy), n: sizeof(char*)*tocopy);
1945 free(ptr: history);
1946 history = new_ptr;
1947 }
1948 history_max_len = len;
1949 if (history_len > history_max_len)
1950 history_len = history_max_len;
1951 return 1;
1952}
1953
1954/* Save the history in the specified file. On success 0 is returned
1955 * otherwise -1 is returned. */
1956int linenoiseHistorySave(const char *filename) {
1957 mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
1958 File file;
1959 file.open(filename, mode: "w");
1960 umask(mask: old_umask);
1961 if (file.file == NULL) {
1962 return -1;
1963 }
1964 chmod(file: filename,S_IRUSR|S_IWUSR);
1965 for (int j = 0; j < history_len; ++j) {
1966 fprintf(stream: file.file, format: "%s\n", history[j]);
1967 }
1968
1969 return 0;
1970}
1971
1972/* Load the history from the specified file. If the file does not exist
1973 * zero is returned and no operation is performed.
1974 *
1975 * If the file exists and the operation succeeded 0 is returned, otherwise
1976 * on error -1 is returned. */
1977int linenoiseHistoryLoad(const char *filename) {
1978 File file;
1979 file.open(filename, mode: "r");
1980 char buf[LINENOISE_MAX_LINE];
1981 if (file.file == NULL) {
1982 return -1;
1983 }
1984
1985 while (fgets(s: buf, LINENOISE_MAX_LINE, stream: file.file) != NULL) {
1986 char *p;
1987
1988 p = strchr(s: buf,c: '\r');
1989 if (!p) p = strchr(s: buf,c: '\n');
1990 if (p) *p = '\0';
1991 linenoiseHistoryAdd(line: buf);
1992 }
1993 return 0;
1994}
1995#endif
1996