int mouse_wgetch(WINDOW *win) { int key; #if defined(NCURSES_MOUSE_VERSION) /* before calling this you have to put (only the first time) a "wtimeout(dialog, WTIMEOUT_VAL);" */ do { key = dlg_getc(win); if (key == KEY_MOUSE) { MEVENT event; mseRegion *p; if (getmouse(&event) != ERR && (p = mouse_region(event.y, event.x)) != 0) { key = M_EVENT + p->code; } else { (void) beep(); key = ERR; } } } while (key == ERR); #elif defined(HAVE_LIBGPM) fd_set selSet; int flag, result; int fd = STDIN_FILENO; static Gpm_Event ev; key = 0; if (!gpm_flag || gpm_fd <= -1) return dlg_getc(win); if (gpm_morekeys) return (*gpm_handler) (&ev, gpm_data); gpm_hflag = 0; while (1) { if (gpm_visiblepointer) GPM_DRAWPOINTER(&ev); do { FD_ZERO(&selSet); FD_SET(fd, &selSet); FD_SET(gpm_fd, &selSet); gpm_timeout.tv_usec = WTIMEOUT_VAL * 10000; gpm_timeout.tv_sec = 0; flag = select(5, &selSet, (fd_set *) 0, (fd_set *) 0, &gpm_timeout); /* fprintf(stderr, "X"); */ } while (!flag); if (FD_ISSET(fd, &selSet)) return dlg_getc(win); if (flag == -1) continue; if (Gpm_GetEvent(&ev) && gpm_handler && (result = (*gpm_handler) (&ev, gpm_data))) { gpm_hflag = 1; return result; } } #else /* before calling this you have to put (only the first time) a "wtimeout(dialog, WTIMEOUT_VAL);" */ do { key = dlg_getc(win); } while (key == ERR); #endif return key; }
int mouse_handler(Gpm_Event * event, void *unused) { static mseRegion *prevPtr; mseRegion *butPtr; static int grabkey = 0; static int reptkey = 0; static int dragging = 0; static int prevY; static int prevMouseDown; /* xterm gives only generic up events */ #define CURRENT_POS (M_EVENT+event->y-bigRegion.y-1) #if 0 fprintf(stderr, "grab %i, more %i, drag %i, x %i, y %i, butt %i, type %x\n", grabkey, gpm_morekeys, dragging, event->x, event->y, event->buttons, event->type); #endif if (grabkey) { /* return key or 0 */ if (Gpm_Repeat(100)) return grabkey; /* go on (slow to ease xterm( */ else return grabkey = gpm_morekeys = 0; /* no more grab */ } if (gpm_morekeys) { /* repeat a key */ gpm_morekeys--; return reptkey; } if (dragging) { /* respond to motions, independently of where they are */ int delta; if (!(event->type & GPM_DRAG)) { dragging--; return CURRENT_POS; } delta = event->y - prevY; if (!delta) return 0; prevY = event->y; reptkey = (delta > 0 ? KEY_DOWN : KEY_UP); gpm_morekeys = bigRegion.step * abs(delta); return (reptkey == KEY_UP ? M_EVENT : M_EVENT + bigRegion.height); } /* the big region */ if (bigregionFlag && event->y >= bigRegion.y && event->y < bigRegion.Y && event->x >= bigRegion.x && event->x < bigRegion.X) { /* top border */ if (event->y == bigRegion.y) { if ((event->type & GPM_DOWN) && (event->buttons & GPM_B_LEFT)) { grabkey = KEY_UP; gpm_morekeys = 1; return KEY_UP; } else return 0; } /* bottom border */ if (event->y + 1 == bigRegion.Y) { if ((event->type & GPM_DOWN) && (event->buttons & GPM_B_LEFT)) { grabkey = KEY_DOWN; gpm_morekeys = 1; return KEY_DOWN; } else return 0; } /* right half */ reptkey = 0; if (event->x > bigRegion.xth) { if (event->type & GPM_DOWN) switch (event->buttons) { case GPM_B_LEFT: reptkey = KEY_DOWN - KEY_UP; /* FALLTHRU */ case GPM_B_RIGHT: reptkey += KEY_UP; gpm_morekeys = event->y - bigRegion.y; return (reptkey == KEY_UP ? M_EVENT : M_EVENT + bigRegion.height); case GPM_B_MIDDLE: prevY = event->y; dragging++; return 0; } return CURRENT_POS; } /* left half */ else { /* WARN *//* check down events as well */ if ((event->type & GPM_UP) && (event->buttons & GPM_B_LEFT)) { if (event->type & GPM_SINGLE) { reptkey = ' '; gpm_morekeys = (bigRegion.mode == 0); return M_EVENT + 'o'; } return '\n'; } return CURRENT_POS; } } /* smaller regions */ /* retrieve the frame under the pointer */ butPtr = mouse_region(event->y, event->x); switch (GPM_BARE_EVENTS(event->type)) { case GPM_MOVE: if (butPtr && butPtr != prevPtr) { /* enter event */ prevPtr = butPtr; return M_EVENT + butPtr->code; } break; case GPM_DRAG: if (butPtr && butPtr != prevPtr) /* enter event (with button) */ return M_EVENT + butPtr->code; break; case GPM_DOWN: /* down: remember where */ prevPtr = butPtr; prevMouseDown = event->buttons; /* to handle xterm b-up event */ break; case GPM_UP: /* WARN multiple presses are bad-behaving */ switch (prevMouseDown) { /* event->buttons doesn't run with xterm */ case GPM_B_RIGHT: return '\n'; case GPM_B_MIDDLE: return '\t'; case GPM_B_LEFT: if (butPtr && butPtr == prevPtr) { /* complete button press *//* return two keys... */ gpm_morekeys++; reptkey = butPtr->code; return M_EVENT + toupper(butPtr->code); } prevPtr = butPtr; return M_EVENT + butPtr->code; /* no, only an enter event */ } } return 0; /* nothing relevant */ }