@@ -222,8 +222,8 @@ const key_code_name_t key_name_conv_tab[] = {
222222
223223#define MC_USEC_PER_MSEC 1000
224224
225- /* The maximum sequence length (32 + null terminator) */
226- #define SEQ_BUFFER_LEN 33
225+ /* The buffer can handle multiple sequences */
226+ #define SEQ_BUFFER_LEN 100
227227
228228/*** file scope type declarations ****************************************************************/
229229
@@ -555,6 +555,7 @@ static GSList *select_list = NULL;
555555static int seq_buffer [SEQ_BUFFER_LEN ];
556556static int * seq_append = NULL ;
557557
558+ static int seq_buffer_temp [SEQ_BUFFER_LEN ];
558559static char seq_char_buffer [SEQ_BUFFER_LEN ];
559560
560561static int * pending_keys = NULL ;
@@ -1727,6 +1728,7 @@ get_key_code (int no_delay)
17271728 int c ;
17281729 int i ;
17291730 int modifiers ;
1731+ int * seq_complex ;
17301732 csi_command_t csi ;
17311733 gchar utf8char [7 ];
17321734 static key_def * this = NULL , * parent ;
@@ -1742,112 +1744,129 @@ get_key_code (int no_delay)
17421744pend_send :
17431745 if (pending_keys != NULL )
17441746 {
1745- gboolean bad_or_complex_seq ;
1747+ gboolean bad_seq ;
17461748
1747- c = * pending_keys ++ ;
1748- while (c == ESC_CHAR )
1749- c = ALT (* pending_keys ++ );
1750-
1751- bad_or_complex_seq = (* pending_keys != ESC_CHAR && * pending_keys != '\0' );
1752-
1753- if (bad_or_complex_seq )
1749+ // May be a complex sequence
1750+ complex_seq :
1751+ while (pending_keys != NULL && pending_keys [0 ] == ESC_CHAR && pending_keys [1 ] == '[' )
17541752 {
17551753 tty_nodelay (TRUE);
17561754 while ((c = tty_lowlevel_getch ()) >= 0 )
17571755 push_char (c );
17581756 tty_nodelay (FALSE);
17591757
1760- // Check for complex sequences if all chars are 8bit only
1761- i = 0 ;
1762- while (seq_buffer [i ] != '\0' )
1763- {
1764- if (seq_buffer [i ] > 255 )
1765- goto no_complex_seq ;
1766- seq_char_buffer [i ] = seq_buffer [i ];
1758+ seq_complex = pending_keys ;
1759+ pending_keys = seq_append = NULL ;
17671760
1768- i ++ ;
1761+ // Check for complex sequence until any KEY_* constant (above 8bit)
1762+ for (i = 0 ; seq_complex [i ] != '\0' ; i ++ )
1763+ {
1764+ if (seq_complex [i ] > 0xFF )
1765+ {
1766+ pending_keys = seq_append = & seq_complex [i ];
1767+ break ;
1768+ }
1769+ seq_char_buffer [i ] = seq_complex [i ];
17691770 }
17701771 seq_char_buffer [i ] = '\0' ;
17711772
1772- if (seq_char_buffer [0 ] == ESC_CHAR && seq_char_buffer [1 ] == '[' )
1773- {
1774- const char * seq_char_buffer_ptr = & seq_char_buffer [2 ];
1775- if (!parse_csi (& csi , & seq_char_buffer_ptr , & seq_char_buffer [i ]))
1776- goto no_complex_seq ;
1773+ const char * seq_char_buffer_ptr = & seq_char_buffer [2 ];
1774+ if (!parse_csi (& csi , & seq_char_buffer_ptr , & seq_char_buffer [i ]))
1775+ continue ;
17771776
1778- // Check for Kitty Keyboard Protocol including backward compatibility sequences
1777+ char final_byte = * (seq_char_buffer_ptr - 1 );
1778+ if (* seq_char_buffer_ptr != '\0' )
1779+ pending_keys = seq_append = & seq_buffer [seq_char_buffer_ptr - seq_char_buffer ];
17791780
1780- if ((seq_char_buffer [i - 1 ] == 'u' && csi .param_count >= 1 )
1781- || (seq_char_buffer [i - 1 ] == '~' && csi .param_count >= 1 )
1782- || (seq_char_buffer [i - 1 ] >= 'A' && seq_char_buffer [i - 1 ] <= 'F' )
1783- || (seq_char_buffer [i - 1 ] == 'H' )
1784- || (seq_char_buffer [i - 1 ] >= 'P' && seq_char_buffer [i - 1 ] <= 'S' ))
1785- {
1786- if (csi .private_mode != 0 )
1787- goto no_complex_seq ;
1781+ // Check for Kitty Keyboard Protocol including backward compatibility sequences:
1782+ // CSI parameters [u~ABCDEFHPQS]
1783+ if ((final_byte == 'u' && csi .param_count >= 1 )
1784+ || (final_byte == '~' && csi .param_count >= 1 )
1785+ || (final_byte >= 'A' && final_byte <= 'F' ) || (final_byte == 'H' )
1786+ || (final_byte >= 'P' && final_byte <= 'S' ))
1787+ {
1788+ if (csi .private_mode != 0 )
1789+ continue ;
17881790
1789- if (csi .param_count >= 2 )
1790- modifiers = ((csi .params [1 ][0 ] - 1 ) << 12 ) & KEY_M_MASK ;
1791- else
1792- modifiers = 0 ;
1791+ if (csi .param_count >= 2 )
1792+ modifiers = ((csi .params [1 ][0 ] - 1 ) << 12 ) & KEY_M_MASK ;
1793+ else
1794+ modifiers = 0 ;
17931795
1794- if (csi .param_count == 0 )
1795- csi .params [0 ][0 ] = 1 ;
1796+ if (csi .param_count == 0 )
1797+ csi .params [0 ][0 ] = 1 ;
17961798
1797- int j = 0 ;
1798- while (kitty_key_defines [j ].code )
1799+ for (int j = 0 ; kitty_key_defines [j ].code != 0 ; j ++ )
1800+ {
1801+ if (kitty_key_defines [j ].kitty_code == csi .params [0 ][0 ]
1802+ && kitty_key_defines [j ].final_byte == final_byte )
17991803 {
1800- if (kitty_key_defines [j ].kitty_code == csi .params [0 ][0 ]
1801- && kitty_key_defines [j ].final_byte == seq_char_buffer [i - 1 ])
1802- {
1803- c = kitty_key_defines [j ].code ;
1804- if (c == -1 )
1805- goto no_complex_seq ;
1806- c |= modifiers ;
1807-
1808- pending_keys = seq_append = NULL ;
1809- goto done ;
1810- }
1811-
1812- j ++ ;
1813- }
1804+ c = kitty_key_defines [j ].code ;
1805+ if (c == -1 )
1806+ goto complex_seq ; // outer continue
1807+ c |= modifiers ;
18141808
1815- // Translate shifted chars so command line input works
1816- if (csi .params [0 ][1 ])
1817- {
1818- c = csi .params [0 ][1 ];
1819- if (modifiers & KEY_M_SHIFT )
1820- modifiers &= ~KEY_M_SHIFT ;
1821- }
1822- else
1823- {
1824- c = csi .params [0 ][0 ];
1825- if ((csi .params [0 ][2 ] || (c >= '0' && c <= '9' )) && modifiers & KEY_M_SHIFT )
1826- modifiers &= ~KEY_M_SHIFT ;
1809+ goto done ;
18271810 }
1811+ }
18281812
1829- if (c >= 0x80 )
1830- {
1831- // Unicode char
1832- i = g_unichar_to_utf8 (c , (gchar * ) & utf8char );
1813+ // Translate shifted chars so command line input works
1814+ if (csi .params [0 ][1 ])
1815+ {
1816+ c = csi .params [0 ][1 ];
1817+ if (modifiers & KEY_M_SHIFT )
1818+ modifiers &= ~KEY_M_SHIFT ;
1819+ }
1820+ else
1821+ {
1822+ c = csi .params [0 ][0 ];
1823+ if ((csi .params [0 ][2 ] || (c >= '0' && c <= '9' )) && modifiers & KEY_M_SHIFT )
1824+ modifiers &= ~KEY_M_SHIFT ;
1825+ }
18331826
1834- c = utf8char [0 ] & 0xFF ;
1835- pending_keys = seq_append = seq_buffer ;
1836- for (j = 1 ; j < i ; j ++ )
1837- push_char (utf8char [j ] & 0xFF );
1838- goto done ;
1839- }
1827+ if (c >= 0x80 )
1828+ {
1829+ // Unicode char
1830+ i = g_unichar_to_utf8 (c , (gchar * ) & utf8char );
18401831
1841- if ((modifiers & KEY_M_CTRL ) && (c == ' ' || (c >= 0x40 && c <= 0x7e )))
1842- c = XCTRL (c );
1832+ seq_buffer_temp [0 ] = '\0' ;
1833+ if (pending_keys != NULL )
1834+ for (int j = 0 ; * pending_keys != '\0' && j < SEQ_BUFFER_LEN ; j ++ )
1835+ seq_buffer_temp [j ] = pending_keys [j ];
18431836
1844- c |= modifiers ;
1837+ c = utf8char [0 ] & 0xFF ;
1838+ pending_keys = seq_append = seq_buffer ;
1839+ for (int j = 1 ; j < i ; j ++ )
1840+ push_char (utf8char [j ] & 0xFF );
1841+
1842+ for (i = 0 ; seq_buffer_temp [i ] != '\0' && i < SEQ_BUFFER_LEN ; i ++ )
1843+ push_char (seq_buffer_temp [i ]);
1844+
1845+ goto done ;
18451846 }
18461847
1847- pending_keys = seq_append = NULL ;
1848- goto done ;
1848+ if ((modifiers & KEY_M_CTRL ) && (c == ' ' || (c >= 0x40 && c <= 0x7e )))
1849+ c = XCTRL (c );
1850+
1851+ c |= modifiers ;
18491852 }
18501853
1854+ goto done ;
1855+ }
1856+
1857+ if (pending_keys == NULL )
1858+ return -1 ;
1859+
1860+ c = * pending_keys ++ ;
1861+ while (c == ESC_CHAR )
1862+ c = ALT (* pending_keys ++ );
1863+
1864+ bad_seq = (* pending_keys != ESC_CHAR && * pending_keys != '\0' );
1865+ if (* pending_keys == '\0' || bad_seq )
1866+ pending_keys = seq_append = NULL ;
1867+
1868+ if (bad_seq )
1869+ {
18511870 /* This is an unknown ESC sequence.
18521871 * To prevent interpreting its tail as a random garbage,
18531872 * eat and discard all buffered and quickly following chars.
@@ -1859,12 +1878,7 @@ get_key_code (int no_delay)
18591878 while (getch_with_timeout (old_esc_mode_timeout ) >= 0 && -- paranoia != 0 )
18601879 ;
18611880 }
1862-
1863- no_complex_seq :
1864- if (* pending_keys == '\0' || bad_or_complex_seq )
1865- pending_keys = seq_append = NULL ;
1866-
1867- if (!bad_or_complex_seq )
1881+ else
18681882 goto done ;
18691883 }
18701884
0 commit comments