* PicSaver V1.0 * By Preben Nielsen * * This is a little utility that lets you cut-out a rectangular * piece of any screen much in the save way as brushes are cut-out * in Deluxe Paint and other paint-programs. The piece can then be * saved on disk as an IFF-ILBM file (can then be used in most * paint-programs). * * NOTE: There's no need to 'RUN' or 'RUNBACK' this program from the * CLI. It is auto-detaching. * *HISTORY * Made with Hisoft V2.12 * * V1.0 26-Mar-91: Can now draw/resize/erase the rectangle correctly. * 26-Mar-91: Now it opens a window. * 27-Mar-91: Saving screen as IFF-ILBM now works. (Unbuffered Output) * 28-Mar-91: Cleaned up a bit. * 31-Mar-91: Added the cross-hair. Still unbuffered Output ! * 31-Mar-91: Drawing rectangles was not perfect. When the rectangle * is only one pixel on either side, it became invisible * because I drew the same line twice in 'Complement' mode. * Now I only draw one line in these cases. * 05-Apr-91: Added 'AutoRequester'. * 06-Apr-91: Added a few features. You can now easily save a window * or an entire screen. Also little change in the * 'SaveILBM' routine. OPT O+ OPT O1+ ; Tells when a branch could be optimised to short OPT i+ ; Tells when '#' is probably missing incdir "AsmInc:" include "exec/exec_lib.i" include "exec/io.i" include "exec/memory.i" include "exec/interrupts.i" include "devices/input.i" include "devices/inputevent.i" include "libraries/dosextens.i" include "libraries/dos_lib.i" include "graphics/graphics_lib.i" include "intuition/intuition_lib.i" include "intuition/intuition.i" include "intuition/intuitionbase.i" * These are the signals sent from the input-handler to the process SIGBASE =20 QUAL_RELEASE_B =SIGBASE QUAL_PRESS_B =SIGBASE+1 LMB_RELEASE_B =SIGBASE+2 LMB_PRESS_B =SIGBASE+3 MOVE_B =SIGBASE+4 WINDOW_B =SIGBASE+5 SCREEN_B =SIGBASE+6 QUIT_B =SIGBASE+7 PORT_B =SIGBASE+8 QUAL_RELEASE_F =1<,stacksize,processpri SECTION SingleSplit,CODE Start Prepare Exec_Call suba.l A1,A1 CallLib FindTask ; Find us move.l D0,A2 tst.l pr_CLI(A2) bne.S SegSplit jmp ProcessStart ; from WorkBench SegSplit CallLib Forbid ; From Dos lea DName(PC),A1 CallLib OldOpenLibrary move.l D0,D5 beq.S 3$ moveq #ML_SIZE+1*ME_SIZE,D0 move.l #MEMF_PUBLIC|MEMF_CLEAR,D1 CallLib AllocMem ; Allocate Memlist move.l D0,A2 tst.l D0 beq.S 2$ move.l #ProcessName,D1 moveq #\3,D2 ; Priority move.l Start-4(PC),D3 move.l #\2,D4 ; StackSize move.l D5,A6 CallLib CreateProc Prepare Exec_Call tst.l D0 beq.S 1$ move.l D0,A0 lea -pr_MsgPort(A0),A0 ; Now we have process not.l pr_CLI(A0) ; All MY programs will now think they were started from the CLI lsl.l #2,D3 subq.l #4,D3 move.l D3,A1 move.w #1,ML_NUMENTRIES(A2) ; MemList -> ml_NumEntries = 1 move.l A1,ML_ME+ME_ADDR(A2) ; MemList -> ml_me[0].me_Addr = Segment move.l (A1),ML_ME+ME_LENGTH(A2); MemList -> ml_me[0].me_Length = Length lea TC_MEMENTRY(A0),A0 move.l A2,A1 CallLib AddTail ; AddTail(&Process->pr_Task.tc_MemEntry,&MemList->ml_Node); lea Start-4(PC),A0 clr.l (A0) ; Split the segments bra.S 2$ 1$ move.l A2,A1 ; CreateProc failed. Can't do anything then moveq #ML_SIZE+1*ME_SIZE,D0 CallLib FreeMem 2$ move.l D5,A1 CallLib CloseLibrary 3$ CallLib Permit moveq #0,D0 rts DName dc.b 'dos.library',0 ProcessName dc.b \1,0 ; CreateProc makes a copy of this name SECTION ProcessCode,CODE ProcessStart ENDM DB EQUR A4 InitProcess Detach <'PicSaver Process'>,4000,0 rAlloc ; Allocate memory for variables rClear ; Clear the memory lea FileInfo(PC),A1 lea FBuffer(DB),A2 move.l A2,si_Buffer(A1) move.w #FileBufSIZE,si_MaxChars(A1) Prepare Exec_Call suba.l A1,A1 CallLib FindTask ; Find us move.l D0,PProcess(DB) movea.l D0,A2 tst.l pr_CLI(A2) bne.S GetLibs WBStart lea pr_MsgPort(A2),A0 CallLib WaitPort ; wait for a message lea pr_MsgPort(A2),A0 CallLib GetMsg ; then get it move.l D0,WBMsg(DB) ; save it for later reply GetLibs CallLib Forbid lea IHS+ihs_PortName(PC),A1 CallLib FindPort move.l D0,D2 CallLib Permit tst.l D2 beq.S 1$ move.l D2,A1 ; PicSaver was already installed ! move.l MP_SIGTASK(A1),A1 move.l #QUIT_F,D0 CallLib Signal ; Signal task to quit and then exit bra.S Exit 1$ lea DosName(PC),A1 CallLib OldOpenLibrary move.l D0,DosBase(DB) beq.S Error lea GfxName(PC),A1 CallLib OldOpenLibrary move.l D0,GfxBase(DB) beq.S Error lea IntName(PC),A1 CallLib OldOpenLibrary move.l D0,IntBase(DB) beq.S Error * Allocate 9 signal-bits moveq #8,D2 2$ moveq #SIGBASE,D0 add.w D2,D0 CallLib AllocSignal dbf D2,2$ bra.S Main Error Exit Prepare Exec_Call FreeInt move.l IntBase(DB),D0 beq.S FreeGfx move.l D0,A1 CallLib CloseLibrary FreeGfx move.l GfxBase(DB),D0 beq.S FreeDos move.l D0,A1 CallLib CloseLibrary FreeDos move.l DosBase(DB),D0 beq.S ReplyWB move.l D0,A1 CallLib CloseLibrary ReplyWB move.l WBMsg(DB),D2 beq.S AllDone CallLib Forbid ; We were started from WB movea.l D2,A1 CallLib ReplyMsg ; Reply WBMessage AllDone rFree moveq #0,D0 rts Main bset #DISABLED,Status(DB) lea IHS(PC),A0 lea PSPrepIHS1(PC),A1 lea PSPrepIHS2(PC),A2 Call InstallHandler beq.S 1$ moveq #CANTINSTALL,D0 Call CONMsg bra.S Error 1$ moveq #INSTALLED,D0 Call CONMsg bclr #DISABLED,Status(DB) EventLoop moveq #0,D0 move.l Up(DB),D1 beq.S 1$ move.l D1,A0 moveq #0,D1 move.b MP_SIGBIT(A0),D1 bset D1,D0 1$ ori.l #WaitMask,D0 Prepare Exec_Call CallLib Wait move.l D0,D5 move.l Up(DB),D1 beq CheckIHS move.l D1,A0 moveq #0,D0 move.b MP_SIGBIT(A0),D0 btst D0,D5 beq CheckIHS GetNextMsg move.l Up(DB),D1 ; Recieved an IDCMP-message beq CheckIHS move.l D1,A0 Prepare Exec_Call CallLib GetMsg tst.l D0 beq CheckIHS move.l D0,A1 move.l im_Class(A1),D2 move.l im_IAddress(A1),A2 CallLib ReplyMsg cmp.l #ACTIVEWINDOW,D2 beq.S ActivateFS cmp.l #GADGETUP,D2 bne.S GetNextMsg GJ move.w gg_GadgetID(A2),D0 ; GadgetID is offset from GJ jmp GJ(PC,D0.W) DoSave Call CloseW move.l WWindow(DB),D0 beq.S 1$ move.l D0,A0 Prepare Intuition_Call CallLib WindowToFront clr.l WWindow(DB) 1$ Call SaveRect beq.S 2$ suba.l A0,A0 suba.l A2,A2 lea ITxtAUTOBody(PC),A1 lea ITxtAUTOOk(PC),A3 moveq #0,D0 moveq #0,D1 move.w #248,D2 moveq #46,D3 Prepare Intuition_Call CallLib AutoRequest bra.S DoCS 2$ suba.l A0,A0 Prepare Intuition_Call CallLib DisplayBeep bra.S DoCS DoCancel Call CloseW DoCS bclr #DISABLED,Status(DB) bra GetNextMsg ActivateFS Prepare Intuition_Call lea Gad1(PC),A0 move.l PWindow(DB),A1 suba.l A2,A2 CallLib ActivateGadget bra GetNextMsg CheckIHS TestQUIT btst #QUIT_B,D5 beq.S TestMOUSE * User pressed the qualifiers + the 'Quit_Key' Call DrawIt Call CloseW ; Close window if it is open bset #DISABLED,Status(DB) moveq #REMOVED,D7 lea IHS(PC),A0 lea PSEndIHS1(PC),A1 lea PSEndIHS2(PC),A2 Call RemoveHandler beq.S 1$ moveq #CANTREMOVE,D0 Call CONMsg bra EventLoop ; Help !! 1$ move.l D7,D0 Call CONMsg bra Exit ; Hmm TestMOUSE btst #DISABLED,Status(DB) ; Are most things disabled ? bne EventLoop TestQ_PRESS btst #QUAL_PRESS_B,D5 beq.S TestQ_RELEASE * User pressed the qualifiers Prepare Intuition_Call move.l ib_ActiveScreen(A6),D0 beq.S TestQ_RELEASE move.l D0,A0 move.w sc_MouseY(A0),D0 bmi.S TestQ_RELEASE move.w sc_MouseX(A0),D1 bmi.S TestQ_RELEASE movem.w D0-D1,ey(DB) ; (x,y) >= (0,0) move.w sc_Width(A0),sw(DB) ; Get starting point move.w sc_Height(A0),sh(DB) ; Get screen width/height move.l A0,WScreen(DB) lea sc_RastPort(A0),A0 ; Get screen Rastport move.l A0,Rp(DB) bset #CROSSHAIR,Status(DB) bclr #RECTANGLE,Status(DB) Call DrawIt ; Draw cross-hair TestQ_RELEASE btst #QUAL_RELEASE_B,D5 beq.S TestLMB_RELEASE * User released the qualifiers Call DrawIt ; Erase cross-hair/rectangle bclr #CROSSHAIR,Status(DB) bclr #RECTANGLE,Status(DB) TestLMB_RELEASE btst #LMB_RELEASE_B,D5 beq.S TestLMB_PRESS * User released the LMB while holding down the qualifiers Call DrawIt ; Erase cross-hair/rectangle bclr #CROSSHAIR,Status(DB) bclr #RECTANGLE,Status(DB) movem.w ey(DB),D0-D3 cmp.w D0,D2 ble.S 1$ exg D0,D2 1$ cmp.w D1,D3 ble.S 2$ exg D1,D3 2$ sub.w D3,D1 sub.w D2,D0 addq.w #1,D1 addq.w #1,D0 movem.w D0-D3,ph(DB) lea RTitle(PC),A0 move.l A0,PTitle(DB) bra ContactTheUser TestLMB_PRESS btst #LMB_PRESS_B,D5 beq.S TestMOVE * User pressed the LMB while holding down the qualifiers Call DrawIt ; Erase cross-hair bclr #CROSSHAIR,Status(DB) move.l WScreen(DB),A0 move.w sc_MouseY(A0),D0 bmi.S TestMOVE move.w sc_MouseX(A0),D1 bmi.S TestMOVE movem.w D0-D1,sy(DB) movem.w D0-D1,ey(DB) bset #RECTANGLE,Status(DB) Call DrawIt ; Draw rectangle TestMOVE btst #MOVE_B,D5 beq.S TestWINDOW * User moved the mouse while holding down the qualifiers and the LMB move.l WScreen(DB),A0 move.w sc_MouseY(A0),D0 ; If Y < 0 bge.S 1$ moveq #0,D0 ; then Y = 0 1$ move.w sc_MouseX(A0),D1 ; If X < 0 bge.S 2$ moveq #0,D1 ; then X = 0 2$ cmp.w ey(DB),D0 ; Did mouse actually move ? bne.S 3$ cmp.w ex(DB),D1 beq.S TestWINDOW 3$ Call DrawIt ; Erase old cross-hair/rectangle movem.w D0-D1,ey(DB) Call DrawIt ; Draw new cross-hair/rectangle TestWINDOW btst #WINDOW_B,D5 beq.S TestSCREEN * User pressed the qualifiers + the 'Window_Key' Call DrawIt ; Erase cross-hair/rectangle bclr #CROSSHAIR,Status(DB) bclr #RECTANGLE,Status(DB) Prepare Intuition_Call move.l ib_ActiveWindow(A6),D0 beq.S TestSCREEN move.l D0,A0 movem.w wd_LeftEdge(A0),D0-D1 move.w D0,px(DB) move.w D1,py(DB) move.w wd_Width(A0),pw(DB) move.w wd_Height(A0),ph(DB) move.l wd_Flags(A0),D0 andi.w #BACKDROP,D0 bne.S ContactTheUser move.l A0,WWindow(DB) lea WTitle(PC),A0 move.l A0,PTitle(DB) bra.S ContactTheUser TestSCREEN btst #SCREEN_B,D5 beq.S DoneTest * User pressed the qualifiers + the 'Screen_Key' Call DrawIt ; Erase cross-hair/rectangle bclr #CROSSHAIR,Status(DB) bclr #RECTANGLE,Status(DB) move.l WScreen(DB),A0 movem.w sc_LeftEdge(A0),D0-D1 move.w D0,px(DB) move.w D1,py(DB) move.w sc_Width(A0),pw(DB) move.w sc_Height(A0),ph(DB) lea STitle(PC),A0 move.l A0,PTitle(DB) ContactTheUser Call OpenW beq EventLoop bset #DISABLED,Status(DB) bra EventLoop DoneTest bra EventLoop DrawIt btst #RECTANGLE,Status(DB) bne.S DoDraw btst #CROSSHAIR,Status(DB) bne.S DoDraw rts DoDraw Push D0-D5/A0-A1/A6 Prepare Gfx_Call move.l Rp(DB),A2 moveq #2,D0 move.l A2,A1 CallLib SetDrMd btst #RECTANGLE,Status(DB) bne.S DrawRect DrawCross moveq #0,D0 move.w ey(DB),D1 move.l A2,A1 CallLib Move move.w sw(DB),D0 move.w ey(DB),D1 move.l A2,A1 CallLib Draw move.w ex(DB),D0 moveq #0,D1 move.l A2,A1 CallLib Move move.w ex(DB),D0 move.w sh(DB),D1 move.l A2,A1 CallLib Draw bra.S EndDrawIt DrawRect move.w sx(DB),D2 ; Always draw lines clockwice move.w ex(DB),D4 cmp.w D2,D4 bge.S 1$ exg D2,D4 1$ move.w sy(DB),D3 move.w ey(DB),D5 cmp.w D3,D5 bge.S 2$ exg D3,D5 2$ move.w D2,D0 move.w D3,D1 move.l A2,A1 CallLib Move cmp.w D2,D4 ; If same x-coordinate then only draw one line bne.S 3$ move.w D2,D0 move.w D5,D1 move.l A2,A1 CallLib Draw bra.S EndDrawIt 3$ move.w D4,D0 move.w D3,D1 move.l A2,A1 CallLib Draw cmp.w D3,D5 ; If same y-coordinate then only draw one line beq.S EndDrawIt move.w D4,D0 ; Draw the rest of the rectangle move.w D5,D1 move.l A2,A1 CallLib Draw move.w D2,D0 move.w D5,D1 move.l A2,A1 CallLib Draw move.w D2,D0 move.w D3,D1 addq.w #1,D1 ; Prevent 'round' corner move.l A2,A1 CallLib Draw EndDrawIt moveq #1,D0 move.l A2,A1 CallLib SetDrMd Pop D0-D5/A0-A1/A6 rts * Call: A0 = where to put it, D0 = number, D1 = count DecStr subq.w #1,D1 bra.S 2$ 1$ move.b #' ',(A0)+ 2$ dbf D1,1$ moveq #'0',D1 move.b D1,(A0)+ ext.l D0 3$ tst.l D0 beq.S 4$ divu #10,D0 swap D0 add.w D1,D0 move.b D0,-(A0) clr.w D0 swap D0 bra.S 3$ 4$ rts * Open a window on the Workbench screen and bring it to the front OpenW Push D0-D7/A0-A6 move.w pw(DB),D0 moveq #4,D1 lea TxtSize+6(PC),A0 Call DecStr move.w ph(DB),D0 moveq #4,D1 lea TxtSize+13(PC),A0 Call DecStr moveq #0,D0 move.l WScreen(DB),A0 move.b sc_BitMap+bm_Depth(A0),D0 moveq #2,D1 lea TxtSize+20(PC),A0 Call DecStr Prepare Intuition_Call lea NW(PC),A0 CallLib OpenWindow move.l D0,PWindow(DB) beq.S 1$ move.l D0,A0 move.l wd_UserPort(A0),Up(DB) move.l PTitle(DB),A1 lea ScrTitle(PC),A2 CallLib SetWindowTitles move.l PWindow(DB),A0 move.l wd_WScreen(A0),A0 CallLib ScreenToFront 1$ tst.l PWindow(DB) Pop D0-D7/A0-A6 rts * Close the window on the Workbench screen if it is open CloseW Push D0-D7/A0-A6 Prepare Intuition_Call move.l PWindow(DB),D0 beq.S 1$ move.l D0,A0 lea NW(PC),A1 movem.w wd_LeftEdge(A0),D0-D1 movem.w D0-D1,nw_LeftEdge(A1) CallLib CloseWindow clr.l Up(DB) clr.l PWindow(DB) move.l WScreen(DB),A0 CallLib ScreenToFront 1$ Pop D0-D7/A0-A6 rts FHandle EQUR D5 * Call: D0 = Msg-number CONMsg Push D0-D7/A0-A6 Prepare Dos_Call move.l D0,D4 moveq #0,D6 CallLib Output move.l D0,FHandle bne.S 1$ moveq #1,D6 lea CONName(PC),A0 move.l A0,D1 move.l #MODE_OLDFILE,D2 CallLib Open move.l D0,FHandle beq.S 2$ 1$ moveq #INFOMSG,D0 Call SendMsg move.l D4,D0 Call SendMsg tst.l D6 beq.S 2$ moveq #127,D1 CallLib Delay move.l FHandle,D1 CallLib Close 2$ Pop D0-D7/A0-A6 rts * Call: D0 = Msg-number SendMsg neg.l D0 lsl.l #1,D0 lea MsgTable(PC),A0 add.w 0(A0,D0),A0 move.l A0,D2 moveq #-1,D3 1$ addq.l #1,D3 tst.b (A0)+ bne.S 1$ move.l FHandle,D1 Prepare Dos_Call CallLib Write rts INFOMSG =0 INSTALLED =-1 REMOVED =-2 CANTINSTALL =-3 CANTREMOVE =-4 MsgText MACRO dc.w \1-MsgTable ENDM MsgTable MsgText Msg MsgText Msg1 MsgText Msg2 MsgText Msg3 MsgText Msg4 CONName dc.b 'CON:100/60/330/63/PicSaver',0 Msg dc.b 10,$9B,'0;33m PicSaver V1.0',10 dc.b $9B,'0;31m 1991 by ',$9B,'0;33mPreben Nielsen',$9B,'0;31m',10,' ',0 Msg1 dc.b 'has just been installed...',10,0 Msg2 dc.b 'has just been removed...',10,0 Msg3 dc.b 'Error: Cannot install handler',10,0 Msg4 dc.b 'Error: Cannot remove handler',10,0 EVEN rtsValue EQUR D7 * This is general-purpose inputhandler removal-routine * It only needs an ihs with a port-name to remove the handler * Call: A0 = ihs * A1 = first ihs-installation-routine or NULL * A2 = second ihs-installation-routine or NULL * Return: D0 = 0 means succes RemoveHandler Push D1/rtsValue/A0-A3/A6 moveq #-1,rtsValue move.l A2,A3 move.l A0,A2 move.l A1,D1 beq.S 1$ jsr (A1) ; A0 = ihs beq.S 2$ move.l D0,A2 1$ move.l A2,A0 Prepare Exec_Call moveq #IND_REMHANDLER,D0 Call TellInputDevice move.l D0,rtsValue bne.S 2$ lea ihs_Port(A2),A1 CallLib RemPort moveq #0,D0 bra.S 3$ 2$ moveq #-1,D0 3$ move.l A3,D1 beq.S 4$ move.l A2,A0 jsr (A3) ; A0 = ihs, D0 = 0 means succes 4$ move.l rtsValue,D0 Pop D1/rtsValue/A0-A3/A6 rts * This is general-purpose inputhandler installation-routine * It only needs an ihs with a port-name to install the handler * Call: A0 = ihs * A1 = first ihs-installation-routine or NULL * A2 = second ihs-installation-routine or NULL * Return: D0 = 0 means succes InstallHandler Push D1/rtsValue/A0-A3/A6 moveq #-1,rtsValue move.l A2,A3 move.l A0,A2 move.l A1,D1 beq.S 1$ jsr (A1) ; A0 = ihs beq.S 2$ move.l D0,A2 1$ move.l A2,A0 moveq #IND_ADDHANDLER,D0 Call TellInputDevice move.l D0,rtsValue bne.S 2$ lea ihs_Port(A2),A1 lea ihs_PortName(A2),A0 move.l A0,MP+LN_NAME(A1) ;MsgPort->mp_Node.ln_Name=Name; clr.b MP+LN_PRI(A1) ;MsgPort->mp_Node.ln_Pri =0; move.b #NT_MSGPORT,MP+LN_TYPE(A1) ;MsgPort->mp_Node.ln_Type=NT_MSGPORT; move.b #PA_IGNORE,MP_FLAGS(A1) ;MsgPort->mp_Flags =PA_IGNORE; Prepare Exec_Call CallLib AddPort moveq #0,D0 bra.S 3$ 2$ moveq #-1,D0 3$ move.l A3,D1 beq.S 4$ move.l A2,A0 jsr (A3) ; A0 = ihs, D0 = 0 means succes 4$ move.l rtsValue,D0 Pop D1/rtsValue/A0-A3/A6 rts * Open the input device. Set up the I/O block to add or remove the * input handler, and send the request to the input device. Finally, * close the device * Call: A0 = ihs * D0 = Function to perform (IND_ADDHANDLER/IND_REMHANDLER) * Return: D0 = 0 means succes TellInputDevice Push D1-D2/rtsValue/A0-A3/A6 Prepare Exec_Call moveq #-1,rtsValue move.l D0,D2 move.l A0,A2 lea IReq(DB),A0 moveq #IOSTD_SIZE,D0 Call MemClear lea IPort(DB),A0 moveq #MP_SIZE,D0 Call MemClear move.l A0,A3 move.b #NT_MSGPORT,MP+LN_TYPE(A3) ; mp_Node.ln_Type=NT_MSGPORT; move.b #PA_SIGNAL,MP_FLAGS(A3) ; mp_Flags =PA_SIGNAL; moveq #-1,D0 CallLib AllocSignal move.b D0,MP_SIGBIT(A3) ; mp_SigBit =MPSigBit; bmi.S 2$ suba.l A1,A1 CallLib FindTask move.l D0,MP_SIGTASK(A3) ; mp_SigTask =FindTask(0); lea IReq(DB),A1 move.l A3,IO+MN_REPLYPORT(A1) ; ExtReq->io_Message.mn_ReplyPort =taskReplyPort; move.b #NT_MESSAGE,IO+MN+LN_TYPE(A1) ; ExtReq->io_Message.mn_Node.ln_Type=NT_MESSAGE; lea InputName(PC),A0 ; input.device moveq #0,D0 ; unit# moveq #0,D1 ; flags CallLib OpenDevice tst.w D0 ; flag: error if > 0 bne.S 1$ lea IReq(DB),A1 move.w D2,IO_COMMAND(A1) lea ihs_Interrupt(A2),A0 move.l A0,IO_DATA(A1) CallLib DoIO move.l D0,rtsValue lea IReq(DB),A1 CallLib CloseDevice 1$ move.b MP_SIGBIT(A3),D0 CallLib FreeSignal 2$ move.l rtsValue,D0 Pop D1-D2/rtsValue/A0-A3/A6 rts * Call: A0 = Memory area * D0:16 = Count MemClear Push D0-D1/A0 moveq #0,D1 bra.S 2$ 1$ move.b D1,(A0)+ 2$ dbf D0,1$ Pop D0-D1/A0 rts * Call: A0 = Source * A1 = Destination * D0:16= Count MemCopy Push D0/A0-A1 bra.S 2$ 1$ move.b (A0)+,(A1)+ 2$ dbf D0,1$ Pop D0/A0-A1 rts * Each handler should have such a pair of installation-routine * The first one is passed to InstallHandler in A1 and it * is called immediately when entering InstallHandler * The second one is passed to InstallHandler in A2 and it * is called if installation of handler and message-port succeds * ----------------------------------------------------------------- * Call: A0 = ihs * Return: D0 has to point to ihs to be used when installation proceeds * If D0 = 0 then installation is aborted PSPrepIHS1 Push A0-A1 move.b #PORT_B,ihs_Port+MP_SIGBIT(A0) ;MsgPort->mp_SigBit =MPSigBit; move.l PProcess(DB),ihs_Port+MP_SIGTASK(A0);MsgPort->mp_SigTask =FindTask(0); move.l #HandlerSize,ihs_Length(A0) ; This will enable removal by other programs lea HandlerCode-IHS(A0),A1 move.l A1,ihs_Interrupt+IS_CODE(A0) ; HandlerBlock.HInterrupt.is_Code = Handler move.l DB,ihs_Interrupt+IS_DATA(A0) ; HandlerBlock.HInterrupt.is_Data = DB move.b #HPRI,ihs_Interrupt+LN_PRI(A0) ; HandlerBlock.HInterrupt.is_Node.ln_Pri = PRI move.l A0,D0 Pop A0-A1 rts * Call: A0 = ihs PSPrepIHS2 rts * Each handler should have such a pair of ending-routine * The first one is passed to RemoveHandler in A1 and it * is called immediately when entering RemoveHandler * The second one is passed to RemoveHandler in A2 and it * is called if removal of handler and message-port succeds * ----------------------------------------------------------------- * Call: A0 = ihs * Return: D0 has to point to ihs to be used when removal proceeds * If D0 = 0 then removal is aborted PSEndIHS1 Push D1-D2/A0-A1/A6 Prepare Exec_Call CallLib Forbid lea ihs_PortName(A0),A1 CallLib FindPort move.l D0,D2 CallLib Permit move.l D2,D0 ; Does Forbid/Permit destroy scratch-registers ? Pop D1-D2/A0-A1/A6 rts * Call: A0 = ihs PSEndIHS2 rts *====================== Input-handler start ========================= ihs_Port =0 ihs_Interrupt =MP_SIZE ihs_ID =MP_SIZE+IS_SIZE ihs_Length =MP_SIZE+IS_SIZE+4 ihs_Flags =MP_SIZE+IS_SIZE+8 ihs_PortName =MP_SIZE+IS_SIZE+10 ihs_Start MACRO dcb.b MP_SIZE ; Message-Port structure dcb.b IS_SIZE ; Interrupt structure dc.l 'P_IH' ; ID dc.l 0 ; Length of handler dc.w 0 ; Flags dc.b \1,0 EVEN ENDM HPRI =51 HDisabled =0 HNoExtRemoval =1 * This is the handler-block IHS ihs_Start <'PicSaver V1.0 Port'> * Local variables Chain dc.l 0 * For each event in the event list: * If we were waiting for this event then signal the task. * When all the events have been checked, return the event list so that * others can do their things. PEvent EQUR A3 ; Previous Event Event EQUR A5 ; This Event Signals EQUR D7 Next =ie_NextEvent Class =ie_Class Code =ie_Code Qual =ie_Qualifier * These are the qualifier-keys the input-handler waits for QUALIFIERS =IEQUALIFIER_LALT|IEQUALIFIER_LSHIFT|IEQUALIFIER_CONTROL * This is the key the input-handler exits on Quit_Key =$45 ; ESC Window_Key =$11 ; w Screen_Key =$21 ; s * Call: A0 = List of InputEvents, A1 = HandlerData HandlerCode Push D1/Signals/A0-A1/PEvent/DB/Event/A6 moveq #0,Signals move.l A1,DB move.w IHS+ihs_Flags(PC),D0 btst #HDisabled,D0 ; Future feature bne NoMoreEvents lea Chain(PC),PEvent move.l A0,Next(PEvent) ieLoop move.l Next(PEvent),Event move.l Event,D0 beq NoMoreEvents cmpi.b #IECLASS_NULL,Class(Event) beq DontRemove cmpi.b #IECLASS_TIMER,Class(Event) beq DontRemove move.w Qual(Event),D0 andi.w #QUALIFIERS,D0 cmp.w #QUALIFIERS,D0 bne NoQual cmpi.b #IECLASS_RAWKEY,Class(Event) bne.S 1$ cmp.w #Quit_Key,Code(Event) beq.S DoQuit cmp.w #Window_Key,Code(Event) beq.S DoWindow cmp.w #Screen_Key,Code(Event) beq.S DoScreen bra.S IsQual bra.S DontRemove 1$ btst #DISABLED,Status(DB) bne.S DontRemove cmpi.b #IECLASS_RAWMOUSE,Class(Event) bne.S DontRemove cmpi.w #IECODE_LBUTTON,Code(Event) beq.S DoStart cmpi.w #IECODE_UP_PREFIX|IECODE_LBUTTON,Code(Event) beq.S DoEnd move.w Qual(Event),D0 andi.w #IEQUALIFIER_RELATIVEMOUSE,D0 beq.S DontRemove DoMove move.b Status(DB),D0 andi.b #1<