]> git.lizzy.rs Git - linenoise.git/blob - linenoise.c
Guard inclusion of stringbuf.h
[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 [ 0 K
61  *    Effect: clear from cursor to end of line
62  *
63  * CUF (CUrsor Forward)
64  *    Sequence: ESC [ n C
65  *    Effect: moves cursor forward n chars
66  *
67  * CR (Carriage Return)
68  *    Sequence: \r
69  *    Effect: moves cursor to column 1
70  *
71  * The following are used to clear the screen: ESC [ H ESC [ 2 J
72  * This is actually composed of two sequences:
73  *
74  * cursorhome
75  *    Sequence: ESC [ H
76  *    Effect: moves the cursor to upper left corner
77  *
78  * ED2 (Clear entire screen)
79  *    Sequence: ESC [ 2 J
80  *    Effect: clear the whole screen
81  *
82  * == For highlighting control characters, we also use the following two ==
83  * SO (enter StandOut)
84  *    Sequence: ESC [ 7 m
85  *    Effect: Uses some standout mode such as reverse video
86  *
87  * SE (Standout End)
88  *    Sequence: ESC [ 0 m
89  *    Effect: Exit standout mode
90  *
91  * == Only used if TIOCGWINSZ fails ==
92  * DSR/CPR (Report cursor position)
93  *    Sequence: ESC [ 6 n
94  *    Effect: reports current cursor position as ESC [ NNN ; MMM R
95  *
96  * == Only used in multiline mode ==
97  * CUU (Cursor Up)
98  *    Sequence: ESC [ n A
99  *    Effect: moves cursor up n chars.
100  *
101  * CUD (Cursor Down)
102  *    Sequence: ESC [ n B
103  *    Effect: moves cursor down n chars.
104  *
105  * win32/console
106  * -------------
107  * If __MINGW32__ is defined, the win32 console API is used.
108  * This could probably be made to work for the msvc compiler too.
109  * This support based in part on work by Jon Griffiths.
110  */
111
112 #ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */
113 #include <windows.h>
114 #include <fcntl.h>
115 #define USE_WINCONSOLE
116 #ifdef __MINGW32__
117 #define HAVE_UNISTD_H
118 #else
119 /* Microsoft headers don't like old POSIX names */
120 #define strdup _strdup
121 #define snprintf _snprintf
122 #endif
123 #else
124 #include <termios.h>
125 #include <sys/ioctl.h>
126 #include <poll.h>
127 #define USE_TERMIOS
128 #define HAVE_UNISTD_H
129 #endif
130
131 #ifdef HAVE_UNISTD_H
132 #include <unistd.h>
133 #endif
134 #include <stdlib.h>
135 #include <stdarg.h>
136 #include <stdio.h>
137 #include <assert.h>
138 #include <errno.h>
139 #include <string.h>
140 #include <signal.h>
141 #include <stdlib.h>
142 #include <sys/types.h>
143
144 #include "linenoise.h"
145 #ifndef STRINGBUF_H
146 #include "stringbuf.h"
147 #endif
148 #include "utf8.h"
149
150 #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
151
152 #define ctrl(C) ((C) - '@')
153
154 /* Use -ve numbers here to co-exist with normal unicode chars */
155 enum {
156     SPECIAL_NONE,
157     /* don't use -1 here since that indicates error */
158     SPECIAL_UP = -20,
159     SPECIAL_DOWN = -21,
160     SPECIAL_LEFT = -22,
161     SPECIAL_RIGHT = -23,
162     SPECIAL_DELETE = -24,
163     SPECIAL_HOME = -25,
164     SPECIAL_END = -26,
165     SPECIAL_INSERT = -27,
166     SPECIAL_PAGE_UP = -28,
167     SPECIAL_PAGE_DOWN = -29,
168
169     /* Some handy names for other special keycodes */
170     CHAR_ESCAPE = 27,
171     CHAR_DELETE = 127,
172 };
173
174 static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
175 static int history_len = 0;
176 static char **history = NULL;
177
178 /* Structure to contain the status of the current (being edited) line */
179 struct current {
180     stringbuf *buf; /* Current buffer. Always null terminated */
181     int pos;    /* Cursor position, measured in chars */
182     int cols;   /* Size of the window, in chars */
183     int nrows;  /* How many rows are being used in multiline mode (>= 1) */
184     int rpos;   /* The current row containing the cursor - multiline mode only */
185     const char *prompt;
186     stringbuf *capture; /* capture buffer, or NULL for none. Always null terminated */
187     stringbuf *output;  /* used only during refreshLine() - output accumulator */
188 #if defined(USE_TERMIOS)
189     int fd;     /* Terminal fd */
190 #elif defined(USE_WINCONSOLE)
191     HANDLE outh; /* Console output handle */
192     HANDLE inh; /* Console input handle */
193     int rows;   /* Screen rows */
194     int x;      /* Current column during output */
195     int y;      /* Current row */
196 #ifdef USE_UTF8
197     #define UBUF_MAX_CHARS 132
198     WORD ubuf[UBUF_MAX_CHARS + 1];  /* Accumulates utf16 output - one extra for final surrogate pairs */
199     int ubuflen;      /* length used in ubuf */
200     int ubufcols;     /* how many columns are represented by the chars in ubuf? */
201 #endif
202 #endif
203 };
204
205 static int fd_read(struct current *current);
206 static int getWindowSize(struct current *current);
207 static void cursorDown(struct current *current, int n);
208 static void cursorUp(struct current *current, int n);
209 static void eraseEol(struct current *current);
210 static void refreshLine(struct current *current);
211 static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos);
212 static void setCursorPos(struct current *current, int x);
213 static void setOutputHighlight(struct current *current, const int *props, int nprops);
214 static void set_current(struct current *current, const char *str);
215
216 void linenoiseHistoryFree(void) {
217     if (history) {
218         int j;
219
220         for (j = 0; j < history_len; j++)
221             free(history[j]);
222         free(history);
223         history = NULL;
224         history_len = 0;
225     }
226 }
227
228 struct esc_parser {
229     enum {
230         EP_START,   /* looking for ESC */
231         EP_ESC,     /* looking for [ */
232         EP_DIGITS,  /* parsing digits */
233         EP_PROPS,   /* parsing digits or semicolons */
234         EP_END,     /* ok */
235         EP_ERROR,   /* error */
236     } state;
237     int props[5];   /* properties are stored here */
238     int maxprops;   /* size of the props[] array */
239     int numprops;   /* number of properties found */
240     int termchar;   /* terminator char, or 0 for any alpha */
241     int current;    /* current (partial) property value */
242 };
243
244 /**
245  * Initialise the escape sequence parser at *parser.
246  *
247  * If termchar is 0 any alpha char terminates ok. Otherwise only the given
248  * char terminates successfully.
249  * Run the parser state machine with calls to parseEscapeSequence() for each char.
250  */
251 static void initParseEscapeSeq(struct esc_parser *parser, int termchar)
252 {
253     parser->state = EP_START;
254     parser->maxprops = sizeof(parser->props) / sizeof(*parser->props);
255     parser->numprops = 0;
256     parser->current = 0;
257     parser->termchar = termchar;
258 }
259
260 /**
261  * Pass character 'ch' into the state machine to parse:
262  *   'ESC' '[' <digits> (';' <digits>)* <termchar>
263  *
264  * The first character must be ESC.
265  * Returns the current state. The state machine is done when it returns either EP_END
266  * or EP_ERROR.
267  *
268  * On EP_END, the "property/attribute" values can be read from parser->props[]
269  * of length parser->numprops.
270  */
271 static int parseEscapeSequence(struct esc_parser *parser, int ch)
272 {
273     switch (parser->state) {
274         case EP_START:
275             parser->state = (ch == '\x1b') ? EP_ESC : EP_ERROR;
276             break;
277         case EP_ESC:
278             parser->state = (ch == '[') ? EP_DIGITS : EP_ERROR;
279             break;
280         case EP_PROPS:
281             if (ch == ';') {
282                 parser->state = EP_DIGITS;
283 donedigits:
284                 if (parser->numprops + 1 < parser->maxprops) {
285                     parser->props[parser->numprops++] = parser->current;
286                     parser->current = 0;
287                 }
288                 break;
289             }
290             /* fall through */
291         case EP_DIGITS:
292             if (ch >= '0' && ch <= '9') {
293                 parser->current = parser->current * 10 + (ch - '0');
294                 parser->state = EP_PROPS;
295                 break;
296             }
297             /* must be terminator */
298             if (parser->termchar != ch) {
299                 if (parser->termchar != 0 || !((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))) {
300                     parser->state = EP_ERROR;
301                     break;
302                 }
303             }
304             parser->state = EP_END;
305             goto donedigits;
306         case EP_END:
307             parser->state = EP_ERROR;
308             break;
309         case EP_ERROR:
310             break;
311     }
312     return parser->state;
313 }
314
315 /*#define DEBUG_REFRESHLINE*/
316
317 #ifdef DEBUG_REFRESHLINE
318 #define DRL(ARGS...) fprintf(dfh, ARGS)
319 static FILE *dfh;
320
321 static void DRL_CHAR(int ch)
322 {
323     if (ch < ' ') {
324         DRL("^%c", ch + '@');
325     }
326     else if (ch > 127) {
327         DRL("\\u%04x", ch);
328     }
329     else {
330         DRL("%c", ch);
331     }
332 }
333 static void DRL_STR(const char *str)
334 {
335     while (*str) {
336         int ch;
337         int n = utf8_tounicode(str, &ch);
338         str += n;
339         DRL_CHAR(ch);
340     }
341 }
342 #else
343 #define DRL(ARGS...)
344 #define DRL_CHAR(ch)
345 #define DRL_STR(str)
346 #endif
347
348 #if defined(USE_WINCONSOLE)
349 #include "linenoise-win32.c"
350 #endif
351
352 #if defined(USE_TERMIOS)
353 static void linenoiseAtExit(void);
354 static struct termios orig_termios; /* in order to restore at exit */
355 static int rawmode = 0; /* for atexit() function to check if restore is needed*/
356 static int atexit_registered = 0; /* register atexit just 1 time */
357
358 static const char *unsupported_term[] = {"dumb","cons25","emacs",NULL};
359
360 static int isUnsupportedTerm(void) {
361     char *term = getenv("TERM");
362
363     if (term) {
364         int j;
365         for (j = 0; unsupported_term[j]; j++) {
366             if (strcmp(term, unsupported_term[j]) == 0) {
367                 return 1;
368             }
369         }
370     }
371     return 0;
372 }
373
374 static int enableRawMode(struct current *current) {
375     struct termios raw;
376
377     current->fd = STDIN_FILENO;
378     current->cols = 0;
379
380     if (!isatty(current->fd) || isUnsupportedTerm() ||
381         tcgetattr(current->fd, &orig_termios) == -1) {
382 fatal:
383         errno = ENOTTY;
384         return -1;
385     }
386
387     if (!atexit_registered) {
388         atexit(linenoiseAtExit);
389         atexit_registered = 1;
390     }
391
392     raw = orig_termios;  /* modify the original mode */
393     /* input modes: no break, no CR to NL, no parity check, no strip char,
394      * no start/stop output control. */
395     raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
396     /* output modes - actually, no need to disable post processing */
397     /*raw.c_oflag &= ~(OPOST);*/
398     /* control modes - set 8 bit chars */
399     raw.c_cflag |= (CS8);
400     /* local modes - choing off, canonical off, no extended functions,
401      * no signal chars (^Z,^C) */
402     raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
403     /* control chars - set return condition: min number of bytes and timer.
404      * We want read to return every single byte, without timeout. */
405     raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
406
407     /* put terminal in raw mode after flushing */
408     if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) {
409         goto fatal;
410     }
411     rawmode = 1;
412     return 0;
413 }
414
415 static void disableRawMode(struct current *current) {
416     /* Don't even check the return value as it's too late. */
417     if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1)
418         rawmode = 0;
419 }
420
421 /* At exit we'll try to fix the terminal to the initial conditions. */
422 static void linenoiseAtExit(void) {
423     if (rawmode) {
424         tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios);
425     }
426     linenoiseHistoryFree();
427 }
428
429 /* gcc/glibc insists that we care about the return code of write!
430  * Clarification: This means that a void-cast like "(void) (EXPR)"
431  * does not work.
432  */
433 #define IGNORE_RC(EXPR) if (EXPR) {}
434
435 /**
436  * Output bytes directly, or accumulate output (if current->output is set)
437  */
438 static void outputChars(struct current *current, const char *buf, int len)
439 {
440     if (len < 0) {
441         len = strlen(buf);
442     }
443     if (current->output) {
444         sb_append_len(current->output, buf, len);
445     }
446     else {
447         IGNORE_RC(write(current->fd, buf, len));
448     }
449 }
450
451 /* Like outputChars, but using printf-style formatting
452  */
453 static void outputFormatted(struct current *current, const char *format, ...)
454 {
455     va_list args;
456     char buf[64];
457     int n;
458
459     va_start(args, format);
460     n = vsnprintf(buf, sizeof(buf), format, args);
461     /* This will never happen because we are sure to use outputFormatted() only for short sequences */
462     assert(n < (int)sizeof(buf));
463     va_end(args);
464     outputChars(current, buf, n);
465 }
466
467 static void cursorToLeft(struct current *current)
468 {
469     outputChars(current, "\r", -1);
470 }
471
472 static void setOutputHighlight(struct current *current, const int *props, int nprops)
473 {
474     outputChars(current, "\x1b[", -1);
475     while (nprops--) {
476         outputFormatted(current, "%d%c", *props, (nprops == 0) ? 'm' : ';');
477         props++;
478     }
479 }
480
481 static void eraseEol(struct current *current)
482 {
483     outputChars(current, "\x1b[0K", -1);
484 }
485
486 static void setCursorPos(struct current *current, int x)
487 {
488     if (x == 0) {
489         cursorToLeft(current);
490     }
491     else {
492         outputFormatted(current, "\r\x1b[%dC", x);
493     }
494 }
495
496 static void cursorUp(struct current *current, int n)
497 {
498     if (n) {
499         outputFormatted(current, "\x1b[%dA", n);
500     }
501 }
502
503 static void cursorDown(struct current *current, int n)
504 {
505     if (n) {
506         outputFormatted(current, "\x1b[%dB", n);
507     }
508 }
509
510 void linenoiseClearScreen(void)
511 {
512     write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7);
513 }
514
515 /**
516  * Reads a char from 'fd', waiting at most 'timeout' milliseconds.
517  *
518  * A timeout of -1 means to wait forever.
519  *
520  * Returns -1 if no char is received within the time or an error occurs.
521  */
522 static int fd_read_char(int fd, int timeout)
523 {
524     struct pollfd p;
525     unsigned char c;
526
527     p.fd = fd;
528     p.events = POLLIN;
529
530     if (poll(&p, 1, timeout) == 0) {
531         /* timeout */
532         return -1;
533     }
534     if (read(fd, &c, 1) != 1) {
535         return -1;
536     }
537     return c;
538 }
539
540 /**
541  * Reads a complete utf-8 character
542  * and returns the unicode value, or -1 on error.
543  */
544 static int fd_read(struct current *current)
545 {
546 #ifdef USE_UTF8
547     char buf[MAX_UTF8_LEN];
548     int n;
549     int i;
550     int c;
551
552     if (read(current->fd, &buf[0], 1) != 1) {
553         return -1;
554     }
555     n = utf8_charlen(buf[0]);
556     if (n < 1) {
557         return -1;
558     }
559     for (i = 1; i < n; i++) {
560         if (read(current->fd, &buf[i], 1) != 1) {
561             return -1;
562         }
563     }
564     /* decode and return the character */
565     utf8_tounicode(buf, &c);
566     return c;
567 #else
568     return fd_read_char(current->fd, -1);
569 #endif
570 }
571
572
573 /**
574  * Stores the current cursor column in '*cols'.
575  * Returns 1 if OK, or 0 if failed to determine cursor pos.
576  */
577 static int queryCursor(struct current *current, int* cols)
578 {
579     struct esc_parser parser;
580     int ch;
581
582     /* Should not be buffering this output, it needs to go immediately */
583     assert(current->output == NULL);
584
585     /* control sequence - report cursor location */
586     outputChars(current, "\x1b[6n", -1);
587
588     /* Parse the response: ESC [ rows ; cols R */
589     initParseEscapeSeq(&parser, 'R');
590     while ((ch = fd_read_char(current->fd, 100)) > 0) {
591         switch (parseEscapeSequence(&parser, ch)) {
592             default:
593                 continue;
594             case EP_END:
595                 if (parser.numprops == 2 && parser.props[1] < 1000) {
596                     *cols = parser.props[1];
597                     return 1;
598                 }
599                 break;
600             case EP_ERROR:
601                 break;
602         }
603         /* failed */
604         break;
605     }
606     return 0;
607 }
608
609 /**
610  * Updates current->cols with the current window size (width)
611  */
612 static int getWindowSize(struct current *current)
613 {
614     struct winsize ws;
615
616     if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0) {
617         current->cols = ws.ws_col;
618         return 0;
619     }
620
621     /* Failed to query the window size. Perhaps we are on a serial terminal.
622      * Try to query the width by sending the cursor as far to the right
623      * and reading back the cursor position.
624      * Note that this is only done once per call to linenoise rather than
625      * every time the line is refreshed for efficiency reasons.
626      *
627      * In more detail, we:
628      * (a) request current cursor position,
629      * (b) move cursor far right,
630      * (c) request cursor position again,
631      * (d) at last move back to the old position.
632      * This gives us the width without messing with the externally
633      * visible cursor position.
634      */
635
636     if (current->cols == 0) {
637         int here;
638
639         /* If anything fails => default 80 */
640         current->cols = 80;
641
642         /* (a) */
643         if (queryCursor (current, &here)) {
644             /* (b) */
645             setCursorPos(current, 999);
646
647             /* (c). Note: If (a) succeeded, then (c) should as well.
648              * For paranoia we still check and have a fallback action
649              * for (d) in case of failure..
650              */
651             if (queryCursor (current, &current->cols)) {
652                 /* (d) Reset the cursor back to the original location. */
653                 if (current->cols > here) {
654                     setCursorPos(current, here);
655                 }
656             }
657         }
658     }
659
660     return 0;
661 }
662
663 /**
664  * If CHAR_ESCAPE was received, reads subsequent
665  * chars to determine if this is a known special key.
666  *
667  * Returns SPECIAL_NONE if unrecognised, or -1 if EOF.
668  *
669  * If no additional char is received within a short time,
670  * CHAR_ESCAPE is returned.
671  */
672 static int check_special(int fd)
673 {
674     int c = fd_read_char(fd, 50);
675     int c2;
676
677     if (c < 0) {
678         return CHAR_ESCAPE;
679     }
680
681     c2 = fd_read_char(fd, 50);
682     if (c2 < 0) {
683         return c2;
684     }
685     if (c == '[' || c == 'O') {
686         /* Potential arrow key */
687         switch (c2) {
688             case 'A':
689                 return SPECIAL_UP;
690             case 'B':
691                 return SPECIAL_DOWN;
692             case 'C':
693                 return SPECIAL_RIGHT;
694             case 'D':
695                 return SPECIAL_LEFT;
696             case 'F':
697                 return SPECIAL_END;
698             case 'H':
699                 return SPECIAL_HOME;
700         }
701     }
702     if (c == '[' && c2 >= '1' && c2 <= '8') {
703         /* extended escape */
704         c = fd_read_char(fd, 50);
705         if (c == '~') {
706             switch (c2) {
707                 case '2':
708                     return SPECIAL_INSERT;
709                 case '3':
710                     return SPECIAL_DELETE;
711                 case '5':
712                     return SPECIAL_PAGE_UP;
713                 case '6':
714                     return SPECIAL_PAGE_DOWN;
715                 case '7':
716                     return SPECIAL_HOME;
717                 case '8':
718                     return SPECIAL_END;
719             }
720         }
721         while (c != -1 && c != '~') {
722             /* .e.g \e[12~ or '\e[11;2~   discard the complete sequence */
723             c = fd_read_char(fd, 50);
724         }
725     }
726
727     return SPECIAL_NONE;
728 }
729 #endif
730
731 static void clearOutputHighlight(struct current *current)
732 {
733     int nohighlight = 0;
734     setOutputHighlight(current, &nohighlight, 1);
735 }
736
737 static void outputControlChar(struct current *current, char ch)
738 {
739     int reverse = 7;
740     setOutputHighlight(current, &reverse, 1);
741     outputChars(current, "^", 1);
742     outputChars(current, &ch, 1);
743     clearOutputHighlight(current);
744 }
745
746 #ifndef utf8_getchars
747 static int utf8_getchars(char *buf, int c)
748 {
749 #ifdef USE_UTF8
750     return utf8_fromunicode(buf, c);
751 #else
752     *buf = c;
753     return 1;
754 #endif
755 }
756 #endif
757
758 /**
759  * Returns the unicode character at the given offset,
760  * or -1 if none.
761  */
762 static int get_char(struct current *current, int pos)
763 {
764     if (pos >= 0 && pos < sb_chars(current->buf)) {
765         int c;
766         int i = utf8_index(sb_str(current->buf), pos);
767         (void)utf8_tounicode(sb_str(current->buf) + i, &c);
768         return c;
769     }
770     return -1;
771 }
772
773 static int char_display_width(int ch)
774 {
775     if (ch < ' ') {
776         /* control chars take two positions */
777         return 2;
778     }
779     else {
780         return utf8_width(ch);
781     }
782 }
783
784 #ifndef NO_COMPLETION
785 static linenoiseCompletionCallback *completionCallback = NULL;
786 static void *completionUserdata = NULL;
787 static int showhints = 1;
788 static linenoiseHintsCallback *hintsCallback = NULL;
789 static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
790 static void *hintsUserdata = NULL;
791
792 static void beep() {
793 #ifdef USE_TERMIOS
794     fprintf(stderr, "\x7");
795     fflush(stderr);
796 #endif
797 }
798
799 static void freeCompletions(linenoiseCompletions *lc) {
800     size_t i;
801     for (i = 0; i < lc->len; i++)
802         free(lc->cvec[i]);
803     free(lc->cvec);
804 }
805
806 static int completeLine(struct current *current) {
807     linenoiseCompletions lc = { 0, NULL };
808     int c = 0;
809
810     completionCallback(sb_str(current->buf),&lc,completionUserdata);
811     if (lc.len == 0) {
812         beep();
813     } else {
814         size_t stop = 0, i = 0;
815
816         while(!stop) {
817             /* Show completion or original buffer */
818             if (i < lc.len) {
819                 int chars = utf8_strlen(lc.cvec[i], -1);
820                 refreshLineAlt(current, current->prompt, lc.cvec[i], chars);
821             } else {
822                 refreshLine(current);
823             }
824
825             c = fd_read(current);
826             if (c == -1) {
827                 break;
828             }
829
830             switch(c) {
831                 case '\t': /* tab */
832                     i = (i+1) % (lc.len+1);
833                     if (i == lc.len) beep();
834                     break;
835                 case CHAR_ESCAPE: /* escape */
836                     /* Re-show original buffer */
837                     if (i < lc.len) {
838                         refreshLine(current);
839                     }
840                     stop = 1;
841                     break;
842                 default:
843                     /* Update buffer and return */
844                     if (i < lc.len) {
845                         set_current(current,lc.cvec[i]);
846                     }
847                     stop = 1;
848                     break;
849             }
850         }
851     }
852
853     freeCompletions(&lc);
854     return c; /* Return last read character */
855 }
856
857 /* Register a callback function to be called for tab-completion.
858    Returns the prior callback so that the caller may (if needed)
859    restore it when done. */
860 linenoiseCompletionCallback * linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn, void *userdata) {
861     linenoiseCompletionCallback * old = completionCallback;
862     completionCallback = fn;
863     completionUserdata = userdata;
864     return old;
865 }
866
867 void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
868     lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1));
869     lc->cvec[lc->len++] = strdup(str);
870 }
871
872 void linenoiseSetHintsCallback(linenoiseHintsCallback *callback, void *userdata)
873 {
874     hintsCallback = callback;
875     hintsUserdata = userdata;
876 }
877
878 void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *callback)
879 {
880     freeHintsCallback = callback;
881 }
882
883 #endif
884
885
886 static const char *reduceSingleBuf(const char *buf, int availcols, int *cursor_pos)
887 {
888     /* We have availcols columns available.
889      * If necessary, strip chars off the front of buf until *cursor_pos
890      * fits within availcols
891      */
892     int needcols = 0;
893     int pos = 0;
894     int new_cursor_pos = *cursor_pos;
895     const char *pt = buf;
896
897     DRL("reduceSingleBuf: availcols=%d, cursor_pos=%d\n", availcols, *cursor_pos);
898
899     while (*pt) {
900         int ch;
901         int n = utf8_tounicode(pt, &ch);
902         pt += n;
903
904         needcols += char_display_width(ch);
905
906         /* If we need too many cols, strip
907          * chars off the front of buf to make it fit.
908          * We keep 3 extra cols to the right of the cursor.
909          * 2 for possible wide chars, 1 for the last column that
910          * can't be used.
911          */
912         while (needcols >= availcols - 3) {
913             n = utf8_tounicode(buf, &ch);
914             buf += n;
915             needcols -= char_display_width(ch);
916             DRL_CHAR(ch);
917
918             /* and adjust the apparent cursor position */
919             new_cursor_pos--;
920
921             if (buf == pt) {
922                 /* can't remove more than this */
923                 break;
924             }
925         }
926
927         if (pos++ == *cursor_pos) {
928             break;
929         }
930
931     }
932     DRL("<snip>");
933     DRL_STR(buf);
934     DRL("\nafter reduce, needcols=%d, new_cursor_pos=%d\n", needcols, new_cursor_pos);
935
936     /* Done, now new_cursor_pos contains the adjusted cursor position
937      * and buf points to he adjusted start
938      */
939     *cursor_pos = new_cursor_pos;
940     return buf;
941 }
942
943 static int mlmode = 0;
944
945 void linenoiseSetMultiLine(int enableml)
946 {
947     mlmode = enableml;
948 }
949
950 /* Helper of refreshSingleLine() and refreshMultiLine() to show hints
951  * to the right of the prompt. */
952 static void refreshShowHints(struct current *current, const char *buf, int availcols) {
953     if (showhints && hintsCallback && availcols > 0) {
954         int bold = 0;
955         int color = -1;
956         char *hint = hintsCallback(buf, &color, &bold, hintsUserdata);
957         if (hint) {
958             const char *pt;
959             if (bold == 1 && color == -1) color = 37;
960             if (bold || color > 0) {
961                 int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
962                 setOutputHighlight(current, props, 3);
963             }
964             DRL("<hint bold=%d,color=%d>", bold, color);
965             pt = hint;
966             while (*pt) {
967                 int ch;
968                 int n = utf8_tounicode(pt, &ch);
969                 int width = char_display_width(ch);
970
971                 if (width >= availcols) {
972                     DRL("<hinteol>");
973                     break;
974                 }
975                 DRL_CHAR(ch);
976
977                 availcols -= width;
978                 outputChars(current, pt, n);
979                 pt += n;
980             }
981             if (bold || color > 0) {
982                 clearOutputHighlight(current);
983             }
984             /* Call the function to free the hint returned. */
985             if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
986         }
987     }
988 }
989
990 #ifdef USE_TERMIOS
991 static void refreshStart(struct current *current)
992 {
993     /* We accumulate all output here */
994     assert(current->output == NULL);
995     current->output = sb_alloc();
996 }
997
998 static void refreshEnd(struct current *current)
999 {
1000     /* Output everything at once */
1001     IGNORE_RC(write(current->fd, sb_str(current->output), sb_len(current->output)));
1002     sb_free(current->output);
1003     current->output = NULL;
1004 }
1005
1006 static void refreshStartChars(struct current *current)
1007 {
1008 }
1009
1010 static void refreshNewline(struct current *current)
1011 {
1012     DRL("<nl>");
1013     outputChars(current, "\n", 1);
1014 }
1015
1016 static void refreshEndChars(struct current *current)
1017 {
1018 }
1019 #endif
1020
1021 static void refreshLineAlt(struct current *current, const char *prompt, const char *buf, int cursor_pos)
1022 {
1023     int i;
1024     const char *pt;
1025     int displaycol;
1026     int displayrow;
1027     int visible;
1028     int currentpos;
1029     int notecursor;
1030     int cursorcol = 0;
1031     int cursorrow = 0;
1032     struct esc_parser parser;
1033
1034 #ifdef DEBUG_REFRESHLINE
1035     dfh = fopen("linenoise.debuglog", "a");
1036 #endif
1037
1038     /* Should intercept SIGWINCH. For now, just get the size every time */
1039     getWindowSize(current);
1040
1041     refreshStart(current);
1042
1043     DRL("wincols=%d, cursor_pos=%d, nrows=%d, rpos=%d\n", current->cols, cursor_pos, current->nrows, current->rpos);
1044
1045     /* Here is the plan:
1046      * (a) move the the bottom row, going down the appropriate number of lines
1047      * (b) move to beginning of line and erase the current line
1048      * (c) go up one line and do the same, until we have erased up to the first row
1049      * (d) output the prompt, counting cols and rows, taking into account escape sequences
1050      * (e) output the buffer, counting cols and rows
1051      *   (e') when we hit the current pos, save the cursor position
1052      * (f) move the cursor to the saved cursor position
1053      * (g) save the current cursor row and number of rows
1054      */
1055
1056     /* (a) - The cursor is currently at row rpos */
1057     cursorDown(current, current->nrows - current->rpos - 1);
1058     DRL("<cud=%d>", current->nrows - current->rpos - 1);
1059
1060     /* (b), (c) - Erase lines upwards until we get to the first row */
1061     for (i = 0; i < current->nrows; i++) {
1062         if (i) {
1063             DRL("<cup>");
1064             cursorUp(current, 1);
1065         }
1066         DRL("<clearline>");
1067         cursorToLeft(current);
1068         eraseEol(current);
1069     }
1070     DRL("\n");
1071
1072     /* (d) First output the prompt. control sequences don't take up display space */
1073     pt = prompt;
1074     displaycol = 0; /* current display column */
1075     displayrow = 0; /* current display row */
1076     visible = 1;
1077
1078     refreshStartChars(current);
1079
1080     while (*pt) {
1081         int width;
1082         int ch;
1083         int n = utf8_tounicode(pt, &ch);
1084
1085         if (visible && ch == CHAR_ESCAPE) {
1086             /* The start of an escape sequence, so not visible */
1087             visible = 0;
1088             initParseEscapeSeq(&parser, 'm');
1089             DRL("<esc-seq-start>");
1090         }
1091
1092         if (ch == '\n' || ch == '\r') {
1093             /* treat both CR and NL the same and force wrap */
1094             refreshNewline(current);
1095             displaycol = 0;
1096             displayrow++;
1097         }
1098         else {
1099             width = visible * utf8_width(ch);
1100
1101             displaycol += width;
1102             if (displaycol >= current->cols) {
1103                 /* need to wrap to the next line because of newline or if it doesn't fit
1104                  * XXX this is a problem in single line mode
1105                  */
1106                 refreshNewline(current);
1107                 displaycol = width;
1108                 displayrow++;
1109             }
1110
1111             DRL_CHAR(ch);
1112 #ifdef USE_WINCONSOLE
1113             if (visible) {
1114                 outputChars(current, pt, n);
1115             }
1116 #else
1117             outputChars(current, pt, n);
1118 #endif
1119         }
1120         pt += n;
1121
1122         if (!visible) {
1123             switch (parseEscapeSequence(&parser, ch)) {
1124                 case EP_END:
1125                     visible = 1;
1126                     setOutputHighlight(current, parser.props, parser.numprops);
1127                     DRL("<esc-seq-end,numprops=%d>", parser.numprops);
1128                     break;
1129                 case EP_ERROR:
1130                     DRL("<esc-seq-err>");
1131                     visible = 1;
1132                     break;
1133             }
1134         }
1135     }
1136
1137     /* Now we are at the first line with all lines erased */
1138     DRL("\nafter prompt: displaycol=%d, displayrow=%d\n", displaycol, displayrow);
1139
1140
1141     /* (e) output the buffer, counting cols and rows */
1142     if (mlmode == 0) {
1143         /* In this mode we may need to trim chars from the start of the buffer until the
1144          * cursor fits in the window.
1145          */
1146         pt = reduceSingleBuf(buf, current->cols - displaycol, &cursor_pos);
1147     }
1148     else {
1149         pt = buf;
1150     }
1151
1152     currentpos = 0;
1153     notecursor = -1;
1154
1155     while (*pt) {
1156         int ch;
1157         int n = utf8_tounicode(pt, &ch);
1158         int width = char_display_width(ch);
1159
1160         if (currentpos == cursor_pos) {
1161             /* (e') wherever we output this character is where we want the cursor */
1162             notecursor = 1;
1163         }
1164
1165         if (displaycol + width >= current->cols) {
1166             if (mlmode == 0) {
1167                 /* In single line mode stop once we print as much as we can on one line */
1168                 DRL("<slmode>");
1169                 break;
1170             }
1171             /* need to wrap to the next line since it doesn't fit */
1172             refreshNewline(current);
1173             displaycol = 0;
1174             displayrow++;
1175         }
1176
1177         if (notecursor == 1) {
1178             /* (e') Save this position as the current cursor position */
1179             cursorcol = displaycol;
1180             cursorrow = displayrow;
1181             notecursor = 0;
1182             DRL("<cursor>");
1183         }
1184
1185         displaycol += width;
1186
1187         if (ch < ' ') {
1188             outputControlChar(current, ch + '@');
1189         }
1190         else {
1191             outputChars(current, pt, n);
1192         }
1193         DRL_CHAR(ch);
1194         if (width != 1) {
1195             DRL("<w=%d>", width);
1196         }
1197
1198         pt += n;
1199         currentpos++;
1200     }
1201
1202     /* If we didn't see the cursor, it is at the current location */
1203     if (notecursor) {
1204         DRL("<cursor>");
1205         cursorcol = displaycol;
1206         cursorrow = displayrow;
1207     }
1208
1209     DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n\n", displaycol, displayrow, cursorcol, cursorrow);
1210
1211     /* (f) show hints */
1212     refreshShowHints(current, buf, current->cols - displaycol);
1213
1214     refreshEndChars(current);
1215
1216     /* (g) move the cursor to the correct place */
1217     cursorUp(current, displayrow - cursorrow);
1218     setCursorPos(current, cursorcol);
1219
1220     /* (h) Update the number of rows if larger, but never reduce this */
1221     if (displayrow >= current->nrows) {
1222         current->nrows = displayrow + 1;
1223     }
1224     /* And remember the row that the cursor is on */
1225     current->rpos = cursorrow;
1226
1227     refreshEnd(current);
1228
1229 #ifdef DEBUG_REFRESHLINE
1230     fclose(dfh);
1231 #endif
1232 }
1233
1234 static void refreshLine(struct current *current)
1235 {
1236     refreshLineAlt(current, current->prompt, sb_str(current->buf), current->pos);
1237 }
1238
1239 static void set_current(struct current *current, const char *str)
1240 {
1241     sb_clear(current->buf);
1242     sb_append(current->buf, str);
1243     current->pos = sb_chars(current->buf);
1244 }
1245
1246 /**
1247  * Removes the char at 'pos'.
1248  *
1249  * Returns 1 if the line needs to be refreshed, 2 if not
1250  * and 0 if nothing was removed
1251  */
1252 static int remove_char(struct current *current, int pos)
1253 {
1254     if (pos >= 0 && pos < sb_chars(current->buf)) {
1255         int offset = utf8_index(sb_str(current->buf), pos);
1256         int nbytes = utf8_index(sb_str(current->buf) + offset, 1);
1257
1258         /* Note that we no longer try to optimise the remove-at-end case
1259          * since control characters and wide characters mess
1260          * up the simple count
1261          */
1262         sb_delete(current->buf, offset, nbytes);
1263
1264         if (current->pos > pos) {
1265             current->pos--;
1266         }
1267         return 1;
1268     }
1269     return 0;
1270 }
1271
1272 /**
1273  * Insert 'ch' at position 'pos'
1274  *
1275  * Returns 1 if the line needs to be refreshed, 2 if not
1276  * and 0 if nothing was inserted (no room)
1277  */
1278 static int insert_char(struct current *current, int pos, int ch)
1279 {
1280     if (pos >= 0 && pos <= sb_chars(current->buf)) {
1281         char buf[MAX_UTF8_LEN + 1];
1282         int offset = utf8_index(sb_str(current->buf), pos);
1283         int n = utf8_getchars(buf, ch);
1284
1285         /* null terminate since sb_insert() requires it */
1286         buf[n] = 0;
1287
1288         /* Optimisation removed - see reason in remove_char() */
1289
1290         sb_insert(current->buf, offset, buf);
1291         if (current->pos >= pos) {
1292             current->pos++;
1293         }
1294         return 1;
1295     }
1296     return 0;
1297 }
1298
1299 /**
1300  * Captures up to 'n' characters starting at 'pos' for the cut buffer.
1301  *
1302  * This replaces any existing characters in the cut buffer.
1303  */
1304 static void capture_chars(struct current *current, int pos, int nchars)
1305 {
1306     if (pos >= 0 && (pos + nchars - 1) < sb_chars(current->buf)) {
1307         int offset = utf8_index(sb_str(current->buf), pos);
1308         int nbytes = utf8_index(sb_str(current->buf) + offset, nchars);
1309
1310         if (nbytes) {
1311             if (current->capture) {
1312                 sb_clear(current->capture);
1313             }
1314             else {
1315                 current->capture = sb_alloc();
1316             }
1317             sb_append_len(current->capture, sb_str(current->buf) + offset, nbytes);
1318         }
1319     }
1320 }
1321
1322 /**
1323  * Removes up to 'n' characters at cursor position 'pos'.
1324  *
1325  * Returns 0 if no chars were removed or non-zero otherwise.
1326  */
1327 static int remove_chars(struct current *current, int pos, int n)
1328 {
1329     int removed = 0;
1330
1331     /* First save any chars which will be removed */
1332     capture_chars(current, pos, n);
1333
1334     while (n-- && remove_char(current, pos)) {
1335         removed++;
1336     }
1337     return removed;
1338 }
1339 /**
1340  * Inserts the characters (string) 'chars' at the cursor position 'pos'.
1341  *
1342  * Returns 0 if no chars were inserted or non-zero otherwise.
1343  */
1344 static int insert_chars(struct current *current, int pos, const char *chars)
1345 {
1346     int inserted = 0;
1347
1348     while (*chars) {
1349         int ch;
1350         int n = utf8_tounicode(chars, &ch);
1351         if (insert_char(current, pos, ch) == 0) {
1352             break;
1353         }
1354         inserted++;
1355         pos++;
1356         chars += n;
1357     }
1358     return inserted;
1359 }
1360
1361 /**
1362  * Returns the keycode to process, or 0 if none.
1363  */
1364 static int reverseIncrementalSearch(struct current *current)
1365 {
1366     /* Display the reverse-i-search prompt and process chars */
1367     char rbuf[50];
1368     char rprompt[80];
1369     int rchars = 0;
1370     int rlen = 0;
1371     int searchpos = history_len - 1;
1372     int c;
1373
1374     rbuf[0] = 0;
1375     while (1) {
1376         int n = 0;
1377         const char *p = NULL;
1378         int skipsame = 0;
1379         int searchdir = -1;
1380
1381         snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf);
1382         refreshLineAlt(current, rprompt, sb_str(current->buf), current->pos);
1383         c = fd_read(current);
1384         if (c == ctrl('H') || c == CHAR_DELETE) {
1385             if (rchars) {
1386                 int p = utf8_index(rbuf, --rchars);
1387                 rbuf[p] = 0;
1388                 rlen = strlen(rbuf);
1389             }
1390             continue;
1391         }
1392 #ifdef USE_TERMIOS
1393         if (c == CHAR_ESCAPE) {
1394             c = check_special(current->fd);
1395         }
1396 #endif
1397         if (c == ctrl('P') || c == SPECIAL_UP) {
1398             /* Search for the previous (earlier) match */
1399             if (searchpos > 0) {
1400                 searchpos--;
1401             }
1402             skipsame = 1;
1403         }
1404         else if (c == ctrl('N') || c == SPECIAL_DOWN) {
1405             /* Search for the next (later) match */
1406             if (searchpos < history_len) {
1407                 searchpos++;
1408             }
1409             searchdir = 1;
1410             skipsame = 1;
1411         }
1412         else if (c >= ' ') {
1413             /* >= here to allow for null terminator */
1414             if (rlen >= (int)sizeof(rbuf) - MAX_UTF8_LEN) {
1415                 continue;
1416             }
1417
1418             n = utf8_getchars(rbuf + rlen, c);
1419             rlen += n;
1420             rchars++;
1421             rbuf[rlen] = 0;
1422
1423             /* Adding a new char resets the search location */
1424             searchpos = history_len - 1;
1425         }
1426         else {
1427             /* Exit from incremental search mode */
1428             break;
1429         }
1430
1431         /* Now search through the history for a match */
1432         for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) {
1433             p = strstr(history[searchpos], rbuf);
1434             if (p) {
1435                 /* Found a match */
1436                 if (skipsame && strcmp(history[searchpos], sb_str(current->buf)) == 0) {
1437                     /* But it is identical, so skip it */
1438                     continue;
1439                 }
1440                 /* Copy the matching line and set the cursor position */
1441                 set_current(current,history[searchpos]);
1442                 current->pos = utf8_strlen(history[searchpos], p - history[searchpos]);
1443                 break;
1444             }
1445         }
1446         if (!p && n) {
1447             /* No match, so don't add it */
1448             rchars--;
1449             rlen -= n;
1450             rbuf[rlen] = 0;
1451         }
1452     }
1453     if (c == ctrl('G') || c == ctrl('C')) {
1454         /* ctrl-g terminates the search with no effect */
1455         set_current(current, "");
1456         c = 0;
1457     }
1458     else if (c == ctrl('J')) {
1459         /* ctrl-j terminates the search leaving the buffer in place */
1460         c = 0;
1461     }
1462
1463     /* Go process the char normally */
1464     refreshLine(current);
1465     return c;
1466 }
1467
1468 static int linenoiseEdit(struct current *current) {
1469     int history_index = 0;
1470
1471     /* The latest history entry is always our current buffer, that
1472      * initially is just an empty string. */
1473     linenoiseHistoryAdd("");
1474
1475     set_current(current, "");
1476     refreshLine(current);
1477
1478     while(1) {
1479         int dir = -1;
1480         int c = fd_read(current);
1481
1482 #ifndef NO_COMPLETION
1483         /* Only autocomplete when the callback is set. It returns < 0 when
1484          * there was an error reading from fd. Otherwise it will return the
1485          * character that should be handled next. */
1486         if (c == '\t' && current->pos == sb_chars(current->buf) && completionCallback != NULL) {
1487             c = completeLine(current);
1488         }
1489 #endif
1490         if (c == ctrl('R')) {
1491             /* reverse incremental search will provide an alternative keycode or 0 for none */
1492             c = reverseIncrementalSearch(current);
1493             /* go on to process the returned char normally */
1494         }
1495
1496 #ifdef USE_TERMIOS
1497         if (c == CHAR_ESCAPE) {   /* escape sequence */
1498             c = check_special(current->fd);
1499         }
1500 #endif
1501         if (c == -1) {
1502             /* Return on errors */
1503             return sb_len(current->buf);
1504         }
1505
1506         switch(c) {
1507         case SPECIAL_NONE:
1508             break;
1509         case '\r':    /* enter */
1510             history_len--;
1511             free(history[history_len]);
1512             current->pos = sb_chars(current->buf);
1513             if (mlmode || hintsCallback) {
1514                 showhints = 0;
1515                 refreshLine(current);
1516                 showhints = 1;
1517             }
1518             return sb_len(current->buf);
1519         case ctrl('C'):     /* ctrl-c */
1520             errno = EAGAIN;
1521             return -1;
1522         case ctrl('Z'):     /* ctrl-z */
1523 #ifdef SIGTSTP
1524             /* send ourselves SIGSUSP */
1525             disableRawMode(current);
1526             raise(SIGTSTP);
1527             /* and resume */
1528             enableRawMode(current);
1529             refreshLine(current);
1530 #endif
1531             continue;
1532         case CHAR_DELETE:   /* backspace */
1533         case ctrl('H'):
1534             if (remove_char(current, current->pos - 1) == 1) {
1535                 refreshLine(current);
1536             }
1537             break;
1538         case ctrl('D'):     /* ctrl-d */
1539             if (sb_len(current->buf) == 0) {
1540                 /* Empty line, so EOF */
1541                 history_len--;
1542                 free(history[history_len]);
1543                 return -1;
1544             }
1545             /* Otherwise fall through to delete char to right of cursor */
1546         case SPECIAL_DELETE:
1547             if (remove_char(current, current->pos) == 1) {
1548                 refreshLine(current);
1549             }
1550             break;
1551         case SPECIAL_INSERT:
1552             /* Ignore. Expansion Hook.
1553              * Future possibility: Toggle Insert/Overwrite Modes
1554              */
1555             break;
1556         case ctrl('W'):    /* ctrl-w, delete word at left. save deleted chars */
1557             /* eat any spaces on the left */
1558             {
1559                 int pos = current->pos;
1560                 while (pos > 0 && get_char(current, pos - 1) == ' ') {
1561                     pos--;
1562                 }
1563
1564                 /* now eat any non-spaces on the left */
1565                 while (pos > 0 && get_char(current, pos - 1) != ' ') {
1566                     pos--;
1567                 }
1568
1569                 if (remove_chars(current, pos, current->pos - pos)) {
1570                     refreshLine(current);
1571                 }
1572             }
1573             break;
1574         case ctrl('T'):    /* ctrl-t */
1575             if (current->pos > 0 && current->pos <= sb_chars(current->buf)) {
1576                 /* If cursor is at end, transpose the previous two chars */
1577                 int fixer = (current->pos == sb_chars(current->buf));
1578                 c = get_char(current, current->pos - fixer);
1579                 remove_char(current, current->pos - fixer);
1580                 insert_char(current, current->pos - 1, c);
1581                 refreshLine(current);
1582             }
1583             break;
1584         case ctrl('V'):    /* ctrl-v */
1585             /* Insert the ^V first */
1586             if (insert_char(current, current->pos, c)) {
1587                 refreshLine(current);
1588                 /* Now wait for the next char. Can insert anything except \0 */
1589                 c = fd_read(current);
1590
1591                 /* Remove the ^V first */
1592                 remove_char(current, current->pos - 1);
1593                 if (c > 0) {
1594                     /* Insert the actual char, can't be error or null */
1595                     insert_char(current, current->pos, c);
1596                 }
1597                 refreshLine(current);
1598             }
1599             break;
1600         case ctrl('B'):
1601         case SPECIAL_LEFT:
1602             if (current->pos > 0) {
1603                 current->pos--;
1604                 refreshLine(current);
1605             }
1606             break;
1607         case ctrl('F'):
1608         case SPECIAL_RIGHT:
1609             if (current->pos < sb_chars(current->buf)) {
1610                 current->pos++;
1611                 refreshLine(current);
1612             }
1613             break;
1614         case SPECIAL_PAGE_UP:
1615           dir = history_len - history_index - 1; /* move to start of history */
1616           goto history_navigation;
1617         case SPECIAL_PAGE_DOWN:
1618           dir = -history_index; /* move to 0 == end of history, i.e. current */
1619           goto history_navigation;
1620         case ctrl('P'):
1621         case SPECIAL_UP:
1622             dir = 1;
1623           goto history_navigation;
1624         case ctrl('N'):
1625         case SPECIAL_DOWN:
1626 history_navigation:
1627             if (history_len > 1) {
1628                 /* Update the current history entry before to
1629                  * overwrite it with tne next one. */
1630                 free(history[history_len - 1 - history_index]);
1631                 history[history_len - 1 - history_index] = strdup(sb_str(current->buf));
1632                 /* Show the new entry */
1633                 history_index += dir;
1634                 if (history_index < 0) {
1635                     history_index = 0;
1636                     break;
1637                 } else if (history_index >= history_len) {
1638                     history_index = history_len - 1;
1639                     break;
1640                 }
1641                 set_current(current, history[history_len - 1 - history_index]);
1642                 refreshLine(current);
1643             }
1644             break;
1645         case ctrl('A'): /* Ctrl+a, go to the start of the line */
1646         case SPECIAL_HOME:
1647             current->pos = 0;
1648             refreshLine(current);
1649             break;
1650         case ctrl('E'): /* ctrl+e, go to the end of the line */
1651         case SPECIAL_END:
1652             current->pos = sb_chars(current->buf);
1653             refreshLine(current);
1654             break;
1655         case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */
1656             if (remove_chars(current, 0, current->pos)) {
1657                 refreshLine(current);
1658             }
1659             break;
1660         case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */
1661             if (remove_chars(current, current->pos, sb_chars(current->buf) - current->pos)) {
1662                 refreshLine(current);
1663             }
1664             break;
1665         case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */
1666             if (current->capture && insert_chars(current, current->pos, sb_str(current->capture))) {
1667                 refreshLine(current);
1668             }
1669             break;
1670         case ctrl('L'): /* Ctrl+L, clear screen */
1671             linenoiseClearScreen();
1672             /* Force recalc of window size for serial terminals */
1673             current->cols = 0;
1674             current->rpos = 0;
1675             refreshLine(current);
1676             break;
1677         default:
1678             /* Only tab is allowed without ^V */
1679             if (c == '\t' || c >= ' ') {
1680                 if (insert_char(current, current->pos, c) == 1) {
1681                     refreshLine(current);
1682                 }
1683             }
1684             break;
1685         }
1686     }
1687     return sb_len(current->buf);
1688 }
1689
1690 int linenoiseColumns(void)
1691 {
1692     struct current current;
1693     enableRawMode (&current);
1694     getWindowSize (&current);
1695     disableRawMode (&current);
1696     return current.cols;
1697 }
1698
1699 /**
1700  * Reads a line from the file handle (without the trailing NL or CRNL)
1701  * and returns it in a stringbuf.
1702  * Returns NULL if no characters are read before EOF or error.
1703  *
1704  * Note that the character count will *not* be correct for lines containing
1705  * utf8 sequences. Do not rely on the character count.
1706  */
1707 static stringbuf *sb_getline(FILE *fh)
1708 {
1709     stringbuf *sb = sb_alloc();
1710     int c;
1711     int n = 0;
1712
1713     while ((c = getc(fh)) != EOF) {
1714         char ch;
1715         n++;
1716         if (c == '\r') {
1717             /* CRLF -> LF */
1718             continue;
1719         }
1720         if (c == '\n' || c == '\r') {
1721             break;
1722         }
1723         ch = c;
1724         /* ignore the effect of character count for partial utf8 sequences */
1725         sb_append_len(sb, &ch, 1);
1726     }
1727     if (n == 0) {
1728         sb_free(sb);
1729         return NULL;
1730     }
1731     return sb;
1732 }
1733
1734 char *linenoise(const char *prompt)
1735 {
1736     int count;
1737     struct current current;
1738     stringbuf *sb;
1739
1740     memset(&current, 0, sizeof(current));
1741
1742     if (enableRawMode(&current) == -1) {
1743         printf("%s", prompt);
1744         fflush(stdout);
1745         sb = sb_getline(stdin);
1746     }
1747     else {
1748         current.buf = sb_alloc();
1749         current.pos = 0;
1750         current.nrows = 1;
1751         current.prompt = prompt;
1752
1753         count = linenoiseEdit(&current);
1754
1755         disableRawMode(&current);
1756         printf("\n");
1757
1758         sb_free(current.capture);
1759         if (count == -1) {
1760             sb_free(current.buf);
1761             return NULL;
1762         }
1763         sb = current.buf;
1764     }
1765     return sb ? sb_to_string(sb) : NULL;
1766 }
1767
1768 /* Using a circular buffer is smarter, but a bit more complex to handle. */
1769 int linenoiseHistoryAddAllocated(char *line) {
1770
1771     if (history_max_len == 0) {
1772 notinserted:
1773         free(line);
1774         return 0;
1775     }
1776     if (history == NULL) {
1777         history = (char **)calloc(sizeof(char*), history_max_len);
1778     }
1779
1780     /* do not insert duplicate lines into history */
1781     if (history_len > 0 && strcmp(line, history[history_len - 1]) == 0) {
1782         goto notinserted;
1783     }
1784
1785     if (history_len == history_max_len) {
1786         free(history[0]);
1787         memmove(history,history+1,sizeof(char*)*(history_max_len-1));
1788         history_len--;
1789     }
1790     history[history_len] = line;
1791     history_len++;
1792     return 1;
1793 }
1794
1795 int linenoiseHistoryAdd(const char *line) {
1796     return linenoiseHistoryAddAllocated(strdup(line));
1797 }
1798
1799 int linenoiseHistoryGetMaxLen(void) {
1800     return history_max_len;
1801 }
1802
1803 int linenoiseHistorySetMaxLen(int len) {
1804     char **newHistory;
1805
1806     if (len < 1) return 0;
1807     if (history) {
1808         int tocopy = history_len;
1809
1810         newHistory = (char **)calloc(sizeof(char*), len);
1811
1812         /* If we can't copy everything, free the elements we'll not use. */
1813         if (len < tocopy) {
1814             int j;
1815
1816             for (j = 0; j < tocopy-len; j++) free(history[j]);
1817             tocopy = len;
1818         }
1819         memcpy(newHistory,history+(history_len-tocopy), sizeof(char*)*tocopy);
1820         free(history);
1821         history = newHistory;
1822     }
1823     history_max_len = len;
1824     if (history_len > history_max_len)
1825         history_len = history_max_len;
1826     return 1;
1827 }
1828
1829 /* Save the history in the specified file. On success 0 is returned
1830  * otherwise -1 is returned. */
1831 int linenoiseHistorySave(const char *filename) {
1832     FILE *fp = fopen(filename,"w");
1833     int j;
1834
1835     if (fp == NULL) return -1;
1836     for (j = 0; j < history_len; j++) {
1837         const char *str = history[j];
1838         /* Need to encode backslash, nl and cr */
1839         while (*str) {
1840             if (*str == '\\') {
1841                 fputs("\\\\", fp);
1842             }
1843             else if (*str == '\n') {
1844                 fputs("\\n", fp);
1845             }
1846             else if (*str == '\r') {
1847                 fputs("\\r", fp);
1848             }
1849             else {
1850                 fputc(*str, fp);
1851             }
1852             str++;
1853         }
1854         fputc('\n', fp);
1855     }
1856
1857     fclose(fp);
1858     return 0;
1859 }
1860
1861 /* Load the history from the specified file.
1862  *
1863  * If the file does not exist or can't be opened, no operation is performed
1864  * and -1 is returned.
1865  * Otherwise 0 is returned.
1866  */
1867 int linenoiseHistoryLoad(const char *filename) {
1868     FILE *fp = fopen(filename,"r");
1869     stringbuf *sb;
1870
1871     if (fp == NULL) return -1;
1872
1873     while ((sb = sb_getline(fp)) != NULL) {
1874         /* Take the stringbuf and decode backslash escaped values */
1875         char *buf = sb_to_string(sb);
1876         char *dest = buf;
1877         const char *src;
1878
1879         for (src = buf; *src; src++) {
1880             char ch = *src;
1881
1882             if (ch == '\\') {
1883                 src++;
1884                 if (*src == 'n') {
1885                     ch = '\n';
1886                 }
1887                 else if (*src == 'r') {
1888                     ch = '\r';
1889                 } else {
1890                     ch = *src;
1891                 }
1892             }
1893             *dest++ = ch;
1894         }
1895         *dest = 0;
1896
1897         linenoiseHistoryAddAllocated(buf);
1898     }
1899     fclose(fp);
1900     return 0;
1901 }
1902
1903 /* Provide access to the history buffer.
1904  *
1905  * If 'len' is not NULL, the length is stored in *len.
1906  */
1907 char **linenoiseHistory(int *len) {
1908     if (len) {
1909         *len = history_len;
1910     }
1911     return history;
1912 }