summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/fhandler.cc20
-rw-r--r--winsup/cygwin/fhandler.h4
-rw-r--r--winsup/cygwin/fhandler_termios.cc29
-rw-r--r--winsup/cygwin/include/sys/termios.h1
4 files changed, 31 insertions, 23 deletions
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index a8fe3b692..aa4cd6983 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -111,26 +111,6 @@ fhandler_base::set_readahead_valid (int val, int ch)
}
int
-fhandler_base::eat_readahead (int n)
-{
- int oralen = ralen;
- if (n < 0)
- n = ralen;
- if (n > 0 && ralen)
- {
- if ((int) (ralen -= n) < 0)
- ralen = 0;
-
- if (raixget >= ralen)
- raixget = raixput = ralen = 0;
- else if (raixput > ralen)
- raixput = ralen;
- }
-
- return oralen;
-}
-
-int
fhandler_base::get_readahead_into_buffer (char *buf, size_t buflen)
{
int ch;
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index c7db8f8e3..14f7680ad 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -288,8 +288,6 @@ class fhandler_base
int get_readahead ();
int peek_readahead (int queryput = 0);
- int eat_readahead (int n);
-
void set_readahead_valid (int val, int ch = -1);
int get_readahead_into_buffer (char *buf, size_t buflen);
@@ -1217,6 +1215,8 @@ class fhandler_termios: public fhandler_base
int ioctl (int, void *);
tty_min *_tc;
tty *get_ttyp () {return (tty *) tc ();}
+ int eat_readahead (int n);
+
public:
tty_min*& tc () {return _tc;}
fhandler_termios () :
diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc
index dc8a19b02..19fcfc9cd 100644
--- a/winsup/cygwin/fhandler_termios.cc
+++ b/winsup/cygwin/fhandler_termios.cc
@@ -30,7 +30,7 @@ fhandler_termios::tcinit (bool is_pty_master)
if (is_pty_master || !tc ()->initialized ())
{
- tc ()->ti.c_iflag = BRKINT | ICRNL | IXON;
+ tc ()->ti.c_iflag = BRKINT | ICRNL | IXON | IUTF8;
tc ()->ti.c_oflag = OPOST | ONLCR;
tc ()->ti.c_cflag = B38400 | CS8 | CREAD;
tc ()->ti.c_lflag = ISIG | ICANON | ECHO | IEXTEN;
@@ -257,6 +257,33 @@ fhandler_termios::bg_check (int sig, bool dontsignal)
#define set_input_done(x) input_done = input_done || (x)
+int
+fhandler_termios::eat_readahead (int n)
+{
+ int oralen = ralen;
+ if (n < 0)
+ n = ralen;
+ if (n > 0 && ralen > 0)
+ {
+ if ((int) (ralen -= n) < 0)
+ ralen = 0;
+ /* If IUTF8 is set, the terminal is in UTF-8 mode. If so, we erase
+ a complete UTF-8 multibyte sequence on VERASE/VWERASE. Otherwise,
+ if we only erase a single byte, invalid unicode chars are left in
+ the input. */
+ if (tc ()->ti.c_iflag & IUTF8)
+ while (ralen > 0 && ((unsigned char) rabuf[ralen] & 0xc0) == 0x80)
+ --ralen;
+
+ if (raixget >= ralen)
+ raixget = raixput = ralen = 0;
+ else if (raixput > ralen)
+ raixput = ralen;
+ }
+
+ return oralen;
+}
+
inline void
fhandler_termios::echo_erase (int force)
{
diff --git a/winsup/cygwin/include/sys/termios.h b/winsup/cygwin/include/sys/termios.h
index 38de08744..17e8d83a3 100644
--- a/winsup/cygwin/include/sys/termios.h
+++ b/winsup/cygwin/include/sys/termios.h
@@ -115,6 +115,7 @@ POSIX commands */
#define IUCLC 0x04000
#define IXANY 0x08000
#define PARMRK 0x10000
+#define IUTF8 0x20000
/* oflag bits */