Re: [PATCH v3 0/3] Reworks for console code

2019-03-31 Thread Corinna Vinschen
On Apr  1 00:47, Takashi Yano wrote:
> Hi Corinna,
> 
> On Sun, 31 Mar 2019 16:36:51 +0200 Corinna Vinschen rote:
> > This hunk is ok, but I wonder if the time hasn't come to simplify the
> > original code.  The `static char NO_COPY' only makes marginal sense
> > since it's strdup'ed anyway.
> > 
> > What if we just define two const char's like this
> > 
> >   const char cygterm[] = "TERM=cygwin";
> >   const char xterm[] = "TERM=xterm-256color";
> > 
> > and then just strdup them conditionally:
> > 
> >   if (!sawTERM)
> > envp[i++] = strdup (wincap.has_con_24bit_colors () ? xterm :
> > cygterm);
> > 
> > What do you think?
> 
> > Sorry, didn't notice this before:  Please prepend this block with
> > a comment along the lines of "/* Not yet defined in Mingw-w64 */"
> 
> Adopted.
> 
> > Doesn't this belong into the select patch?
> 
> Actually, no. This makes select() recognize Ctrl-space, but
> is just tentative. Patch 0002 overwrites this fix.
> 
> This is corresponding to:
> > @@ -435,7 +451,8 @@ fhandler_console::read (void *pv, size_t& buflen)
> >   toadd = tmp;
> > }
> >   /* Allow Ctrl-Space to emit ^@ */
> > - else if (input_rec.Event.KeyEvent.wVirtualKeyCode == VK_SPACE
> > + else if (input_rec.Event.KeyEvent.wVirtualKeyCode
> > +  == (wincap.has_con_24bit_colors () ? '2' : VK_SPACE)
> >&& (ctrl_key_state & CTRL_PRESSED)
> >&& !(ctrl_key_state & ALT_PRESSED))
> > toadd = "";

Ah, right, that makes sense.

Pushed.  I added release info accordingly.  I'm also just building new
developer snapshots with this patchset included.


Thanks,
Corinna

-- 
Corinna Vinschen
Cygwin Maintainer


signature.asc
Description: PGP signature


[PATCH v3 1/3] Cygwin: console: support 24 bit color

2019-03-31 Thread Takashi Yano
- Add 24 bit color support using xterm compatibility mode in
  Windows 10 1703 or later.
- Add fake 24 bit color support for legacy console, which uses
  the nearest color from 16 system colors.
---
 winsup/cygwin/environ.cc  |   7 +-
 winsup/cygwin/fhandler.h  |   4 +
 winsup/cygwin/fhandler_console.cc | 230 +-
 winsup/cygwin/select.cc   |   8 ++
 winsup/cygwin/wincap.cc   |  10 ++
 winsup/cygwin/wincap.h|   2 +
 6 files changed, 227 insertions(+), 34 deletions(-)

diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 21f13734c..a47ed72e7 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -869,7 +869,8 @@ win32env_to_cygenv (PWCHAR rawenv, bool posify)
   char *newp;
   int i;
   int sawTERM = 0;
-  static char NO_COPY cygterm[] = "TERM=cygwin";
+  const char cygterm[] = "TERM=cygwin";
+  const char xterm[] = "TERM=xterm-256color";
   char *tmpbuf = tp.t_get ();
   PWCHAR w;
 
@@ -899,8 +900,10 @@ win32env_to_cygenv (PWCHAR rawenv, bool posify)
   debug_printf ("%p: %s", envp[i], envp[i]);
 }
 
+  /* If console has 24 bit color capability, TERM=xterm-256color,
+ otherwise, TERM=cygwin */
   if (!sawTERM)
-envp[i++] = strdup (cygterm);
+envp[i++] = strdup (wincap.has_con_24bit_colors () ? xterm : cygterm);
 
   envp[i] = NULL;
   return envp;
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index b336eb63a..66e724bcb 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1778,6 +1778,8 @@ enum ansi_intensity
 #define eattitle 7
 #define gotparen 8
 #define gotrparen 9
+#define eatpalette 10
+#define endpalette 11
 #define MAXARGS 10
 
 enum cltype
@@ -1791,6 +1793,8 @@ enum cltype
 
 class dev_console
 {
+  pid_t owner;
+
   WORD default_color, underline_color, dim_color;
 
   /* Used to determine if an input keystroke should be modified with META. */
diff --git a/winsup/cygwin/fhandler_console.cc 
b/winsup/cygwin/fhandler_console.cc
index 281c2005c..6b14d4a25 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -15,6 +15,7 @@ details. */
 #include 
 #include 
 #include 
+#include 
 #include "cygerrno.h"
 #include "security.h"
 #include "path.h"
@@ -32,6 +33,17 @@ details. */
 #include "child_info.h"
 #include "cygwait.h"
 
+/* Not yet defined in Mingw-w64 */
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif /* ENABLE_VIRTUAL_TERMINAL_PROCESSING */
+#ifndef DISABLE_NEWLINE_AUTO_RETURN
+#define DISABLE_NEWLINE_AUTO_RETURN 0x0008
+#endif /* DISABLE_NEWLINE_AUTO_RETURN */
+#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
+#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
+#endif /* ENABLE_VIRTUAL_TERMINAL_INPUT */
+
 /* Don't make this bigger than NT_MAX_PATH as long as the temporary buffer
is allocated using tmp_pathbuf!!! */
 #define CONVERT_LIMIT NT_MAX_PATH
@@ -148,7 +160,11 @@ fhandler_console::set_unit ()
   if (created)
shared_console_info->tty_min_state.setntty (DEV_CONS_MAJOR, 
console_unit (me));
   devset = (fh_devices) shared_console_info->tty_min_state.getntty ();
+  if (created)
+   con.owner = getpid ();
 }
+  if (!created && shared_console_info && kill (con.owner, 0) == -1)
+con.owner = getpid ();
 
   dev ().parse (devset);
   if (devset != FH_ERROR)
@@ -167,33 +183,33 @@ void
 fhandler_console::setup ()
 {
   if (set_unit ())
-  {
-   con.scroll_region.Bottom = -1;
-   con.dwLastCursorPosition.X = -1;
-   con.dwLastCursorPosition.Y = -1;
-   con.dwLastMousePosition.X = -1;
-   con.dwLastMousePosition.Y = -1;
-   con.dwLastButtonState = 0;  /* none pressed */
-   con.last_button_code = 3;   /* released */
-   con.underline_color = FOREGROUND_GREEN | FOREGROUND_BLUE;
-   con.dim_color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
-   con.meta_mask = LEFT_ALT_PRESSED;
-   /* Set the mask that determines if an input keystroke is modified by
-  META.  We set this based on the keyboard layout language loaded
-  for the current thread.  The left  key always generates
-  META, but the right  key only generates META if we are using
-  an English keyboard because many "international" keyboards
-  replace common shell symbols ('[', '{', etc.) with accented
-  language-specific characters (umlaut, accent grave, etc.).  On
-  these keyboards right  (called AltGr) is used to produce the
-  shell symbols and should not be interpreted as META. */
-   if (PRIMARYLANGID (LOWORD (GetKeyboardLayout (0))) == LANG_ENGLISH)
- con.meta_mask |= RIGHT_ALT_PRESSED;
-   con.set_default_attr ();
-   con.backspace_keycode = CERASE;
-   con.cons_rapoi = NULL;
-   shared_console_info->tty_min_state.is_console = true;
-  }
+{
+  con.scroll_region.Bottom = -1;
+  

[PATCH v3 2/3] Cygwin: console: fix select() behaviour

2019-03-31 Thread Takashi Yano
- Previously, select() would return when only one key is typed even
  in canonical mode. With this patch, it returns after one line is
  completed.
---
 winsup/cygwin/fhandler.h  |  12 +-
 winsup/cygwin/fhandler_console.cc | 794 --
 winsup/cygwin/select.cc   |  81 +--
 3 files changed, 462 insertions(+), 425 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 66e724bcb..e4a6de610 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1884,6 +1884,15 @@ public:
 tty_min tty_min_state;
 dev_console con;
   };
+  bool input_ready;
+  enum input_states
+  {
+input_error = -1,
+input_processing = 0,
+input_ok = 1,
+input_signalled = 2,
+input_winch = 3
+  };
 private:
   static const unsigned MAX_WRITE_CHARS;
   static console_state *shared_console_info;
@@ -1969,7 +1978,7 @@ private:
   void fixup_after_fork (HANDLE) {fixup_after_fork_exec (false);}
   void set_close_on_exec (bool val);
   void set_input_state ();
-  void send_winch_maybe ();
+  bool send_winch_maybe ();
   void setup ();
   bool set_unit ();
   static bool need_invisible ();
@@ -1992,6 +2001,7 @@ private:
 copyto (fh);
 return fh;
   }
+  input_states process_input_message ();
   friend tty_min * tty_list::get_cttyp ();
 };
 
diff --git a/winsup/cygwin/fhandler_console.cc 
b/winsup/cygwin/fhandler_console.cc
index 6b14d4a25..160ae284a 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -53,7 +53,9 @@ details. */
 
 #define con (shared_console_info->con)
 #define srTop (con.b.srWindow.Top + con.scroll_region.Top)
-#define srBottom ((con.scroll_region.Bottom < 0) ? con.b.srWindow.Bottom : 
con.b.srWindow.Top + con.scroll_region.Bottom)
+#define srBottom ((con.scroll_region.Bottom < 0) ? \
+ con.b.srWindow.Bottom : \
+ con.b.srWindow.Top + con.scroll_region.Bottom)
 
 const unsigned fhandler_console::MAX_WRITE_CHARS = 16384;
 
@@ -149,16 +151,19 @@ fhandler_console::set_unit ()
shared_unit : FH_ERROR;
   created = false;
 }
-  else if ((!generic_console && (myself->ctty != -1 && !iscons_dev 
(myself->ctty)))
+  else if ((!generic_console &&
+   (myself->ctty != -1 && !iscons_dev (myself->ctty)))
   || !(me = GetConsoleWindow ()))
 devset = FH_ERROR;
   else
 {
   created = true;
-  shared_console_info = open_shared_console (me, cygheap->console_h, 
created);
+  shared_console_info =
+   open_shared_console (me, cygheap->console_h, created);
   ProtectHandleINH (cygheap->console_h);
   if (created)
-   shared_console_info->tty_min_state.setntty (DEV_CONS_MAJOR, 
console_unit (me));
+   shared_console_info->
+ tty_min_state.setntty (DEV_CONS_MAJOR, console_unit (me));
   devset = (fh_devices) shared_console_info->tty_min_state.getntty ();
   if (created)
con.owner = getpid ();
@@ -251,7 +256,8 @@ fhandler_console::set_raw_win32_keyboard_mode (bool 
new_mode)
 {
   bool old_mode = con.raw_win32_keyboard_mode;
   con.raw_win32_keyboard_mode = new_mode;
-  syscall_printf ("raw keyboard mode %sabled", con.raw_win32_keyboard_mode ? 
"en" : "dis");
+  syscall_printf ("raw keyboard mode %sabled",
+ con.raw_win32_keyboard_mode ? "en" : "dis");
   return old_mode;
 };
 
@@ -267,7 +273,7 @@ fhandler_console::set_cursor_maybe ()
 }
 }
 
-void
+bool
 fhandler_console::send_winch_maybe ()
 {
   SHORT y = con.dwWinSize.Y;
@@ -279,7 +285,9 @@ fhandler_console::send_winch_maybe ()
   con.scroll_region.Top = 0;
   con.scroll_region.Bottom = -1;
   get_ttyp ()->kill_pgrp (SIGWINCH);
+  return true;
 }
+  return false;
 }
 
 /* Check whether a mouse event is to be reported as an escape sequence */
@@ -299,7 +307,8 @@ fhandler_console::mouse_aware (MOUSE_EVENT_RECORD& 
mouse_event)
   con.dwMousePosition.X = mouse_event.dwMousePosition.X - now.srWindow.Left;
   con.dwMousePosition.Y = mouse_event.dwMousePosition.Y - now.srWindow.Top;
 
-  return ((mouse_event.dwEventFlags == 0 || mouse_event.dwEventFlags == 
DOUBLE_CLICK)
+  return ((mouse_event.dwEventFlags == 0
+  || mouse_event.dwEventFlags == DOUBLE_CLICK)
  && mouse_event.dwButtonState != con.dwLastButtonState)
 || mouse_event.dwEventFlags == MOUSE_WHEELED
 || (mouse_event.dwEventFlags == MOUSE_MOVED
@@ -312,36 +321,17 @@ fhandler_console::mouse_aware (MOUSE_EVENT_RECORD& 
mouse_event)
 void __reg3
 fhandler_console::read (void *pv, size_t& buflen)
 {
+  termios_printf ("read(%p,%d)", pv, buflen);
+
   push_process_state process_state (PID_TTYIN);
 
-  HANDLE h = get_handle ();
+  int copied_chars = 0;
 
-#define buf ((char *) pv)
+  DWORD timeout = is_nonblocking () ? 0 : INFINITE;
 
-  int ch;
   set_input_state ();
 
-  /* Check console read-ahead buffer filled from terminal requests */
-  if (con.cons_rapoi && *con.cons_rapoi)
-{
-   

[PATCH v3 0/3] Reworks for console code

2019-03-31 Thread Takashi Yano
Hi Corinna,

On Sun, 31 Mar 2019 16:36:51 +0200 Corinna Vinschen rote:
> This hunk is ok, but I wonder if the time hasn't come to simplify the
> original code.  The `static char NO_COPY' only makes marginal sense
> since it's strdup'ed anyway.
> 
> What if we just define two const char's like this
> 
>   const char cygterm[] = "TERM=cygwin";
>   const char xterm[] = "TERM=xterm-256color";
> 
> and then just strdup them conditionally:
> 
>   if (!sawTERM)
> envp[i++] = strdup (wincap.has_con_24bit_colors () ? xterm :
> cygterm);
> 
> What do you think?

