1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 6*a970610aSStefan Eßer * Copyright (c) 2018-2024 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 82d101cdd6SStefan Eßer // These must come before the #if BC_ENABLE_LINE_LIB below because status.h 83d101cdd6SStefan Eßer // defines it. 84d101cdd6SStefan Eßer #include <status.h> 85d101cdd6SStefan Eßer #include <vector.h> 8678bc019dSStefan Eßer 8778bc019dSStefan Eßer #if BC_ENABLE_LINE_LIB 88252884aeSStefan Eßer 89252884aeSStefan Eßer #include <stdbool.h> 9078bc019dSStefan Eßer #include <setjmp.h> 9178bc019dSStefan Eßer #include <signal.h> 9278bc019dSStefan Eßer 9378bc019dSStefan Eßer extern sigjmp_buf bc_history_jmpbuf; 9478bc019dSStefan Eßer extern volatile sig_atomic_t bc_history_inlinelib; 9578bc019dSStefan Eßer 9678bc019dSStefan Eßer #endif // BC_ENABLE_LINE_LIB 9778bc019dSStefan Eßer 9878bc019dSStefan Eßer #if BC_ENABLE_EDITLINE 9978bc019dSStefan Eßer 10078bc019dSStefan Eßer #include <stdio.h> 10178bc019dSStefan Eßer #include <histedit.h> 10278bc019dSStefan Eßer 10378bc019dSStefan Eßer /** 10478bc019dSStefan Eßer * The history struct for editline. 10578bc019dSStefan Eßer */ 10678bc019dSStefan Eßer typedef struct BcHistory 10778bc019dSStefan Eßer { 10878bc019dSStefan Eßer /// A place to store the current line. 10978bc019dSStefan Eßer EditLine* el; 11078bc019dSStefan Eßer 11178bc019dSStefan Eßer /// The history. 11278bc019dSStefan Eßer History* hist; 11378bc019dSStefan Eßer 11478bc019dSStefan Eßer /// Whether the terminal is bad. This is more or less not used. 11578bc019dSStefan Eßer bool badTerm; 11678bc019dSStefan Eßer 11778bc019dSStefan Eßer } BcHistory; 11878bc019dSStefan Eßer 11978bc019dSStefan Eßer // The path to the editrc and its length. 12078bc019dSStefan Eßer extern const char bc_history_editrc[]; 12178bc019dSStefan Eßer extern const size_t bc_history_editrc_len; 12278bc019dSStefan Eßer 12378bc019dSStefan Eßer #else // BC_ENABLE_EDITLINE 12478bc019dSStefan Eßer 12578bc019dSStefan Eßer #if BC_ENABLE_READLINE 12678bc019dSStefan Eßer 12778bc019dSStefan Eßer #include <stdio.h> 12878bc019dSStefan Eßer #include <readline/readline.h> 12978bc019dSStefan Eßer #include <readline/history.h> 13078bc019dSStefan Eßer 13178bc019dSStefan Eßer /** 13278bc019dSStefan Eßer * The history struct for readline. 13378bc019dSStefan Eßer */ 13478bc019dSStefan Eßer typedef struct BcHistory 13578bc019dSStefan Eßer { 13678bc019dSStefan Eßer /// A place to store the current line. 13778bc019dSStefan Eßer char* line; 13878bc019dSStefan Eßer 13978bc019dSStefan Eßer /// Whether the terminal is bad. This is more or less not used. 14078bc019dSStefan Eßer bool badTerm; 14178bc019dSStefan Eßer 14278bc019dSStefan Eßer } BcHistory; 14378bc019dSStefan Eßer 14478bc019dSStefan Eßer #else // BC_ENABLE_READLINE 14578bc019dSStefan Eßer 14678bc019dSStefan Eßer #if BC_ENABLE_HISTORY 14778bc019dSStefan Eßer 148252884aeSStefan Eßer #include <stddef.h> 149252884aeSStefan Eßer 150252884aeSStefan Eßer #include <signal.h> 151252884aeSStefan Eßer 15244d4804dSStefan Eßer #ifndef _WIN32 153252884aeSStefan Eßer #include <termios.h> 154252884aeSStefan Eßer #include <time.h> 155252884aeSStefan Eßer #include <unistd.h> 156252884aeSStefan Eßer #include <sys/select.h> 15744d4804dSStefan Eßer #else // _WIN32 15844d4804dSStefan Eßer 15944d4804dSStefan Eßer #ifndef WIN32_LEAN_AND_MEAN 16044d4804dSStefan Eßer #define WIN32_LEAN_AND_MEAN 16144d4804dSStefan Eßer #endif // WIN32_LEAN_AND_MEAN 16244d4804dSStefan Eßer 16344d4804dSStefan Eßer #include <Windows.h> 16444d4804dSStefan Eßer #include <io.h> 16544d4804dSStefan Eßer #include <conio.h> 16644d4804dSStefan Eßer 16744d4804dSStefan Eßer #define strncasecmp _strnicmp 16844d4804dSStefan Eßer #define strcasecmp _stricmp 16944d4804dSStefan Eßer 17044d4804dSStefan Eßer #endif // _WIN32 171252884aeSStefan Eßer 172252884aeSStefan Eßer #include <status.h> 173252884aeSStefan Eßer #include <vector.h> 174252884aeSStefan Eßer #include <read.h> 175252884aeSStefan Eßer 17644d4804dSStefan Eßer /// Default columns. 177252884aeSStefan Eßer #define BC_HIST_DEF_COLS (80) 17844d4804dSStefan Eßer 17944d4804dSStefan Eßer /// Max number of history entries. 180252884aeSStefan Eßer #define BC_HIST_MAX_LEN (128) 18144d4804dSStefan Eßer 18244d4804dSStefan Eßer /// Max length of a line. 183252884aeSStefan Eßer #define BC_HIST_MAX_LINE (4095) 18444d4804dSStefan Eßer 18544d4804dSStefan Eßer /// Max size for cursor position buffer. 186252884aeSStefan Eßer #define BC_HIST_SEQ_SIZE (64) 187252884aeSStefan Eßer 18844d4804dSStefan Eßer /** 18944d4804dSStefan Eßer * The number of entries in the history. 19044d4804dSStefan Eßer * @param h The history data. 19144d4804dSStefan Eßer */ 192252884aeSStefan Eßer #define BC_HIST_BUF_LEN(h) ((h)->buf.len - 1) 19344d4804dSStefan Eßer 19444d4804dSStefan Eßer /** 19544d4804dSStefan Eßer * Read n characters into s and check the error. 19644d4804dSStefan Eßer * @param s The buffer to read into. 19744d4804dSStefan Eßer * @param n The number of bytes to read. 19844d4804dSStefan Eßer * @return True if there was an error, false otherwise. 19944d4804dSStefan Eßer */ 200252884aeSStefan Eßer #define BC_HIST_READ(s, n) (bc_history_read((s), (n)) == -1) 201252884aeSStefan Eßer 20244d4804dSStefan Eßer /// Markers for direction when using arrow keys. 203252884aeSStefan Eßer #define BC_HIST_NEXT (false) 204252884aeSStefan Eßer #define BC_HIST_PREV (true) 205252884aeSStefan Eßer 206252884aeSStefan Eßer #if BC_DEBUG_CODE 207252884aeSStefan Eßer 20844d4804dSStefan Eßer // These are just for debugging. 20944d4804dSStefan Eßer 210252884aeSStefan Eßer #define BC_HISTORY_DEBUG_BUF_SIZE (1024) 211252884aeSStefan Eßer 21278bc019dSStefan Eßer // clang-format off 213252884aeSStefan Eßer #define lndebug(...) \ 21478bc019dSStefan Eßer do \ 21578bc019dSStefan Eßer { \ 21678bc019dSStefan Eßer if (bc_history_debug_fp.fd == 0) \ 21778bc019dSStefan Eßer { \ 218252884aeSStefan Eßer bc_history_debug_buf = bc_vm_malloc(BC_HISTORY_DEBUG_BUF_SIZE); \ 219252884aeSStefan Eßer bc_file_init(&bc_history_debug_fp, \ 220252884aeSStefan Eßer open("/tmp/lndebug.txt", O_APPEND), \ 221252884aeSStefan Eßer BC_HISTORY_DEBUG_BUF_SIZE); \ 222252884aeSStefan Eßer bc_file_printf(&bc_history_debug_fp, \ 223252884aeSStefan Eßer "[%zu %zu %zu] p: %d, rows: %d, " \ 224252884aeSStefan Eßer "rpos: %d, max: %zu, oldmax: %d\n", \ 225252884aeSStefan Eßer l->len, l->pos, l->oldcolpos, plen, rows, rpos, \ 226252884aeSStefan Eßer l->maxrows, old_rows); \ 227252884aeSStefan Eßer } \ 228252884aeSStefan Eßer bc_file_printf(&bc_history_debug_fp, ", " __VA_ARGS__); \ 229252884aeSStefan Eßer bc_file_flush(&bc_history_debug_fp); \ 23078bc019dSStefan Eßer } \ 23178bc019dSStefan Eßer while (0) 232252884aeSStefan Eßer #else // BC_DEBUG_CODE 233252884aeSStefan Eßer #define lndebug(fmt, ...) 234252884aeSStefan Eßer #endif // BC_DEBUG_CODE 23578bc019dSStefan Eßer // clang-format on 236252884aeSStefan Eßer 23744d4804dSStefan Eßer /// An enum of useful actions. To understand what these mean, check terminal 23844d4804dSStefan Eßer /// emulators for their shortcuts or the VT100 codes. 23978bc019dSStefan Eßer typedef enum BcHistoryAction 24078bc019dSStefan Eßer { 241252884aeSStefan Eßer BC_ACTION_NULL = 0, 242252884aeSStefan Eßer BC_ACTION_CTRL_A = 1, 243252884aeSStefan Eßer BC_ACTION_CTRL_B = 2, 244252884aeSStefan Eßer BC_ACTION_CTRL_C = 3, 245252884aeSStefan Eßer BC_ACTION_CTRL_D = 4, 246252884aeSStefan Eßer BC_ACTION_CTRL_E = 5, 247252884aeSStefan Eßer BC_ACTION_CTRL_F = 6, 248252884aeSStefan Eßer BC_ACTION_CTRL_H = 8, 249252884aeSStefan Eßer BC_ACTION_TAB = 9, 250252884aeSStefan Eßer BC_ACTION_LINE_FEED = 10, 251252884aeSStefan Eßer BC_ACTION_CTRL_K = 11, 252252884aeSStefan Eßer BC_ACTION_CTRL_L = 12, 253252884aeSStefan Eßer BC_ACTION_ENTER = 13, 254252884aeSStefan Eßer BC_ACTION_CTRL_N = 14, 255252884aeSStefan Eßer BC_ACTION_CTRL_P = 16, 2568c39e252SStefan Eßer BC_ACTION_CTRL_S = 19, 257252884aeSStefan Eßer BC_ACTION_CTRL_T = 20, 258252884aeSStefan Eßer BC_ACTION_CTRL_U = 21, 259252884aeSStefan Eßer BC_ACTION_CTRL_W = 23, 260252884aeSStefan Eßer BC_ACTION_CTRL_Z = 26, 261252884aeSStefan Eßer BC_ACTION_ESC = 27, 26244d4804dSStefan Eßer BC_ACTION_CTRL_BSLASH = 28, 263252884aeSStefan Eßer BC_ACTION_BACKSPACE = 127 264252884aeSStefan Eßer 265252884aeSStefan Eßer } BcHistoryAction; 266252884aeSStefan Eßer 267252884aeSStefan Eßer /** 268252884aeSStefan Eßer * This represents the state during line editing. We pass this state 269252884aeSStefan Eßer * to functions implementing specific editing functionalities. 270252884aeSStefan Eßer */ 27178bc019dSStefan Eßer typedef struct BcHistory 27278bc019dSStefan Eßer { 273252884aeSStefan Eßer /// Edited line buffer. 274252884aeSStefan Eßer BcVec buf; 275252884aeSStefan Eßer 276252884aeSStefan Eßer /// The history. 277252884aeSStefan Eßer BcVec history; 278252884aeSStefan Eßer 2797e5c51e5SStefan Eßer /// Any material printed without a trailing newline. 2807e5c51e5SStefan Eßer BcVec extras; 2817e5c51e5SStefan Eßer 282252884aeSStefan Eßer /// Prompt to display. 283252884aeSStefan Eßer const char* prompt; 284252884aeSStefan Eßer 285252884aeSStefan Eßer /// Prompt length. 286252884aeSStefan Eßer size_t plen; 287252884aeSStefan Eßer 288252884aeSStefan Eßer /// Prompt column length. 289252884aeSStefan Eßer size_t pcol; 290252884aeSStefan Eßer 291252884aeSStefan Eßer /// Current cursor position. 292252884aeSStefan Eßer size_t pos; 293252884aeSStefan Eßer 294252884aeSStefan Eßer /// Previous refresh cursor column position. 295252884aeSStefan Eßer size_t oldcolpos; 296252884aeSStefan Eßer 297252884aeSStefan Eßer /// Number of columns in terminal. 298252884aeSStefan Eßer size_t cols; 299252884aeSStefan Eßer 300252884aeSStefan Eßer /// The history index we are currently editing. 301252884aeSStefan Eßer size_t idx; 302252884aeSStefan Eßer 30344d4804dSStefan Eßer #ifndef _WIN32 304252884aeSStefan Eßer /// The original terminal state. 305252884aeSStefan Eßer struct termios orig_termios; 30644d4804dSStefan Eßer #else // _WIN32 307d43fa8efSStefan Eßer /// The original input console mode. 308d43fa8efSStefan Eßer DWORD orig_in; 309d43fa8efSStefan Eßer 310d43fa8efSStefan Eßer /// The original output console mode. 311d43fa8efSStefan Eßer DWORD orig_out; 31244d4804dSStefan Eßer #endif // _WIN32 313252884aeSStefan Eßer 31444d4804dSStefan Eßer /// These next two are here because pahole found a 4 byte hole here. 315252884aeSStefan Eßer 316252884aeSStefan Eßer /// Whether we are in rawmode. 317252884aeSStefan Eßer bool rawMode; 318252884aeSStefan Eßer 319252884aeSStefan Eßer /// Whether the terminal is bad. 320252884aeSStefan Eßer bool badTerm; 321252884aeSStefan Eßer 32244d4804dSStefan Eßer #ifndef _WIN32 323252884aeSStefan Eßer /// This is to check if stdin has more data. 324252884aeSStefan Eßer fd_set rdset; 325252884aeSStefan Eßer 326252884aeSStefan Eßer /// This is to check if stdin has more data. 327252884aeSStefan Eßer struct timespec ts; 328252884aeSStefan Eßer 329252884aeSStefan Eßer /// This is to check if stdin has more data. 330252884aeSStefan Eßer sigset_t sigmask; 33144d4804dSStefan Eßer #endif // _WIN32 332252884aeSStefan Eßer 333252884aeSStefan Eßer } BcHistory; 334252884aeSStefan Eßer 33544d4804dSStefan Eßer /** 33644d4804dSStefan Eßer * Frees strings used by history. 33744d4804dSStefan Eßer * @param str The string to free. 33844d4804dSStefan Eßer */ 33978bc019dSStefan Eßer void 34078bc019dSStefan Eßer bc_history_string_free(void* str); 34144d4804dSStefan Eßer 34244d4804dSStefan Eßer // A list of terminals that don't work. 343252884aeSStefan Eßer extern const char* bc_history_bad_terms[]; 34444d4804dSStefan Eßer 34544d4804dSStefan Eßer // A tab in history and its length. 346252884aeSStefan Eßer extern const char bc_history_tab[]; 347252884aeSStefan Eßer extern const size_t bc_history_tab_len; 34844d4804dSStefan Eßer 34944d4804dSStefan Eßer // A ctrl+c string. 350252884aeSStefan Eßer extern const char bc_history_ctrlc[]; 35144d4804dSStefan Eßer 35244d4804dSStefan Eßer // UTF-8 data arrays. 353252884aeSStefan Eßer extern const uint32_t bc_history_wchars[][2]; 354252884aeSStefan Eßer extern const size_t bc_history_wchars_len; 355252884aeSStefan Eßer extern const uint32_t bc_history_combo_chars[]; 356252884aeSStefan Eßer extern const size_t bc_history_combo_chars_len; 35744d4804dSStefan Eßer 358252884aeSStefan Eßer #if BC_DEBUG_CODE 35944d4804dSStefan Eßer 36044d4804dSStefan Eßer // Debug data. 361252884aeSStefan Eßer extern BcFile bc_history_debug_fp; 362252884aeSStefan Eßer extern char* bc_history_debug_buf; 36344d4804dSStefan Eßer 36444d4804dSStefan Eßer /** 36544d4804dSStefan Eßer * A function to print keycodes for debugging. 36644d4804dSStefan Eßer * @param h The history data. 36744d4804dSStefan Eßer */ 36878bc019dSStefan Eßer void 36978bc019dSStefan Eßer bc_history_printKeyCodes(BcHistory* h); 37044d4804dSStefan Eßer 371252884aeSStefan Eßer #endif // BC_DEBUG_CODE 372252884aeSStefan Eßer 373252884aeSStefan Eßer #endif // BC_ENABLE_HISTORY 374252884aeSStefan Eßer 37578bc019dSStefan Eßer #endif // BC_ENABLE_READLINE 37678bc019dSStefan Eßer 37778bc019dSStefan Eßer #endif // BC_ENABLE_EDITLINE 37878bc019dSStefan Eßer 37978bc019dSStefan Eßer #if BC_ENABLE_HISTORY 38078bc019dSStefan Eßer 38178bc019dSStefan Eßer /** 38278bc019dSStefan Eßer * Get a line from stdin using history. This returns a status because I don't 38378bc019dSStefan Eßer * want to throw errors while the terminal is in raw mode. 38478bc019dSStefan Eßer * @param h The history data. 38578bc019dSStefan Eßer * @param vec A vector to put the line into. 38678bc019dSStefan Eßer * @param prompt The prompt to display, if desired. 38778bc019dSStefan Eßer * @return A status indicating an error, if any. Returning a status here 38878bc019dSStefan Eßer * is better because if we throw an error out of history, we 38978bc019dSStefan Eßer * leave the terminal in raw mode or in some other half-baked 39078bc019dSStefan Eßer * state. 39178bc019dSStefan Eßer */ 39278bc019dSStefan Eßer BcStatus 39378bc019dSStefan Eßer bc_history_line(BcHistory* h, BcVec* vec, const char* prompt); 39478bc019dSStefan Eßer 39578bc019dSStefan Eßer /** 39678bc019dSStefan Eßer * Initialize history data. 39778bc019dSStefan Eßer * @param h The struct to initialize. 39878bc019dSStefan Eßer */ 39978bc019dSStefan Eßer void 40078bc019dSStefan Eßer bc_history_init(BcHistory* h); 40178bc019dSStefan Eßer 40278bc019dSStefan Eßer /** 40378bc019dSStefan Eßer * Free history data (and recook the terminal). 40478bc019dSStefan Eßer * @param h The struct to free. 40578bc019dSStefan Eßer */ 40678bc019dSStefan Eßer void 40778bc019dSStefan Eßer bc_history_free(BcHistory* h); 40878bc019dSStefan Eßer 40978bc019dSStefan Eßer #endif // BC_ENABLE_HISTORY 41078bc019dSStefan Eßer 411252884aeSStefan Eßer #endif // BC_HISTORY_H 412