home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 1: Collection A / 17Bit_Collection_A.iso / files / 1183.dms / 1183.adf / PicSaver / PicSaver.asm < prev    next >
Assembly Source File  |  1991-07-17  |  41KB  |  1,607 lines

  1. *    PicSaver V1.0
  2. *    By Preben Nielsen
  3. *
  4. *      This is a little utility that lets you cut-out a rectangular
  5. *    piece of any screen much in the save way as brushes are cut-out
  6. *    in Deluxe Paint and other paint-programs. The piece can then be
  7. *    saved on disk as an IFF-ILBM file (can then be used in most
  8. *    paint-programs).
  9. *
  10. *    NOTE:    There's no need to 'RUN' or 'RUNBACK' this program from the
  11. *        CLI. It is auto-detaching.
  12. *
  13. *HISTORY
  14. *          Made with Hisoft V2.12
  15. *
  16. *  V1.0   26-Mar-91: Can now draw/resize/erase the rectangle correctly.
  17. *         26-Mar-91: Now it opens a window.
  18. *         27-Mar-91: Saving screen as IFF-ILBM now works. (Unbuffered Output)
  19. *         28-Mar-91: Cleaned up a bit.
  20. *         31-Mar-91: Added the cross-hair. Still unbuffered Output !
  21. *         31-Mar-91: Drawing rectangles was not perfect. When the rectangle
  22. *                    is only one pixel on either side, it became invisible
  23. *                    because I drew the same line twice in 'Complement' mode.
  24. *                    Now I only draw one line in these cases.
  25. *         05-Apr-91: Added 'AutoRequester'.
  26. *         06-Apr-91: Added a few features. You can now easily save a window
  27. *                    or an entire screen. Also little change in the
  28. *                    'SaveILBM' routine.
  29.                    
  30.     OPT O+
  31.     OPT O1+            ; Tells when a branch could be optimised to short
  32.     OPT i+            ; Tells when '#' is probably missing
  33.  
  34.         incdir        "AsmInc:"
  35.         include        "exec/exec_lib.i"
  36.         include        "exec/io.i"
  37.         include        "exec/memory.i"
  38.         include        "exec/interrupts.i"
  39.         include        "devices/input.i"
  40.         include        "devices/inputevent.i"
  41.         include        "libraries/dosextens.i"
  42.         include        "libraries/dos_lib.i"
  43.         include        "graphics/graphics_lib.i"
  44.         include        "intuition/intuition_lib.i"
  45.         include        "intuition/intuition.i"
  46.         include        "intuition/intuitionbase.i"
  47.  
  48. * These are the signals sent from the input-handler to the process
  49. SIGBASE        =20
  50. QUAL_RELEASE_B    =SIGBASE
  51. QUAL_PRESS_B    =SIGBASE+1
  52. LMB_RELEASE_B    =SIGBASE+2
  53. LMB_PRESS_B    =SIGBASE+3
  54. MOVE_B        =SIGBASE+4
  55. WINDOW_B    =SIGBASE+5
  56. SCREEN_B    =SIGBASE+6
  57. QUIT_B        =SIGBASE+7
  58. PORT_B        =SIGBASE+8
  59. QUAL_RELEASE_F    =1<<QUAL_RELEASE_B
  60. QUAL_PRESS_F    =1<<QUAL_PRESS_B
  61. LMB_RELEASE_F    =1<<LMB_RELEASE_B
  62. LMB_PRESS_F    =1<<LMB_PRESS_B
  63. MOVE_F        =1<<MOVE_B
  64. WINDOW_F    =1<<WINDOW_B
  65. SCREEN_F    =1<<SCREEN_B
  66. QUIT_F        =1<<QUIT_B
  67. PORT_F        =1<<PORT_B
  68. WaitMask    =QUAL_RELEASE_F|LMB_RELEASE_F|LMB_PRESS_F|MOVE_F|WINDOW_F|SCREEN_F|QUIT_F|QUAL_PRESS_F
  69.  
  70. RECTANGLE    =0
  71. CROSSHAIR    =1
  72. DISABLED    =2
  73.  
  74. FileBufSIZE    =50
  75.  
  76. Prepare        MACRO
  77.         IFC        '\1','Exec_Call'
  78.         movea.l        4.W,A6
  79.         ENDC
  80.         IFC        '\1','Intuition_Call'
  81.         movea.l        IntBase(DB),A6
  82.         ENDC
  83.         IFC        '\1','Gfx_Call'
  84.         movea.l        GfxBase(DB),A6
  85.         ENDC
  86.         IFC        '\1','Dos_Call'
  87.         movea.l        DosBase(DB),A6
  88.         ENDC
  89.         ENDM
  90. CallLib        MACRO
  91.         jsr        _LVO\1(A6)
  92.         ENDM
  93. Call        MACRO
  94.         bsr        \1
  95.         ENDM
  96. CallS        MACRO
  97.         bsr.S        \1
  98.         ENDM
  99. Push        MACRO
  100.         movem.l        \1,-(SP)
  101.         ENDM
  102. Pop        MACRO
  103.         movem.l        (SP)+,\1
  104.         ENDM
  105. rAPtr        MACRO        name
  106. DefSiz        set        DefSiz+4
  107. DefPtr        set        DefPtr-4
  108. \1        =        DefPtr
  109.         ENDM
  110. rLong        MACRO        name
  111. DefSiz        set        DefSiz+4
  112. DefPtr        set        DefPtr-4
  113. \1        =        DefPtr
  114.         ENDM
  115. rWord        MACRO        name
  116. DefSiz        set        DefSiz+2
  117. DefPtr        set        DefPtr-2
  118. \1        =        DefPtr
  119.         ENDM
  120. rByte        MACRO        name
  121. DefSiz        set        DefSiz+1
  122. DefPtr        set        DefPtr-1
  123. \1        =        DefPtr
  124.         ENDM
  125. rStorage    MACRO        name,size    ; Define storage
  126. DefSiz        set        DefSiz+\2
  127. DefPtr        set        DefPtr-\2
  128. \1        =        DefPtr
  129.         ENDM
  130. rEVEN        MACRO                ; Word boundary
  131.         IFNE        DefPtr&1
  132. DefPtr        set        DefPtr-1
  133. DefSiz        set        DefSiz+1
  134.         ENDC
  135.         ENDM
  136. rStart        MACRO                ; Define var section
  137. DefPtr        set        0
  138. DefSiz        set        0
  139.         ENDM
  140. rEnd        MACRO                ; End var section
  141. RelSize        =        DefSiz
  142.         ENDM
  143. rAlloc        MACRO                ; Allocate vars
  144.         link        DB,#-RelSize
  145.         ENDM
  146. rFree        MACRO                ; Deallocate vars
  147.         unlk        DB
  148.         ENDM
  149. rClear        MACRO                ; Reset all vars
  150.         movem.l        D0/DB,-(SP)
  151.         move.w        #RelSize-1,D0
  152. rClr.\@        clr.b        -(DB)
  153.         dbf        D0,rClr.\@
  154.         movem.l        (SP)+,D0/DB
  155.         ENDM
  156. Gadget        MACRO
  157.         dc.l        \1
  158.         dc.w        \2,\3,\4,\5,\6,\7,\8
  159.         ENDM
  160. Gadget2        MACRO
  161.         dc.l        \1,\2,\3,\4,\5
  162.         dc.w        \6
  163.         dc.l        \7
  164.         ENDM
  165. Border        MACRO
  166.         dc.w        \1,\2
  167.         dc.b        \3,\4,\5,\6
  168.         dc.l        \7,\8
  169.         ENDM
  170. Image        MACRO
  171.         dc.w        \1,\2,\3,\4,\5
  172.         dc.l        \6
  173.         dc.b        \7,\8
  174.         dc.l        \9
  175.         ENDM
  176. IntuiText    MACRO
  177.         dc.b        \1,\2,\3,0
  178.         dc.w        \4,\5
  179.         dc.l        TxtAttr,\6,\7
  180.         ENDM
  181. Detach        MACRO        ; Detach <'process name'>,stacksize,processpri
  182.         SECTION        SingleSplit,CODE
  183. Start        Prepare        Exec_Call
  184.         suba.l        A1,A1
  185.         CallLib        FindTask        ; Find us
  186.         move.l        D0,A2
  187.         tst.l        pr_CLI(A2)
  188.         bne.S        SegSplit
  189.         jmp        ProcessStart        ; from WorkBench
  190. SegSplit    CallLib        Forbid            ; From Dos
  191.         lea        DName(PC),A1
  192.         CallLib        OldOpenLibrary
  193.         move.l        D0,D5
  194.         beq.S        3$
  195.         moveq        #ML_SIZE+1*ME_SIZE,D0
  196.         move.l        #MEMF_PUBLIC|MEMF_CLEAR,D1
  197.         CallLib        AllocMem        ; Allocate Memlist
  198.         move.l        D0,A2
  199.         tst.l        D0
  200.         beq.S        2$
  201.         move.l        #ProcessName,D1
  202.         moveq        #\3,D2            ; Priority
  203.         move.l        Start-4(PC),D3
  204.         move.l        #\2,D4            ; StackSize
  205.         move.l        D5,A6
  206.         CallLib        CreateProc
  207.         Prepare        Exec_Call
  208.         tst.l        D0
  209.         beq.S        1$
  210.         move.l        D0,A0
  211.         lea        -pr_MsgPort(A0),A0    ; Now we have process
  212.         not.l        pr_CLI(A0)        ; All MY programs will now think they were started from the CLI
  213.         lsl.l        #2,D3
  214.         subq.l        #4,D3
  215.         move.l        D3,A1
  216.         move.w        #1,ML_NUMENTRIES(A2)    ; MemList -> ml_NumEntries    = 1
  217.         move.l        A1,ML_ME+ME_ADDR(A2)    ; MemList -> ml_me[0].me_Addr    = Segment
  218.         move.l        (A1),ML_ME+ME_LENGTH(A2); MemList -> ml_me[0].me_Length    = Length
  219.         lea        TC_MEMENTRY(A0),A0
  220.         move.l        A2,A1
  221.         CallLib        AddTail            ; AddTail(&Process->pr_Task.tc_MemEntry,&MemList->ml_Node);
  222.         lea        Start-4(PC),A0
  223.         clr.l        (A0)            ; Split the segments
  224.         bra.S        2$
  225. 1$        move.l        A2,A1            ; CreateProc failed. Can't do anything then
  226.         moveq        #ML_SIZE+1*ME_SIZE,D0
  227.         CallLib        FreeMem
  228. 2$        move.l        D5,A1
  229.         CallLib        CloseLibrary
  230. 3$        CallLib        Permit
  231.         moveq        #0,D0
  232.         rts
  233. DName        dc.b        'dos.library',0
  234. ProcessName    dc.b        \1,0            ; CreateProc makes a copy of this name
  235.         SECTION        ProcessCode,CODE
  236. ProcessStart
  237.         ENDM
  238.  
  239. DB        EQUR        A4
  240.  
  241. InitProcess    Detach        <'PicSaver Process'>,4000,0
  242.         rAlloc                    ; Allocate memory for variables
  243.         rClear                    ; Clear the memory
  244.         lea        FileInfo(PC),A1
  245.         lea        FBuffer(DB),A2
  246.         move.l        A2,si_Buffer(A1)
  247.         move.w        #FileBufSIZE,si_MaxChars(A1)
  248.         Prepare        Exec_Call
  249.         suba.l        A1,A1
  250.         CallLib        FindTask        ; Find us
  251.         move.l        D0,PProcess(DB)
  252.         movea.l        D0,A2
  253.         tst.l        pr_CLI(A2)
  254.         bne.S        GetLibs
  255. WBStart        lea        pr_MsgPort(A2),A0
  256.         CallLib        WaitPort        ; wait for a message
  257.         lea        pr_MsgPort(A2),A0
  258.         CallLib        GetMsg            ; then get it
  259.         move.l        D0,WBMsg(DB)        ; save it for later reply
  260. GetLibs        CallLib        Forbid
  261.         lea        IHS+ihs_PortName(PC),A1
  262.         CallLib        FindPort
  263.         move.l        D0,D2
  264.         CallLib        Permit
  265.         tst.l        D2
  266.         beq.S        1$
  267.         move.l        D2,A1            ; PicSaver was already installed ! 
  268.         move.l        MP_SIGTASK(A1),A1
  269.         move.l        #QUIT_F,D0
  270.         CallLib        Signal            ; Signal task to quit and then exit
  271.         bra.S        Exit
  272. 1$        lea        DosName(PC),A1
  273.         CallLib        OldOpenLibrary
  274.         move.l        D0,DosBase(DB)
  275.         beq.S        Error
  276.         lea        GfxName(PC),A1
  277.         CallLib        OldOpenLibrary
  278.         move.l        D0,GfxBase(DB)
  279.         beq.S        Error
  280.         lea        IntName(PC),A1
  281.         CallLib        OldOpenLibrary
  282.         move.l        D0,IntBase(DB)
  283.         beq.S        Error
  284. * Allocate 9 signal-bits
  285.         moveq        #8,D2
  286. 2$        moveq        #SIGBASE,D0
  287.         add.w        D2,D0
  288.         CallLib        AllocSignal
  289.         dbf        D2,2$
  290.         bra.S        Main
  291.  
  292. Error
  293. Exit        Prepare        Exec_Call
  294. FreeInt        move.l        IntBase(DB),D0
  295.         beq.S        FreeGfx
  296.         move.l        D0,A1
  297.         CallLib        CloseLibrary
  298. FreeGfx        move.l        GfxBase(DB),D0
  299.         beq.S        FreeDos
  300.         move.l        D0,A1
  301.         CallLib        CloseLibrary
  302. FreeDos        move.l        DosBase(DB),D0
  303.         beq.S        ReplyWB
  304.         move.l        D0,A1
  305.         CallLib        CloseLibrary
  306. ReplyWB        move.l        WBMsg(DB),D2
  307.         beq.S        AllDone
  308.         CallLib        Forbid            ; We were started from WB
  309.         movea.l        D2,A1
  310.         CallLib        ReplyMsg        ; Reply WBMessage
  311. AllDone        rFree
  312.         moveq        #0,D0
  313.         rts
  314.  
  315. Main        bset        #DISABLED,Status(DB)
  316.         lea        IHS(PC),A0
  317.         lea        PSPrepIHS1(PC),A1
  318.         lea        PSPrepIHS2(PC),A2
  319.         Call        InstallHandler
  320.         beq.S        1$
  321.         moveq        #CANTINSTALL,D0
  322.         Call        CONMsg
  323.         bra.S        Error
  324. 1$        moveq        #INSTALLED,D0
  325.         Call        CONMsg
  326.         bclr        #DISABLED,Status(DB)
  327. EventLoop    moveq        #0,D0
  328.         move.l        Up(DB),D1
  329.         beq.S        1$
  330.         move.l        D1,A0
  331.         moveq        #0,D1
  332.         move.b        MP_SIGBIT(A0),D1
  333.         bset        D1,D0
  334. 1$        ori.l        #WaitMask,D0
  335.         Prepare        Exec_Call
  336.         CallLib        Wait
  337.         move.l        D0,D5
  338.         move.l        Up(DB),D1
  339.         beq        CheckIHS
  340.         move.l        D1,A0
  341.         moveq        #0,D0
  342.         move.b        MP_SIGBIT(A0),D0
  343.         btst        D0,D5
  344.         beq        CheckIHS
  345. GetNextMsg    move.l        Up(DB),D1        ; Recieved an IDCMP-message
  346.         beq        CheckIHS
  347.         move.l        D1,A0
  348.         Prepare        Exec_Call
  349.         CallLib        GetMsg
  350.         tst.l        D0
  351.         beq        CheckIHS
  352.         move.l        D0,A1
  353.         move.l        im_Class(A1),D2
  354.         move.l        im_IAddress(A1),A2
  355.         CallLib        ReplyMsg
  356.         cmp.l        #ACTIVEWINDOW,D2
  357.         beq.S        ActivateFS
  358.         cmp.l        #GADGETUP,D2
  359.         bne.S        GetNextMsg
  360. GJ        move.w        gg_GadgetID(A2),D0    ; GadgetID is offset from GJ
  361.         jmp        GJ(PC,D0.W)
  362. DoSave        Call        CloseW
  363.         move.l        WWindow(DB),D0
  364.         beq.S        1$
  365.         move.l        D0,A0
  366.         Prepare        Intuition_Call
  367.         CallLib        WindowToFront
  368.         clr.l        WWindow(DB)
  369. 1$        Call        SaveRect
  370.         beq.S        2$
  371.         suba.l        A0,A0
  372.         suba.l        A2,A2
  373.         lea        ITxtAUTOBody(PC),A1
  374.         lea        ITxtAUTOOk(PC),A3
  375.         moveq        #0,D0
  376.         moveq        #0,D1
  377.         move.w        #248,D2
  378.         moveq        #46,D3
  379.         Prepare        Intuition_Call
  380.         CallLib        AutoRequest
  381.         bra.S        DoCS
  382. 2$        suba.l        A0,A0
  383.         Prepare        Intuition_Call
  384.         CallLib        DisplayBeep
  385.         bra.S        DoCS
  386. DoCancel    Call        CloseW
  387. DoCS        bclr        #DISABLED,Status(DB)
  388.         bra        GetNextMsg
  389. ActivateFS    Prepare        Intuition_Call
  390.         lea        Gad1(PC),A0
  391.         move.l        PWindow(DB),A1
  392.         suba.l        A2,A2
  393.         CallLib        ActivateGadget
  394.         bra        GetNextMsg
  395.  
  396. CheckIHS
  397. TestQUIT    btst        #QUIT_B,D5
  398.         beq.S        TestMOUSE
  399. * User pressed the qualifiers + the 'Quit_Key'
  400.         Call        DrawIt
  401.         Call        CloseW            ; Close window if it is open
  402.         bset        #DISABLED,Status(DB)
  403.         moveq        #REMOVED,D7
  404.         lea        IHS(PC),A0
  405.         lea        PSEndIHS1(PC),A1
  406.         lea        PSEndIHS2(PC),A2
  407.         Call        RemoveHandler
  408.         beq.S        1$
  409.         moveq        #CANTREMOVE,D0
  410.         Call        CONMsg
  411.         bra        EventLoop        ; Help !!
  412. 1$        move.l        D7,D0
  413.         Call        CONMsg
  414.         bra        Exit            ; Hmm
  415. TestMOUSE    btst        #DISABLED,Status(DB)    ; Are most things disabled ?
  416.         bne        EventLoop
  417.  
  418. TestQ_PRESS    btst        #QUAL_PRESS_B,D5
  419.         beq.S        TestQ_RELEASE
  420. * User pressed the qualifiers
  421.         Prepare        Intuition_Call
  422.         move.l        ib_ActiveScreen(A6),D0
  423.         beq.S        TestQ_RELEASE
  424.         move.l        D0,A0
  425.         move.w        sc_MouseY(A0),D0
  426.         bmi.S        TestQ_RELEASE
  427.         move.w        sc_MouseX(A0),D1
  428.         bmi.S        TestQ_RELEASE
  429.         movem.w        D0-D1,ey(DB)        ; (x,y) >= (0,0)
  430.         move.w        sc_Width(A0),sw(DB)    ; Get starting point
  431.         move.w        sc_Height(A0),sh(DB)    ; Get screen width/height
  432.         move.l        A0,WScreen(DB)
  433.         lea        sc_RastPort(A0),A0    ; Get screen Rastport
  434.         move.l        A0,Rp(DB)
  435.         bset        #CROSSHAIR,Status(DB)
  436.         bclr        #RECTANGLE,Status(DB)
  437.         Call        DrawIt            ; Draw cross-hair
  438.  
  439. TestQ_RELEASE    btst        #QUAL_RELEASE_B,D5
  440.         beq.S        TestLMB_RELEASE
  441. * User released the qualifiers
  442.         Call        DrawIt            ; Erase cross-hair/rectangle
  443.         bclr        #CROSSHAIR,Status(DB)
  444.         bclr        #RECTANGLE,Status(DB)
  445.  
  446. TestLMB_RELEASE    btst        #LMB_RELEASE_B,D5
  447.         beq.S        TestLMB_PRESS
  448. * User released the LMB while holding down the qualifiers
  449.         Call        DrawIt            ; Erase cross-hair/rectangle
  450.         bclr        #CROSSHAIR,Status(DB)
  451.         bclr        #RECTANGLE,Status(DB)
  452.         movem.w        ey(DB),D0-D3
  453.         cmp.w        D0,D2
  454.         ble.S        1$
  455.         exg        D0,D2
  456. 1$        cmp.w        D1,D3
  457.         ble.S        2$
  458.         exg        D1,D3
  459. 2$        sub.w        D3,D1
  460.         sub.w        D2,D0
  461.         addq.w        #1,D1
  462.         addq.w        #1,D0
  463.         movem.w        D0-D3,ph(DB)
  464.         lea        RTitle(PC),A0
  465.         move.l        A0,PTitle(DB)
  466.         bra        ContactTheUser
  467.  
  468. TestLMB_PRESS    btst        #LMB_PRESS_B,D5
  469.         beq.S        TestMOVE
  470. * User pressed the LMB while holding down the qualifiers
  471.         Call        DrawIt            ; Erase cross-hair
  472.         bclr        #CROSSHAIR,Status(DB)
  473.         move.l        WScreen(DB),A0
  474.         move.w        sc_MouseY(A0),D0
  475.         bmi.S        TestMOVE
  476.         move.w        sc_MouseX(A0),D1
  477.         bmi.S        TestMOVE
  478.         movem.w        D0-D1,sy(DB)
  479.         movem.w        D0-D1,ey(DB)
  480.         bset        #RECTANGLE,Status(DB)
  481.         Call        DrawIt            ; Draw rectangle
  482.  
  483. TestMOVE    btst        #MOVE_B,D5
  484.         beq.S        TestWINDOW
  485. * User moved the mouse while holding down the qualifiers and the LMB
  486.         move.l        WScreen(DB),A0
  487.         move.w        sc_MouseY(A0),D0    ; If Y < 0
  488.         bge.S        1$
  489.         moveq        #0,D0            ; then Y = 0
  490. 1$        move.w        sc_MouseX(A0),D1    ; If X < 0
  491.         bge.S        2$    
  492.         moveq        #0,D1            ; then X = 0
  493. 2$        cmp.w        ey(DB),D0        ; Did mouse actually move ?
  494.         bne.S        3$
  495.         cmp.w        ex(DB),D1
  496.         beq.S        TestWINDOW
  497. 3$        Call        DrawIt            ; Erase old cross-hair/rectangle
  498.         movem.w        D0-D1,ey(DB)
  499.         Call        DrawIt            ; Draw new cross-hair/rectangle
  500.  
  501. TestWINDOW    btst        #WINDOW_B,D5
  502.         beq.S        TestSCREEN
  503. * User pressed the qualifiers + the 'Window_Key'
  504.         Call        DrawIt            ; Erase cross-hair/rectangle
  505.         bclr        #CROSSHAIR,Status(DB)
  506.         bclr        #RECTANGLE,Status(DB)
  507.         Prepare        Intuition_Call
  508.         move.l        ib_ActiveWindow(A6),D0
  509.         beq.S        TestSCREEN
  510.         move.l        D0,A0
  511.         movem.w        wd_LeftEdge(A0),D0-D1
  512.         move.w        D0,px(DB)
  513.         move.w        D1,py(DB)
  514.         move.w        wd_Width(A0),pw(DB)
  515.         move.w        wd_Height(A0),ph(DB)
  516.         move.l        wd_Flags(A0),D0
  517.         andi.w        #BACKDROP,D0
  518.         bne.S        ContactTheUser
  519.         move.l        A0,WWindow(DB)
  520.         lea        WTitle(PC),A0
  521.         move.l        A0,PTitle(DB)
  522.         bra.S        ContactTheUser
  523.  
  524. TestSCREEN    btst        #SCREEN_B,D5
  525.         beq.S        DoneTest
  526. * User pressed the qualifiers + the 'Screen_Key'
  527.         Call        DrawIt            ; Erase cross-hair/rectangle
  528.         bclr        #CROSSHAIR,Status(DB)
  529.         bclr        #RECTANGLE,Status(DB)
  530.         move.l        WScreen(DB),A0
  531.         movem.w        sc_LeftEdge(A0),D0-D1
  532.         move.w        D0,px(DB)
  533.         move.w        D1,py(DB)
  534.         move.w        sc_Width(A0),pw(DB)
  535.         move.w        sc_Height(A0),ph(DB)
  536.         lea        STitle(PC),A0
  537.         move.l        A0,PTitle(DB)
  538. ContactTheUser    Call        OpenW
  539.         beq        EventLoop
  540.         bset        #DISABLED,Status(DB)
  541.         bra        EventLoop
  542. DoneTest    bra        EventLoop
  543.  
  544. DrawIt        btst        #RECTANGLE,Status(DB)
  545.         bne.S        DoDraw
  546.         btst        #CROSSHAIR,Status(DB)
  547.         bne.S        DoDraw
  548.         rts
  549. DoDraw        Push        D0-D5/A0-A1/A6
  550.         Prepare        Gfx_Call
  551.         move.l        Rp(DB),A2
  552.         moveq        #2,D0
  553.         move.l        A2,A1
  554.         CallLib        SetDrMd
  555.         btst        #RECTANGLE,Status(DB)
  556.         bne.S        DrawRect
  557. DrawCross    moveq        #0,D0
  558.         move.w        ey(DB),D1
  559.         move.l        A2,A1
  560.         CallLib        Move
  561.         move.w        sw(DB),D0
  562.         move.w        ey(DB),D1
  563.         move.l        A2,A1
  564.         CallLib        Draw
  565.         move.w        ex(DB),D0
  566.         moveq        #0,D1
  567.         move.l        A2,A1
  568.         CallLib        Move
  569.         move.w        ex(DB),D0
  570.         move.w        sh(DB),D1
  571.         move.l        A2,A1
  572.         CallLib        Draw
  573.         bra.S        EndDrawIt
  574. DrawRect    move.w        sx(DB),D2    ; Always draw lines clockwice
  575.         move.w        ex(DB),D4
  576.         cmp.w        D2,D4
  577.         bge.S        1$
  578.         exg        D2,D4
  579. 1$        move.w        sy(DB),D3
  580.         move.w        ey(DB),D5
  581.         cmp.w        D3,D5
  582.         bge.S        2$
  583.         exg        D3,D5
  584. 2$        move.w        D2,D0
  585.         move.w        D3,D1
  586.         move.l        A2,A1
  587.         CallLib        Move
  588.         cmp.w        D2,D4        ; If same x-coordinate then only draw one line
  589.         bne.S        3$
  590.         move.w        D2,D0
  591.         move.w        D5,D1
  592.         move.l        A2,A1
  593.         CallLib        Draw
  594.         bra.S        EndDrawIt
  595. 3$        move.w        D4,D0
  596.         move.w        D3,D1
  597.         move.l        A2,A1
  598.         CallLib        Draw
  599.         cmp.w        D3,D5        ; If same y-coordinate then only draw one line
  600.         beq.S        EndDrawIt
  601.         move.w        D4,D0        ; Draw the rest of the rectangle
  602.         move.w        D5,D1
  603.         move.l        A2,A1
  604.         CallLib        Draw
  605.         move.w        D2,D0
  606.         move.w        D5,D1
  607.         move.l        A2,A1
  608.         CallLib        Draw
  609.         move.w        D2,D0
  610.         move.w        D3,D1
  611.         addq.w        #1,D1        ; Prevent 'round' corner
  612.         move.l        A2,A1
  613.         CallLib        Draw
  614. EndDrawIt    moveq        #1,D0
  615.         move.l        A2,A1
  616.         CallLib        SetDrMd
  617.         Pop        D0-D5/A0-A1/A6
  618.         rts
  619.  
  620. * Call:  A0 = where to put it, D0 = number, D1 = count
  621. DecStr        subq.w        #1,D1
  622.         bra.S        2$
  623. 1$        move.b        #' ',(A0)+
  624. 2$        dbf        D1,1$
  625.         moveq        #'0',D1
  626.         move.b        D1,(A0)+
  627.         ext.l        D0
  628. 3$        tst.l        D0
  629.         beq.S        4$
  630.         divu        #10,D0
  631.         swap        D0
  632.         add.w        D1,D0
  633.         move.b        D0,-(A0)
  634.         clr.w        D0
  635.         swap        D0
  636.         bra.S        3$
  637. 4$        rts
  638.  
  639.  
  640. * Open a window on the Workbench screen and bring it to the front
  641. OpenW        Push        D0-D7/A0-A6
  642.         move.w        pw(DB),D0
  643.         moveq        #4,D1
  644.         lea        TxtSize+6(PC),A0
  645.         Call        DecStr
  646.         move.w        ph(DB),D0
  647.         moveq        #4,D1
  648.         lea        TxtSize+13(PC),A0
  649.         Call        DecStr
  650.         moveq        #0,D0
  651.         move.l        WScreen(DB),A0
  652.         move.b        sc_BitMap+bm_Depth(A0),D0
  653.         moveq        #2,D1
  654.         lea        TxtSize+20(PC),A0
  655.         Call        DecStr
  656.         Prepare        Intuition_Call
  657.         lea        NW(PC),A0
  658.         CallLib        OpenWindow
  659.         move.l        D0,PWindow(DB)
  660.         beq.S        1$
  661.         move.l        D0,A0
  662.         move.l        wd_UserPort(A0),Up(DB)
  663.         move.l        PTitle(DB),A1
  664.         lea        ScrTitle(PC),A2
  665.         CallLib        SetWindowTitles
  666.         move.l        PWindow(DB),A0
  667.         move.l        wd_WScreen(A0),A0
  668.         CallLib        ScreenToFront
  669. 1$        tst.l        PWindow(DB)
  670.         Pop        D0-D7/A0-A6
  671.         rts
  672.  
  673. * Close the window on the Workbench screen if it is open
  674. CloseW        Push        D0-D7/A0-A6
  675.         Prepare        Intuition_Call
  676.         move.l        PWindow(DB),D0
  677.         beq.S        1$
  678.         move.l        D0,A0
  679.         lea        NW(PC),A1
  680.         movem.w        wd_LeftEdge(A0),D0-D1
  681.         movem.w        D0-D1,nw_LeftEdge(A1)
  682.         CallLib        CloseWindow
  683.         clr.l        Up(DB)
  684.         clr.l        PWindow(DB)
  685.         move.l        WScreen(DB),A0
  686.         CallLib        ScreenToFront
  687. 1$        Pop        D0-D7/A0-A6
  688.         rts
  689.  
  690. FHandle        EQUR        D5
  691. * Call: D0 = Msg-number
  692. CONMsg        Push        D0-D7/A0-A6
  693.         Prepare        Dos_Call
  694.         move.l        D0,D4
  695.         moveq        #0,D6
  696.         CallLib        Output
  697.         move.l        D0,FHandle
  698.         bne.S        1$
  699.         moveq        #1,D6
  700.         lea        CONName(PC),A0
  701.         move.l        A0,D1
  702.         move.l        #MODE_OLDFILE,D2
  703.         CallLib        Open
  704.         move.l        D0,FHandle
  705.         beq.S        2$
  706. 1$        moveq        #INFOMSG,D0
  707.         Call        SendMsg
  708.         move.l        D4,D0
  709.         Call        SendMsg
  710.         tst.l        D6
  711.         beq.S        2$
  712.         moveq        #127,D1
  713.         CallLib        Delay
  714.         move.l        FHandle,D1
  715.         CallLib        Close
  716. 2$        Pop        D0-D7/A0-A6
  717.         rts
  718.  
  719. * Call: D0 = Msg-number
  720. SendMsg        neg.l        D0
  721.         lsl.l        #1,D0
  722.         lea        MsgTable(PC),A0
  723.         add.w        0(A0,D0),A0
  724.         move.l        A0,D2
  725.         moveq        #-1,D3
  726. 1$        addq.l        #1,D3
  727.         tst.b        (A0)+
  728.         bne.S        1$
  729.         move.l        FHandle,D1
  730.         Prepare        Dos_Call
  731.         CallLib        Write
  732.         rts
  733.  
  734. INFOMSG        =0
  735. INSTALLED    =-1
  736. REMOVED        =-2
  737. CANTINSTALL    =-3
  738. CANTREMOVE    =-4
  739.  
  740. MsgText        MACRO
  741.         dc.w        \1-MsgTable
  742.         ENDM
  743. MsgTable    MsgText        Msg
  744.         MsgText        Msg1
  745.         MsgText        Msg2
  746.         MsgText        Msg3
  747.         MsgText        Msg4
  748.  
  749. CONName        dc.b        'CON:100/60/330/63/PicSaver',0
  750. Msg        dc.b        10,$9B,'0;33m PicSaver V1.0',10
  751.         dc.b        $9B,'0;31m 1991 by ',$9B,'0;33mPreben Nielsen',$9B,'0;31m',10,' ',0
  752. Msg1        dc.b        'has just been installed...',10,0
  753. Msg2        dc.b        'has just been removed...',10,0
  754. Msg3        dc.b        'Error: Cannot install handler',10,0
  755. Msg4        dc.b        'Error: Cannot remove handler',10,0
  756.         EVEN
  757.  
  758. rtsValue    EQUR        D7
  759. * This is general-purpose inputhandler removal-routine
  760. * It only needs an ihs with a port-name to remove the handler
  761. * Call:   A0 = ihs
  762. *      A1 = first ihs-installation-routine or NULL
  763. *      A2 = second ihs-installation-routine or NULL
  764. * Return: D0 = 0 means succes
  765. RemoveHandler    Push        D1/rtsValue/A0-A3/A6
  766.         moveq        #-1,rtsValue
  767.         move.l        A2,A3
  768.         move.l        A0,A2
  769.         move.l        A1,D1
  770.         beq.S        1$
  771.         jsr        (A1)        ; A0 = ihs
  772.         beq.S        2$
  773.         move.l        D0,A2
  774. 1$        move.l        A2,A0
  775.         Prepare        Exec_Call
  776.         moveq        #IND_REMHANDLER,D0
  777.         Call        TellInputDevice
  778.         move.l        D0,rtsValue
  779.         bne.S        2$
  780.         lea        ihs_Port(A2),A1
  781.         CallLib        RemPort
  782.         moveq        #0,D0
  783.         bra.S        3$
  784. 2$        moveq        #-1,D0
  785. 3$        move.l        A3,D1
  786.         beq.S        4$
  787.         move.l        A2,A0
  788.         jsr        (A3)        ; A0 = ihs, D0 = 0 means succes
  789. 4$        move.l        rtsValue,D0
  790.         Pop        D1/rtsValue/A0-A3/A6
  791.         rts
  792.  
  793. * This is general-purpose inputhandler installation-routine
  794. * It only needs an ihs with a port-name to install the handler
  795. * Call:   A0 = ihs
  796. *      A1 = first ihs-installation-routine or NULL
  797. *      A2 = second ihs-installation-routine or NULL
  798. * Return: D0 = 0 means succes
  799. InstallHandler    Push        D1/rtsValue/A0-A3/A6
  800.         moveq        #-1,rtsValue
  801.         move.l        A2,A3
  802.         move.l        A0,A2
  803.         move.l        A1,D1
  804.         beq.S        1$
  805.         jsr        (A1)        ; A0 = ihs
  806.         beq.S        2$
  807.         move.l        D0,A2
  808. 1$        move.l        A2,A0
  809.         moveq        #IND_ADDHANDLER,D0
  810.         Call        TellInputDevice
  811.         move.l        D0,rtsValue
  812.         bne.S        2$
  813.         lea        ihs_Port(A2),A1
  814.         lea        ihs_PortName(A2),A0
  815.         move.l        A0,MP+LN_NAME(A1)        ;MsgPort->mp_Node.ln_Name=Name;
  816.         clr.b        MP+LN_PRI(A1)            ;MsgPort->mp_Node.ln_Pri =0;
  817.         move.b        #NT_MSGPORT,MP+LN_TYPE(A1)    ;MsgPort->mp_Node.ln_Type=NT_MSGPORT;
  818.         move.b        #PA_IGNORE,MP_FLAGS(A1)        ;MsgPort->mp_Flags     =PA_IGNORE;
  819.         Prepare        Exec_Call
  820.         CallLib        AddPort
  821.         moveq        #0,D0
  822.         bra.S        3$
  823. 2$        moveq        #-1,D0
  824. 3$        move.l        A3,D1
  825.         beq.S        4$
  826.         move.l        A2,A0
  827.         jsr        (A3)        ; A0 = ihs, D0 = 0 means succes
  828. 4$        move.l        rtsValue,D0
  829.         Pop        D1/rtsValue/A0-A3/A6
  830.         rts
  831.  
  832. * Open the input device. Set up the I/O block to add or remove the
  833. * input handler, and send the request to the input device. Finally,
  834. * close the device
  835. * Call:   A0 = ihs
  836. *      D0 = Function to perform (IND_ADDHANDLER/IND_REMHANDLER)
  837. * Return: D0 = 0 means succes
  838. TellInputDevice    Push        D1-D2/rtsValue/A0-A3/A6
  839.         Prepare        Exec_Call
  840.         moveq        #-1,rtsValue
  841.         move.l        D0,D2
  842.         move.l        A0,A2
  843.         lea        IReq(DB),A0
  844.         moveq        #IOSTD_SIZE,D0
  845.         Call        MemClear
  846.         lea        IPort(DB),A0
  847.         moveq        #MP_SIZE,D0
  848.         Call        MemClear
  849.         move.l        A0,A3
  850.         move.b        #NT_MSGPORT,MP+LN_TYPE(A3)    ; mp_Node.ln_Type=NT_MSGPORT;
  851.         move.b        #PA_SIGNAL,MP_FLAGS(A3)        ; mp_Flags    =PA_SIGNAL;
  852.         moveq        #-1,D0
  853.         CallLib        AllocSignal
  854.         move.b        D0,MP_SIGBIT(A3)        ; mp_SigBit    =MPSigBit;
  855.         bmi.S        2$
  856.         suba.l        A1,A1
  857.         CallLib        FindTask
  858.         move.l        D0,MP_SIGTASK(A3)        ; mp_SigTask     =FindTask(0);
  859.         lea        IReq(DB),A1
  860.         move.l        A3,IO+MN_REPLYPORT(A1)        ; ExtReq->io_Message.mn_ReplyPort   =taskReplyPort;
  861.         move.b        #NT_MESSAGE,IO+MN+LN_TYPE(A1)    ; ExtReq->io_Message.mn_Node.ln_Type=NT_MESSAGE;
  862.         lea        InputName(PC),A0        ; input.device
  863.         moveq        #0,D0                ; unit#
  864.         moveq        #0,D1                ; flags
  865.         CallLib        OpenDevice
  866.         tst.w        D0                ; flag: error if > 0
  867.         bne.S        1$
  868.         lea        IReq(DB),A1
  869.         move.w        D2,IO_COMMAND(A1)
  870.         lea        ihs_Interrupt(A2),A0
  871.         move.l        A0,IO_DATA(A1)
  872.         CallLib        DoIO
  873.         move.l        D0,rtsValue
  874.         lea        IReq(DB),A1
  875.         CallLib        CloseDevice
  876. 1$        move.b        MP_SIGBIT(A3),D0
  877.         CallLib        FreeSignal
  878. 2$        move.l        rtsValue,D0
  879.         Pop        D1-D2/rtsValue/A0-A3/A6
  880.         rts
  881.  
  882. * Call: A0    = Memory area
  883. *    D0:16 = Count
  884. MemClear    Push        D0-D1/A0
  885.         moveq        #0,D1
  886.         bra.S        2$
  887. 1$        move.b        D1,(A0)+
  888. 2$        dbf        D0,1$
  889.         Pop        D0-D1/A0
  890.         rts
  891.  
  892. * Call: A0   = Source
  893. *    A1   = Destination
  894. *    D0:16= Count
  895. MemCopy        Push        D0/A0-A1
  896.         bra.S        2$
  897. 1$        move.b        (A0)+,(A1)+
  898. 2$        dbf        D0,1$
  899.         Pop        D0/A0-A1
  900.         rts
  901.  
  902. * Each handler should have such a pair of installation-routine
  903. * The first one is passed to InstallHandler in A1 and it
  904. * is called immediately when entering InstallHandler
  905. * The second one is passed to InstallHandler in A2 and it
  906. * is called if installation of handler and message-port succeds
  907. * -----------------------------------------------------------------
  908. * Call:   A0 = ihs
  909. * Return: D0 has to point to ihs to be used when installation proceeds
  910. *      If D0 = 0 then installation is aborted
  911. PSPrepIHS1    Push        A0-A1
  912.         move.b        #PORT_B,ihs_Port+MP_SIGBIT(A0)    ;MsgPort->mp_SigBit     =MPSigBit;
  913.         move.l        PProcess(DB),ihs_Port+MP_SIGTASK(A0);MsgPort->mp_SigTask =FindTask(0);
  914.         move.l        #HandlerSize,ihs_Length(A0)    ; This will enable removal by other programs
  915.         lea        HandlerCode-IHS(A0),A1
  916.         move.l        A1,ihs_Interrupt+IS_CODE(A0)    ; HandlerBlock.HInterrupt.is_Code = Handler
  917.         move.l        DB,ihs_Interrupt+IS_DATA(A0)    ; HandlerBlock.HInterrupt.is_Data = DB
  918.         move.b        #HPRI,ihs_Interrupt+LN_PRI(A0)    ; HandlerBlock.HInterrupt.is_Node.ln_Pri = PRI
  919.         move.l        A0,D0
  920.         Pop        A0-A1
  921.         rts
  922. * Call:   A0 = ihs
  923. PSPrepIHS2    rts
  924.  
  925. * Each handler should have such a pair of ending-routine
  926. * The first one is passed to RemoveHandler in A1 and it
  927. * is called immediately when entering RemoveHandler
  928. * The second one is passed to RemoveHandler in A2 and it
  929. * is called if removal of handler and message-port succeds
  930. * -----------------------------------------------------------------
  931. * Call:   A0 = ihs
  932. * Return: D0 has to point to ihs to be used when removal proceeds
  933. *      If D0 = 0 then removal is aborted
  934. PSEndIHS1    Push        D1-D2/A0-A1/A6
  935.         Prepare        Exec_Call
  936.         CallLib        Forbid
  937.         lea        ihs_PortName(A0),A1
  938.         CallLib        FindPort
  939.         move.l        D0,D2
  940.         CallLib        Permit
  941.         move.l        D2,D0            ; Does Forbid/Permit destroy scratch-registers ?
  942.         Pop        D1-D2/A0-A1/A6
  943.         rts
  944. * Call:   A0 = ihs
  945. PSEndIHS2    rts
  946.  
  947. *====================== Input-handler start =========================
  948. ihs_Port    =0
  949. ihs_Interrupt    =MP_SIZE
  950. ihs_ID        =MP_SIZE+IS_SIZE
  951. ihs_Length    =MP_SIZE+IS_SIZE+4
  952. ihs_Flags    =MP_SIZE+IS_SIZE+8
  953. ihs_PortName    =MP_SIZE+IS_SIZE+10
  954.  
  955. ihs_Start    MACRO
  956.         dcb.b        MP_SIZE        ; Message-Port structure
  957.         dcb.b        IS_SIZE        ; Interrupt structure
  958.         dc.l        'P_IH'        ; ID
  959.         dc.l        0        ; Length of handler 
  960.         dc.w        0        ; Flags
  961.         dc.b        \1,0
  962.         EVEN
  963.         ENDM
  964.  
  965. HPRI        =51
  966. HDisabled    =0
  967. HNoExtRemoval    =1
  968.  
  969. * This is the handler-block
  970. IHS        ihs_Start    <'PicSaver V1.0 Port'>
  971. * Local variables
  972. Chain        dc.l        0
  973. * For each event in the event list:
  974. *  If we were waiting for this event then signal the task.
  975. * When all the events have been checked, return the event list so that
  976. * others can do their things.
  977. PEvent        EQUR    A3                ; Previous Event
  978. Event        EQUR    A5                ; This Event
  979. Signals        EQUR    D7
  980. Next        =ie_NextEvent
  981. Class        =ie_Class
  982. Code        =ie_Code
  983. Qual        =ie_Qualifier
  984. * These are the qualifier-keys the input-handler waits for
  985. QUALIFIERS    =IEQUALIFIER_LALT|IEQUALIFIER_LSHIFT|IEQUALIFIER_CONTROL
  986. * This is the key the input-handler exits on
  987. Quit_Key    =$45                    ; ESC
  988. Window_Key    =$11                    ; w
  989. Screen_Key    =$21                    ; s
  990.  
  991. * Call:  A0 = List of InputEvents, A1 = HandlerData
  992. HandlerCode    Push        D1/Signals/A0-A1/PEvent/DB/Event/A6
  993.         moveq        #0,Signals
  994.         move.l        A1,DB
  995.         move.w        IHS+ihs_Flags(PC),D0
  996.         btst        #HDisabled,D0        ; Future feature
  997.         bne        NoMoreEvents
  998.         lea        Chain(PC),PEvent
  999.         move.l        A0,Next(PEvent)
  1000. ieLoop        move.l        Next(PEvent),Event
  1001.         move.l        Event,D0
  1002.         beq        NoMoreEvents
  1003.         cmpi.b        #IECLASS_NULL,Class(Event)
  1004.         beq        DontRemove
  1005.         cmpi.b        #IECLASS_TIMER,Class(Event)
  1006.         beq        DontRemove
  1007.         move.w        Qual(Event),D0
  1008.         andi.w        #QUALIFIERS,D0
  1009.         cmp.w        #QUALIFIERS,D0
  1010.         bne        NoQual
  1011.         cmpi.b        #IECLASS_RAWKEY,Class(Event)
  1012.         bne.S        1$
  1013.         cmp.w        #Quit_Key,Code(Event)
  1014.         beq.S        DoQuit
  1015.         cmp.w        #Window_Key,Code(Event)
  1016.         beq.S        DoWindow
  1017.         cmp.w        #Screen_Key,Code(Event)
  1018.         beq.S        DoScreen
  1019.         bra.S        IsQual
  1020.         bra.S        DontRemove
  1021. 1$        btst        #DISABLED,Status(DB)
  1022.         bne.S        DontRemove
  1023.         cmpi.b        #IECLASS_RAWMOUSE,Class(Event)
  1024.         bne.S        DontRemove
  1025.         cmpi.w        #IECODE_LBUTTON,Code(Event)
  1026.         beq.S        DoStart
  1027.         cmpi.w        #IECODE_UP_PREFIX|IECODE_LBUTTON,Code(Event)
  1028.         beq.S        DoEnd
  1029.         move.w        Qual(Event),D0
  1030.             andi.w        #IEQUALIFIER_RELATIVEMOUSE,D0
  1031.         beq.S        DontRemove
  1032. DoMove        move.b        Status(DB),D0
  1033.         andi.b        #1<<RECTANGLE|1<<CROSSHAIR,D0
  1034.         beq.S        DontRemove
  1035.         bset        #MOVE_B,Signals
  1036.         bra.S        DontRemove
  1037. DoEnd        btst        #RECTANGLE,Status(DB)
  1038.         beq.S        DontRemove
  1039.         bset        #LMB_RELEASE_B,Signals
  1040.         bra.S        DontRemove
  1041. DoStart        bset        #LMB_PRESS_B,Signals
  1042.         bra.S        Remove
  1043. DoWindow    bset        #WINDOW_B,Signals
  1044.         bra.S        Remove
  1045. DoScreen    bset        #SCREEN_B,Signals
  1046.         bra.S        Remove
  1047. DoQuit        bset        #QUIT_B,Signals
  1048.         bra.S        Remove
  1049. IsQual        move.b        Status(DB),D0
  1050.         andi.b        #1<<RECTANGLE|1<<CROSSHAIR,D0
  1051.         bne.S        DontRemove
  1052.         bset        #QUAL_PRESS_B,Signals
  1053.         bra.S        DontRemove
  1054. NoQual        move.b        Status(DB),D0
  1055.         andi.b        #1<<RECTANGLE|1<<CROSSHAIR,D0
  1056.         beq.S        DontRemove
  1057.         bset        #QUAL_RELEASE_B,Signals
  1058. * Just move on to next Event
  1059. DontRemove    move.l        Event,PEvent
  1060.         bra        ieLoop
  1061. * Remove event from chain and move on to next Event
  1062. Remove        move.l        Next(Event),Next(PEvent)
  1063.         bra        ieLoop
  1064. * Lets return
  1065. NoMoreEvents    move.l        Signals,D0
  1066.         beq.S        1$
  1067.         Prepare        Exec_Call
  1068.         movea.l        PProcess(DB),A1
  1069.         CallLib        Signal
  1070. 1$        Pop        D1/Signals/A0-A1/PEvent/DB/Event/A6
  1071.         move.l        Chain(PC),D0        ; Return (shortened ?) chain
  1072.         rts
  1073. HandlerSize    =        *-IHS
  1074. *====================== Input-handler end ===========================
  1075.  
  1076. *====================== Picture-saver start =========================
  1077. PicScreen    =0
  1078. PicName        =4
  1079. PicX        =8
  1080. PicY        =10
  1081. PicWidth    =12
  1082. PicHeight    =14
  1083. PicCompression    =16
  1084. Pic_SIZE    =18
  1085.  
  1086. PicDefine    dc.l    0,0
  1087.         dc.w    0,0,0,0,0
  1088.  
  1089. SaveRect    Push        D0-D1/A0-A1
  1090.         lea        PicDefine(PC),A1
  1091.         lea        FBuffer(DB),A0
  1092.         move.l        A0,PicName(A1)
  1093.         move.l        WScreen(DB),PicScreen(A1)
  1094.         move.w        px(DB),PicX(A1)
  1095.         move.w        pw(DB),PicWidth(A1)
  1096.         move.w        py(DB),PicY(A1)
  1097.         move.w        ph(DB),PicHeight(A1)
  1098.         move.w        #1,PicCompression(A1)
  1099.         lea        PicDefine(PC),A0
  1100.         Call        SaveILBM
  1101.         Pop        D0-D1/A0-A1
  1102.         rts
  1103.  
  1104. ILBMHDSize    =20
  1105. BMHDSize    =20
  1106. ILBMHeader    dc.b        'FORM'
  1107.         dc.l        0
  1108.         dc.b        'ILBM'
  1109.         dc.b        'BMHD'
  1110.         dc.l        BMHDSize
  1111. BMHeader    dc.w        0,0    ; raster width, height in pixels
  1112.         dc.w        0,0    ; x,y pixel position for this image
  1113.         dc.b        0    ; # source bitplanes
  1114.         dc.b        0    ; masking
  1115.         dc.b        0    ; compression
  1116.         dc.b        0    ; unused; for consistency, put 0 here
  1117.         dc.w        0    ; transparent 'color number'
  1118.         dc.b        1,1    ; pixel aspect, a ratio width : height
  1119.         dc.w        0,0    ; source 'page' size in pixels
  1120. CAMGHDSize    =8
  1121. CAMGHeader    dc.b        'CAMG'
  1122.         dc.l        4
  1123.         dc.l        0
  1124. CMAPHDSize    =8
  1125. CMAPHeader    dc.b        'CMAP'
  1126.         dc.l        0
  1127. BODYHDSize    =8
  1128. BODYHeader    dc.b        'BODY'
  1129.         dc.l        0
  1130.  
  1131. * Call:   A0 = PicDefine
  1132. * Return: D0 = 0 means succes
  1133. SaveILBM    Push        D1-D7/A0-A6
  1134.         clr.l        Pic_Total(DB)
  1135.         move.l        PicScreen(A0),Pic_Screen(DB)
  1136.         move.l        PicName(A0),Pic_FileName(DB)
  1137.         move.w        PicCompression(A0),Pic_Compression(DB)
  1138.         move.w        PicX(A0),D0
  1139.         move.w        D0,Pic_x(DB)
  1140.         move.w        PicWidth(A0),D1
  1141.         move.w        D1,Pic_Width(DB)
  1142.         add.w        D1,D0
  1143.         move.w        D0,Pic_EndCol(DB)
  1144.         move.w        PicY(A0),D0
  1145.         move.w        D0,Pic_y(DB)
  1146.         move.w        PicHeight(A0),D1
  1147.         move.w        D1,Pic_Height(DB)
  1148.         add.w        D1,D0
  1149.         move.w        D0,Pic_EndRow(DB)
  1150.         move.w        Pic_x(DB),D0
  1151.         ext.l        D0
  1152.         divu        #8,D0
  1153.         move.w        D0,Pic_SkipBytes(DB)    ; How many bytes should I skip at the beginning of each row
  1154.         swap        D0
  1155.         move.w        D0,Pic_LShift(DB)    ; How often should I shift bits to the left
  1156.         move.w        Pic_Width(DB),D0    ; Calculate bytes per line (word aligned)
  1157.         add.w        #15,D0
  1158.         lsr.w        #3,D0
  1159.         bclr        #0,D0
  1160.         move.w        D0,Pic_BytesPerRow(DB)
  1161.         lsl.w        #3,D0
  1162.         sub.w        Pic_Width(DB),D0
  1163.         ext.l        D0
  1164.         moveq        #-1,D1
  1165.         lsl.w        D0,D1
  1166.         move.w        D1,Pic_EndMask(DB)    ; Bits to cut of at the end of each line
  1167.         move.l        Pic_Screen(DB),A0
  1168.         lea        sc_BitMap(A0),A1
  1169.         move.l        A1,Pic_BitMap(DB)
  1170.         move.b        bm_Depth(A1),Pic_Depth+1(DB)
  1171.         move.w        bm_BytesPerRow(A1),Pic_BMBytesPerRow(DB)
  1172.         lea        sc_ViewPort(A0),A1
  1173.         move.l        A1,Pic_ViewPort(DB)
  1174.         move.w        vp_Modes(A1),D0
  1175.         and.w        #V_HIRES|V_HAM|V_LACE,D0
  1176.         move.w        D0,Pic_ViewMode(DB)
  1177.         move.l        vp_ColorMap(A1),A1
  1178.         move.l        cm_ColorTable(A1),Pic_ColorTable(DB)
  1179.         lea        PBuffer1(DB),A0
  1180.         move.l        A0,Pic_ByteBuffer(DB)
  1181.         lea        PBuffer2(DB),A0
  1182.         move.l        A0,Pic_PackBuffer(DB)
  1183.         lea        BMHeader(PC),A0
  1184.         move.w        Pic_Width(DB),(A0)
  1185.         move.w        Pic_Height(DB),2(A0)
  1186.         move.w        Pic_Width(DB),16(A0)
  1187.         move.w        Pic_Height(DB),16+2(A0)
  1188.         move.b        Pic_Depth+1(DB),8(A0)
  1189.         move.b        Pic_Compression+1(DB),10(A0)
  1190.         Prepare        Dos_Call
  1191.         move.l        Pic_FileName(DB),D1
  1192.         move.l        #MODE_NEWFILE,D2
  1193.         CallLib        Open
  1194.         move.l        D0,Pic_FileHandle(DB)
  1195.         beq        NoPicFile
  1196.         lea        CAMGHeader(PC),A0
  1197.         move.w        Pic_ViewMode(DB),2+8(A0)
  1198.         lea        ILBMHeader(PC),A0    ; Write ILBM File Header
  1199.         moveq        #ILBMHDSize+BMHDSize+CAMGHDSize+4+CMAPHDSize-4,D0
  1200.         Call        WriteBytes
  1201.         bne        WriteError
  1202.         move.w        Pic_Depth(DB),D1
  1203.         moveq        #0,D3
  1204.         bset        D1,D3            ; Number of colours (2^depth)
  1205.         move.l        D3,D4
  1206.         mulu        #3,D4
  1207.         move.l        Pic_ByteBuffer(DB),A0    ; Write CMAP
  1208.         move.l        D4,(A0)+
  1209.         move.l        Pic_ColorTable(DB),A1
  1210.         moveq        #$F0-256,D5        ; Tricky way to make D5=FFF0
  1211.         bra.S        2$
  1212. 1$        move.w        (A1)+,D0        ; Copy colours into buffer
  1213.         move.w        D0,D1
  1214.         move.w        D0,D2
  1215.         lsr.w        #4,D0
  1216.         lsl.w        #4,D2
  1217.         and.w        D5,D0
  1218.         and.w        D5,D1
  1219.         and.w        D5,D2
  1220.         move.b        D0,(A0)+
  1221.         move.b        D1,(A0)+
  1222.         move.b        D2,(A0)+
  1223. 2$        dbra        D3,1$
  1224.         move.l        Pic_ByteBuffer(DB),A0
  1225.         move.l        D4,D0
  1226.         addq.l        #4,D0
  1227.         Call        WriteBytes
  1228.         bne        WriteError
  1229.         Call        WritePad        ; Unnecessary
  1230.         bne        WriteError
  1231.         move.l        Pic_Total(DB),Pic_BODYPos(DB)    ; We have to get back here
  1232.         lea        BODYHeader(PC),A0
  1233.         moveq        #BODYHDSize,D0
  1234.         Call        WriteBytes
  1235.         bne        WriteError
  1236.         move.w        Pic_y(DB),D7        ; Current row = D7
  1237.         subq.w        #1,D7
  1238. RowLoop        addq.w        #1,D7
  1239.         cmp.w        Pic_EndRow(DB),D7    ; Last row ?
  1240.         beq.S        DonePlanes
  1241.         move.l        Pic_BitMap(DB),A2
  1242.         lea        bm_Planes(A2),A2    ; Get pointer to bitplane
  1243.         move.w        Pic_Depth(DB),Pic_Looper(DB)
  1244. PlaneLoop    subq.w        #1,Pic_Looper(DB)
  1245.         bmi.S        RowLoop
  1246.         move.l        (A2)+,A0
  1247.         move.w        Pic_BMBytesPerRow(DB),D0; Offset
  1248.         mulu        D7,D0
  1249.         add.l        D0,A0
  1250.         add.w        Pic_SkipBytes(DB),A0    ; Skip some bytes
  1251.         move.l        Pic_ByteBuffer(DB),A1    ; Copy row to buffer
  1252.         move.w        Pic_BytesPerRow(DB),D0
  1253.         bra.S        2$
  1254. 1$        move.b        (A0)+,(A1)+
  1255. 2$        dbra        D0,1$
  1256.         moveq        #0,D2
  1257.         move.w        Pic_LShift(DB),D2    ; Shift bits to the left
  1258.         beq.S        NoPicShift
  1259.         move.l        Pic_ByteBuffer(DB),A0
  1260.         move.w        Pic_BytesPerRow(DB),D0
  1261.         addq.w        #1,D0            ; If you save byte alligned
  1262.         lsr.w        #1,D0
  1263.         bra.S        4$
  1264. 3$        move.l        (A0),D1            ; Copy four words to d1
  1265.         lsl.l        D2,D1            ; Now move bits of 2nd word into the 1st word
  1266.         swap        D1
  1267.         move.w        D1,(A0)+        ; Copy 1st word back to buffer
  1268. 4$        dbra        D0,3$
  1269.         move.w        Pic_EndMask(DB),D0
  1270.         and.w        D0,-(A0)
  1271. NoPicShift    moveq        #0,D0
  1272.         move.w        Pic_BytesPerRow(DB),D0
  1273.         cmp.w        #1,Pic_Compression(DB)
  1274.         bne.S        NotPacked
  1275.         Call        Packer
  1276. NotPacked    move.l        Pic_PackBuffer(DB),A0
  1277.         Call        WriteBytes
  1278.         bne.S        WriteError
  1279.         bra.S        PlaneLoop        ; Next bitplane
  1280. DonePlanes    Call        WritePad
  1281.         bne.S        WriteError
  1282.         move.l        Pic_FileHandle(DB),D1    ; Write BODY size
  1283.         move.l        Pic_BODYPos(DB),D2
  1284.         moveq        #OFFSET_BEGINNING,D3
  1285.         CallLib        Seek
  1286.         lea        BODYHeader(PC),A0
  1287.         move.l        Pic_Total(DB),D0
  1288.         sub.l        Pic_BODYPos(DB),D0
  1289.         subq.l        #BODYHDSize,D0
  1290.         move.l        D0,4(A0)
  1291.         moveq        #BODYHDSize,D0
  1292.         Call        WriteBytes
  1293.         bne.S        WriteError
  1294.         move.l        Pic_FileHandle(DB),D1    ; Write FORM size
  1295.         moveq        #0,D2
  1296.         moveq        #OFFSET_BEGINNING,D3
  1297.         CallLib        Seek
  1298.         lea        ILBMHeader(PC),A0
  1299.         move.l        Pic_Total(DB),D0
  1300.         sub.l        #8+BODYHDSize,D0
  1301.         move.l        D0,4(A0)
  1302.         moveq        #ILBMHDSize,D0
  1303.         Call        WriteBytes
  1304.         bne.S        WriteError
  1305.         move.l        Pic_FileHandle(DB),D1
  1306.         CallLib        Close
  1307.         moveq        #0,D0
  1308.         bra.S        DoneSaveILBM
  1309. WriteError    move.l        Pic_FileHandle(DB),D1
  1310.         CallLib        Close
  1311.         move.l        Pic_FileName(DB),D1
  1312.         CallLib        DeleteFile
  1313. NoPicFile    moveq        #-1,D0
  1314. DoneSaveILBM    tst.l        D0
  1315.         Pop        D1-D7/A0-A6
  1316.         rts
  1317.  
  1318. WritePad    btst        #0,Pic_Total+3(DB)
  1319.         beq.S        WRet
  1320.         move.l        Pic_ByteBuffer(DB),A0
  1321.         clr.b        (A0)
  1322.         moveq        #1,D0
  1323. * Write D0 bytes from A0
  1324. * A0 = Buffer, D0=Count
  1325. WriteBytes    move.l        Pic_FileHandle(DB),D1
  1326.         move.l        A0,D2
  1327.         move.l        D0,D3
  1328.         add.l        D0,Pic_Total(DB)
  1329.         CallLib        Write
  1330.         cmp.l        D3,D0
  1331. WRet        rts
  1332.  
  1333. Packer        Push        D1/A0-A3
  1334.         move.l        Pic_PackBuffer(DB),A0    ; A0=buffer
  1335.         move.l        Pic_ByteBuffer(DB),A1    ; A1=row
  1336.         move.l        A1,A3                
  1337.         add.w        Pic_BytesPerRow(DB),A3    ; A3=end of row
  1338. PackLoop    cmp.l        A3,A1
  1339.         bge.S        PackExit
  1340.         move.l        A1,A2
  1341. 1$        cmp.l        A3,A2
  1342.         bge.S        2$
  1343.         move.b        (A2)+,D0
  1344.         cmp.b        (A2),D0
  1345.         bne.S        1$
  1346.         subq.l        #1,A2
  1347. 2$        move.l        A2,D1
  1348.         sub.l        A1,D1
  1349.         beq.S        PackIt            ; Are there bytes between two parts of identical bytes
  1350.         subq.w        #1,D1            ; Code = n-1
  1351.         move.b        D1,(A0)+
  1352. 3$        move.b        (A1)+,(A0)+        ; Copy bytes
  1353.         dbra        D1,3$
  1354.         bra.S        PackLoop
  1355. PackIt        move.l        A1,A2
  1356. 1$        cmp.l        A3,A1
  1357.         beq.S        2$
  1358.         cmp.b        (A1)+,D0
  1359.         beq.S        1$
  1360.         subq.l        #1,A1
  1361. 2$        move.l        A1,D1
  1362.         sub.l        A2,D1
  1363.         neg.w        D1            ; Code = -n+1
  1364.         addq.w        #1,D1
  1365.         move.b        D1,(A0)+
  1366.         move.b        D0,(A0)+
  1367.         bra.S        PackLoop
  1368. PackExit    move.l        A0,D0
  1369.         sub.l        Pic_PackBuffer(DB),D0
  1370. 1$        Pop        D1/A0-A3
  1371.         rts
  1372.  
  1373.  
  1374. *====================== Picture-saver end ===========================
  1375.  
  1376. *====================== Data-definition start =======================
  1377.  rStart
  1378.  rAPtr        PProcess
  1379.  rAPtr        WBMsg
  1380.  rAPtr        DosBase
  1381.  rAPtr        GfxBase
  1382.  rAPtr        IntBase
  1383.  rAPtr        Rp
  1384.  rAPtr        Up
  1385.  rAPtr        WScreen
  1386.  rAPtr        WWindow
  1387.  rAPtr        PWindow
  1388.  rAPtr        PTitle
  1389.  rWord        Status
  1390.  rWord        sh
  1391.  rWord        sw
  1392.  rWord        sx
  1393.  rWord        sy
  1394.  rWord        ex
  1395.  rWord        ey
  1396.  rWord        px
  1397.  rWord        py
  1398.  rWord        pw
  1399.  rWord        ph
  1400.  rStorage    IReq,IOSTD_SIZE
  1401.  rStorage    IPort,MP_SIZE
  1402.  rStorage    FBuffer,FileBufSIZE
  1403.  
  1404.  rAPtr        Pic_FileName
  1405.  rAPtr        Pic_FileHandle
  1406.  rAPtr        Pic_ByteBuffer
  1407.  rAPtr        Pic_PackBuffer
  1408.  rLong        Pic_BODYPos
  1409.  rWord        Pic_x
  1410.  rWord        Pic_y
  1411.  rWord        Pic_Width
  1412.  rWord        Pic_Height
  1413.  rWord        Pic_EndCol
  1414.  rWord        Pic_EndRow
  1415.  rWord        Pic_Depth
  1416.  rWord        Pic_BytesPerRow
  1417.  rWord        Pic_BMBytesPerRow
  1418.  rWord        Pic_SkipBytes
  1419.  rWord        Pic_LShift
  1420.  rWord        Pic_EndMask
  1421.  rWord        Pic_ViewMode
  1422.  rWord        Pic_Compression
  1423.  rAPtr        Pic_Screen
  1424.  rAPtr        Pic_BitMap
  1425.  rAPtr        Pic_ViewPort
  1426.  rAPtr        Pic_ColorTable
  1427.  rWord        Pic_Looper
  1428.  rLong        Pic_Total
  1429.  rStorage    PBuffer1,164
  1430.  rStorage    PBuffer2,164
  1431.  rEnd
  1432.  
  1433. DosName        dc.b        'dos.library',0
  1434. GfxName        dc.b        'graphics.library',0
  1435. IntName        dc.b        'intuition.library',0
  1436. InputName    dc.b        'input.device',0
  1437. STitle        dc.b        'Save Screen as...',0
  1438. WTitle        dc.b        'Save Window as...',0
  1439. RTitle        dc.b        'Save Rectangle as...',0
  1440. ScrTitle    dc.b        'PicSaver V1.0 1991 by Preben Nielsen',0
  1441.         EVEN
  1442.  
  1443. IDCMP_Flags    =        GADGETUP|ACTIVEWINDOW
  1444. Other_Flags    =        NOCAREREFRESH|ACTIVATE|RMBTRAP|WINDOWDEPTH|WINDOWDRAG
  1445. WW        =240
  1446. WH        =64
  1447. NW        dc.w        300,200-WH,WW,WH
  1448.         dc.b        0,1
  1449.         dc.l        IDCMP_Flags,Other_Flags,GadgetList,0,0,0,0
  1450.         dc.w        0,0,0,0,WBENCHSCREEN
  1451. GadgetList
  1452. Gad1        Gadget        Gad2,56,30,FWIDTH,FHEIGHT,GADGHCOMP,RELVERIFY,STRGADGET
  1453.         Gadget2        FBorder,0,ITxtFile,0,FileInfo,ActivateFS-GJ,0
  1454. Gad2        Gadget        Gad3,15,46,BWIDTH,BHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET
  1455.         Gadget2        BBorder,0,ITxtPos,0,0,DoSave-GJ,0
  1456. Gad3        Gadget        0,151,46,BWIDTH,BHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET
  1457.         Gadget2        BBorder,0,ITxtNeg,0,0,DoCancel-GJ,0
  1458.  
  1459. FileInfo    dcb.b        si_SIZEOF,0
  1460.  
  1461. FWIDTH        =173
  1462. FHEIGHT        =11
  1463. FBorder        Border        -6,-3,1,0,1,9,FVectors,0
  1464. FVectors    dc.w        2,0,FWIDTH+1,0,FWIDTH+3,2,FWIDTH+3,FHEIGHT-1,FWIDTH+1,FHEIGHT+1,2,FHEIGHT+1,0,FHEIGHT-1,0,2,2,0
  1465. BWIDTH        =74
  1466. BHEIGHT        =11
  1467. BBorder        Border        -2,-1,1,0,1,9,BVectors,0
  1468. BVectors    dc.w        2,0,BWIDTH+1,0,BWIDTH+3,2,BWIDTH+3,BHEIGHT-1,BWIDTH+1,BHEIGHT+1,2,BHEIGHT+1,0,BHEIGHT-1,0,2,2,0
  1469.  
  1470. ITxtSize    IntuiText    1,0,1,-43,-15,TxtSize,0
  1471. ITxtFile    IntuiText    1,0,1,-43,0,TxtFile,ITxtSize
  1472. ITxtPos        IntuiText    1,0,1,21,2,TxtPos,0
  1473. ITxtNeg        IntuiText    1,0,1,14,2,TxtNeg,0
  1474. TxtSize        dc.b        'Size:    0 x    0 x  0',0
  1475. TxtFile        dc.b        'File',0
  1476. TxtPos        dc.b        'Save',0
  1477. TxtNeg        dc.b        'Cancel',0
  1478.         EVEN
  1479.  
  1480. ITxtAUTOBody    IntuiText    AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,8,4,TxtAUTOBody,0
  1481. ITxtAUTOOk    IntuiText    AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,6,3,TxtAUTOOk,0
  1482. TxtAUTOBody    dc.b        "PicSaver: Can't write file",0
  1483. TxtAUTOOk    dc.b        ' Ok ',0
  1484.  
  1485. TxtAttr        dc.l        FontName
  1486.         dc.w        TOPAZ_EIGHTY
  1487.         dc.b        FS_NORMAL,FPB_ROMFONT
  1488. FontName    dc.b        'topaz.font',0
  1489.         END
  1490.  
  1491. * These defines are here for quick reference only
  1492.  --- InputEvent.ie_Class ---
  1493. IECLASS_NULL        0x00    A NOP input event
  1494. IECLASS_RAWKEY        0x01    A raw keycode from the keyboard device
  1495. IECLASS_RAWMOUSE    0x02    The raw mouse report from the game port device
  1496. IECLASS_EVENT        0x03    A private console event
  1497. IECLASS_POINTERPOS    0x04    A Pointer Position report
  1498. IECLASS_TIMER        0x06    A timer event
  1499. IECLASS_GADGETDOWN    0x07    select button pressed down over a Gadget (address in ie_EventAddress)
  1500. IECLASS_GADGETUP    0x08    select button released over the same Gadget (address in ie_EventAddress)
  1501. IECLASS_REQUESTER    0x09    some Requester activity has taken place.  See Codes REQCLEAR and REQSET
  1502. IECLASS_MENULIST    0x0A    this is a Menu Number transmission (Menu number is in ie_Code)
  1503. IECLASS_CLOSEWINDOW    0x0B    User has selected the active Window's Close Gadget
  1504. IECLASS_SIZEWINDOW    0x0C    this Window has a new size
  1505. IECLASS_REFRESHWINDOW    0x0D    the Window pointed to by ie_EventAddress needs to be refreshed
  1506. IECLASS_NEWPREFS    0x0E    new preferences are available
  1507. IECLASS_DISKREMOVED    0x0F    the disk has been removed
  1508. IECLASS_DISKINSERTED    0x10    the disk has been inserted
  1509. IECLASS_ACTIVEWINDOW    0x11    the window is about to be made active
  1510. IECLASS_INACTIVEWINDOW    0x12    the window is about to be made inactive
  1511. IECLASS_MAX        0x12    the last class
  1512.  
  1513.   --- InputEvent.ie_Code ---
  1514. IECLASS_RAWKEY
  1515. IECODE_UP_PREFIX    0x80
  1516. IECODE_KEY_CODE_FIRST    0x00
  1517. IECODE_KEY_CODE_LAST    0x77
  1518. IECODE_COMM_CODE_FIRST    0x78
  1519. IECODE_COMM_CODE_LAST    0x7F
  1520.   
  1521. IECLASS_ANSI
  1522. IECODE_C0_FIRST        0x00
  1523. IECODE_C0_LAST        0x1F
  1524. IECODE_ASCII_FIRST    0x20
  1525. IECODE_ASCII_LAST    0x7E
  1526. IECODE_ASCII_DEL    0x7F
  1527. IECODE_C1_FIRST        0x80
  1528. IECODE_C1_LAST        0x9F
  1529. IECODE_LATIN1_FIRST    0xA0
  1530. IECODE_LATIN1_LAST    0xFF
  1531.   
  1532. IECLASS_RAWMOUSE
  1533. IECODE_LBUTTON        0x68    also uses IECODE_UP_PREFIX
  1534. IECODE_RBUTTON        0x69
  1535. IECODE_MBUTTON        0x6A
  1536. IECODE_NOBUTTON        0xFF
  1537.   
  1538. IECLASS_EVENT
  1539. IECODE_NEWACTIVE    0x01    active input window changed
  1540.  
  1541. IECLASS_REQUESTER Codes
  1542. REQSET is broadcast when the first Requester (not subsequent ones) opens
  1543. in the Window
  1544.  
  1545. IECODE_REQSET        0x01
  1546. REQCLEAR is broadcast when the last Requester clears out of the Window
  1547. IECODE_REQCLEAR        0x00
  1548.  
  1549.  --- InputEvent.ie_Qualifier ---
  1550. IEQUALIFIER_LSHIFT        0x0001
  1551. IEQUALIFIER_RSHIFT        0x0002
  1552. IEQUALIFIER_CAPSLOCK        0x0004
  1553. IEQUALIFIER_CONTROL        0x0008
  1554. IEQUALIFIER_LALT        0x0010
  1555. IEQUALIFIER_RALT        0x0020
  1556. IEQUALIFIER_LCOMMAND        0x0040
  1557. IEQUALIFIER_RCOMMAND        0x0080
  1558. IEQUALIFIER_NUMERICPAD        0x0100
  1559. IEQUALIFIER_REPEAT        0x0200
  1560. IEQUALIFIER_INTERRUPT        0x0400
  1561. IEQUALIFIER_MULTIBROADCAST    0x0800
  1562. IEQUALIFIER_MIDBUTTON        0x1000
  1563. IEQUALIFIER_RBUTTON        0x2000
  1564. IEQUALIFIER_LEFTBUTTON        0x4000
  1565. IEQUALIFIER_RELATIVEMOUSE    0x8000
  1566.  
  1567. IEQUALIFIERB_LSHIFT        0
  1568. IEQUALIFIERB_RSHIFT        1
  1569. IEQUALIFIERB_CAPSLOCK        2
  1570. IEQUALIFIERB_CONTROL        3
  1571. IEQUALIFIERB_LALT        4
  1572. IEQUALIFIERB_RALT        5
  1573. IEQUALIFIERB_LCOMMAND        6
  1574. IEQUALIFIERB_RCOMMAND        7
  1575. IEQUALIFIERB_NUMERICPAD        8
  1576. IEQUALIFIERB_REPEAT        9
  1577. IEQUALIFIERB_INTERRUPT        10
  1578. IEQUALIFIERB_MULTIBROADCAST    11
  1579. IEQUALIFIERB_MIDBUTTON        12
  1580. IEQUALIFIERB_RBUTTON        13
  1581. IEQUALIFIERB_LEFTBUTTON        14
  1582. IEQUALIFIERB_RELATIVEMOUSE    15
  1583.   
  1584. struct InputEvent
  1585. {
  1586.  struct  InputEvent *ie_NextEvent    ;the chronologically next event
  1587.  UBYTE   ie_Class            ;the input event class
  1588.  UBYTE   ie_SubClass            ;optional subclass of the class
  1589.  UWORD   ie_Code            ;the input event code
  1590.  UWORD   ie_Qualifier            ;qualifiers in effect for the event
  1591.  union
  1592.   {
  1593.    struct
  1594.     {
  1595.      WORD    ie_x            ;the pointer position for the event
  1596.      WORD    ie_y
  1597.     } ie_xy
  1598.    APTR    ie_addr
  1599.   } ie_position
  1600.   struct timeval ie_TimeStamp        ;the system tick at the event
  1601. };
  1602.  
  1603. ie_X            =ie_position.ie_xy.ie_x
  1604. ie_Y            =ie_position.ie_xy.ie_y
  1605. ie_EventAddress        =ie_position.ie_addr
  1606.  
  1607.