> Sorry, didn't notice this before:  Please prepend this block with
> a comment along the lines of "/* Not yet defined in Mingw-w64 */"

Adopted.

> Doesn't this belong into the select patch?

Actually, no. This makes select() recognize Ctrl-space, but
is just tentative. Patch 0002 overwrites this fix.

This is corresponding to:
> @@ -435,7 +451,8 @@ fhandler_console::read (void *pv, size_t& buflen)
> toadd = tmp;
>   }
> /* Allow Ctrl-Space to emit ^@ */
> -   else if (input_rec.Event.KeyEvent.wVirtualKeyCode == VK_SPACE
> +   else if (input_rec.Event.KeyEvent.wVirtualKeyCode
> +== (wincap.has_con_24bit_colors () ? '2' : VK_SPACE)
>  && (ctrl_key_state & CTRL_PRESSED)
>  && !(ctrl_key_state & ALT_PRESSED))
>   toadd = "";

Takashi Yano (3):
  Cygwin: console: support 24 bit color
  Cygwin: console: fix select() behaviour
  Cygwin: console: Make I/O functions thread-safe

 winsup/cygwin/environ.cc  |7 +-
 winsup/cygwin/fhandler.h  |   34 +-
 winsup/cygwin/fhandler_console.cc | 1154 +++--
 winsup/cygwin/select.cc   |   90 +--
 winsup/cygwin/wincap.cc   |   10 +
 winsup/cygwin/wincap.h|2 +
 6 files changed, 840 insertions(+), 457 deletions(-)

-- 
2.17.0



[PATCH v3 3/3] Cygwin: console: Make I/O functions thread-safe

2019-03-31 Thread Takashi Yano
- POSIX states I/O functions shall be thread-safe, however, cygwin
  console I/O functions were not. This patch makes console I/O
  functions thread-safe.
---
 winsup/cygwin/fhandler.h  |  18 +++-
 winsup/cygwin/fhandler_console.cc | 136 +-
 winsup/cygwin/select.cc   |  23 +++--
 3 files changed, 165 insertions(+), 12 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index e4a6de610..bc66377cd 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1698,6 +1698,12 @@ class fhandler_serial: public fhandler_base
   }
 };
 
