1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 610328f8bSStefan Eßer * Copyright (c) 2018-2021 Gavin D. Howard and contributors. 7252884aeSStefan Eßer * 8252884aeSStefan Eßer * Redistribution and use in source and binary forms, with or without 9252884aeSStefan Eßer * modification, are permitted provided that the following conditions are met: 10252884aeSStefan Eßer * 11252884aeSStefan Eßer * * Redistributions of source code must retain the above copyright notice, this 12252884aeSStefan Eßer * list of conditions and the following disclaimer. 13252884aeSStefan Eßer * 14252884aeSStefan Eßer * * Redistributions in binary form must reproduce the above copyright notice, 15252884aeSStefan Eßer * this list of conditions and the following disclaimer in the documentation 16252884aeSStefan Eßer * and/or other materials provided with the distribution. 17252884aeSStefan Eßer * 18252884aeSStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19252884aeSStefan Eßer * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20252884aeSStefan Eßer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21252884aeSStefan Eßer * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22252884aeSStefan Eßer * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23252884aeSStefan Eßer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24252884aeSStefan Eßer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25252884aeSStefan Eßer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26252884aeSStefan Eßer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27252884aeSStefan Eßer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28252884aeSStefan Eßer * POSSIBILITY OF SUCH DAMAGE. 29252884aeSStefan Eßer * 30252884aeSStefan Eßer * ***************************************************************************** 31252884aeSStefan Eßer * 32252884aeSStefan Eßer * Adapted from the following: 33252884aeSStefan Eßer * 34252884aeSStefan Eßer * linenoise.c -- guerrilla line editing library against the idea that a 35252884aeSStefan Eßer * line editing lib needs to be 20,000 lines of C code. 36252884aeSStefan Eßer * 37252884aeSStefan Eßer * You can find the original source code at: 38252884aeSStefan Eßer * http://github.com/antirez/linenoise 39252884aeSStefan Eßer * 40252884aeSStefan Eßer * You can find the fork that this code is based on at: 41252884aeSStefan Eßer * https://github.com/rain-1/linenoise-mob 42252884aeSStefan Eßer * 43252884aeSStefan Eßer * ------------------------------------------------------------------------ 44252884aeSStefan Eßer * 45252884aeSStefan Eßer * This code is also under the following license: 46252884aeSStefan Eßer * 47252884aeSStefan Eßer * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com> 48252884aeSStefan Eßer * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com> 49252884aeSStefan Eßer * 50252884aeSStefan Eßer * Redistribution and use in source and binary forms, with or without 51252884aeSStefan Eßer * modification, are permitted provided that the following conditions are 52252884aeSStefan Eßer * met: 53252884aeSStefan Eßer * 54252884aeSStefan Eßer * * Redistributions of source code must retain the above copyright 55252884aeSStefan Eßer * notice, this list of conditions and the following disclaimer. 56252884aeSStefan Eßer * 57252884aeSStefan Eßer * * Redistributions in binary form must reproduce the above copyright 58252884aeSStefan Eßer * notice, this list of conditions and the following disclaimer in the 59252884aeSStefan Eßer * documentation and/or other materials provided with the distribution. 60252884aeSStefan Eßer * 61252884aeSStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 62252884aeSStefan Eßer * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 63252884aeSStefan Eßer * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 64252884aeSStefan Eßer * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 65252884aeSStefan Eßer * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 66252884aeSStefan Eßer * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 67252884aeSStefan Eßer * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 68252884aeSStefan Eßer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 69252884aeSStefan Eßer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 70252884aeSStefan Eßer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 71252884aeSStefan Eßer * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 72252884aeSStefan Eßer * 73252884aeSStefan Eßer * ***************************************************************************** 74252884aeSStefan Eßer * 75252884aeSStefan Eßer * Definitions for line history. 76252884aeSStefan Eßer * 77252884aeSStefan Eßer */ 78252884aeSStefan Eßer 79252884aeSStefan Eßer #ifndef BC_HISTORY_H 80252884aeSStefan Eßer #define BC_HISTORY_H 81252884aeSStefan Eßer 82252884aeSStefan Eßer #ifndef BC_ENABLE_HISTORY 83252884aeSStefan Eßer #define BC_ENABLE_HISTORY (1) 84252884aeSStefan Eßer #endif // BC_ENABLE_HISTORY 85252884aeSStefan Eßer 86*78bc019dSStefan Eßer #ifndef BC_ENABLE_EDITLINE 87*78bc019dSStefan Eßer #define BC_ENABLE_EDITLINE (0) 88*78bc019dSStefan Eßer #endif // BC_ENABLE_EDITLINE 89*78bc019dSStefan Eßer 90*78bc019dSStefan Eßer #ifndef BC_ENABLE_READLINE 91*78bc019dSStefan Eßer #define BC_ENABLE_READLINE (0) 92*78bc019dSStefan Eßer #endif // BC_ENABLE_READLINE 93*78bc019dSStefan Eßer 94*78bc019dSStefan Eßer #if BC_ENABLE_EDITLINE && BC_ENABLE_READLINE 95*78bc019dSStefan Eßer #error Must enable only one of editline or readline, not both. 96*78bc019dSStefan Eßer #endif // BC_ENABLE_EDITLINE && BC_ENABLE_READLINE 97*78bc019dSStefan Eßer 98*78bc019dSStefan Eßer #if BC_ENABLE_EDITLINE || BC_ENABLE_READLINE 99*78bc019dSStefan Eßer #define BC_ENABLE_LINE_LIB (1) 100*78bc019dSStefan Eßer #else // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE 101*78bc019dSStefan Eßer #define BC_ENABLE_LINE_LIB (0) 102*78bc019dSStefan Eßer #endif // BC_ENABLE_EDITLINE || BC_ENABLE_READLINE 103*78bc019dSStefan Eßer 104*78bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB 105252884aeSStefan Eßer 106252884aeSStefan Eßer #include <stdbool.h> 107*78bc019dSStefan Eßer #include <setjmp.h> 108*78bc019dSStefan Eßer #include <signal.h> 109*78bc019dSStefan Eßer 110*78bc019dSStefan Eßer #include <status.h> 111*78bc019dSStefan Eßer #include <vector.h> 112*78bc019dSStefan Eßer 113*78bc019dSStefan Eßer extern sigjmp_buf bc_history_jmpbuf; 114*78bc019dSStefan Eßer extern volatile sig_atomic_t bc_history_inlinelib; 115*78bc019dSStefan Eßer 116*78bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB 117*78bc019dSStefan Eßer 118*78bc019dSStefan Eßer #if BC_ENABLE_EDITLINE 119*78bc019dSStefan Eßer 120*78bc019dSStefan Eßer #include <stdio.h> 121*78bc019dSStefan Eßer #include <histedit.h> 122*78bc019dSStefan Eßer 123*78bc019dSStefan Eßer /** 124*78bc019dSStefan Eßer * The history struct for editline. 125*78bc019dSStefan Eßer */ 126*78bc019dSStefan Eßer typedef struct BcHistory 127*78bc019dSStefan Eßer { 128*78bc019dSStefan Eßer /// A place to store the current line. 129*78bc019dSStefan Eßer EditLine* el; 130*78bc019dSStefan Eßer 131*78bc019dSStefan Eßer /// The history. 132*78bc019dSStefan Eßer History* hist; 133*78bc019dSStefan Eßer 134*78bc019dSStefan Eßer /// Whether the terminal is bad. This is more or less not used. 135*78bc019dSStefan Eßer bool badTerm; 136*78bc019dSStefan Eßer 137*78bc019dSStefan Eßer } BcHistory; 138*78bc019dSStefan Eßer 139*78bc019dSStefan Eßer // The path to the editrc and its length. 140*78bc019dSStefan Eßer extern const char bc_history_editrc[]; 141*78bc019dSStefan Eßer extern const size_t bc_history_editrc_len; 142*78bc019dSStefan Eßer 143*78bc019dSStefan Eßer #else // BC_ENABLE_EDITLINE 144*78bc019dSStefan Eßer 145*78bc019dSStefan Eßer #if BC_ENABLE_READLINE 146*78bc019dSStefan Eßer 147*78bc019dSStefan Eßer #include <stdio.h> 148*78bc019dSStefan Eßer #include <readline/readline.h> 149*78bc019dSStefan Eßer #include <readline/history.h> 150*78bc019dSStefan Eßer 151*78bc019dSStefan Eßer /** 152*78bc019dSStefan Eßer * The history struct for readline. 153*78bc019dSStefan Eßer */ 154*78bc019dSStefan Eßer typedef struct BcHistory 155*78bc019dSStefan Eßer { 156*78bc019dSStefan Eßer /// A place to store the current line. 157*78bc019dSStefan Eßer char* line; 158*78bc019dSStefan Eßer 159*78bc019dSStefan Eßer /// Whether the terminal is bad. This is more or less not used. 160*78bc019dSStefan Eßer bool badTerm; 161*78bc019dSStefan Eßer 162*78bc019dSStefan Eßer } BcHistory; 163*78bc019dSStefan Eßer 164*78bc019dSStefan Eßer #else // BC_ENABLE_READLINE 165*78bc019dSStefan Eßer 166*78bc019dSStefan Eßer #if BC_ENABLE_HISTORY 167*78bc019dSStefan Eßer 168252884aeSStefan Eßer #include <stddef.h> 169252884aeSStefan Eßer 170252884aeSStefan Eßer #include <signal.h> 171252884aeSStefan Eßer 17244d4804dSStefan Eßer #ifndef _WIN32 173252884aeSStefan Eßer #include <termios.h> 174252884aeSStefan Eßer #include <time.h> 175252884aeSStefan Eßer #include <unistd.h> 176252884aeSStefan Eßer #include <sys/select.h> 17744d4804dSStefan Eßer #else // _WIN32 17844d4804dSStefan Eßer 17944d4804dSStefan Eßer #ifndef WIN32_LEAN_AND_MEAN 18044d4804dSStefan Eßer #define WIN32_LEAN_AND_MEAN 18144d4804dSStefan Eßer #endif // WIN32_LEAN_AND_MEAN 18244d4804dSStefan Eßer 18344d4804dSStefan Eßer #include <Windows.h> 18444d4804dSStefan Eßer #include <io.h> 18544d4804dSStefan Eßer #include <conio.h> 18644d4804dSStefan Eßer 18744d4804dSStefan Eßer #define strncasecmp _strnicmp 18844d4804dSStefan Eßer #define strcasecmp _stricmp 18944d4804dSStefan Eßer 19044d4804dSStefan Eßer #endif // _WIN32 191252884aeSStefan Eßer 192252884aeSStefan Eßer #include <status.h> 193252884aeSStefan Eßer #include <vector.h> 194252884aeSStefan Eßer #include <read.h> 195252884aeSStefan Eßer 196252884aeSStefan Eßer #if BC_DEBUG_CODE 197252884aeSStefan Eßer #include <file.h> 198252884aeSStefan Eßer #endif // BC_DEBUG_CODE 199252884aeSStefan Eßer 20044d4804dSStefan Eßer /// Default columns. 201252884aeSStefan Eßer #define BC_HIST_DEF_COLS (80) 20244d4804dSStefan Eßer 20344d4804dSStefan Eßer /// Max number of history entries. 204252884aeSStefan Eßer #define BC_HIST_MAX_LEN (128) 20544d4804dSStefan Eßer 20644d4804dSStefan Eßer /// Max length of a line. 207252884aeSStefan Eßer #define BC_HIST_MAX_LINE (4095) 20844d4804dSStefan Eßer 20944d4804dSStefan Eßer /// Max size for cursor position buffer. 210252884aeSStefan Eßer #define BC_HIST_SEQ_SIZE (64) 211252884aeSStefan Eßer 21244d4804dSStefan Eßer /** 21344d4804dSStefan Eßer * The number of entries in the history. 21444d4804dSStefan Eßer * @param h The history data. 21544d4804dSStefan Eßer */ 216252884aeSStefan Eßer #define BC_HIST_BUF_LEN(h) ((h)->buf.len - 1) 21744d4804dSStefan Eßer 21844d4804dSStefan Eßer /** 21944d4804dSStefan Eßer * Read n characters into s and check the error. 22044d4804dSStefan Eßer * @param s The buffer to read into. 22144d4804dSStefan Eßer * @param n The number of bytes to read. 22244d4804dSStefan Eßer * @return True if there was an error, false otherwise. 22344d4804dSStefan Eßer */ 224252884aeSStefan Eßer #define BC_HIST_READ(s, n) (bc_history_read((s), (n)) == -1) 225252884aeSStefan Eßer 22644d4804dSStefan Eßer /// Markers for direction when using arrow keys. 227252884aeSStefan Eßer #define BC_HIST_NEXT (false) 228252884aeSStefan Eßer #define BC_HIST_PREV (true) 229252884aeSStefan Eßer 230252884aeSStefan Eßer #if BC_DEBUG_CODE 231252884aeSStefan Eßer 23244d4804dSStefan Eßer // These are just for debugging. 23344d4804dSStefan Eßer 234252884aeSStefan Eßer #define BC_HISTORY_DEBUG_BUF_SIZE (1024) 235252884aeSStefan Eßer 236*78bc019dSStefan Eßer // clang-format off 237252884aeSStefan Eßer #define lndebug(...) \ 238*78bc019dSStefan Eßer do \ 239*78bc019dSStefan Eßer { \ 240*78bc019dSStefan Eßer if (bc_history_debug_fp.fd == 0) \ 241*78bc019dSStefan Eßer { \ 242252884aeSStefan Eßer bc_history_debug_buf = bc_vm_malloc(BC_HISTORY_DEBUG_BUF_SIZE); \ 243252884aeSStefan Eßer bc_file_init(&bc_history_debug_fp, \ 244252884aeSStefan Eßer open("/tmp/lndebug.txt", O_APPEND), \ 245252884aeSStefan Eßer BC_HISTORY_DEBUG_BUF_SIZE); \ 246252884aeSStefan Eßer bc_file_printf(&bc_history_debug_fp, \ 247252884aeSStefan Eßer "[%zu %zu %zu] p: %d, rows: %d, " \ 248252884aeSStefan Eßer "rpos: %d, max: %zu, oldmax: %d\n", \ 249252884aeSStefan Eßer l->len, l->pos, l->oldcolpos, plen, rows, rpos, \ 250252884aeSStefan Eßer l->maxrows, old_rows); \ 251252884aeSStefan Eßer } \ 252252884aeSStefan Eßer bc_file_printf(&bc_history_debug_fp, ", " __VA_ARGS__); \ 253252884aeSStefan Eßer bc_file_flush(&bc_history_debug_fp); \ 254*78bc019dSStefan Eßer } \ 255*78bc019dSStefan Eßer while (0) 256252884aeSStefan Eßer #else // BC_DEBUG_CODE 257252884aeSStefan Eßer #define lndebug(fmt, ...) 258252884aeSStefan Eßer #endif // BC_DEBUG_CODE 259*78bc019dSStefan Eßer // clang-format on 260252884aeSStefan Eßer 26144d4804dSStefan Eßer /// An enum of useful actions. To understand what these mean, check terminal 26244d4804dSStefan Eßer /// emulators for their shortcuts or the VT100 codes. 263*78bc019dSStefan Eßer typedef enum BcHistoryAction 264*78bc019dSStefan Eßer { 265252884aeSStefan Eßer BC_ACTION_NULL = 0, 266252884aeSStefan Eßer BC_ACTION_CTRL_A = 1, 267252884aeSStefan Eßer BC_ACTION_CTRL_B = 2, 268252884aeSStefan Eßer BC_ACTION_CTRL_C = 3, 269252884aeSStefan Eßer BC_ACTION_CTRL_D = 4, 270252884aeSStefan Eßer BC_ACTION_CTRL_E = 5, 271252884aeSStefan Eßer BC_ACTION_CTRL_F = 6, 272252884aeSStefan Eßer BC_ACTION_CTRL_H = 8, 273252884aeSStefan Eßer BC_ACTION_TAB = 9, 274252884aeSStefan Eßer BC_ACTION_LINE_FEED = 10, 275252884aeSStefan Eßer BC_ACTION_CTRL_K = 11, 276252884aeSStefan Eßer BC_ACTION_CTRL_L = 12, 277252884aeSStefan Eßer BC_ACTION_ENTER = 13, 278252884aeSStefan Eßer BC_ACTION_CTRL_N = 14, 279252884aeSStefan Eßer BC_ACTION_CTRL_P = 16, 2808c39e252SStefan Eßer BC_ACTION_CTRL_S = 19, 281252884aeSStefan Eßer BC_ACTION_CTRL_T = 20, 282252884aeSStefan Eßer BC_ACTION_CTRL_U = 21, 283252884aeSStefan Eßer BC_ACTION_CTRL_W = 23, 284252884aeSStefan Eßer BC_ACTION_CTRL_Z = 26, 285252884aeSStefan Eßer BC_ACTION_ESC = 27, 28644d4804dSStefan Eßer BC_ACTION_CTRL_BSLASH = 28, 287252884aeSStefan Eßer BC_ACTION_BACKSPACE = 127 288252884aeSStefan Eßer 289252884aeSStefan Eßer } BcHistoryAction; 290252884aeSStefan Eßer 291252884aeSStefan Eßer /** 292252884aeSStefan Eßer * This represents the state during line editing. We pass this state 293252884aeSStefan Eßer * to functions implementing specific editing functionalities. 294252884aeSStefan Eßer */ 295*78bc019dSStefan Eßer typedef struct BcHistory 296*78bc019dSStefan Eßer { 297252884aeSStefan Eßer /// Edited line buffer. 298252884aeSStefan Eßer BcVec buf; 299252884aeSStefan Eßer 300252884aeSStefan Eßer /// The history. 301252884aeSStefan Eßer BcVec history; 302252884aeSStefan Eßer 3037e5c51e5SStefan Eßer /// Any material printed without a trailing newline. 3047e5c51e5SStefan Eßer BcVec extras; 3057e5c51e5SStefan Eßer 306252884aeSStefan Eßer /// Prompt to display. 307252884aeSStefan Eßer const char* prompt; 308252884aeSStefan Eßer 309252884aeSStefan Eßer /// Prompt length. 310252884aeSStefan Eßer size_t plen; 311252884aeSStefan Eßer 312252884aeSStefan Eßer /// Prompt column length. 313252884aeSStefan Eßer size_t pcol; 314252884aeSStefan Eßer 315252884aeSStefan Eßer /// Current cursor position. 316252884aeSStefan Eßer size_t pos; 317252884aeSStefan Eßer 318252884aeSStefan Eßer /// Previous refresh cursor column position. 319252884aeSStefan Eßer size_t oldcolpos; 320252884aeSStefan Eßer 321252884aeSStefan Eßer /// Number of columns in terminal. 322252884aeSStefan Eßer size_t cols; 323252884aeSStefan Eßer 324252884aeSStefan Eßer /// The history index we are currently editing. 325252884aeSStefan Eßer size_t idx; 326252884aeSStefan Eßer 32744d4804dSStefan Eßer #ifndef _WIN32 328252884aeSStefan Eßer /// The original terminal state. 329252884aeSStefan Eßer struct termios orig_termios; 33044d4804dSStefan Eßer #else // _WIN32 331d43fa8efSStefan Eßer /// The original input console mode. 332d43fa8efSStefan Eßer DWORD orig_in; 333d43fa8efSStefan Eßer 334d43fa8efSStefan Eßer /// The original output console mode. 335d43fa8efSStefan Eßer DWORD orig_out; 33644d4804dSStefan Eßer #endif // _WIN32 337252884aeSStefan Eßer 33844d4804dSStefan Eßer /// These next two are here because pahole found a 4 byte hole here. 339252884aeSStefan Eßer 340252884aeSStefan Eßer /// Whether we are in rawmode. 341252884aeSStefan Eßer bool rawMode; 342252884aeSStefan Eßer 343252884aeSStefan Eßer /// Whether the terminal is bad. 344252884aeSStefan Eßer bool badTerm; 345252884aeSStefan Eßer 34644d4804dSStefan Eßer #ifndef _WIN32 347252884aeSStefan Eßer /// This is to check if stdin has more data. 348252884aeSStefan Eßer fd_set rdset; 349252884aeSStefan Eßer 350252884aeSStefan Eßer /// This is to check if stdin has more data. 351252884aeSStefan Eßer struct timespec ts; 352252884aeSStefan Eßer 353252884aeSStefan Eßer /// This is to check if stdin has more data. 354252884aeSStefan Eßer sigset_t sigmask; 35544d4804dSStefan Eßer #endif // _WIN32 356252884aeSStefan Eßer 357252884aeSStefan Eßer } BcHistory; 358252884aeSStefan Eßer 35944d4804dSStefan Eßer /** 36044d4804dSStefan Eßer * Frees strings used by history. 36144d4804dSStefan Eßer * @param str The string to free. 36244d4804dSStefan Eßer */ 363*78bc019dSStefan Eßer void 364*78bc019dSStefan Eßer bc_history_string_free(void* str); 36544d4804dSStefan Eßer 36644d4804dSStefan Eßer // A list of terminals that don't work. 367252884aeSStefan Eßer extern const char* bc_history_bad_terms[]; 36844d4804dSStefan Eßer 36944d4804dSStefan Eßer // A tab in history and its length. 370252884aeSStefan Eßer extern const char bc_history_tab[]; 371252884aeSStefan Eßer extern const size_t bc_history_tab_len; 37244d4804dSStefan Eßer 37344d4804dSStefan Eßer // A ctrl+c string. 374252884aeSStefan Eßer extern const char bc_history_ctrlc[]; 37544d4804dSStefan Eßer 37644d4804dSStefan Eßer // UTF-8 data arrays. 377252884aeSStefan Eßer extern const uint32_t bc_history_wchars[][2]; 378252884aeSStefan Eßer extern const size_t bc_history_wchars_len; 379252884aeSStefan Eßer extern const uint32_t bc_history_combo_chars[]; 380252884aeSStefan Eßer extern const size_t bc_history_combo_chars_len; 38144d4804dSStefan Eßer 382252884aeSStefan Eßer #if BC_DEBUG_CODE 38344d4804dSStefan Eßer 38444d4804dSStefan Eßer // Debug data. 385252884aeSStefan Eßer extern BcFile bc_history_debug_fp; 386252884aeSStefan Eßer extern char* bc_history_debug_buf; 38744d4804dSStefan Eßer 38844d4804dSStefan Eßer /** 38944d4804dSStefan Eßer * A function to print keycodes for debugging. 39044d4804dSStefan Eßer * @param h The history data. 39144d4804dSStefan Eßer */ 392*78bc019dSStefan Eßer void 393*78bc019dSStefan Eßer bc_history_printKeyCodes(BcHistory* h); 39444d4804dSStefan Eßer 395252884aeSStefan Eßer #endif // BC_DEBUG_CODE 396252884aeSStefan Eßer 397252884aeSStefan Eßer #endif // BC_ENABLE_HISTORY 398252884aeSStefan Eßer 399*78bc019dSStefan Eßer #endif // BC_ENABLE_READLINE 400*78bc019dSStefan Eßer 401*78bc019dSStefan Eßer #endif // BC_ENABLE_EDITLINE 402*78bc019dSStefan Eßer 403*78bc019dSStefan Eßer #if BC_ENABLE_HISTORY 404*78bc019dSStefan Eßer 405*78bc019dSStefan Eßer /** 406*78bc019dSStefan Eßer * Get a line from stdin using history. This returns a status because I don't 407*78bc019dSStefan Eßer * want to throw errors while the terminal is in raw mode. 408*78bc019dSStefan Eßer * @param h The history data. 409*78bc019dSStefan Eßer * @param vec A vector to put the line into. 410*78bc019dSStefan Eßer * @param prompt The prompt to display, if desired. 411*78bc019dSStefan Eßer * @return A status indicating an error, if any. Returning a status here 412*78bc019dSStefan Eßer * is better because if we throw an error out of history, we 413*78bc019dSStefan Eßer * leave the terminal in raw mode or in some other half-baked 414*78bc019dSStefan Eßer * state. 415*78bc019dSStefan Eßer */ 416*78bc019dSStefan Eßer BcStatus 417*78bc019dSStefan Eßer bc_history_line(BcHistory* h, BcVec* vec, const char* prompt); 418*78bc019dSStefan Eßer 419*78bc019dSStefan Eßer /** 420*78bc019dSStefan Eßer * Initialize history data. 421*78bc019dSStefan Eßer * @param h The struct to initialize. 422*78bc019dSStefan Eßer */ 423*78bc019dSStefan Eßer void 424*78bc019dSStefan Eßer bc_history_init(BcHistory* h); 425*78bc019dSStefan Eßer 426*78bc019dSStefan Eßer /** 427*78bc019dSStefan Eßer * Free history data (and recook the terminal). 428*78bc019dSStefan Eßer * @param h The struct to free. 429*78bc019dSStefan Eßer */ 430*78bc019dSStefan Eßer void 431*78bc019dSStefan Eßer bc_history_free(BcHistory* h); 432*78bc019dSStefan Eßer 433*78bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY 434*78bc019dSStefan Eßer 435252884aeSStefan Eßer #endif // BC_HISTORY_H 436