ref: 0cd1f6455c02fe0c2ade3e630debb315f054b253
dir: /bindings.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#include "dat.h"
#include "fns.h"
Binding * BindingRoot = nil;
typedef struct DefaultBinding
{
int type;
int code;
char * command;
void (*func)(int);
} DefaultBinding;
// made with
// grep '^Binding[a-zA-Z][a-zA-Z]*' bindings.c | sed 's/^(.*)$/static void \1;/g'
static void BindingQuit(int);
static void BindingStroke(int e);
static void BindingZoomIn(int);
static void BindingZoomOut(int);
static void BindingMoveCanvas(int e);
static void BindingMoveLayer(int e);
static void BindingClearLayer(int e);
static void BindingSwitchMode(int);
static void BindingResetCanvas(int);
static void BindingResetCurrentLayer(int);
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
BindingMoveCanvas(int e)
{
static Point MoveMark = {0};
static int movetask = -1;
if (e == BEenter)
MoveMark = MousePosition;
else if (e == BEleave) {
CanvasAt = addpt(CanvasAt, subpt(MousePosition, MoveMark));
CanvasMoved = DrawAllLayers = 1;
}
}
static void
BindingMoveLayer(int e)
{
static Point MoveMark = {0};
static int movetask = -1;
if (e == BEenter)
MoveMark = MousePosition;
else if (e == BEleave && CurrentLayer != nil) {
CurrentLayer->offset = addpt(CurrentLayer->offset,
subpt(MoveMark, MousePosition));
CurrentLayer->changed = 1;
clearview();
}
}
static void
BindingClearLayer(int)
{
if (CurrentLayer != nil && newlayerimage(CurrentLayer))
sysfatal("newlayerimage: %r");
clearview();
}
static void
BindingSwitchMode(int)
{
static int mode = 0;
Binding * bm, * br;
char * s;
removebindings(BMouse, 2);
removebindings(BKeyboard, 'r');
if ((bm = addbinding(BMouse, 2)) == nil)
sysfatal("addbinding: %r");
if ((br = addbinding(BKeyboard, 'r')) == nil)
sysfatal("addbinding: %r");
s = "";
switch(mode)
{
case 0:
bm->func = BindingMoveLayer;
br->func = BindingResetCurrentLayer;
s = "layer";
mode = 1;
break;
case 1:
bm->func = BindingMoveCanvas;
br->func = BindingResetCanvas;
s = "canvas";
mode = 0;
break;
}
ntfprint("changed to %s mode\n", s);
}
static void
BindingResetCanvas(int)
{
TargetZoom = 1;
applyzoom();
CanvasAt = Pt(0, 0);
centercanvas();
}
static void
BindingResetCurrentLayer(int)
{
if (CurrentLayer == nil)
return;
CurrentLayer->offset = Pt(0, 0);
clearview();
}
static void
BindingNewLayer(int)
{
newlayer();
}
static void
BindingNextLayer(int)
{
setcurrentlayer(CurrentLayer->next);
}
static void
BindingPreviousLayer(int)
{
setcurrentlayer(CurrentLayer->prev);
}
static void
BindingDeleteCurrentLayer(int)
{
ntfprint("not yet implemented");
}
static void
BindingSave(int)
{
int fd;
char s[32];
snprint(s, 32, "/tmp/pain.XXXXXX");
mktemp(s);
fd = create(s, OWRITE, 0755);
if (fd < 0) {
ntfprint("failed to save image to %s", s);
}
writeimage(fd, ViewImage, 0);
close(fd);
ntfprint("current canvas saved to %s", s);
}
DefaultBinding DefaultBindings[] =
{
{BKeyboard, 'q', nil, BindingQuit},
{BKeyboard, 'c', nil, BindingClearLayer},
{BKeyboard, 'm', nil, BindingSwitchMode},
{BKeyboard, 'r', nil, BindingResetCanvas},
{BKeyboard, 'n', nil, BindingNewLayer},
{BKeyboard, 'd', nil, BindingDeleteCurrentLayer},
{BKeyboard, 'o', nil, BindingPreviousLayer},
{BKeyboard, 'p', nil, BindingNextLayer},
{BKeyboard, 's', nil, BindingSave},
{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 = e->next;
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) {
if (b->type != type)
continue;
e = b->type == BKeyboard ? BEenter : BEleave;
if (b->code != code) {
if (b->state == BEleave || b->type == BKeyboard)
continue;
} else if(b->type == BMouse) {
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;
}
}