diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-15 03:27:53 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-15 03:27:53 +0200 |
commit | c15f40c3e7bfeae1b616c53a574308c2df707b3d (patch) | |
tree | 402bed67555916e3ff3c6a08ccc6e994372d4524 /libbb/lineedit.c | |
parent | 1b0a93edb93a93c30d7fbb35571f109ddf8a67a2 (diff) | |
download | busybox-w32-c15f40c3e7bfeae1b616c53a574308c2df707b3d.tar.gz busybox-w32-c15f40c3e7bfeae1b616c53a574308c2df707b3d.tar.bz2 busybox-w32-c15f40c3e7bfeae1b616c53a574308c2df707b3d.zip |
lineedit: use read_key to recognize ESC sequence.
This fixes several vi mode bugs and prepares for further fixes.
function old new delta
read_line_input 3287 5511 +2224
remember_in_history - 499 +499
lineedit_read_key - 70 +70
read_key 321 332 +11
input_tab 2823 - -2823
------------------------------------------------------------------------------
(add/remove: 2/1 grow/shrink: 2/0 up/down: 2804/-2823) Total: -19 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r-- | libbb/lineedit.c | 309 |
1 files changed, 145 insertions, 164 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index e0ab73250..ccf3e0dc8 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -1430,6 +1430,22 @@ static void win_changed(int nsig) | |||
1430 | signal(SIGWINCH, win_changed); /* rearm ourself */ | 1430 | signal(SIGWINCH, win_changed); /* rearm ourself */ |
1431 | } | 1431 | } |
1432 | 1432 | ||
1433 | static int lineedit_read_key(smalluint *read_key_bufsize, char *read_key_buffer) | ||
1434 | { | ||
1435 | int ic; | ||
1436 | struct pollfd pfd; | ||
1437 | pfd.fd = STDIN_FILENO; | ||
1438 | pfd.events = POLLIN; | ||
1439 | do { | ||
1440 | /* Wait for input. Can't just call read_key, it will return | ||
1441 | * at once if stdin is in non-blocking mode. */ | ||
1442 | safe_poll(&pfd, 1, -1); | ||
1443 | /* note: read_key sets errno to 0 on success: */ | ||
1444 | ic = read_key(STDIN_FILENO, read_key_bufsize, read_key_buffer); | ||
1445 | } while (errno == EAGAIN); | ||
1446 | return ic; | ||
1447 | } | ||
1448 | |||
1433 | /* | 1449 | /* |
1434 | * The emacs and vi modes share much of the code in the big | 1450 | * The emacs and vi modes share much of the code in the big |
1435 | * command loop. Commands entered when in vi's command mode (aka | 1451 | * command loop. Commands entered when in vi's command mode (aka |
@@ -1438,7 +1454,7 @@ static void win_changed(int nsig) | |||
1438 | * big switch a bit, but keeps all the code in one place. | 1454 | * big switch a bit, but keeps all the code in one place. |
1439 | */ | 1455 | */ |
1440 | 1456 | ||
1441 | #define vbit 0x100 | 1457 | #define VI_CMDMODE_BIT 0x100 |
1442 | 1458 | ||
1443 | /* leave out the "vi-mode"-only case labels if vi editing isn't | 1459 | /* leave out the "vi-mode"-only case labels if vi editing isn't |
1444 | * configured. */ | 1460 | * configured. */ |
@@ -1459,15 +1475,15 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1459 | #if ENABLE_FEATURE_TAB_COMPLETION | 1475 | #if ENABLE_FEATURE_TAB_COMPLETION |
1460 | smallint lastWasTab = FALSE; | 1476 | smallint lastWasTab = FALSE; |
1461 | #endif | 1477 | #endif |
1462 | unsigned ic; | 1478 | int ic; |
1463 | unsigned char c; | ||
1464 | smallint break_out = 0; | 1479 | smallint break_out = 0; |
1465 | #if ENABLE_FEATURE_EDITING_VI | 1480 | #if ENABLE_FEATURE_EDITING_VI |
1466 | smallint vi_cmdmode = 0; | 1481 | smallint vi_cmdmode = 0; |
1467 | smalluint prevc; | ||
1468 | #endif | 1482 | #endif |
1469 | struct termios initial_settings; | 1483 | struct termios initial_settings; |
1470 | struct termios new_settings; | 1484 | struct termios new_settings; |
1485 | smalluint read_key_bufsize; | ||
1486 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; | ||
1471 | 1487 | ||
1472 | INIT_S(); | 1488 | INIT_S(); |
1473 | 1489 | ||
@@ -1545,42 +1561,40 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1545 | 1561 | ||
1546 | while (1) { | 1562 | while (1) { |
1547 | fflush(NULL); | 1563 | fflush(NULL); |
1548 | 1564 | ic = lineedit_read_key(&read_key_bufsize, read_key_buffer); | |
1549 | if (nonblock_safe_read(STDIN_FILENO, &c, 1) < 1) { | ||
1550 | /* if we can't read input then exit */ | ||
1551 | goto prepare_to_die; | ||
1552 | } | ||
1553 | |||
1554 | ic = c; | ||
1555 | 1565 | ||
1556 | #if ENABLE_FEATURE_EDITING_VI | 1566 | #if ENABLE_FEATURE_EDITING_VI |
1557 | newdelflag = 1; | 1567 | newdelflag = 1; |
1558 | if (vi_cmdmode) | 1568 | if (vi_cmdmode) { |
1559 | ic |= vbit; | 1569 | /* btw, since KEYCODE_xxx are all < 0, this doesn't |
1570 | * change ic if it contains one of them: */ | ||
1571 | ic |= VI_CMDMODE_BIT; | ||
1572 | } | ||
1560 | #endif | 1573 | #endif |
1574 | |||
1561 | switch (ic) { | 1575 | switch (ic) { |
1562 | case '\n': | 1576 | case '\n': |
1563 | case '\r': | 1577 | case '\r': |
1564 | vi_case('\n'|vbit:) | 1578 | vi_case('\n'|VI_CMDMODE_BIT:) |
1565 | vi_case('\r'|vbit:) | 1579 | vi_case('\r'|VI_CMDMODE_BIT:) |
1566 | /* Enter */ | 1580 | /* Enter */ |
1567 | goto_new_line(); | 1581 | goto_new_line(); |
1568 | break_out = 1; | 1582 | break_out = 1; |
1569 | break; | 1583 | break; |
1570 | case CTRL('A'): | 1584 | case CTRL('A'): |
1571 | vi_case('0'|vbit:) | 1585 | vi_case('0'|VI_CMDMODE_BIT:) |
1572 | /* Control-a -- Beginning of line */ | 1586 | /* Control-a -- Beginning of line */ |
1573 | input_backward(cursor); | 1587 | input_backward(cursor); |
1574 | break; | 1588 | break; |
1575 | case CTRL('B'): | 1589 | case CTRL('B'): |
1576 | vi_case('h'|vbit:) | 1590 | vi_case('h'|VI_CMDMODE_BIT:) |
1577 | vi_case('\b'|vbit:) | 1591 | vi_case('\b'|VI_CMDMODE_BIT:) |
1578 | vi_case('\x7f'|vbit:) /* DEL */ | 1592 | vi_case('\x7f'|VI_CMDMODE_BIT:) /* DEL */ |
1579 | /* Control-b -- Move back one character */ | 1593 | /* Control-b -- Move back one character */ |
1580 | input_backward(1); | 1594 | input_backward(1); |
1581 | break; | 1595 | break; |
1582 | case CTRL('C'): | 1596 | case CTRL('C'): |
1583 | vi_case(CTRL('C')|vbit:) | 1597 | vi_case(CTRL('C')|VI_CMDMODE_BIT:) |
1584 | /* Control-c -- stop gathering input */ | 1598 | /* Control-c -- stop gathering input */ |
1585 | goto_new_line(); | 1599 | goto_new_line(); |
1586 | command_len = 0; | 1600 | command_len = 0; |
@@ -1598,31 +1612,27 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1598 | } | 1612 | } |
1599 | input_delete(0); | 1613 | input_delete(0); |
1600 | break; | 1614 | break; |
1601 | |||
1602 | case CTRL('E'): | 1615 | case CTRL('E'): |
1603 | vi_case('$'|vbit:) | 1616 | vi_case('$'|VI_CMDMODE_BIT:) |
1604 | /* Control-e -- End of line */ | 1617 | /* Control-e -- End of line */ |
1605 | input_end(); | 1618 | input_end(); |
1606 | break; | 1619 | break; |
1607 | case CTRL('F'): | 1620 | case CTRL('F'): |
1608 | vi_case('l'|vbit:) | 1621 | vi_case('l'|VI_CMDMODE_BIT:) |
1609 | vi_case(' '|vbit:) | 1622 | vi_case(' '|VI_CMDMODE_BIT:) |
1610 | /* Control-f -- Move forward one character */ | 1623 | /* Control-f -- Move forward one character */ |
1611 | input_forward(); | 1624 | input_forward(); |
1612 | break; | 1625 | break; |
1613 | |||
1614 | case '\b': | 1626 | case '\b': |
1615 | case '\x7f': /* DEL */ | 1627 | case '\x7f': /* DEL */ |
1616 | /* Control-h and DEL */ | 1628 | /* Control-h and DEL */ |
1617 | input_backspace(); | 1629 | input_backspace(); |
1618 | break; | 1630 | break; |
1619 | |||
1620 | #if ENABLE_FEATURE_TAB_COMPLETION | 1631 | #if ENABLE_FEATURE_TAB_COMPLETION |
1621 | case '\t': | 1632 | case '\t': |
1622 | input_tab(&lastWasTab); | 1633 | input_tab(&lastWasTab); |
1623 | break; | 1634 | break; |
1624 | #endif | 1635 | #endif |
1625 | |||
1626 | case CTRL('K'): | 1636 | case CTRL('K'): |
1627 | /* Control-k -- clear to end of line */ | 1637 | /* Control-k -- clear to end of line */ |
1628 | command[cursor] = 0; | 1638 | command[cursor] = 0; |
@@ -1630,31 +1640,29 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1630 | printf("\033[J"); | 1640 | printf("\033[J"); |
1631 | break; | 1641 | break; |
1632 | case CTRL('L'): | 1642 | case CTRL('L'): |
1633 | vi_case(CTRL('L')|vbit:) | 1643 | vi_case(CTRL('L')|VI_CMDMODE_BIT:) |
1634 | /* Control-l -- clear screen */ | 1644 | /* Control-l -- clear screen */ |
1635 | printf("\033[H"); | 1645 | printf("\033[H"); |
1636 | redraw(0, command_len - cursor); | 1646 | redraw(0, command_len - cursor); |
1637 | break; | 1647 | break; |
1638 | |||
1639 | #if MAX_HISTORY > 0 | 1648 | #if MAX_HISTORY > 0 |
1640 | case CTRL('N'): | 1649 | case CTRL('N'): |
1641 | vi_case(CTRL('N')|vbit:) | 1650 | vi_case(CTRL('N')|VI_CMDMODE_BIT:) |
1642 | vi_case('j'|vbit:) | 1651 | vi_case('j'|VI_CMDMODE_BIT:) |
1643 | /* Control-n -- Get next command in history */ | 1652 | /* Control-n -- Get next command in history */ |
1644 | if (get_next_history()) | 1653 | if (get_next_history()) |
1645 | goto rewrite_line; | 1654 | goto rewrite_line; |
1646 | break; | 1655 | break; |
1647 | case CTRL('P'): | 1656 | case CTRL('P'): |
1648 | vi_case(CTRL('P')|vbit:) | 1657 | vi_case(CTRL('P')|VI_CMDMODE_BIT:) |
1649 | vi_case('k'|vbit:) | 1658 | vi_case('k'|VI_CMDMODE_BIT:) |
1650 | /* Control-p -- Get previous command from history */ | 1659 | /* Control-p -- Get previous command from history */ |
1651 | if (get_previous_history()) | 1660 | if (get_previous_history()) |
1652 | goto rewrite_line; | 1661 | goto rewrite_line; |
1653 | break; | 1662 | break; |
1654 | #endif | 1663 | #endif |
1655 | |||
1656 | case CTRL('U'): | 1664 | case CTRL('U'): |
1657 | vi_case(CTRL('U')|vbit:) | 1665 | vi_case(CTRL('U')|VI_CMDMODE_BIT:) |
1658 | /* Control-U -- Clear line before cursor */ | 1666 | /* Control-U -- Clear line before cursor */ |
1659 | if (cursor) { | 1667 | if (cursor) { |
1660 | overlapping_strcpy(command, command + cursor); | 1668 | overlapping_strcpy(command, command + cursor); |
@@ -1663,7 +1671,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1663 | } | 1671 | } |
1664 | break; | 1672 | break; |
1665 | case CTRL('W'): | 1673 | case CTRL('W'): |
1666 | vi_case(CTRL('W')|vbit:) | 1674 | vi_case(CTRL('W')|VI_CMDMODE_BIT:) |
1667 | /* Control-W -- Remove the last word */ | 1675 | /* Control-W -- Remove the last word */ |
1668 | while (cursor > 0 && isspace(command[cursor-1])) | 1676 | while (cursor > 0 && isspace(command[cursor-1])) |
1669 | input_backspace(); | 1677 | input_backspace(); |
@@ -1672,75 +1680,80 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1672 | break; | 1680 | break; |
1673 | 1681 | ||
1674 | #if ENABLE_FEATURE_EDITING_VI | 1682 | #if ENABLE_FEATURE_EDITING_VI |
1675 | case 'i'|vbit: | 1683 | case 'i'|VI_CMDMODE_BIT: |
1676 | vi_cmdmode = 0; | 1684 | vi_cmdmode = 0; |
1677 | break; | 1685 | break; |
1678 | case 'I'|vbit: | 1686 | case 'I'|VI_CMDMODE_BIT: |
1679 | input_backward(cursor); | 1687 | input_backward(cursor); |
1680 | vi_cmdmode = 0; | 1688 | vi_cmdmode = 0; |
1681 | break; | 1689 | break; |
1682 | case 'a'|vbit: | 1690 | case 'a'|VI_CMDMODE_BIT: |
1683 | input_forward(); | 1691 | input_forward(); |
1684 | vi_cmdmode = 0; | 1692 | vi_cmdmode = 0; |
1685 | break; | 1693 | break; |
1686 | case 'A'|vbit: | 1694 | case 'A'|VI_CMDMODE_BIT: |
1687 | input_end(); | 1695 | input_end(); |
1688 | vi_cmdmode = 0; | 1696 | vi_cmdmode = 0; |
1689 | break; | 1697 | break; |
1690 | case 'x'|vbit: | 1698 | case 'x'|VI_CMDMODE_BIT: |
1691 | input_delete(1); | 1699 | input_delete(1); |
1692 | break; | 1700 | break; |
1693 | case 'X'|vbit: | 1701 | case 'X'|VI_CMDMODE_BIT: |
1694 | if (cursor > 0) { | 1702 | if (cursor > 0) { |
1695 | input_backward(1); | 1703 | input_backward(1); |
1696 | input_delete(1); | 1704 | input_delete(1); |
1697 | } | 1705 | } |
1698 | break; | 1706 | break; |
1699 | case 'W'|vbit: | 1707 | case 'W'|VI_CMDMODE_BIT: |
1700 | vi_Word_motion(command, 1); | 1708 | vi_Word_motion(command, 1); |
1701 | break; | 1709 | break; |
1702 | case 'w'|vbit: | 1710 | case 'w'|VI_CMDMODE_BIT: |
1703 | vi_word_motion(command, 1); | 1711 | vi_word_motion(command, 1); |
1704 | break; | 1712 | break; |
1705 | case 'E'|vbit: | 1713 | case 'E'|VI_CMDMODE_BIT: |
1706 | vi_End_motion(command); | 1714 | vi_End_motion(command); |
1707 | break; | 1715 | break; |
1708 | case 'e'|vbit: | 1716 | case 'e'|VI_CMDMODE_BIT: |
1709 | vi_end_motion(command); | 1717 | vi_end_motion(command); |
1710 | break; | 1718 | break; |
1711 | case 'B'|vbit: | 1719 | case 'B'|VI_CMDMODE_BIT: |
1712 | vi_Back_motion(command); | 1720 | vi_Back_motion(command); |
1713 | break; | 1721 | break; |
1714 | case 'b'|vbit: | 1722 | case 'b'|VI_CMDMODE_BIT: |
1715 | vi_back_motion(command); | 1723 | vi_back_motion(command); |
1716 | break; | 1724 | break; |
1717 | case 'C'|vbit: | 1725 | case 'C'|VI_CMDMODE_BIT: |
1718 | vi_cmdmode = 0; | 1726 | vi_cmdmode = 0; |
1719 | /* fall through */ | 1727 | /* fall through */ |
1720 | case 'D'|vbit: | 1728 | case 'D'|VI_CMDMODE_BIT: |
1721 | goto clear_to_eol; | 1729 | goto clear_to_eol; |
1722 | 1730 | ||
1723 | case 'c'|vbit: | 1731 | case 'c'|VI_CMDMODE_BIT: |
1724 | vi_cmdmode = 0; | 1732 | vi_cmdmode = 0; |
1725 | /* fall through */ | 1733 | /* fall through */ |
1726 | case 'd'|vbit: { | 1734 | case 'd'|VI_CMDMODE_BIT: { |
1727 | int nc, sc; | 1735 | int nc, sc; |
1736 | int prev_ic; | ||
1737 | |||
1728 | sc = cursor; | 1738 | sc = cursor; |
1729 | prevc = ic; | 1739 | prev_ic = ic; |
1730 | if (safe_read(STDIN_FILENO, &c, 1) < 1) | 1740 | |
1741 | ic = lineedit_read_key(&read_key_bufsize, read_key_buffer); | ||
1742 | if (errno) /* error */ | ||
1731 | goto prepare_to_die; | 1743 | goto prepare_to_die; |
1732 | if (c == (prevc & 0xff)) { | 1744 | |
1745 | if ((ic | VI_CMDMODE_BIT) == prev_ic) { | ||
1733 | /* "cc", "dd" */ | 1746 | /* "cc", "dd" */ |
1734 | input_backward(cursor); | 1747 | input_backward(cursor); |
1735 | goto clear_to_eol; | 1748 | goto clear_to_eol; |
1736 | break; | 1749 | break; |
1737 | } | 1750 | } |
1738 | switch (c) { | 1751 | switch (ic) { |
1739 | case 'w': | 1752 | case 'w': |
1740 | case 'W': | 1753 | case 'W': |
1741 | case 'e': | 1754 | case 'e': |
1742 | case 'E': | 1755 | case 'E': |
1743 | switch (c) { | 1756 | switch (ic) { |
1744 | case 'w': /* "dw", "cw" */ | 1757 | case 'w': /* "dw", "cw" */ |
1745 | vi_word_motion(command, vi_cmdmode); | 1758 | vi_word_motion(command, vi_cmdmode); |
1746 | break; | 1759 | break; |
@@ -1763,7 +1776,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1763 | break; | 1776 | break; |
1764 | case 'b': /* "db", "cb" */ | 1777 | case 'b': /* "db", "cb" */ |
1765 | case 'B': /* implemented as B */ | 1778 | case 'B': /* implemented as B */ |
1766 | if (c == 'b') | 1779 | if (ic == 'b') |
1767 | vi_back_motion(command); | 1780 | vi_back_motion(command); |
1768 | else | 1781 | else |
1769 | vi_Back_motion(command); | 1782 | vi_Back_motion(command); |
@@ -1774,143 +1787,109 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1774 | input_delete(1); | 1787 | input_delete(1); |
1775 | break; | 1788 | break; |
1776 | case '$': /* "d$", "c$" */ | 1789 | case '$': /* "d$", "c$" */ |
1777 | clear_to_eol: | 1790 | clear_to_eol: |
1778 | while (cursor < command_len) | 1791 | while (cursor < command_len) |
1779 | input_delete(1); | 1792 | input_delete(1); |
1780 | break; | 1793 | break; |
1781 | } | 1794 | } |
1782 | break; | 1795 | break; |
1783 | } | 1796 | } |
1784 | case 'p'|vbit: | 1797 | case 'p'|VI_CMDMODE_BIT: |
1785 | input_forward(); | 1798 | input_forward(); |
1786 | /* fallthrough */ | 1799 | /* fallthrough */ |
1787 | case 'P'|vbit: | 1800 | case 'P'|VI_CMDMODE_BIT: |
1788 | put(); | 1801 | put(); |
1789 | break; | 1802 | break; |
1790 | case 'r'|vbit: | 1803 | case 'r'|VI_CMDMODE_BIT: |
1791 | if (safe_read(STDIN_FILENO, &c, 1) < 1) | 1804 | ic = lineedit_read_key(&read_key_bufsize, read_key_buffer); |
1805 | if (errno) /* error */ | ||
1792 | goto prepare_to_die; | 1806 | goto prepare_to_die; |
1793 | if (c == 0) | 1807 | if (ic < ' ' || ic > 255) { |
1794 | beep(); | 1808 | beep(); |
1795 | else { | 1809 | } else { |
1796 | *(command + cursor) = c; | 1810 | command[cursor] = ic; |
1797 | bb_putchar(c); | 1811 | bb_putchar(ic); |
1798 | bb_putchar('\b'); | 1812 | bb_putchar('\b'); |
1799 | } | 1813 | } |
1800 | break; | 1814 | break; |
1801 | #endif /* FEATURE_COMMAND_EDITING_VI */ | ||
1802 | |||
1803 | case '\x1b': /* ESC */ | 1815 | case '\x1b': /* ESC */ |
1804 | |||
1805 | #if ENABLE_FEATURE_EDITING_VI | ||
1806 | if (state->flags & VI_MODE) { | 1816 | if (state->flags & VI_MODE) { |
1807 | /* ESC: insert mode --> command mode */ | 1817 | /* insert mode --> command mode */ |
1808 | vi_cmdmode = 1; | 1818 | vi_cmdmode = 1; |
1809 | input_backward(1); | 1819 | input_backward(1); |
1810 | break; | ||
1811 | } | ||
1812 | #endif | ||
1813 | /* escape sequence follows */ | ||
1814 | if (safe_read(STDIN_FILENO, &c, 1) < 1) | ||
1815 | goto prepare_to_die; | ||
1816 | /* different vt100 emulations */ | ||
1817 | if (c == '[' || c == 'O') { | ||
1818 | vi_case('['|vbit:) | ||
1819 | vi_case('O'|vbit:) | ||
1820 | if (safe_read(STDIN_FILENO, &c, 1) < 1) | ||
1821 | goto prepare_to_die; | ||
1822 | } | ||
1823 | if (c >= '1' && c <= '9') { | ||
1824 | unsigned char dummy; | ||
1825 | |||
1826 | if (safe_read(STDIN_FILENO, &dummy, 1) < 1) | ||
1827 | goto prepare_to_die; | ||
1828 | if (dummy != '~') | ||
1829 | c = '\0'; | ||
1830 | } | 1820 | } |
1821 | break; | ||
1822 | #endif /* FEATURE_COMMAND_EDITING_VI */ | ||
1831 | 1823 | ||
1832 | switch (c) { | ||
1833 | #if ENABLE_FEATURE_TAB_COMPLETION | ||
1834 | case '\t': /* Alt-Tab */ | ||
1835 | input_tab(&lastWasTab); | ||
1836 | break; | ||
1837 | #endif | ||
1838 | #if MAX_HISTORY > 0 | 1824 | #if MAX_HISTORY > 0 |
1839 | case 'A': | 1825 | case KEYCODE_UP: |
1840 | /* Up Arrow -- Get previous command from history */ | 1826 | if (get_previous_history()) |
1841 | if (get_previous_history()) | 1827 | goto rewrite_line; |
1842 | goto rewrite_line; | 1828 | beep(); |
1843 | beep(); | 1829 | break; |
1830 | case KEYCODE_DOWN: | ||
1831 | if (!get_next_history()) | ||
1844 | break; | 1832 | break; |
1845 | case 'B': | ||
1846 | /* Down Arrow -- Get next command in history */ | ||
1847 | if (!get_next_history()) | ||
1848 | break; | ||
1849 | rewrite_line: | 1833 | rewrite_line: |
1850 | /* Rewrite the line with the selected history item */ | 1834 | /* Rewrite the line with the selected history item */ |
1851 | /* change command */ | 1835 | /* change command */ |
1852 | command_len = strlen(strcpy(command, state->history[state->cur_history] ? : "")); | 1836 | command_len = strlen(strcpy(command, state->history[state->cur_history] ? : "")); |
1853 | /* redraw and go to eol (bol, in vi */ | 1837 | /* redraw and go to eol (bol, in vi) */ |
1854 | redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0); | 1838 | redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0); |
1855 | break; | 1839 | break; |
1856 | #endif | 1840 | #endif |
1857 | case 'C': | 1841 | case KEYCODE_RIGHT: |
1858 | /* Right Arrow -- Move forward one character */ | 1842 | input_forward(); |
1859 | input_forward(); | 1843 | break; |
1860 | break; | 1844 | case KEYCODE_LEFT: |
1861 | case 'D': | 1845 | input_backward(1); |
1862 | /* Left Arrow -- Move back one character */ | 1846 | break; |
1863 | input_backward(1); | 1847 | case KEYCODE_DELETE: |
1864 | break; | 1848 | input_delete(0); |
1865 | case '3': | 1849 | break; |
1866 | /* Delete */ | 1850 | case KEYCODE_HOME: |
1867 | input_delete(0); | 1851 | input_backward(cursor); |
1868 | break; | 1852 | break; |
1869 | case '1': // vt100? linux vt? or what? | 1853 | case KEYCODE_END: |
1870 | case '7': // vt100? linux vt? or what? | 1854 | input_end(); |
1871 | case 'H': /* xterm's <Home> */ | ||
1872 | input_backward(cursor); | ||
1873 | break; | ||
1874 | case '4': // vt100? linux vt? or what? | ||
1875 | case '8': // vt100? linux vt? or what? | ||
1876 | case 'F': /* xterm's <End> */ | ||
1877 | input_end(); | ||
1878 | break; | ||
1879 | default: | ||
1880 | c = '\0'; | ||
1881 | beep(); | ||
1882 | } | ||
1883 | break; | 1855 | break; |
1884 | 1856 | ||
1885 | default: /* If it's regular input, do the normal thing */ | 1857 | default: |
1886 | 1858 | // /* Control-V -- force insert of next char */ | |
1887 | /* Control-V -- force insert of next char */ | 1859 | // if (c == CTRL('V')) { |
1888 | if (c == CTRL('V')) { | 1860 | // if (safe_read(STDIN_FILENO, &c, 1) < 1) |
1889 | if (safe_read(STDIN_FILENO, &c, 1) < 1) | 1861 | // goto prepare_to_die; |
1890 | goto prepare_to_die; | 1862 | // if (c == 0) { |
1891 | if (c == 0) { | 1863 | // beep(); |
1892 | beep(); | 1864 | // break; |
1893 | break; | 1865 | // } |
1894 | } | 1866 | // } |
1895 | } | 1867 | if (ic < ' ' || ic > 255) { |
1896 | 1868 | /* If VI_CMDMODE_BIT is set, ic is >= 256 | |
1897 | #if ENABLE_FEATURE_EDITING_VI | 1869 | * and command mode ignores unexpected chars. |
1898 | if (vi_cmdmode) /* Don't self-insert */ | 1870 | * Otherwise, we are here if ic is a |
1871 | * control char or an unhandled ESC sequence, | ||
1872 | * which is also ignored. | ||
1873 | */ | ||
1899 | break; | 1874 | break; |
1900 | #endif | 1875 | } |
1901 | if ((int)command_len >= (maxsize - 2)) /* Need to leave space for enter */ | 1876 | if ((int)command_len >= (maxsize - 2)) { |
1877 | /* Not enough space for the char and EOL */ | ||
1902 | break; | 1878 | break; |
1879 | } | ||
1903 | 1880 | ||
1904 | command_len++; | 1881 | command_len++; |
1905 | if (cursor == (command_len - 1)) { /* Append if at the end of the line */ | 1882 | if (cursor == (command_len - 1)) { |
1906 | command[cursor] = c; | 1883 | /* We are at the end, append */ |
1907 | command[cursor+1] = '\0'; | 1884 | command[cursor] = ic; |
1885 | command[cursor + 1] = '\0'; | ||
1908 | cmdedit_set_out_char(' '); | 1886 | cmdedit_set_out_char(' '); |
1909 | } else { /* Insert otherwise */ | 1887 | } else { |
1888 | /* In the middle, insert */ | ||
1910 | int sc = cursor; | 1889 | int sc = cursor; |
1911 | 1890 | ||
1912 | memmove(command + sc + 1, command + sc, command_len - sc); | 1891 | memmove(command + sc + 1, command + sc, command_len - sc); |
1913 | command[sc] = c; | 1892 | command[sc] = ic; |
1914 | sc++; | 1893 | sc++; |
1915 | /* rewrite from cursor */ | 1894 | /* rewrite from cursor */ |
1916 | input_end(); | 1895 | input_end(); |
@@ -1918,15 +1897,17 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1918 | input_backward(cursor - sc); | 1897 | input_backward(cursor - sc); |
1919 | } | 1898 | } |
1920 | break; | 1899 | break; |
1921 | } | 1900 | } /* switch (input_key) */ |
1922 | if (break_out) /* Enter is the command terminator, no more input. */ | 1901 | |
1902 | if (break_out) | ||
1923 | break; | 1903 | break; |
1924 | 1904 | ||
1925 | #if ENABLE_FEATURE_TAB_COMPLETION | 1905 | #if ENABLE_FEATURE_TAB_COMPLETION |
1926 | if (c != '\t') | 1906 | ic &= ~VI_CMDMODE_BIT; |
1907 | if (ic != '\t') | ||
1927 | lastWasTab = FALSE; | 1908 | lastWasTab = FALSE; |
1928 | #endif | 1909 | #endif |
1929 | } | 1910 | } /* while (1) */ |
1930 | 1911 | ||
1931 | if (command_len > 0) | 1912 | if (command_len > 0) |
1932 | remember_in_history(command); | 1913 | remember_in_history(command); |