]> git.lizzy.rs Git - linenoise.git/blob - linenoise.c
Fix a couple of compiler warnings
[linenoise.git] / linenoise.c
1 /* linenoise.c -- guerrilla line editing library against the idea that a
2  * line editing lib needs to be 20,000 lines of C code.
3  *
4  * You can find the latest source code at:
5  *
6  *   http://github.com/msteveb/linenoise
7  *   (forked from http://github.com/antirez/linenoise)
8  *
9  * Does a number of crazy assumptions that happen to be true in 99.9999% of
10  * the 2010 UNIX computers around.
11  *
12  * ------------------------------------------------------------------------
13  *
14  * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
15  * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
16  * Copyright (c) 2011, Steve Bennett <steveb at workware dot net dot au>
17  *
18  * All rights reserved.
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions are
22  * met:
23  *
24  *  *  Redistributions of source code must retain the above copyright
25  *     notice, this list of conditions and the following disclaimer.
26  *
27  *  *  Redistributions in binary form must reproduce the above copyright
28  *     notice, this list of conditions and the following disclaimer in the
29  *     documentation and/or other materials provided with the distribution.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  *
43  * ------------------------------------------------------------------------
44  *
45  * References:
46  * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
47  * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
48  *
49  * Bloat:
50  * - Completion?
51  *
52  * Unix/termios
53  * ------------
54  * List of escape sequences used by this program, we do everything just
55  * a few 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 of n chars
68  *
69  * CR (Carriage Return)
70  *    Sequence: \r
71  *    Effect: moves cursor to column 1
72  *
73  * The following are used to clear the screen: ESC [ H ESC [ 2 J
74  * This is actually composed of two sequences:
75  *
76  * cursorhome
77  *    Sequence: ESC [ H
78  *    Effect: moves the cursor to upper left corner
79  *
80  * ED2 (Clear entire screen)
81  *    Sequence: ESC [ 2 J
82  *    Effect: clear the whole screen
83  *
84  * == For highlighting control characters, we also use the following two ==
85  * SO (enter StandOut)
86  *    Sequence: ESC [ 7 m
87  *    Effect: Uses some standout mode such as reverse video
88  *
89  * SE (Standout End)
90  *    Sequence: ESC [ 0 m
91  *    Effect: Exit standout mode
92  *
93  * == Only used if TIOCGWINSZ fails ==
94  * DSR/CPR (Report cursor position)
95  *    Sequence: ESC [ 6 n
96  *    Effect: reports current cursor position as ESC [ NNN ; MMM R
97  *
98  * win32/console
99  * -------------
100  * If __MINGW32__ is defined, the win32 console API is used.
101  * This could probably be made to work for the msvc compiler too.
102  * This support based in part on work by Jon Griffiths.
103  */
104
105 #ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */
106 #include <windows.h>
107 #include <fcntl.h>
108 #define USE_WINCONSOLE
109 #ifdef __MINGW32__
110 #define HAVE_UNISTD_H
111 #else
112 /* Microsoft headers don't like old POSIX names */
113 #define strdup _strdup
114 #define snprintf _snprintf
115 #endif
116 #else
117 #include <termios.h>
118 #include <sys/ioctl.h>
119 #include <sys/poll.h>
120 #define USE_TERMIOS
121 #define HAVE_UNISTD_H
122 #endif
123
124 #ifdef HAVE_UNISTD_H
125 #include <unistd.h>
126 #endif
127 #include <stdlib.h>
128 #include <stdarg.h>
129 #include <stdio.h>
130 #include <errno.h>
131 #include <string.h>
132 #include <stdlib.h>
133 #include <sys/types.h>
134
135 #include "linenoise.h"
136 #include "utf8.h"
137
138 #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
139 #define LINENOISE_MAX_LINE 4096
140
141 #define ctrl(C) ((C) - '@')
142
143 /* Use -ve numbers here to co-exist with normal unicode chars */
144 enum {
145     SPECIAL_NONE,
146     SPECIAL_UP = -20,
147     SPECIAL_DOWN = -21,
148     SPECIAL_LEFT = -22,
149     SPECIAL_RIGHT = -23,
150     SPECIAL_DELETE = -24,
151     SPECIAL_HOME = -25,
152     SPECIAL_END = -26,
153     SPECIAL_INSERT = -27,
154     SPECIAL_PAGE_UP = -28,
155     SPECIAL_PAGE_DOWN = -29
156 };
157
158 static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
159 static int history_len = 0;
160 static char **history = NULL;
161
162 /* Structure to contain the status of the current (being edited) line */
163 struct current {
164     char *buf;  /* Current buffer. Always null terminated */
165     int bufmax; /* Size of the buffer, including space for the null termination */
166     int len;    /* Number of bytes in 'buf' */
167     int chars;  /* Number of chars in 'buf' (utf-8 chars) */
168     int pos;    /* Cursor position, measured in chars */
169     int cols;   /* Size of the window, in chars */
170     const char *prompt;
171     char *capture; /* Allocated capture buffer, or NULL for none. Always null terminated */
172 #if defined(USE_TERMIOS)
173     int fd;     /* Terminal fd */
174 #elif defined(USE_WINCONSOLE)
175     HANDLE outh; /* Console output handle */
176     HANDLE inh; /* Console input handle */
177     int rows;   /* Screen rows */
178     int x;      /* Current column during output */
179     int y;      /* Current row */
180 #endif
181 };
182
183 static int fd_read(struct current *current);
184 static int getWindowSize(struct current *current);
185
186 void linenoiseHistoryFree(void) {
187     if (history) {
188         int j;
189
190         for (j = 0; j < history_len; j++)
191             free(history[j]);
192         free(history);
193         history = NULL;
194         history_len = 0;
195     }
196 }
197
198 #if defined(USE_TERMIOS)
199 static void linenoiseAtExit(void);
200 static struct termios orig_termios; /* in order to restore at exit */
201 static int rawmode = 0; /* for atexit() function to check if restore is needed*/
202 static int atexit_registered = 0; /* register atexit just 1 time */
203
204 static const char *unsupported_term[] = {"dumb","cons25",NULL};
205
206 static int isUnsupportedTerm(void) {
207     char *term = getenv("TERM");
208
209     if (term) {
210         int j;
211         for (j = 0; unsupported_term[j]; j++) {
212             if (strcmp(term, unsupported_term[j]) == 0) {
213                 return 1;
214             }
215         }
216     }
217     return 0;
218 }
219
220 static int enableRawMode(struct current *current) {
221     struct termios raw;
222
223     current->fd = STDIN_FILENO;
224
225     if (!isatty(current->fd) || isUnsupportedTerm() ||
226         tcgetattr(current->fd, &orig_termios) == -1) {
227 fatal:
228         errno = ENOTTY;
229         return -1;
230     }
231
232     if (!atexit_registered) {
233         atexit(linenoiseAtExit);
234         atexit_registered = 1;
235     }
236
237     raw = orig_termios;  /* modify the original mode */
238     /* input modes: no break, no CR to NL, no parity check, no strip char,
239      * no start/stop output control. */
240     raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
241     /* output modes - disable post processing */
242     raw.c_oflag &= ~(OPOST);
243     /* control modes - set 8 bit chars */
244     raw.c_cflag |= (CS8);
245     /* local modes - choing off, canonical off, no extended functions,
246      * no signal chars (^Z,^C) */
247     raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
248     /* control chars - set return condition: min number of bytes and timer.
249      * We want read to return every single byte, without timeout. */
250     raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
251
252     /* put terminal in raw mode after flushing */
253     if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) {
254         goto fatal;
255     }
256     rawmode = 1;
257
258     current->cols = 0;
259     return 0;
260 }
261
262 static void disableRawMode(struct current *current) {
263     /* Don't even check the return value as it's too late. */
264     if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1)
265         rawmode = 0;
266 }
267
268 /* At exit we'll try to fix the terminal to the initial conditions. */
269 static void linenoiseAtExit(void) {
270     if (rawmode) {
271         tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios);
272     }
273     linenoiseHistoryFree();
274 }
275
276 /* gcc/glibc insists that we care about the return code of write!
277  * Clarification: This means that a void-cast like "(void) (EXPR)"
278  * does not work.
279  */
280 #define IGNORE_RC(EXPR) if (EXPR) {}
281
282 /* This is fdprintf() on some systems, but use a different
283  * name to avoid conflicts
284  */
285 static void fd_printf(int fd, const char *format, ...)
286 {
287     va_list args;
288     char buf[64];
289     int n;
290
291     va_start(args, format);
292     n = vsnprintf(buf, sizeof(buf), format, args);
293     va_end(args);
294     IGNORE_RC(write(fd, buf, n));
295 }
296
297 static void clearScreen(struct current *current)
298 {
299     fd_printf(current->fd, "\x1b[H\x1b[2J");
300 }
301
302 static void cursorToLeft(struct current *current)
303 {
304     fd_printf(current->fd, "\r");
305 }
306
307 static int outputChars(struct current *current, const char *buf, int len)
308 {
309     return write(current->fd, buf, len);
310 }
311
312 static void outputControlChar(struct current *current, char ch)
313 {
314     fd_printf(current->fd, "\x1b[7m^%c\x1b[0m", ch);
315 }
316
317 static void eraseEol(struct current *current)
318 {
319     fd_printf(current->fd, "\x1b[0K");
320 }
321
322 static void setCursorPos(struct current *current, int x)
323 {
324     fd_printf(current->fd, "\r\x1b[%dC", x);
325 }
326
327 /**
328  * Reads a char from 'fd', waiting at most 'timeout' milliseconds.
329  *
330  * A timeout of -1 means to wait forever.
331  *
332  * Returns -1 if no char is received within the time or an error occurs.
333  */
334 static int fd_read_char(int fd, int timeout)
335 {
336     struct pollfd p;
337     unsigned char c;
338
339     p.fd = fd;
340     p.events = POLLIN;
341
342     if (poll(&p, 1, timeout) == 0) {
343         /* timeout */
344         return -1;
345     }
346     if (read(fd, &c, 1) != 1) {
347         return -1;
348     }
349     return c;
350 }
351
352 /**
353  * Reads a complete utf-8 character
354  * and returns the unicode value, or -1 on error.
355  */
356 static int fd_read(struct current *current)
357 {
358 #ifdef USE_UTF8
359     char buf[4];
360     int n;
361     int i;
362     int c;
363
364     if (read(current->fd, &buf[0], 1) != 1) {
365         return -1;
366     }
367     n = utf8_charlen(buf[0]);
368     if (n < 1 || n > 3) {
369         return -1;
370     }
371     for (i = 1; i < n; i++) {
372         if (read(current->fd, &buf[i], 1) != 1) {
373             return -1;
374         }
375     }
376     buf[n] = 0;
377     /* decode and return the character */
378     utf8_tounicode(buf, &c);
379     return c;
380 #else
381     return fd_read_char(current->fd, -1);
382 #endif
383 }
384
385 static int countColorControlChars(const char* prompt)
386 {
387     /* ANSI color control sequences have the form:
388      * "\x1b" "[" [0-9;]* "m"
389      * We parse them with a simple state machine.
390      */
391
392     enum {
393         search_esc,
394         expect_bracket,
395         expect_trail
396     } state = search_esc;
397     int len = 0, found = 0;
398     char ch;
399
400     /* XXX: Strictly we should be checking utf8 chars rather than
401      *      bytes in case of the extremely unlikely scenario where
402      *      an ANSI sequence is part of a utf8 sequence.
403      */
404     while ((ch = *prompt++) != 0) {
405         switch (state) {
406         case search_esc:
407             if (ch == '\x1b') {
408                 state = expect_bracket;
409             }
410             break;
411         case expect_bracket:
412             if (ch == '[') {
413                 state = expect_trail;
414                 /* 3 for "\e[ ... m" */
415                 len = 3;
416                 break;
417             }
418             state = search_esc;
419             break;
420         case expect_trail:
421             if ((ch == ';') || ((ch >= '0' && ch <= '9'))) {
422                 /* 0-9, or semicolon */
423                 len++;
424                 break;
425             }
426             if (ch == 'm') {
427                 found += len;
428             }
429             state = search_esc;
430             break;
431         }
432     }
433
434     return found;
435 }
436
437 static int getWindowSize(struct current *current)
438 {
439     struct winsize ws;
440
441     if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0) {
442         current->cols = ws.ws_col;
443         return 0;
444     }
445
446     /* Failed to query the window size. Perhaps we are on a serial terminal.
447      * Try to query the width by sending the cursor as far to the right
448      * and reading back the cursor position.
449      * Note that this is only done once per call to linenoise rather than
450      * every time the line is refreshed for efficiency reasons.
451      */
452     if (current->cols == 0) {
453         current->cols = 80;
454
455         /* Move cursor far right and report cursor position, then back to the left */
456         fd_printf(current->fd, "\x1b[999C" "\x1b[6n");
457
458         /* Parse the response: ESC [ rows ; cols R */
459         if (fd_read_char(current->fd, 100) == 0x1b && fd_read_char(current->fd, 100) == '[') {
460             int n = 0;
461             while (1) {
462                 int ch = fd_read_char(current->fd, 100);
463                 if (ch == ';') {
464                     /* Ignore rows */
465                     n = 0;
466                 }
467                 else if (ch == 'R') {
468                     /* Got cols */
469                     if (n != 0 && n < 1000) {
470                         current->cols = n;
471                     }
472                     break;
473                 }
474                 else if (ch >= 0 && ch <= '9') {
475                     n = n * 10 + ch - '0';
476                 }
477                 else {
478                     break;
479                 }
480             }
481         }
482     }
483     return 0;
484 }
485
486 /**
487  * If escape (27) was received, reads subsequent
488  * chars to determine if this is a known special key.
489  *
490  * Returns SPECIAL_NONE if unrecognised, or -1 if EOF.
491  *
492  * If no additional char is received within a short time,
493  * 27 is returned.
494  */
495 static int check_special(int fd)
496 {
497     int c = fd_read_char(fd, 50);
498     int c2;
499
500     if (c < 0) {
501         return 27;
502     }
503
504     c2 = fd_read_char(fd, 50);
505     if (c2 < 0) {
506         return c2;
507     }
508     if (c == '[' || c == 'O') {
509         /* Potential arrow key */
510         switch (c2) {
511             case 'A':
512                 return SPECIAL_UP;
513             case 'B':
514                 return SPECIAL_DOWN;
515             case 'C':
516                 return SPECIAL_RIGHT;
517             case 'D':
518                 return SPECIAL_LEFT;
519             case 'F':
520                 return SPECIAL_END;
521             case 'H':
522                 return SPECIAL_HOME;
523         }
524     }
525     if (c == '[' && c2 >= '1' && c2 <= '8') {
526         /* extended escape */
527         c = fd_read_char(fd, 50);
528         if (c == '~') {
529             switch (c2) {
530                 case '2':
531                     return SPECIAL_INSERT;
532                 case '3':
533                     return SPECIAL_DELETE;
534                 case '5':
535                     return SPECIAL_PAGE_UP;
536                 case '6':
537                     return SPECIAL_PAGE_DOWN;
538                 case '7':
539                     return SPECIAL_HOME;
540                 case '8':
541                     return SPECIAL_END;
542             }
543         }
544         while (c != -1 && c != '~') {
545             /* .e.g \e[12~ or '\e[11;2~   discard the complete sequence */
546             c = fd_read_char(fd, 50);
547         }
548     }
549
550     return SPECIAL_NONE;
551 }
552 #elif defined(USE_WINCONSOLE)
553
554 static DWORD orig_consolemode = 0;
555
556 static int enableRawMode(struct current *current) {
557     DWORD n;
558     INPUT_RECORD irec;
559
560     current->outh = GetStdHandle(STD_OUTPUT_HANDLE);
561     current->inh = GetStdHandle(STD_INPUT_HANDLE);
562
563     if (!PeekConsoleInput(current->inh, &irec, 1, &n)) {
564         return -1;
565     }
566     if (getWindowSize(current) != 0) {
567         return -1;
568     }
569     if (GetConsoleMode(current->inh, &orig_consolemode)) {
570         SetConsoleMode(current->inh, ENABLE_PROCESSED_INPUT);
571     }
572     return 0;
573 }
574
575 static void disableRawMode(struct current *current)
576 {
577     SetConsoleMode(current->inh, orig_consolemode);
578 }
579
580 static void clearScreen(struct current *current)
581 {
582     COORD topleft = { 0, 0 };
583     DWORD n;
584
585     FillConsoleOutputCharacter(current->outh, ' ',
586         current->cols * current->rows, topleft, &n);
587     FillConsoleOutputAttribute(current->outh,
588         FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN,
589         current->cols * current->rows, topleft, &n);
590     SetConsoleCursorPosition(current->outh, topleft);
591 }
592
593 static void cursorToLeft(struct current *current)
594 {
595     COORD pos = { 0, (SHORT)current->y };
596     DWORD n;
597
598     FillConsoleOutputAttribute(current->outh,
599         FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, current->cols, pos, &n);
600     current->x = 0;
601 }
602
603 static int outputChars(struct current *current, const char *buf, int len)
604 {
605     COORD pos = { (SHORT)current->x, (SHORT)current->y };
606     DWORD n;
607
608     WriteConsoleOutputCharacter(current->outh, buf, len, pos, &n);
609     current->x += len;
610     return 0;
611 }
612
613 static void outputControlChar(struct current *current, char ch)
614 {
615     COORD pos = { (SHORT)current->x, (SHORT)current->y };
616     DWORD n;
617
618     FillConsoleOutputAttribute(current->outh, BACKGROUND_INTENSITY, 2, pos, &n);
619     outputChars(current, "^", 1);
620     outputChars(current, &ch, 1);
621 }
622
623 static void eraseEol(struct current *current)
624 {
625     COORD pos = { (SHORT)current->x, (SHORT)current->y };
626     DWORD n;
627
628     FillConsoleOutputCharacter(current->outh, ' ', current->cols - current->x, pos, &n);
629 }
630
631 static void setCursorPos(struct current *current, int x)
632 {
633     COORD pos = { (SHORT)x, (SHORT)current->y };
634
635     SetConsoleCursorPosition(current->outh, pos);
636     current->x = x;
637 }
638
639 static int fd_read(struct current *current)
640 {
641     while (1) {
642         INPUT_RECORD irec;
643         DWORD n;
644         if (WaitForSingleObject(current->inh, INFINITE) != WAIT_OBJECT_0) {
645             break;
646         }
647         if (!ReadConsoleInput (current->inh, &irec, 1, &n)) {
648             break;
649         }
650         if (irec.EventType == KEY_EVENT && irec.Event.KeyEvent.bKeyDown) {
651             KEY_EVENT_RECORD *k = &irec.Event.KeyEvent;
652             if (k->dwControlKeyState & ENHANCED_KEY) {
653                 switch (k->wVirtualKeyCode) {
654                  case VK_LEFT:
655                     return SPECIAL_LEFT;
656                  case VK_RIGHT:
657                     return SPECIAL_RIGHT;
658                  case VK_UP:
659                     return SPECIAL_UP;
660                  case VK_DOWN:
661                     return SPECIAL_DOWN;
662                  case VK_INSERT:
663                     return SPECIAL_INSERT;
664                  case VK_DELETE:
665                     return SPECIAL_DELETE;
666                  case VK_HOME:
667                     return SPECIAL_HOME;
668                  case VK_END:
669                     return SPECIAL_END;
670                  case VK_PRIOR:
671                     return SPECIAL_PAGE_UP;
672                  case VK_NEXT:
673                     return SPECIAL_PAGE_DOWN;
674                 }
675             }
676             /* Note that control characters are already translated in AsciiChar */
677             else {
678 #ifdef USE_UTF8
679                 return k->uChar.UnicodeChar;
680 #else
681                 return k->uChar.AsciiChar;
682 #endif
683             }
684         }
685     }
686     return -1;
687 }
688
689 static int countColorControlChars(const char* prompt)
690 {
691     /* For windows we assume that there are no embedded ansi color
692      * control sequences.
693      */
694     return 0;
695 }
696
697 static int getWindowSize(struct current *current)
698 {
699     CONSOLE_SCREEN_BUFFER_INFO info;
700     if (!GetConsoleScreenBufferInfo(current->outh, &info)) {
701         return -1;
702     }
703     current->cols = info.dwSize.X;
704     current->rows = info.dwSize.Y;
705     if (current->cols <= 0 || current->rows <= 0) {
706         current->cols = 80;
707         return -1;
708     }
709     current->y = info.dwCursorPosition.Y;
710     current->x = info.dwCursorPosition.X;
711     return 0;
712 }
713 #endif
714
715 static int utf8_getchars(char *buf, int c)
716 {
717 #ifdef USE_UTF8
718     return utf8_fromunicode(buf, c);
719 #else
720     *buf = c;
721     return 1;
722 #endif
723 }
724
725 /**
726  * Returns the unicode character at the given offset,
727  * or -1 if none.
728  */
729 static int get_char(struct current *current, int pos)
730 {
731     if (pos >= 0 && pos < current->chars) {
732         int c;
733         int i = utf8_index(current->buf, pos);
734         (void)utf8_tounicode(current->buf + i, &c);
735         return c;
736     }
737     return -1;
738 }
739
740 static void refreshLine(const char *prompt, struct current *current)
741 {
742     int plen;
743     int pchars;
744     int backup = 0;
745     int i;
746     const char *buf = current->buf;
747     int chars = current->chars;
748     int pos = current->pos;
749     int b;
750     int ch;
751     int n;
752
753     /* Should intercept SIGWINCH. For now, just get the size every time */
754     getWindowSize(current);
755
756     plen = strlen(prompt);
757     pchars = utf8_strlen(prompt, plen);
758
759     /* Scan the prompt for embedded ansi color control sequences and
760      * discount them as characters/columns.
761      */
762     pchars -= countColorControlChars(prompt);
763
764     /* Account for a line which is too long to fit in the window.
765      * Note that control chars require an extra column
766      */
767
768     /* How many cols are required to the left of 'pos'?
769      * The prompt, plus one extra for each control char
770      */
771     n = pchars + utf8_strlen(buf, current->len);
772     b = 0;
773     for (i = 0; i < pos; i++) {
774         b += utf8_tounicode(buf + b, &ch);
775         if (ch < ' ') {
776             n++;
777         }
778     }
779
780     /* If too many are needed, strip chars off the front of 'buf'
781      * until it fits. Note that if the current char is a control character,
782      * we need one extra col.
783      */
784     if (current->pos < current->chars && get_char(current, current->pos) < ' ') {
785         n++;
786     }
787
788     while (n >= current->cols && pos > 0) {
789         b = utf8_tounicode(buf, &ch);
790         if (ch < ' ') {
791             n--;
792         }
793         n--;
794         buf += b;
795         pos--;
796         chars--;
797     }
798
799     /* Cursor to left edge, then the prompt */
800     cursorToLeft(current);
801     outputChars(current, prompt, plen);
802
803     /* Now the current buffer content */
804
805     /* Need special handling for control characters.
806      * If we hit 'cols', stop.
807      */
808     b = 0; /* unwritted bytes */
809     n = 0; /* How many control chars were written */
810     for (i = 0; i < chars; i++) {
811         int ch;
812         int w = utf8_tounicode(buf + b, &ch);
813         if (ch < ' ') {
814             n++;
815         }
816         if (pchars + i + n >= current->cols) {
817             break;
818         }
819         if (ch < ' ') {
820             /* A control character, so write the buffer so far */
821             outputChars(current, buf, b);
822             buf += b + w;
823             b = 0;
824             outputControlChar(current, ch + '@');
825             if (i < pos) {
826                 backup++;
827             }
828         }
829         else {
830             b += w;
831         }
832     }
833     outputChars(current, buf, b);
834
835     /* Erase to right, move cursor to original position */
836     eraseEol(current);
837     setCursorPos(current, pos + pchars + backup);
838 }
839
840 static void set_current(struct current *current, const char *str)
841 {
842     strncpy(current->buf, str, current->bufmax);
843     current->buf[current->bufmax - 1] = 0;
844     current->len = strlen(current->buf);
845     current->pos = current->chars = utf8_strlen(current->buf, current->len);
846 }
847
848 static int has_room(struct current *current, int bytes)
849 {
850     return current->len + bytes < current->bufmax - 1;
851 }
852
853 /**
854  * Removes the char at 'pos'.
855  *
856  * Returns 1 if the line needs to be refreshed, 2 if not
857  * and 0 if nothing was removed
858  */
859 static int remove_char(struct current *current, int pos)
860 {
861     if (pos >= 0 && pos < current->chars) {
862         int p1, p2;
863         int ret = 1;
864         p1 = utf8_index(current->buf, pos);
865         p2 = p1 + utf8_index(current->buf + p1, 1);
866
867 #ifdef USE_TERMIOS
868         /* optimise remove char in the case of removing the last char */
869         if (current->pos == pos + 1 && current->pos == current->chars) {
870             if (current->buf[pos] >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) {
871                 ret = 2;
872                 fd_printf(current->fd, "\b \b");
873             }
874         }
875 #endif
876
877         /* Move the null char too */
878         memmove(current->buf + p1, current->buf + p2, current->len - p2 + 1);
879         current->len -= (p2 - p1);
880         current->chars--;
881
882         if (current->pos > pos) {
883             current->pos--;
884         }
885         return ret;
886     }
887     return 0;
888 }
889
890 /**
891  * Insert 'ch' at position 'pos'
892  *
893  * Returns 1 if the line needs to be refreshed, 2 if not
894  * and 0 if nothing was inserted (no room)
895  */
896 static int insert_char(struct current *current, int pos, int ch)
897 {
898     char buf[3];
899     int n = utf8_getchars(buf, ch);
900
901     if (has_room(current, n) && pos >= 0 && pos <= current->chars) {
902         int p1, p2;
903         int ret = 1;
904         p1 = utf8_index(current->buf, pos);
905         p2 = p1 + n;
906
907 #ifdef USE_TERMIOS
908         /* optimise the case where adding a single char to the end and no scrolling is needed */
909         if (current->pos == pos && current->chars == pos) {
910             if (ch >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) {
911                 IGNORE_RC(write(current->fd, buf, n));
912                 ret = 2;
913             }
914         }
915 #endif
916
917         memmove(current->buf + p2, current->buf + p1, current->len - p1);
918         memcpy(current->buf + p1, buf, n);
919         current->len += n;
920
921         current->chars++;
922         if (current->pos >= pos) {
923             current->pos++;
924         }
925         return ret;
926     }
927     return 0;
928 }
929
930 /**
931  * Captures up to 'n' characters starting at 'pos' for the cut buffer.
932  *
933  * This replaces any existing characters in the cut buffer.
934  */
935 static void capture_chars(struct current *current, int pos, int n)
936 {
937     if (pos >= 0 && (pos + n - 1) < current->chars) {
938         int p1 = utf8_index(current->buf, pos);
939         int nbytes = utf8_index(current->buf + p1, n);
940
941         if (nbytes) {
942             free(current->capture);
943             /* Include space for the null terminator */
944             current->capture = (char *)malloc(nbytes + 1);
945             memcpy(current->capture, current->buf + p1, nbytes);
946             current->capture[nbytes] = '\0';
947         }
948     }
949 }
950
951 /**
952  * Removes up to 'n' characters at cursor position 'pos'.
953  *
954  * Returns 0 if no chars were removed or non-zero otherwise.
955  */
956 static int remove_chars(struct current *current, int pos, int n)
957 {
958     int removed = 0;
959
960     /* First save any chars which will be removed */
961     capture_chars(current, pos, n);
962
963     while (n-- && remove_char(current, pos)) {
964         removed++;
965     }
966     return removed;
967 }
968 /**
969  * Inserts the characters (string) 'chars' at the cursor position 'pos'.
970  *
971  * Returns 0 if no chars were inserted or non-zero otherwise.
972  */
973 static int insert_chars(struct current *current, int pos, const char *chars)
974 {
975     int inserted = 0;
976
977     while (*chars) {
978         int ch;
979         int n = utf8_tounicode(chars, &ch);
980         if (insert_char(current, pos, ch) == 0) {
981             break;
982         }
983         inserted++;
984         pos++;
985         chars += n;
986     }
987     return inserted;
988 }
989
990 #ifndef NO_COMPLETION
991 static linenoiseCompletionCallback *completionCallback = NULL;
992
993 static void beep() {
994 #ifdef USE_TERMIOS
995     fprintf(stderr, "\x7");
996     fflush(stderr);
997 #endif
998 }
999
1000 static void freeCompletions(linenoiseCompletions *lc) {
1001     size_t i;
1002     for (i = 0; i < lc->len; i++)
1003         free(lc->cvec[i]);
1004     free(lc->cvec);
1005 }
1006
1007 static int completeLine(struct current *current) {
1008     linenoiseCompletions lc = { 0, NULL };
1009     int c = 0;
1010
1011     completionCallback(current->buf,&lc);
1012     if (lc.len == 0) {
1013         beep();
1014     } else {
1015         size_t stop = 0, i = 0;
1016
1017         while(!stop) {
1018             /* Show completion or original buffer */
1019             if (i < lc.len) {
1020                 struct current tmp = *current;
1021                 tmp.buf = lc.cvec[i];
1022                 tmp.pos = tmp.len = strlen(tmp.buf);
1023                 tmp.chars = utf8_strlen(tmp.buf, tmp.len);
1024                 refreshLine(current->prompt, &tmp);
1025             } else {
1026                 refreshLine(current->prompt, current);
1027             }
1028
1029             c = fd_read(current);
1030             if (c == -1) {
1031                 break;
1032             }
1033
1034             switch(c) {
1035                 case '\t': /* tab */
1036                     i = (i+1) % (lc.len+1);
1037                     if (i == lc.len) beep();
1038                     break;
1039                 case 27: /* escape */
1040                     /* Re-show original buffer */
1041                     if (i < lc.len) {
1042                         refreshLine(current->prompt, current);
1043                     }
1044                     stop = 1;
1045                     break;
1046                 default:
1047                     /* Update buffer and return */
1048                     if (i < lc.len) {
1049                         set_current(current,lc.cvec[i]);
1050                     }
1051                     stop = 1;
1052                     break;
1053             }
1054         }
1055     }
1056
1057     freeCompletions(&lc);
1058     return c; /* Return last read character */
1059 }
1060
1061 /* Register a callback function to be called for tab-completion. */
1062 void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
1063     completionCallback = fn;
1064 }
1065
1066 void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
1067     lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1));
1068     lc->cvec[lc->len++] = strdup(str);
1069 }
1070
1071 #endif
1072
1073 static int linenoiseEdit(struct current *current) {
1074     int history_index = 0;
1075
1076     /* The latest history entry is always our current buffer, that
1077      * initially is just an empty string. */
1078     linenoiseHistoryAdd("");
1079
1080     set_current(current, "");
1081     refreshLine(current->prompt, current);
1082
1083     while(1) {
1084         int dir = -1;
1085         int c = fd_read(current);
1086
1087 #ifndef NO_COMPLETION
1088         /* Only autocomplete when the callback is set. It returns < 0 when
1089          * there was an error reading from fd. Otherwise it will return the
1090          * character that should be handled next. */
1091         if (c == '\t' && current->pos == current->chars && completionCallback != NULL) {
1092             c = completeLine(current);
1093             /* Return on errors */
1094             if (c < 0) return current->len;
1095             /* Read next character when 0 */
1096             if (c == 0) continue;
1097         }
1098 #endif
1099
1100 process_char:
1101         if (c == -1) return current->len;
1102 #ifdef USE_TERMIOS
1103         if (c == 27) {   /* escape sequence */
1104             c = check_special(current->fd);
1105         }
1106 #endif
1107         switch(c) {
1108         case '\r':    /* enter */
1109             history_len--;
1110             free(history[history_len]);
1111             return current->len;
1112         case ctrl('C'):     /* ctrl-c */
1113             errno = EAGAIN;
1114             return -1;
1115         case 127:   /* backspace */
1116         case ctrl('H'):
1117             if (remove_char(current, current->pos - 1) == 1) {
1118                 refreshLine(current->prompt, current);
1119             }
1120             break;
1121         case ctrl('D'):     /* ctrl-d */
1122             if (current->len == 0) {
1123                 /* Empty line, so EOF */
1124                 history_len--;
1125                 free(history[history_len]);
1126                 return -1;
1127             }
1128             /* Otherwise fall through to delete char to right of cursor */
1129         case SPECIAL_DELETE:
1130             if (remove_char(current, current->pos) == 1) {
1131                 refreshLine(current->prompt, current);
1132             }
1133             break;
1134         case SPECIAL_INSERT:
1135             /* Ignore. Expansion Hook.
1136              * Future possibility: Toggle Insert/Overwrite Modes
1137              */
1138             break;
1139         case ctrl('W'):    /* ctrl-w, delete word at left. save deleted chars */
1140             /* eat any spaces on the left */
1141             {
1142                 int pos = current->pos;
1143                 while (pos > 0 && get_char(current, pos - 1) == ' ') {
1144                     pos--;
1145                 }
1146
1147                 /* now eat any non-spaces on the left */
1148                 while (pos > 0 && get_char(current, pos - 1) != ' ') {
1149                     pos--;
1150                 }
1151
1152                 if (remove_chars(current, pos, current->pos - pos)) {
1153                     refreshLine(current->prompt, current);
1154                 }
1155             }
1156             break;
1157         case ctrl('R'):    /* ctrl-r */
1158             {
1159                 /* Display the reverse-i-search prompt and process chars */
1160                 char rbuf[50];
1161                 char rprompt[80];
1162                 int rchars = 0;
1163                 int rlen = 0;
1164                 int searchpos = history_len - 1;
1165
1166                 rbuf[0] = 0;
1167                 while (1) {
1168                     int n = 0;
1169                     const char *p = NULL;
1170                     int skipsame = 0;
1171                     int searchdir = -1;
1172
1173                     snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf);
1174                     refreshLine(rprompt, current);
1175                     c = fd_read(current);
1176                     if (c == ctrl('H') || c == 127) {
1177                         if (rchars) {
1178                             int p = utf8_index(rbuf, --rchars);
1179                             rbuf[p] = 0;
1180                             rlen = strlen(rbuf);
1181                         }
1182                         continue;
1183                     }
1184 #ifdef USE_TERMIOS
1185                     if (c == 27) {
1186                         c = check_special(current->fd);
1187                     }
1188 #endif
1189                     if (c == ctrl('P') || c == SPECIAL_UP) {
1190                         /* Search for the previous (earlier) match */
1191                         if (searchpos > 0) {
1192                             searchpos--;
1193                         }
1194                         skipsame = 1;
1195                     }
1196                     else if (c == ctrl('N') || c == SPECIAL_DOWN) {
1197                         /* Search for the next (later) match */
1198                         if (searchpos < history_len) {
1199                             searchpos++;
1200                         }
1201                         searchdir = 1;
1202                         skipsame = 1;
1203                     }
1204                     else if (c >= ' ') {
1205                         if (rlen >= (int)sizeof(rbuf) + 3) {
1206                             continue;
1207                         }
1208
1209                         n = utf8_getchars(rbuf + rlen, c);
1210                         rlen += n;
1211                         rchars++;
1212                         rbuf[rlen] = 0;
1213
1214                         /* Adding a new char resets the search location */
1215                         searchpos = history_len - 1;
1216                     }
1217                     else {
1218                         /* Exit from incremental search mode */
1219                         break;
1220                     }
1221
1222                     /* Now search through the history for a match */
1223                     for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) {
1224                         p = strstr(history[searchpos], rbuf);
1225                         if (p) {
1226                             /* Found a match */
1227                             if (skipsame && strcmp(history[searchpos], current->buf) == 0) {
1228                                 /* But it is identical, so skip it */
1229                                 continue;
1230                             }
1231                             /* Copy the matching line and set the cursor position */
1232                             set_current(current,history[searchpos]);
1233                             current->pos = utf8_strlen(history[searchpos], p - history[searchpos]);
1234                             break;
1235                         }
1236                     }
1237                     if (!p && n) {
1238                         /* No match, so don't add it */
1239                         rchars--;
1240                         rlen -= n;
1241                         rbuf[rlen] = 0;
1242                     }
1243                 }
1244                 if (c == ctrl('G') || c == ctrl('C')) {
1245                     /* ctrl-g terminates the search with no effect */
1246                     set_current(current, "");
1247                     c = 0;
1248                 }
1249                 else if (c == ctrl('J')) {
1250                     /* ctrl-j terminates the search leaving the buffer in place */
1251                     c = 0;
1252                 }
1253                 /* Go process the char normally */
1254                 refreshLine(current->prompt, current);
1255                 goto process_char;
1256             }
1257             break;
1258         case ctrl('T'):    /* ctrl-t */
1259             if (current->pos > 0 && current->pos <= current->chars) {
1260                 /* If cursor is at end, transpose the previous two chars */
1261                 int fixer = (current->pos == current->chars);
1262                 c = get_char(current, current->pos - fixer);
1263                 remove_char(current, current->pos - fixer);
1264                 insert_char(current, current->pos - 1, c);
1265                 refreshLine(current->prompt, current);
1266             }
1267             break;
1268         case ctrl('V'):    /* ctrl-v */
1269             if (has_room(current, 3)) {
1270                 /* Insert the ^V first */
1271                 if (insert_char(current, current->pos, c)) {
1272                     refreshLine(current->prompt, current);
1273                     /* Now wait for the next char. Can insert anything except \0 */
1274                     c = fd_read(current);
1275
1276                     /* Remove the ^V first */
1277                     remove_char(current, current->pos - 1);
1278                     if (c != -1) {
1279                         /* Insert the actual char */
1280                         insert_char(current, current->pos, c);
1281                     }
1282                     refreshLine(current->prompt, current);
1283                 }
1284             }
1285             break;
1286         case ctrl('B'):
1287         case SPECIAL_LEFT:
1288             if (current->pos > 0) {
1289                 current->pos--;
1290                 refreshLine(current->prompt, current);
1291             }
1292             break;
1293         case ctrl('F'):
1294         case SPECIAL_RIGHT:
1295             if (current->pos < current->chars) {
1296                 current->pos++;
1297                 refreshLine(current->prompt, current);
1298             }
1299             break;
1300         case SPECIAL_PAGE_UP:
1301           dir = history_len - history_index - 1; /* move to start of history */
1302           goto history_navigation;
1303         case SPECIAL_PAGE_DOWN:
1304           dir = -history_index; /* move to 0 == end of history, i.e. current */
1305           goto history_navigation;
1306         case ctrl('P'):
1307         case SPECIAL_UP:
1308             dir = 1;
1309           goto history_navigation;
1310         case ctrl('N'):
1311         case SPECIAL_DOWN:
1312 history_navigation:
1313             if (history_len > 1) {
1314                 /* Update the current history entry before to
1315                  * overwrite it with tne next one. */
1316                 free(history[history_len - 1 - history_index]);
1317                 history[history_len - 1 - history_index] = strdup(current->buf);
1318                 /* Show the new entry */
1319                 history_index += dir;
1320                 if (history_index < 0) {
1321                     history_index = 0;
1322                     break;
1323                 } else if (history_index >= history_len) {
1324                     history_index = history_len - 1;
1325                     break;
1326                 }
1327                 set_current(current, history[history_len - 1 - history_index]);
1328                 refreshLine(current->prompt, current);
1329             }
1330             break;
1331         case ctrl('A'): /* Ctrl+a, go to the start of the line */
1332         case SPECIAL_HOME:
1333             current->pos = 0;
1334             refreshLine(current->prompt, current);
1335             break;
1336         case ctrl('E'): /* ctrl+e, go to the end of the line */
1337         case SPECIAL_END:
1338             current->pos = current->chars;
1339             refreshLine(current->prompt, current);
1340             break;
1341         case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */
1342             if (remove_chars(current, 0, current->pos)) {
1343                 refreshLine(current->prompt, current);
1344             }
1345             break;
1346         case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */
1347             if (remove_chars(current, current->pos, current->chars - current->pos)) {
1348                 refreshLine(current->prompt, current);
1349             }
1350             break;
1351         case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */
1352             if (current->capture && insert_chars(current, current->pos, current->capture)) {
1353                 refreshLine(current->prompt, current);
1354             }
1355             break;
1356         case ctrl('L'): /* Ctrl+L, clear screen */
1357             clearScreen(current);
1358             /* Force recalc of window size for serial terminals */
1359             current->cols = 0;
1360             refreshLine(current->prompt, current);
1361             break;
1362         default:
1363             /* Only tab is allowed without ^V */
1364             if (c == '\t' || c >= ' ') {
1365                 if (insert_char(current, current->pos, c) == 1) {
1366                     refreshLine(current->prompt, current);
1367                 }
1368             }
1369             break;
1370         }
1371     }
1372     return current->len;
1373 }
1374
1375 int linenoiseColumns(void)
1376 {
1377     struct current current;
1378     enableRawMode (&current);
1379     getWindowSize (&current);
1380     disableRawMode (&current);
1381     return current.cols;
1382 }
1383
1384 char *linenoise(const char *prompt)
1385 {
1386     int count;
1387     struct current current;
1388     char buf[LINENOISE_MAX_LINE];
1389
1390     if (enableRawMode(&current) == -1) {
1391         printf("%s", prompt);
1392         fflush(stdout);
1393         if (fgets(buf, sizeof(buf), stdin) == NULL) {
1394             return NULL;
1395         }
1396         count = strlen(buf);
1397         if (count && buf[count-1] == '\n') {
1398             count--;
1399             buf[count] = '\0';
1400         }
1401     }
1402     else
1403     {
1404         current.buf = buf;
1405         current.bufmax = sizeof(buf);
1406         current.len = 0;
1407         current.chars = 0;
1408         current.pos = 0;
1409         current.prompt = prompt;
1410         current.capture = NULL;
1411
1412         count = linenoiseEdit(&current);
1413
1414         disableRawMode(&current);
1415         printf("\n");
1416
1417         free(current.capture);
1418         if (count == -1) {
1419             return NULL;
1420         }
1421     }
1422     return strdup(buf);
1423 }
1424
1425 /* Using a circular buffer is smarter, but a bit more complex to handle. */
1426 int linenoiseHistoryAdd(const char *line) {
1427     char *linecopy;
1428
1429     if (history_max_len == 0) return 0;
1430     if (history == NULL) {
1431         history = (char **)malloc(sizeof(char*)*history_max_len);
1432         if (history == NULL) return 0;
1433         memset(history,0,(sizeof(char*)*history_max_len));
1434     }
1435
1436     /* do not insert duplicate lines into history */
1437     if (history_len > 0 && strcmp(line, history[history_len - 1]) == 0) {
1438         return 0;
1439     }
1440
1441     linecopy = strdup(line);
1442     if (!linecopy) return 0;
1443     if (history_len == history_max_len) {
1444         free(history[0]);
1445         memmove(history,history+1,sizeof(char*)*(history_max_len-1));
1446         history_len--;
1447     }
1448     history[history_len] = linecopy;
1449     history_len++;
1450     return 1;
1451 }
1452
1453 int linenoiseHistoryGetMaxLen(void) {
1454     return history_max_len;
1455 }
1456
1457 int linenoiseHistorySetMaxLen(int len) {
1458     char **newHistory;
1459
1460     if (len < 1) return 0;
1461     if (history) {
1462         int tocopy = history_len;
1463
1464         newHistory = (char **)malloc(sizeof(char*)*len);
1465         if (newHistory == NULL) return 0;
1466
1467         /* If we can't copy everything, free the elements we'll not use. */
1468         if (len < tocopy) {
1469             int j;
1470
1471             for (j = 0; j < tocopy-len; j++) free(history[j]);
1472             tocopy = len;
1473         }
1474         memset(newHistory,0,sizeof(char*)*len);
1475         memcpy(newHistory,history+(history_len-tocopy), sizeof(char*)*tocopy);
1476         free(history);
1477         history = newHistory;
1478     }
1479     history_max_len = len;
1480     if (history_len > history_max_len)
1481         history_len = history_max_len;
1482     return 1;
1483 }
1484
1485 /* Save the history in the specified file. On success 0 is returned
1486  * otherwise -1 is returned. */
1487 int linenoiseHistorySave(const char *filename) {
1488     FILE *fp = fopen(filename,"w");
1489     int j;
1490
1491     if (fp == NULL) return -1;
1492     for (j = 0; j < history_len; j++) {
1493         const char *str = history[j];
1494         /* Need to encode backslash, nl and cr */
1495         while (*str) {
1496             if (*str == '\\') {
1497                 fputs("\\\\", fp);
1498             }
1499             else if (*str == '\n') {
1500                 fputs("\\n", fp);
1501             }
1502             else if (*str == '\r') {
1503                 fputs("\\r", fp);
1504             }
1505             else {
1506                 fputc(*str, fp);
1507             }
1508             str++;
1509         }
1510         fputc('\n', fp);
1511     }
1512
1513     fclose(fp);
1514     return 0;
1515 }
1516
1517 /* Load the history from the specified file. If the file does not exist
1518  * zero is returned and no operation is performed.
1519  *
1520  * If the file exists and the operation succeeded 0 is returned, otherwise
1521  * on error -1 is returned. */
1522 int linenoiseHistoryLoad(const char *filename) {
1523     FILE *fp = fopen(filename,"r");
1524     char buf[LINENOISE_MAX_LINE];
1525
1526     if (fp == NULL) return -1;
1527
1528     while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {
1529         char *src, *dest;
1530
1531         /* Decode backslash escaped values */
1532         for (src = dest = buf; *src; src++) {
1533             char ch = *src;
1534
1535             if (ch == '\\') {
1536                 src++;
1537                 if (*src == 'n') {
1538                     ch = '\n';
1539                 }
1540                 else if (*src == 'r') {
1541                     ch = '\r';
1542                 } else {
1543                     ch = *src;
1544                 }
1545             }
1546             *dest++ = ch;
1547         }
1548         /* Remove trailing newline */
1549         if (dest != buf && (dest[-1] == '\n' || dest[-1] == '\r')) {
1550             dest--;
1551         }
1552         *dest = 0;
1553
1554         linenoiseHistoryAdd(buf);
1555     }
1556     fclose(fp);
1557     return 0;
1558 }
1559
1560 /* Provide access to the history buffer.
1561  *
1562  * If 'len' is not NULL, the length is stored in *len.
1563  */
1564 char **linenoiseHistory(int *len) {
1565     if (len) {
1566         *len = history_len;
1567     }
1568     return history;
1569 }