ref: 892668527d0e1f705ab39c7da828c54d9dc4cc6e
dir: /bindings.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#include "dat.h"
#include "fns.h"
Binding * BindingRoot = nil;
static Point MoveMark = {0};
typedef struct DefaultBinding
{
int type;
int code;
char * command;
void (*func)(int);
} DefaultBinding;
static void
BindingQuit(int)
{
quitloop();
}
static void
BindingStroke(int e)
{
if (e == BEleave)
{
if (CurrentLayer != nil)
CurrentLayer->changed = 1;
return;
}
stroke();
}
static void
BindingZoomIn(int)
{
zoom(ZoomSensitivity);
}
static void
BindingZoomOut(int)
{
zoom(-ZoomSensitivity);
}
static void
movecanvas(void)
{
CanvasAt = addpt(CanvasAt, subpt(MousePosition, MoveMark));
CanvasMoved = DrawAllLayers = 1;
}
static void
BindingMoveCanvas(int e)
{
static int movetask = -1;
if (e == BEenter)
MoveMark = MousePosition;
else if (e == BEleave) {
CanvasAt = addpt(CanvasAt, subpt(MousePosition, MoveMark));
CanvasMoved = DrawAllLayers = 1;
}
}
static void
BindingClearLayer(int e)
{
if (e != BEenter)
return;
if (CurrentLayer != nil && newlayerimage(CurrentLayer))
sysfatal("newlayerimage: %r");
}
DefaultBinding DefaultBindings[] =
{
{BKeyboard, 'q', nil, BindingQuit},
{BKeyboard, 'c', nil, BindingClearLayer},
{BMouse, 1, nil, BindingStroke},
{BMouse, 8, nil, BindingZoomIn},
{BMouse, 16, nil, BindingZoomOut},
{BMouse, 2, nil, BindingMoveCanvas}
};
void
freebinding(Binding * b)
{
if (b == nil)
return;
if (b->command != nil)
free(b->command);
free(b);
}
int
removebindings(int type, int code)
{
int rc;
Binding * e, * n;
rc = 0;
for (e = BindingRoot; e != nil; e = n) {
if (e->type != type || e->code != code) {
n = e->next;
continue;
}
if (e->prev != nil)
e->prev->next = e->next;
if (e->next != nil)
e->next->prev = e->prev;
n = e->next;
freebinding(e);
if (e == BindingRoot)
BindingRoot = nil;
rc++;
}
return rc;
}
Binding *
addbinding(int type, int code)
{
Binding * b, * e;
if ((b = calloc(sizeof(Binding), 1)) == nil) {
werrstr("failed to allocate Binding");
return nil;
}
b->next = b->prev = nil;
b->type = type;
b->code = code;
b->state = BEleave;
if (BindingRoot != nil) {
for (e = BindingRoot; e->next != nil; e = e->next)
;
e->next = b;
b->prev = e;
} else
BindingRoot = b;
return b;
}
int
runbindings(int type, int code)
{
int rc;
int e;
Binding * b;
// print("handling bindings for %d %d\n", type,code);
rc = 0;
for (b = BindingRoot; b != nil; b = b->next) {
e = BEleave;
if (b->type != type || b->code != code) {
if (b->state == BEleave)
continue;
} else {
switch (b->state) {
case BEenter:
e = BEin;
break;
case BEin:
e = BEin;
break;
case BEleave:
e = BEenter;
break;
default:
werrstr("invalid state");
break;
}
}
b->state = e;
if (b->func != nil)
b->func(e);
if (b->command != nil)
NOOP(); // TODO: Add shell command support
rc++;
}
return rc;
}
Binding *
adduniquebinding(int type, int code)
{
removebindings(type, code);
return addbinding(type, code);
}
void
setdefaultbindings()
{
int i;
Binding * b;
DefaultBinding * db;
for (i = 0; i < ARRLEN(DefaultBindings); i++) {
db = &DefaultBindings[i];
if ((b = addbinding(db->type, db->code)) == nil)
sysfatal("addbinding: %r");
if (db->command != nil)
b->command = strdup(db->command);
if (db->func != nil)
b->func = db->func;
}
}