1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00
elinks/src/osdep/unix/bsd.c

225 lines
4.3 KiB
C
Raw Normal View History

/* BSD mouse system-specific routines. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "osdep/system.h"
#include <stdio.h>
#ifdef CONFIG_SYSMOUSE
#ifdef HAVE_SYS_CONSIO_H
#include <sys/consio.h>
#include <sys/fbio.h>
#else
#include <machine/console.h>
#endif /* HAVE_SYS_CONSIO_H */
#endif /* CONFIG_SYSMOUSE */
#include "elinks.h"
#include "main/select.h"
#include "osdep/osdep.h"
#include "osdep/signals.h"
#include "terminal/event.h"
#include "terminal/mouse.h"
#if defined(CONFIG_SYSMOUSE) && defined(CONFIG_MOUSE)
struct sysmouse_spec {
void *itrm;
int cheight;
int cwidth;
void (*fn)(void *, unsigned char *, int);
};
static void
sysmouse_handler(void *data)
{
static struct term_event_mouse prev_mouse;
static int prev_buttons;
struct sysmouse_spec *sp = data;
void *itrm = sp->itrm;
int fd = get_output_handle();
int buttons, change;
int extended_button;
mouse_info_t mi;
struct term_event_mouse mouse;
struct term_event ev;
mi.operation = MOUSE_GETINFO;
if (ioctl(fd, CONS_MOUSECTL, &mi) == -1) return;
mouse.x = int_max(mi.u.data.x / sp->cwidth, 0);
mouse.y = int_max(mi.u.data.y / sp->cheight, 0);
/* for cosmetic bug in syscons.c on FreeBSD 3.3/3.4 */
#ifdef HAVE_MACHINE_CONSOLE_H
mi.operation = MOUSE_HIDE;
ioctl(fd, CONS_MOUSECTL, &mi);
mi.operation = MOUSE_SHOW;
ioctl(fd, CONS_MOUSECTL, &mi);
#endif
buttons = mi.u.data.buttons & 7;
change = (mouse.x != prev_mouse.x || mouse.y != prev_mouse.y);
prev_mouse = mouse;
/* It's horrible. */
switch (buttons) {
case 0:
switch (prev_buttons) {
case 0:
extended_button = mi.u.data.buttons & 24;
if (!extended_button) return;
if (extended_button & 8) mouse.button = B_WHEEL_UP;
else mouse.button = B_WHEEL_DOWN;
break;
case 1:
case 3:
case 5:
case 7:
mouse.button = B_LEFT | B_UP;
break;
case 2:
case 6:
mouse.button = B_MIDDLE | B_UP;
break;
case 4:
mouse.button = B_RIGHT | B_UP;
break;
}
break;
case 1:
case 3:
case 5:
case 7:
switch (prev_buttons) {
case 0:
case 2:
case 4:
case 6:
mouse.button = B_LEFT | B_DOWN;
break;
case 1:
case 3:
case 5:
case 7:
if (change)
mouse.button = B_LEFT | B_DRAG;
else mouse.button = B_LEFT | B_DOWN;
break;
}
break;
case 2:
case 6:
switch (prev_buttons) {
case 1:
case 3:
case 5:
case 7:
mouse.button = B_LEFT | B_UP;
break;
case 0:
case 4:
mouse.button = B_MIDDLE | B_DOWN;
break;
case 2:
case 6:
if (change)
mouse.button = B_MIDDLE | B_DRAG;
else mouse.button = B_MIDDLE | B_DOWN;
break;
}
break;
case 4:
switch (prev_buttons) {
case 1:
case 3:
case 5:
case 7:
mouse.button = B_LEFT | B_UP;
break;
case 2:
case 6:
mouse.button = B_MIDDLE | B_UP;
break;
case 0:
mouse.button = B_RIGHT | B_DOWN;
break;
case 4:
if (change)
mouse.button = B_RIGHT | B_DRAG;
else mouse.button = B_RIGHT | B_DOWN;
break;
}
break;
}
prev_buttons = buttons;
set_mouse_term_event(&ev, mouse.x, mouse.y, mouse.button);
sp->fn(itrm, (unsigned char *)&ev, sizeof(ev));
}
static void
sysmouse_signal_handler(void *data)
{
register_bottom_half(sysmouse_handler, data);
}
void *
handle_mouse(int cons, void (*fn)(void *, unsigned char *, int),
void *data)
{
static struct sysmouse_spec mouse_spec;
video_info_t vi;
mouse_info_t mi;
int fd = get_output_handle();
if (is_xterm()) return NULL;
mouse_spec.itrm = data;
mouse_spec.fn = fn;
if (ioctl(fd, FBIO_GETMODE, &vi.vi_mode) != -1 &&
ioctl(fd, FBIO_MODEINFO, &vi) != -1) {
mouse_spec.cwidth = vi.vi_cwidth;
mouse_spec.cheight = vi.vi_cheight;
} else {
return NULL;
}
install_signal_handler(SIGUSR2, NULL, NULL, 0);
mi.operation = MOUSE_MODE;
mi.u.mode.mode = 0;
mi.u.mode.signal = SIGUSR2;
if (ioctl(fd, CONS_MOUSECTL, &mi) != -1) {
install_signal_handler(SIGUSR2,
(void (*)(void *))sysmouse_signal_handler, &mouse_spec, 0);
mi.operation = MOUSE_SHOW;
ioctl(fd, CONS_MOUSECTL, &mi);
return &mouse_spec;
} else {
return NULL;
}
}
void
unhandle_mouse(void *data)
{
if (data) install_signal_handler(SIGUSR2, NULL, NULL, 0);
}
void
suspend_mouse(void *data)
{
if (data) install_signal_handler(SIGUSR2, NULL, NULL, 0);
}
void
resume_mouse(void *data)
{
if (data) install_signal_handler(SIGUSR2,
(void (*)(void *))sysmouse_signal_handler, data, 0);
}
#endif