xref: /freebsd/contrib/bc/src/history.c (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2021 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  * Does a number of crazy assumptions that happen to be true in 99.9999% of
76  * the 2010 UNIX computers around.
77  *
78  * References:
79  * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
80  * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
81  *
82  * Todo list:
83  * - Filter bogus Ctrl+<char> combinations.
84  * - Win32 support
85  *
86  * Bloat:
87  * - History search like Ctrl+r in readline?
88  *
89  * List of escape sequences used by this program, we do everything just
90  * with three sequences. In order to be so cheap we may have some
91  * flickering effect with some slow terminal, but the lesser sequences
92  * the more compatible.
93  *
94  * EL (Erase Line)
95  *    Sequence: ESC [ n K
96  *    Effect: if n is 0 or missing, clear from cursor to end of line
97  *    Effect: if n is 1, clear from beginning of line to cursor
98  *    Effect: if n is 2, clear entire line
99  *
100  * CUF (CUrsor Forward)
101  *    Sequence: ESC [ n C
102  *    Effect: moves cursor forward n chars
103  *
104  * CUB (CUrsor Backward)
105  *    Sequence: ESC [ n D
106  *    Effect: moves cursor backward n chars
107  *
108  * The following is used to get the terminal width if getting
109  * the width with the TIOCGWINSZ ioctl fails
110  *
111  * DSR (Device Status Report)
112  *    Sequence: ESC [ 6 n
113  *    Effect: reports the current cusor position as ESC [ n ; m R
114  *            where n is the row and m is the column
115  *
116  * When multi line mode is enabled, we also use two additional escape
117  * sequences. However multi line editing is disabled by default.
118  *
119  * CUU (CUrsor Up)
120  *    Sequence: ESC [ n A
121  *    Effect: moves cursor up of n chars.
122  *
123  * CUD (CUrsor Down)
124  *    Sequence: ESC [ n B
125  *    Effect: moves cursor down of n chars.
126  *
127  * When bc_history_clearScreen() is called, two additional escape sequences
128  * are used in order to clear the screen and position the cursor at home
129  * position.
130  *
131  * CUP (CUrsor Position)
132  *    Sequence: ESC [ H
133  *    Effect: moves the cursor to upper left corner
134  *
135  * ED (Erase Display)
136  *    Sequence: ESC [ 2 J
137  *    Effect: clear the whole screen
138  *
139  * *****************************************************************************
140  *
141  * Code for line history.
142  *
143  */
144 
145 #if BC_ENABLE_HISTORY
146 
147 #include <assert.h>
148 #include <stdlib.h>
149 #include <errno.h>
150 #include <string.h>
151 #include <ctype.h>
152 
153 #include <signal.h>
154 #include <sys/stat.h>
155 #include <sys/types.h>
156 
157 #ifndef _WIN32
158 #include <strings.h>
159 #include <termios.h>
160 #include <unistd.h>
161 #include <sys/ioctl.h>
162 #include <sys/select.h>
163 #endif // _WIN32
164 
165 #include <status.h>
166 #include <vector.h>
167 #include <history.h>
168 #include <read.h>
169 #include <file.h>
170 #include <vm.h>
171 
172 #if BC_DEBUG_CODE
173 
174 /// A file for outputting to when debugging.
175 BcFile bc_history_debug_fp;
176 
177 /// A buffer for the above file.
178 char *bc_history_debug_buf;
179 
180 #endif // BC_DEBUG_CODE
181 
182 /**
183  * Checks if the code is a wide character.
184  * @param cp  The codepoint to check.
185  * @return    True if @a cp is a wide character, false otherwise.
186  */
187 static bool bc_history_wchar(uint32_t cp) {
188 
189 	size_t i;
190 
191 	for (i = 0; i < bc_history_wchars_len; ++i) {
192 
193 		// Ranges are listed in ascending order.  Therefore, once the
194 		// whole range is higher than the codepoint we're testing, the
195 		// codepoint won't be found in any remaining range => bail early.
196 		if (bc_history_wchars[i][0] > cp) return false;
197 
198 		// Test this range.
199 		if (bc_history_wchars[i][0] <= cp && cp <= bc_history_wchars[i][1])
200 			return true;
201 	}
202 
203 	return false;
204 }
205 
206 /**
207  * Checks if the code is a combining character.
208  * @param cp  The codepoint to check.
209  * @return    True if @a cp is a combining character, false otherwise.
210  */
211 static bool bc_history_comboChar(uint32_t cp) {
212 
213 	size_t i;
214 
215 	for (i = 0; i < bc_history_combo_chars_len; ++i) {
216 
217 		// Combining chars are listed in ascending order, so once we pass
218 		// the codepoint of interest, we know it's not a combining char.
219 		if (bc_history_combo_chars[i] > cp) return false;
220 		if (bc_history_combo_chars[i] == cp) return true;
221 	}
222 
223 	return false;
224 }
225 
226 /**
227  * Gets the length of previous UTF8 character.
228  * @param buf  The buffer of characters.
229  * @param pos  The index into the buffer.
230  */
231 static size_t bc_history_prevCharLen(const char *buf, size_t pos) {
232 	size_t end = pos;
233 	for (pos -= 1; pos < end && (buf[pos] & 0xC0) == 0x80; --pos);
234 	return end - (pos >= end ? 0 : pos);
235 }
236 
237 /**
238  * Converts UTF-8 to a Unicode code point.
239  * @param s    The string.
240  * @param len  The length of the string.
241  * @param cp   An out parameter for the codepoint.
242  * @return     The number of bytes eaten by the codepoint.
243  */
244 static size_t bc_history_codePoint(const char *s, size_t len, uint32_t *cp) {
245 
246 	if (len) {
247 
248 		uchar byte = (uchar) s[0];
249 
250 		// This is literally the UTF-8 decoding algorithm. Look that up if you
251 		// don't understand this.
252 
253 		if ((byte & 0x80) == 0) {
254 			*cp = byte;
255 			return 1;
256 		}
257 		else if ((byte & 0xE0) == 0xC0) {
258 
259 			if (len >= 2) {
260 				*cp = (((uint32_t) (s[0] & 0x1F)) << 6) |
261 					   ((uint32_t) (s[1] & 0x3F));
262 				return 2;
263 			}
264 		}
265 		else if ((byte & 0xF0) == 0xE0) {
266 
267 			if (len >= 3) {
268 				*cp = (((uint32_t) (s[0] & 0x0F)) << 12) |
269 					  (((uint32_t) (s[1] & 0x3F)) << 6) |
270 					   ((uint32_t) (s[2] & 0x3F));
271 				return 3;
272 			}
273 		}
274 		else if ((byte & 0xF8) == 0xF0) {
275 
276 			if (len >= 4) {
277 				*cp = (((uint32_t) (s[0] & 0x07)) << 18) |
278 					  (((uint32_t) (s[1] & 0x3F)) << 12) |
279 					  (((uint32_t) (s[2] & 0x3F)) << 6) |
280 					   ((uint32_t) (s[3] & 0x3F));
281 				return 4;
282 			}
283 		}
284 		else {
285 			*cp = 0xFFFD;
286 			return 1;
287 		}
288 	}
289 
290 	*cp = 0;
291 
292 	return 1;
293 }
294 
295 /**
296  * Gets the length of next grapheme.
297  * @param buf      The buffer.
298  * @param buf_len  The length of the buffer.
299  * @param pos      The index into the buffer.
300  * @param col_len  An out parameter for the length of the grapheme on screen.
301  * @return         The number of bytes in the grapheme.
302  */
303 static size_t bc_history_nextLen(const char *buf, size_t buf_len,
304                                  size_t pos, size_t *col_len)
305 {
306 	uint32_t cp;
307 	size_t beg = pos;
308 	size_t len = bc_history_codePoint(buf + pos, buf_len - pos, &cp);
309 
310 	if (bc_history_comboChar(cp)) {
311 
312 		BC_UNREACHABLE
313 
314 		if (col_len != NULL) *col_len = 0;
315 
316 		return 0;
317 	}
318 
319 	// Store the width of the character on screen.
320 	if (col_len != NULL) *col_len = bc_history_wchar(cp) ? 2 : 1;
321 
322 	pos += len;
323 
324 	// Find the first non-combining character.
325 	while (pos < buf_len) {
326 
327 		len = bc_history_codePoint(buf + pos, buf_len - pos, &cp);
328 
329 		if (!bc_history_comboChar(cp)) return pos - beg;
330 
331 		pos += len;
332 	}
333 
334 	return pos - beg;
335 }
336 
337 /**
338  * Gets the length of previous grapheme.
339  * @param buf  The buffer.
340  * @param pos  The index into the buffer.
341  * @return     The number of bytes in the grapheme.
342  */
343 static size_t bc_history_prevLen(const char *buf, size_t pos) {
344 
345 	size_t end = pos;
346 
347 	// Find the first non-combining character.
348 	while (pos > 0) {
349 
350 		uint32_t cp;
351 		size_t len = bc_history_prevCharLen(buf, pos);
352 
353 		pos -= len;
354 		bc_history_codePoint(buf + pos, len, &cp);
355 
356 		// The original linenoise-mob had an extra parameter col_len, like
357 		// bc_history_nextLen(), which, if not NULL, was set in this if
358 		// statement. However, we always passed NULL, so just skip that.
359 		if (!bc_history_comboChar(cp)) return end - pos;
360 	}
361 
362 	BC_UNREACHABLE
363 
364 	return 0;
365 }
366 
367 /**
368  * Reads @a n characters from stdin.
369  * @param buf  The buffer to read into. The caller is responsible for making
370  *             sure this is big enough for @a n.
371  * @param n    The number of characters to read.
372  * @return     The number of characters read or less than 0 on error.
373  */
374 static ssize_t bc_history_read(char *buf, size_t n) {
375 
376 	ssize_t ret;
377 
378 	BC_SIG_ASSERT_LOCKED;
379 
380 #ifndef _WIN32
381 
382 	do {
383 		// We don't care about being interrupted.
384 		ret = read(STDIN_FILENO, buf, n);
385 	} while (ret == EINTR);
386 
387 #else // _WIN32
388 
389 	bool good;
390 	DWORD read;
391 	HANDLE hn = GetStdHandle(STD_INPUT_HANDLE);
392 
393 	good = ReadConsole(hn, buf, (DWORD) n, &read, NULL);
394 
395 	ret = (read != n) ? -1 : 1;
396 
397 #endif // _WIN32
398 
399 	return ret;
400 }
401 
402 /**
403  * Reads a Unicode code point into a buffer.
404  * @param buf      The buffer to read into.
405  * @param buf_len  The length of the buffer.
406  * @param cp       An out parameter for the codepoint.
407  * @param nread    An out parameter for the number of bytes read.
408  * @return         BC_STATUS_EOF or BC_STATUS_SUCCESS.
409  */
410 static BcStatus bc_history_readCode(char *buf, size_t buf_len,
411                                     uint32_t *cp, size_t *nread)
412 {
413 	ssize_t n;
414 
415 	assert(buf_len >= 1);
416 
417 	BC_SIG_LOCK;
418 
419 	// Read a byte.
420 	n = bc_history_read(buf, 1);
421 
422 	BC_SIG_UNLOCK;
423 
424 	if (BC_ERR(n <= 0)) goto err;
425 
426 	// Get the byte.
427 	uchar byte = ((uchar*) buf)[0];
428 
429 	// Once again, this is the UTF-8 decoding algorithm, but it has reads
430 	// instead of actual decoding.
431 	if ((byte & 0x80) != 0) {
432 
433 		if ((byte & 0xE0) == 0xC0) {
434 
435 			assert(buf_len >= 2);
436 
437 			BC_SIG_LOCK;
438 
439 			n = bc_history_read(buf + 1, 1);
440 
441 			BC_SIG_UNLOCK;
442 
443 			if (BC_ERR(n <= 0)) goto err;
444 		}
445 		else if ((byte & 0xF0) == 0xE0) {
446 
447 			assert(buf_len >= 3);
448 
449 			BC_SIG_LOCK;
450 
451 			n = bc_history_read(buf + 1, 2);
452 
453 			BC_SIG_UNLOCK;
454 
455 			if (BC_ERR(n <= 0)) goto err;
456 		}
457 		else if ((byte & 0xF8) == 0xF0) {
458 
459 			assert(buf_len >= 3);
460 
461 			BC_SIG_LOCK;
462 
463 			n = bc_history_read(buf + 1, 3);
464 
465 			BC_SIG_UNLOCK;
466 
467 			if (BC_ERR(n <= 0)) goto err;
468 		}
469 		else {
470 			n = -1;
471 			goto err;
472 		}
473 	}
474 
475 	// Convert to the codepoint.
476 	*nread = bc_history_codePoint(buf, buf_len, cp);
477 
478 	return BC_STATUS_SUCCESS;
479 
480 err:
481 	// If we get here, we either had a fatal error of EOF.
482 	if (BC_ERR(n < 0)) bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
483 	else *nread = (size_t) n;
484 	return BC_STATUS_EOF;
485 }
486 
487 /**
488  * Gets the column length from beginning of buffer to current byte position.
489  * @param buf      The buffer.
490  * @param buf_len  The length of the buffer.
491  * @param pos      The index into the buffer.
492  * @return         The number of columns between the beginning of @a buffer to
493  *                 @a pos.
494  */
495 static size_t bc_history_colPos(const char *buf, size_t buf_len, size_t pos) {
496 
497 	size_t ret = 0, off = 0;
498 
499 	// While we haven't reached the offset, get the length of the next grapheme.
500 	while (off < pos && off < buf_len) {
501 
502 		size_t col_len, len;
503 
504 		len = bc_history_nextLen(buf, buf_len, off, &col_len);
505 
506 		off += len;
507 		ret += col_len;
508 	}
509 
510 	return ret;
511 }
512 
513 /**
514  * Returns true if the terminal name is in the list of terminals we know are
515  * not able to understand basic escape sequences.
516  * @return  True if the terminal is a bad terminal.
517  */
518 static inline bool bc_history_isBadTerm(void) {
519 
520 	size_t i;
521 	bool ret = false;
522 	char *term = bc_vm_getenv("TERM");
523 
524 	if (term == NULL) return false;
525 
526 	for (i = 0; !ret && bc_history_bad_terms[i]; ++i)
527 		ret = (!strcasecmp(term, bc_history_bad_terms[i]));
528 
529 	bc_vm_getenvFree(term);
530 
531 	return ret;
532 }
533 
534 /**
535  * Enables raw mode (1960's black magic).
536  * @param h  The history data.
537  */
538 static void bc_history_enableRaw(BcHistory *h) {
539 
540 	// I don't do anything for Windows because in Windows, you set their
541 	// equivalent of raw mode and leave it, so I do it in bc_history_init().
542 
543 #ifndef _WIN32
544 	struct termios raw;
545 	int err;
546 
547 	assert(BC_TTYIN);
548 
549 	if (h->rawMode) return;
550 
551 	BC_SIG_LOCK;
552 
553 	if (BC_ERR(tcgetattr(STDIN_FILENO, &h->orig_termios) == -1))
554 		bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
555 
556 	BC_SIG_UNLOCK;
557 
558 	// Modify the original mode.
559 	raw = h->orig_termios;
560 
561 	// Input modes: no break, no CR to NL, no parity check, no strip char,
562 	// no start/stop output control.
563 	raw.c_iflag &= (unsigned int) (~(BRKINT | ICRNL | INPCK | ISTRIP | IXON));
564 
565 	// Control modes: set 8 bit chars.
566 	raw.c_cflag |= (CS8);
567 
568 	// Local modes - choing off, canonical off, no extended functions,
569 	// no signal chars (^Z,^C).
570 	raw.c_lflag &= (unsigned int) (~(ECHO | ICANON | IEXTEN | ISIG));
571 
572 	// Control chars - set return condition: min number of bytes and timer.
573 	// We want read to give every single byte, w/o timeout (1 byte, no timer).
574 	raw.c_cc[VMIN] = 1;
575 	raw.c_cc[VTIME] = 0;
576 
577 	BC_SIG_LOCK;
578 
579 	// Put terminal in raw mode after flushing.
580 	do {
581 		err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
582 	} while (BC_ERR(err < 0) && errno == EINTR);
583 
584 	BC_SIG_UNLOCK;
585 
586 	if (BC_ERR(err < 0)) bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
587 #endif // _WIN32
588 
589 	h->rawMode = true;
590 }
591 
592 /**
593  * Disables raw mode.
594  * @param h  The history data.
595  */
596 static void bc_history_disableRaw(BcHistory *h) {
597 
598 	sig_atomic_t lock;
599 
600 	if (!h->rawMode) return;
601 
602 	BC_SIG_TRYLOCK(lock);
603 
604 #ifndef _WIN32
605 	if (BC_ERR(tcsetattr(STDIN_FILENO, TCSAFLUSH, &h->orig_termios) != -1))
606 		h->rawMode = false;
607 #endif // _WIN32
608 
609 	BC_SIG_TRYUNLOCK(lock);
610 }
611 
612 /**
613  * Uses the ESC [6n escape sequence to query the horizontal cursor position
614  * and return it. On error -1 is returned, on success the position of the
615  * cursor.
616  * @return  The horizontal cursor position.
617  */
618 static size_t bc_history_cursorPos(void) {
619 
620 	char buf[BC_HIST_SEQ_SIZE];
621 	char *ptr, *ptr2;
622 	size_t cols, rows, i;
623 
624 	BC_SIG_ASSERT_LOCKED;
625 
626 	// Report cursor location.
627 	bc_file_write(&vm.fout, bc_flush_none, "\x1b[6n", 4);
628 	bc_file_flush(&vm.fout, bc_flush_none);
629 
630 	// Read the response: ESC [ rows ; cols R.
631 	for (i = 0; i < sizeof(buf) - 1; ++i) {
632 		if (bc_history_read(buf + i, 1) != 1 || buf[i] == 'R') break;
633 	}
634 
635 	buf[i] = '\0';
636 
637 	// This is basically an error; we didn't get what we were expecting.
638 	if (BC_ERR(buf[0] != BC_ACTION_ESC || buf[1] != '[')) return SIZE_MAX;
639 
640 	// Parse the rows.
641 	ptr = buf + 2;
642 	rows = strtoul(ptr, &ptr2, 10);
643 
644 	// Here we also didn't get what we were expecting.
645 	if (BC_ERR(!rows || ptr2[0] != ';')) return SIZE_MAX;
646 
647 	// Parse the columns.
648 	ptr = ptr2 + 1;
649 	cols = strtoul(ptr, NULL, 10);
650 
651 	if (BC_ERR(!cols)) return SIZE_MAX;
652 
653 	return cols <= UINT16_MAX ? cols : 0;
654 }
655 
656 /**
657  * Tries to get the number of columns in the current terminal, or assume 80
658  * if it fails.
659  * @return  The number of columns in the terminal.
660  */
661 static size_t bc_history_columns(void) {
662 
663 #ifndef _WIN32
664 
665 	struct winsize ws;
666 	int ret;
667 
668 	ret = ioctl(vm.fout.fd, TIOCGWINSZ, &ws);
669 
670 	if (BC_ERR(ret == -1 || !ws.ws_col)) {
671 
672 		// Calling ioctl() failed. Try to query the terminal itself.
673 		size_t start, cols;
674 
675 		// Get the initial position so we can restore it later.
676 		start = bc_history_cursorPos();
677 		if (BC_ERR(start == SIZE_MAX)) return BC_HIST_DEF_COLS;
678 
679 		// Go to right margin and get position.
680 		bc_file_write(&vm.fout, bc_flush_none, "\x1b[999C", 6);
681 		bc_file_flush(&vm.fout, bc_flush_none);
682 		cols = bc_history_cursorPos();
683 		if (BC_ERR(cols == SIZE_MAX)) return BC_HIST_DEF_COLS;
684 
685 		// Restore position.
686 		if (cols > start) {
687 			bc_file_printf(&vm.fout, "\x1b[%zuD", cols - start);
688 			bc_file_flush(&vm.fout, bc_flush_none);
689 		}
690 
691 		return cols;
692 	}
693 
694 	return ws.ws_col;
695 
696 #else // _WIN32
697 
698 	CONSOLE_SCREEN_BUFFER_INFO csbi;
699 
700 	if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
701 		return 80;
702 
703 	return ((size_t) (csbi.srWindow.Right)) - csbi.srWindow.Left + 1;
704 
705 #endif // _WIN32
706 }
707 
708 /**
709  * Gets the column length of prompt text. This is probably unnecessary because
710  * the prompts that I use are ASCII, but I kept it just in case.
711  * @param prompt  The prompt.
712  * @param plen    The length of the prompt.
713  * @return        The column length of the prompt.
714  */
715 static size_t bc_history_promptColLen(const char *prompt, size_t plen) {
716 
717 	char buf[BC_HIST_MAX_LINE + 1];
718 	size_t buf_len = 0, off = 0;
719 
720 	// The original linenoise-mob checked for ANSI escapes here on the prompt. I
721 	// know the prompts do not have ANSI escapes. I deleted the code.
722 	while (off < plen) buf[buf_len++] = prompt[off++];
723 
724 	return bc_history_colPos(buf, buf_len, buf_len);
725 }
726 
727 /**
728  * Rewrites the currently edited line accordingly to the buffer content,
729  * cursor position, and number of columns of the terminal.
730  * @param h  The history data.
731  */
732 static void bc_history_refresh(BcHistory *h) {
733 
734 	char* buf = h->buf.v;
735 	size_t colpos, len = BC_HIST_BUF_LEN(h), pos = h->pos, extras_len = 0;
736 
737 	BC_SIG_ASSERT_LOCKED;
738 
739 	bc_file_flush(&vm.fout, bc_flush_none);
740 
741 	// Get to the prompt column position from the left.
742 	while(h->pcol + bc_history_colPos(buf, len, pos) >= h->cols) {
743 
744 		size_t chlen = bc_history_nextLen(buf, len, 0, NULL);
745 
746 		buf += chlen;
747 		len -= chlen;
748 		pos -= chlen;
749 	}
750 
751 	// Get to the prompt column position from the right.
752 	while (h->pcol + bc_history_colPos(buf, len, len) > h->cols)
753 		len -= bc_history_prevLen(buf, len);
754 
755 	// Cursor to left edge.
756 	bc_file_write(&vm.fout, bc_flush_none, "\r", 1);
757 
758 	// Take the extra stuff into account. This is where history makes sure to
759 	// preserve stuff that was printed without a newline.
760 	if (h->extras.len > 1) {
761 
762 		extras_len = h->extras.len - 1;
763 
764 		bc_vec_grow(&h->buf, extras_len);
765 
766 		len += extras_len;
767 		pos += extras_len;
768 
769 		bc_file_write(&vm.fout, bc_flush_none, h->extras.v, extras_len);
770 	}
771 
772 	// Write the prompt, if desired.
773 	if (BC_PROMPT) bc_file_write(&vm.fout, bc_flush_none, h->prompt, h->plen);
774 
775 	bc_file_write(&vm.fout, bc_flush_none, h->buf.v, len - extras_len);
776 
777 	// Erase to right.
778 	bc_file_write(&vm.fout, bc_flush_none, "\x1b[0K", 4);
779 
780 	// We need to be sure to grow this.
781 	if (pos >= h->buf.len - extras_len)
782 		bc_vec_grow(&h->buf, pos + extras_len);
783 
784 	// Move cursor to original position. Do NOT move the putchar of '\r' to the
785 	// printf with colpos. That causes a bug where the cursor will go to the end
786 	// of the line when there is no prompt.
787 	bc_file_putchar(&vm.fout, bc_flush_none, '\r');
788 	colpos = bc_history_colPos(h->buf.v, len - extras_len, pos) + h->pcol;
789 
790 	// Set the cursor position again.
791 	if (colpos) bc_file_printf(&vm.fout, "\x1b[%zuC", colpos);
792 
793 	bc_file_flush(&vm.fout, bc_flush_none);
794 }
795 
796 /**
797  * Inserts the character(s) 'c' at cursor current position.
798  * @param h     The history data.
799  * @param cbuf  The character buffer to copy from.
800  * @param clen  The number of characters to copy.
801  */
802 static void bc_history_edit_insert(BcHistory *h, const char *cbuf, size_t clen)
803 {
804 	BC_SIG_ASSERT_LOCKED;
805 
806 	bc_vec_grow(&h->buf, clen);
807 
808 	// If we are at the end of the line...
809 	if (h->pos == BC_HIST_BUF_LEN(h)) {
810 
811 		size_t colpos = 0, len;
812 
813 		// Copy into the buffer.
814 		memcpy(bc_vec_item(&h->buf, h->pos), cbuf, clen);
815 
816 		// Adjust the buffer.
817 		h->pos += clen;
818 		h->buf.len += clen - 1;
819 		bc_vec_pushByte(&h->buf, '\0');
820 
821 		// Set the length and column position.
822 		len = BC_HIST_BUF_LEN(h) + h->extras.len - 1;
823 		colpos = bc_history_promptColLen(h->prompt, h->plen);
824 		colpos += bc_history_colPos(h->buf.v, len, len);
825 
826 		// Do we have the trivial case?
827 		if (colpos < h->cols) {
828 
829 			// Avoid a full update of the line in the trivial case.
830 			bc_file_write(&vm.fout, bc_flush_none, cbuf, clen);
831 			bc_file_flush(&vm.fout, bc_flush_none);
832 		}
833 		else bc_history_refresh(h);
834 	}
835 	else {
836 
837 		// Amount that we need to move.
838 		size_t amt = BC_HIST_BUF_LEN(h) - h->pos;
839 
840 		// Move the stuff.
841 		memmove(h->buf.v + h->pos + clen, h->buf.v + h->pos, amt);
842 		memcpy(h->buf.v + h->pos, cbuf, clen);
843 
844 		// Adjust the buffer.
845 		h->pos += clen;
846 		h->buf.len += clen;
847 		h->buf.v[BC_HIST_BUF_LEN(h)] = '\0';
848 
849 		bc_history_refresh(h);
850 	}
851 }
852 
853 /**
854  * Moves the cursor to the left.
855  * @param h  The history data.
856  */
857 static void bc_history_edit_left(BcHistory *h) {
858 
859 	BC_SIG_ASSERT_LOCKED;
860 
861 	// Stop at the left end.
862 	if (h->pos <= 0) return;
863 
864 	h->pos -= bc_history_prevLen(h->buf.v, h->pos);
865 
866 	bc_history_refresh(h);
867 }
868 
869 /**
870  * Moves the cursor to the right.
871  * @param h  The history data.
872 */
873 static void bc_history_edit_right(BcHistory *h) {
874 
875 	BC_SIG_ASSERT_LOCKED;
876 
877 	// Stop at the right end.
878 	if (h->pos == BC_HIST_BUF_LEN(h)) return;
879 
880 	h->pos += bc_history_nextLen(h->buf.v, BC_HIST_BUF_LEN(h), h->pos, NULL);
881 
882 	bc_history_refresh(h);
883 }
884 
885 /**
886  * Moves the cursor to the end of the current word.
887  * @param h  The history data.
888  */
889 static void bc_history_edit_wordEnd(BcHistory *h) {
890 
891 	size_t len = BC_HIST_BUF_LEN(h);
892 
893 	BC_SIG_ASSERT_LOCKED;
894 
895 	// Don't overflow.
896 	if (!len || h->pos >= len) return;
897 
898 	// Find the word, then find the end of it.
899 	while (h->pos < len && isspace(h->buf.v[h->pos])) h->pos += 1;
900 	while (h->pos < len && !isspace(h->buf.v[h->pos])) h->pos += 1;
901 
902 	bc_history_refresh(h);
903 }
904 
905 /**
906  * Moves the cursor to the start of the current word.
907  * @param h  The history data.
908  */
909 static void bc_history_edit_wordStart(BcHistory *h) {
910 
911 	size_t len = BC_HIST_BUF_LEN(h);
912 
913 	BC_SIG_ASSERT_LOCKED;
914 
915 	// Stop with no data.
916 	if (!len) return;
917 
918 	// Find the word, the find the beginning of the word.
919 	while (h->pos > 0 && isspace(h->buf.v[h->pos - 1])) h->pos -= 1;
920 	while (h->pos > 0 && !isspace(h->buf.v[h->pos - 1])) h->pos -= 1;
921 
922 	bc_history_refresh(h);
923 }
924 
925 /**
926  * Moves the cursor to the start of the line.
927  * @param h  The history data.
928  */
929 static void bc_history_edit_home(BcHistory *h) {
930 
931 	BC_SIG_ASSERT_LOCKED;
932 
933 	// Stop at the beginning.
934 	if (!h->pos) return;
935 
936 	h->pos = 0;
937 
938 	bc_history_refresh(h);
939 }
940 
941 /**
942  * Moves the cursor to the end of the line.
943  * @param h  The history data.
944  */
945 static void bc_history_edit_end(BcHistory *h) {
946 
947 	BC_SIG_ASSERT_LOCKED;
948 
949 	// Stop at the end of the line.
950 	if (h->pos == BC_HIST_BUF_LEN(h)) return;
951 
952 	h->pos = BC_HIST_BUF_LEN(h);
953 
954 	bc_history_refresh(h);
955 }
956 
957 /**
958  * Substitutes the currently edited line with the next or previous history
959  * entry as specified by 'dir' (direction).
960  * @param h    The history data.
961  * @param dir  The direction to substitute; true means previous, false next.
962  */
963 static void bc_history_edit_next(BcHistory *h, bool dir) {
964 
965 	const char *dup, *str;
966 
967 	BC_SIG_ASSERT_LOCKED;
968 
969 	// Stop if there is no history.
970 	if (h->history.len <= 1) return;
971 
972 	// Duplicate the buffer.
973 	if (h->buf.v[0]) dup = bc_vm_strdup(h->buf.v);
974 	else dup = "";
975 
976 	// Update the current history entry before overwriting it with the next one.
977 	bc_vec_replaceAt(&h->history, h->history.len - 1 - h->idx, &dup);
978 
979 	// Show the new entry.
980 	h->idx += (dir == BC_HIST_PREV ? 1 : SIZE_MAX);
981 
982 	// Se the index appropriately at the ends.
983 	if (h->idx == SIZE_MAX) {
984 		h->idx = 0;
985 		return;
986 	}
987 	else if (h->idx >= h->history.len) {
988 		h->idx = h->history.len - 1;
989 		return;
990 	}
991 
992 	// Get the string.
993 	str = *((char**) bc_vec_item(&h->history, h->history.len - 1 - h->idx));
994 	bc_vec_string(&h->buf, strlen(str), str);
995 
996 	assert(h->buf.len > 0);
997 
998 	// Set the position at the end.
999 	h->pos = BC_HIST_BUF_LEN(h);
1000 
1001 	bc_history_refresh(h);
1002 }
1003 
1004 /**
1005  * Deletes the character at the right of the cursor without altering the cursor
1006  * position. Basically, this is what happens with the "Delete" keyboard key.
1007  * @param h  The history data.
1008  */
1009 static void bc_history_edit_delete(BcHistory *h) {
1010 
1011 	size_t chlen, len = BC_HIST_BUF_LEN(h);
1012 
1013 	BC_SIG_ASSERT_LOCKED;
1014 
1015 	// If there is no character, skip.
1016 	if (!len || h->pos >= len) return;
1017 
1018 	// Get the length of the character.
1019 	chlen = bc_history_nextLen(h->buf.v, len, h->pos, NULL);
1020 
1021 	// Move characters after it into its place.
1022 	memmove(h->buf.v + h->pos, h->buf.v + h->pos + chlen, len - h->pos - chlen);
1023 
1024 	// Make the buffer valid again.
1025 	h->buf.len -= chlen;
1026 	h->buf.v[BC_HIST_BUF_LEN(h)] = '\0';
1027 
1028 	bc_history_refresh(h);
1029 }
1030 
1031 /**
1032  * Deletes the character to the left of the cursor and moves the cursor back one
1033  * space. Basically, this is what happens with the "Backspace" keyboard key.
1034  * @param h  The history data.
1035  */
1036 static void bc_history_edit_backspace(BcHistory *h) {
1037 
1038 	size_t chlen, len = BC_HIST_BUF_LEN(h);
1039 
1040 	BC_SIG_ASSERT_LOCKED;
1041 
1042 	// If there are no characters, skip.
1043 	if (!h->pos || !len) return;
1044 
1045 	// Get the length of the previous character.
1046 	chlen = bc_history_prevLen(h->buf.v, h->pos);
1047 
1048 	// Move everything back one.
1049 	memmove(h->buf.v + h->pos - chlen, h->buf.v + h->pos, len - h->pos);
1050 
1051 	// Make the buffer valid again.
1052 	h->pos -= chlen;
1053 	h->buf.len -= chlen;
1054 	h->buf.v[BC_HIST_BUF_LEN(h)] = '\0';
1055 
1056 	bc_history_refresh(h);
1057 }
1058 
1059 /**
1060  * Deletes the previous word, maintaining the cursor at the start of the
1061  * current word.
1062  * @param h  The history data.
1063  */
1064 static void bc_history_edit_deletePrevWord(BcHistory *h) {
1065 
1066 	size_t diff, old_pos = h->pos;
1067 
1068 	BC_SIG_ASSERT_LOCKED;
1069 
1070 	// If at the beginning of the line, skip.
1071 	if (!old_pos) return;
1072 
1073 	// Find the word, then the beginning of the word.
1074 	while (h->pos > 0 && isspace(h->buf.v[h->pos - 1])) --h->pos;
1075 	while (h->pos > 0 && !isspace(h->buf.v[h->pos - 1])) --h->pos;
1076 
1077 	// Get the difference in position.
1078 	diff = old_pos - h->pos;
1079 
1080 	// Move the data back.
1081 	memmove(h->buf.v + h->pos, h->buf.v + old_pos,
1082 	        BC_HIST_BUF_LEN(h) - old_pos + 1);
1083 
1084 	// Make the buffer valid again.
1085 	h->buf.len -= diff;
1086 
1087 	bc_history_refresh(h);
1088 }
1089 
1090 /**
1091  * Deletes the next word, maintaining the cursor at the same position.
1092  * @param h  The history data.
1093  */
1094 static void bc_history_edit_deleteNextWord(BcHistory *h) {
1095 
1096 	size_t next_end = h->pos, len = BC_HIST_BUF_LEN(h);
1097 
1098 	BC_SIG_ASSERT_LOCKED;
1099 
1100 	// If at the end of the line, skip.
1101 	if (next_end == len) return;
1102 
1103 	// Find the word, then the end of the word.
1104 	while (next_end < len && isspace(h->buf.v[next_end])) ++next_end;
1105 	while (next_end < len && !isspace(h->buf.v[next_end])) ++next_end;
1106 
1107 	// Move the stuff into position.
1108 	memmove(h->buf.v + h->pos, h->buf.v + next_end, len - next_end);
1109 
1110 	// Make the buffer valid again.
1111 	h->buf.len -= next_end - h->pos;
1112 
1113 	bc_history_refresh(h);
1114 }
1115 
1116 /**
1117  * Swaps two characters, the one under the cursor and the one to the left.
1118  * @param h  The history data.
1119  */
1120 static void bc_history_swap(BcHistory *h) {
1121 
1122 	size_t pcl, ncl;
1123 	char auxb[5];
1124 
1125 	BC_SIG_ASSERT_LOCKED;
1126 
1127 	// Get the length of the previous and next characters.
1128 	pcl = bc_history_prevLen(h->buf.v, h->pos);
1129 	ncl = bc_history_nextLen(h->buf.v, BC_HIST_BUF_LEN(h), h->pos, NULL);
1130 
1131 	// To perform a swap we need:
1132 	// * Nonzero char length to the left.
1133 	// * To not be at the end of the line.
1134 	if (pcl && h->pos != BC_HIST_BUF_LEN(h) && pcl < 5 && ncl < 5) {
1135 
1136 		// Swap.
1137 		memcpy(auxb, h->buf.v + h->pos - pcl, pcl);
1138 		memcpy(h->buf.v + h->pos - pcl, h->buf.v + h->pos, ncl);
1139 		memcpy(h->buf.v + h->pos - pcl + ncl, auxb, pcl);
1140 
1141 		// Reset the position.
1142 		h->pos += ((~pcl) + 1) + ncl;
1143 
1144 		bc_history_refresh(h);
1145 	}
1146 }
1147 
1148 /**
1149  * Raises the specified signal. This is a convenience function.
1150  * @param h    The history data.
1151  * @param sig  The signal to raise.
1152  */
1153 static void bc_history_raise(BcHistory *h, int sig) {
1154 
1155 	// We really don't want to be in raw mode when longjmp()'s are flying.
1156 	bc_history_disableRaw(h);
1157 	raise(sig);
1158 }
1159 
1160 /**
1161  * Handles escape sequences. This function will make sense if you know VT100
1162  * escape codes; otherwise, it will be confusing.
1163  * @param h  The history data.
1164  */
1165 static void bc_history_escape(BcHistory *h) {
1166 
1167 	char c, seq[3];
1168 
1169 	BC_SIG_ASSERT_LOCKED;
1170 
1171 	// Read a character into seq.
1172 	if (BC_ERR(BC_HIST_READ(seq, 1))) return;
1173 
1174 	c = seq[0];
1175 
1176 	// ESC ? sequences.
1177 	if (c != '[' && c != 'O') {
1178 		if (c == 'f') bc_history_edit_wordEnd(h);
1179 		else if (c == 'b') bc_history_edit_wordStart(h);
1180 		else if (c == 'd') bc_history_edit_deleteNextWord(h);
1181 	}
1182 	else {
1183 
1184 		// Read a character into seq.
1185 		if (BC_ERR(BC_HIST_READ(seq + 1, 1)))
1186 			bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
1187 
1188 		// ESC [ sequences.
1189 		if (c == '[') {
1190 
1191 			c = seq[1];
1192 
1193 			if (c >= '0' && c <= '9') {
1194 
1195 				// Extended escape, read additional byte.
1196 				if (BC_ERR(BC_HIST_READ(seq + 2, 1)))
1197 					bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
1198 
1199 				if (seq[2] == '~') {
1200 
1201 					switch(c) {
1202 
1203 						case '1':
1204 						{
1205 							bc_history_edit_home(h);
1206 							break;
1207 						}
1208 
1209 						case '3':
1210 						{
1211 							bc_history_edit_delete(h);
1212 							break;
1213 						}
1214 
1215 						case '4':
1216 						{
1217 							bc_history_edit_end(h);
1218 							break;
1219 						}
1220 
1221 						default:
1222 						{
1223 							break;
1224 						}
1225 					}
1226 				}
1227 				else if(seq[2] == ';') {
1228 
1229 					// Read two characters into seq.
1230 					if (BC_ERR(BC_HIST_READ(seq, 2)))
1231 						bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
1232 
1233 					if (seq[0] != '5') return;
1234 					else if (seq[1] == 'C') bc_history_edit_wordEnd(h);
1235 					else if (seq[1] == 'D') bc_history_edit_wordStart(h);
1236 				}
1237 			}
1238 			else {
1239 
1240 				switch(c) {
1241 
1242 					// Up.
1243 					case 'A':
1244 					{
1245 						bc_history_edit_next(h, BC_HIST_PREV);
1246 						break;
1247 					}
1248 
1249 					// Down.
1250 					case 'B':
1251 					{
1252 						bc_history_edit_next(h, BC_HIST_NEXT);
1253 						break;
1254 					}
1255 
1256 					// Right.
1257 					case 'C':
1258 					{
1259 						bc_history_edit_right(h);
1260 						break;
1261 					}
1262 
1263 					// Left.
1264 					case 'D':
1265 					{
1266 						bc_history_edit_left(h);
1267 						break;
1268 					}
1269 
1270 					// Home.
1271 					case 'H':
1272 					case '1':
1273 					{
1274 						bc_history_edit_home(h);
1275 						break;
1276 					}
1277 
1278 					// End.
1279 					case 'F':
1280 					case '4':
1281 					{
1282 						bc_history_edit_end(h);
1283 						break;
1284 					}
1285 
1286 					case 'd':
1287 					{
1288 						bc_history_edit_deleteNextWord(h);
1289 						break;
1290 					}
1291 				}
1292 			}
1293 		}
1294 		// ESC O sequences.
1295 		else {
1296 
1297 			switch (seq[1]) {
1298 
1299 				case 'A':
1300 				{
1301 					bc_history_edit_next(h, BC_HIST_PREV);
1302 					break;
1303 				}
1304 
1305 				case 'B':
1306 				{
1307 					bc_history_edit_next(h, BC_HIST_NEXT);
1308 					break;
1309 				}
1310 
1311 				case 'C':
1312 				{
1313 					bc_history_edit_right(h);
1314 					break;
1315 				}
1316 
1317 				case 'D':
1318 				{
1319 					bc_history_edit_left(h);
1320 					break;
1321 				}
1322 
1323 				case 'F':
1324 				{
1325 					bc_history_edit_end(h);
1326 					break;
1327 				}
1328 
1329 				case 'H':
1330 				{
1331 					bc_history_edit_home(h);
1332 					break;
1333 				}
1334 			}
1335 		}
1336 	}
1337 }
1338 
1339 /**
1340  * Adds a line to the history.
1341  * @param h     The history data.
1342  * @param line  The line to add.
1343  */
1344 static void bc_history_add(BcHistory *h, char *line) {
1345 
1346 	BC_SIG_ASSERT_LOCKED;
1347 
1348 	// If there is something already there...
1349 	if (h->history.len) {
1350 
1351 		// Get the previous.
1352 		char *s = *((char**) bc_vec_item_rev(&h->history, 0));
1353 
1354 		// Check for, and discard, duplicates.
1355 		if (!strcmp(s, line)) {
1356 			free(line);
1357 			return;
1358 		}
1359 	}
1360 
1361 	bc_vec_push(&h->history, &line);
1362 }
1363 
1364 /**
1365  * Adds an empty line to the history. This is separate from bc_history_add()
1366  * because we don't want it allocating.
1367  * @param h  The history data.
1368  */
1369 static void bc_history_add_empty(BcHistory *h) {
1370 
1371 	BC_SIG_ASSERT_LOCKED;
1372 
1373 	const char *line = "";
1374 
1375 	// If there is something already there...
1376 	if (h->history.len) {
1377 
1378 		// Get the previous.
1379 		char *s = *((char**) bc_vec_item_rev(&h->history, 0));
1380 
1381 		// Check for, and discard, duplicates.
1382 		if (!s[0]) return;
1383 	}
1384 
1385 	bc_vec_push(&h->history, &line);
1386 }
1387 
1388 /**
1389  * Resets the history state to nothing.
1390  * @param h  The history data.
1391  */
1392 static void bc_history_reset(BcHistory *h) {
1393 
1394 	BC_SIG_ASSERT_LOCKED;
1395 
1396 	h->oldcolpos = h->pos = h->idx = 0;
1397 	h->cols = bc_history_columns();
1398 
1399 	// The latest history entry is always our current buffer, that
1400 	// initially is just an empty string.
1401 	bc_history_add_empty(h);
1402 
1403 	// Buffer starts empty.
1404 	bc_vec_empty(&h->buf);
1405 }
1406 
1407 /**
1408  * Prints a control character.
1409  * @param h  The history data.
1410  * @param c  The control character to print.
1411  */
1412 static void bc_history_printCtrl(BcHistory *h, unsigned int c) {
1413 
1414 	char str[3] = "^A";
1415 	const char newline[2] = "\n";
1416 
1417 	BC_SIG_ASSERT_LOCKED;
1418 
1419 	// Set the correct character.
1420 	str[1] = (char) (c + 'A' - BC_ACTION_CTRL_A);
1421 
1422 	// Concatenate the string.
1423 	bc_vec_concat(&h->buf, str);
1424 
1425 	bc_history_refresh(h);
1426 
1427 	// Pop the string.
1428 	bc_vec_npop(&h->buf, sizeof(str));
1429 	bc_vec_pushByte(&h->buf, '\0');
1430 
1431 #ifndef _WIN32
1432 	if (c != BC_ACTION_CTRL_C && c != BC_ACTION_CTRL_D)
1433 #endif // _WIN32
1434 	{
1435 		// We sometimes want to print a newline; for the times we don't; it's
1436 		// because newlines are taken care of elsewhere.
1437 		bc_file_write(&vm.fout, bc_flush_none, newline, sizeof(newline) - 1);
1438 		bc_history_refresh(h);
1439 	}
1440 }
1441 
1442 /**
1443  * Edits a line of history. This function is the core of the line editing
1444  * capability of bc history. It expects 'fd' to be already in "raw mode" so that
1445  * every key pressed will be returned ASAP to read().
1446  * @param h       The history data.
1447  * @param prompt  The prompt.
1448  * @return        BC_STATUS_SUCCESS or BC_STATUS_EOF.
1449  */
1450 static BcStatus bc_history_edit(BcHistory *h, const char *prompt) {
1451 
1452 	BC_SIG_LOCK;
1453 
1454 	bc_history_reset(h);
1455 
1456 	// Don't write the saved output the first time. This is because it has
1457 	// already been written to output. In other words, don't uncomment the
1458 	// line below or add anything like it.
1459 	// bc_file_write(&vm.fout, bc_flush_none, h->extras.v, h->extras.len - 1);
1460 
1461 	// Write the prompt if desired.
1462 	if (BC_PROMPT) {
1463 
1464 		h->prompt = prompt;
1465 		h->plen = strlen(prompt);
1466 		h->pcol = bc_history_promptColLen(prompt, h->plen);
1467 
1468 		bc_file_write(&vm.fout, bc_flush_none, prompt, h->plen);
1469 		bc_file_flush(&vm.fout, bc_flush_none);
1470 	}
1471 
1472 	// This is the input loop.
1473 	for (;;) {
1474 
1475 		BcStatus s;
1476 		char cbuf[32];
1477 		unsigned int c = 0;
1478 		size_t nread = 0;
1479 
1480 		BC_SIG_UNLOCK;
1481 
1482 		// Read a code.
1483 		s = bc_history_readCode(cbuf, sizeof(cbuf), &c, &nread);
1484 		if (BC_ERR(s)) return s;
1485 
1486 		BC_SIG_LOCK;
1487 
1488 		switch (c) {
1489 
1490 			case BC_ACTION_LINE_FEED:
1491 			case BC_ACTION_ENTER:
1492 			{
1493 				// Return the line.
1494 				bc_vec_pop(&h->history);
1495 				BC_SIG_UNLOCK;
1496 				return s;
1497 			}
1498 
1499 			case BC_ACTION_TAB:
1500 			{
1501 				// My tab handling is dumb; it just prints 8 spaces every time.
1502 				memcpy(cbuf, bc_history_tab, bc_history_tab_len + 1);
1503 				bc_history_edit_insert(h, cbuf, bc_history_tab_len);
1504 				break;
1505 			}
1506 
1507 #ifndef _WIN32
1508 			case BC_ACTION_CTRL_C:
1509 			{
1510 				bc_history_printCtrl(h, c);
1511 
1512 				// Quit if the user wants it.
1513 				if (!BC_SIGINT) {
1514 					vm.status = BC_STATUS_QUIT;
1515 					BC_SIG_UNLOCK;
1516 					BC_JMP;
1517 				}
1518 
1519 				// Print the ready message.
1520 				bc_file_write(&vm.fout, bc_flush_none, vm.sigmsg, vm.siglen);
1521 				bc_file_write(&vm.fout, bc_flush_none, bc_program_ready_msg,
1522 				              bc_program_ready_msg_len);
1523 				bc_history_reset(h);
1524 				bc_history_refresh(h);
1525 
1526 				break;
1527 			}
1528 #endif // _WIN32
1529 
1530 			case BC_ACTION_BACKSPACE:
1531 			case BC_ACTION_CTRL_H:
1532 			{
1533 				bc_history_edit_backspace(h);
1534 				break;
1535 			}
1536 
1537 #ifndef _WIN32
1538 			// Act as end-of-file or delete-forward-char.
1539 			case BC_ACTION_CTRL_D:
1540 			{
1541 				// Act as EOF if there's no chacters, otherwise emulate Emacs
1542 				// delete next character to match historical gnu bc behavior.
1543 				if (BC_HIST_BUF_LEN(h) == 0) {
1544 					bc_history_printCtrl(h, c);
1545 					BC_SIG_UNLOCK;
1546 					return BC_STATUS_EOF;
1547 				}
1548 
1549 				bc_history_edit_delete(h);
1550 
1551 				break;
1552 			}
1553 #endif // _WIN32
1554 
1555 			// Swaps current character with previous.
1556 			case BC_ACTION_CTRL_T:
1557 			{
1558 				bc_history_swap(h);
1559 				break;
1560 			}
1561 
1562 			case BC_ACTION_CTRL_B:
1563 			{
1564 				bc_history_edit_left(h);
1565 				break;
1566 			}
1567 
1568 			case BC_ACTION_CTRL_F:
1569 			{
1570 				bc_history_edit_right(h);
1571 				break;
1572 			}
1573 
1574 			case BC_ACTION_CTRL_P:
1575 			{
1576 				bc_history_edit_next(h, BC_HIST_PREV);
1577 				break;
1578 			}
1579 
1580 			case BC_ACTION_CTRL_N:
1581 			{
1582 				bc_history_edit_next(h, BC_HIST_NEXT);
1583 				break;
1584 			}
1585 
1586 			case BC_ACTION_ESC:
1587 			{
1588 				bc_history_escape(h);
1589 				break;
1590 			}
1591 
1592 			// Delete the whole line.
1593 			case BC_ACTION_CTRL_U:
1594 			{
1595 				bc_vec_string(&h->buf, 0, "");
1596 				h->pos = 0;
1597 
1598 				bc_history_refresh(h);
1599 
1600 				break;
1601 			}
1602 
1603 			// Delete from current to end of line.
1604 			case BC_ACTION_CTRL_K:
1605 			{
1606 				bc_vec_npop(&h->buf, h->buf.len - h->pos);
1607 				bc_vec_pushByte(&h->buf, '\0');
1608 				bc_history_refresh(h);
1609 				break;
1610 			}
1611 
1612 			// Go to the start of the line.
1613 			case BC_ACTION_CTRL_A:
1614 			{
1615 				bc_history_edit_home(h);
1616 				break;
1617 			}
1618 
1619 			// Go to the end of the line.
1620 			case BC_ACTION_CTRL_E:
1621 			{
1622 				bc_history_edit_end(h);
1623 				break;
1624 			}
1625 
1626 			// Clear screen.
1627 			case BC_ACTION_CTRL_L:
1628 			{
1629 				bc_file_write(&vm.fout, bc_flush_none, "\x1b[H\x1b[2J", 7);
1630 				bc_history_refresh(h);
1631 				break;
1632 			}
1633 
1634 			// Delete previous word.
1635 			case BC_ACTION_CTRL_W:
1636 			{
1637 				bc_history_edit_deletePrevWord(h);
1638 				break;
1639 			}
1640 
1641 			default:
1642 			{
1643 				// If we have a control character, print it and raise signals as
1644 				// needed.
1645 				if ((c >= BC_ACTION_CTRL_A && c <= BC_ACTION_CTRL_Z) ||
1646 				    c == BC_ACTION_CTRL_BSLASH)
1647 				{
1648 					bc_history_printCtrl(h, c);
1649 #ifndef _WIN32
1650 					if (c == BC_ACTION_CTRL_Z) bc_history_raise(h, SIGTSTP);
1651 					if (c == BC_ACTION_CTRL_S) bc_history_raise(h, SIGSTOP);
1652 					if (c == BC_ACTION_CTRL_BSLASH)
1653 						bc_history_raise(h, SIGQUIT);
1654 #else // _WIN32
1655 					vm.status = BC_STATUS_QUIT;
1656 					BC_SIG_UNLOCK;
1657 					BC_JMP;
1658 #endif // _WIN32
1659 				}
1660 				// Otherwise, just insert.
1661 				else bc_history_edit_insert(h, cbuf, nread);
1662 				break;
1663 			}
1664 		}
1665 	}
1666 
1667 	BC_SIG_UNLOCK;
1668 
1669 	return BC_STATUS_SUCCESS;
1670 }
1671 
1672 /**
1673  * Returns true if stdin has more data. This is for multi-line pasting, and it
1674  * does not work on Windows.
1675  * @param h  The history data.
1676  */
1677 static inline bool bc_history_stdinHasData(BcHistory *h) {
1678 #ifndef _WIN32
1679 	int n;
1680 	return pselect(1, &h->rdset, NULL, NULL, &h->ts, &h->sigmask) > 0 ||
1681 	       (ioctl(STDIN_FILENO, FIONREAD, &n) >= 0 && n > 0);
1682 #else // _WIN32
1683 	return false;
1684 #endif // _WIN32
1685 }
1686 
1687 BcStatus bc_history_line(BcHistory *h, BcVec *vec, const char *prompt) {
1688 
1689 	BcStatus s;
1690 	char* line;
1691 
1692 	assert(vm.fout.len == 0);
1693 
1694 	bc_history_enableRaw(h);
1695 
1696 	do {
1697 
1698 		// Do the edit.
1699 		s = bc_history_edit(h, prompt);
1700 
1701 		// Print a newline and flush.
1702 		bc_file_write(&vm.fout, bc_flush_none, "\n", 1);
1703 		bc_file_flush(&vm.fout, bc_flush_none);
1704 
1705 		BC_SIG_LOCK;
1706 
1707 		// If we actually have data...
1708 		if (h->buf.v[0]) {
1709 
1710 			// Duplicate it.
1711 			line = bc_vm_strdup(h->buf.v);
1712 
1713 			// Store it.
1714 			bc_history_add(h, line);
1715 		}
1716 		// Add an empty string.
1717 		else bc_history_add_empty(h);
1718 
1719 		BC_SIG_UNLOCK;
1720 
1721 		// Concatenate the line to the return vector.
1722 		bc_vec_concat(vec, h->buf.v);
1723 		bc_vec_concat(vec, "\n");
1724 
1725 	} while (!s && bc_history_stdinHasData(h));
1726 
1727 	assert(!s || s == BC_STATUS_EOF);
1728 
1729 	bc_history_disableRaw(h);
1730 
1731 	return s;
1732 }
1733 
1734 void bc_history_string_free(void *str) {
1735 	char *s = *((char**) str);
1736 	BC_SIG_ASSERT_LOCKED;
1737 	if (s[0]) free(s);
1738 }
1739 
1740 void bc_history_init(BcHistory *h) {
1741 
1742 #ifdef _WIN32
1743 	HANDLE out, in;
1744 #endif // _WIN32
1745 
1746 	BC_SIG_ASSERT_LOCKED;
1747 
1748 	h->rawMode = false;
1749 	h->badTerm = bc_history_isBadTerm();
1750 
1751 #ifdef _WIN32
1752 
1753 	h->orig_in = 0;
1754 	h->orig_out = 0;
1755 
1756 	in = GetStdHandle(STD_INPUT_HANDLE);
1757 	out = GetStdHandle(STD_OUTPUT_HANDLE);
1758 
1759 	if (!h->badTerm) {
1760 		SetConsoleCP(CP_UTF8);
1761 		SetConsoleOutputCP(CP_UTF8);
1762 		if (!GetConsoleMode(in, &h->orig_in) ||
1763 			!GetConsoleMode(out, &h->orig_out))
1764 		{
1765 			h->badTerm = true;
1766 			return;
1767 		}
1768 		else {
1769 			DWORD reqOut = ENABLE_VIRTUAL_TERMINAL_PROCESSING |
1770 				DISABLE_NEWLINE_AUTO_RETURN;
1771 			DWORD reqIn = ENABLE_VIRTUAL_TERMINAL_INPUT;
1772 			if (!SetConsoleMode(in, h->orig_in | reqIn) ||
1773 				!SetConsoleMode(out, h->orig_out | reqOut))
1774 			{
1775 				h->badTerm = true;
1776 			}
1777 		}
1778 	}
1779 #endif // _WIN32
1780 
1781 	bc_vec_init(&h->buf, sizeof(char), BC_DTOR_NONE);
1782 	bc_vec_init(&h->history, sizeof(char*), BC_DTOR_HISTORY_STRING);
1783 	bc_vec_init(&h->extras, sizeof(char), BC_DTOR_NONE);
1784 
1785 #ifndef _WIN32
1786 	FD_ZERO(&h->rdset);
1787 	FD_SET(STDIN_FILENO, &h->rdset);
1788 	h->ts.tv_sec = 0;
1789 	h->ts.tv_nsec = 0;
1790 
1791 	sigemptyset(&h->sigmask);
1792 	sigaddset(&h->sigmask, SIGINT);
1793 #endif // _WIN32
1794 }
1795 
1796 void bc_history_free(BcHistory *h) {
1797 	BC_SIG_ASSERT_LOCKED;
1798 #ifndef _WIN32
1799 	bc_history_disableRaw(h);
1800 #else // _WIN32
1801 	SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), h->orig_in);
1802 	SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), h->orig_out);
1803 #endif // _WIN32
1804 #ifndef NDEBUG
1805 	bc_vec_free(&h->buf);
1806 	bc_vec_free(&h->history);
1807 	bc_vec_free(&h->extras);
1808 #endif // NDEBUG
1809 }
1810 
1811 #if BC_DEBUG_CODE
1812 
1813 /**
1814  * Prints scan codes. This special mode is used by bc history in order to print
1815  * scan codes on screen for debugging / development purposes.
1816  * @param h  The history data.
1817  */
1818 void bc_history_printKeyCodes(BcHistory *h) {
1819 
1820 	char quit[4];
1821 
1822 	bc_vm_printf("Linenoise key codes debugging mode.\n"
1823 	             "Press keys to see scan codes. "
1824 	             "Type 'quit' at any time to exit.\n");
1825 
1826 	bc_history_enableRaw(h);
1827 	memset(quit, ' ', 4);
1828 
1829 	while(true) {
1830 
1831 		char c;
1832 		ssize_t nread;
1833 
1834 		nread = bc_history_read(&c, 1);
1835 		if (nread <= 0) continue;
1836 
1837 		// Shift string to left.
1838 		memmove(quit, quit + 1, sizeof(quit) - 1);
1839 
1840 		// Insert current char on the right.
1841 		quit[sizeof(quit) - 1] = c;
1842 		if (!memcmp(quit, "quit", sizeof(quit))) break;
1843 
1844 		bc_vm_printf("'%c' %lu (type quit to exit)\n",
1845 		             isprint(c) ? c : '?', (unsigned long) c);
1846 
1847 		// Go left edge manually, we are in raw mode.
1848 		bc_vm_putchar('\r', bc_flush_none);
1849 		bc_file_flush(&vm.fout, bc_flush_none);
1850 	}
1851 
1852 	bc_history_disableRaw(h);
1853 }
1854 #endif // BC_DEBUG_CODE
1855 
1856 #endif // BC_ENABLE_HISTORY
1857