+#define acquire_input_mutex(ms) \
+  __acquire_input_mutex (__PRETTY_FUNCTION__, __LINE__, ms)
+
+#define release_input_mutex() \
+  __release_input_mutex (__PRETTY_FUNCTION__, __LINE__)
+
 #define acquire_output_mutex(ms) \
   __acquire_output_mutex (__PRETTY_FUNCTION__, __LINE__, ms)
 
@@ -1897,6 +1903,7 @@ private:
   static const unsigned MAX_WRITE_CHARS;
   static console_state *shared_console_info;
   static bool invisible_console;
+  HANDLE input_mutex, output_mutex;
 
   /* Used when we encounter a truncated multi-byte sequence.  The
  lead bytes are stored here and revisited in the next write call. */
@@ -1966,8 +1973,11 @@ private:
   bool focus_aware () {return shared_console_info->con.use_focus;}
   bool get_cons_readahead_valid ()
   {
-return shared_console_info->con.cons_rapoi != NULL &&
+acquire_input_mutex (INFINITE);
+bool ret = shared_console_info->con.cons_rapoi != NULL &&
   *shared_console_info->con.cons_rapoi;
+release_input_mutex ();
+return ret;
   }
 
   select_record *select_read (select_stuff *);
@@ -2002,6 +2012,12 @@ private:
 return fh;
   }
   input_states process_input_message ();
+  void setup_io_mutex (void);
+  DWORD __acquire_input_mutex (const char *fn, int ln, DWORD ms);
+  void __release_input_mutex (const char *fn, int ln);
+  DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
+  void __release_output_mutex (const char *fn, int ln);
+
   friend tty_min * tty_list::get_cttyp ();
 };
 
diff --git a/winsup/cygwin/fhandler_console.cc 
b/winsup/cygwin/fhandler_console.cc
index 160ae284a..6d42ed888 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -232,6 +232,45 @@ tty_list::get_cttyp ()
 return NULL;
 }
 
