Skip to content

Instantly share code, notes, and snippets.

@saitoha
Created July 12, 2012 12:04
Show Gist options
  • Save saitoha/3097729 to your computer and use it in GitHub Desktop.
Save saitoha/3097729 to your computer and use it in GitHub Desktop.
Support SGR 1006 mouse reporting, for GNU Screen
diff --git a/src/ansi.c b/src/ansi.c
index d88e153..088ab0b 100644
--- a/src/ansi.c
+++ b/src/ansi.c
@@ -193,6 +193,7 @@ register struct win *p;
p->w_insert = 0;
p->w_revvid = 0;
p->w_mouse = 0;
+ p->w_mouse_protocol = 0;
p->w_curinv = 0;
p->w_curvvis = 0;
p->w_autolf = 0;
@@ -1462,6 +1463,11 @@ int c, intermediate;
curr->w_mouse = i ? a1 : 0;
LMouseMode(&curr->w_layer, curr->w_mouse);
break;
+ case 1006: /* sgr mouse*/
+ curr->w_mouse_protocol = i ? a1 : 0;
+ LMouseProtocol(&curr->w_layer, curr->w_mouse_protocol);
+ break;
+ /* case 1015: urxvt mouse */
}
}
break;
diff --git a/src/display.c b/src/display.c
index 94c05f1..7948508 100644
--- a/src/display.c
+++ b/src/display.c
@@ -183,6 +183,7 @@ DefRestore()
LCursorkeysMode(flayer, 0);
LCursorVisibility(flayer, 0);
LMouseMode(flayer, 0);
+ LMouseProtocol(flayer, 0);
LSetRendition(flayer, &mchar_null);
LSetFlow(flayer, nwin_default.flowflag & FLOW_NOW);
}
@@ -836,6 +837,35 @@ int mode;
}
}
+void
+MouseProtocol(mode)
+int mode;
+{
+ if (!display)
+ return;
+
+ if (mode < D_mousetrack)
+ mode = D_mousetrack;
+
+ if (D_mouseprotocol != mode)
+ {
+ char mousebuf[20];
+ if (!D_CXT)
+ return;
+ if (D_mouseprotocol)
+ {
+ sprintf(mousebuf, "\033[?%dl", D_mouseprotocol);
+ AddStr(mousebuf);
+ }
+ if (mode)
+ {
+ sprintf(mousebuf, "\033[?%dh", mode);
+ AddStr(mousebuf);
+ }
+ D_mouseprotocol = mode;
+ }
+}
+
static int StrCost;
/* ARGSUSED */
@@ -1261,6 +1291,7 @@ int cur_only;
CursorkeysMode(0);
CursorVisibility(0);
MouseMode(0);
+ MouseProtocol(0);
SetRendition(&mchar_null);
SetFlow(FLOW_NOW);
@@ -3121,6 +3152,7 @@ NukePending()
int oldkeypad = D_keypad, oldcursorkeys = D_cursorkeys;
int oldcurvis = D_curvis;
int oldmouse = D_mouse;
+ int oldmouseprotocol = D_mouseprotocol;
oldrend = D_rend;
len = D_obufp - D_obuf;
@@ -3183,6 +3215,7 @@ NukePending()
CursorkeysMode(oldcursorkeys);
CursorVisibility(oldcurvis);
MouseMode(oldmouse);
+ MouseProtocol(oldmouseprotocol);
if (D_CWS)
{
debug("ResizeDisplay: using WS\n");
@@ -3407,20 +3440,65 @@ char *data;
if (D_mouse && D_forecv)
{
unsigned char *bp = (unsigned char *)buf;
- int x, y, i = size;
+ int x, y, i = size, j, k;
/* XXX this assumes that the string is read in as a whole... */
for (i = size; i > 0; i--, bp++)
{
- if (i > 5 && bp[0] == 033 && bp[1] == '[' && bp[2] == 'M')
+ if (bp[0] == 033 && bp[1] == '[' && bp[2] == 'M')
+ {
+ /* 8bit Normal protocol */
+ bp++;
+ i--;
+ }
+ else if (bp[0] == 033 && bp[1] == '[' && bp[2] == '<')
{
+ /* 8bit SGR 1006 protocol */
bp++;
i--;
}
- else if (i < 5 || bp[0] != 0233 || bp[1] != 'M')
+ else if (bp[0] == 0233 && bp[1] == 'M')
+ {
+ /* 7bit Normal protocol */
+ }
+ else if (bp[0] == 0233 && bp[1] == '<')
+ {
+ /* 7bit SGR 1006 protocol */
+ }
+ else
continue;
- x = bp[3] - 33;
- y = bp[4] - 33;
+
+ if (bp[1] == 'M') {
+ /* Normal protocol:
+ *
+ * CSI M Cb Cx Cy
+ * (Cb, Cx, Cy as byte.)
+ *
+ * This coordinate values (Cx, Cy) are added origin offset +1
+ * and base offset +32 (to make it printable)
+ */
+ x = bp[3] - 33;
+ y = bp[4] - 33;
+ } else if (bp[1] == '<') {
+ /* SGR 1006 protocol:
+ *
+ * CSI M Db ; Dx ; Dy M/m
+ * (Db, Dx, Dy as decimal formatted strings.)
+ *
+ * The coordinate values (Dx, Dy) are added origin offset +1
+ */
+ for (j = 2; '0' <= bp[j] && bp[j] <= '9'; j++)
+ ;
+ if (bp[j++] != ';')
+ continue;
+ for (x = 0; '0' <= bp[j] && bp[j] <= '9'; j++)
+ x = x * 10 + bp[j] - '0';
+ if (bp[j++] != ';')
+ continue;
+ for (y = 0; '0' <= bp[j] && bp[j] <= '9'; j++)
+ y = y * 10 + bp[j] - '0';
+ }
+
if (x >= D_forecv->c_xs && x <= D_forecv->c_xe && y >= D_forecv->c_ys && y <= D_forecv->c_ye)
{
if ((D_fore && D_fore->w_mouse) || (D_mousetrack && D_forecv->c_layer->l_mode == 1))
@@ -3430,15 +3508,36 @@ char *data;
y -= D_forecv->c_yoff;
if (x >= 0 && x < D_forecv->c_layer->l_width && y >= 0 && y < D_forecv->c_layer->l_height)
{
- bp[3] = x + 33;
- bp[4] = y + 33;
- i -= 4;
- bp += 4;
+ if (bp[1] == 'M')
+ {
+ bp[3] = x + 33;
+ bp[4] = y + 33;
+ i -= 4;
+ bp += 4;
+ }
+ else if (bp[1] == '<')
+ {
+ k = j;
+ while (bp[--k] != ';')
+ {
+ bp[k] = y % 10 + '0';
+ y /= 10;
+ }
+ while (bp[--k] != ';')
+ {
+ bp[k] = x % 10 + '0';
+ x /= 10;
+ }
+ i -= j;
+ bp += j;
+ }
continue;
}
}
}
- else if (D_mousetrack && bp[2] == '#')
+ else if (D_mousetrack && (
+ (bp[1] == 'M' && bp[2] == '#') || /* Normal protocol */
+ (bp[1] == '<' && bp[j] == 'm'))) /* SGR 1006 protocol */
{
/* 'focus' to the clicked region, only on mouse up */
struct canvas *cv = FindCanvas(x, y);
@@ -3454,11 +3553,23 @@ char *data;
bp--;
size--;
}
- if (i > 5)
- bcopy((char *)bp + 5, (char *)bp, i - 5);
- bp--;
- i -= 4;
- size -= 5;
+
+ if (bp[1] == 'M')
+ {
+ if (i > 5)
+ bcopy((char *)bp + 5, (char *)bp, i - 5);
+ bp--;
+ i -= 4;
+ size -= 5;
+ }
+ else if (bp[1] == '<')
+ {
+ if (i > j + 1)
+ bcopy((char *)bp + j + 1, (char *)bp, i - j - 1);
+ bp--;
+ i -= j;
+ size -= j + 1;
+ }
}
}
#ifdef ENCODINGS
diff --git a/src/display.h b/src/display.h
index e8b3b80..f435493 100644
--- a/src/display.h
+++ b/src/display.h
@@ -100,6 +100,7 @@ struct display
int d_hstatus; /* hardstatus used */
int d_lp_missing; /* last character on bot line missing */
int d_mouse; /* mouse mode */
+ int d_mouseprotocol; /* mouse protocol */
int d_mousetrack; /* set when user wants to use mouse even when the window
does not */
#ifdef RXVT_OSC
@@ -227,6 +228,7 @@ extern struct display TheDisplay;
#define D_hstatus DISPLAY(d_hstatus)
#define D_lp_missing DISPLAY(d_lp_missing)
#define D_mouse DISPLAY(d_mouse)
+#define D_mouseprotocol DISPLAY(d_mouseprotocol)
#define D_mousetrack DISPLAY(d_mousetrack)
#define D_xtermosc DISPLAY(d_xtermosc)
#define D_lpchar DISPLAY(d_lpchar)
diff --git a/src/layer.c b/src/layer.c
index 1ae7972..063340d 100644
--- a/src/layer.c
+++ b/src/layer.c
@@ -911,6 +911,23 @@ int on;
}
void
+LMouseProtocol(l, on)
+struct layer *l;
+int on;
+{
+ struct canvas *cv;
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ display = cv->c_display;
+ if (D_blocked)
+ continue;
+ if (cv != D_forecv)
+ continue;
+ MouseProtocol(on);
+ }
+}
+
+void
LClearAll(l, uself)
struct layer *l;
int uself;
diff --git a/src/window.c b/src/window.c
index 1c6f5b6..5779bcf 100644
--- a/src/window.c
+++ b/src/window.c
@@ -498,6 +498,7 @@ WinRestore()
ReverseVideo(fore->w_revvid);
CursorVisibility(fore->w_curinv ? -1 : fore->w_curvvis);
MouseMode(fore->w_mouse);
+ MouseProtocol(fore->w_mouse_protocol);
}
}
diff --git a/src/window.h b/src/window.h
index 7311ecb..a55eaff 100644
--- a/src/window.h
+++ b/src/window.h
@@ -235,6 +235,7 @@ struct win
char w_xtermosc[4][MAXSTR]; /* special xterm/rxvt escapes */
#endif
int w_mouse; /* mouse mode 0,9,1000 */
+ int w_mouse_protocol; /* mouse protocol 0,1006,1015 */
#ifdef HAVE_BRAILLE
int w_bd_x, w_bd_y; /* Braille cursor position */
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment