summaryrefslogtreecommitdiff
path: root/third_party/linenoise/linenoise_win32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/linenoise/linenoise_win32.cpp')
-rw-r--r--third_party/linenoise/linenoise_win32.cpp442
1 files changed, 0 insertions, 442 deletions
diff --git a/third_party/linenoise/linenoise_win32.cpp b/third_party/linenoise/linenoise_win32.cpp
deleted file mode 100644
index 0a2c33485b1..00000000000
--- a/third_party/linenoise/linenoise_win32.cpp
+++ /dev/null
@@ -1,442 +0,0 @@
-/* linenoise_win32.c -- Linenoise win32 port.
- *
- * Modifications copyright 2010, Jon Griffiths <jon_p_griffiths at yahoo dot com>.
- * All rights reserved.
- * Based on linenoise, copyright 2010, Salvatore Sanfilippo <antirez at gmail dot com>.
- * The original linenoise can be found at: http://github.com/antirez/linenoise
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Redis nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Todo list:
- * Actually switch to/from raw mode so emacs key combos work.
- * Set a console handler to clean up onn exit.
- */
-#include <conio.h>
-#include <windows.h>
-#include <stdio.h>
-
-/* If ALT_KEYS is defined, emacs key combos using ALT instead of CTRL are
- * available. At this time, you don't get key repeats when enabled though. */
-/* #define ALT_KEYS */
-
-static HANDLE console_in, console_out;
-
-#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
-#define LINENOISE_MAX_LINE 4096
-
-static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
-static int history_len = 0;
-char** history = NULL;
-
-int linenoiseHistoryAdd(const char* line);
-
-static int enableRawMode()
-{
- if (!console_in)
- {
- console_in = GetStdHandle(STD_INPUT_HANDLE);
- console_out = GetStdHandle(STD_OUTPUT_HANDLE);
- }
- return 0;
-}
-
-static void disableRawMode()
-{
- /* Nothing to do yet */
-}
-
-static void output(const char* str,
- size_t len,
- int x,
- int y)
-{
- COORD pos = { (SHORT)x, (SHORT)y };
- DWORD count = 0;
- WriteConsoleOutputCharacterA(console_out, str, len, pos, &count);
-}
-
-static void refreshLine(const char* prompt,
- char* buf,
- size_t len,
- size_t pos,
- size_t cols)
-{
- size_t plen = strlen(prompt);
-
- while ((plen + pos) >= cols)
- {
- buf++;
- len--;
- pos--;
- }
- while (plen + len > cols)
- {
- len--;
- }
-
- CONSOLE_SCREEN_BUFFER_INFO inf = { 0 };
- GetConsoleScreenBufferInfo(console_out, &inf);
- size_t prompt_len = strlen(prompt);
- output(prompt, prompt_len, 0, inf.dwCursorPosition.Y);
- output(buf, len, prompt_len, inf.dwCursorPosition.Y);
- if (prompt_len + len < (size_t)inf.dwSize.X)
- {
- /* Blank to EOL */
- char* tmp = (char*)malloc(inf.dwSize.X - (prompt_len + len));
- memset(tmp, ' ', inf.dwSize.X - (prompt_len + len));
- output(tmp, inf.dwSize.X - (prompt_len + len), len + prompt_len, inf.dwCursorPosition.Y);
- free(tmp);
- }
- inf.dwCursorPosition.X = (SHORT)(pos + prompt_len);
- SetConsoleCursorPosition(console_out, inf.dwCursorPosition);
-}
-
-static int linenoisePrompt(char* buf,
- size_t buflen,
- const char* prompt)
-{
- size_t plen = strlen(prompt);
- size_t pos = 0;
- size_t len = 0;
- int history_index = 0;
-#ifdef ALT_KEYS
- unsigned char last_down = 0;
-#endif
- buf[0] = '\0';
- buflen--; /* Make sure there is always space for the nulterm */
-
- /* The latest history entry is always our current buffer, that
- * initially is just an empty string. */
- linenoiseHistoryAdd("");
-
- CONSOLE_SCREEN_BUFFER_INFO inf = { 0 };
- GetConsoleScreenBufferInfo(console_out, &inf);
- size_t cols = inf.dwSize.X;
- output(prompt, plen, 0, inf.dwCursorPosition.Y);
- inf.dwCursorPosition.X = (SHORT)plen;
- SetConsoleCursorPosition(console_out, inf.dwCursorPosition);
-
- for ( ; ; )
- {
- INPUT_RECORD rec;
- DWORD count;
- ReadConsoleInputA(console_in, &rec, 1, &count);
- if (rec.EventType != KEY_EVENT)
- continue;
-#ifdef ALT_KEYS
- if (rec.Event.KeyEvent.bKeyDown)
- {
- last_down = rec.Event.KeyEvent.uChar.AsciiChar;
- continue;
- }
-#else
- if (!rec.Event.KeyEvent.bKeyDown)
- {
- continue;
- }
-#endif
- switch (rec.Event.KeyEvent.wVirtualKeyCode)
- {
- case VK_RETURN: /* enter */
- history_len--;
- free(history[history_len]);
- return (int)len;
- case VK_BACK: /* backspace */
-#ifdef ALT_KEYS
- backspace:
-#endif
- if (pos > 0 && len > 0)
- {
- memmove(buf + pos - 1, buf + pos, len - pos);
- pos--;
- len--;
- buf[len] = '\0';
- refreshLine(prompt, buf, len, pos, cols);
- }
- break;
- case VK_LEFT:
-#ifdef ALT_KEYS
- left_arrow:
-#endif
- /* left arrow */
- if (pos > 0)
- {
- pos--;
- refreshLine(prompt, buf, len, pos, cols);
- }
- break;
- case VK_RIGHT:
-#ifdef ALT_KEYS
- right_arrow:
-#endif
- /* right arrow */
- if (pos != len)
- {
- pos++;
- refreshLine(prompt, buf, len, pos, cols);
- }
- break;
- case VK_UP:
- case VK_DOWN:
-#ifdef ALT_KEYS
- up_down_arrow:
-#endif
- /* up and down arrow: history */
- if (history_len > 1)
- {
- /* Update the current history entry before to
- * overwrite it with tne next one. */
- free(history[history_len - 1 - history_index]);
- history[history_len - 1 - history_index] = _strdup(buf);
- /* Show the new entry */
- history_index += (rec.Event.KeyEvent.wVirtualKeyCode == VK_UP) ? 1 : -1;
- if (history_index < 0)
- {
- history_index = 0;
- break;
- }
- else if (history_index >= history_len)
- {
- history_index = history_len - 1;
- break;
- }
- strncpy(buf, history[history_len - 1 - history_index], buflen);
- buf[buflen] = '\0';
- len = pos = strlen(buf);
- refreshLine(prompt, buf, len, pos, cols);
- }
- break;
- case VK_DELETE:
- /* delete */
- if (len > 0 && pos < len)
- {
- memmove(buf + pos, buf + pos + 1, len - pos - 1);
- len--;
- buf[len] = '\0';
- refreshLine(prompt, buf, len, pos, cols);
- }
- break;
- case VK_HOME: /* Ctrl+a, go to the start of the line */
-#ifdef ALT_KEYS
- home:
-#endif
- pos = 0;
- refreshLine(prompt, buf, len, pos, cols);
- break;
- case VK_END: /* ctrl+e, go to the end of the line */
-#ifdef ALT_KEYS
- end:
-#endif
- pos = len;
- refreshLine(prompt, buf, len, pos, cols);
- break;
- default:
-#ifdef ALT_KEYS
- /* Use alt instead of CTRL since windows eats CTRL+char combos */
- if (rec.Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
- {
- switch (last_down)
- {
- case 'a': /* ctrl-t */
- goto home;
- case 'e': /* ctrl-t */
- goto end;
- case 't': /* ctrl-t */
- if (pos > 0 && pos < len)
- {
- int aux = buf[pos - 1];
- buf[pos - 1] = buf[pos];
- buf[pos] = aux;
- if (pos != len - 1)
- pos++;
- refreshLine(prompt, buf, len, pos, cols);
- }
- break;
- case 'h': /* ctrl-h */
- goto backspace;
- case 'b': /* ctrl-b */
- goto left_arrow;
- case 'f': /* ctrl-f */
- goto right_arrow;
- case 'p': /* ctrl-p */
- rec.Event.KeyEvent.wVirtualKeyCode = VK_UP;
- goto up_down_arrow;
- case 'n': /* ctrl-n */
- rec.Event.KeyEvent.wVirtualKeyCode = VK_DOWN;
- goto up_down_arrow;
- case 'u': /* Ctrl+u, delete the whole line. */
- buf[0] = '\0';
- pos = len = 0;
- refreshLine(prompt, buf, len, pos, cols);
- break;
- case 'k': /* Ctrl+k, delete from current to end of line. */
- buf[pos] = '\0';
- len = pos;
- refreshLine(prompt, buf, len, pos, cols);
- break;
- }
- continue;
- }
-#endif /* ALT_KEYS */
- if (rec.Event.KeyEvent.uChar.AsciiChar < ' ' ||
- rec.Event.KeyEvent.uChar.AsciiChar > '~')
- continue;
-
- if (len < buflen)
- {
- if (len != pos)
- memmove(buf + pos + 1, buf + pos, len - pos);
- buf[pos] = rec.Event.KeyEvent.uChar.AsciiChar;
- len++;
- pos++;
- buf[len] = '\0';
- refreshLine(prompt, buf, len, pos, cols);
- }
- break;
- }
- }
-}
-
-static int linenoiseRaw(char* buf,
- size_t buflen,
- const char* prompt)
-{
- int count = -1;
-
- if (buflen != 0)
- {
- if (enableRawMode() == -1)
- return -1;
- count = linenoisePrompt(buf, buflen, prompt);
- disableRawMode();
- printf("\n");
- }
- return count;
-}
-
-char* linenoise(const char* prompt)
-{
- char buf[LINENOISE_MAX_LINE];
- int count = linenoiseRaw(buf, LINENOISE_MAX_LINE, prompt);
- if (count == -1)
- return NULL;
- return _strdup(buf);
-}
-
-/* Using a circular buffer is smarter, but a bit more complex to handle. */
-int linenoiseHistoryAdd(const char* line)
-{
- char* linecopy;
-
- if (history_max_len == 0)
- return 0;
- if (history == NULL)
- {
- history = (char**)malloc(sizeof(char*) * history_max_len);
- if (history == NULL)
- return 0;
- memset(history, 0, (sizeof(char*) * history_max_len));
- }
- linecopy = _strdup(line);
- if (!linecopy)
- return 0;
- if (history_len == history_max_len)
- {
- free(history[0]);
- memmove(history, history + 1, sizeof(char*) * (history_max_len - 1));
- history_len--;
- }
- history[history_len] = linecopy;
- history_len++;
- return 1;
-}
-
-int linenoiseHistorySetMaxLen(int len)
-{
- char** new_history;
-
- if (len < 1)
- return 0;
- if (history)
- {
- int tocopy = history_len;
-
- new_history = (char**)malloc(sizeof(char*) * len);
- if (new_history == NULL)
- return 0;
- if (len < tocopy)
- tocopy = len;
- memcpy(new_history, history + (history_max_len - tocopy), sizeof(char*) * tocopy);
- free(history);
- history = new_history;
- }
- history_max_len = len;
- if (history_len > history_max_len)
- history_len = history_max_len;
- return 1;
-}
-
-/* Save the history in the specified file. On success 0 is returned
- * otherwise -1 is returned. */
-int linenoiseHistorySave(const char* filename)
-{
- FILE* fp = fopen(filename, "w");
- int j;
-
- if (fp == NULL)
- return -1;
- for (j = 0; j < history_len; j++)
- fprintf(fp, "%s\n", history[j]);
- fclose(fp);
- return 0;
-}
-
-/* Load the history from the specified file. If the file does not exist
- * zero is returned and no operation is performed.
- *
- * If the file exists and the operation succeeded 0 is returned, otherwise
- * on error -1 is returned. */
-int linenoiseHistoryLoad(const char* filename)
-{
- FILE* fp = fopen(filename, "r");
- char buf[LINENOISE_MAX_LINE];
-
- if (fp == NULL)
- return -1;
-
- while (fgets(buf, LINENOISE_MAX_LINE, fp) != NULL)
- {
- char* p;
-
- p = strchr(buf, '\r');
- if (!p)
- p = strchr(buf, '\n');
- if (p)
- *p = '\0';
- linenoiseHistoryAdd(buf);
- }
- fclose(fp);
- return 0;
-}