Skip to content

Commit a842fc5

Browse files
committed
Merge branch 'master' of http://github.com/MidnightCommander/mc
2 parents f1eacfb + 0c8d54e commit a842fc5

File tree

4 files changed

+186
-21
lines changed

4 files changed

+186
-21
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Antonio Palama, DOS port <[email protected]>
6161

6262
Egmont Koblinger <[email protected]>
6363
Support of 256 colors
64+
Support of extended mouse clicks beyond 223
6465

6566
Erwin van Eijk <[email protected]>
6667

lib/tty/key.c

+170-21
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,8 @@ static int *seq_append = NULL;
517517

518518
static int *pending_keys = NULL;
519519

520+
static int mouse_btn, mouse_x, mouse_y;
521+
520522
#ifdef __QNXNTO__
521523
ph_dv_f ph_attach;
522524
ph_ov_f ph_input_group;
@@ -707,18 +709,14 @@ getch_with_delay (void)
707709
static void
708710
xmouse_get_event (Gpm_Event * ev)
709711
{
710-
int btn;
711712
static struct timeval tv1 = { 0, 0 }; /* Force first click as single */
712713
static struct timeval tv2;
713714
static int clicks = 0;
714715
static int last_btn = 0;
716+
int btn = mouse_btn;
715717

716718
/* Decode Xterm mouse information to a GPM style event */
717719

718-
/* Variable btn has following meaning: */
719-
/* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
720-
btn = tty_lowlevel_getch () - 32;
721-
722720
/* There seems to be no way of knowing which button was released */
723721
/* So we assume all the buttons were released */
724722

@@ -796,10 +794,8 @@ xmouse_get_event (Gpm_Event * ev)
796794
}
797795
last_btn = ev->buttons;
798796
}
799-
/* Coordinates are 33-based */
800-
/* Transform them to 1-based */
801-
ev->x = tty_lowlevel_getch () - 32;
802-
ev->y = tty_lowlevel_getch () - 32;
797+
ev->x = mouse_x;
798+
ev->y = mouse_y;
803799
}
804800

805801
/* --------------------------------------------------------------------------------------------- */
@@ -933,6 +929,134 @@ push_char (int c)
933929
return ret;
934930
}
935931