+void
+fhandler_console::setup_io_mutex (void)
+{
+  char buf[MAX_PATH];
+  DWORD res;
+
+  res = WAIT_FAILED;
+  if (!input_mutex || WAIT_FAILED == (res = acquire_input_mutex (0)))
+{
+  shared_name (buf, "cygcons.input.mutex", get_minor ());
+  input_mutex = OpenMutex (MAXIMUM_ALLOWED, TRUE, buf);
+  if (!input_mutex)
+   input_mutex = CreateMutex (_none, FALSE, buf);
+  if (!input_mutex)
+   {
+ __seterrno ();
+ return;
+   }
+}
+  if (res == WAIT_OBJECT_0)
+release_input_mutex ();
+
+  res = WAIT_FAILED;
+  if (!output_mutex || WAIT_FAILED == (res = acquire_output_mutex (0)))
+{
+  shared_name (buf, "cygcons.output.mutex", get_minor ());
+  output_mutex = OpenMutex (MAXIMUM_ALLOWED, TRUE, buf);
+  if (!output_mutex)
+   output_mutex = CreateMutex (_none, FALSE, buf);
+  if (!output_mutex)
+   {
+ __seterrno ();
+ return;
+   }
+}
+  if (res == WAIT_OBJECT_0)
+release_output_mutex ();
+}
+
 inline DWORD
 dev_console::con_to_str (char *d, int dlen, WCHAR w)
 {
@@ -362,7 +401,9 @@ fhandler_console::read (void *pv, size_t& buflen)
 #define buf ((char *) pv)
 
   int ret;
+  acquire_input_mutex (INFINITE);
   ret = process_input_message ();
+  release_input_mutex ();
   switch (ret)
{
case input_error:
@@ -382,6 +423,7 @@ fhandler_console::read (void *pv, size_t& buflen)
 }
 
   /* Check console read-ahead buffer filled from terminal requests */
+  acquire_input_mutex (INFINITE);
   while (con.cons_rapoi && *con.cons_rapoi && buflen)
 {
   buf[copied_chars++] = *con.cons_rapoi++;
@@ -393,6 +435,7 @@ fhandler_console::read (void *pv, size_t& buflen)
 
   if (!ralen)
 input_ready = false;
+  release_input_mutex ();
 
 #undef buf
 
@@ -903,6 +946,8 @@ fhandler_console::open (int flags, mode_t)
 }
   set_output_handle (h);
 
+  setup_io_mutex ();
+
   if (con.fillin (get_output_handle ()))
 {
   con.current_win32_attr = con.b.wAttributes;
@@ -953,6 +998,11 @@ fhandler_console::close ()
 {
   debug_printf ("closing: %p, %p", get_handle (), get_output_handle ());
 
+  CloseHandle (input_mutex);
+  input_mutex = NULL;
+  CloseHandle (output_mutex);
+  output_mutex = NULL;
+
   if (shared_console_info && getpid () == con.owner &&
   wincap.has_con_24bit_colors ())
 {
@@ -980,6 +1030,7 @@ fhandler_console::ioctl (unsigned int cmd, void *arg)
   int res = fhandler_termios::ioctl (cmd, arg);
   if (res <= 0)
 return res;
+  acquire_output_mutex (INFINITE);
   switch (cmd)
 {
   case TIOCGWINSZ:

Re: [PATCH v2 1/3] Cygwin: console: support 24 bit color

2019-03-31 Thread Corinna Vinschen
On Mar 31 22:47, Takashi Yano wrote:
> - Add 24 bit color support using xterm compatibility mode in
>   Windows 10 1703 or later.
> - Add fake 24 bit color support for legacy console, which uses
>   the nearest color from 16 system colors.
> ---
>  winsup/cygwin/environ.cc  |   7 +-
>  winsup/cygwin/fhandler.h  |   4 +
>  winsup/cygwin/fhandler_console.cc | 229 +-
>  winsup/cygwin/select.cc   |   8 ++
>  winsup/cygwin/wincap.cc   |  10 ++
>  winsup/cygwin/wincap.h|   2 +
>  6 files changed, 227 insertions(+), 33 deletions(-)
> 
> diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
> index 21f13734c..c27d10fe1 100644
> --- a/winsup/cygwin/environ.cc
> +++ b/winsup/cygwin/environ.cc
> @@ -869,10 +869,15 @@ win32env_to_cygenv (PWCHAR rawenv, bool posify)
>char *newp;
>int i;
>int sawTERM = 0;
> -  static char NO_COPY cygterm[] = "TERM=cygwin";
> +  static char NO_COPY cygterm[] = "TERM=xterm-256color";
>char *tmpbuf = tp.t_get ();
>PWCHAR w;
>  
> +  /* If console has 24 bit color capability, TERM=xterm-256color,
> + otherwise, TERM=cygwin */
> +  if (!wincap.has_con_24bit_colors ())
> +strncpy (cygterm, "TERM=cygwin", sizeof (cygterm));
> +

This hunk is ok, but I wonder if the time hasn't come to simplify the
original code.  The `static char NO_COPY' only makes marginal sense
since it's strdup'ed anyway.

What if we just define two const char's like this

  const char cygterm[] = "TERM=cygwin";
  const char xterm[] = "TERM=xterm-256color";

and then just strdup them conditionally:

  if (!sawTERM)
envp[i++] = strdup (wincap.has_con_24bit_colors () ? xterm : cygterm);

What do you think?

> +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
> +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
> +#endif /* ENABLE_VIRTUAL_TERMINAL_PROCESSING */
> +#ifndef DISABLE_NEWLINE_AUTO_RETURN
> +#define DISABLE_NEWLINE_AUTO_RETURN 0x0008
> +#endif /* DISABLE_NEWLINE_AUTO_RETURN */
> +#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
> +#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
> +#endif /* ENABLE_VIRTUAL_TERMINAL_INPUT */

Sorry, didn't notice this before:  Please prepend this block with
a comment along the lines of "/* Not yet defined in Mingw-w64 */"

> diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
> index 9b18e8f80..28adcf3e7 100644
> --- a/winsup/cygwin/select.cc
> +++ b/winsup/cygwin/select.cc
> @@ -1053,6 +1053,14 @@ peek_console (select_record *me, bool)
> else if (irec.Event.KeyEvent.uChar.UnicodeChar
>  || fhandler_console::get_nonascii_key (irec, tmpbuf))
>   return me->read_ready = true;
> +   /* Allow Ctrl-Space for ^@ */
> +   else if ( (irec.Event.KeyEvent.wVirtualKeyCode == VK_SPACE
> +  || irec.Event.KeyEvent.wVirtualKeyCode == '2')
> +&& (irec.Event.KeyEvent.dwControlKeyState &
> +(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
> +&& !(irec.Event.KeyEvent.dwControlKeyState
> + & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) )
> + return me->read_ready = true;
>   }
> /* Ignore key up events, except for Alt+Numpad events. */
> else if (is_alt_numpad_event ())

Doesn't this belong into the select patch?


Thanks,
Corinna

-- 
Corinna Vinschen
Cygwin Maintainer


signature.asc
Description: PGP signature


Re: [PATCH v2 0/3] Reworks for console code

2019-03-31 Thread Corinna Vinschen
Hi Takashi,

On Mar 31 22:47, Takashi Yano wrote:
> Hi Corinna,
> 
> I have revised the patches according to your advice.
> Could you please have a look?

Thanks for sending this in git `send-email' style :)))

I have a few comments on patch 1 only.  Please see there.


Thanks,
Corinna

-- 
Corinna Vinschen
Cygwin Maintainer


signature.asc
Description: PGP signature


[PATCH v2 2/3] Cygwin: console: fix select() behaviour

2019-03-31 Thread Takashi Yano
- Previously, select() would return when only one key is typed even
  in canonical mode. With this patch, it returns after one line is
  completed.
---
 winsup/cygwin/fhandler.h  |  12 +-
 winsup/cygwin/fhandler_console.cc | 794 --
 winsup/cygwin/select.cc   |  81 +--
 3 files changed, 462 insertions(+), 425 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 66e724bcb..e4a6de610 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1884,6 +1884,15 @@ public:
 tty_min tty_min_state;
 dev_console con;
   };
+  bool input_ready;
+  enum input_states
+  {
+input_error = -1,
+input_processing = 0,
+input_ok = 1,
+input_signalled = 2,
+input_winch = 3
+  };
 private:
   static const unsigned MAX_WRITE_CHARS;
   static console_state *shared_console_info;
@@ -1969,7 +1978,7 @@ private:
   void fixup_after_fork (HANDLE) {fixup_after_fork_exec (false);}
   void set_close_on_exec (bool val);
   void set_input_state ();
-  void send_winch_maybe ();
+  bool send_winch_maybe ();
   void setup ();
   bool set_unit ();
   static bool need_invisible ();
@@ -1992,6 +2001,7 @@ private:
 copyto (fh);
 return fh;
   }
+  input_states process_input_message ();
   friend tty_min * tty_list::get_cttyp ();
 };
 
diff --git a/winsup/cygwin/fhandler_console.cc 
b/winsup/cygwin/fhandler_console.cc
index 7fed912c7..788bc5cf4 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -52,7 +52,9 @@ details. */
 
 #define con (shared_console_info->con)
 #define srTop (con.b.srWindow.Top + con.scroll_region.Top)
-#define srBottom ((con.scroll_region.Bottom < 0) ? con.b.srWindow.Bottom : 
con.b.srWindow.Top + con.scroll_region.Bottom)
+#define srBottom ((con.scroll_region.Bottom < 0) ? \
+ con.b.srWindow.Bottom : \
+ con.b.srWindow.Top + con.scroll_region.Bottom)
 
 const unsigned fhandler_console::MAX_WRITE_CHARS = 16384;
 
