history.c (f53b5fe7865f4e4240e40ba0f6345f81d337a823) | history.c (d101cdd6edd782f6ec56eef63ed91abd77a8b317) |
---|---|
1/* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * | 1/* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * |
6 * Copyright (c) 2018-2021 Gavin D. Howard and contributors. | 6 * Copyright (c) 2018-2023 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, --- 139 unchanged lines hidden (view full) --- 154#include <vm.h> 155 156sigjmp_buf bc_history_jmpbuf; 157volatile sig_atomic_t bc_history_inlinelib; 158 159static char* bc_history_prompt; 160static char bc_history_no_prompt[] = ""; 161static HistEvent bc_history_event; | 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, --- 139 unchanged lines hidden (view full) --- 154#include <vm.h> 155 156sigjmp_buf bc_history_jmpbuf; 157volatile sig_atomic_t bc_history_inlinelib; 158 159static char* bc_history_prompt; 160static char bc_history_no_prompt[] = ""; 161static HistEvent bc_history_event; |
162static bool bc_history_use_prompt; |
|
162 163static char* 164bc_history_promptFunc(EditLine* el) 165{ 166 BC_UNUSED(el); | 163 164static char* 165bc_history_promptFunc(EditLine* el) 166{ 167 BC_UNUSED(el); |
167 return BC_PROMPT ? bc_history_prompt : bc_history_no_prompt; | 168 return BC_PROMPT && bc_history_use_prompt ? bc_history_prompt : 169 bc_history_no_prompt; |
168} 169 170void 171bc_history_init(BcHistory* h) 172{ 173 BcVec v; 174 char* home; 175 --- 14 unchanged lines hidden (view full) --- 190 { 191 bc_vec_string(&v, strlen(home), home); 192 bc_vec_concat(&v, bc_history_editrc); 193 } 194 195 h->hist = history_init(); 196 if (BC_ERR(h->hist == NULL)) bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR); 197 | 170} 171 172void 173bc_history_init(BcHistory* h) 174{ 175 BcVec v; 176 char* home; 177 --- 14 unchanged lines hidden (view full) --- 192 { 193 bc_vec_string(&v, strlen(home), home); 194 bc_vec_concat(&v, bc_history_editrc); 195 } 196 197 h->hist = history_init(); 198 if (BC_ERR(h->hist == NULL)) bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR); 199 |
198 h->el = el_init(vm.name, stdin, stdout, stderr); | 200 h->el = el_init(vm->name, stdin, stdout, stderr); |
199 if (BC_ERR(h->el == NULL)) bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR); 200 201 // I want history and a prompt. 202 history(h->hist, &bc_history_event, H_SETSIZE, 100); 203 history(h->hist, &bc_history_event, H_SETUNIQUE, 1); 204 el_set(h->el, EL_EDITOR, "emacs"); 205 el_set(h->el, EL_HIST, history, h->hist); 206 el_set(h->el, EL_PROMPT, bc_history_promptFunc); --- 43 unchanged lines hidden (view full) --- 250 { 251 free(bc_history_prompt); 252 bc_history_prompt = bc_vm_strdup(prompt); 253 } 254 } 255 else bc_history_prompt = bc_vm_strdup(prompt); 256 } 257 | 201 if (BC_ERR(h->el == NULL)) bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR); 202 203 // I want history and a prompt. 204 history(h->hist, &bc_history_event, H_SETSIZE, 100); 205 history(h->hist, &bc_history_event, H_SETUNIQUE, 1); 206 el_set(h->el, EL_EDITOR, "emacs"); 207 el_set(h->el, EL_HIST, history, h->hist); 208 el_set(h->el, EL_PROMPT, bc_history_promptFunc); --- 43 unchanged lines hidden (view full) --- 252 { 253 free(bc_history_prompt); 254 bc_history_prompt = bc_vm_strdup(prompt); 255 } 256 } 257 else bc_history_prompt = bc_vm_strdup(prompt); 258 } 259 |
260 bc_history_use_prompt = true; 261 262 line = NULL; 263 len = -1; 264 errno = EINTR; 265 |
|
258 // Get the line. | 266 // Get the line. |
259 line = el_gets(h->el, &len); | 267 while (line == NULL && len == -1 && errno == EINTR) 268 { 269 line = el_gets(h->el, &len); 270 bc_history_use_prompt = false; 271 } |
260 261 // If there is no line... 262 if (BC_ERR(line == NULL)) 263 { 264 // If this is true, there was an error. Otherwise, it's just EOF. 265 if (len == -1) 266 { 267 if (errno == ENOMEM) bc_err(BC_ERR_FATAL_ALLOC_ERR); 268 bc_err(BC_ERR_FATAL_IO_ERR); 269 } 270 else 271 { | 272 273 // If there is no line... 274 if (BC_ERR(line == NULL)) 275 { 276 // If this is true, there was an error. Otherwise, it's just EOF. 277 if (len == -1) 278 { 279 if (errno == ENOMEM) bc_err(BC_ERR_FATAL_ALLOC_ERR); 280 bc_err(BC_ERR_FATAL_IO_ERR); 281 } 282 else 283 { |
272 bc_file_printf(&vm.fout, "\n"); | 284 bc_file_printf(&vm->fout, "\n"); |
273 s = BC_STATUS_EOF; 274 } 275 } 276 // If there is a line... 277 else 278 { 279 bc_vec_string(vec, strlen(line), line); 280 --- 82 unchanged lines hidden (view full) --- 363 364 bc_vec_expand(vec, len + 2); 365 366 bc_vec_string(vec, len, h->line); 367 bc_vec_concat(vec, "\n"); 368 } 369 else if (h->line == NULL) 370 { | 285 s = BC_STATUS_EOF; 286 } 287 } 288 // If there is a line... 289 else 290 { 291 bc_vec_string(vec, strlen(line), line); 292 --- 82 unchanged lines hidden (view full) --- 375 376 bc_vec_expand(vec, len + 2); 377 378 bc_vec_string(vec, len, h->line); 379 bc_vec_concat(vec, "\n"); 380 } 381 else if (h->line == NULL) 382 { |
371 bc_file_printf(&vm.fout, "%s\n", "^D"); | 383 bc_file_printf(&vm->fout, "%s\n", "^D"); |
372 s = BC_STATUS_EOF; 373 } 374 else bc_vec_string(vec, 1, "\n"); 375 376end: 377 378 bc_history_inlinelib = 0; 379 --- 181 unchanged lines hidden (view full) --- 561 uint32_t cp; 562 size_t beg = pos; 563 size_t len = bc_history_codePoint(buf + pos, buf_len - pos, &cp); 564 565 if (bc_history_comboChar(cp)) 566 { 567 BC_UNREACHABLE 568 | 384 s = BC_STATUS_EOF; 385 } 386 else bc_vec_string(vec, 1, "\n"); 387 388end: 389 390 bc_history_inlinelib = 0; 391 --- 181 unchanged lines hidden (view full) --- 573 uint32_t cp; 574 size_t beg = pos; 575 size_t len = bc_history_codePoint(buf + pos, buf_len - pos, &cp); 576 577 if (bc_history_comboChar(cp)) 578 { 579 BC_UNREACHABLE 580 |
581#if !BC_CLANG |
|
569 if (col_len != NULL) *col_len = 0; 570 571 return 0; | 582 if (col_len != NULL) *col_len = 0; 583 584 return 0; |
585#endif // !BC_CLANG |
|
572 } 573 574 // Store the width of the character on screen. 575 if (col_len != NULL) *col_len = bc_history_wchar(cp) ? 2 : 1; 576 577 pos += len; 578 579 // Find the first non-combining character. --- 32 unchanged lines hidden (view full) --- 612 // The original linenoise-mob had an extra parameter col_len, like 613 // bc_history_nextLen(), which, if not NULL, was set in this if 614 // statement. However, we always passed NULL, so just skip that. 615 if (!bc_history_comboChar(cp)) return end - pos; 616 } 617 618 BC_UNREACHABLE 619 | 586 } 587 588 // Store the width of the character on screen. 589 if (col_len != NULL) *col_len = bc_history_wchar(cp) ? 2 : 1; 590 591 pos += len; 592 593 // Find the first non-combining character. --- 32 unchanged lines hidden (view full) --- 626 // The original linenoise-mob had an extra parameter col_len, like 627 // bc_history_nextLen(), which, if not NULL, was set in this if 628 // statement. However, we always passed NULL, so just skip that. 629 if (!bc_history_comboChar(cp)) return end - pos; 630 } 631 632 BC_UNREACHABLE 633 |
634#if !BC_CLANG |
|
620 return 0; | 635 return 0; |
636#endif // BC_CLANG |
|
621} 622 623/** 624 * Reads @a n characters from stdin. 625 * @param buf The buffer to read into. The caller is responsible for making 626 * sure this is big enough for @a n. 627 * @param n The number of characters to read. 628 * @return The number of characters read or less than 0 on error. --- 36 unchanged lines hidden (view full) --- 665 * @param cp An out parameter for the codepoint. 666 * @param nread An out parameter for the number of bytes read. 667 * @return BC_STATUS_EOF or BC_STATUS_SUCCESS. 668 */ 669static BcStatus 670bc_history_readCode(char* buf, size_t buf_len, uint32_t* cp, size_t* nread) 671{ 672 ssize_t n; | 637} 638 639/** 640 * Reads @a n characters from stdin. 641 * @param buf The buffer to read into. The caller is responsible for making 642 * sure this is big enough for @a n. 643 * @param n The number of characters to read. 644 * @return The number of characters read or less than 0 on error. --- 36 unchanged lines hidden (view full) --- 681 * @param cp An out parameter for the codepoint. 682 * @param nread An out parameter for the number of bytes read. 683 * @return BC_STATUS_EOF or BC_STATUS_SUCCESS. 684 */ 685static BcStatus 686bc_history_readCode(char* buf, size_t buf_len, uint32_t* cp, size_t* nread) 687{ 688 ssize_t n; |
689 uchar byte; |
|
673 674 assert(buf_len >= 1); 675 676 BC_SIG_LOCK; 677 678 // Read a byte. 679 n = bc_history_read(buf, 1); 680 681 BC_SIG_UNLOCK; 682 683 if (BC_ERR(n <= 0)) goto err; 684 685 // Get the byte. | 690 691 assert(buf_len >= 1); 692 693 BC_SIG_LOCK; 694 695 // Read a byte. 696 n = bc_history_read(buf, 1); 697 698 BC_SIG_UNLOCK; 699 700 if (BC_ERR(n <= 0)) goto err; 701 702 // Get the byte. |
686 uchar byte = ((uchar*) buf)[0]; | 703 byte = ((uchar*) buf)[0]; |
687 688 // Once again, this is the UTF-8 decoding algorithm, but it has reads 689 // instead of actual decoding. 690 if ((byte & 0x80) != 0) 691 { 692 if ((byte & 0xE0) == 0xC0) 693 { 694 assert(buf_len >= 2); --- 198 unchanged lines hidden (view full) --- 893 char buf[BC_HIST_SEQ_SIZE]; 894 char* ptr; 895 char* ptr2; 896 size_t cols, rows, i; 897 898 BC_SIG_ASSERT_LOCKED; 899 900 // Report cursor location. | 704 705 // Once again, this is the UTF-8 decoding algorithm, but it has reads 706 // instead of actual decoding. 707 if ((byte & 0x80) != 0) 708 { 709 if ((byte & 0xE0) == 0xC0) 710 { 711 assert(buf_len >= 2); --- 198 unchanged lines hidden (view full) --- 910 char buf[BC_HIST_SEQ_SIZE]; 911 char* ptr; 912 char* ptr2; 913 size_t cols, rows, i; 914 915 BC_SIG_ASSERT_LOCKED; 916 917 // Report cursor location. |
901 bc_file_write(&vm.fout, bc_flush_none, "\x1b[6n", 4); 902 bc_file_flush(&vm.fout, bc_flush_none); | 918 bc_file_write(&vm->fout, bc_flush_none, "\x1b[6n", 4); 919 bc_file_flush(&vm->fout, bc_flush_none); |
903 904 // Read the response: ESC [ rows ; cols R. 905 for (i = 0; i < sizeof(buf) - 1; ++i) 906 { 907 if (bc_history_read(buf + i, 1) != 1 || buf[i] == 'R') break; 908 } 909 910 buf[i] = '\0'; --- 26 unchanged lines hidden (view full) --- 937bc_history_columns(void) 938{ 939 940#ifndef _WIN32 941 942 struct winsize ws; 943 int ret; 944 | 920 921 // Read the response: ESC [ rows ; cols R. 922 for (i = 0; i < sizeof(buf) - 1; ++i) 923 { 924 if (bc_history_read(buf + i, 1) != 1 || buf[i] == 'R') break; 925 } 926 927 buf[i] = '\0'; --- 26 unchanged lines hidden (view full) --- 954bc_history_columns(void) 955{ 956 957#ifndef _WIN32 958 959 struct winsize ws; 960 int ret; 961 |
945 ret = ioctl(vm.fout.fd, TIOCGWINSZ, &ws); | 962 ret = ioctl(vm->fout.fd, TIOCGWINSZ, &ws); |
946 947 if (BC_ERR(ret == -1 || !ws.ws_col)) 948 { 949 // Calling ioctl() failed. Try to query the terminal itself. 950 size_t start, cols; 951 952 // Get the initial position so we can restore it later. 953 start = bc_history_cursorPos(); 954 if (BC_ERR(start == SIZE_MAX)) return BC_HIST_DEF_COLS; 955 956 // Go to right margin and get position. | 963 964 if (BC_ERR(ret == -1 || !ws.ws_col)) 965 { 966 // Calling ioctl() failed. Try to query the terminal itself. 967 size_t start, cols; 968 969 // Get the initial position so we can restore it later. 970 start = bc_history_cursorPos(); 971 if (BC_ERR(start == SIZE_MAX)) return BC_HIST_DEF_COLS; 972 973 // Go to right margin and get position. |
957 bc_file_write(&vm.fout, bc_flush_none, "\x1b[999C", 6); 958 bc_file_flush(&vm.fout, bc_flush_none); | 974 bc_file_write(&vm->fout, bc_flush_none, "\x1b[999C", 6); 975 bc_file_flush(&vm->fout, bc_flush_none); |
959 cols = bc_history_cursorPos(); 960 if (BC_ERR(cols == SIZE_MAX)) return BC_HIST_DEF_COLS; 961 962 // Restore position. 963 if (cols > start) 964 { | 976 cols = bc_history_cursorPos(); 977 if (BC_ERR(cols == SIZE_MAX)) return BC_HIST_DEF_COLS; 978 979 // Restore position. 980 if (cols > start) 981 { |
965 bc_file_printf(&vm.fout, "\x1b[%zuD", cols - start); 966 bc_file_flush(&vm.fout, bc_flush_none); | 982 bc_file_printf(&vm->fout, "\x1b[%zuD", cols - start); 983 bc_file_flush(&vm->fout, bc_flush_none); |
967 } 968 969 return cols; 970 } 971 972 return ws.ws_col; 973 974#else // _WIN32 --- 41 unchanged lines hidden (view full) --- 1016static void 1017bc_history_refresh(BcHistory* h) 1018{ 1019 char* buf = h->buf.v; 1020 size_t colpos, len = BC_HIST_BUF_LEN(h), pos = h->pos, extras_len = 0; 1021 1022 BC_SIG_ASSERT_LOCKED; 1023 | 984 } 985 986 return cols; 987 } 988 989 return ws.ws_col; 990 991#else // _WIN32 --- 41 unchanged lines hidden (view full) --- 1033static void 1034bc_history_refresh(BcHistory* h) 1035{ 1036 char* buf = h->buf.v; 1037 size_t colpos, len = BC_HIST_BUF_LEN(h), pos = h->pos, extras_len = 0; 1038 1039 BC_SIG_ASSERT_LOCKED; 1040 |
1024 bc_file_flush(&vm.fout, bc_flush_none); | 1041 bc_file_flush(&vm->fout, bc_flush_none); |
1025 1026 // Get to the prompt column position from the left. 1027 while (h->pcol + bc_history_colPos(buf, len, pos) >= h->cols) 1028 { 1029 size_t chlen = bc_history_nextLen(buf, len, 0, NULL); 1030 1031 buf += chlen; 1032 len -= chlen; 1033 pos -= chlen; 1034 } 1035 1036 // Get to the prompt column position from the right. 1037 while (h->pcol + bc_history_colPos(buf, len, len) > h->cols) 1038 { 1039 len -= bc_history_prevLen(buf, len); 1040 } 1041 1042 // Cursor to left edge. | 1042 1043 // Get to the prompt column position from the left. 1044 while (h->pcol + bc_history_colPos(buf, len, pos) >= h->cols) 1045 { 1046 size_t chlen = bc_history_nextLen(buf, len, 0, NULL); 1047 1048 buf += chlen; 1049 len -= chlen; 1050 pos -= chlen; 1051 } 1052 1053 // Get to the prompt column position from the right. 1054 while (h->pcol + bc_history_colPos(buf, len, len) > h->cols) 1055 { 1056 len -= bc_history_prevLen(buf, len); 1057 } 1058 1059 // Cursor to left edge. |
1043 bc_file_write(&vm.fout, bc_flush_none, "\r", 1); | 1060 bc_file_write(&vm->fout, bc_flush_none, "\r", 1); |
1044 1045 // Take the extra stuff into account. This is where history makes sure to 1046 // preserve stuff that was printed without a newline. 1047 if (h->extras.len > 1) 1048 { 1049 extras_len = h->extras.len - 1; 1050 1051 bc_vec_grow(&h->buf, extras_len); 1052 1053 len += extras_len; 1054 pos += extras_len; 1055 | 1061 1062 // Take the extra stuff into account. This is where history makes sure to 1063 // preserve stuff that was printed without a newline. 1064 if (h->extras.len > 1) 1065 { 1066 extras_len = h->extras.len - 1; 1067 1068 bc_vec_grow(&h->buf, extras_len); 1069 1070 len += extras_len; 1071 pos += extras_len; 1072 |
1056 bc_file_write(&vm.fout, bc_flush_none, h->extras.v, extras_len); | 1073 bc_file_write(&vm->fout, bc_flush_none, h->extras.v, extras_len); |
1057 } 1058 1059 // Write the prompt, if desired. | 1074 } 1075 1076 // Write the prompt, if desired. |
1060 if (BC_PROMPT) bc_file_write(&vm.fout, bc_flush_none, h->prompt, h->plen); | 1077 if (BC_PROMPT) bc_file_write(&vm->fout, bc_flush_none, h->prompt, h->plen); |
1061 | 1078 |
1062 bc_file_write(&vm.fout, bc_flush_none, h->buf.v, len - extras_len); | 1079 bc_file_write(&vm->fout, bc_flush_none, h->buf.v, len - extras_len); |
1063 1064 // Erase to right. | 1080 1081 // Erase to right. |
1065 bc_file_write(&vm.fout, bc_flush_none, "\x1b[0K", 4); | 1082 bc_file_write(&vm->fout, bc_flush_none, "\x1b[0K", 4); |
1066 1067 // We need to be sure to grow this. 1068 if (pos >= h->buf.len - extras_len) bc_vec_grow(&h->buf, pos + extras_len); 1069 1070 // Move cursor to original position. Do NOT move the putchar of '\r' to the 1071 // printf with colpos. That causes a bug where the cursor will go to the end 1072 // of the line when there is no prompt. | 1083 1084 // We need to be sure to grow this. 1085 if (pos >= h->buf.len - extras_len) bc_vec_grow(&h->buf, pos + extras_len); 1086 1087 // Move cursor to original position. Do NOT move the putchar of '\r' to the 1088 // printf with colpos. That causes a bug where the cursor will go to the end 1089 // of the line when there is no prompt. |
1073 bc_file_putchar(&vm.fout, bc_flush_none, '\r'); | 1090 bc_file_putchar(&vm->fout, bc_flush_none, '\r'); |
1074 colpos = bc_history_colPos(h->buf.v, len - extras_len, pos) + h->pcol; 1075 1076 // Set the cursor position again. | 1091 colpos = bc_history_colPos(h->buf.v, len - extras_len, pos) + h->pcol; 1092 1093 // Set the cursor position again. |
1077 if (colpos) bc_file_printf(&vm.fout, "\x1b[%zuC", colpos); | 1094 if (colpos) bc_file_printf(&vm->fout, "\x1b[%zuC", colpos); |
1078 | 1095 |
1079 bc_file_flush(&vm.fout, bc_flush_none); | 1096 bc_file_flush(&vm->fout, bc_flush_none); |
1080} 1081 1082/** 1083 * Inserts the character(s) 'c' at cursor current position. 1084 * @param h The history data. 1085 * @param cbuf The character buffer to copy from. 1086 * @param clen The number of characters to copy. 1087 */ --- 21 unchanged lines hidden (view full) --- 1109 len = BC_HIST_BUF_LEN(h) + h->extras.len - 1; 1110 colpos = bc_history_promptColLen(h->prompt, h->plen); 1111 colpos += bc_history_colPos(h->buf.v, len, len); 1112 1113 // Do we have the trivial case? 1114 if (colpos < h->cols) 1115 { 1116 // Avoid a full update of the line in the trivial case. | 1097} 1098 1099/** 1100 * Inserts the character(s) 'c' at cursor current position. 1101 * @param h The history data. 1102 * @param cbuf The character buffer to copy from. 1103 * @param clen The number of characters to copy. 1104 */ --- 21 unchanged lines hidden (view full) --- 1126 len = BC_HIST_BUF_LEN(h) + h->extras.len - 1; 1127 colpos = bc_history_promptColLen(h->prompt, h->plen); 1128 colpos += bc_history_colPos(h->buf.v, len, len); 1129 1130 // Do we have the trivial case? 1131 if (colpos < h->cols) 1132 { 1133 // Avoid a full update of the line in the trivial case. |
1117 bc_file_write(&vm.fout, bc_flush_none, cbuf, clen); 1118 bc_file_flush(&vm.fout, bc_flush_none); | 1134 bc_file_write(&vm->fout, bc_flush_none, cbuf, clen); 1135 bc_file_flush(&vm->fout, bc_flush_none); |
1119 } 1120 else bc_history_refresh(h); 1121 } 1122 else 1123 { 1124 // Amount that we need to move. 1125 size_t amt = BC_HIST_BUF_LEN(h) - h->pos; 1126 --- 318 unchanged lines hidden (view full) --- 1445static void 1446bc_history_swap(BcHistory* h) 1447{ 1448 size_t pcl, ncl; 1449 char auxb[5]; 1450 1451 BC_SIG_ASSERT_LOCKED; 1452 | 1136 } 1137 else bc_history_refresh(h); 1138 } 1139 else 1140 { 1141 // Amount that we need to move. 1142 size_t amt = BC_HIST_BUF_LEN(h) - h->pos; 1143 --- 318 unchanged lines hidden (view full) --- 1462static void 1463bc_history_swap(BcHistory* h) 1464{ 1465 size_t pcl, ncl; 1466 char auxb[5]; 1467 1468 BC_SIG_ASSERT_LOCKED; 1469 |
1470 // If there are no characters, skip. 1471 if (!h->pos) return; 1472 |
|
1453 // Get the length of the previous and next characters. 1454 pcl = bc_history_prevLen(h->buf.v, h->pos); 1455 ncl = bc_history_nextLen(h->buf.v, BC_HIST_BUF_LEN(h), h->pos, NULL); 1456 1457 // To perform a swap we need: 1458 // * Nonzero char length to the left. 1459 // * To not be at the end of the line. 1460 if (pcl && h->pos != BC_HIST_BUF_LEN(h) && pcl < 5 && ncl < 5) --- 240 unchanged lines hidden (view full) --- 1701/** 1702 * Adds an empty line to the history. This is separate from bc_history_add() 1703 * because we don't want it allocating. 1704 * @param h The history data. 1705 */ 1706static void 1707bc_history_add_empty(BcHistory* h) 1708{ | 1473 // Get the length of the previous and next characters. 1474 pcl = bc_history_prevLen(h->buf.v, h->pos); 1475 ncl = bc_history_nextLen(h->buf.v, BC_HIST_BUF_LEN(h), h->pos, NULL); 1476 1477 // To perform a swap we need: 1478 // * Nonzero char length to the left. 1479 // * To not be at the end of the line. 1480 if (pcl && h->pos != BC_HIST_BUF_LEN(h) && pcl < 5 && ncl < 5) --- 240 unchanged lines hidden (view full) --- 1721/** 1722 * Adds an empty line to the history. This is separate from bc_history_add() 1723 * because we don't want it allocating. 1724 * @param h The history data. 1725 */ 1726static void 1727bc_history_add_empty(BcHistory* h) 1728{ |
1709 BC_SIG_ASSERT_LOCKED; 1710 | |
1711 const char* line = ""; 1712 | 1729 const char* line = ""; 1730 |
1731 BC_SIG_ASSERT_LOCKED; 1732 |
|
1713 // If there is something already there... 1714 if (h->history.len) 1715 { 1716 // Get the previous. 1717 char* s = *((char**) bc_vec_item_rev(&h->history, 0)); 1718 1719 // Check for, and discard, duplicates. 1720 if (!s[0]) return; --- 42 unchanged lines hidden (view full) --- 1763 bc_vec_concat(&h->buf, str); 1764 1765 h->pos = BC_HIST_BUF_LEN(h); 1766 bc_history_refresh(h); 1767 1768 // Pop the string. 1769 bc_vec_npop(&h->buf, sizeof(str)); 1770 bc_vec_pushByte(&h->buf, '\0'); | 1733 // If there is something already there... 1734 if (h->history.len) 1735 { 1736 // Get the previous. 1737 char* s = *((char**) bc_vec_item_rev(&h->history, 0)); 1738 1739 // Check for, and discard, duplicates. 1740 if (!s[0]) return; --- 42 unchanged lines hidden (view full) --- 1783 bc_vec_concat(&h->buf, str); 1784 1785 h->pos = BC_HIST_BUF_LEN(h); 1786 bc_history_refresh(h); 1787 1788 // Pop the string. 1789 bc_vec_npop(&h->buf, sizeof(str)); 1790 bc_vec_pushByte(&h->buf, '\0'); |
1791 h->pos = 0; |
|
1771 1772 if (c != BC_ACTION_CTRL_C && c != BC_ACTION_CTRL_D) 1773 { 1774 // We sometimes want to print a newline; for the times we don't; it's 1775 // because newlines are taken care of elsewhere. | 1792 1793 if (c != BC_ACTION_CTRL_C && c != BC_ACTION_CTRL_D) 1794 { 1795 // We sometimes want to print a newline; for the times we don't; it's 1796 // because newlines are taken care of elsewhere. |
1776 bc_file_write(&vm.fout, bc_flush_none, newline, sizeof(newline) - 1); | 1797 bc_file_write(&vm->fout, bc_flush_none, newline, sizeof(newline) - 1); |
1777 bc_history_refresh(h); 1778 } 1779} 1780 1781/** 1782 * Edits a line of history. This function is the core of the line editing 1783 * capability of bc history. It expects 'fd' to be already in "raw mode" so that 1784 * every key pressed will be returned ASAP to read(). --- 6 unchanged lines hidden (view full) --- 1791{ 1792 BC_SIG_LOCK; 1793 1794 bc_history_reset(h); 1795 1796 // Don't write the saved output the first time. This is because it has 1797 // already been written to output. In other words, don't uncomment the 1798 // line below or add anything like it. | 1798 bc_history_refresh(h); 1799 } 1800} 1801 1802/** 1803 * Edits a line of history. This function is the core of the line editing 1804 * capability of bc history. It expects 'fd' to be already in "raw mode" so that 1805 * every key pressed will be returned ASAP to read(). --- 6 unchanged lines hidden (view full) --- 1812{ 1813 BC_SIG_LOCK; 1814 1815 bc_history_reset(h); 1816 1817 // Don't write the saved output the first time. This is because it has 1818 // already been written to output. In other words, don't uncomment the 1819 // line below or add anything like it. |
1799 // bc_file_write(&vm.fout, bc_flush_none, h->extras.v, h->extras.len - 1); | 1820 // bc_file_write(&vm->fout, bc_flush_none, h->extras.v, h->extras.len - 1); |
1800 1801 // Write the prompt if desired. 1802 if (BC_PROMPT) 1803 { 1804 h->prompt = prompt; 1805 h->plen = strlen(prompt); 1806 h->pcol = bc_history_promptColLen(prompt, h->plen); 1807 | 1821 1822 // Write the prompt if desired. 1823 if (BC_PROMPT) 1824 { 1825 h->prompt = prompt; 1826 h->plen = strlen(prompt); 1827 h->pcol = bc_history_promptColLen(prompt, h->plen); 1828 |
1808 bc_file_write(&vm.fout, bc_flush_none, prompt, h->plen); 1809 bc_file_flush(&vm.fout, bc_flush_none); | 1829 bc_file_write(&vm->fout, bc_flush_none, prompt, h->plen); 1830 bc_file_flush(&vm->fout, bc_flush_none); |
1810 } 1811 1812 // This is the input loop. 1813 for (;;) 1814 { 1815 BcStatus s; 1816 char cbuf[32]; 1817 unsigned int c = 0; --- 28 unchanged lines hidden (view full) --- 1846 1847 case BC_ACTION_CTRL_C: 1848 { 1849 bc_history_printCtrl(h, c); 1850 1851 // Quit if the user wants it. 1852 if (!BC_SIGINT) 1853 { | 1831 } 1832 1833 // This is the input loop. 1834 for (;;) 1835 { 1836 BcStatus s; 1837 char cbuf[32]; 1838 unsigned int c = 0; --- 28 unchanged lines hidden (view full) --- 1867 1868 case BC_ACTION_CTRL_C: 1869 { 1870 bc_history_printCtrl(h, c); 1871 1872 // Quit if the user wants it. 1873 if (!BC_SIGINT) 1874 { |
1854 vm.status = BC_STATUS_QUIT; | 1875 vm->status = BC_STATUS_QUIT; |
1855 BC_SIG_UNLOCK; 1856 BC_JMP; 1857 } 1858 1859 // Print the ready message. | 1876 BC_SIG_UNLOCK; 1877 BC_JMP; 1878 } 1879 1880 // Print the ready message. |
1860 bc_file_write(&vm.fout, bc_flush_none, vm.sigmsg, vm.siglen); 1861 bc_file_write(&vm.fout, bc_flush_none, bc_program_ready_msg, | 1881 bc_file_write(&vm->fout, bc_flush_none, vm->sigmsg, vm->siglen); 1882 bc_file_write(&vm->fout, bc_flush_none, bc_program_ready_msg, |
1862 bc_program_ready_msg_len); 1863 bc_history_reset(h); 1864 bc_history_refresh(h); 1865 1866 break; 1867 } 1868 1869 case BC_ACTION_BACKSPACE: --- 89 unchanged lines hidden (view full) --- 1959 { 1960 bc_history_edit_end(h); 1961 break; 1962 } 1963 1964 // Clear screen. 1965 case BC_ACTION_CTRL_L: 1966 { | 1883 bc_program_ready_msg_len); 1884 bc_history_reset(h); 1885 bc_history_refresh(h); 1886 1887 break; 1888 } 1889 1890 case BC_ACTION_BACKSPACE: --- 89 unchanged lines hidden (view full) --- 1980 { 1981 bc_history_edit_end(h); 1982 break; 1983 } 1984 1985 // Clear screen. 1986 case BC_ACTION_CTRL_L: 1987 { |
1967 bc_file_write(&vm.fout, bc_flush_none, "\x1b[H\x1b[2J", 7); | 1988 bc_file_write(&vm->fout, bc_flush_none, "\x1b[H\x1b[2J", 7); |
1968 bc_history_refresh(h); 1969 break; 1970 } 1971 1972 // Delete previous word. 1973 case BC_ACTION_CTRL_W: 1974 { 1975 bc_history_edit_deletePrevWord(h); --- 11 unchanged lines hidden (view full) --- 1987#ifndef _WIN32 1988 if (c == BC_ACTION_CTRL_Z) bc_history_raise(h, SIGTSTP); 1989 if (c == BC_ACTION_CTRL_S) bc_history_raise(h, SIGSTOP); 1990 if (c == BC_ACTION_CTRL_BSLASH) 1991 { 1992 bc_history_raise(h, SIGQUIT); 1993 } 1994#else // _WIN32 | 1989 bc_history_refresh(h); 1990 break; 1991 } 1992 1993 // Delete previous word. 1994 case BC_ACTION_CTRL_W: 1995 { 1996 bc_history_edit_deletePrevWord(h); --- 11 unchanged lines hidden (view full) --- 2008#ifndef _WIN32 2009 if (c == BC_ACTION_CTRL_Z) bc_history_raise(h, SIGTSTP); 2010 if (c == BC_ACTION_CTRL_S) bc_history_raise(h, SIGSTOP); 2011 if (c == BC_ACTION_CTRL_BSLASH) 2012 { 2013 bc_history_raise(h, SIGQUIT); 2014 } 2015#else // _WIN32 |
1995 vm.status = BC_STATUS_QUIT; | 2016 vm->status = BC_STATUS_QUIT; |
1996 BC_SIG_UNLOCK; 1997 BC_JMP; 1998#endif // _WIN32 1999 } 2000 // Otherwise, just insert. 2001 else bc_history_edit_insert(h, cbuf, nread); 2002 break; 2003 } --- 23 unchanged lines hidden (view full) --- 2027} 2028 2029BcStatus 2030bc_history_line(BcHistory* h, BcVec* vec, const char* prompt) 2031{ 2032 BcStatus s; 2033 char* line; 2034 | 2017 BC_SIG_UNLOCK; 2018 BC_JMP; 2019#endif // _WIN32 2020 } 2021 // Otherwise, just insert. 2022 else bc_history_edit_insert(h, cbuf, nread); 2023 break; 2024 } --- 23 unchanged lines hidden (view full) --- 2048} 2049 2050BcStatus 2051bc_history_line(BcHistory* h, BcVec* vec, const char* prompt) 2052{ 2053 BcStatus s; 2054 char* line; 2055 |
2035 assert(vm.fout.len == 0); | 2056 assert(vm->fout.len == 0); |
2036 2037 bc_history_enableRaw(h); 2038 2039 do 2040 { 2041 // Do the edit. 2042 s = bc_history_edit(h, prompt); 2043 2044 // Print a newline and flush. | 2057 2058 bc_history_enableRaw(h); 2059 2060 do 2061 { 2062 // Do the edit. 2063 s = bc_history_edit(h, prompt); 2064 2065 // Print a newline and flush. |
2045 bc_file_write(&vm.fout, bc_flush_none, "\n", 1); 2046 bc_file_flush(&vm.fout, bc_flush_none); | 2066 bc_file_write(&vm->fout, bc_flush_none, "\n", 1); 2067 bc_file_flush(&vm->fout, bc_flush_none); |
2047 2048 BC_SIG_LOCK; 2049 2050 // If we actually have data... 2051 if (h->buf.v[0]) 2052 { 2053 // Duplicate it. 2054 line = bc_vm_strdup(h->buf.v); --- 152 unchanged lines hidden (view full) --- 2207 quit[sizeof(quit) - 1] = c; 2208 if (!memcmp(quit, "quit", sizeof(quit))) break; 2209 2210 bc_vm_printf("'%c' %lu (type quit to exit)\n", isprint(c) ? c : '?', 2211 (unsigned long) c); 2212 2213 // Go left edge manually, we are in raw mode. 2214 bc_vm_putchar('\r', bc_flush_none); | 2068 2069 BC_SIG_LOCK; 2070 2071 // If we actually have data... 2072 if (h->buf.v[0]) 2073 { 2074 // Duplicate it. 2075 line = bc_vm_strdup(h->buf.v); --- 152 unchanged lines hidden (view full) --- 2228 quit[sizeof(quit) - 1] = c; 2229 if (!memcmp(quit, "quit", sizeof(quit))) break; 2230 2231 bc_vm_printf("'%c' %lu (type quit to exit)\n", isprint(c) ? c : '?', 2232 (unsigned long) c); 2233 2234 // Go left edge manually, we are in raw mode. 2235 bc_vm_putchar('\r', bc_flush_none); |
2215 bc_file_flush(&vm.fout, bc_flush_none); | 2236 bc_file_flush(&vm->fout, bc_flush_none); |
2216 } 2217 2218 bc_history_disableRaw(h); 2219} 2220#endif // BC_DEBUG_CODE 2221 2222#endif // BC_ENABLE_HISTORY 2223 2224#endif // BC_ENABLE_READLINE 2225 2226#endif // BC_ENABLE_EDITLINE | 2237 } 2238 2239 bc_history_disableRaw(h); 2240} 2241#endif // BC_DEBUG_CODE 2242 2243#endif // BC_ENABLE_HISTORY 2244 2245#endif // BC_ENABLE_READLINE 2246 2247#endif // BC_ENABLE_EDITLINE |