This repository was archived by the owner on Oct 11, 2022. It is now read-only.
forked from nickelsworth/swag
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path0019.pas
More file actions
188 lines (156 loc) · 6.16 KB
/
Copy path0019.pas
File metadata and controls
188 lines (156 loc) · 6.16 KB
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
{ Rodent unit v1.3 OooO } { << isn't he cute? } { 09/01/93 \/ }
{ Interrupt-style interface for Microsoft mouse, Turbo Pascal 6.0+}
{ by Sean L. Palmer }
{ Released to the Public Domain }
{ Please credit me if your program uses these routines! }
unit Rodent;
{$A-,B-,D-,E-,F-,G+,I-,L-,N-,O-,R-,S-,V-,X+}
{make sure you alloc enough stack space in main program!} {as written, requires a 286+ and that the mouse exists}
interface
const
x :integer=0; y :integer=0; {current mouse pos}
xs:integer=0; ys:integer=0; {mickey counts}
left=1; center=2; right=4; {button masks- (btn and left)<>0 if left button
down}
b:boolean=false; {button status, true if any button down} var
btn:byte absolute b; {button status, mask with (btn and mask)<>0 to
get a specific button}
hidden:boolean;
type
pMouseHook=^tMouseHook;
tMouseHook=procedure;
{avoid calling dos, bios, and mouse routines from these if possible}
function erasHook(h:tMouseHook):pMouseHook;
function moveHook(h:tMouseHook):pMouseHook;
function drawHook(h:tMouseHook):pMouseHook; {change out handlers}
function clikHook(h:tMouseHook):pMouseHook;
function liftHook(h:tMouseHook):pMouseHook;
procedure show(f:boolean); {true=show}
procedure confine(l,t,r,b:integer); {set min,max bounds}
procedure moveTo(h,v:integer);
procedure setSpeed(xs,ys,thr:word); {set x,y pix per 16 mickeys, double speed threshold}
implementation
{This unit should work in any mode, but you need to provide the routines
to draw and erase the cursor.}
{note: reason coords are scaled *8 throughout is because mouse driver}
{stupidly messes with the values differently in different modes.}
{This is just a work-around so it won't be limited to every eighth column
or row in text modes.}
{PS: be very careful using mickey counts in DI & SI in event handler.}
var
hideCount:byte absolute hidden;
{this procedure does nothing, used to disable an event} procedure defaultMouseHook;far;assembler;asm end;
{must save previous setting of I-flag}
procedure clearInts;inline($9C/$FA); {pushF;cli} procedure restoreInts;inline($9D); {popF}
const
vDrawHook:tMouseHook=defaultMouseHook; {pre-set all hooks to do nothing}
vErasHook:tMouseHook=defaultMouseHook;
vMoveHook:tMouseHook=defaultMouseHook;
vClikHook:tMouseHook=defaultMouseHook;
vLiftHook:tMouseHook=defaultMouseHook;
{these all both set a hook to a procedure you provide, and also return
the old hook so you can later restore it} {Use something like:}
{var savedClikHook:tMouseHook;}
{...}
{@savedClikHook:=clikHook(myClikHook);}
{...}
{clikHook(savedClikHook)}
function drawHook(h:tMouseHook):pMouseHook;begin
drawHook:=@vDrawHook; clearInts; vDrawHook:=h; restoreInts;
end;
function erasHook(h:tMouseHook):pMouseHook;begin
erasHook:=@vErasHook; clearInts; vErasHook:=h; restoreInts;
end;
function moveHook(h:tMouseHook):pMouseHook;begin
moveHook:=@vMoveHook; clearInts; vMoveHook:=h; restoreInts;
end;
function clikHook(h:tMouseHook):pMouseHook;begin
clikHook:=@vclikHook; clearInts; vClikHook:=h; restoreInts;
end;
function liftHook(h:tMouseHook):pMouseHook;begin
liftHook:=@vLiftHook; clearInts; vLiftHook:=h; restoreInts;
end;
{here is the callback function for the mouse driver}
{calling regs:}
{ax:triggering event bit mask}
{bx:button status bit mask (bit 0=left,1=center,2=right)}
{cx:mouse X/bit 7 is sign for di,bit 0 always=0}
{dx:mouse Y/bit 7 is sign for si}
{di:abs mouse Delta X}
{si:abs mouse Delta Y}
{bits in event mask:}
{0:move}
{1:left btn down}
{2:left btn up}
{3,4:center btn}
{5,6:right btn}
{This code is real easy to break, be careful!} procedure doMouseHook;far;assembler;asm
push ax; mov ax,seg @DATA; mov ds,ax; pop ax;
mov xs,si; mov ys,di; {disregard di,si mickey counts}
mov btn,bl;
and cx,$3FFF; shr cx,3; and dx,$3FFF; shr dx,3; {strip hi bits}
push ax; push cx; push dx; {save event status}
test hidden,$FF; jnz @NOERAS; call vErasHook; @NOERAS:
pop dx; mov y,dx; pop cx; mov x,cx;
call vMoveHook; {always assume mouse has moved, disregard bit 0 of ax}
test hidden,$FF; jnz @NODRAW; call vDrawHook; @NODRAW:
pop ax; {restore event status}
@CLIK: test al,00101010b; jz @LIFT; {check any button clik flag}
push ax; call vClikHook; pop ax;
@LIFT: test al,01010100b; jz @EXIT; {check any button lift flag}
call vLiftHook;
@EXIT:
end;
procedure show(f:boolean);begin
clearInts;
if f then begin
if hidden then begin dec(hideCount); if not hidden then vDrawHook; end;
end
else begin if not hidden then vErasHook; inc(hideCount); end;
restoreInts;
end;
Procedure confine(l,t,r,b:integer);assembler;asm
mov ax,7; mov cx,l; shl cx,3; mov dx,r; shl dx,3; int $33;
mov ax,8; mov cx,t; shl cx,3; mov dx,b; shl dx,3; int $33;
end;
procedure moveTo(h,v:integer);begin
if not hidden then vErasHook;
asm mov cx,h; mov x,cx; shl cx,3;
mov dx,v; mov y,dx; shl dx,3;
mov ax,4; int $33; end;
if not hidden then vDrawHook;
end;
procedure setSpeed(xs,ys,thr:word);assembler;asm
mov ax,$1A; mov bx,xs; shl bx,3; mov cx,ys; shl cx,3; mov dx,thr; int $33;
end;
var
oldMouseHook:pointer;
oldEventMask:word;
procedure removeMouse;begin
if not hidden then show(false);
asm les dx,oldMouseHook; mov cx,oldEventMask; mov ax,$C; int $33;end;
end;
var
mouseHook:pointer absolute 0:$33*4;
const
eventMask=$7F; {all events}
function exists:boolean;assembler;asm
xor ax,ax; mov es,ax; {get ready to check interrupt vector for nil}
mov bx,es:[$33*4]; or bx,es:[$33*4+2]; jz @X; {no}
{ax still 0} int $33; @X: {result in al}
end;
begin
if exists then begin
setSpeed(32,64,4); {set up a natural-feeling speed for 640x480}
moveTo(0,0); confine(0,0,0,0); {trap the little sucker}
hideCount:=1;
asm
push cs; pop es; mov dx,offset doMouseHook; {loc of callback function}
mov cx,eventMask; mov ax,$14; int $33; {enable event callbacks}
mov oldEventMask,cx;
mov word ptr oldMouseHook,dx; mov word ptr oldMouseHook+2,es;
end;
end
else begin writeln('Need mouse.'); halt(1);end;
end.