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