forked from harrisonpartch/spasim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Inputs.Mod
executable file
·329 lines (276 loc) · 8.1 KB
/
Inputs.Mod
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
(* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
MODULE Inputs; (** AUTHOR "pjm"; PURPOSE "Abstract input device"; *)
(* Based on SemInput.Mod by Marc Frei *)
IMPORT Machine, Kernel, Plugins;
CONST
(** KeyboardMsg flags. *)
Release* = 0; (** a key release event, otherwise a key press or repeat. *)
(** shift key states. *)
LeftShift* = 1; RightShift* = 2; LeftCtrl* = 3; RightCtrl* = 4;
LeftAlt* = 5; RightAlt* = 6; LeftMeta* = 7; RightMeta* = 8;
(** combined shift key states. *)
Shift* = {LeftShift, RightShift}; Ctrl* = {LeftCtrl, RightCtrl};
Alt* = {LeftAlt, RightAlt}; Meta* = {LeftMeta, RightMeta};
(** flags for KeyState *)
SHIFT* = 0; CTRL* = 1; ALT* = 2;
(** keysym values, similar to X11 keysyms *)
KsNil* = 0FFFFFFH; (** no key *)
(** TTY Functions, cleverly chosen to map to ascii *)
KsBackSpace* = 0FF08H; (** back space, back char *)
KsTab* = 0FF09H;
KsReturn* = 0FF0DH; (** Return, enter *)
KsPause* = 0FF13H; (** Pause, hold *)
KsScrollLock* = 0FF14H;
KsSysReq* = 0FF15H;
KsEscape* = 0FF1BH;
KsDelete* = 0FFFFH; (** Delete, rubout *)
(** Cursor control & motion *)
KsHome* = 0FF50H;
KsLeft* = 0FF51H; (** Move left, left arrow *)
KsUp* = 0FF52H; (** Move up, up arrow *)
KsRight* = 0FF53H; (** Move right, right arrow *)
KsDown* = 0FF54H; (** Move down, down arrow *)
KsPageUp* = 0FF55H; (** Prior, previous *)
KsPageDown* = 0FF56H; (** Next *)
KsEnd* = 0FF57H; (** EOL *)
(** Misc Functions *)
KsPrint* = 0FF61H;
KsInsert* = 0FF63H; (** Insert, insert here *)
KsMenu* = 0FF67H; (** Windows menu *)
KsBreak* = 0FF6BH;
KsNumLock* = 0FF7FH;
(** Keypad functions *)
KsKPEnter* = 0FF8DH; (** enter *)
KsKPMultiply* = 0FFAAH;
KsKPAdd* = 0FFABH;
KsKPSubtract* = 0FFADH;
KsKPDecimal* = 0FFAEH;
KsKPDivide* = 0FFAFH;
(** Function keys *)
KsF1* = 0FFBEH; KsF2* = 0FFBFH; KsF3* = 0FFC0H; KsF4* = 0FFC1H; KsF5* = 0FFC2H; KsF6* = 0FFC3H;
KsF7* = 0FFC4H; KsF8* = 0FFC5H; KsF9* = 0FFC6H; KsF10* = 0FFC7H; KsF11* = 0FFC8H; KsF12* = 0FFC9H;
(** Modifiers *)
KsShiftL* = 0FFE1H; (** Left shift *)
KsShiftR* = 0FFE2H; (** Right shift *)
KsControlL* = 0FFE3H; (** Left control *)
KsControlR* = 0FFE4H; (** Right control *)
KsCapsLock* = 0FFE5H; (** Caps lock *)
KsMetaL* = 0FFE7H; (** Left meta, Left Windows *)
KsMetaR* = 0FFE8H; (** Right meta, Right Windows *)
KsAltL* = 0FFE9H; (** Left alt *)
KsAltR* = 0FFEAH; (** Right alt *)
(** HID Consumer Keys**)
KsScanPreviousTrack*= 0FF0000H;
KsScanNextTrack*= 0FF0001H;
KsALConsumerControl*= 0FF0002H;
KsMute*= 0FF0003H;
KsVolumeDecrement*= 0FF0004H;
KsVolumeIncrement*= 0FF0005H;
KsPlayPause*= 0FF0006H;
KsStopOSC*= 0FF0007H;
KsALEmailReader*= 0FF0008H;
KsALCalculator*= 0FF0009H;
KsACSearch*= 0FF000AH;
KsACHome*= 0FF000BH;
KsACBack*= 0FF000CH;
KsACForward*= 0FF000DH;
KsACBookmarks*= 0FF000EH;
KsConsumerButtons*= 0FFF000H;
TYPE
Message* = RECORD END; (** generic message. *)
KeyboardMsg* = RECORD (Message)
ch*: CHAR; (** extended ASCII key code, or 0X if not relevant *)
flags*: SET; (** key flags *)
keysym*: LONGINT (** X11-compatible key code *)
END;
MouseMsg* = RECORD (Message)
keys*: SET; (** mouse key state. *)
dx*, dy*, dz*: LONGINT (** mouse movement vector. *)
END;
AbsMouseMsg*= RECORD(Message);
keys*: SET;
x*,y*,z*,dx*,dy*,dz*: LONGINT;
END;
PointerMsg* = RECORD (Message)
keys*: SET; (** pointer key state. *)
x*, y*, z*: LONGINT; (** pointer position. *)
mx*, my*, mz*: LONGINT (** pointer max values. *)
END;
TYPE
Sink* = OBJECT (** a message receiver. *)
(** Handle is overriden by a concrete receiver. *)
PROCEDURE Handle*(VAR msg: Message);
BEGIN HALT(301) END Handle;
END Sink;
Group* = OBJECT (** a group of message receivers. *)
(** Add a receiver to a group. *)
PROCEDURE Register*(s: Sink);
BEGIN HALT(301) END Register;
(** Remove a receiver from a group. *)
PROCEDURE Unregister*(s: Sink);
BEGIN HALT(301) END Unregister;
(** Send a message to all receivers currently in the group. *)
PROCEDURE Handle*(VAR msg: Message);
BEGIN HALT(301) END Handle;
END Group;
TYPE
Pointer* = OBJECT (Sink) (** convert incremental movements into absolute positions *)
VAR
cur: PointerMsg;
threshold, speedup: LONGINT;
fixedKeys: SET;
PROCEDURE Update;
VAR p: PointerMsg;
BEGIN
IF cur.x < 0 THEN cur.x := 0
ELSIF cur.x > cur.mx THEN cur.x := cur.mx
END;
IF cur.y < 0 THEN cur.y := 0
ELSIF cur.y > cur.my THEN cur.y := cur.my
END;
IF cur.z < 0 THEN cur.z := 0
ELSIF cur.z > cur.mz THEN cur.z := cur.mz
END;
p := cur; p.keys := p.keys + fixedKeys;
pointer.Handle(p)
END Update;
PROCEDURE SetKeys(keys: SET);
BEGIN {EXCLUSIVE}
fixedKeys := keys; Update
END SetKeys;
PROCEDURE Handle*(VAR m: Message);
VAR dx, dy: LONGINT;
BEGIN {EXCLUSIVE}
IF m IS MouseMsg THEN
WITH m: MouseMsg DO
dx := m.dx; dy := m.dy;
IF (ABS(dx) > threshold) OR (ABS(dy) > threshold) THEN
dx := dx*speedup DIV 10; dy := dy*speedup DIV 10
END;
INC(cur.x, dx); INC(cur.y, dy); INC(cur.z, m.dz);
cur.keys := m.keys;
Update;
END;
ELSIF m IS AbsMouseMsg THEN
WITH m: AbsMouseMsg DO
cur.x := m.x; cur.y := m.y; cur.z := m.z;
cur.keys := m.keys;
Update
END;
END
END Handle;
PROCEDURE SetLimits*(mx, my, mz: LONGINT);
BEGIN {EXCLUSIVE}
cur.mx := mx; cur.my := my; cur.mz := mz;
Update
END SetLimits;
PROCEDURE &Init*(t, s: LONGINT);
BEGIN
threshold := t; speedup := s;
cur.x := 0; cur.y := 0; cur.z := 0;
cur.mx := 1; cur.my := 1; cur.mz := 1;
cur.keys := {}; fixedKeys := {};
mouse.Register(SELF)
END Init;
END Pointer;
TYPE
List = POINTER TO RECORD
next: List;
s: Sink
END;
Broadcaster = OBJECT (Group)
VAR sentinel: List;
PROCEDURE Register(s: Sink);
VAR n: List;
BEGIN {EXCLUSIVE}
NEW(n); n.s := s; n.next := sentinel.next; sentinel.next := n
END Register;
PROCEDURE Unregister(s: Sink);
VAR n: List;
BEGIN {EXCLUSIVE}
n := sentinel;
WHILE (n.next # NIL) & (n.next.s # s) DO n := n.next END;
IF n.next # NIL THEN n.next := n.next.next END
END Unregister;
PROCEDURE Handle(VAR msg: Message);
VAR n: List;
BEGIN {EXCLUSIVE}
n := sentinel.next;
WHILE n # NIL DO n.s.Handle(msg); n := n.next END
END Handle;
END Broadcaster;
TYPE
OberonInput* = OBJECT (Plugins.Plugin)
VAR timer-: Kernel.Timer;
PROCEDURE Mouse*(VAR x, y: INTEGER; VAR keys:SET);
BEGIN
HALT(99) (* abstract *)
END Mouse;
PROCEDURE Read*(VAR ch: CHAR; VAR break: BOOLEAN);
BEGIN
HALT(99) (* abstract *)
END Read;
PROCEDURE Available*(VAR num: INTEGER; VAR break: BOOLEAN);
BEGIN
HALT(99) (* abstract *)
END Available;
PROCEDURE KeyState*(VAR k: SET);
BEGIN
HALT(99) (* abstract *)
END KeyState;
PROCEDURE &Init*;
BEGIN
NEW(timer)
END Init;
END OberonInput;
TYPE
MouseFixer = OBJECT (Sink)
VAR ctrl: BOOLEAN;
PROCEDURE Handle(VAR m: Message);
VAR new: BOOLEAN;
BEGIN {EXCLUSIVE}
WITH m: KeyboardMsg DO
new := m.flags * Ctrl # {};
IF new # ctrl THEN
ctrl := new;
IF ctrl THEN main.SetKeys({1}) ELSE main.SetKeys({}) END
END
END
END Handle;
PROCEDURE &Init*;
BEGIN
ctrl := FALSE; keyboard.Register(SELF)
END Init;
END MouseFixer;
VAR
keyboard*, mouse*, pointer*: Group;
main*: Pointer;
oberonInput*: Plugins.Registry;
mouseFixer: MouseFixer;
(** Return a default message broadcaster instance. *)
PROCEDURE NewBroadcaster*(): Group;
VAR b: Broadcaster;
BEGIN
NEW(b); NEW(b.sentinel); b.sentinel.next := NIL;
RETURN b
END NewBroadcaster;
PROCEDURE Init;
VAR s: ARRAY 16 OF CHAR; i, threshold, speedup: LONGINT;
BEGIN
Machine.GetConfig("Threshold", s);
i := 0; threshold := Machine.StrToInt(i, s);
IF threshold <= 0 THEN threshold := 5 END;
Machine.GetConfig("Speedup", s);
i := 0; speedup := Machine.StrToInt(i, s);
IF speedup <= 0 THEN speedup := 15 END;
NEW(main, threshold, speedup);
Machine.GetConfig("MB", s);
IF (s = "2") OR (s = "-2") THEN NEW(mouseFixer) END
END Init;
BEGIN
keyboard := NewBroadcaster();
mouse := NewBroadcaster();
pointer := NewBroadcaster();
NEW(oberonInput, "Inputs", "Oberon input drivers");
Init
END Inputs.