-
Notifications
You must be signed in to change notification settings - Fork 0
/
macroeng.asm
286 lines (219 loc) · 7.9 KB
/
macroeng.asm
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
include stdapp.def ; Standard Geos stuff
include timer.def ; Timer, sleeping etc.
include thread.def
include Objects/inputC.def
include Internal/im.def ; Input Manager internals
include macroeng.def
global _KeyPressed:far
SetGeosConvention ; set calling convention
idata segment
myMonitorData Monitor
myGeodeHandle word ; Geode handle of Monitor application
hotkeyList fptr ; pointer to current hotkey list
defaultHotkey MacroHotkeyList ; default target for key messages
macroMode word MACRO_MODE_NORMAL
idata ends
ASM_FIXED segment resource
assume ds:dgroup ; dgroup loaded on call of MyMonitor
;
; MyMonitor
;
MyMonitor proc far
cmp di,MSG_META_KBD_CHAR
je key_event
nohot_event: ret
; "Pass" mode is only effective for one key
pass_event: mov ds:macroMode,MACRO_MODE_NORMAL
jmp nohot_event
key_event: test dl,mask CF_RELEASE
jnz nohot_event ; not looking for releases of hotkey
cmp ds:macroMode,MACRO_MODE_PASS
je pass_event ; pass key through if requested
push ax,dx,di,es
; convert key to KeyboardShortcut format for convenient
; comparison with table entries
mov ax,cx ; get character
and ax,0fffh ; mask out upper 4 bits of charset
test dh,mask SS_LSHIFT or mask SS_RSHIFT
jz noshift ; both shifts are equal
or ax,mask KS_SHIFT
noshift:
test dh,mask SS_LALT or mask SS_RALT
jz noalt ; both alts are equal
or ax,mask KS_ALT
noalt:
test dh,mask SS_LCTRL or mask SS_RCTRL
jz noctrl ; both ctrls are equal
or ax,mask KS_CTRL
noctrl:
cmp cx, ((CS_CONTROL shl 8) or VC_CAPSLOCK)
jne nocapslock
test bp, mask TS_CAPSLOCK
jz nocapslock
; Mark Capslock enable by setting Ctrl/Alt flags
or ax,mask KS_CTRL or mask KS_ALT
nocapslock:
cmp ds:macroMode,MACRO_MODE_HOTKEY
jne nohotkey
; Ignore Shift,Ctrl keys while waiting for hotkey, to allow
; for combinations
cmp cx, ((CS_CONTROL shl 8) or VC_LCTRL)
stc ; pass Ctrl keys on
je badhotkey_x
cmp cx, ((CS_CONTROL shl 8) or VC_RCTRL)
stc ; pass Ctrl keys on
je badhotkey_x
cmp cx, ((CS_CONTROL shl 8) or VC_LSHIFT)
stc ; pass Ctrl keys on
je badhotkey_x
cmp cx, ((CS_CONTROL shl 8) or VC_RSHIFT)
stc ; pass Ctrl keys on
je badhotkey_x
; Hotkey handling
; Hotkey mode is only active for one key
mov ds:macroMode,MACRO_MODE_NORMAL
test {word}ds:hotkeyList+2,0ffffh
clc
jz badhotkey ; no hotkey list: don't scan
; start scanning from start of hotkey list
les di,ds:hotkeyList
jmp start_scan
hotkey_scan: cmp es:[di].MHL_keyboardShortcut,ax
clc ; don't pass on hotkeys to app
je hotkey_found
; advance to next entry in list
add di,size MacroHotkeyList
start_scan: cmp es:[di].MHL_keyboardShortcut,0
jne hotkey_scan ; not reached end of list: continue
clc ; don't pass on key anyway
badhotkey_x: jmp badhotkey
nohotkey:
; in "absorb" mode, send message, but don't pass on or
; interpret hotkeys
cmp ds:macroMode,MACRO_MODE_ABSORB
jne noabsorb
clc ; Do not pass on
jmp absorb_key
noabsorb: cmp ax,(((CS_UI_FUNCS and 15) shl 8) or UC_ZOOM)
jne no_zoom
mov ds:macroMode,MACRO_MODE_HOTKEY
clc
jmp badhotkey
no_zoom:
cmp ax,(((CS_UI_FUNCS and 15) shl 8) or UC_BACKLIGHT)
jne no_backlight
mov ds:macroMode,MACRO_MODE_PASS
clc
jmp badhotkey
no_backlight:
stc ; don't kill non-hotkeys
absorb_key: push ds
pop es
mov di,offset defaultHotkey
; found hotkey: send message to destination
hotkey_found: pushf
push bx,cx,si,bp
mov bp,ax ; bp: KeyboardShortcut
call TimerGetCount
mov cx,bx
mov dx,ax
mov ax,es:[di].MHL_message
mov si,{word}es:[di].MHL_destination
mov bx,{word}es:[di].MHL_destination+2
mov di,0 ; MessageFlags
call ObjMessage
; For fast reactions...
push bp
call _KeyPressed
add sp,2
pop bx,cx,si,bp
popf
badhotkey: pop ax,dx,di,es
jc nokill
push ax
mov ax, SST_KEY_CLICK
call UserStandardSound
pop ax
xor al,al ; kill message
nokill: ret
MyMonitor endp
ASM_FIXED ends
MACROENG_TEXT segment resource
;------------------------------------------------------------------------------
; void _pascal MacroInit(void);
;------------------------------------------------------------------------------
global MACROINIT:far
MACROINIT proc far
uses bp
.enter
call GeodeGetProcessHandle
mov ds:myGeodeHandle,bx
mov al,ML_DRIVER+1
mov bx,offset myMonitorData
mov cx,segment MyMonitor
mov dx,offset MyMonitor
call ImAddMonitor
.leave
ret
MACROINIT endp
;------------------------------------------------------------------------------
; void _pascal MacroDeinit(void);
;------------------------------------------------------------------------------
global MACRODEINIT:far
MACRODEINIT proc far
.enter
mov al,mask MF_REMOVE_IMMEDIATE
mov bx,offset myMonitorData
call ImRemoveMonitor
.leave
ret
MACRODEINIT endp
;------------------------------------------------------------------------------
; void _pascal MacroSetHotkeys(MacroHotkeyList *hot, optr target, word msg);
;------------------------------------------------------------------------------
global MACROSETHOTKEYS:far
MACROSETHOTKEYS proc far _hot:fptr, _target:dword, _msg:word
.enter
; store new hotkey list
mov ax,{word}_hot
mov dx,{word}_hot+2
mov {word}ds:hotkeyList,ax
mov {word}ds:hotkeyList+2,dx
; store new default message
mov ax,{word}_target
mov ds:{word}defaultHotkey.MHL_destination,ax
mov ax,{word}_target+2
mov ds:{word}defaultHotkey.MHL_destination+2,ax
mov ax,_msg
mov ds:defaultHotkey.MHL_message,ax
.leave
ret
MACROSETHOTKEYS endp
;------------------------------------------------------------------------------
; void _pascal MacroSetAbsorbMode(Boolean enable);
;------------------------------------------------------------------------------
global MACROSETABSORBMODE:far
MACROSETABSORBMODE proc far _enable:word
.enter
; store new key mode
test _enable,0ffffh
jnz do_absorb
mov ax,MACRO_MODE_NORMAL
jmp set_mode
do_absorb: mov ax,MACRO_MODE_ABSORB
set_mode: mov ds:macroMode,ax
.leave
ret
MACROSETABSORBMODE endp
;------------------------------------------------------------------------------
; word _pascal MacroGetInputProcess(void);
;------------------------------------------------------------------------------
global MACROGETINPUTPROCESS:far
MACROGETINPUTPROCESS proc far
.enter
call ImInfoInputProcess ; returns: bx <- process handle
mov ax,bx
.leave
ret
MACROGETINPUTPROCESS endp
MACROENG_TEXT ends