home *** CD-ROM | disk | FTP | other *** search
- ***************************************************
- * CapsLockExtender *
- * by Douglas Nelson *
- * *
- * Assemble with Macro68 *
- * *
- * To make the executable small, this uses (x,A4) *
- * addressing and byte branches where possible. *
- * Executable size is 1265 bytes. *
- ***************************************************
-
-
- strict
- exeobj
- errfile ram:assem.output
- objfile ram:CLE
- listfile ram:listfile
- incpath mac:includes
- incpath ram:includes
- macfile alllibraryoffsets.i
- macfile exec/alerts.i
- macfile workbench/workbench.i
- macfile workbench/startup.i
- macfile devices/inputevent.i
- macfile libraries/commodities.i
- macfile dos/dosextens.i
-
- libcall macro
- jsr (_LVO\1,a6)
- endm
-
- * 2.0 startups are so easy, what with ReadArgs and all
- lea (dt,pc),a4
- move.l sp,(stackptr-dt,a4)
- move.l d0,d7 ;store dosCmdLen
- movea.l (4).w,a6
- move.l a6,(execbase-dt,a4)
-
- * open dos
- lea (dosname-dt,a4),a1
- move.l #37,d0
- libcall OpenLibrary
- move.l d0,(dosbase-dt,a4)
- bne.b gotdos
- move.l #AG_OpenLib!AO_DOSLib,d7
- libcall Alert
- failexit tst.l d7
- bne.b fail2
- bsr.b getWbMsg
- bsr.b replyWbMsg
- fail2 moveq #20,d0 ;FAIL
- rts
-
- exit movea.l (execbase-dt,a4),a6
- movea.l (dosbase-dt,a4),a1
- libcall CloseLibrary
- tst.l (WBenchMsg-dt,a4)
- beq.b exit2
- bsr.b replyWbMsg
- exit2 move.l (rc-dt,a4),d0
-
- movea.l (stackptr-dt,a4),sp
- rts
-
- * the next two subroutines here appear to allow byte branches
-
- replyWbMsg movea.l (execbase-dt,a4),a6
- libcall Forbid
- movea.l (WBenchMsg-dt,a4),a1
- libcall ReplyMsg
- rts
-
- getWbMsg suba.l a1,a1
- libcall FindTask
- movea.l d0,a5
- lea (pr_MsgPort,a5),a0
- libcall WaitPort
- lea (pr_MsgPort,a5),a0
- libcall GetMsg
- move.l d0,(WBenchMsg-dt,a4)
- rts
-
- gotdos move.l #10,(rc-dt,a4) ;ERROR for early exit
- tst.l d7 ;dosCmdLen
- beq.b WBstart
-
- * read command line
- lea (template-dt,a4),a0
- move.l a0,d1
- lea (priority-dt,a4),a0
- move.l a0,d2
- moveq #0,d3 ;no optional RdArgs
- movea.l (dosbase-dt,a4),a6
- libcall ReadArgs
- move.l d0,d1
- libcall FreeArgs
- tst.l (priority-dt,a4)
- beq main
- movea.l (priority-dt,a4),a0 ;priority is ptr to value
- move.l (a0),(priority-dt,a4) ;put value in priority
-
- bra main
-
- WBstart
- bsr.b getWbMsg
- * read WBArgs
- movea.l d0,a2
- movea.l (sm_ArgList,a2),a2
- move.l (wa_Lock,a2),d1
- movea.l (dosbase),a6
- libcall CurrentDir
- move.l d0,d7 ;store old dir
-
- * open icon.library
- lea (iconname-dt,a4),a1
- move.l #37,d0
- movea.l (execbase-dt,a4),a6
- libcall OpenLibrary
- move.l d0,(iconbase-dt,a4)
- beq.b endicon
-
- *read ToolTypes
- movea.l d0,a6
- movea.l (wa_Name,a2),a0
- libcall GetDiskObject
- tst.l d0
- beq.b closeicon
- movea.l d0,a2
- movea.l (do_ToolTypes,a2),a0
- lea (priorityname-dt,a4),a1
- libcall FindToolType ;returns ptr to digits
- move.l d0,d1
- beq.b checkNKP ;no CX_PRIORITY
- lea (priority-dt,a4),a0
- move.l a0,d2
- movea.l (dosbase-dt,a4),a6
- libcall StrToLong ;sets priority
-
- checkNKP movea.l (do_ToolTypes,a2),a0
- lea (nokeypadname-dt,a4),a1
- movea.l (iconbase-dt,a4),a6
- libcall FindToolType
- tst.l d0
- beq.b checkhot ;no NOKEYPAD
- move.l #1,(nokeypad-dt,a4)
-
- checkhot movea.l (do_ToolTypes,a2),a0
- lea (hotname-dt,a4),a1
- movea.l (iconbase-dt,a4),a6
- libcall FindToolType
- tst.l d0
- beq.b freediskobj ;no HOT
- move.l #1,(hot-dt,a4)
-
- freediskobj
- movea.l (iconbase-dt,a4),a6
- movea.l a2,a0
- libcall FreeDiskObject
-
- closeicon movea.l (iconbase-dt,a4),a1
- movea.l (execbase-dt,a4),a6
- libcall CloseLibrary
-
- * restore old dir
- endicon move.l d7,d1
- movea.l (dosbase),a6
- libcall CurrentDir
-
-
- main
- * open commodities.library
- lea (cxname-dt,a4),a1
- move.l #37,d0
- movea.l (execbase-dt,a4),a6
- libcall OpenLibrary
- move.l d0,(cxbase-dt,a4)
- beq exit
-
- * create MsgPort for broker
- gotcx libcall CreateMsgPort
- move.l d0,(brokerport-dt,a4)
- beq cleanup
-
- * put priority in NewBroker
- * priority must be longword for ReadArgs, but nb_Priority is a byte
- move.b (priority+3-dt,a4),(nbpriority-dt,a4)
-
- * create broker
- lea (brokererror-dt,a4),a0
- move.l a0,d0
- lea (newbroker-dt,a4),a0
- movea.l (cxbase-dt,a4),a6
- libcall CxBroker
- move.l d0,(broker-dt,a4)
- beq cleanup
-
- * create null FILTER CxObj
- moveq #CX_FILTER,d0
- suba.l a0,a0
- suba.l a1,a1
- libcall CreateCxObj
- move.l d0,(filterobj-dt,a4)
- beq cleanup
-
- * set FILTER to our InputXpression
- movea.l d0,a0
- tst.l (nokeypad-dt,a4)
- bne.b setNKPix
- lea (ix-dt,a4),a1
- bra.b setfilter
- setNKPix lea (NKPix-dt,a4),a1
- setfilter libcall SetFilterIX
- tst.l d0
- beq cleanup
-
- * create CUSTOM CxObj
- moveq #CX_CUSTOM,d0
- tst.l (hot-dt,a4)
- bne.b setHOTfunc
- lea (defaultfunc-dt,a4),a0
- bra.b makecustom
- setHOTfunc lea (hotfunc-dt,a4),a0
- makecustom movea.l #1,a1 ;id
- libcall CreateCxObj
- move.l d0,(customobj-dt,a4)
- beq cleanup
-
- * link CxObjs to broker
- movea.l (broker-dt,a4),a0
- movea.l (filterobj-dt,a4),a1
- libcall AttachCxObj
- movea.l (filterobj-dt,a4),a0
- movea.l (customobj-dt,a4),a1
- libcall AttachCxObj
-
- * activate broker
- movea.l (broker-dt,a4),a0
- moveq #1,d0
- libcall ActivateCxObj
-
- * cleared all obstacles, so set rc to SUCCESS
- move.l #0,(rc-dt,a4)
-
- * make waitmask
- movea.l (brokerport-dt,a4),a0
- moveq #0,d0
- move.b (MP_SIGBIT,a0),d0
- moveq #1,d7
- lsl.l d0,d7 ;port signal
- ori.w #(1<<$E)!(1<<$C),d7 ;CTRL-E or CTRL-C
-
- * wait for signal
- waitloop move.l d7,d0
- movea.l (execbase-dt,a4),a6
- libcall Wait
- andi.l #(1<<$C)!(1<<$E),d0
- bne cleanup
-
- * not CTRL-C or CTRL-E so must be portsignal
- getmsgloop movea.l (execbase-dt,a4),a6
- movea.l (brokerport-dt,a4),a0
- libcall GetMsg
- tst.l d0 ;another Message?
- beq.b waitloop
- movea.l d0,a5 ;store Message ptr
-
- * check Message type
- movea.l d0,a0
- movea.l (cxbase-dt,a4),a6
- libcall CxMsgType
- cmpi.l #CXM_COMMAND,d0
- bne.b replymsg ;unknown msg
-
- * respond to command
- movea.l a5,a0
- libcall CxMsgID
- disable cmpi.l #CXCMD_DISABLE,d0
- bne.b enable
- movea.l (broker-dt,a4),a0
- moveq #0,d0 ;disable code
- libcall ActivateCxObj
- bra.b replymsg
-
- enable cmpi.l #CXCMD_ENABLE,d0
- bne.b kill
- movea.l (broker-dt,a4),a0
- moveq #1,d0 ;enable code
- libcall ActivateCxObj
- bra.b replymsg
-
- kill cmpi.l #CXCMD_KILL,d0
- bne.b unique
- gotkill movea.l a5,a1
- movea.l (execbase-dt,a4),a6
- libcall ReplyMsg
- bra cleanup
-
- unique cmpi.l #CXCMD_UNIQUE,d0
- bne.b replymsg
- bra.b gotkill
-
- replymsg movea.l a5,a1
- movea.l (execbase-dt,a4),a6
- libcall ReplyMsg
- bra getmsgloop
-
- cleanup move.l (broker-dt,a4),d0
- beq.b deleteport
- movea.l d0,a0
- movea.l (cxbase-dt,a4),a6
- libcall DeleteCxObjAll ;delete CxObjs
-
- deleteport tst.l (brokerport-dt,a4)
- beq.b closecx
- clearmsg movea.l (execbase-dt,a4),a6
- movea.l (brokerport-dt,a4),a0
- libcall GetMsg
- tst.l d0 ;another Message?
- beq.b nomsgs
- movea.l d0,a1
- libcall ReplyMsg
- bra.b clearmsg
-
- nomsgs movea.l (brokerport-dt,a4),a0
- libcall DeleteMsgPort
-
- closecx movea.l (execbase-dt,a4),a6
- movea.l (cxbase-dt,a4),a1
- libcall CloseLibrary
- bra exit
-
- * Here are the two CUSTOM CxObj functions. Since they are called from
- * commodities.library, they cannot use (x,A4) addressing.
-
- * An oddity: Under 2.04 the function need not save a6 if all input comes
- * from the keyboard. However, if another program is simulating keypresses
- * by writing to input.device, then the system will crash if a6 is not saved.
-
- defaultfunc pushm d0/a0/a6
- movea.l (16,sp),a0 ;CxMsg ptr is on stack
- movea.l (cxbase,pc),a6
- libcall CxMsgData ;get input event
- movea.l d0,a0
- move.w (ie_Qualifier,a0),d0
- andi.w #IEQUALIFIER_LSHIFT!IEQUALIFIER_RSHIFT,d0
- bne.b cancel1
- ori.w #IEQUALIFIER_LSHIFT,(ie_Qualifier,a0) ;add SHIFT
- bra.b enddefaultfunc
-
- cancel1 andi.w #~(IEQUALIFIER_LSHIFT!IEQUALIFIER_RSHIFT!IEQUALIFIER_CAPSLOCK),(ie_Qualifier,a0)
- * this clears the Shift and CapsLock bits
-
- enddefaultfunc
- popm d0/a0/a6
- rts
-
- hotfunc pushm d0/a0/a6
- movea.l (16,sp),a0 ;CxMsg ptr is on stack
- movea.l (cxbase,pc),a6
- libcall CxMsgData ;get input event
- movea.l d0,a0
- move.w (ie_Qualifier,a0),d0
- andi.w #IEQUALIFIER_LSHIFT!IEQUALIFIER_RSHIFT,d0
- bne.b cancel2
- ori.w #IEQUALIFIER_LSHIFT,(ie_Qualifier,a0) ;add SHIFT
- andi.w #~IEQUALIFIER_CAPSLOCK,(ie_Qualifier,a0) ;delete CAPSLOCK
- bra.b endhotfunc
-
- cancel2 andi.w #~(IEQUALIFIER_LSHIFT!IEQUALIFIER_RSHIFT!IEQUALIFIER_CAPSLOCK),(ie_Qualifier,a0)
- * this clears the Shift and CapsLock bits
-
- endhotfunc popm d0/a0/a6
- rts
-
- dt quad
- execbase dl 0
- dosbase dl 0
- iconbase dl 0
- stackptr dl 0
- WBenchMsg dl 0
- priority dl 0 ;\
- nokeypad dl 0 ; - array for ReadArgs
- hot dl 0 ;/
- rc dl 0
- cxbase dl 0
- newbroker db NB_VERSION
- db 0 ;Reserve1
- dl brokername
- dl brokertitle
- dl brokerdescr
- dw NBU_UNIQUE!NBU_NOTIFY
- dw 0 ;flags
- nbpriority db 0
- db 0 ;reserve2
- brokerport dl 0
- dw 0 ;ReservedChannel
- brokererror dl 0
- broker dl 0
- filterobj dl 0
- customobj dl 0
- ix db IX_VERSION ;ix_Version
- db IECLASS_RAWKEY ;ix_Class
- dw 0 ;ix_Code
- dw 0 ;ix_CodeMask is 0 to ignore all codes
- dw IEQUALIFIER_CAPSLOCK ;ix_Qualifier
- dw IEQUALIFIER_CAPSLOCK ;ix_QualMask
- dw 0 ;ix_QualSame
- NKPix db IX_VERSION ;ix_Version
- db IECLASS_RAWKEY ;ix_Class
- dw 0 ;ix_Code
- dw 0 ;ix_CodeMask is 0 to ignore all codes
- dw IEQUALIFIER_CAPSLOCK ;ix_Qualifier
- dw IEQUALIFIER_CAPSLOCK!IEQUALIFIER_NUMERICPAD ;ix_QualMask
- dw 0 ;ix_QualSame
-
- dosname cstr 'dos.library'
- iconname cstr 'icon.library'
- template cstr 'CX_PRIORITY/N/K,NOKEYPAD/S,HOT/S'
- priorityname cstr 'CX_PRIORITY'
- nokeypadname cstr 'NOKEYPAD'
- hotname cstr 'HOT'
- cstr '$VER: Version 1.0 (2.12.93)'
- cstr 'By Douglas Nelson. Freely distributable.'
- cxname cstr 'commodities.library'
- brokername cstr 'CapsLockExtender'
- brokertitle cstr 'Caps Lock Extender'
- brokerdescr cstr 'Makes CapsLock affect entire keyboard'
-
- end