@@ -148,16 +150,19 @@ fhandler_console::set_unit ()
shared_unit : FH_ERROR;
   created = false;
 }
-  else if ((!generic_console && (myself->ctty != -1 && !iscons_dev 
(myself->ctty)))
+  else if ((!generic_console &&
+   (myself->ctty != -1 && !iscons_dev (myself->ctty)))
   || !(me = GetConsoleWindow ()))
 devset = FH_ERROR;
   else
 {
   created = true;
-  shared_console_info = open_shared_console (me, cygheap->console_h, 
created);
+  shared_console_info =
+   open_shared_console (me, cygheap->console_h, created);
   ProtectHandleINH (cygheap->console_h);
   if (created)
-   shared_console_info->tty_min_state.setntty (DEV_CONS_MAJOR, 
console_unit (me));
+   shared_console_info->
+ tty_min_state.setntty (DEV_CONS_MAJOR, console_unit (me));
   devset = (fh_devices) shared_console_info->tty_min_state.getntty ();
   if (created)
con.owner = getpid ();
@@ -250,7 +255,8 @@ fhandler_console::set_raw_win32_keyboard_mode (bool 
new_mode)
 {
   bool old_mode = con.raw_win32_keyboard_mode;
   con.raw_win32_keyboard_mode = new_mode;
-  syscall_printf ("raw keyboard mode %sabled", con.raw_win32_keyboard_mode ? 
"en" : "dis");
+  syscall_printf ("raw keyboard mode %sabled",
+ con.raw_win32_keyboard_mode ? "en" : "dis");
   return old_mode;
 };
 
@@ -266,7 +272,7 @@ fhandler_console::set_cursor_maybe ()
 }
 }
 
-void
+bool
 fhandler_console::send_winch_maybe ()
 {
   SHORT y = con.dwWinSize.Y;
@@ -278,7 +284,9 @@ fhandler_console::send_winch_maybe ()
   con.scroll_region.Top = 0;
   con.scroll_region.Bottom = -1;
   get_ttyp ()->kill_pgrp (SIGWINCH);
+  return true;
 }
+  return false;
 }
 
 /* Check whether a mouse event is to be reported as an escape sequence */
@@ -298,7 +306,8 @@ fhandler_console::mouse_aware (MOUSE_EVENT_RECORD& 
mouse_event)
   con.dwMousePosition.X = mouse_event.dwMousePosition.X - now.srWindow.Left;
   con.dwMousePosition.Y = mouse_event.dwMousePosition.Y - now.srWindow.Top;
 
