aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-22 14:11:12 +0000
committerRon Yorston <rmy@pobox.com>2012-03-22 14:11:12 +0000
commit67758035a4fe040c6ac69b39d61bcd6bddd7b827 (patch)
treea4a1db7f54c16d12fabe2626b8f1e235cd694e9e /libbb/lineedit.c
parent811c449748d5bd0505f8510e5582892f94ac0cda (diff)
parentb83c9704128dd106071184e4b00335a3b8486857 (diff)
downloadbusybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.tar.gz
busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.tar.bz2
busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.zip
Merge commit 'b83c9704128dd106071184e4b00335a3b8486857' into merge
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c152
1 files changed, 92 insertions, 60 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 92ecc330a..67c5e0baa 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -204,65 +204,82 @@ static void deinit_S(void)
204#if ENABLE_UNICODE_SUPPORT 204#if ENABLE_UNICODE_SUPPORT
205static size_t load_string(const char *src, int maxsize) 205static size_t load_string(const char *src, int maxsize)
206{ 206{
207 ssize_t len = mbstowcs(command_ps, src, maxsize - 1); 207 if (unicode_status == UNICODE_ON) {
208 if (len < 0) 208 ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
209 len = 0; 209 if (len < 0)
210 command_ps[len] = BB_NUL; 210 len = 0;
211 return len; 211 command_ps[len] = BB_NUL;
212 return len;
213 } else {
214 unsigned i = 0;
215 while ((command_ps[i] = src[i]) != 0)
216 i++;
217 return i;
218 }
212} 219}
213static unsigned save_string(char *dst, unsigned maxsize) 220static unsigned save_string(char *dst, unsigned maxsize)
214{ 221{
222 if (unicode_status == UNICODE_ON) {
215# if !ENABLE_UNICODE_PRESERVE_BROKEN 223# if !ENABLE_UNICODE_PRESERVE_BROKEN
216 ssize_t len = wcstombs(dst, command_ps, maxsize - 1); 224 ssize_t len = wcstombs(dst, command_ps, maxsize - 1);
217 if (len < 0) 225 if (len < 0)
218 len = 0; 226 len = 0;
219 dst[len] = '\0'; 227 dst[len] = '\0';
220 return len; 228 return len;
221# else 229# else
222 unsigned dstpos = 0; 230 unsigned dstpos = 0;
223 unsigned srcpos = 0; 231 unsigned srcpos = 0;
224 232
225 maxsize--; 233 maxsize--;
226 while (dstpos < maxsize) { 234 while (dstpos < maxsize) {
227 wchar_t wc; 235 wchar_t wc;
228 int n = srcpos; 236 int n = srcpos;
229 237
230 /* Convert up to 1st invalid byte (or up to end) */ 238 /* Convert up to 1st invalid byte (or up to end) */
231 while ((wc = command_ps[srcpos]) != BB_NUL 239 while ((wc = command_ps[srcpos]) != BB_NUL
232 && !unicode_is_raw_byte(wc) 240 && !unicode_is_raw_byte(wc)
233 ) { 241 ) {
242 srcpos++;
243 }
244 command_ps[srcpos] = BB_NUL;
245 n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos);
246 if (n < 0) /* should not happen */
247 break;
248 dstpos += n;
249 if (wc == BB_NUL) /* usually is */
250 break;
251
252 /* We do have invalid byte here! */
253 command_ps[srcpos] = wc; /* restore it */
234 srcpos++; 254 srcpos++;
255 if (dstpos == maxsize)
256 break;
257 dst[dstpos++] = (char) wc;
235 } 258 }
236 command_ps[srcpos] = BB_NUL; 259 dst[dstpos] = '\0';
237 n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos); 260 return dstpos;
238 if (n < 0) /* should not happen */
239 break;
240 dstpos += n;
241 if (wc == BB_NUL) /* usually is */
242 break;
243
244 /* We do have invalid byte here! */
245 command_ps[srcpos] = wc; /* restore it */
246 srcpos++;
247 if (dstpos == maxsize)
248 break;
249 dst[dstpos++] = (char) wc;
250 }
251 dst[dstpos] = '\0';
252 return dstpos;
253# endif 261# endif
262 } else {
263 unsigned i = 0;
264 while ((dst[i] = command_ps[i]) != 0)
265 i++;
266 return i;
267 }
254} 268}
255/* I thought just fputwc(c, stdout) would work. But no... */ 269/* I thought just fputwc(c, stdout) would work. But no... */
256static void BB_PUTCHAR(wchar_t c) 270static void BB_PUTCHAR(wchar_t c)
257{ 271{
258 char buf[MB_CUR_MAX + 1]; 272 if (unicode_status == UNICODE_ON) {
259 mbstate_t mbst = { 0 }; 273 char buf[MB_CUR_MAX + 1];
260 ssize_t len; 274 mbstate_t mbst = { 0 };
261 275 ssize_t len = wcrtomb(buf, c, &mbst);
262 len = wcrtomb(buf, c, &mbst); 276 if (len > 0) {
263 if (len > 0) { 277 buf[len] = '\0';
264 buf[len] = '\0'; 278 fputs(buf, stdout);
265 fputs(buf, stdout); 279 }
280 } else {
281 /* In this case, c is always one byte */
282 putchar(c);
266 } 283 }
267} 284}
268# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS 285# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS
@@ -1234,12 +1251,26 @@ line_input_t* FAST_FUNC new_line_input_t(int flags)
1234{ 1251{
1235 line_input_t *n = xzalloc(sizeof(*n)); 1252 line_input_t *n = xzalloc(sizeof(*n));
1236 n->flags = flags; 1253 n->flags = flags;
1254 n->max_history = MAX_HISTORY;
1237 return n; 1255 return n;
1238} 1256}
1239 1257
1240 1258
1241#if MAX_HISTORY > 0 1259#if MAX_HISTORY > 0
1242 1260
1261unsigned size_from_HISTFILESIZE(const char *hp)
1262{
1263 int size = MAX_HISTORY;
1264 if (hp) {
1265 size = atoi(hp);
1266 if (size <= 0)
1267 return 1;
1268 if (size > MAX_HISTORY)
1269 return MAX_HISTORY;
1270 }
1271 return size;
1272}
1273
1243static void save_command_ps_at_cur_history(void) 1274static void save_command_ps_at_cur_history(void)
1244{ 1275{
1245 if (command_ps[0] != BB_NUL) { 1276 if (command_ps[0] != BB_NUL) {
@@ -1330,7 +1361,7 @@ static void load_history(line_input_t *st_parm)
1330 temp_h[idx] = line; 1361 temp_h[idx] = line;
1331 st_parm->cnt_history_in_file++; 1362 st_parm->cnt_history_in_file++;
1332 idx++; 1363 idx++;
1333 if (idx == MAX_HISTORY) 1364 if (idx == st_parm->max_history)
1334 idx = 0; 1365 idx = 0;
1335 } 1366 }
1336 fclose(fp); 1367 fclose(fp);
@@ -1339,18 +1370,18 @@ static void load_history(line_input_t *st_parm)
1339 if (st_parm->cnt_history_in_file) { 1370 if (st_parm->cnt_history_in_file) {
1340 while (temp_h[idx] == NULL) { 1371 while (temp_h[idx] == NULL) {
1341 idx++; 1372 idx++;
1342 if (idx == MAX_HISTORY) 1373 if (idx == st_parm->max_history)
1343 idx = 0; 1374 idx = 0;
1344 } 1375 }
1345 } 1376 }
1346 1377
1347 /* copy temp_h[] to st_parm->history[] */ 1378 /* copy temp_h[] to st_parm->history[] */
1348 for (i = 0; i < MAX_HISTORY;) { 1379 for (i = 0; i < st_parm->max_history;) {
1349 line = temp_h[idx]; 1380 line = temp_h[idx];
1350 if (!line) 1381 if (!line)
1351 break; 1382 break;
1352 idx++; 1383 idx++;
1353 if (idx == MAX_HISTORY) 1384 if (idx == st_parm->max_history)
1354 idx = 0; 1385 idx = 0;
1355 line_len = strlen(line); 1386 line_len = strlen(line);
1356 if (line_len >= MAX_LINELEN) 1387 if (line_len >= MAX_LINELEN)
@@ -1381,7 +1412,7 @@ static void save_history(char *str)
1381 1412
1382 /* did we write so much that history file needs trimming? */ 1413 /* did we write so much that history file needs trimming? */
1383 state->cnt_history_in_file++; 1414 state->cnt_history_in_file++;
1384 if (state->cnt_history_in_file > MAX_HISTORY * 4) { 1415 if (state->cnt_history_in_file > state->max_history * 4) {
1385 char *new_name; 1416 char *new_name;
1386 line_input_t *st_temp; 1417 line_input_t *st_temp;
1387 1418
@@ -1389,6 +1420,7 @@ static void save_history(char *str)
1389 * load them */ 1420 * load them */
1390 st_temp = new_line_input_t(state->flags); 1421 st_temp = new_line_input_t(state->flags);
1391 st_temp->hist_file = state->hist_file; 1422 st_temp->hist_file = state->hist_file;
1423 st_temp->max_history = state->max_history;
1392 load_history(st_temp); 1424 load_history(st_temp);
1393 1425
1394 /* write out temp file and replace hist_file atomically */ 1426 /* write out temp file and replace hist_file atomically */
@@ -1427,20 +1459,20 @@ static void remember_in_history(char *str)
1427 if (i && strcmp(state->history[i-1], str) == 0) 1459 if (i && strcmp(state->history[i-1], str) == 0)
1428 return; 1460 return;
1429 1461
1430 free(state->history[MAX_HISTORY]); /* redundant, paranoia */ 1462 free(state->history[state->max_history]); /* redundant, paranoia */
1431 state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */ 1463 state->history[state->max_history] = NULL; /* redundant, paranoia */
1432 1464
1433 /* If history[] is full, remove the oldest command */ 1465 /* If history[] is full, remove the oldest command */
1434 /* we need to keep history[MAX_HISTORY] empty, hence >=, not > */ 1466 /* we need to keep history[state->max_history] empty, hence >=, not > */
1435 if (i >= MAX_HISTORY) { 1467 if (i >= state->max_history) {
1436 free(state->history[0]); 1468 free(state->history[0]);
1437 for (i = 0; i < MAX_HISTORY-1; i++) 1469 for (i = 0; i < state->max_history-1; i++)
1438 state->history[i] = state->history[i+1]; 1470 state->history[i] = state->history[i+1];
1439 /* i == MAX_HISTORY-1 */ 1471 /* i == state->max_history-1 */
1440 } 1472 }
1441 /* i <= MAX_HISTORY-1 */ 1473 /* i <= state->max_history-1 */
1442 state->history[i++] = xstrdup(str); 1474 state->history[i++] = xstrdup(str);
1443 /* i <= MAX_HISTORY */ 1475 /* i <= state->max_history */
1444 state->cur_history = i; 1476 state->cur_history = i;
1445 state->cnt_history = i; 1477 state->cnt_history = i;
1446# if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY 1478# if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -1968,7 +2000,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
1968 maxsize = MAX_LINELEN; 2000 maxsize = MAX_LINELEN;
1969 S.maxsize = maxsize; 2001 S.maxsize = maxsize;
1970 2002
1971 /* With null flags, no other fields are ever used */ 2003 /* With zero flags, no other fields are ever used */
1972 state = st ? st : (line_input_t*) &const_int_0; 2004 state = st ? st : (line_input_t*) &const_int_0;
1973#if MAX_HISTORY > 0 2005#if MAX_HISTORY > 0
1974# if ENABLE_FEATURE_EDITING_SAVEHISTORY 2006# if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -2020,7 +2052,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2020#endif 2052#endif
2021 2053
2022#if 0 2054#if 0
2023 for (i = 0; i <= MAX_HISTORY; i++) 2055 for (i = 0; i <= state->max_history; i++)
2024 bb_error_msg("history[%d]:'%s'", i, state->history[i]); 2056 bb_error_msg("history[%d]:'%s'", i, state->history[i]);
2025 bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history); 2057 bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
2026#endif 2058#endif