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
|
implement Devpointer;
include "sys.m";
sys: Sys;
include "draw.m";
Pointer: import Draw;
include "devpointer.m";
init()
{
sys = load Sys Sys->PATH;
}
reader(file: string, posn: chan of ref Pointer, pid: chan of (int, string))
{
if(file == nil)
file = "/dev/pointer";
dfd := sys->open(file, sys->OREAD);
if(dfd == nil){
if(pid != nil){
pid <-= (-1, sys->sprint("cannot open %s: %r", file));
return;
}
}
if(pid != nil)
pid <-= (sys->pctl(0, nil), nil);
b:= array[Size] of byte;
while((n := sys->read(dfd, b, len b)) == Size)
posn <-= bytes2ptr(b);
}
bytes2ptr(b: array of byte): ref Pointer
{
if(len b < Size || int b[0] != 'm')
return nil;
x := int string b[1:13];
y := int string b[13:25];
but := int string b[25:37];
msec := int string b[37:49];
return ref Pointer (but, (x, y), msec);
}
ptr2bytes(p: ref Pointer): array of byte
{
if(p == nil)
return nil;
return sys->aprint("m%11d %11d %11d %11ud ", p.xy.x, p.xy.y, p.buttons, p.msec);
}
srv(c: chan of ref Pointer, f: ref Sys->FileIO)
{
ptrq := ref Ptrqueue;
dummy := chan of (int, int, int, Sys->Rread);
sys = load Sys Sys->PATH;
for(;;){
r := dummy;
if(ptrq.nonempty())
r = f.read;
alt{
p := <-c =>
if(p == nil)
exit;
ptrq.put(p);
(nil, n, nil, rc) := <-r =>
if(rc != nil){
alt{
rc <-= (ptr2bytes(ptrq.get()), nil) =>;
* =>;
}
}
(nil, nil, nil, rc) := <-f.write =>
if(rc != nil)
rc <-= (0, "read only");
}
}
}
Ptrqueue.put(q: self ref Ptrqueue, s: ref Pointer)
{
if(q.last != nil && s.buttons == q.last.buttons)
*q.last = *s;
else{
q.t = s :: q.t;
q.last = s;
}
}
Ptrqueue.get(q: self ref Ptrqueue): ref Pointer
{
s: ref Pointer;
h := q.h;
if(h == nil){
for(t := q.t; t != nil; t = tl t)
h = hd t :: h;
q.t = nil;
}
if(h != nil){
s = hd h;
h = tl h;
if(h == nil)
q.last = nil;
}
q.h = h;
return s;
}
Ptrqueue.peek(q: self ref Ptrqueue): ref Pointer
{
s: ref Pointer;
if (q.h == nil && q.t == nil)
return s;
t := q.last;
s = q.get();
q.h = s :: q.h;
q.last = t;
return s;
}
Ptrqueue.nonempty(q: self ref Ptrqueue): int
{
return q.h != nil || q.t != nil;
}
|