-  return ((mouse_event.dwEventFlags == 0 || mouse_event.dwEventFlags == 
DOUBLE_CLICK)
+  return ((mouse_event.dwEventFlags == 0
+  || mouse_event.dwEventFlags == DOUBLE_CLICK)
  && mouse_event.dwButtonState != con.dwLastButtonState)
 || mouse_event.dwEventFlags == MOUSE_WHEELED
 || (mouse_event.dwEventFlags == MOUSE_MOVED
@@ -311,36 +320,17 @@ fhandler_console::mouse_aware (MOUSE_EVENT_RECORD& 
mouse_event)
 void __reg3
 fhandler_console::read (void *pv, size_t& buflen)
 {
+  termios_printf ("read(%p,%d)", pv, buflen);
+
   push_process_state process_state (PID_TTYIN);
 
-  HANDLE h = get_handle ();
+  int copied_chars = 0;
 
-#define buf ((char *) pv)
+  DWORD timeout = is_nonblocking () ? 0 : INFINITE;
 
-  int ch;
   set_input_state ();
 
-  /* Check console read-ahead buffer filled from terminal requests */
-  if (con.cons_rapoi && *con.cons_rapoi)
-{
-   

[PATCH v2 0/3] Reworks for console code

2019-03-31 Thread Takashi Yano
Hi Corinna,

I have revised the patches according to your advice.
Could you please have a look?

Takashi Yano (3):
  Cygwin: console: support 24 bit color
  Cygwin: console: fix select() behaviour
  Cygwin: console: Make I/O functions thread-safe

 winsup/cygwin/environ.cc  |7 +-
 winsup/cygwin/fhandler.h  |   34 +-
 winsup/cygwin/fhandler_console.cc | 1153 +++--
 winsup/cygwin/select.cc   |   90 +--
 winsup/cygwin/wincap.cc   |   10 +
 winsup/cygwin/wincap.h|2 +
 6 files changed, 840 insertions(+), 456 deletions(-)

-- 
2.17.0



[PATCH v2 1/3] Cygwin: console: support 24 bit color

2019-03-31 Thread Takashi Yano
- Add 24 bit color support using xterm compatibility mode in
  Windows 10 1703 or later.
- Add fake 24 bit color support for legacy console, which uses
  the nearest color from 16 system colors.
---
 winsup/cygwin/environ.cc  |   7 +-
 winsup/cygwin/fhandler.h  |   4 +
 winsup/cygwin/fhandler_console.cc | 229 +-
 winsup/cygwin/select.cc   |   8 ++
 winsup/cygwin/wincap.cc   |  10 ++
 winsup/cygwin/wincap.h|   2 +
 6 files changed, 227 insertions(+), 33 deletions(-)

diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 21f13734c..c27d10fe1 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -869,10 +869,15 @@ win32env_to_cygenv (PWCHAR rawenv, bool posify)
   char *newp;
   int i;
   int sawTERM = 0;
-  static char NO_COPY cygterm[] = "TERM=cygwin";
+  static char NO_COPY cygterm[] = "TERM=xterm-256color";
   char *tmpbuf = tp.t_get ();
   PWCHAR w;
 
+  /* If console has 24 bit color capability, TERM=xterm-256color,
+ otherwise, TERM=cygwin */
+  if (!wincap.has_con_24bit_colors ())
+strncpy (cygterm, "TERM=cygwin", sizeof (cygterm));
+
   /* Allocate space for environment + trailing NULL + CYGWIN env. */
   envp = (char **) malloc ((4 + (envc = 100)) * sizeof (char *));
 
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index b336eb63a..66e724bcb 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1778,6 +1778,8 @@ enum ansi_intensity
 #define eattitle 7
 #define gotparen 8
 #define gotrparen 9
+#define eatpalette 10
+#define endpalette 11
 #define MAXARGS 10
 
 enum cltype
@@ -1791,6 +1793,8 @@ enum cltype
 
 class dev_console
 {
+  pid_t owner;
+
   WORD default_color, underline_color, dim_color;
 
   /* Used to determine if an input keystroke should be modified with META. */
diff --git a/winsup/cygwin/fhandler_console.cc 
b/winsup/cygwin/fhandler_console.cc
index 281c2005c..7fed912c7 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -15,6 +15,7 @@ details. */
 #include 
 #include 
 #include 
+#include 
 #include "cygerrno.h"
 #include "security.h"
 #include "path.h"
@@ -32,6 +33,16 @@ details. */
 #include "child_info.h"
 #include "cygwait.h"
 
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif /* ENABLE_VIRTUAL_TERMINAL_PROCESSING */
+#ifndef DISABLE_NEWLINE_AUTO_RETURN
+#define DISABLE_NEWLINE_AUTO_RETURN 0x0008
+#endif /* DISABLE_NEWLINE_AUTO_RETURN */
+#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
+#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
+#endif /* ENABLE_VIRTUAL_TERMINAL_INPUT */
+
 /* Don't make this bigger than NT_MAX_PATH as long as the temporary buffer
is allocated using tmp_pathbuf!!! */
 #define CONVERT_LIMIT NT_MAX_PATH
@@ -148,7 +159,11 @@ fhandler_console::set_unit ()
   if (created)
shared_console_info->tty_min_state.setntty (DEV_CONS_MAJOR, 
console_unit (me));
   devset = (fh_devices) shared_console_info->tty_min_state.getntty ();
+  if (created)
+   con.owner = getpid ();
 }
+  if (!created && shared_console_info && kill (con.owner, 0) == -1)
+con.owner = getpid ();
 
   dev ().parse (devset);
   if (devset != FH_ERROR)
@@ -167,33 +182,33 @@ void
 fhandler_console::setup ()
 {
   if (set_unit ())
-  {
-   con.scroll_region.Bottom = -1;
-   con.dwLastCursorPosition.X = -1;
-   con.dwLastCursorPosition.Y = -1;
-   con.dwLastMousePosition.X = -1;
-   con.dwLastMousePosition.Y = -1;
-   con.dwLastButtonState = 0;  /* none pressed */
-   con.last_button_code = 3;   /* released */
-   con.underline_color = FOREGROUND_GREEN | FOREGROUND_BLUE;
-   con.dim_color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
-   con.meta_mask = LEFT_ALT_PRESSED;
-   /* Set the mask that determines if an input keystroke is modified by
-  META.  We set this based on the keyboard layout language loaded
-  for the current thread.  The left  key always generates
-  META, but the right  key only generates META if we are using
-  an English keyboard because many "international" keyboards
-  replace common shell symbols ('[', '{', etc.) with accented
-  language-specific characters (umlaut, accent grave, etc.).  On
-  these keyboards right  (called AltGr) is used to produce the
-  shell symbols and should not be interpreted as META. */
-   if (PRIMARYLANGID (LOWORD (GetKeyboardLayout (0))) == LANG_ENGLISH)
- con.meta_mask |= RIGHT_ALT_PRESSED;
-   con.set_default_attr ();
-   con.backspace_keycode = CERASE;
-   con.cons_rapoi = NULL;
-   shared_console_info->tty_min_state.is_console = true;
-  }
+{
+  con.scroll_region.Bottom = -1;
+  con.dwLastCursorPosition.X = -1;
+  con.dwLastCursorPosition.Y = -1;
+  con.dwLastMousePosition.X = -1;
+  

[PATCH v2 3/3] Cygwin: console: Make I/O functions thread-safe

2019-03-31 Thread Takashi Yano
- POSIX states I/O functions shall be thread-safe, however, cygwin
  console I/O functions were not. This patch makes console I/O
  functions thread-safe.
---
 winsup/cygwin/fhandler.h  |  18 +++-
 winsup/cygwin/fhandler_console.cc | 136 +-
 winsup/cygwin/select.cc   |  23 +++--
 3 files changed, 165 insertions(+), 12 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index e4a6de610..bc66377cd 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1698,6 +1698,12 @@ class fhandler_serial: public fhandler_base
   }
 };
 
+#define acquire_input_mutex(ms) \
+  __acquire_input_mutex (__PRETTY_FUNCTION__, __LINE__, ms)
+
+#define release_input_mutex() \
+  __release_input_mutex (__PRETTY_FUNCTION__, __LINE__)
+
 #define acquire_output_mutex(ms) \
   __acquire_output_mutex (__PRETTY_FUNCTION__, __LINE__, ms)
 
@@ -1897,6 +1903,7 @@ private:
   static const unsigned MAX_WRITE_CHARS;
   static console_state *shared_console_info;
   static bool invisible_console;
+  HANDLE input_mutex, output_mutex;
 
   /* Used when we encounter a truncated multi-byte sequence.  The
  lead bytes are stored here and revisited in the next write call. */
@@ -1966,8 +1973,11 @@ private:
   bool focus_aware () {return shared_console_info->con.use_focus;}
   bool get_cons_readahead_valid ()
   {
-return shared_console_info->con.cons_rapoi != NULL &&
+acquire_input_mutex (INFINITE);
+bool ret = shared_console_info->con.cons_rapoi != NULL &&
   *shared_console_info->con.cons_rapoi;
+release_input_mutex ();
+return ret;
   }
 
   select_record *select_read (select_stuff *);
@@ -2002,6 +2012,12 @@ private:
 return fh;
   }
   input_states process_input_message ();
+  void setup_io_mutex (void);
+  DWORD __acquire_input_mutex (const char *fn, int ln, DWORD ms);
+  void __release_input_mutex (const char *fn, int ln);
+  DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
+  void __release_output_mutex (const char *fn, int ln);
+
   friend tty_min * tty_list::get_cttyp ();
 };
 
diff --git a/winsup/cygwin/fhandler_console.cc 
b/winsup/cygwin/fhandler_console.cc
index 788bc5cf4..04e59a474 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -231,6 +231,45 @@ tty_list::get_cttyp ()
 return NULL;
 }
 
+void
+fhandler_console::setup_io_mutex (void)
+{
+  char buf[MAX_PATH];
+  DWORD res;
+
+  res = WAIT_FAILED;
+  if (!input_mutex || WAIT_FAILED == (res = acquire_input_mutex (0)))
+{
+  shared_name (buf, "cygcons.input.mutex", get_minor ());
+  input_mutex = OpenMutex (MAXIMUM_ALLOWED, TRUE, buf);
+  if (!input_mutex)
+   input_mutex = CreateMutex (_none, FALSE, buf);
+  if (!input_mutex)
+   {
+ __seterrno ();
+ return;
+   }
+}
+  if (res == WAIT_OBJECT_0)
+release_input_mutex ();
+
+  res = WAIT_FAILED;
+  if (!output_mutex || WAIT_FAILED == (res = acquire_output_mutex (0)))
+{
+  shared_name (buf, "cygcons.output.mutex", get_minor ());
+  output_mutex = OpenMutex (MAXIMUM_ALLOWED, TRUE, buf);
+  if (!output_mutex)
+   output_mutex = CreateMutex (_none, FALSE, buf);
+  if (!output_mutex)
+   {
+ __seterrno ();
+ return;
+   }
+}
+  if (res == WAIT_OBJECT_0)
+release_output_mutex ();
+}
+
 inline DWORD
 dev_console::con_to_str (char *d, int dlen, WCHAR w)
 {
@@ -361,7 +400,9 @@ fhandler_console::read (void *pv, size_t& buflen)
 #define buf ((char *) pv)
 
   int ret;
+  acquire_input_mutex (INFINITE);
   ret = process_input_message ();
+  release_input_mutex ();
   switch (ret)
{
case input_error:
@@ -381,6 +422,7 @@ fhandler_console::read (void *pv, size_t& buflen)
 }
 
   /* Check console read-ahead buffer filled from terminal requests */
+  acquire_input_mutex (INFINITE);
   while (con.cons_rapoi && *con.cons_rapoi && buflen)
 {
   buf[copied_chars++] = *con.cons_rapoi++;
@@ -392,6 +434,7 @@ fhandler_console::read (void *pv, size_t& buflen)
 
   if (!ralen)
 input_ready = false;
+  release_input_mutex ();
 
 #undef buf
 
@@ -902,6 +945,8 @@ fhandler_console::open (int flags, mode_t)
 }
   set_output_handle (h);
 
+  setup_io_mutex ();
+
   if (con.fillin (get_output_handle ()))
 {
   con.current_win32_attr = con.b.wAttributes;
@@ -952,6 +997,11 @@ fhandler_console::close ()
 {
   debug_printf ("closing: %p, %p", get_handle (), get_output_handle ());
 
+  CloseHandle (input_mutex);
+  input_mutex = NULL;
+  CloseHandle (output_mutex);
+  output_mutex = NULL;
+
   if (shared_console_info && getpid () == con.owner &&
   wincap.has_con_24bit_colors ())
 {
@@ -979,6 +1029,7 @@ fhandler_console::ioctl (unsigned int cmd, void *arg)
   int res = fhandler_termios::ioctl (cmd, arg);
   if (res <= 0)
 return res;
+  acquire_output_mutex (INFINITE);
   switch (cmd)
 {
   case TIOCGWINSZ:

Re: [PATCH] Reworks for console code

2019-03-31 Thread Corinna Vinschen
Hi Takashi,

On Mar 31 15:20, Takashi Yano wrote:
> Hi,
> 
> I would like to propose 3 patches attached to improve console code.

Not a hard requirement, but it would be nice if you could send your
patches as patchset with cover letter via `git send-email' from the
git-email package or in the same style.  See, e. g.
https://sourceware.org/ml/cygwin-patches/2019-q1/msg00036.html

This really simplifies review, discussion and applying patches.
With attached patches, replying to a patch does not quote the patch
so inline commenting is pretty tricky.  Thanks for considering.

Having said that, this is a snippet from patch 1:

+  /* Check if 24bit color is available */
+  DWORD dwVersion = GetVersion ();
+  dwVersion = (LOBYTE (LOWORD (dwVersion)) << 24)
+   | (HIBYTE (LOWORD (dwVersion)) << 16) | HIWORD (dwVersion);
+  if (dwVersion >= ((10 << 24) | (0 << 16) | 14931))
+   {
+ con.cap24bit_color = true;

OS features or bug tests should be performed via wincap, see wincap.cc
and wincap.h.  We do not care for Windows test release, so this should
be enabled for W10 1703 and later.  Just add an "has_con_24bit_colors"(*)
flag to the wincaps struct and set it to false on older Windows
versions, true otherwise.  So the above code snippet can go away and
in subsequent code just check for wincap.has_con_24bit_colors ().

(*) exact name of the flag is your choice

+ /* If system has 24bit color capability,
+use xterm compatible mode. */
+ setenv ("TERM", "xterm-256color", 1);

Having the 24bit color capability check in wincap also means, setting
TERM could be moved into environ.cc, function win32env_to_cygenv()
where we already set TERM=cygwin.  This could then be done conditionally
based on the wincap.has_con_24bit_colors check.


Patch 2:  Looks good, just a question:

+ if (mouse_event.dwEventFlags == MOUSE_MOVED)
+   {
+ b = con.last_button_code;
+   }
+ else if (mouse_event.dwButtonState < con.dwLastButtonState && 
!con.ext_mouse_mode6)
+   {
+ b = 3;
+ strcpy (sz, "btn up");
+   }
+ else if ((mouse_event.dwButtonState & 1) != 
(con.dwLastButtonState & 1))
+   {
+ b = 0;
+ strcpy (sz, "btn1 down");
+   }
+ else if ((mouse_event.dwButtonState & 2) != 
(con.dwLastButtonState & 2))
+   {
+ b = 2;
+ strcpy (sz, "btn2 down");
+   }
+ else if ((mouse_event.dwButtonState & 4) != 
(con.dwLastButtonState & 4))
+   {
+ b = 1;
+ strcpy (sz, "btn3 down");
+   }
+

This is not your code but while you're at it, would you mind to reformat
to 80 chars line length max?  Thanks!

Patch 3:  Looks good.


Thanks,
Corinna

-- 
Corinna Vinschen
Cygwin Maintainer


signature.asc
Description: PGP signature


[PATCH] Reworks for console code

2019-03-31 Thread Takashi Yano
Hi,

I would like to propose 3 patches attached to improve console code.

Patch 0001:
This revises console code for better color handling. This provides
24 bit color support for Windows 10 build 14931 or later. For legacy
console, fake 24 bit color support is implemented, which use the
nearest color from 16 system colors.

To check the color handling, use:
https://gist.github.com/hSATAC/1095100

Results are at:
http://tyan0.dip.jp/cgi-bin/FSWiki/wiki.cgi?page=24+bit+color+support+for+cygwin+console

Patch 0002:
Previously, select() would return by typing only one key even in
canonical mode. With this patch, it returns after one line is
completed.

To check this behaviour, use attached STC (confirm-select.c) and
type something and [Enter]. Type ^D to exit from the STC.

Expected result:
This is one line.
select() returns 1
read() returns 18
54, 68, 69, 73, 20, 69, 73, 20, 6f, 6e, 65, 20, 6c, 69, 6e, 65, 2e, 0a,
select() returns 1
read() returns 0

Cygwin current version:
select() returns 1
This is one line.
read() returns 18
54, 68, 69, 73, 20, 69, 73, 20, 6f, 6e, 65, 20, 6c, 69, 6e, 65, 2e, 0a,
select() returns 1
read() returns 0

Patch 0003:
POSIX states I/O functions shall be thread-safe, however, cygwin
console I/O functions were not. This patch makes console I/O
functions thread-safe.

To check this, use attached STC (confirm-thread-safe.c).
Expected resut is red 'A's at the first 12 lines and green 'B's
at the second 12 lines. However, the result is completely broken
in current cygwin.

-- 
Takashi Yano 


0001-Cygwin-console-support-24-bit-color.patch
Description: Binary data


0002-Cygwin-console-fix-select-behaviour.patch
Description: Binary data


0003-Cygwin-console-Make-I-O-functions-thread-safe.patch
Description: Binary data
#include 
#include 
#include 
#include 
#include 

int main()
{
	fd_set fds;
	int ret;

	while (1) {
		FD_ZERO();
		FD_SET(0, );
		errno = 0;
		ret = select(1, , NULL, NULL, NULL);
		printf("select() returns %d\n", ret);
		if (FD_ISSET(0, )) {
			char buf[1024];
			size_t n = read(0, buf, sizeof(buf));
			printf("read() returns %d\n", n);
			if (n <= 0) break;
			size_t i;
			for (i=0; i#include 
#include 
#include 
#include 

void *write_thread(void *arg)
{
	int n = (int)arg;
	const int rows = 12;
	const int cols = 79;
	char buf[64];
	for (int i=0; i<1; i++) {
		for (int r=1; r<=rows; r++) {
			for (int c=1; c<=cols; c++) {
sprintf(buf, "\033[%d;%dH\033[%dm%c", r + n*rows, c, 31+n, 'A'+n);
write(1, buf, strlen(buf));
			}
		}
	}
}

int main()
{
	pthread_t th1, th2;

	printf("\033[H\033[J");
	fflush(stdout);
	if (pthread_create(, NULL, write_thread, (void*)0)) {
		perror ("1: pthred_create");
		return -1;
	}
	if (pthread_create(, NULL, write_thread, (void*)1)) {
		perror ("2: pthred_create");
		return -1;
	}
	pthread_join(th1, NULL);
	pthread_join(th2, NULL);
	usleep(300);
	printf("\033[H\033[J\033[m");
	fflush(stdout);
	return 0;
}