932+
/* --------------------------------------------------------------------------------------------- */
933+
/* Parse extended mouse coordinates.
934+
Returns -1 if pending_keys cannot be a prefix of extended mouse coordinates.
935+
Returns 0 if pending_keys is a valid (but still incomplete) prefix for extended mouse
936+
coordinates, e.g. "^[[32;4".
937+
Returns 1 and fills the mouse_btn, mouse_x, mouse_y values if pending_keys is a complete extended
938+
mouse sequence, e.g. "^[[32;42;5M"
939+
*/
940+
941+
/* Technical info (Egmont Koblinger <[email protected]>):
942+
943+
The ancient way of reporting mouse coordinates only supports coordinates up to 231,
944+
so if your terminal is wider (or taller, but that's unlikely), you cannot use your mouse
945+
in the rightmost columns.
946+
947+
* The old way of reporting mouse coordinates is the following:
948+
+ Output DECSET 1000 to enable mouse
949+
+ Expect escape sequences in the format \e[M<action+32><x+32><y+32> whereas <action+32>,
950+
<x+32> and <y+32> are single bytes. (Action is 0 for left click, 1 for middle click,
951+
2 for right click, 3 for release, or something like this.)
952+
+ Disadvantages of this format:
953+
+ x and y can only go up to 231.
954+
+ Coordinates above 95 are not ascii-compatible, so any character set converting
955+
layer (e.g. luit) messes them up.
956+
+ The stream is not valid UTF-8, even if everything else is.
957+
958+
* The first new extension, introduced by xterm-262, is the following:
959+
+ Output DECSET 1000 to enable mouse, followed by DECSET 1005 to activate extended mode.
960+
+ Expect escape sequences in the format \e[M<action+32><<x+32>><<y+32>> whereas <<x+32>>
961+
and <<y+32>> each can be up to two bytes long: coordinate+32 is encoded in UTF-8.
962+
+ Disadvantates of this format:
963+
+ There's still a limit of 2015 rows/columns (okay, it's not a real life problem).
964+
+ Doesn't solve the luit issue.
965+
+ It is "horribly broken" (quoting urxvt's changelog) in terms of compatibility
966+
with the previous standard. There is no way for an application to tell whether
967+
the underlying terminal supports this new mode (whether DECSET 1005 did actually change
968+
the behavior or not), but depending on this a completely different user action might
969+
generate the same input. Example:
970+
+ If the terminal doesn't support this extension, then clicking at (162, 129)
971+
generates \e[M<32><194><161>.
972+
+ If the terminal supports this extension, then clicking at (129, 1) [bit of math:
973+
129+32 = 161, U+0161 in UTF-8 is 194 161] generates \e[M<32><194><161><33>.
974+
+ so there's no way to tell whether the terminal ignored the 1005 escape sequence,
975+
the user clicked on (162, 129) and then typed an exclamation mark; or whether
976+
the terminal recognized the escape, and the user clicked on (129, 1).
977+
+ Due to this horrible brokenness, there's no way to implement support it without
978+
explicitly asking the user (via a setting) if the terminal can speak this extension.
979+
980+
* The second new extension, introduced by rxvt-unicode-9.10, is the following:
981+
+ Output DECSET 1000 to enable mouse, followed by DECSET 1015 to activate this extended mode.
982+
+ Expect escape sequences in the format \e[{action+32};{x};{y}M where this time I used
983+
the braces to denote spelling out the numbers in decimal, rather than using raw bytes.
984+
+ The only thing I don't understand is why they kept the offset of 32 at action, but other
985+
than that, this format is totally okay, and solves all the weaknesses of the previous ones.
986+
987+
Currently, at least the following terminal emulators have support for these:
988+
* xterm supports the xterm extension
989+
* rxvt-unicode >= 9.10 supports both extensions
990+
* iterm2 supports both extensions.
991+
*/
992+
993+
static int
994+
parse_extended_mouse_coordinates (void)
995+
{
996+
int c, btn = 0, x = 0, y = 0;
997+
const int *p = pending_keys;
998+
999+
c = *p++;
1000+
if (c == 0)
1001+
return 0;
1002+
if (c != ESC_CHAR)
1003+
return -1;
1004+
1005+
c = *p++;
1006+
if (c == 0)
1007+
return 0;
1008+
if (c != '[')
1009+
return -1;
1010+
1011+
while (TRUE)
1012+
{
1013+
c = *p++;
1014+
if (c == 0)
1015+
return 0;
1016+
if (c == ';')
1017+
break;
1018+
if (c < '0' || c > '9')
1019+
return -1;
1020+
btn = 10 * btn + c - '0';
1021+
}
1022+
if (btn < 32)
1023+
return -1;
1024+
btn -= 32;
1025+
1026+
while (TRUE)
1027+
{
1028+
c = *p++;
1029+
if (c == 0)
1030+
return 0;
1031+
if (c == ';')
1032+
break;
1033+
if (c < '0' || c > '9')
1034+
return -1;
1035+
x = 10 * x + c - '0';
1036+
}
1037+
if (x < 1)
1038+
return -1;
1039+
1040+
while (TRUE)
1041+
{
1042+
c = *p++;
1043+
if (c == 0)
1044+
return 0;
1045+
if (c == 'M')
1046+
break;
1047+
if (c < '0' || c > '9')
1048+
return -1;
1049+
y = 10 * y + c - '0';
1050+
}
1051+
if (y < 1)
1052+
return -1;
1053+
1054+
mouse_btn = btn;
1055+
mouse_x = x;
1056+
mouse_y = y;
1057+
return 1;
1058+
}
1059+
9361060
/* --------------------------------------------------------------------------------------------- */
9371061
/* Apply corrections for the keycode generated in get_key_code() */
9381062

