Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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