@@ -289,7 +289,18 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
289289  const  int  additional_space = 128 ; /*  Possible max number of incoming events
290290				       during the process. Additional space 
291291				       should be left for writeback fix. */  
292-   const  int  inrec_size = INREC_SIZE + additional_space;
292+   DWORD inrec_size = INREC_SIZE + additional_space;
293+   INPUT_RECORD *input_rec =
294+     (INPUT_RECORD *) malloc  (inrec_size * sizeof  (INPUT_RECORD));
295+   INPUT_RECORD *input_tmp =
296+     (INPUT_RECORD *) malloc  (inrec_size * sizeof  (INPUT_RECORD));
297+ 
298+   if  (!input_rec || !input_tmp)
299+     return ; /*  Cannot continue */ 
300+ 
301+   DWORD inrec_size1 =
302+     wincap.cons_need_small_input_record_buf  () ? INREC_SIZE : inrec_size;
303+ 
293304  struct  m 
294305  {
295306    inline  static  size_t  bytes  (size_t  n)
@@ -301,33 +312,62 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
301312  while  (con.owner  == myself->pid )
302313    {
303314      DWORD total_read, n, i;
304-       INPUT_RECORD input_rec[inrec_size];
305315
306316      if  (con.disable_master_thread )
307317	{
308318	  cygwait  (40 );
309319	  continue ;
310320	}
311321
322+       acquire_attach_mutex  (mutex_timeout);
323+       GetNumberOfConsoleInputEvents  (p->input_handle , &total_read);
324+       release_attach_mutex  ();
325+       if  (total_read > INREC_SIZE)
326+ 	{
327+ 	  cygwait  (40 );
328+ 	  acquire_attach_mutex  (mutex_timeout);
329+ 	  GetNumberOfConsoleInputEvents  (p->input_handle , &n);
330+ 	  release_attach_mutex  ();
331+ 	  if  (n < total_read)
332+ 	    {
333+ 	      /*  read() seems to be called. Process special keys
334+ 		 in process_input_message (). */  
335+ 	      con.master_thread_suspended  = true ;
336+ 	      continue ;
337+ 	    }
338+ 	  total_read = n;
339+ 	}
340+       con.master_thread_suspended  = false ;
341+       if  (total_read + additional_space > inrec_size)
342+ 	{
343+ 	  DWORD new_inrec_size = total_read + additional_space;
344+ 	  INPUT_RECORD *new_input_rec = (INPUT_RECORD *)
345+ 	    realloc  (input_rec, new_inrec_size * sizeof  (INPUT_RECORD));
346+ 	  INPUT_RECORD *new_input_tmp = (INPUT_RECORD *)
347+ 	    realloc  (input_tmp, new_inrec_size * sizeof  (INPUT_RECORD));
348+ 	  if  (new_input_rec && new_input_tmp)
349+ 	    {
350+ 	      inrec_size = new_inrec_size;
351+ 	      input_rec = new_input_rec;
352+ 	      input_tmp = new_input_tmp;
353+ 	      if  (!wincap.cons_need_small_input_record_buf  ())
354+ 		inrec_size1 = inrec_size;
355+ 	    }
356+ 	}
357+ 
312358      WaitForSingleObject  (p->input_mutex , mutex_timeout);
313359      total_read = 0 ;
314-       bool  nowait = false ;
315360      switch  (cygwait  (p->input_handle , (DWORD) 0 ))
316361	{
317362	case  WAIT_OBJECT_0:
318- 	  acquire_attach_mutex  (mutex_timeout);
319- 	  ReadConsoleInputW  (p->input_handle ,
320- 			     input_rec, INREC_SIZE, &total_read);
321- 	  if  (total_read == INREC_SIZE /*  Working space full */ 
322- 	      && cygwait  (p->input_handle , (DWORD) 0 ) == WAIT_OBJECT_0)
363+ 	  total_read = 0 ;
364+ 	  while  (cygwait  (p->input_handle , (DWORD) 0 ) == WAIT_OBJECT_0)
323365	    {
324- 	      const  int  incr = min  (con.num_processed , additional_space);
325- 	      ReadConsoleInputW  (p->input_handle ,
326- 				 input_rec + total_read, incr, &n);
327- 	      /*  Discard oldest n events. */ 
328- 	      memmove  (input_rec, input_rec + n, m::bytes  (total_read));
329- 	      con.num_processed  -= n;
330- 	      nowait = true ;
366+ 	      DWORD len;
367+ 	      ReadConsoleInputW  (p->input_handle , input_rec + total_read,
368+ 				 min  (inrec_size - total_read, inrec_size1),
369+ 				 &len);
370+ 	      total_read += len;
331371	    }
332372	  release_attach_mutex  ();
333373	  break ;
@@ -416,33 +456,56 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
416456	{
417457	  do 
418458	    {
419- 	      INPUT_RECORD tmp[inrec_size];
420459	      /*  Writeback input records other than interrupt. */ 
421460	      acquire_attach_mutex  (mutex_timeout);
422- 	      WriteConsoleInputW  (p->input_handle , input_rec, total_read, &n);
461+ 	      n = 0 ;
462+ 	      while  (n < total_read)
463+ 		{
464+ 		  DWORD len;
465+ 		  WriteConsoleInputW  (p->input_handle , input_rec + n,
466+ 				      min  (total_read - n, inrec_size1), &len);
467+ 		  n += len;
468+ 		}
423469	      /*  Check if writeback was successfull. */ 
424- 	      PeekConsoleInputW  (p->input_handle , tmp, inrec_size , &n);
470+ 	      PeekConsoleInputW  (p->input_handle , input_tmp, inrec_size1 , &n);
425471	      release_attach_mutex  ();
426- 	      if  (n < total_read)
472+ 	      if  (n < min  ( total_read, inrec_size1) )
427473		break ; /*  Someone has read input without acquiring
428474			  input_mutex. ConEmu cygwin-connector? */  
429- 	      if  (inrec_eq  (input_rec, tmp, total_read))
475+ 	      if  (inrec_eq  (input_rec, input_tmp,
476+ 			    min  (total_read, inrec_size1)))
430477		break ; /*  OK */ 
431478	      /*  Try to fix */ 
432479	      acquire_attach_mutex  (mutex_timeout);
433- 	      ReadConsoleInputW  (p->input_handle , tmp, inrec_size, &n);
480+ 	      n = 0 ;
481+ 	      while  (cygwait  (p->input_handle , (DWORD) 0 ) == WAIT_OBJECT_0)
482+ 		{
483+ 		  DWORD len;
484+ 		  ReadConsoleInputW  (p->input_handle , input_tmp + n,
485+ 				     min  (inrec_size - n, inrec_size1), &len);
486+ 		  n += len;
487+ 		}
434488	      release_attach_mutex  ();
435489	      for  (DWORD i = 0 , j = 0 ; j < n; j++)
436- 		if  (i == total_read || !inrec_eq  (input_rec + i, tmp + j, 1 ))
490+ 		if  (i == total_read
491+ 		    || !inrec_eq  (input_rec + i, input_tmp + j, 1 ))
437492		  {
438493		    if  (total_read + j - i >= n)
439494		      { /*  Something is wrong. Giving up. */ 
440495			acquire_attach_mutex  (mutex_timeout);
441- 			WriteConsoleInputW  (p->input_handle , tmp, n, &n);
496+ 			WriteConsoleInputW  (p->input_handle , input_tmp, n, &n);
497+ 			n = 0 ;
498+ 			while  (n < total_read)
499+ 			  {
500+ 			    DWORD len;
501+ 			    WriteConsoleInputW  (p->input_handle , input_rec + n,
502+ 				      min  (total_read - n, inrec_size1), &len);
503+ 			    n += len;
504+ 			  }
442505			release_attach_mutex  ();
443506			goto  skip_writeback;
444507		      }
445- 		    input_rec[total_read + j - i] = tmp [j];
508+ 		    input_rec[total_read + j - i] = input_tmp [j];
446509		  }
447510		else 
448511		  i++;
@@ -452,9 +515,10 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
452515	}
453516skip_writeback:
454517      ReleaseMutex  (p->input_mutex );
455-       if  (!nowait)
456- 	cygwait  (40 );
518+       cygwait  (40 );
457519    }
520+   free  (input_rec);
521+   free  (input_tmp);
458522}
459523
460524bool 
@@ -549,6 +613,7 @@ fhandler_console::setup ()
549613      shared_console_info->tty_min_state .is_console  = true ;
550614      con.cursor_key_app_mode  = false ;
551615      con.disable_master_thread  = true ;
616+       con.master_thread_suspended  = false ;
552617      con.num_processed  = 0 ;
553618    }
554619}
@@ -602,6 +667,8 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t,
602667      break ;
603668    case  tty::cygwin:
604669      flags |= ENABLE_WINDOW_INPUT;
670+       if  (con.master_thread_suspended )
671+ 	flags |= ENABLE_PROCESSED_INPUT;
605672      if  (wincap.has_con_24bit_colors  () && !con_is_legacy)
606673	flags |= ENABLE_VIRTUAL_TERMINAL_INPUT;
607674      else 
@@ -4173,5 +4240,5 @@ fhandler_console::close_handle_set (handle_set_t *p)
41734240bool 
41744241fhandler_console::need_console_handler  ()
41754242{
4176-   return  con.disable_master_thread ;
4243+   return  con.disable_master_thread  || con. master_thread_suspended ;
41774244}
0 commit comments