@@ -1692,22 +1816,35 @@ get_key_code (int no_delay)
16921816
pend_send:
16931817
if (pending_keys != NULL)
16941818
{
1695-
int d = *pending_keys++;
1696-
check_pend:
1697-
if (*pending_keys == 0)
1819+
int m;
1820+
1821+
m = parse_extended_mouse_coordinates ();
1822+
if (m == 1)
16981823
{
1699-
pending_keys = NULL;
1700-
seq_append = NULL;
1824+
pending_keys = seq_append = NULL;
1825+
this = NULL;
1826+
return MCKEY_EXTENDED_MOUSE;
17011827
}
1702-
if ((d == ESC_CHAR) && (pending_keys != NULL))
1828+
if (m == -1)
17031829
{
1704-
d = ALT (*pending_keys++);
1705-
goto check_pend;
1830+
int d = *pending_keys++;
1831+
check_pend:
1832+
if (*pending_keys == 0)
1833+
{
1834+
pending_keys = NULL;
1835+
seq_append = NULL;
1836+
}
1837+
if ((d == ESC_CHAR) && (pending_keys != NULL))
1838+
{
1839+
d = ALT (*pending_keys++);
1840+
goto check_pend;
1841+
}
1842+
if ((d > 127 && d < 256) && use_8th_bit_as_meta)
1843+
d = ALT (d & 0x7f);
1844+
this = NULL;
1845+
return correct_key_code (d);
17061846
}
1707-
if ((d > 127 && d < 256) && use_8th_bit_as_meta)
1708-
d = ALT (d & 0x7f);
1709-
this = NULL;
1710-
return correct_key_code (d);
1847+
/* else if (m == 0), just let it continue */
17111848
}
17121849

17131850
nodelay_try_again:
@@ -2014,9 +2151,21 @@ tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block)
20142151
#ifdef KEY_MOUSE
20152152
|| c == KEY_MOUSE
20162153
#endif /* KEY_MOUSE */
2154+
|| c == MCKEY_EXTENDED_MOUSE
20172155
))
20182156
{
20192157
/* Mouse event */
2158+
/* In case of extended coordinates, mouse_btn, mouse_x and mouse_y are already filled in. */
2159+
if (c != MCKEY_EXTENDED_MOUSE)
2160+
{
2161+
/* Variable btn has following meaning: */
2162+
/* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
2163+
mouse_btn = tty_lowlevel_getch () - 32;
2164+
/* Coordinates are 33-based */
2165+
/* Transform them to 1-based */
2166+
mouse_x = tty_lowlevel_getch () - 32;
2167+
mouse_y = tty_lowlevel_getch () - 32;
2168+
}
20202169
xmouse_get_event (event);
20212170
return (event->type != 0) ? EV_MOUSE : EV_NONE;
20222171
}

lib/tty/key.h

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
/* Return code for the mouse sequence */
3434
#define MCKEY_MOUSE -2
3535

36+
/* Return code for the extended mouse sequence */
37+
#define MCKEY_EXTENDED_MOUSE -3
38+
3639
/*** enums ***************************************************************************************/
3740

3841
/*** structures declarations (and typedefs of structures)*****************************************/

lib/tty/mouse.c

+12
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ enable_mouse (void)
138138
/* enable mouse tracking */
139139
printf (ESC_STR "[?1000h");
140140

141+
/* enable urxvt extended mouse coordinate reporting */
142+
printf (ESC_STR "[?1015h");
143+
141144
fflush (stdout);
142145
mouse_enabled = TRUE;
143146
break;
@@ -149,6 +152,9 @@ enable_mouse (void)
149152
/* enable mouse tracking */
150153
printf (ESC_STR "[?1002h");
151154

155+
/* enable urxvt extended mouse coordinate reporting */
156+
printf (ESC_STR "[?1015h");
157+
152158
fflush (stdout);
153159
mouse_enabled = TRUE;
154160
break;
@@ -176,6 +182,9 @@ disable_mouse (void)
176182
break;
177183
#endif
178184
case MOUSE_XTERM_NORMAL_TRACKING:
185+
/* disable urxvt extended mouse coordinate reporting */
186+
printf (ESC_STR "[?1015l");
187+
179188
/* disable mouse tracking */
180189
printf (ESC_STR "[?1000l");
181190

@@ -185,6 +194,9 @@ disable_mouse (void)
185194
fflush (stdout);
186195
break;
187196
case MOUSE_XTERM_BUTTON_EVENT_TRACKING:
197+
/* disable urxvt extended mouse coordinate reporting */
198+
printf (ESC_STR "[?1015l");
199+
188200
/* disable mouse tracking */
189201
printf (ESC_STR "[?1002l");
190202

0 commit comments

Comments
 (0)