summaryrefslogtreecommitdiff
path: root/Src/Modules
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2007-11-07 22:35:13 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2007-11-07 22:35:13 +0000
commita563cd895832c198a06818ebd975a19ff3532a85 (patch)
treea0165317f02ea590a649513ec5b7707116b638b9 /Src/Modules
parent1e836045b308d05fa8bd46aef812f73b14d82fb2 (diff)
downloadzsh-a563cd895832c198a06818ebd975a19ff3532a85.tar.gz
zsh-a563cd895832c198a06818ebd975a19ff3532a85.zip
24073 (plus tweak): zcurses mouse handling
Diffstat (limited to 'Src/Modules')
-rw-r--r--Src/Modules/curses.c249
1 files changed, 230 insertions, 19 deletions
diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index 08fe0099b..64ba356a1 100644
--- a/Src/Modules/curses.c
+++ b/Src/Modules/curses.c
@@ -92,6 +92,7 @@ static struct ttyinfo saved_tty_state;
static struct ttyinfo curses_tty_state;
static LinkList zcurses_windows;
static HashTable zcurses_colorpairs = NULL;
+static int zcurses_flags;
#define ZCURSES_EINVALID 1
#define ZCURSES_EDEFINED 2
@@ -106,6 +107,11 @@ static HashTable zcurses_colorpairs = NULL;
static int zc_errno, zc_color_phase=0;
static short next_cp=0;
+enum {
+ ZCF_MOUSE_ACTIVE,
+ ZCF_MOUSE_MASK_CHANGED
+};
+
static const struct zcurses_namenumberpair zcurses_attributes[] = {
{"blink", A_BLINK},
{"bold", A_BOLD},
@@ -131,6 +137,70 @@ static const struct zcurses_namenumberpair zcurses_colors[] = {
{NULL, 0}
};
+#ifdef NCURSES_MOUSE_VERSION
+enum zcurses_mouse_event_types {
+ ZCME_PRESSED,
+ ZCME_RELEASED,
+ ZCME_CLICKED,
+ ZCME_DOUBLE_CLICKED,
+ ZCME_TRIPLE_CLICKED
+};
+
+static const struct zcurses_namenumberpair zcurses_mouse_event_list[] = {
+ {"PRESSED", ZCME_PRESSED},
+ {"RELEASED", ZCME_RELEASED},
+ {"CLICKED", ZCME_CLICKED},
+ {"DOUBLE_CLICKED", ZCME_DOUBLE_CLICKED},
+ {"TRIPLE_CLICKED", ZCME_TRIPLE_CLICKED},
+ {NULL, 0}
+};
+
+struct zcurses_mouse_event {
+ int button;
+ int what;
+ mmask_t event;
+};
+
+static const struct zcurses_mouse_event zcurses_mouse_map[] = {
+ { 1, ZCME_PRESSED, BUTTON1_PRESSED },
+ { 1, ZCME_RELEASED, BUTTON1_RELEASED },
+ { 1, ZCME_CLICKED, BUTTON1_CLICKED },
+ { 1, ZCME_DOUBLE_CLICKED, BUTTON1_DOUBLE_CLICKED },
+ { 1, ZCME_TRIPLE_CLICKED, BUTTON1_TRIPLE_CLICKED },
+
+ { 2, ZCME_PRESSED, BUTTON2_PRESSED },
+ { 2, ZCME_RELEASED, BUTTON2_RELEASED },
+ { 2, ZCME_CLICKED, BUTTON2_CLICKED },
+ { 2, ZCME_DOUBLE_CLICKED, BUTTON2_DOUBLE_CLICKED },
+ { 2, ZCME_TRIPLE_CLICKED, BUTTON2_TRIPLE_CLICKED },
+
+ { 3, ZCME_PRESSED, BUTTON3_PRESSED },
+ { 3, ZCME_RELEASED, BUTTON3_RELEASED },
+ { 3, ZCME_CLICKED, BUTTON3_CLICKED },
+ { 3, ZCME_DOUBLE_CLICKED, BUTTON3_DOUBLE_CLICKED },
+ { 3, ZCME_TRIPLE_CLICKED, BUTTON3_TRIPLE_CLICKED },
+
+ { 4, ZCME_PRESSED, BUTTON4_PRESSED },
+ { 4, ZCME_RELEASED, BUTTON4_RELEASED },
+ { 4, ZCME_CLICKED, BUTTON4_CLICKED },
+ { 4, ZCME_DOUBLE_CLICKED, BUTTON4_DOUBLE_CLICKED },
+ { 4, ZCME_TRIPLE_CLICKED, BUTTON4_TRIPLE_CLICKED },
+
+#ifdef BUTTON5_PRESSED
+ /* Not defined if only 32 bits available */
+ { 5, ZCME_PRESSED, BUTTON5_PRESSED },
+ { 5, ZCME_RELEASED, BUTTON5_RELEASED },
+ { 5, ZCME_CLICKED, BUTTON5_CLICKED },
+ { 5, ZCME_DOUBLE_CLICKED, BUTTON5_DOUBLE_CLICKED },
+ { 5, ZCME_TRIPLE_CLICKED, BUTTON5_TRIPLE_CLICKED },
+#endif
+ { 0, 0, 0 }
+};
+
+mmask_t zcurses_mouse_mask = ALL_MOUSE_EVENTS;
+
+#endif
+
/* Autogenerated keypad string/number mapping*/
#include "curses_keys.h"
@@ -919,6 +989,7 @@ zccmd_input(const char *nam, char **args)
ZCWin w;
char *var;
int keypadnum = -1;
+ int nargs = arrlen(args);
#ifdef HAVE_WGET_WCH
int ret;
wint_t wi;
@@ -936,12 +1007,37 @@ zccmd_input(const char *nam, char **args)
w = (ZCWin)getdata(node);
- if (args[1] && args[2]) {
+ if (nargs >= 3) {
keypad(w->win, TRUE);
} else {
keypad(w->win, FALSE);
}
+ if (nargs >= 4) {
+#ifdef NCURSES_MOUSE_VERSION
+ if (!(zcurses_flags & ZCF_MOUSE_ACTIVE) ||
+ (zcurses_flags & ZCF_MOUSE_MASK_CHANGED)) {
+ if (mousemask(zcurses_mouse_mask, NULL) == ERR) {
+ zwarnnam(nam, "current mouse mode is not supported");
+ return 1;
+ }
+ zcurses_flags = (zcurses_flags & ~ZCF_MOUSE_MASK_CHANGED) |
+ ZCF_MOUSE_ACTIVE;
+ }
+#else
+ zwarnnam(nam, "mouse events are not supported");
+ return 1;
+#endif
+ }
+#ifdef NCURSES_MOUSE_VERSION
+ else {
+ if (zcurses_flags & ZCF_MOUSE_ACTIVE) {
+ mousemask((mmask_t)0, NULL);
+ zcurses_flags &= ~ZCF_MOUSE_ACTIVE;
+ }
+ }
+#endif
+
#ifdef HAVE_WGET_WCH
switch (wget_wch(w->win, &wi)) {
case OK:
@@ -988,32 +1084,97 @@ zccmd_input(const char *nam, char **args)
var = "REPLY";
if (!setsparam(var, ztrdup(instr)))
return 1;
- if (args[1] && args[2]) {
+ if (nargs >= 3) {
if (keypadnum > 0) {
- const struct zcurses_namenumberpair *nnptr;
- char fbuf[DIGBUFSIZE+1];
-
- for (nnptr = keypad_names; nnptr->name; nnptr++) {
- if (keypadnum == nnptr->number) {
- if (!setsparam(args[2], ztrdup(nnptr->name)))
- return 1;
+#ifdef NCURSES_MOUSE_VERSION
+ if (nargs >= 4 && keypadnum == KEY_MOUSE) {
+ MEVENT mevent;
+ char digits[DIGBUFSIZE];
+ LinkList margs;
+ const struct zcurses_mouse_event *zcmmp = zcurses_mouse_map;
+
+ if (!setsparam(args[2], ztrdup("MOUSE")))
+ return 1;
+ if (getmouse(&mevent) == ERR) {
+ /*
+ * This may happen if the mouse wasn't in
+ * the window, so set the array to empty
+ * but return success.
+ */
+ setaparam(args[3], mkarray(NULL));
return 0;
}
- }
- if (keypadnum > KEY_F0) {
- /* assume it's a function key */
- sprintf(fbuf, "F%d", keypadnum - KEY_F0);
+ margs = newlinklist();
+ sprintf(digits, "%d", (int)mevent.id);
+ addlinknode(margs, dupstring(digits));
+ sprintf(digits, "%d", mevent.x);
+ addlinknode(margs, dupstring(digits));
+ sprintf(digits, "%d", mevent.y);
+ addlinknode(margs, dupstring(digits));
+ sprintf(digits, "%d", mevent.z);
+ addlinknode(margs, dupstring(digits));
+
+ /*
+ * We only expect one event, but it doesn't hurt
+ * to keep testing.
+ */
+ for (; zcmmp->button; zcmmp++) {
+ if (mevent.bstate & zcmmp->event) {
+ const struct zcurses_namenumberpair *zcmelp =
+ zcurses_mouse_event_list;
+ for (; zcmelp->name; zcmelp++) {
+ if (zcmelp->number == zcmmp->what) {
+ char *evstr = zhalloc(strlen(zcmelp->name)+2);
+ sprintf(evstr, "%s%d", zcmelp->name,
+ zcmmp->button);
+ addlinknode(margs, evstr);
+
+ break;
+ }
+ }
+ }
+ }
+ if (mevent.bstate & BUTTON_SHIFT)
+ addlinknode(margs, "SHIFT");
+ if (mevent.bstate & BUTTON_CTRL)
+ addlinknode(margs, "CTRL");
+ if (mevent.bstate & BUTTON_SHIFT)
+ addlinknode(margs, "ALT");
+ if (!setaparam(args[3], zlinklist2array(margs)));
+ return 1;
} else {
- /* print raw number */
- sprintf(fbuf, "%d", keypadnum);
+#endif
+ const struct zcurses_namenumberpair *nnptr;
+ char fbuf[DIGBUFSIZE+1];
+
+ for (nnptr = keypad_names; nnptr->name; nnptr++) {
+ if (keypadnum == nnptr->number) {
+ if (!setsparam(args[2], ztrdup(nnptr->name)))
+ return 1;
+ return 0;
+ }
+ }
+ if (keypadnum > KEY_F0) {
+ /* assume it's a function key */
+ sprintf(fbuf, "F%d", keypadnum - KEY_F0);
+ } else {
+ /* print raw number */
+ sprintf(fbuf, "%d", keypadnum);
+ }
+ if (!setsparam(args[2], ztrdup(fbuf)))
+ return 1;
+#ifdef NCURSES_MOUSE_VERSION
}
- if (!setsparam(args[2], ztrdup(fbuf)))
- return 1;
+#endif
} else {
if (!setsparam(args[2], ztrdup("")))
return 1;
}
}
+#ifdef NCURSES_MOUSE_VERSION
+ if (keypadnum != KEY_MOUSE && nargs >= 4)
+ setaparam(args[3], mkarray(NULL));
+#endif
return 0;
}
@@ -1058,6 +1219,55 @@ zccmd_timeout(const char *nam, char **args)
static int
+zccmd_mouse(const char *nam, char **args)
+{
+#ifdef NCURSES_MOUSE_VERSION
+ int ret = 0;
+
+ for (; *args; args++) {
+ if (!strcmp(*args, "delay")) {
+ char *eptr;
+ zlong delay;
+
+ if (!*++args ||
+ ((delay = zstrtol(*args, &eptr, 10)), eptr != NULL)) {
+ zwarnnam(nam, "mouse delay requires an integer argument");
+ return 1;
+ }
+ if (mouseinterval((int)delay) != OK)
+ ret = 1;
+ } else {
+ char *arg = *args;
+ int onoff = 1;
+ if (*arg == '+')
+ arg++;
+ else if (*arg == '-') {
+ arg++;
+ onoff = 0;
+ }
+ if (!strcmp(arg, "motion")) {
+ mmask_t old_mask = zcurses_mouse_mask;
+ if (onoff)
+ zcurses_mouse_mask |= REPORT_MOUSE_POSITION;
+ else
+ zcurses_mouse_mask &= ~REPORT_MOUSE_POSITION;
+ if (old_mask != zcurses_mouse_mask)
+ zcurses_flags |= ZCF_MOUSE_MASK_CHANGED;
+ } else {
+ zwarnnam(nam, "unrecognised mouse command: %s", *arg);
+ return 1;
+ }
+ }
+ }
+
+ return ret;
+#else
+ return 1;
+#endif
+}
+
+
+static int
zccmd_position(const char *nam, char **args)
{
LinkNode node;
@@ -1141,8 +1351,9 @@ bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
{"attr", zccmd_attr, 2, -1},
{"bg", zccmd_bg, 2, -1},
{"scroll", zccmd_scroll, 2, 2},
- {"input", zccmd_input, 1, 3},
+ {"input", zccmd_input, 1, 4},
{"timeout", zccmd_timeout, 2, 2},
+ {"mouse", zccmd_mouse, 0, -1},
{"touch", zccmd_touch, 1, -1},
{NULL, (zccmd_t)0, 0, 0}
};
@@ -1165,7 +1376,7 @@ bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
zwarnnam(nam, "too few arguments for subcommand: %s", args[0]);
return 1;
} else if (zcsc->maxargs >= 0 && num_args > zcsc->maxargs) {
- zwarnnam(nam, "too may arguments for subcommand: %s", args[0]);
+ zwarnnam(nam, "too many arguments for subcommand: %s", args[0]);
return 1;
}