]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - include/history.h
Import version 3.1.4
[FreeBSD/FreeBSD.git] / include / history.h
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, this
12  *   list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright notice,
15  *   this list of conditions and the following disclaimer in the documentation
16  *   and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * *****************************************************************************
31  *
32  * Adapted from the following:
33  *
34  * linenoise.c -- guerrilla line editing library against the idea that a
35  * line editing lib needs to be 20,000 lines of C code.
36  *
37  * You can find the original source code at:
38  *   http://github.com/antirez/linenoise
39  *
40  * You can find the fork that this code is based on at:
41  *   https://github.com/rain-1/linenoise-mob
42  *
43  * ------------------------------------------------------------------------
44  *
45  * This code is also under the following license:
46  *
47  * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>
48  * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
49  *
50  * Redistribution and use in source and binary forms, with or without
51  * modification, are permitted provided that the following conditions are
52  * met:
53  *
54  *  *  Redistributions of source code must retain the above copyright
55  *     notice, this list of conditions and the following disclaimer.
56  *
57  *  *  Redistributions in binary form must reproduce the above copyright
58  *     notice, this list of conditions and the following disclaimer in the
59  *     documentation and/or other materials provided with the distribution.
60  *
61  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
62  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
63  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
64  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
65  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
66  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
67  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
68  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
69  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
70  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
71  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72  *
73  * *****************************************************************************
74  *
75  * Definitions for line history.
76  *
77  */
78
79 #ifndef BC_HISTORY_H
80 #define BC_HISTORY_H
81
82 #ifndef BC_ENABLE_HISTORY
83 #define BC_ENABLE_HISTORY (1)
84 #endif // BC_ENABLE_HISTORY
85
86 #if BC_ENABLE_HISTORY
87
88 #ifdef _WIN32
89 #error History is not supported on Windows.
90 #endif // _WIN32
91
92 #include <stdbool.h>
93 #include <stddef.h>
94
95 #include <signal.h>
96
97 #include <termios.h>
98 #include <time.h>
99 #include <unistd.h>
100 #include <sys/select.h>
101
102 #include <status.h>
103 #include <vector.h>
104 #include <read.h>
105
106 #if BC_DEBUG_CODE
107 #include <file.h>
108 #endif // BC_DEBUG_CODE
109
110 #define BC_HIST_DEF_COLS (80)
111 #define BC_HIST_MAX_LEN (128)
112 #define BC_HIST_MAX_LINE (4095)
113 #define BC_HIST_SEQ_SIZE (64)
114
115 #define BC_HIST_BUF_LEN(h) ((h)->buf.len - 1)
116 #define BC_HIST_READ(s, n) (bc_history_read((s), (n)) == -1)
117
118 #define BC_HIST_NEXT (false)
119 #define BC_HIST_PREV (true)
120
121 #if BC_DEBUG_CODE
122
123 #define BC_HISTORY_DEBUG_BUF_SIZE (1024)
124
125 #define lndebug(...)                                                        \
126         do {                                                                    \
127                 if (bc_history_debug_fp.fd == 0) {                                  \
128                         bc_history_debug_buf = bc_vm_malloc(BC_HISTORY_DEBUG_BUF_SIZE); \
129                         bc_file_init(&bc_history_debug_fp,                              \
130                                      open("/tmp/lndebug.txt", O_APPEND),                \
131                                  BC_HISTORY_DEBUG_BUF_SIZE);                        \
132                         bc_file_printf(&bc_history_debug_fp,                            \
133                                "[%zu %zu %zu] p: %d, rows: %d, "                        \
134                                "rpos: %d, max: %zu, oldmax: %d\n",                      \
135                                l->len, l->pos, l->oldcolpos, plen, rows, rpos,          \
136                                l->maxrows, old_rows);                                   \
137                 }                                                                   \
138                 bc_file_printf(&bc_history_debug_fp, ", " __VA_ARGS__);             \
139                 bc_file_flush(&bc_history_debug_fp);                                \
140         } while (0)
141 #else // BC_DEBUG_CODE
142 #define lndebug(fmt, ...)
143 #endif // BC_DEBUG_CODE
144
145 #if !BC_ENABLE_PROMPT
146 #define bc_history_line(h, vec, prompt) bc_history_line(h, vec)
147 #define bc_history_raw(h, prompt) bc_history_raw(h)
148 #define bc_history_edit(h, prompt) bc_history_edit(h)
149 #endif // BC_ENABLE_PROMPT
150
151 typedef enum BcHistoryAction {
152
153         BC_ACTION_NULL = 0,
154         BC_ACTION_CTRL_A = 1,
155         BC_ACTION_CTRL_B = 2,
156         BC_ACTION_CTRL_C = 3,
157         BC_ACTION_CTRL_D = 4,
158         BC_ACTION_CTRL_E = 5,
159         BC_ACTION_CTRL_F = 6,
160         BC_ACTION_CTRL_H = 8,
161         BC_ACTION_TAB = 9,
162         BC_ACTION_LINE_FEED = 10,
163         BC_ACTION_CTRL_K = 11,
164         BC_ACTION_CTRL_L = 12,
165         BC_ACTION_ENTER = 13,
166         BC_ACTION_CTRL_N = 14,
167         BC_ACTION_CTRL_P = 16,
168         BC_ACTION_CTRL_T = 20,
169         BC_ACTION_CTRL_U = 21,
170         BC_ACTION_CTRL_W = 23,
171         BC_ACTION_CTRL_Z = 26,
172         BC_ACTION_ESC = 27,
173         BC_ACTION_BACKSPACE =  127
174
175 } BcHistoryAction;
176
177 /**
178  * This represents the state during line editing. We pass this state
179  * to functions implementing specific editing functionalities.
180  */
181 typedef struct BcHistory {
182
183         /// Edited line buffer.
184         BcVec buf;
185
186         /// The history.
187         BcVec history;
188
189 #if BC_ENABLE_PROMPT
190         /// Prompt to display.
191         const char *prompt;
192
193         /// Prompt length.
194         size_t plen;
195 #endif // BC_ENABLE_PROMPT
196
197         /// Prompt column length.
198         size_t pcol;
199
200         /// Current cursor position.
201         size_t pos;
202
203         /// Previous refresh cursor column position.
204         size_t oldcolpos;
205
206         /// Number of columns in terminal.
207         size_t cols;
208
209         /// The history index we are currently editing.
210         size_t idx;
211
212         /// The original terminal state.
213         struct termios orig_termios;
214
215         /// These next three are here because pahole found a 4 byte hole here.
216
217         /// This is to signal that there is more, so we don't process yet.
218         bool stdin_has_data;
219
220         /// Whether we are in rawmode.
221         bool rawMode;
222
223         /// Whether the terminal is bad.
224         bool badTerm;
225
226         /// This is to check if stdin has more data.
227         fd_set rdset;
228
229         /// This is to check if stdin has more data.
230         struct timespec ts;
231
232         /// This is to check if stdin has more data.
233         sigset_t sigmask;
234
235 } BcHistory;
236
237 BcStatus bc_history_line(BcHistory *h, BcVec *vec, const char *prompt);
238
239 void bc_history_init(BcHistory *h);
240 void bc_history_free(BcHistory *h);
241
242 extern const char *bc_history_bad_terms[];
243 extern const char bc_history_tab[];
244 extern const size_t bc_history_tab_len;
245 extern const char bc_history_ctrlc[];
246 extern const uint32_t bc_history_wchars[][2];
247 extern const size_t bc_history_wchars_len;
248 extern const uint32_t bc_history_combo_chars[];
249 extern const size_t bc_history_combo_chars_len;
250 #if BC_DEBUG_CODE
251 extern BcFile bc_history_debug_fp;
252 extern char *bc_history_debug_buf;
253 void bc_history_printKeyCodes(BcHistory* l);
254 #endif // BC_DEBUG_CODE
255
256 #endif // BC_ENABLE_HISTORY
257
258 #endif // BC_HISTORY_H