home *** CD-ROM | disk | FTP | other *** search
- ;***************************************************************************
- ; This program is an example of how to add a Rexx implementation to any
- ; program using the rexxapp.library. The original Freedraw program (without
- ; REXX) is from Fred Fish Disk 1. The rexxapp.library is based upon a C module
- ; by Radical Eye Software which was modified and down-coded to a 68000 shared
- ; library.
- ; All the REXX stuff is bracketed by IFNE TALKTOREXX, so you can identify it
- ; easily. If you assemble with TALKTOREXX equ 0, you will get the default
- ; program with no REXX port. The REXX port on this program increases the
- ; executable slightly, but a lot of functionality comes with that. You can draw
- ; from Rexx, spawn macros from Rexx, etc. But go to the next TALKTOREXX for
- ; more information. To run a rexx macro on startup, simply give that rexx macro
- ; as part of the command line, as in "freedraw sample" or "freedraw bspline 20
- ; 100 20 20 280 20 280 100". All modifications are placed in the public domain.
- ;
- ; Note that I did not do much more than just run the original C through a
- ; compiler to produce this assembly module. I did not think it worthwhile to
- ; optimize the example, although the rexxapp.library is a very tight Rexx
- ; interface.
-
- TALKTOREXX equ 1
-
- ;**********************************************************************
- ; FreeDraw - PD graphics for Amiga
- ;
- ; This is an extremely simple graphics editor which works in the windowing
- ; environment of the Amiga. It is very limited in features. The basic idea of
- ; this program is to provide some minimal image editing functions which can be
- ; used to develop images for other programs. I know there will be a lot of
- ; Paint There are only two menu topics in this version, so using it is really
- ; quite easy. Boxes are not allowed to be drawn in areas outside of the window
- ; where border gadgets are located, and the pen-draw mode also clips to these
- ; same boundaries. If you have begun to draw a box by clicking the left button
- ; while the cursor is located in the FreeDraw window, then you can cancel that
- ; box by clicking the right button. In the pen mode pressing and holding the
- ; left button will draw. Colors are selected by simply releasing the menu
- ; button over the desired color in the Color menu. The erase feature always
- ; clears the window to the currently selected color. This is no gem of
- ; programming style, but you're getting it for the right price so be patient
- ; with its design flaws. New versions will appear here on BIX as soon as I can
- ; get them in shape for release. I apologize to anyone who objects to my lack
- ; of coding grace, but I just want to get the project off the ground, and
- ; improvements will be forthcoming. There are a lot of comments, but I didn't
- ; know what needed to be made clear so I just commented everything.
- ;
- ;Rick Ross 11/14/85
-
- OBJFILE "rad:freedraw.o"
- ADDSYM
- SMALLOBJ
-
- ;from small.lib or amiga.lib
- XREF _LVOWindowToBack,_LVOWindowToFront,_LVOCloseWindow,_LVOOpenWindow
- XREF _LVOSetMenuStrip,_LVOClearMenuStrip,_LVOSetWindowTitles
- XREF _LVOGetMsg,_LVOReplyMsg,_LVOWait
- XREF _LVOOpenLibrary,_LVOOldOpenLibrary,_LVOCloseLibrary
- XREF _LVODraw,_LVOMove,_LVOSetAPen,_LVORectFill,_LVOSetDrMd
-
- ;from StartUp.o
- XREF _exit,_SysBase,_DOSBase
-
- ;from Rexx App lib
- _LVOSetRexxPort equ -30
- _LVOReceiveRexx equ -36
- _LVOFreeRexxPort equ -42
- _LVOSendRexxCmd equ -48
- _LVOASyncRexxCmd equ -54
- _LVOSyncRexxCmd equ -60
- _LVOSetupResults equ -66
-
- ;**************************************************************
- ;DrawBox - Simple routine to draw an unfilled rectangle
- ;
- ;It accepts the coordinates of the top-left and lower-right points of the
- ;rectangle, a pointer to the Window structure, and the color in which to render
- ;the rectangle. The current FgPen color of the window is preserved thru the
- ;call. No clipping is done.
- ;
- ;DrawBox(topleftx, toplefty, lowrightx, lowrighty, window, color )
-
- XDEF DrawBox
- DrawBox:
- link a5,#0
- movea.l _GfxBase,a6
- movem.l d2/a2,-(sp)
- ;---save window's FgPen
- movea.l 24(a5),a0
- movea.l 50(a0),a2 ;RastPort
- move.b 25(a2),d2
- ;---set draw color for box
- move.l 28(a5),d0
- movea.l a2,a1
- jsr _LVOSetAPen(a6)
- ;---move to top-left point
- move.l 12(a5),d1
- move.l 8(a5),d0
- movea.l a2,a1
- jsr _LVOMove(a6)
- ;---Draw to each of the four corners of the box
- move.l 12(a5),d1
- move.l 16(a5),d0
- movea.l a2,a1
- jsr _LVODraw(a6)
- move.l 20(a5),d1
- move.l 16(a5),d0
- movea.l a2,a1
- jsr _LVODraw(a6)
- move.l 20(a5),d1
- move.l 8(a5),d0
- movea.l a2,a1
- jsr _LVODraw(a6)
- move.l 12(a5),d1
- move.l 8(a5),d0
- movea.l a2,a1
- jsr _LVODraw(a6)
- ;---restore old FgPen
- moveq #0,d0
- move.b d2,d0
- movea.l a2,a1
- jsr _LVOSetAPen(a6)
- movem.l (sp)+,d2/a2
- unlk a5
- rts
-
- ;**************************************************************
- ;The following function initializes the structure arrays
- ;needed to provide the Color menu topic.
- ;
- ;InitColorItems(depth)
- ; d0
- ;
- ;depth is the number of bit-planes in window
-
- XDEF InitColorItems
- InitColorItems:
- movem.l d2/d3/d4/d5,-(sp)
- ;---get # of colors allowed for this depth
- move.w d0,d4
- lea _palette,a0
- adda.w d0,a0
- moveq #0,d2
- move.b (a0),d2
- lea _coloritem,a0
- lea _colorimage,a1
- moveq #0,d3
- bra 2$
- ;=============== Init Next Item ===============
- ;coloritem[n].NextItem = &coloritem[n+1]
- 1$ lea 34(a0),a6
- move.l a6,(a0)+
- ;the next two items might be changed for when bit-planes is greater than 2
- ;coloritem[n].LeftEdge = 2 + CW * (n % 4)
- move.l d3,d0
- moveq #4,d1
- divu.w d1,d0
- move.w d0,d5
- swap d0
- moveq #40,d1
- mulu.w d1,d0
- addq.w #2,d0
- move.w d0,(a0)+
- ;coloritem[n].TopEdge = CH * (n / 4)
- moveq #25,d1
- mulu.w d1,d5
- move.w d5,(a0)+
- ;coloritem[n].Width = CW
- move.w #40,(a0)+
- ;coloritem[n].Height = CH
- move.w #25,(a0)+
- ;coloritem[n].Flags = ITEMSTUFF
- move.w #144,(a0)+
- ;coloritem[n].MutualExclude = 0
- clr.l (a0)+
- ;coloritem[n].ItemFill = (APTR)&colorimage[n]
- move.l a1,(a0)+
- ;coloritem[n].SelectFill = NULL
- clr.l (a0)+
- ;coloritem[n].Command = 0
- clr.w (a0)+
- ;coloritem[n].SubItem = NULL
- clr.l (a0)+
- ;coloritem[n].NextSelect = 0
- clr.w (a0)+
- ;=============== Init next Image ===============
- ;colorimage[n].LeftEdge = 1
- move.w #1,(a1)+
- ;colorimage[n].TopEdge = 1
- move.w #1,(a1)+
- ;colorimage[n].Width = CW-2
- move.w #38,(a1)+
- ;colorimage[n].Height = CH-2
- move.w #23,(a1)+
- ;colorimage[n].Depth = depth
- move.w d4,(a1)+
- ;colorimage[n].ImageData = NULL
- clr.l (a1)+
- ;colorimage[n].PlanePick = 0
- clr.b (a1)+
- ;colorimage[n].PlaneOnOff = n
- move.b d3,(a1)+
- ;colorimage[n].NextImage = 0
- clr.l (a1)+
- addq.w #1,d3
- 2$ Dbra d2,1$(pc)
- ;coloritem[colors-1].NextItem = NULL (needed for last item in list)
- clr.l -34(a0)
- movem.l (sp)+,d2/d3/d4/d5
- rts
-
- ;******************************************************
- ;* Main Program *
- ;* *
- ;* This is the main body of the program. *
- ;******************************************************
-
- XDEF _main
- _main:
- link a5,#-310
- ;---DrawColor = 1 (initial drawing color)
- move.b #1,-5(a5)
- ;---OldBRX = 30, OldBRY = 30 (point coords used for boxes)
- move.w #30,-8(a5)
- move.w #30,-10(a5)
- ;---TLX = 20, TLY = 20 (initial top-left point coords)
- move.w #20,-12(a5)
- move.w #20,-14(a5)
- ;---MouseMoved = FALSE (indicates new mouse position ready)
- clr.w -38(a5)
- ;---ClipIt = FALSE (are new point coords out of bounds?)
- clr.w -40(a5)
- ;---ClippedLast = FALSE (was last PenDraw operation clipped?)
- clr.w -42(a5)
- ;---PenMode = FALSE (indicates PenDraw mode is set)
- clr.w -44(a5)
- ;---PenDown = FALSE (if mouse moved, then should it draw?)
- clr.w -46(a5)
- ;---RubberBox = FALSE (are we currently rubberbanding a box?)
- clr.w -48(a5)
- ;---FilledBox = FALSE (should boxes be filled when drawn?)
- clr.w -50(a5)
- ;---Open Graphics
- movea.l _SysBase,a6
- lea GfxName,a1
- jsr _LVOOldOpenLibrary(a6)
- move.l d0,_GfxBase
- ;---Open Intuition
- lea IntuiName,a1
- jsr _LVOOldOpenLibrary(a6)
- move.l d0,_IntuitionBase
-
- IFNE TALKTOREXX
- ;---Open RexxApp lib
- lea RexxName,a1
- moveq #0,d0
- jsr _LVOOpenLibrary(a6)
- move.l d0,_rexxBase
- beq CLSE2
- ENDIF
-
- ;---Try to open new window for application
- lea _NewWindow,a0
- movea.l _IntuitionBase,a6
- jsr _LVOOpenWindow(a6)
- move.l d0,_Window
- beq CLSE
- ;set initial clipping boundaries from the values found in the window
- ;structure for border dimensions
- bsr SetBounds
- ;initialize Color menu arrays
- moveq #2,d0
- bsr InitColorItems
- ;SetMenuStrip( Window, &menu[0] )
- lea _menu1,a1
- move.l _Window,a0
- movea.l _IntuitionBase,a6
- jsr _LVOSetMenuStrip(a6)
- ;set initial draw mode JAM1 and color
- moveq #0,d0
- movea.l _Window,a0
- movea.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVOSetDrMd(a6)
- ;SetAPen( Window->RPort, DrawColor )
- moveq #0,d0
- move.b -5(a5),d0
- movea.l _Window,a0
- movea.l 50(a0),a1
- jsr _LVOSetAPen(a6)
-
- ;==================================================================
- IFNE TALKTOREXX
- ;For rexx, we open up a Rexx port, and send out the first command, if there
- ;was one, that the user typed on the CLI line. We send it out asynchronously
- ;(ie as a macro for the ARexx server to execute). Arexx will load the script
- ;(ie our command string will be the name of the script) and execute it (ie
- ;send ARexx msgs to the target task). It just so happens that all the demo
- ;ARexx scripts that we wrote use Freedraw itself as the target task. In
- ;other words, we are sending out a Rexxmsg which will cause the ARexx server
- ;to execute a script which sends ARexx msgs to Freedraw. This is how a self-
- ;running demo of a program might be implemented. We could have written some
- ;scripts to control other products, which Freedraw could start up as so:
- move.l 8(a5),d2
- movea.l 12(a5),a2
- addq.l #4,a2
- ;---Save a5, and set it up as the base of our RexxData
- move.l a5,-(sp)
- lea _rexxPort,a5
- ;---rexxMask = SetRexxPort()
- movea.l _rexxBase,a6
- lea RXname,a1
- jsr _LVOSetRexxPort(a6)
- beq.s 4$ ;an error in setting up the port
- ;---append all the args from the CLI into 1 string with spaces between each arg
- subq.l #2,d2 ;don't count the name of the program
- bcs.s 5$
- lea ArexxCmdStr,a1 ;here's where we'll make our Arexx scriptname
- 1$ movea.l (a2)+,a0
- 2$ move.b (a0)+,(a1)+
- bne.s 2$
- move.b #' ',-1(a1)
- clr.b (a1)
- dbra d2,1$
- ;---Send this command string out as a macro (ie asyncRexxCmd)
- lea ArexxCmdStr,a0
- jsr _LVOASyncRexxCmd(a6)
- ;---If an error in sending out Rexxmsg, print the returned err msg to window
- bne.s 5$
- 4$ ;---null-term error string in a0
- bsr printRexxErr
- ;---Restore a5
- 5$ movea.l (sp)+,a5
- ENDIF
-
- ;Everything the program needs is now initialized and put in place. The
- ;program enters the following loop and processes message continuously as they
- ;are received from Intuition. I guess this loop is the real workhorse of the
- ;program. By the way, the loop control variable KeepGoing remains TRUE until a
- ;CLOSEWINDOW message is received. At that point it goes FALSE, and the program
- ;cleans up and exits.
- ; while( KeepGoing )
- .37 tst.w _KeepGoing
- beq .38
- ;stay here until a message is received from Intuition or REXX port
- movea.l _Window,a0
- movea.l 86(a0),a1
-
- IFNE TALKTOREXX
- move.l RexxMask,d0 ;If ARexx, use the mask that the lib setup
- ENDIF
- IFEQ TALKTOREXX
- moveq #0,d0
- ENDIF
-
- move.b 15(a1),d1
- bset.l d1,d0
- movea.l _SysBase,a6
- jsr _LVOWait(a6)
-
- IFNE TALKTOREXX
- ;---see if any REXX msgs to handle (safe to call even if Rexx port not setup)
- ; If there are any ARexx msgs, receiveRexx will handle them by calling our
- ; ErrorVector for msgs that WE sent out (ie the msg that started up the
- ; whole, initial script process), or by calling myDispatch() for msgs that
- ; some other task sends us (ie the ARexx server will be sending us msgs when
- ; it executes that script file, or another program could be sending msgs to
- ; our FreeDraw _rexxPort).
- move.l a5,-(sp)
- lea _rexxPort,a5 ;setup a5 as base of Rexx data section
- movea.l _rexxBase,a6
- jsr _LVOReceiveRexx(a6)
- movea.l (sp)+,a5
- ENDIF
-
- ;---MouseMoved = FALSE (clear this flag each time thru loop)
- clr.w -38(a5)
- ;---get next IntuiMsg at window
- .39 movea.l _Window,a0
- movea.l 86(a0),a0
- movea.l _SysBase,a6
- jsr _LVOGetMsg(a6)
- move.l d0,-4(a5)
- beq .40
- movea.l d0,a1
- move.l 20(a1),-18(a5)
- ;code = NewMessage->Code
- move.w 24(a1),-20(a5)
- ;x = Window->MouseX
- move.l _Window,a0
- move.w 14(a0),-22(a5)
- ;y = Window->MouseY
- move.w 12(a0),-24(a5)
- ;Reply the IntuiMessage
- jsr _LVOReplyMsg(a6)
- ;Examine point coords from message received and set the clipping flag if out
- ;of bounds. If user was drawing in PenMode when message was received, then the
- ;ClippedLast flag should also be set to indicate this to the next draw oper-
- ;ation.
- ;if(ClipIt = ( x < MinX || x > MaxX || y < MinY || y > MaxY )) if( PenDown )
- move.w -22(a5),d0
- cmp.w _MinX,d0
- blt.s .43
- move.w -22(a5),d0
- cmp.w _MaxX,d0
- bgt.s .43
- move.w -24(a5),d0
- cmp.w _MinY,d0
- blt.s .43
- move.w -24(a5),d0
- cmp.w _MaxY,d0
- ble.s .42
- .43 moveq #1,d0
- bra.s .44
- .42 moveq #0,d0
- .44 move.w d0,-40(a5)
- beq .41
- ;ClippedLast = TRUE
- tst.w -46(a5)
- beq.s .41
- move.w #1,-42(a5)
- ;enter switch on type of message received
- .41 move.l -18(a5),d0
- subq.l #2,d0
- beq.s .49
- subq.l #6,d0
- beq.s .51
- subq.l #8,d0
- beq.s .48
- sub.l #240,d0
- beq .66
- sub.l #256,d0
- beq.s .50
- sub.l #523776,d0
- beq .82
- bra .39
- ;========================case MOUSEMOVE:
- ;Don't really do anything with this one
- ;until any other, more important, messages
- ;are received and processed.
- ;MouseMoved = TRUE
- .48 move.w #1,-38(a5)
- bra .39
- ;========================case NEWSIZE:
- .49 bsr SetBounds
- bra .39
- ;========================case CLOSEWINDOW:
- ;User is ready to quit, so indicate that execution should terminate
- ;with next iteration of the IDCMP loop.
- .50 clr.w _KeepGoing
- bra .39
- ;=======================case MOUSEBUTTONS:
- ;A number of things could have happened here, and further examination of data
- ;received from message is needed to determine what action should be taken.
- ;The code variable holds important info about what actually caused the message
- ;to be sent in the first place.
- .51 move.w -20(a5),d0
- subi.w #104,d0
- beq.s .55
- subq.w #1,d0
- beq .64
- subi.w #127,d0
- bne .39
- ;case SELECTUP:
- ;User was holding down the left button and just released it. The PenMode
- ;flag variables are set accordingly. The pen can no longer be down, and
- ;ClippedLast is reset for next time.
- ;PenDown = ClippedLast = FALSE
- .54 clr.w -42(a5)
- clr.w -46(a5)
- bra .39
- ;case SELECTDOWN:
- ;User has pressed the left button, and
- ;several differnt actions may need to
- ;be taken. If the ClipIt value is TRUE,
- ;then no action should be taken at all.
- ;
- ;if( ClipIt ) break;
- .55 tst.w -40(a5)
- bne .39
- ;If user is currently in PenMode, then set up to draw when MOUSEMOVED messages
- ;are received until a subsequent SELECTUP message comes in.
- ;if( PenMode )
- tst.w -44(a5)
- beq .56
- ;PenDown = TRUE
- move.w #1,-46(a5)
- ;ClippedLast = FALSE
- clr.w -42(a5)
- ;make sure to set appropriate mode, JAM1
- moveq #0,d0
- movea.l _Window,a0
- movea.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVOSetDrMd(a6)
- ;and establish initial position to draw
- moveq #0,d1
- move.w -24(a5),d1
- moveq #0,d0
- move.w -22(a5),d0
- move.l _Window,a0
- move.l 50(a0),a1
- jsr _LVOMove(a6)
- bra .39
- ;If user is currently rubberbanding a box, then a SELECTDOWN message means it
- ;is time to stop rubberbanding and actually draw it. The following code will
- ;be executed if this is the case, and it will determine if a filled box is
- ;needed before rendering.
- ;if( RubberBox )
- .56 tst.w -48(a5)
- beq .57
- ;set draw mode back to JAM1 since it is now currently set to COMPLEMENT
- moveq #0,d0
- movea.l _Window,a0
- movea.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVOSetDrMd(a6)
- ;RubberBox = FALSE (turn off rubberbanding)
- clr.w -48(a5)
- ;Restore the condition of the RMBTRAP bit in the Window structure's Flags
- ;member. Menubutton events will not be received by this loop.
- movea.l _Window,a0
- bclr.b #0,25(a0)
- ;RectFill is not condusive to the smooth execution of programs if arguments are
- ;out of order, so this code sorts them in preparation for the call.
- ;if( FilledBox )
- tst.w -50(a5)
- beq .58
- ;first sort the x-coords
- ;if TLX < OldBRX
- move.w -12(a5),d0
- cmp.w -8(a5),d0
- bge.s .59
- ;x1 = TLX, x2 = OldBRX
- move.w -12(a5),-26(a5)
- move.w -8(a5),-30(a5)
- bra.s .60
- ;x1 = OldBRX, x2 = TLX
- .59 move.w -8(a5),-26(a5)
- move.w -12(a5),-30(a5)
- ;then sort the y-coords
- ;if TLY < OldBRY
- .60 move.w -14(a5),d0
- cmp.w -10(a5),d0
- bge.s .61
- ;y1 = TLY; y2 = OldBRY
- move.w -14(a5),-28(a5)
- move.w -10(a5),-32(a5)
- bra.s .62
- ;y1 = OldBRY; y2 = TLY
- .61 move.w -10(a5),-28(a5)
- move.w -14(a5),-32(a5)
- ; now generate the filled rectangle
- ;RectFill( Window->RPort, (long)x1, (long)y1,(long)x2, (long)y2 )
- .62 moveq #0,d3
- move.w -32(a5),d3
- moveq #0,d2
- move.w -30(a5),d2
- moveq #0,d1
- move.w -28(a5),d1
- moveq #0,d0
- move.w -26(a5),d0
- move.l _Window,a0
- move.l 50(a0),a1
- jsr _LVORectFill(a6)
- bra .39
- ;FilledBox not set, so draw hollow box
- ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor )
- .58 moveq #0,d0
- move.b -5(a5),d0
- move.l d0,-(sp)
- move.l _Window,-(sp)
- moveq #0,d0
- move.w -10(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -8(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -14(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -12(a5),d0
- move.l d0,-(sp)
- bsr DrawBox
- lea 24(sp),sp
- bra .39
- ;If execution comes here, then PenMode was
- ;not set and user was not rubberbanding.
- ;SELECTDOWN therefore indicates to start the
- ;rubberbanding process at this point. The
- ;initial coords are set to the values we
- ;received when the GetMsg() was executed.
- ;TLX = OldBRX = x, TLY = OldBRY = y
- .57 move.w -22(a5),-8(a5)
- move.w -22(a5),-12(a5)
- move.w -24(a5),-10(a5)
- move.w -24(a5),-14(a5)
- ;set to render in COMPLEMENT mode
- moveq #2,d0
- movea.l _Window,a0
- movea.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVOSetDrMd(a6)
- ;/* set flag to indicate we are now rubberbanding */
- ;RubberBox = TRUE
- move.w #1,-48(a5)
- ;This instruction indicates to Intuition that we now wish to receive a message
- ;each time the Menubutton is pressed. This is how we hijack the right button
- ;for temporary use as a Cancel button instead of a Menubutton.
- ;Window->Flags |= RMBTRAP
- move.l _Window,a0
- bset.b #0,25(a0)
- ;render the initial rubberbox and exit
- ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor )
- moveq #0,d0
- move.b -5(a5),d0
- move.l d0,-(sp)
- move.l _Window,-(sp)
- moveq #0,d0
- move.w -10(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -8(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -14(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -12(a5),d0
- move.l d0,-(sp)
- bsr DrawBox
- lea 24(sp),sp
- bra .39
- ;=======================case MENUDOWN:
- ;WE only receive this message class if
- ;the RMBTRAP flag bit has been set, so
- ;it always means that we should cancel
- ;the box which is currently rubberbanding.
- ;turn the flag off */
- ;RubberBox = FALSE
- .64 clr.w -48(a5)
- ;restore control of menubutton to Intuition */
- ;Window->Flags &= ( 0xFFFFFFFF ^ RMBTRAP );
- move.l _Window,a0
- bclr.b #0,25(a0)
- ;erase (by double XOR'ing) the current
- ;rubberbox and exit switch.
- ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
- moveq #0,d0
- move.b -5(a5),d0
- move.l d0,-(sp)
- move.l _Window,-(sp)
- moveq #0,d0
- move.w -10(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -8(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -14(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -12(a5),d0
- move.l d0,-(sp)
- bsr DrawBox
- lea 24(sp),sp
- bra .39
- ;=======================case MENUPICK:
- ;A menu event has taken place and is ready to be processed. Examine the code
- ;variable received from the message to determine what action should be taken.
- ;The first check is for code=MENUNULL, which means that nothing should be done.
- .66 cmp.w #-1,-20(a5)
- beq .39
- ;get menu and item numbers from code
- ;MenuNum = MENUNUM( code )
- moveq #31,d0
- and.w -20(a5),d0
- move.w d0,-34(a5)
- ;ItemNum = ITEMNUM( code )
- move.w -20(a5),d1
- lsr.w #5,d1
- and.w #63,d1
- move.w d1,-36(a5)
- ;determine appropriate action by menu number
- ;switch ( MenuNum )
- tst.w d0
- beq.s .70
- subq.w #1,d0
- beq.s .71
- bra .39
- ;case 0:
- ;Menu 0 is the Color menu. The item number indicates which new color to set.
- ;DrawColor = ItemNum
- .70 moveq #0,d0
- move.b d1,d0
- move.b d0,-5(a5)
- movea.l _Window,a0
- movea.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVOSetAPen(a6)
- bra .39
- ;case 1:
- ;Menu 1 is the DrawMode menu. The item number indicates what to do.
- ;NOTE: Since we cannot have received this message if we were rubberbanding,
- ;then there is no need to clean up before changing drawing modes.
- .71 move.w d1,d0
- beq.s .74
- subq.w #1,d1
- beq.s .75
- subq.w #1,d1
- beq.s .76
- subq.w #1,d1
- bne .39
- ;case 3:
- ;set flag variables for PenMode
- ;PenMode = TRUE;
- .77 move.w #1,-44(a5)
- bra .39
- ;case 1: set flag variables for hollow box */
- ;PenMode = FALSE;
- .75 clr.w -44(a5)
- ;FilledBox = FALSE;
- clr.w -50(a5)
- bra .39
- ;case 2: set flag variables for filled box
- ;PenMode = FALSE
- .76 clr.w -44(a5)
- ;FilledBox = TRUE
- move.w #1,-50(a5)
- bra .39
- ;case 0: Erase window to current color
- ;---set JAM1
- .74 moveq #0,d0
- movea.l _Window,a0
- movea.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVOSetDrMd(a6)
- ;RectFill( Window->RPort, (long)MinX, (long)MinY,(long)MaxX, (long)MaxY);
- moveq #0,d3
- move.w _MaxY,d3
- moveq #0,d2
- move.w _MaxX,d2
- moveq #0,d1
- move.w _MinY,d1
- moveq #0,d0
- move.w _MinX,d0
- move.l _Window,a0
- move.l 50(a0),a1
- jsr _LVORectFill(a6)
- bra .39
- ;============case INACTIVEWINDOW:
- .82
- ;User has de-selected our window, so a
- ;little bit of cleaning up may be needed
- ;to prevent untoward events when he comes
- ;back to it.
- ;erase any outstanding rubberbox */
- ;if( RubberBox )
- ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor)
- tst.w -48(a5)
- beq .83
- moveq #0,d0
- move.b -5(a5),d0
- move.l d0,-(sp)
- move.l _Window,-(sp)
- moveq #0,d0
- move.w -10(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -8(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -14(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -12(a5),d0
- move.l d0,-(sp)
- bsr DrawBox
- lea 24(sp),sp
- ;reset all the flafg variables */
- ;PenDown = ClippedLast = RubberBox = FALSE;
- .83
- clr.w -48(a5)
- clr.w -42(a5)
- clr.w -46(a5)
- ;return possibly diverted menubutton events to Big I
- ;Window->Flags &= ( 0xFFFFFFFF ^ RMBTRAP );
- move.l _Window,a0
- bclr.b #0,25(a0)
- bra .39
- ;============================================================
- ;There are no more messages waiting at the IDCMP port, so we can now proceed
- ;to process any MOUSEMOVED message we may have received.
- ;if( MouseMoved && !ClipIt)
- .40 tst.w -38(a5)
- beq .37
- tst.w -40(a5)
- bne .37
- ;the mouse did move, and we don't need to clip
- ;check first if we are drawing in PenMode
- ;if( PenDown )
- tst.w -46(a5)
- beq .88
- ;We have to examine if we clipped the
- ;last PenMode draw operation. If we did,
- ;then this is the first move back into
- ;window boundaries, so we mov instead of
- ;drawing.
- ;if( ClippedLast )
- tst.w -42(a5)
- beq .89
- ;ClippedLast = FALSE; /* reset this flag
- clr.w -42(a5)
- moveq #0,d1
- move.w -24(a5),d1
- moveq #0,d0
- move.w -22(a5),d0
- move.l _Window,a0
- move.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVOMove(a6)
- bra .37
- ;Draw( Window->RPort, (long)x, (long)y ); /* draw to x,y coords
- .89 moveq #0,d1
- move.w -24(a5),d1
- moveq #0,d0
- move.w -22(a5),d0
- move.l _Window,a0
- move.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVODraw(a6)
- bra .37
- ;We weren't in PenMode, but we still might
- ;be rubberbanding a box. If so, then we
- ;should erase the current rubberbox and
- ;draw a new one with the new mouse coords.
- ;
- ;if( RubberBox )
- .88 tst.w -48(a5)
- beq .37
- ;erase the old rubberbox - draw mode is COMPLEMENT
- ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
- moveq #0,d0
- move.b -5(a5),d0
- move.l d0,-(sp)
- move.l _Window,-(sp)
- moveq #0,d0
- move.w -10(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -8(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -14(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -12(a5),d0
- move.l d0,-(sp)
- bsr DrawBox
- lea 24(sp),sp
- ;assign new values to box coords */
- ;OldBRX = x; OldBRY = y;
- move.w -22(a5),-8(a5)
- move.w -24(a5),-10(a5)
- ;and draw the new rubberbox */
- ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
- moveq #0,d0
- move.b -5(a5),d0
- move.l d0,-(sp)
- move.l _Window,-(sp)
- moveq #0,d0
- move.w -10(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -8(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -14(a5),d0
- move.l d0,-(sp)
- moveq #0,d0
- move.w -12(a5),d0
- move.l d0,-(sp)
- bsr DrawBox
- lea 24(sp),sp
- bra .37
- ;====================== PROGRAM CLEANUP AND EXIT ========================
- .38
- ;It must be time to quit, so we have to clean up and exit.
-
- IFNE TALKTOREXX
- ;With Rexx, we need to bring the port down. You must call freeRexxPort before
- ;doing any exit() for programs that have multiple paths to exit.
- move.l a5,-(sp)
- lea _rexxPort,a5
- movea.l _rexxBase,a6
- jsr _LVOFreeRexxPort(a6)
- movea.l (sp)+,a5
- ENDIF
-
- ;---Clear our MenuStrip
- movea.l _Window,a0
- movea.l _IntuitionBase,a6
- jsr _LVOClearMenuStrip(a6)
- ;---Close our Window
- move.l _Window,a0
- jsr _LVOCloseWindow(a6)
- ;---Close the RexxApp lib
- CLSE movea.l _SysBase,a6
-
- IFNE TALKTOREXX
- movea.l _rexxBase,a1
- jsr _LVOCloseLibrary(a6)
- ENDIF
-
- ;---Close Graphics and Intuition
- CLSE2 movea.l _IntuitionBase,a1
- jsr _LVOCloseLibrary(a6)
- movea.l _GfxBase,a1
- jsr _LVOCloseLibrary(a6)
- ;---exit the program
- pea 1
- jsr _exit
- add.w #4,sp
- unlk a5
- rts
-
- SetBounds:
- ;---MinX = Window->BorderLeft
- move.l _Window,a0
- move.b 54(a0),d0
- ext.w d0
- move.w d0,_MinX
- ;---MinY = Window->BorderTop
- move.b 55(a0),d0
- ext.w d0
- move.w d0,_MinY
- ;---MaxX = Window->Width - Window->BorderRight - 1
- move.w 8(a0),d0
- move.b 56(a0),d1
- ext.w d1
- sub.w d1,d0
- subq.w #1,d0
- move.w d0,_MaxX
- ;---MaxY = Window->Height - Window->BorderBottom - 1
- move.w 10(a0),d0
- move.b 57(a0),d1
- ext.w d1
- sub.w d1,d0
- subq.w #1,d0
- move.w d0,_MaxY
- rts
-
- IFNE TALKTOREXX
-
- ;Now we get into the actual code necessary for our REXX port; functions
- ;that do the real work. Note that this program was not structured
- ;particularly nicely for Rexx. I had to write each of these functions.
- ;Many programs have these subroutines already in place. They are called
- ;as part of the event loop. This program, however, just has one big
- ;IDCMP loop in main with different actions . . .
-
- ;********************************************************************
- ;This is our REXX dispatch function. This is called whenever some other appli-
- ;cation has sent us an Arexx msg with a command that our program understands.
- ;The ARexx app lib has already determined which command, and set up a3 as
- ;the address of the appropriate handler. We now check to make sure a Window
- ;currently exists. Then, we store away the `current color' and change it to
- ;Rexx's current color, call our handler function, and then restore the color.
- ;If our handler replies, it sets userreplied to indicate that. If the parse and
- ;everything else was successful, we send an rm_Result of 0 (via setupResults).
- ;Otherwise, we send a failure of 20 to ARexx server to indicate that the args
- ;were messed up. We always return TRUE, because we don't have an instance of
- ;needing to hold onto a Rexxmsg after we use it here. Note that we must not
- ;alter register a5, but a2, a3, and a4 are OK to scratch.
- ;
- ;myDispatch(Rexxmsg, asscListVector, string, RexxDataBase)
- ; a2 a3 a4 a5
-
- XDEF myDispatch
- myDispatch:
- ;---Make sure that our window is open
- move.l _Window,d0
- beq.s 1$
- ;---Initially, error = 0 (indicate no error with getting args from Argstring)
- clr.l error
- ;---Initially, no returned Result string
- clr.l ResultStr
- ;---Save window's current PenA
- move.l d4,-(sp)
- movea.l d0,a0
- movea.l 50(a0),a1
- moveq #0,d4
- move.b 25(a1),d4
- ;---Set PenA to currrexxcolor
- move.l _currrexxcolor,d0
- movea.l _GfxBase,a6
- jsr _LVOSetAPen(a6)
- ;---Call our vector for this rexx command
- movea.l a4,a0 ;put Argstring in a0 too
- jsr (a3)
- ;---Restore PenA
- move.l d4,d0
- movea.l _Window,a0
- movea.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVOSetAPen(a6)
- move.l (sp)+,d4
- ;---if error = 0 (success), SetupResults(Rexxmsg, 0, 0, ResultStr)
- movea.l ResultStr,a0
- move.l error,d0 ;primary return
- bne.s 1$
- moveq #0,d1
- 3$ movea.l a2,a1
- movea.l _rexxBase,a6
- jsr _LVOSetupResults(a6)
- ;---Tell the lib to reply it now
- moveq #1,d0
- rts
- ;---ERROR: SetupResults(Rexxmsg, error, 10, NULL)
- 1$ moveq #10,d1
- suba.l a0,a0 ;no return Argstring
- bra.s 3$
-
- ;*******************************************************
- ;This handler sets the current rexx color.
- ;
- ;rexxcolor(Rexxmsg, string)
- ; a2 a0,a4
-
- XDEF rexxcolor
- rexxcolor:
- ;---Get 1 number from the ascii string
- bsr.s getnm
- move.l d0,_currrexxcolor
- rxout rts
-
- ;***********************************************************************
- ;This function takes an address of a string (in a0), parses the next number
- ;(ie converts the next ascii digits into a numeric value), returns it in d0,
- ;and advances a0 to point to the next char after the last ascii digit. If
- ;there are no ascii digits in the string at all (if we called this function
- ;then we must have expected some), then set error to indicate an error in
- ;this ARexx supplied string (ie there's an arg missing from this ARexx line).
- ;
- ;number,string = getnm(string)
- ; d0 a0 a0
-
- XDEF getnm
- getnm:
- ;---value = 0
- moveq #0,d0
- moveq #0,d1
- ;---If between '0' to '9'
- 2$ move.b (a0)+,d1
- beq.s 3$
- subi.b #'0',d1
- bcs.s 2$
- cmp.b #9,d1
- bhi.s 2$
- 5$ mulu.w #10,d0
- add.l d1,d0
- move.b (a0)+,d1
- beq.s 6$
- subi.b #'0',d1
- bcs.s 6$
- cmp.b #9,d1
- bls.s 5$
- subq.l #1,a0
- 4$ rts
- ;---No ascii chars to convert
- 3$ move.b #20,error+3 ;indicate an error upon return to myDispatch of level 20
- 6$ subq.l #1,a0
- rts
-
- ;**********************************************************************
- ;This function trys to find `numArgs' numeric arguments in the command
- ;string, and stuffs them into the args array.
- ;
- ;parseargs(string, numArgs)
- ; a0 d0
-
- XDEF parseargs
- parseargs:
- move.l d4,-(sp)
- move.l d0,d4
- lea Points,a1
- bra.s 2$
- 1$ bsr.s getnm
- move.l d0,(a1)+
- 2$ dbra d4,1$(pc)
- move.l (sp)+,d4
- rts
-
- ;***********************************************************************
- ;This function silently clips the x and y values of the passed Point
- ;structure to the current window bounds. My Point is defined as so:
- ;
- ;X dc.l [x pixel position of the Point]
- ;Y dc.l [y pixel position]
- ;
- ;clipxy(LineStruct)
- ; a0
-
- XDEF clipxy
- clipxy:
- ;---Check that Rectangle[leftX] > MinX
- moveq #0,d1
- move.w _MinX,d1
- move.l (a0),d0
- cmp.l d0,d1
- bls.s 1$
- move.l d1,d0
- ;---Check that Rectangle[leftX] < MaxX
- 1$ move.w _MaxX,d1
- cmp.l d0,d1
- bcc.s 2$
- move.l d1,d0
- 2$ move.l d0,(a0)+
- ;---Check that Rectangle[topY] > MinY
- move.w _MinY,d1
- move.l (a0),d0
- cmp.l d0,d1
- bls.s 3$
- move.l d1,d0
- ;---Check that Rectangle[topY] < MaxY
- 3$ move.w _MaxY,d1
- cmp.l d0,d1
- bcc.s 4$
- move.l d1,d0
- 4$ move.l d0,(a0)+
- rts
-
- ;*************************************************************************
- ; This gets 4 numbers from the passed ascii string and stores them in the
- ; Rectangle array (4 LONGS). It then clips the Rec to the window dimensions.
- ;
- ;leftX dc.l [the left x pixel position of the rectangle]
- ;topY dc.l [the upper y pixel position]
- ;rightX dc.l [the right x]
- ;bottomY dc.l [the bottom y pixel position]
- ;
- ;Note that I treat the Rectangle structure as two adjacent Point structures
- ;
- ;GetBoxCoords(string)
- ; a0
-
- GetBoxCoords:
- ;---Parse 4 numbers from the ARexx string into a Rectangle structure
- moveq #4,d0
- bsr.s parseargs
- ;---Check the leftX and topY coords
- lea Points,a0
- bsr.s clipxy
- ;---Now check the rightX and bottomY coords
- bra.s clipxy
-
- ;***********************************************************
- ;This handler parses 4 numbers into Rectangle struct and draws a wireframe box.
- ;
- ;rexxbox(Rexxmsg, string)
-
- XDEF rexxbox
- rexxbox:
- bsr.s GetBoxCoords
- ;DrawBox(args[0], args[1], args[2], args[3], Window, currrexxcolor)
- move.l _currrexxcolor,-(sp)
- move.l _Window,-(sp)
- move.l Points+12,-(sp)
- move.l Points+8,-(sp)
- move.l Points+4,-(sp)
- move.l Points,-(sp)
- bsr DrawBox
- lea 24(sp),sp
- unlk a5
- rts
-
- ;******************************************************************
- ; This handler parses 4 numbers into Rectangle struct and draws a filled box.
- ;
- ; rexxfbox(Rexxmsg, string)
-
- XDEF rexxfbox
- rexxfbox:
- movem.l d2/d3,-(sp)
- bsr.s GetBoxCoords
- ;---Get 4 corners and error check
- move.l Points+12,d3
- move.l Points+8,d2
- move.l Points+4,d1
- move.l Points,d0
- cmp.l d2,d0
- bls.s 1$
- exg.l d0,d2
- 1$ cmp.l d3,d1
- ble.s 2$
- exg.l d1,d3
- ;---Draw box
- 2$ movea.l _Window,a0
- movea.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVORectFill(a6)
- movem.l (sp)+,d2/d3
- rts
-
- ;*********************************************************************
- ;This handler grabs four numbers from the Rexxstring and draws a line
- ;We interprete the 4 numbers as X and Y pixel start positions, and X and Y end
- ;positions.
- ;
- ;rexxline(Rexxmsg, string)
-
- XDEF rexxline
- rexxline:
- bsr GetBoxCoords
- ;---Move to start position
- move.l Points+4,d1
- move.l Points,d0
- movea.l _Window,a0
- movea.l 50(a0),a1
- movea.l _GfxBase,a6
- jsr _LVOMove(a6)
- ;---Draw to end position
- move.l Points+12,d1
- move.l Points+8,d0
- movea.l _Window,a0
- movea.l 50(a0),a1
- jmp _LVODraw(a6)
-
- ;**********************************************************
- ;This handler pops the window to front.
- ;
- ;rexxtofront(Rexxmsg, string)
-
- XDEF rexxtofront
- rexxtofront:
- movea.l _Window,a0
- movea.l _IntuitionBase,a6
- jmp _LVOWindowToFront(a6)
-
- ;******************************************************************
- ;This handler pops the window to back.
- ;
- ;rexxtoback(Rexxmsg, string)
-
- XDEF rexxtoback
- rexxtoback:
- movea.l _Window,a0
- movea.l _IntuitionBase,a6
- jmp _LVOWindowToBack(a6)
-
- ;***************************************************************
- ;This handler sets the exit flag.
- ;
- ;rexxexit(Rexxmsg, string)
-
- XDEF rexxexit
- rexxexit:
- clr.w _KeepGoing
- suba.l a0,a0 ;no returned Result string
- rts
-
- ;**************************************************************
- ;This handler returns the version of the program.
- ;
- ;rexxversion(Rexxmsg, string)
-
- XDEF rexxversion
- rexxversion:
- ;---Setup the address of VERSION as the returned Argstring
- ; Note that this is our only example of returning a Result string
- lea VERSION,a0
- move.l a0,ResultStr
- rts
-
- ;***********************************************************************
- ;This handler sends the rest of the command asynchronously, allowing us to
- ;run macros in parallel. Note that the App lib strips leading whitespace from
- ;the Argstring, so we don't have to do that here.
- ;
- ;rexxspawn(Rexxmsg, string)
-
- XDEF rexxspawn
- rexxspawn:
- ;string in a0
- movea.l _rexxBase,a6
- jmp _LVOASyncRexxCmd(a6)
-
- ;*************************************************************************
- ; The error routine for Rexxmsgs that we sent out and were returned with an
- ; error. The error message is in a0 and the error code is in d0. Let's just
- ; print out the message in the title bar.
-
- printRexxErr:
- movea.l _IntuitionBase,a6
- movea.l a0,a1
- movea.l _Window,a0
- move.l a2,-(sp)
- suba.l a2,a2
- jsr _LVOSetWindowTitles(a6)
- movea.l (sp)+,a2
- rts
-
- ;*************************************************************************
- ; The Result routine for Rexxmsgs that we sent out and were returned success-
- ; fully. The Result string is in a0 (or NULL if none) and the Result1 code is
- ; in d0. Let's just print out the message in the title bar (if not 0) since
- ; we really don't have any rexx handlers that expect returned strings.
-
- doResult:
- move.l a0,d1
- bne.s printRexxErr
- rts
-
- ENDIF
-
- ; SECTION FDdata,DATA ;some asms may need this uncommented
-
- _Window dc.l 0
- _MinX dc.w 0
- _MinY dc.w 0
- _MaxX dc.w 0
- _MaxY dc.w 0
- _KeepGoing dc.w 1 ;when this is a 0, we exit
-
- XDEF _IntuitionBase,_GfxBase
- _IntuitionBase dc.l 0
- _GfxBase dc.l 0
-
- ; This is the Window structure declaration. Nothing fancy is going on here,
- ;but note the Flags and IDCMPFlags members of the structure define which
- ;messages will be sent by Intuition. I haven't used them all and if you want
- ;to change the settings you should probably do it here instead of using
- ;ModifyIDCMP later.
-
- XDEF _NewWindow
- _NewWindow:
- dc.w 10,10,600,180
- dc.b 0,1
- ;CLOSEWINDOW | MOUSEMOVE | MOUSEBUTTONS | MENUPICK | NEWSIZE | INACTIVEWINDOW
- dc.l $8031a
- ;WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING | REPORTMOUSE
- dc.l $120f
- dc.l 0,0
- dc.l WindowTitle
- dc.l 0,0
- dc.w 100,35,-1,-1
- dc.w 1
-
- ;****************************** MENUS ********************************
-
- _menu1 dc.l _menu2
- dc.w 10,0,50,10,1
- dc.l Color
- dc.l _coloritem
- dc.w 0,0,0,0
- _menu2 dc.l 0
- dc.w 65,0,85,10,1
- dc.l DrawMode
- dc.l EraseItem
- dc.w 0,0,0,0
-
- ;================= Menu Items For DrawMode Menu =================
-
- EraseItem:
- dc.l HollowItem
- dc.w 0,0,112,10
- dc.w 146 ;ITEMTEXT|ITEMENABLED|HIGHBOX
- dc.l 0
- dc.l EraseText
- dc.l 0
- dc.b 0,0
- dc.l 0
- dc.w 0
- HollowItem:
- dc.l FilledItem
- dc.w 0,10,112,10
- dc.w 146
- dc.l 0
- dc.l HollowBoxText
- dc.l 0
- dc.b 0,0
- dc.l 0
- dc.w 0
- FilledItem:
- dc.l PenItem
- dc.w 0,20,112,10
- dc.w 146
- dc.l 0
- dc.l FilledBoxText
- dc.l 0
- dc.b 0,0
- dc.l 0
- dc.w 0
- PenItem:
- dc.l 0
- dc.w 0,30,112,10
- dc.w 146
- dc.l 0
- dc.l PenDrawText
- dc.l 0
- dc.b 0,0
- dc.l 0
- dc.w 0
-
- EraseText:
- dc.b 0,1,1,0
- dc.w 0,1
- dc.l 0,EraseAll,0
- HollowBoxText:
- dc.b 0,1,1,0
- dc.w 0,1
- dc.l 0,HollowBox,0
- FilledBoxText:
- dc.b 0,1,1,0
- dc.w 0,1
- dc.l 0,FilledBox,0
- PenDrawText:
- dc.b 0,1,1,0
- dc.w 0,1
- dc.l 0,PenDraw,0
-
- ;******************************************************
- ; Color Select Menu *
- ; *
- ; This is where the menu for color selection is *
- ; defined. It should be flexible enough to allow for *
- ; increased palette sizes, but this version is only *
- ; for the 4-color mode of the WorkBench screen. *
-
- _coloritem ds.b 136
- _colorimage ds.b 80
- ;array of palette sizes to correspond with depth of window in bit-planes
- _palette dc.b 0,2,4,8,16,32
-
-
- IFNE TALKTOREXX
-
- ;These first 6 variables are only needed by this program and are not required
- ;by the Rexx App lib. (ie they exist merely for the use of FreeDraw's ARexx
- ;handlers)
-
- ;the base of rexxapp.library
- _rexxBase dc.l 0
-
- ;A buffer into which we place the user's command string for ARexx
- ArexxCmdStr ds.b 256
-
- ;The address of the Result string
- ResultStr dc.l 0
-
- ;What color is *rexx* drawing in?
- _currrexxcolor dc.l 1
-
- ;what args did we see to this function? MAX 4 LONGS
- Points ds.l 4
-
- ;was argument parsing successful? A 0 if so, a 1 for error
- error dc.l 0
-
- ;******************************** RexxData *********************************
- ; This part is the mandatory data section needed by the Rexx App lib. Whenever
- ; you call a function in this library, register a5 must be setup with the base
- ; of this data block (ie lea _rexxPort,a5). The data must be in this order
- ; up to the end of the association list! Note that the association list can
- ; be any length as long as it ends with a 0 LONG.
- ;
- ; For another program, you will need to alter the command association list
- ; (and the strings for it). Also, change RexxMacroExt and RXname. If you call
- ; your Dispatch, Error, and Result vector routines the same as I did, then you
- ; won't need to alter the variables dispatchFunc, ErrorVector and ResultVector.
-
- ;These are the offsets from the base of the data (ie from _rexxPort)
- mr_RexxPort equ 0 ;The imbedded RexxPort (to be setup by SetRexxPort)
- mr_RxName equ 10 ;DO NOT ALTER
- mr_RxSig equ 15 ;DO NOT ALTER
- mr_RxTask equ 16 ;DO NOT ALTER
- mr_Flags equ 32 ;DO NOT ALTER the highest 4 bits (4-7)
- mr_MsgsOut equ 33 ;how many RexxMsgs this app created and has not received back (DO NOT ALTER)
- mr_Exten equ 34 ;the extension for invoking Rexx scripts
- mr_Func equ 38 ;a routine to handle received RexxMsg's from some other application
- mr_RxsLib equ 42 ;the lib base of ARexx server library (DO NOT ALTER)
- mr_ErrorV equ 46 ;a routine for error return of a RexxMsg the app created and sent
- mr_Return equ 50 ;a routine for successful return of a RexxMsg the app created and sent
- mr_RexxMask equ 54 ;signal mask of the Rexx port's mp_SigBit
- mr_UserData equ 58 ;for application's use
- mr_AsscList equ 62 ;the imbedded association list
-
- CNOP 0,2
- XDEF _rexxPort
- ;Our Rexx port
- _rexxPort:
- dc.l 0,0
- dc.b 4,0
- dc.l RXname
- dc.b 0
- dc.b -1 ;This is negative (bit 7 set) whenever our port isn't set up
- dc.l 0
- rxmsg dc.l rxmsg+4
- dc.l 0
- dc.l rxmsg
- dc.b 0 ;DO NOT ALTER THESE LAST 2 BYTES OF THE PORT
- dc.b 0
-
- ;extension is the address of a null-term file extension string for ARexx macros
- ;invoked by this program. If not 0, any `primitive' not in the association
- ;list will be sent out to ARexx for interpretation, thus allowing macro
- ;programs to work just like primitives. If you do not want this behavior,
- ;supply a 0 here, and those commands not specified in your association list
- ;will be sent back to ARexx with an error value of RXERRORNOCMD. It should be
- ;noted that extension should point to a nulled string if no particular
- ;extention is desired. Here, I've set it to point to 'fd',0
- extension dc.l RexxMacroExt
-
- ;dispatchFunc is the address of the app's Dispatch function. This function
- ;will *only* be called by the library when the application calls ReceiveRexx().
- ;Anytime a command match is found in the association list, this function will
- ;be called with 3 arguments--- the Rexx message that was received (a2), a
- ;pointer to the association jmp vector in a3 (ie the handler to be executed),
- ;and the Argstring in a4 (ARG0) stripped of the command. This function should
- ;return a 1 if the message is to be replied to by the lib or a 0 if not. If
- ;not, the application itself is responsible for replying the message later via
- ;Exec's ReplyMsg(). Otherwise, the library ALWAYS takes care of properly
- ;replying all messages. (Freedraw lets the lib take care of all replies. Unless
- ;you need to hold onto a Rexxmsg and consequently "put the Rexx script to
- ;sleep" until you reply it later, you'll let the lib take care of replies.
- ;Also, the app should setup the return values with SetupResults().
- dispatchFunc dc.l myDispatch
-
- ;Address of rexxsyslib.library (DO NOT ALTER)
- _RexxSysBase dc.l 0
-
- ;This routine is called when each msg that the application created and sent out
- ;is returned with an error. It is passed an appropriate error message in a0,
- ;and the error code in d0. Typically, this routine needs to do nothing more
- ;than print the message for the user. You must supply at least a dummy routine.
- ErrorVector dc.l printRexxErr
-
- ;This routine is called when each msg that the application created and sent out
- ;is returned successfully. It is passed any returned Result string in a0,
- ;and the Result1 code in d0. This routine may do various things with the
- ;Result1 string or code depending upon which function initially sent the
- ;message out. You must supply at least a dummy routine.
- ResultVector dc.l doResult
-
- ;The mask of our rexxPort's SigBit (used by our app to wait for Arexx msgs)
- RexxMask dc.l 0
-
- ;The application can do anything with this
- dc.l 0
-
- ;Here is our command association list. This is simply a table of LONGS. Each
- ;two LONGS is an entry for a REXX command. For example, the first 2 LONGS in
- ;the table are for the first REXX command. Remember that REXX commands are
- ;null-terminated strings. The first LONG is the address of the command string.
- ;For example, in our command association list for FreeDraw, the first long
- ;points to the string "color". The next LONG is the address of the function
- ;that implements the REXX command. For example, the next LONG points to the
- ;function, rexxcolor. Now whenever we receive a REXX msg with its command
- ;string being "color", we jsr to the function, rexxcolor. This is the way the
- ;Rexx app lib determines whether a received Rexxmsg holds a legitimate command
- ;for our application. For another program, you simply make a new association
- ;list (and write the respective handlers). This list MUST end with a 0 LONG.
- ;Please note that your command strings must also be lower case letters (and
- ;only letters with no imbedded spaces). You will probably also write a new
- ;dispatch function (modeled after myDispatch), since you may need to do other
- ;things besides change window colors, check for an open window, etc like what
- ;FreeDraw needs to do with its ARexx implementation.
-
- XDEF myAsscList
- myAsscList:
- ;"color"
- dc.l color
- dc.l rexxcolor
- ;"box"
- dc.l box
- dc.l rexxbox
- ;"fbox"
- dc.l fbox
- dc.l rexxfbox
- ;"line"
- dc.l line
- dc.l rexxline
- ;"tofront"
- dc.l tofront
- dc.l rexxtofront
- ;"toback"
- dc.l toback
- dc.l rexxtoback
- ;"exit"
- dc.l exit
- dc.l rexxexit
- ;"version"
- dc.l version
- dc.l rexxversion
- ;"spawn"
- dc.l spawn
- dc.l rexxspawn
- ;END OF LIST
- dc.l 0
-
- ;The following data can be placed anywhere, and will change for another application
-
- ;These are the command strings that we will accept ARexx msgs for
- color dc.b 'color',0
- box dc.b 'box',0
- fbox dc.b 'fbox',0
- line dc.b 'line',0
- version dc.b 'version',0
- spawn dc.b 'spawn',0
- exit dc.b 'exit',0
- tofront dc.b 'tofront',0
- toback dc.b 'toback',0
-
- ;This is the name of our Rexx port, and is used with the ADDRESS command
- ;within a Rexx macro to find this app's rexx port. This must be unique for
- ;every Rexx application. Note that if the user runs 2 copies of FreeDraw,
- ;the second port's name will be "freedraw2". Also, note that we have an extra
- ;null byte on the end of our name. THIS EXTRA BYTE IS REQUIRED!
- RXname dc.b 'freedraw',0,0
-
- RexxMacroExt dc.b 'fd',0 ;the macro extention desired for ARexx
-
- RexxName dc.b 'rexxapp.library',0
-
- ENDIF
-
- ;********************** END OF MANDATORY REXX DATA **********************
-
- GfxName dc.b 'graphics.library',0
- IntuiName dc.b 'intuition.library',0
- VERSION dc.b 'Freedraw 0.01 by Richard M. Ross',0
- WindowTitle dc.b 'AMIGA FreeDraw 0.01',0
- Color dc.b 'Color',0
- DrawMode dc.b 'DrawMode',0
- EraseAll dc.b 'Erase All',0
- HollowBox dc.b 'Hollow Box',0
- FilledBox dc.b 'Filled Box',0
- PenDraw dc.b 'Pen Draw',0
-
- END
-