1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
#include "wily.h"
#include "view.h"
#include <ctype.h>
static void b2 (View *, Range, Bool);
static void dobutton (View *, Mouse *);
static void doscroll (View *, Mouse *);
static void action (View *, Mouse *, Range, ulong);
/* PRE: a mouse button is down
* POST: no mouse buttons down, we've probably done something.
*/
void
domouse(View *v, Mouse *m) {
assert(m->buttons);
if ( POINTINSCROLL(m->xy, v) ) {
if(v->scroll)
doscroll(v,m);
else
dobutton(v, m);
} else {
ulong oldbuttons = m->buttons;
Range r = vselect(v, m);
action(v, m, r, oldbuttons);
}
}
/******************************************************
static functions
******************************************************/
static void
dobutton(View *v, Mouse *orig) {
Mouse m;
Tile *tile = view_tile(v);
assert(ISTAG(v));
assert(orig->buttons);
if(tile == wily) /* can't move the main window this way */
return;
/* swap cursor, follow mouse until button state changes */
cursorswitch(&boxcursor);
do {
m = emouse();
} while(m.buttons == orig->buttons);
cursorswitch(cursor);
/* aborted by pressing a different button? */
if(m.buttons)
return;
if (distance(m.xy, orig->xy) < SMALLDISTANCE) {
tile_grow(tile, orig->buttons);
cursorset(buttonpos(tile));
} else
tile_move(tile, m.xy);
}
/*
* Some builtins should always be applied to the window where
* you clicked button 2.
*/
static char *locals[] = {"Look", "Put", "Get", "Undo", "Redo", 0};
static Bool
islocal(char *s) {
char **ptr;
for (ptr =locals; *ptr; ptr++)
if (!strncmp(s, *ptr, strlen(*ptr)))
return true;
return false;
}
/* clicked button 2 in 'v' selecting 'r'. 'ischord' is true
* if we also clicked button 1.
*/
static void
b2(View *v, Range r, Bool ischord) {
char *cmd,*arg;
View *ls = last_selection;
r = view_expand(v, r, notcommand);
if(!RLEN(r))
return;
cmd = text_duputf(v->t, r);
if(ischord && ls) {
Range rarg;
rarg = view_expand(ls, ls->sel, notfilename);
arg = text_duputf(ls->t, rarg);
/* use arg for context-- with some exceptions */
if(!islocal(cmd))
v = ls;
} else
arg = 0;
if (!data_sendexec(view_data(v),cmd, arg))
run(v, cmd, arg);
free(cmd);
if(arg)
free(arg);
}
/*
* Currently mouse is like 'm', originally we had 'oldbuttons'. When
* we're finished, v's display should be correct, and no mouse buttons
* should be down.
*/
static void
action(View *v, Mouse *m, Range r, ulong oldbuttons) {
/* mouse button state has changed, possibly do something */
assert(m->buttons != oldbuttons);
if (oldbuttons&LEFT) {
enum {Cancut = 1, Canpaste = 2} state = Cancut | Canpaste;
while(m->buttons) {
if(m->buttons&MIDDLE) {
if (state&Cancut) {
view_cut(v, v->sel);
state = Canpaste;
}
} else if ( m->buttons&RIGHT) {
if (state&Canpaste) {
view_paste(v);
state = Cancut;
}
}
*m = emouse();
}
} else if (oldbuttons & MIDDLE) {
if(m->buttons) {
if(m->buttons&LEFT) /* chord */
b2(v,r,true);
while (m->buttons) /* wait for button up */
*m = emouse();
} else {
b2(v,r,false);
}
} else {
assert((oldbuttons&RIGHT));
if(m->buttons) /* cancelled a b3 */
while (m->buttons)
*m = emouse();
else
b3(v, r);
}
}
/* PRE: 'e' a mouse event in 'v', but not in v's frame, so probably in
* the scrollbar. 'v' is a body frame.
* POST: we've tracked the mouse until all the buttons are down,
* and have scrolled if we should have.
*/
static void
doscroll(View *v, Mouse *m ) {
ulong buttons;
ulong timer;
ulong type;
int delay = DOUBLECLICK / SCROLLTIME;
Bool firstmouse;
Event e;
assert(ptinrect(m->xy, v->r));
assert(v->scroll);
buttons = m->buttons;
assert(buttons);
type = Emouse;
firstmouse = true;
e.mouse = *m;
m = &e.mouse;
/* start waiting for timer events */
timer = etimer(0, SCROLLTIME);
do {
assert(type== timer || type == Emouse);
if(type==Emouse) {
if (firstmouse) {
firstmouse = false;
view_scroll(v, m);
}
} else {
if(delay)
delay--;
else
view_scroll(v, m);
}
type = eread(Emouse|timer,&e);
} while (!(type ==Emouse && m->buttons != buttons));
estoptimer(timer);
/* stop the timer */
/* wait for buttons up */
while (m->buttons)
eread(Emouse, &e);
}
|