home *** CD-ROM | disk | FTP | other *** search
- ;ClickToFront V1.1 Copyright 1987 Bryce Nesbitt. Unlimited, revokable, free,
- ;non-exclusive licence hereby granted to any sentient being to use or abuse
- ;this code in any way whatsoever provided that this and any other copyright
- ;notices remain fully attached and are reproduced in any simultaneously
- ;distributed printed matter and with the exception that, without prior
- ;written permission, it not be utilized by any entity that has been commonly
- ;referred to as Robert W. Skyles, Skyles Electric Works, Jim Drew, Regie
- ;Warren or any organization founded by, controlled, employing or profiting
- ;any such entity, it's offspring or spouses. FISH use ok. Author
- ;correspondence, bug or stupidity reports may be directed to:
- ; 1712 Marin Ave.
- ; Berkeley, Ca 94707-2902
- ; bryce@cogsci.berkeley.EDU -or- ucbvax!cogsci!bryce
- ;"(almost) as seen in Transactor magazine".
- ;
- ;USAGE
- ; CLI - ClickToFront
- ; WB - Brings up requester, choose Install or Cancel
- ;
- ; A click into any part of any window works as normal.
- ; A double click brings it to the front. How handy!
- ;
- ; !!! In order to prevent false activation, lower the !!!
- ; !!! double-click sensitvity from preferences. !!!
- ;
- ;BUGS
- ; No provisions for un-install. The only way I can think to do this would
- ;be to add a handler at priority 52, then search the chain downward for a
- ;handler with name ClickToFront. This seems like a kludge.
- ; This program is NOT Intuition. This makes certain things more difficult.
- ;A test should be made that both clicks are over the same window. If some,
- ;kind Intuition() hacker has a way...
- ; No longer brings screens to the front.
- ; Proper size when assembled with Metacomco and Blink'ed with NODEBUG
- ; is 956 bytes.
- ;
- **************
- NOLIST
- INCLUDE 'exec/types.i'
- INCLUDE 'exec/memory.i'
- INCLUDE 'exec/interrupts.i'
- INCLUDE 'exec/io.i'
- ; INCLUDE 'exec/tasks.i'
- ThisTask EQU $114
- INCLUDE 'libraries/dosextens.i'
- INCLUDE 'devices/inputevent.i'
- INCLUDE 'devices/input.i'
- ; INCLUDE 'intuition/intuitionbase.i'
- ib_ActiveWindow EQU $34
- ib_ActiveScreen EQU $38
- ib_FirstScreen EQU $3C
- ;
- ;What follows is a non-standard extension that eliminates the need to link
- ;with the HUGE amiga.lib file.
- ;
- ;INCLUDE 'lib/exec_lib.i'
- ;INCLUDE 'lib/intuition_lib.i'
- LIST
- jsrlib macro
- xref _LVO\1
- jsr _LVO\1(a6)
- endm
- jmplib macro
- xref _LVO\1
- jmp _LVO\1(a6)
- endm
- ********************
- CODE
- startup: move.l 4,a6
- move.l ThisTask(a6),a5
- moveq #0,d0 ;Set zero for later
- move.l pr_CLI(a5),d1 ;Pointer to CLI only structure
- bne.s fromCLI ;If not zero, then save a zero...
- ;
- ; If called from Workbench a message will be sent. This waits for it,
- ; and saves it's pointer to be returned to Workbench later.
- ;
- lea.l pr_MsgPort(a5),a0
- jsrlib WaitPort
- lea.l pr_MsgPort(a5),a0
- jsrlib GetMsg ;Message pointer in D0
- fromCLI move.l d0,-(a7) ;Save message for later...
- ******************************** [A6=ExecBase][a5=this task]
- failcode equr d7
- Ibase equr d6
- portsave equr a5
- IOReqsave equr a4
-
- moveq #20,failcode ;Default code
- ;---Prepare StdIO---
- bsr _CreatePortE ;[d0=Port]
- beq ExitToDOS
- move.l d0,portsave
- bsr _CreateStdIOE ;[a1=IoRequest]
- beq e_StdIO
- move.l a1,IOReqsave
- ;---Open input.device---
- moveq #0,d0 ;Unit
- move.l d0,d1 ;Flags
- lea.l devname(pc),a0
- ;[a1-IoRequest]
- jsrlib OpenDevice ;[d0=zero if ok]
- tst.l d0
- bne e_Open
- ;---Open Intuition---
- ;Intuition will be opened, and the pointer given to the interrupt code
- ; Since the interrupt will still be installed after this task exits,
- ; intuition will be left open.
- ;
- lea.l IntuiName(pc),a1
- jsrlib OldOpenLibrary ;V1.0 Compatible :-)
- move.l d0,Ibase ;(d)
- beq e_Intui
- tst.l (a7) ;check CLI flag on stack
- beq.s DoIt ;always do it from CLI
-
- move.l Ibase,a6
- suba.l a0,a0
- lea.l IText1(pc),a1
- lea.l IText2(pc),a2
- lea.l IText3(pc),a3
- moveq #0,d0
- moveq #0,d1
- move.l #560,d2
- moveq #68,d3
- jsrlib AutoRequest
- move.l 4,a6
- tst.l d0 ;grumble, gritch, grrr...
- bne.s DoIt
- ;---User said no, so pack our bags and go home--
- move.l Ibase,a1
- jsrlib CloseLibrary
- bra.s Cancel
- ;---Copy Handler---
- DoIt move.l #DownEnd-Start,d0
- move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
- jsrlib AllocMem
- move.l d0,a2 ;location of block
- move.l d0,a1
- tst.l d0
- beq.s e_nomem
-
- lea.l Start(pc),a0
- moveq #((DownEnd-Start)/4)-1,d1 ;Length in LONGS-1
- copylp move.l (a0)+,(a1)+ ;Copy handler to Public Memory
- dbra d1,copylp ;68010 Loop mode!
-
- ;---Prepare IOReq with proper addresses---
- lea.l Handlercode-Start(a2),a0 ;offset+memblock
- move.l a0,IS_DATA(a2) ;unused
- move.l a0,IS_CODE(a2) ;where code is
- lea.l PopName-Start(a2),a0 ;set ascii name
- move.l a0,LN_NAME(a2)
- move.l Ibase,IBASE1+2-Start(a2) ;modify code
- move.l Ibase,IBASE2+2-Start(a2) ;modify code
-
- ;---Send ADDHANDLER---
- move.l IOReqsave,a1
- move.w #IND_ADDHANDLER,IO_COMMAND(a1)
- move.l a2,IO_DATA(a1)
- ;(IOReq in a1)
- jsrlib DoIO ;d0=(IOReq-a0)
- tst.l d0
- bne.s e_DoIO ;bad<>0. Forget the memory...
-
- Cancel moveq #0,d7
- e_nomem
- e_DoIO
- e_Intui move.l IOReqsave,a1
- jsrlib CloseDevice
- e_Open move.l IOReqsave,a1
- bsr _DeleteStdIOE
- e_StdIO move.l portsave,a1
- bsr _DeletePortE
- tst.l failcode
- beq.s ExitToDOS
-
- ;-- There can be only one reason why we failed (knock on formica) --
- ;-- and that is lack of memory. Unless you have a better idea... --
-
- move.l ThisTask(a6),a1
- moveq #ERROR_NO_FREE_STORE,d0
- move.l d0,pr_Result2(a1)
-
- ******************************* (a7)+=message d7=return code a6=exec
- ExitToDOS: move.l (a7)+,d2
- beq.s NotWB ;If saved pointer is zero, exit to CLI...
- ;
- ; Return the startup message to the parent Workbench tool. The forbid
- ; is needed so workbench can't UnLoadSeg() the code too early.
- ;
- jsrlib Forbid
- move.l d2,a1 ;message pointer
- jsrlib ReplyMsg
- NotWB move.l failcode,d0 ;Set "failat" code
- rts
-
- ;**** exec_support/CreatePort ***
- ;
- ; port=_CreatePort()
- ; d0
- ;
- ;FUNCTION: Create a nameless message port with a 0 priority.
- ; (exec/ports.i)
- ;RESULT: The port pointer or Z=1 if an error occured.
- ;REGISTERS: a6 is destroyed unless _CreatePortE is called,
- ; in which case a6 must contain ExecBase.
- ;EXAMPLE:
- ; moveq #3,d0 ;Set Priority
- ; jsr _CreatePort
- ; beq.s noport ;Not enough memory or signals
- ;
- ;xref _CreatePort
- ;xref _CreatePortE
- ;_CreatePort move.l 4,a6
- _CreatePortE: move.l a2,-(a7)
- move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
- moveq #MP_SIZE,d0
- jsrlib AllocMem
- move.l d0,a2
- tst.l d0
- beq.s cp_nomemory
- moveq #-1,d0
- jsrlib AllocSignal ;d0=return
- moveq #-1,d1
- cmp.l d0,d1 ;-1 indicates bad signal
- bne.s cp_sigok
- move.l a2,a1
- moveq #MP_SIZE,d0
- jsrlib FreeMem
- cp_nomemory moveq #0,d0 ;set z=1
- bra.s cp_xit
-
- cp_sigok move.b d0,MP_SIGBIT(a2)
- move.b #PA_SIGNAL,MP_FLAGS(a2)
- move.b #NT_MSGPORT,LN_TYPE(a2)
- clr.b LN_PRI(a2)
- move.l ThisTask(a6),MP_SIGTASK(a2)
- lea.l MP_MSGLIST(a2),a0 ;Point to list header
- NEWLIST a0 ;Init new list macro
- move.l a2,d0
- cp_xit move.l (a7)+,a2 ;cc's NOT affected
- rts
-
- ;**** exec_support/DeletePort ***
- ;
- ;_DeletePort(port)
- ; a1
- ;
- ;FUNCTION: Deletes the port by first setting some
- ; fields to illegal values then calling FreeMem.
- ;RESULT: none
- ;REGISTERS: a6 is destroyed unless _DeleteStdIOE is called,
- ; in which case a6 must contain ExecBase.
- ;
- ;xref _DeletePort
- ;xref _DeletePortE
- ;_DeletePort move.l 4,a6
- _DeletePortE: move.l a1,-(a7)
- moveq #-1,d0
- move.b d0,LN_TYPE(a1)
- move.l d0,MP_MSGLIST+LH_HEAD(a1)
- moveq #0,d0 ;Clear upper 3/4 of d0
- move.b MP_SIGBIT(a1),d0
- jsrlib FreeSignal
- move.l (a7)+,a1
- moveq #MP_SIZE,d0
- jmplib FreeMem
- ;
- ;ioStdReq=CreateStdIO(ioReplyPort)
- ; a1 d0
- ;
- ;Function: Allocate a IoRequest block of standard size.
- ;Example: move.l MyPort,d0
- ; jsr _CreateStdIO
- ; beq.s badnews
- ;
- ;xref _CreateStdIOE
- ;xref _CreateStdIO
- ;_CreateStdIO move.l 4,a6
- _CreateStdIOE: move.l d0,-(a7)
- moveq #IOSTD_SIZE,d0
- move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
- jsrlib AllocMem
- move.l d0,a1
- tst.l d0
- beq.s nomem
- move.b #NT_MESSAGE,LN_TYPE(a1)
- move.l (a7)+,MN_REPLYPORT(a1)
- nomem rts
-
- ;*** exec_support/DeleteStdIO ***
- ;
- ;_DeleteStdIO(ioStdReq)
- ; a1
- ;
- ;FUNCTION: Deletes an ioStdReq by setting some
- ; fields to illegal values then calling FreeMem.
- ;RESULT: none
- ;REGISTERS: a6 is destroyed unless _DeleteStdIOE is called,
- ; in which case a6 must contain ExecBase.
- ;
- ;xref _DeleteStdIO
- ;xref _DeleteStdIOE
- ;_DeleteStdIO move.l 4,a6 ;Get ExecBase
- _DeleteStdIOE: moveq #-1,d0 ;Set fields to illegal value
- move.b d0,LN_TYPE(a1)
- move.l d0,IO_DEVICE(a1)
- move.l d0,IO_UNIT(a1)
- moveq #IOSTD_SIZE,d0
- jmplib FreeMem
-
- IText1: dc.b 0,1,1,0 ;pens, drawmode and filler
- dc.w 20,6 ;XY
- dc.l 0 ;NULL for default font
- dc.l ITextText1 ;pointer to text
- dc.l IText1b ;next IntuitText structure
- IText1b dc.b 0,1,1,0
- dc.w 20,17
- dc.l 0
- dc.l ITextText1b
- dc.l 0
-
- IText2: dc.b 0,1,1,0
- dc.w 6,3
- dc.l 0
- dc.l ITextText2
- dc.l 0
- IText3: dc.b 0,1,1,0
- dc.w 6,3
- dc.l 0
- dc.l ITextText3
- dc.l 0
-
- ITextText1: dc.b 'ClickToFront installer v1.1. '
- dc.b $a9,'1987 Bryce Nesbitt',0
- ITextText1b dc.b 'Double-clicking will bring '
- ITextText1c dc.b 'any window to the front',0
- ITextText2: dc.b 'Install',0
- ITextText3: dc.b 'Cancel',0
- IntuiName: dc.b 'intuition.library',0
- devname: dc.b 'input.device',0
-
- ;-------------------------------
- cnop 0,4 ;LONG word align
- Start:
- ints: ;This is an interrupt structure (exec/interrupts.i)
- ;since it will be referenced by an interrupt it MUST be
- ;copied into PUBLIC memory. (All memory that will be used
- ;by interrupts or other tasks must be PUBLIC.)
- dc.l 0 ;succ
- dc.l 0 ;pred
- dc.b 0 ;type
- dc.b 51 ;Priority (One step higher than Intuition)
- dc.l 0 ;Name
- dc.l 0 ;Data
- dc.l 0 ;Code
- inte
-
- ;When the handler is entered a0 will point to a linked list of input
- ; events of the type defined in the incude file (devices/inputevent.i)
- ; When done mangling the input stream it returns a new pointer in d0
- ;Note: All references to (a0) below refer to ie_NextEvent(a0). The
- ; offeset equates to zero and was eliminated for effeciency.
-
- Handlercode: move.l a0,d0 ;Save pointer to start of chain
- cmpi.w #$0200,ie_Class(a0)
-
- ;Compare class AND subclass. $0200 is a combination of IECLASS_RAWMOUSE for
- ;ie_Class and IECLASS_NULL for ie_SubClass (it checks two BYTEs at once).
-
- beq.s hurdle1
- move.l (a0),d1 ;Get {ie_NextEvent} pointer
- bne.s MoreEvents ;If any...
- rts ;exit (with no changes made)
-
- hurdle1 move.l ie_Code(a0),d1 ;Code & Qualifier.
- andi.w #%0011000000000000,d1
- ;
- ;Mask off the bits of the qualifier field that we do not care about. In this
- ; case that's all but the RIGHT and MIDDLE buttons, which may not be down.
-
- cmpi.l #$00680000,d1
- ;
- ;The upper word of this comparison ($0068) is the RAWMOUSE code for LBUTTON
- ; the lower is the match for the qualifier.
-
- beq.s CheckClick
- KeepLooking move.l (a0),d1 ;See above...
- bne.s MoreEvents ;See above...
- rts ;exit (no changes)
- ;
- ;MoreEvents handles the case where several events may be linked and
- ; can extract one of them from the middle.
-
- MoreEvents ;move.l a0,a1 ;Temporary for unlinking
- move.l d1,a0 ;Look here next...
- cmpi.w #$0200,ie_Class(a0)
- bne.s KeepLooking
- move.l ie_Code(a0),d1
- andi.w #%0011000000000000,d1
- cmpi.l #$00680000,d1
- bne.s KeepLooking
- ;
- ;Don't unlink the event, that would cause problems.
- ;
- CheckClick movem.l a6/a1/d3/d2/d0,-(a7)
- move.l a0,-(a7)
- IBASE2 move.l #-1,a6 ;Self-modifying-> Intuitionbase
- move.l TimeSave+0(pc),d0
- move.l TimeSave+4(pc),d1
- move.l ie_TimeStamp+0(a0),d2
- move.l ie_TimeStamp+4(a0),d3
- jsrlib DoubleClick
- move.l (a7)+,a0
- lea.l TimeSave+0(pc),a1
- move.l ie_TimeStamp+0(a0),(a1)+
- move.l ie_TimeStamp+4(a0),(a1)+
- tst.l d0
- movem.l (a7)+,d0/d2/d3/a1/a6 ;cc's not
- beq.s KeepLooking
-
- ;[d0-short input]
-
- ;The pointer to the currently active Screen and Windows are available at a
- ; positive offset from the Intuition base pointer. These will be brought
- ; to the front. Note that it may not be proper under the Amiga system to
- ; do this in the actual handler. It may be safer to have another task
- ; lying around in the background to do the actual work. The description
- ; of the Intuition WindowToFront commands indicates that it will not take
- ; effect until the NEXT input event, which (of course) will not happen
- ; until this one exits. Now, if Intuition was a device...
- ;
- tofront: movem.l a6/d0,-(a7)
- IBASE1 move.l #-1,a6 ;Self-modifying-> Intuitionbase
- moveq #0,d0
- jsrlib LockIBase ;Lock before reading any private
- move.l d0,-(a7) ;Intuition structures
-
- ;move.l ib_ActiveScreen(a6),d0 ;Uncomment to bring screen
- ;beq.s iinoscreen ;to front also
- ;move.l d0,a0
- ;jsrlib ScreenToFront
-
- ;move.l ib_ActiveScreen(a6),d0 ;Garbage, forget it
- ;beq.s inoscreen
- ;move.l d0,a0
- ;lea.l MouseYX(pc),a1
- ;move.l sc_MouseX(a0),d1
- ;cmp.l d1,(a1)
- ;bne.s imousemoved ;The mouse moved!! Don't do it!!
- ;move.l d1,(a1)
- ;jsrlib ScreenToFront
-
- iinoscreen move.l ib_ActiveWindow(a6),d0
- beq.s inowindow
- move.l d0,a0
- jsrlib WindowToFront
- inowindow move.l (a7)+,a0
- jsrlib UnlockIBase
- movem.l (a7)+,d0/a6 ;d0 contains output pointer
- rts
-
- imousemoved ;move.l d1,(a1) ;Set last position
- inoscreen ;move.l (a7)+,a0
- ;jsrlib UnlockIBase
- ;movem.l (a7)+,d0/a6
- ;rts ;don't bother with remaining chained events
-
- PopName: dc.b 'ClickToFront',0
- cnop 0,4 ;Pad out to Longword boundary
- TimeSave: dc.l 0,0 ;longs on longs retain long
- ;MouseYX dc.l 0
- DownEnd
- END
-