home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 499.lha / RexxLib_rel2 / FreeDraw.asm < prev    next >
Assembly Source File  |  1991-04-08  |  46KB  |  1,640 lines

  1. ;***************************************************************************
  2. ; This program is an example of how to add a Rexx implementation to any
  3. ; program using the rexxapp.library.  The original Freedraw program (without
  4. ; REXX) is from Fred Fish Disk 1. The rexxapp.library is based upon a C module
  5. ; by Radical Eye Software which was modified and down-coded to a 68000 shared
  6. ; library.
  7. ; All the REXX stuff is bracketed by IFNE TALKTOREXX, so you can identify it
  8. ; easily.  If you assemble with TALKTOREXX equ 0, you will get the default
  9. ; program with no REXX port. The REXX port on this program increases the
  10. ; executable slightly, but a lot of functionality comes with that. You can draw
  11. ; from Rexx, spawn macros from Rexx, etc.  But go to the next TALKTOREXX for
  12. ; more information. To run a rexx macro on startup, simply give that rexx macro
  13. ; as part of the command line, as in "freedraw sample" or "freedraw bspline 20
  14. ; 100 20 20 280 20 280 100". All modifications are placed in the public domain.
  15. ;
  16. ; Note that I did not do much more than just run the original C through a
  17. ; compiler to produce this assembly module. I did not think it worthwhile to
  18. ; optimize the example, although the rexxapp.library is a very tight Rexx
  19. ; interface.
  20.  
  21. TALKTOREXX    equ    1
  22.  
  23. ;**********************************************************************
  24. ;               FreeDraw - PD graphics for Amiga           
  25. ;
  26. ; This is an extremely simple graphics editor which works in the windowing
  27. ; environment of the Amiga.  It is very limited in features. The basic idea of
  28. ; this program is to provide some minimal image editing functions which can be
  29. ; used to develop images for other programs.  I know there will be a lot of
  30. ; Paint There are only two menu topics in this version, so using it is really
  31. ; quite easy.  Boxes are not allowed to be drawn in areas outside of the window
  32. ; where border gadgets are located, and the pen-draw mode also clips to these
  33. ; same boundaries. If you have begun to draw a box by clicking the left button
  34. ; while the cursor is located in the FreeDraw window, then you can cancel that
  35. ; box by clicking the right button. In the pen mode pressing and holding the
  36. ; left button will draw.  Colors are selected by simply releasing the menu
  37. ; button over the desired color in the Color menu. The erase feature always
  38. ; clears the window to the currently selected color. This is no gem of
  39. ; programming style, but you're getting it for the right price so be patient
  40. ; with its design flaws. New versions will appear here on BIX as soon as I can
  41. ; get them in shape for release.  I apologize to anyone who objects to my lack
  42. ; of coding grace, but I just want to get the project off the ground, and
  43. ; improvements will be forthcoming.  There are a lot of comments, but I didn't
  44. ; know what needed to be made clear so I just commented everything.             
  45. ;
  46. ;Rick Ross 11/14/85
  47.  
  48.     OBJFILE    "rad:freedraw.o"
  49.     ADDSYM
  50.     SMALLOBJ
  51.  
  52.     ;from small.lib or amiga.lib
  53.     XREF    _LVOWindowToBack,_LVOWindowToFront,_LVOCloseWindow,_LVOOpenWindow
  54.     XREF    _LVOSetMenuStrip,_LVOClearMenuStrip,_LVOSetWindowTitles
  55.     XREF    _LVOGetMsg,_LVOReplyMsg,_LVOWait
  56.     XREF    _LVOOpenLibrary,_LVOOldOpenLibrary,_LVOCloseLibrary
  57.     XREF    _LVODraw,_LVOMove,_LVOSetAPen,_LVORectFill,_LVOSetDrMd
  58.  
  59.     ;from StartUp.o
  60.     XREF    _exit,_SysBase,_DOSBase
  61.  
  62.     ;from Rexx App lib
  63. _LVOSetRexxPort        equ    -30
  64. _LVOReceiveRexx        equ    -36
  65. _LVOFreeRexxPort    equ    -42
  66. _LVOSendRexxCmd        equ    -48
  67. _LVOASyncRexxCmd    equ    -54
  68. _LVOSyncRexxCmd        equ    -60
  69. _LVOSetupResults    equ    -66
  70.  
  71. ;**************************************************************
  72. ;DrawBox - Simple routine to draw an unfilled rectangle 
  73. ;
  74. ;It accepts the  coordinates of the top-left and lower-right points of the
  75. ;rectangle, a pointer to the Window structure, and the color in which to render
  76. ;the rectangle.  The current FgPen color of the window is preserved thru the
  77. ;call. No clipping is done.
  78. ;
  79. ;DrawBox(topleftx, toplefty, lowrightx, lowrighty, window, color )
  80.  
  81.     XDEF    DrawBox
  82. DrawBox:
  83.     link    a5,#0
  84.     movea.l    _GfxBase,a6
  85.     movem.l    d2/a2,-(sp)
  86. ;---save window's FgPen
  87.     movea.l    24(a5),a0
  88.     movea.l    50(a0),a2    ;RastPort
  89.     move.b    25(a2),d2
  90. ;---set draw color for box
  91.     move.l    28(a5),d0
  92.     movea.l    a2,a1
  93.     jsr    _LVOSetAPen(a6)
  94. ;---move to top-left point
  95.     move.l    12(a5),d1
  96.     move.l    8(a5),d0
  97.     movea.l    a2,a1
  98.     jsr    _LVOMove(a6)
  99. ;---Draw to each of the four corners of the box
  100.     move.l    12(a5),d1
  101.     move.l    16(a5),d0
  102.     movea.l    a2,a1
  103.     jsr    _LVODraw(a6)
  104.     move.l    20(a5),d1
  105.     move.l    16(a5),d0
  106.     movea.l    a2,a1
  107.     jsr    _LVODraw(a6)
  108.     move.l    20(a5),d1
  109.     move.l    8(a5),d0
  110.     movea.l    a2,a1
  111.     jsr    _LVODraw(a6)
  112.     move.l    12(a5),d1
  113.     move.l    8(a5),d0
  114.     movea.l    a2,a1
  115.     jsr    _LVODraw(a6)
  116. ;---restore old FgPen
  117.     moveq    #0,d0
  118.     move.b    d2,d0
  119.     movea.l    a2,a1
  120.     jsr    _LVOSetAPen(a6)
  121.     movem.l    (sp)+,d2/a2
  122.     unlk    a5
  123.     rts
  124.  
  125. ;**************************************************************
  126. ;The following function initializes the structure arrays
  127. ;needed to provide the Color menu topic.
  128. ;
  129. ;InitColorItems(depth)
  130. ;         d0
  131. ;
  132. ;depth is the number of bit-planes in window
  133.  
  134.     XDEF    InitColorItems
  135. InitColorItems:
  136.     movem.l    d2/d3/d4/d5,-(sp)
  137. ;---get # of colors allowed for this depth
  138.     move.w    d0,d4
  139.     lea    _palette,a0
  140.     adda.w    d0,a0
  141.     moveq    #0,d2
  142.     move.b    (a0),d2
  143.     lea    _coloritem,a0
  144.     lea    _colorimage,a1
  145.     moveq    #0,d3
  146.     bra    2$
  147. ;=============== Init Next Item ===============
  148. ;coloritem[n].NextItem = &coloritem[n+1]
  149. 1$    lea    34(a0),a6
  150.     move.l    a6,(a0)+
  151. ;the next two items might be changed for when bit-planes is greater than 2
  152. ;coloritem[n].LeftEdge = 2 + CW * (n % 4)
  153.     move.l    d3,d0
  154.     moveq    #4,d1
  155.     divu.w    d1,d0
  156.     move.w    d0,d5
  157.     swap    d0
  158.     moveq    #40,d1
  159.     mulu.w    d1,d0
  160.     addq.w    #2,d0
  161.     move.w    d0,(a0)+
  162. ;coloritem[n].TopEdge = CH * (n / 4)
  163.     moveq    #25,d1
  164.     mulu.w    d1,d5
  165.     move.w    d5,(a0)+
  166. ;coloritem[n].Width = CW
  167.     move.w    #40,(a0)+
  168. ;coloritem[n].Height = CH
  169.     move.w    #25,(a0)+
  170. ;coloritem[n].Flags = ITEMSTUFF
  171.     move.w    #144,(a0)+
  172. ;coloritem[n].MutualExclude = 0
  173.     clr.l    (a0)+
  174. ;coloritem[n].ItemFill = (APTR)&colorimage[n]
  175.     move.l    a1,(a0)+
  176. ;coloritem[n].SelectFill = NULL
  177.     clr.l    (a0)+
  178. ;coloritem[n].Command = 0
  179.     clr.w    (a0)+
  180. ;coloritem[n].SubItem = NULL
  181.     clr.l    (a0)+
  182. ;coloritem[n].NextSelect = 0
  183.     clr.w    (a0)+
  184. ;=============== Init next Image ===============
  185. ;colorimage[n].LeftEdge = 1
  186.     move.w    #1,(a1)+
  187. ;colorimage[n].TopEdge = 1
  188.     move.w    #1,(a1)+
  189. ;colorimage[n].Width = CW-2
  190.     move.w    #38,(a1)+
  191. ;colorimage[n].Height = CH-2
  192.     move.w    #23,(a1)+
  193. ;colorimage[n].Depth = depth
  194.     move.w    d4,(a1)+
  195. ;colorimage[n].ImageData = NULL
  196.     clr.l    (a1)+
  197. ;colorimage[n].PlanePick = 0
  198.     clr.b    (a1)+
  199. ;colorimage[n].PlaneOnOff = n
  200.     move.b    d3,(a1)+
  201. ;colorimage[n].NextImage = 0
  202.     clr.l    (a1)+
  203.     addq.w    #1,d3
  204. 2$    Dbra    d2,1$(pc)
  205. ;coloritem[colors-1].NextItem = NULL (needed for last item in list)
  206.     clr.l    -34(a0)
  207.     movem.l    (sp)+,d2/d3/d4/d5
  208.     rts
  209.  
  210. ;******************************************************
  211. ;*                   Main Program                     *
  212. ;*                                                    *
  213. ;*      This is the main body of the program.         *
  214. ;******************************************************
  215.  
  216.     XDEF    _main
  217. _main:
  218.     link    a5,#-310
  219. ;---DrawColor = 1  (initial drawing color)
  220.     move.b    #1,-5(a5)
  221. ;---OldBRX = 30, OldBRY = 30  (point coords used for boxes)
  222.     move.w    #30,-8(a5)
  223.     move.w    #30,-10(a5)
  224. ;---TLX = 20, TLY = 20  (initial top-left point coords)
  225.     move.w    #20,-12(a5)
  226.     move.w    #20,-14(a5)
  227. ;---MouseMoved = FALSE   (indicates new mouse position ready)
  228.     clr.w    -38(a5)
  229. ;---ClipIt = FALSE    (are new point coords out of bounds?)
  230.     clr.w    -40(a5)
  231. ;---ClippedLast = FALSE    (was last PenDraw operation clipped?)
  232.     clr.w    -42(a5)
  233. ;---PenMode = FALSE    (indicates PenDraw mode is set)
  234.     clr.w    -44(a5)
  235. ;---PenDown = FALSE     (if mouse moved, then should it draw?)
  236.     clr.w    -46(a5)
  237. ;---RubberBox = FALSE    (are we currently rubberbanding a box?)
  238.     clr.w    -48(a5)
  239. ;---FilledBox = FALSE   (should boxes be filled when drawn?)
  240.     clr.w    -50(a5)
  241. ;---Open Graphics
  242.     movea.l    _SysBase,a6
  243.     lea    GfxName,a1
  244.     jsr    _LVOOldOpenLibrary(a6)
  245.     move.l    d0,_GfxBase
  246. ;---Open Intuition
  247.     lea    IntuiName,a1
  248.     jsr    _LVOOldOpenLibrary(a6)
  249.     move.l    d0,_IntuitionBase
  250.  
  251.     IFNE    TALKTOREXX
  252. ;---Open RexxApp lib
  253.     lea    RexxName,a1
  254.     moveq    #0,d0
  255.     jsr    _LVOOpenLibrary(a6)
  256.     move.l    d0,_rexxBase
  257.     beq    CLSE2
  258.     ENDIF
  259.  
  260. ;---Try to open new window for application
  261.     lea    _NewWindow,a0
  262.     movea.l    _IntuitionBase,a6
  263.     jsr    _LVOOpenWindow(a6)
  264.     move.l    d0,_Window
  265.     beq    CLSE
  266. ;set initial clipping boundaries from the values found in the window
  267. ;structure for border dimensions
  268.     bsr    SetBounds
  269. ;initialize Color menu arrays
  270.     moveq    #2,d0
  271.     bsr    InitColorItems
  272. ;SetMenuStrip( Window, &menu[0] )
  273.     lea    _menu1,a1
  274.     move.l    _Window,a0
  275.     movea.l    _IntuitionBase,a6
  276.     jsr    _LVOSetMenuStrip(a6)
  277. ;set initial draw mode JAM1 and color
  278.     moveq    #0,d0
  279.     movea.l    _Window,a0
  280.     movea.l    50(a0),a1
  281.     movea.l    _GfxBase,a6
  282.     jsr    _LVOSetDrMd(a6)
  283. ;SetAPen( Window->RPort, DrawColor )
  284.     moveq    #0,d0
  285.     move.b    -5(a5),d0
  286.     movea.l    _Window,a0
  287.     movea.l    50(a0),a1
  288.     jsr    _LVOSetAPen(a6)
  289.  
  290. ;==================================================================
  291.     IFNE TALKTOREXX
  292. ;For rexx, we open up a Rexx port, and send out the first command, if there
  293. ;was one, that the user typed on the CLI line. We send it out asynchronously
  294. ;(ie as a macro for the ARexx server to execute). Arexx will load the script
  295. ;(ie our command string will be the name of the script) and execute it (ie
  296. ;send ARexx msgs to the target task). It just so happens that all the demo
  297. ;ARexx scripts that we wrote use Freedraw itself as the target task. In
  298. ;other words, we are sending out a Rexxmsg which will cause the ARexx server
  299. ;to execute a script which sends ARexx msgs to Freedraw. This is how a self-
  300. ;running demo of a program might be implemented. We could have written some
  301. ;scripts to control other products, which Freedraw could start up as so:
  302.     move.l    8(a5),d2
  303.     movea.l    12(a5),a2
  304.     addq.l    #4,a2
  305. ;---Save a5, and set it up as the base of our RexxData
  306.     move.l    a5,-(sp)
  307.     lea    _rexxPort,a5
  308. ;---rexxMask = SetRexxPort()
  309.     movea.l    _rexxBase,a6
  310.     lea        RXname,a1
  311.     jsr    _LVOSetRexxPort(a6)
  312.     beq.s    4$        ;an error in setting up the port
  313. ;---append all the args from the CLI into 1 string with spaces between each arg
  314.     subq.l    #2,d2        ;don't count the name of the program
  315.     bcs.s    5$
  316.     lea    ArexxCmdStr,a1    ;here's where we'll make our Arexx scriptname
  317. 1$    movea.l    (a2)+,a0
  318. 2$    move.b    (a0)+,(a1)+
  319.     bne.s    2$
  320.     move.b    #' ',-1(a1)
  321.     clr.b    (a1)
  322.     dbra    d2,1$
  323. ;---Send this command string out as a macro (ie asyncRexxCmd)
  324.     lea    ArexxCmdStr,a0
  325.     jsr    _LVOASyncRexxCmd(a6)
  326. ;---If an error in sending out Rexxmsg, print the returned err msg to window
  327.     bne.s    5$
  328. 4$    ;---null-term error string in a0
  329.     bsr    printRexxErr
  330. ;---Restore a5
  331. 5$    movea.l    (sp)+,a5
  332.     ENDIF
  333.  
  334. ;Everything the program needs is now initialized and put in place.  The
  335. ;program enters the following loop and processes message continuously as they
  336. ;are received from Intuition. I guess this loop is the real workhorse of the
  337. ;program.  By the way, the loop control variable KeepGoing remains TRUE until a
  338. ;CLOSEWINDOW message is received. At that point it goes FALSE, and the program
  339. ;cleans up and exits.
  340. ;   while( KeepGoing )
  341. .37    tst.w    _KeepGoing
  342.     beq    .38
  343. ;stay here until a message is received from Intuition or REXX port
  344.     movea.l    _Window,a0
  345.     movea.l    86(a0),a1
  346.  
  347.     IFNE    TALKTOREXX
  348.     move.l    RexxMask,d0    ;If ARexx, use the mask that the lib setup
  349.     ENDIF
  350.     IFEQ    TALKTOREXX
  351.     moveq    #0,d0
  352.     ENDIF
  353.  
  354.     move.b    15(a1),d1
  355.     bset.l    d1,d0
  356.     movea.l    _SysBase,a6
  357.     jsr    _LVOWait(a6)
  358.  
  359.     IFNE    TALKTOREXX
  360. ;---see if any REXX msgs to handle (safe to call even if Rexx port not setup)
  361. ;   If there are any ARexx msgs, receiveRexx will handle them by calling our
  362. ;   ErrorVector for msgs that WE sent out (ie the msg that started up the
  363. ;   whole, initial script process), or by calling myDispatch() for msgs that
  364. ;   some other task sends us (ie the ARexx server will be sending us msgs when
  365. ;   it executes that script file, or another program could be sending msgs to
  366. ;   our FreeDraw _rexxPort).
  367.     move.l    a5,-(sp)
  368.     lea    _rexxPort,a5    ;setup a5 as base of Rexx data section
  369.     movea.l    _rexxBase,a6
  370.     jsr    _LVOReceiveRexx(a6)
  371.     movea.l    (sp)+,a5
  372.     ENDIF
  373.  
  374. ;---MouseMoved = FALSE   (clear this flag each time thru loop)
  375.     clr.w    -38(a5)
  376. ;---get next IntuiMsg at window
  377. .39    movea.l    _Window,a0
  378.     movea.l    86(a0),a0
  379.     movea.l    _SysBase,a6
  380.     jsr    _LVOGetMsg(a6)
  381.     move.l    d0,-4(a5)
  382.     beq    .40
  383.     movea.l    d0,a1
  384.     move.l    20(a1),-18(a5)
  385. ;code = NewMessage->Code
  386.     move.w    24(a1),-20(a5)
  387. ;x = Window->MouseX
  388.     move.l    _Window,a0
  389.     move.w    14(a0),-22(a5)
  390. ;y = Window->MouseY
  391.     move.w    12(a0),-24(a5)
  392. ;Reply the IntuiMessage
  393.     jsr    _LVOReplyMsg(a6)
  394. ;Examine point coords from message received and set the clipping flag if out
  395. ;of bounds. If user was drawing in PenMode when message was received, then the
  396. ;ClippedLast flag should also be set to indicate this to the next draw oper-
  397. ;ation.
  398. ;if(ClipIt = ( x < MinX || x > MaxX || y < MinY || y > MaxY )) if( PenDown )
  399.     move.w    -22(a5),d0
  400.     cmp.w    _MinX,d0
  401.     blt.s    .43
  402.     move.w    -22(a5),d0
  403.     cmp.w    _MaxX,d0
  404.     bgt.s    .43
  405.     move.w    -24(a5),d0
  406.     cmp.w    _MinY,d0
  407.     blt.s    .43
  408.     move.w    -24(a5),d0
  409.     cmp.w    _MaxY,d0
  410.     ble.s    .42
  411. .43    moveq    #1,d0
  412.     bra.s    .44
  413. .42    moveq    #0,d0
  414. .44    move.w    d0,-40(a5)
  415.     beq    .41
  416. ;ClippedLast = TRUE
  417.     tst.w    -46(a5)
  418.     beq.s    .41
  419.     move.w    #1,-42(a5)
  420. ;enter switch on type of message received
  421. .41    move.l    -18(a5),d0
  422.     subq.l    #2,d0
  423.     beq.s    .49
  424.     subq.l    #6,d0
  425.     beq.s    .51
  426.     subq.l    #8,d0
  427.     beq.s    .48
  428.     sub.l    #240,d0
  429.     beq    .66
  430.     sub.l    #256,d0
  431.     beq.s    .50
  432.     sub.l    #523776,d0
  433.     beq    .82
  434.     bra    .39
  435. ;========================case MOUSEMOVE:
  436. ;Don't really do anything with this one
  437. ;until any other, more important, messages
  438. ;are received and processed.
  439. ;MouseMoved = TRUE
  440. .48    move.w    #1,-38(a5)
  441.     bra    .39
  442. ;========================case NEWSIZE:
  443. .49    bsr    SetBounds
  444.     bra    .39
  445. ;========================case CLOSEWINDOW:
  446. ;User is ready to quit, so indicate that execution should terminate
  447. ;with next iteration of the IDCMP loop.
  448. .50    clr.w    _KeepGoing
  449.     bra    .39
  450. ;=======================case MOUSEBUTTONS:
  451. ;A number of things could have happened here, and further examination of data
  452. ;received from message is needed to determine what action should be taken.
  453. ;The code variable holds important info about what actually caused the message
  454. ;to be sent in the first place.
  455. .51    move.w    -20(a5),d0
  456.     subi.w    #104,d0
  457.     beq.s    .55
  458.     subq.w    #1,d0
  459.     beq    .64
  460.     subi.w    #127,d0
  461.     bne    .39
  462. ;case SELECTUP:
  463. ;User was holding down the left button and just released it. The PenMode
  464. ;flag variables are set accordingly. The pen can no longer be down, and
  465. ;ClippedLast is reset for next time.
  466. ;PenDown = ClippedLast = FALSE
  467. .54    clr.w    -42(a5)
  468.     clr.w    -46(a5)
  469.     bra    .39
  470. ;case SELECTDOWN:
  471. ;User has pressed the left button, and
  472. ;several differnt actions may need to
  473. ;be taken.  If the ClipIt value is TRUE,
  474. ;then no action should be taken at all.
  475. ;
  476. ;if( ClipIt ) break;
  477. .55    tst.w    -40(a5)
  478.     bne    .39
  479. ;If user is currently in PenMode, then set up to draw when MOUSEMOVED messages
  480. ;are received until a subsequent SELECTUP message comes in.
  481. ;if( PenMode )
  482.     tst.w    -44(a5)
  483.     beq    .56
  484. ;PenDown = TRUE
  485.     move.w    #1,-46(a5)
  486. ;ClippedLast = FALSE
  487.     clr.w    -42(a5)
  488. ;make sure to set appropriate mode, JAM1
  489.     moveq    #0,d0
  490.     movea.l    _Window,a0
  491.     movea.l    50(a0),a1
  492.     movea.l    _GfxBase,a6
  493.     jsr    _LVOSetDrMd(a6)
  494. ;and establish initial position to draw
  495.     moveq    #0,d1
  496.     move.w    -24(a5),d1
  497.     moveq    #0,d0
  498.     move.w    -22(a5),d0
  499.     move.l    _Window,a0
  500.     move.l    50(a0),a1
  501.     jsr    _LVOMove(a6)
  502.     bra    .39
  503. ;If user is currently rubberbanding a box, then a SELECTDOWN message means it
  504. ;is time to stop rubberbanding and actually draw it. The following code will
  505. ;be executed if this is the case, and it will determine if a filled box is
  506. ;needed before rendering.
  507. ;if( RubberBox )
  508. .56    tst.w    -48(a5)
  509.     beq    .57
  510. ;set draw mode back to JAM1 since it is now currently set to COMPLEMENT
  511.     moveq    #0,d0
  512.     movea.l    _Window,a0
  513.     movea.l    50(a0),a1
  514.     movea.l    _GfxBase,a6
  515.     jsr    _LVOSetDrMd(a6)
  516. ;RubberBox = FALSE  (turn off rubberbanding)
  517.     clr.w    -48(a5)
  518. ;Restore the condition of the RMBTRAP bit in the Window structure's Flags
  519. ;member.  Menubutton events will not be received by this loop.
  520.     movea.l    _Window,a0
  521.     bclr.b    #0,25(a0)
  522. ;RectFill is not condusive to the smooth execution of programs if arguments are
  523. ;out of order, so this code sorts them in preparation for the call.
  524. ;if( FilledBox )
  525.     tst.w    -50(a5)
  526.     beq    .58
  527. ;first sort the x-coords
  528. ;if TLX < OldBRX
  529.     move.w    -12(a5),d0
  530.     cmp.w    -8(a5),d0
  531.     bge.s    .59
  532. ;x1 = TLX,  x2 = OldBRX
  533.     move.w    -12(a5),-26(a5)
  534.     move.w    -8(a5),-30(a5)
  535.     bra.s    .60
  536. ;x1 = OldBRX,  x2 = TLX
  537. .59    move.w    -8(a5),-26(a5)
  538.     move.w    -12(a5),-30(a5)
  539. ;then sort the y-coords
  540. ;if TLY < OldBRY
  541. .60    move.w    -14(a5),d0
  542.     cmp.w    -10(a5),d0
  543.     bge.s    .61
  544. ;y1 = TLY;  y2 = OldBRY
  545.     move.w    -14(a5),-28(a5)
  546.     move.w    -10(a5),-32(a5)
  547.     bra.s    .62
  548. ;y1 = OldBRY;  y2 = TLY
  549. .61    move.w    -10(a5),-28(a5)
  550.     move.w    -14(a5),-32(a5)
  551. ; now generate the filled rectangle
  552. ;RectFill( Window->RPort, (long)x1, (long)y1,(long)x2, (long)y2 )
  553. .62    moveq    #0,d3
  554.     move.w    -32(a5),d3
  555.     moveq    #0,d2
  556.     move.w    -30(a5),d2
  557.     moveq    #0,d1
  558.     move.w    -28(a5),d1
  559.     moveq    #0,d0
  560.     move.w    -26(a5),d0
  561.     move.l    _Window,a0
  562.     move.l    50(a0),a1
  563.     jsr    _LVORectFill(a6)
  564.     bra    .39
  565. ;FilledBox not set, so draw hollow box
  566. ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor )
  567. .58    moveq    #0,d0
  568.     move.b    -5(a5),d0
  569.     move.l    d0,-(sp)
  570.     move.l    _Window,-(sp)
  571.     moveq    #0,d0
  572.     move.w    -10(a5),d0
  573.     move.l    d0,-(sp)
  574.     moveq    #0,d0
  575.     move.w    -8(a5),d0
  576.     move.l    d0,-(sp)
  577.     moveq    #0,d0
  578.     move.w    -14(a5),d0
  579.     move.l    d0,-(sp)
  580.     moveq    #0,d0
  581.     move.w    -12(a5),d0
  582.     move.l    d0,-(sp)
  583.     bsr    DrawBox
  584.     lea    24(sp),sp
  585.     bra    .39
  586. ;If execution comes here, then PenMode was
  587. ;not set and user was not rubberbanding.
  588. ;SELECTDOWN therefore indicates to start the
  589. ;rubberbanding process at this point. The
  590. ;initial coords are set to the values we
  591. ;received when the GetMsg() was executed.
  592. ;TLX = OldBRX = x,  TLY = OldBRY = y
  593. .57    move.w    -22(a5),-8(a5)
  594.     move.w    -22(a5),-12(a5)
  595.     move.w    -24(a5),-10(a5)
  596.     move.w    -24(a5),-14(a5)
  597. ;set to render in COMPLEMENT mode
  598.     moveq    #2,d0
  599.     movea.l    _Window,a0
  600.     movea.l    50(a0),a1
  601.     movea.l    _GfxBase,a6
  602.     jsr    _LVOSetDrMd(a6)
  603. ;/* set flag to indicate we are now rubberbanding */
  604. ;RubberBox = TRUE
  605.     move.w    #1,-48(a5)
  606. ;This instruction indicates to Intuition that we now wish to receive a message
  607. ;each time the Menubutton is pressed. This is how we hijack the right button
  608. ;for temporary use as a Cancel button instead of a Menubutton.
  609. ;Window->Flags |= RMBTRAP
  610.     move.l    _Window,a0
  611.     bset.b    #0,25(a0)
  612. ;render the initial rubberbox and exit
  613. ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor )
  614.     moveq    #0,d0
  615.     move.b    -5(a5),d0
  616.     move.l    d0,-(sp)
  617.     move.l    _Window,-(sp)
  618.     moveq    #0,d0
  619.     move.w    -10(a5),d0
  620.     move.l    d0,-(sp)
  621.     moveq    #0,d0
  622.     move.w    -8(a5),d0
  623.     move.l    d0,-(sp)
  624.     moveq    #0,d0
  625.     move.w    -14(a5),d0
  626.     move.l    d0,-(sp)
  627.     moveq    #0,d0
  628.     move.w    -12(a5),d0
  629.     move.l    d0,-(sp)
  630.     bsr    DrawBox
  631.     lea    24(sp),sp
  632.     bra    .39
  633. ;=======================case MENUDOWN:
  634. ;WE only receive this message class if
  635. ;the RMBTRAP flag bit has been set, so
  636. ;it always means that we should cancel
  637. ;the box which is currently rubberbanding.
  638. ;turn the flag off */
  639. ;RubberBox = FALSE
  640. .64    clr.w    -48(a5)
  641. ;restore control of menubutton to Intuition */
  642. ;Window->Flags &= ( 0xFFFFFFFF ^ RMBTRAP );
  643.     move.l    _Window,a0
  644.     bclr.b    #0,25(a0)
  645. ;erase (by double XOR'ing) the current
  646. ;rubberbox and exit switch.
  647. ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
  648.     moveq    #0,d0
  649.     move.b    -5(a5),d0
  650.     move.l    d0,-(sp)
  651.     move.l    _Window,-(sp)
  652.     moveq    #0,d0
  653.     move.w    -10(a5),d0
  654.     move.l    d0,-(sp)
  655.     moveq    #0,d0
  656.     move.w    -8(a5),d0
  657.     move.l    d0,-(sp)
  658.     moveq    #0,d0
  659.     move.w    -14(a5),d0
  660.     move.l    d0,-(sp)
  661.     moveq    #0,d0
  662.     move.w    -12(a5),d0
  663.     move.l    d0,-(sp)
  664.     bsr    DrawBox
  665.     lea    24(sp),sp
  666.     bra    .39
  667. ;=======================case MENUPICK:
  668. ;A menu event has taken place and is ready to be processed. Examine the code
  669. ;variable received from the message to determine what action should be taken.
  670. ;The first check is for code=MENUNULL, which means that nothing should be done.
  671. .66    cmp.w    #-1,-20(a5)
  672.     beq    .39
  673. ;get menu and item numbers from code
  674. ;MenuNum = MENUNUM( code )
  675.     moveq    #31,d0
  676.     and.w    -20(a5),d0
  677.     move.w    d0,-34(a5)
  678. ;ItemNum = ITEMNUM( code )
  679.     move.w    -20(a5),d1
  680.     lsr.w    #5,d1
  681.     and.w    #63,d1
  682.     move.w    d1,-36(a5)
  683. ;determine appropriate action by menu number
  684. ;switch ( MenuNum )
  685.     tst.w    d0
  686.     beq.s    .70
  687.     subq.w    #1,d0
  688.     beq.s    .71
  689.     bra    .39
  690. ;case 0:
  691. ;Menu 0 is the Color menu. The item number indicates which new color to set.
  692. ;DrawColor = ItemNum
  693. .70    moveq    #0,d0
  694.     move.b    d1,d0
  695.     move.b    d0,-5(a5)
  696.     movea.l    _Window,a0
  697.     movea.l    50(a0),a1
  698.     movea.l    _GfxBase,a6
  699.     jsr    _LVOSetAPen(a6)
  700.     bra    .39
  701. ;case 1:
  702. ;Menu 1 is the DrawMode menu. The item number indicates what to do.
  703. ;NOTE: Since we cannot have received this message if we were rubberbanding,
  704. ;then there is no need to clean up before changing drawing modes.
  705. .71    move.w    d1,d0
  706.     beq.s    .74
  707.     subq.w    #1,d1
  708.     beq.s    .75
  709.     subq.w    #1,d1
  710.     beq.s    .76
  711.     subq.w    #1,d1
  712.     bne    .39
  713. ;case 3:
  714. ;set flag variables for PenMode
  715. ;PenMode = TRUE;
  716. .77    move.w    #1,-44(a5)
  717.     bra    .39
  718. ;case 1: set flag variables for hollow box */
  719. ;PenMode = FALSE;
  720. .75    clr.w    -44(a5)
  721. ;FilledBox = FALSE;
  722.     clr.w    -50(a5)
  723.     bra    .39
  724. ;case 2: set flag variables for filled box
  725. ;PenMode = FALSE
  726. .76    clr.w    -44(a5)
  727. ;FilledBox = TRUE
  728.     move.w    #1,-50(a5)
  729.     bra    .39
  730. ;case 0: Erase window to current color 
  731. ;---set JAM1
  732. .74    moveq    #0,d0
  733.     movea.l    _Window,a0
  734.     movea.l    50(a0),a1
  735.     movea.l    _GfxBase,a6
  736.     jsr    _LVOSetDrMd(a6)
  737. ;RectFill( Window->RPort, (long)MinX, (long)MinY,(long)MaxX, (long)MaxY);
  738.     moveq    #0,d3
  739.     move.w    _MaxY,d3
  740.     moveq    #0,d2
  741.     move.w    _MaxX,d2
  742.     moveq    #0,d1
  743.     move.w    _MinY,d1
  744.     moveq    #0,d0
  745.     move.w    _MinX,d0
  746.     move.l    _Window,a0
  747.     move.l    50(a0),a1
  748.     jsr    _LVORectFill(a6)
  749.     bra    .39
  750. ;============case INACTIVEWINDOW:
  751. .82
  752. ;User has de-selected our window, so a
  753. ;little bit of cleaning up may be needed
  754. ;to prevent untoward events when he comes
  755. ;back to it.
  756. ;erase any outstanding rubberbox */
  757. ;if( RubberBox )
  758. ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor)
  759.     tst.w    -48(a5)
  760.     beq    .83
  761.     moveq    #0,d0
  762.     move.b    -5(a5),d0
  763.     move.l    d0,-(sp)
  764.     move.l    _Window,-(sp)
  765.     moveq    #0,d0
  766.     move.w    -10(a5),d0
  767.     move.l    d0,-(sp)
  768.     moveq    #0,d0
  769.     move.w    -8(a5),d0
  770.     move.l    d0,-(sp)
  771.     moveq    #0,d0
  772.     move.w    -14(a5),d0
  773.     move.l    d0,-(sp)
  774.     moveq    #0,d0
  775.     move.w    -12(a5),d0
  776.     move.l    d0,-(sp)
  777.     bsr    DrawBox
  778.     lea    24(sp),sp
  779. ;reset all the flafg variables */
  780. ;PenDown = ClippedLast = RubberBox = FALSE;
  781. .83
  782.     clr.w    -48(a5)
  783.     clr.w    -42(a5)
  784.     clr.w    -46(a5)
  785. ;return possibly diverted menubutton events to Big I
  786. ;Window->Flags &= ( 0xFFFFFFFF ^ RMBTRAP );
  787.     move.l    _Window,a0
  788.     bclr.b    #0,25(a0)
  789.     bra    .39
  790. ;============================================================
  791. ;There are no more messages waiting at the IDCMP port, so we can now proceed
  792. ;to process any MOUSEMOVED message we may have received.
  793. ;if( MouseMoved && !ClipIt)
  794. .40    tst.w    -38(a5)
  795.     beq    .37
  796.     tst.w    -40(a5)
  797.     bne    .37
  798. ;the mouse did move, and we don't need to clip
  799. ;check first if we are drawing in PenMode
  800. ;if( PenDown )
  801.     tst.w    -46(a5)
  802.     beq    .88
  803. ;We have to examine if we clipped the
  804. ;last PenMode draw operation.  If we did,
  805. ;then this is the first move back into
  806. ;window boundaries, so we mov instead of
  807. ;drawing.
  808. ;if( ClippedLast )
  809.     tst.w    -42(a5)
  810.     beq    .89
  811. ;ClippedLast = FALSE;         /* reset this flag 
  812.     clr.w    -42(a5)
  813.     moveq    #0,d1
  814.     move.w    -24(a5),d1
  815.     moveq    #0,d0
  816.     move.w    -22(a5),d0
  817.     move.l    _Window,a0
  818.     move.l    50(a0),a1
  819.     movea.l    _GfxBase,a6
  820.     jsr    _LVOMove(a6)
  821.     bra    .37
  822. ;Draw( Window->RPort, (long)x, (long)y ); /* draw to x,y coords
  823. .89    moveq    #0,d1
  824.     move.w    -24(a5),d1
  825.     moveq    #0,d0
  826.     move.w    -22(a5),d0
  827.     move.l    _Window,a0
  828.     move.l    50(a0),a1
  829.     movea.l    _GfxBase,a6
  830.     jsr    _LVODraw(a6)
  831.     bra    .37
  832. ;We weren't in PenMode, but we still might
  833. ;be rubberbanding a box.  If so, then we
  834. ;should erase the current rubberbox and
  835. ;draw a new one with the new mouse coords.
  836. ;
  837. ;if( RubberBox )
  838. .88    tst.w    -48(a5)
  839.     beq    .37
  840. ;erase the old rubberbox - draw mode is COMPLEMENT
  841. ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
  842.     moveq    #0,d0
  843.     move.b    -5(a5),d0
  844.     move.l    d0,-(sp)
  845.     move.l    _Window,-(sp)
  846.     moveq    #0,d0
  847.     move.w    -10(a5),d0
  848.     move.l    d0,-(sp)
  849.     moveq    #0,d0
  850.     move.w    -8(a5),d0
  851.     move.l    d0,-(sp)
  852.     moveq    #0,d0
  853.     move.w    -14(a5),d0
  854.     move.l    d0,-(sp)
  855.     moveq    #0,d0
  856.     move.w    -12(a5),d0
  857.     move.l    d0,-(sp)
  858.     bsr    DrawBox
  859.     lea    24(sp),sp
  860. ;assign new values to box coords */
  861. ;OldBRX = x;  OldBRY = y;
  862.     move.w    -22(a5),-8(a5)
  863.     move.w    -24(a5),-10(a5)
  864. ;and draw the new rubberbox */ 
  865. ;DrawBox( TLX, TLY, OldBRX, OldBRY, Window, DrawColor );
  866.     moveq    #0,d0
  867.     move.b    -5(a5),d0
  868.     move.l    d0,-(sp)
  869.     move.l    _Window,-(sp)
  870.     moveq    #0,d0
  871.     move.w    -10(a5),d0
  872.     move.l    d0,-(sp)
  873.     moveq    #0,d0
  874.     move.w    -8(a5),d0
  875.     move.l    d0,-(sp)
  876.     moveq    #0,d0
  877.     move.w    -14(a5),d0
  878.     move.l    d0,-(sp)
  879.     moveq    #0,d0
  880.     move.w    -12(a5),d0
  881.     move.l    d0,-(sp)
  882.     bsr    DrawBox
  883.     lea    24(sp),sp
  884.     bra    .37
  885. ;====================== PROGRAM CLEANUP AND EXIT ========================
  886. .38
  887. ;It must be time to quit, so we have to clean up and exit.
  888.  
  889.     IFNE TALKTOREXX
  890. ;With Rexx, we need to bring the port down.  You must call freeRexxPort before
  891. ;doing any exit() for programs that have multiple paths to exit.
  892.     move.l    a5,-(sp)
  893.     lea    _rexxPort,a5
  894.     movea.l    _rexxBase,a6
  895.     jsr    _LVOFreeRexxPort(a6)
  896.     movea.l    (sp)+,a5
  897.     ENDIF
  898.  
  899. ;---Clear our MenuStrip
  900.     movea.l    _Window,a0
  901.     movea.l    _IntuitionBase,a6
  902.     jsr    _LVOClearMenuStrip(a6)
  903. ;---Close our Window
  904.     move.l    _Window,a0
  905.     jsr    _LVOCloseWindow(a6)
  906. ;---Close the RexxApp lib
  907. CLSE    movea.l    _SysBase,a6
  908.  
  909.     IFNE    TALKTOREXX
  910.     movea.l    _rexxBase,a1
  911.     jsr    _LVOCloseLibrary(a6)
  912.     ENDIF
  913.  
  914. ;---Close Graphics and Intuition
  915. CLSE2    movea.l    _IntuitionBase,a1
  916.     jsr    _LVOCloseLibrary(a6)
  917.     movea.l    _GfxBase,a1
  918.     jsr    _LVOCloseLibrary(a6)
  919. ;---exit the program
  920.     pea    1
  921.     jsr    _exit
  922.     add.w    #4,sp
  923.     unlk    a5
  924.     rts
  925.  
  926. SetBounds:
  927. ;---MinX = Window->BorderLeft
  928.     move.l    _Window,a0
  929.     move.b    54(a0),d0
  930.     ext.w    d0
  931.     move.w    d0,_MinX
  932. ;---MinY = Window->BorderTop
  933.     move.b    55(a0),d0
  934.     ext.w    d0
  935.     move.w    d0,_MinY
  936. ;---MaxX = Window->Width - Window->BorderRight - 1
  937.     move.w    8(a0),d0
  938.     move.b    56(a0),d1
  939.     ext.w    d1
  940.     sub.w    d1,d0
  941.     subq.w    #1,d0
  942.     move.w    d0,_MaxX
  943. ;---MaxY = Window->Height - Window->BorderBottom - 1
  944.     move.w    10(a0),d0
  945.     move.b    57(a0),d1
  946.     ext.w    d1
  947.     sub.w    d1,d0
  948.     subq.w    #1,d0
  949.     move.w    d0,_MaxY
  950.     rts
  951.  
  952.     IFNE TALKTOREXX
  953.  
  954. ;Now we get into the actual code necessary for our REXX port; functions
  955. ;that do the real work.  Note that this program was not structured
  956. ;particularly nicely for Rexx. I had to write each of these functions.
  957. ;Many programs have these subroutines already in place. They are called
  958. ;as part of the event loop.  This program, however, just has one big
  959. ;IDCMP loop in main with different actions . . .
  960.  
  961. ;********************************************************************
  962. ;This is our REXX dispatch function. This is called whenever some other appli-
  963. ;cation has sent us an Arexx msg with a command that our program understands.
  964. ;The ARexx app lib has already determined which command, and set up a3 as
  965. ;the address of the appropriate handler. We now check to make sure a Window
  966. ;currently exists.  Then, we store away the `current color' and change it to
  967. ;Rexx's current color, call our handler function, and then restore the color.
  968. ;If our handler replies, it sets userreplied to indicate that. If the parse and
  969. ;everything else was successful, we send an rm_Result of 0 (via setupResults).
  970. ;Otherwise, we send a failure of 20 to ARexx server to indicate that the args
  971. ;were messed up. We always return TRUE, because we don't have an instance of
  972. ;needing to hold onto a Rexxmsg after we use it here. Note that we must not
  973. ;alter register a5, but a2, a3, and a4 are OK to scratch.
  974. ;
  975. ;myDispatch(Rexxmsg, asscListVector, string, RexxDataBase)
  976. ;        a2    a3        a4    a5
  977.  
  978.     XDEF    myDispatch
  979. myDispatch:
  980. ;---Make sure that our window is open
  981.     move.l    _Window,d0
  982.     beq.s    1$
  983. ;---Initially, error = 0 (indicate no error with getting args from Argstring)
  984.     clr.l    error
  985. ;---Initially, no returned Result string
  986.     clr.l    ResultStr
  987. ;---Save window's current PenA
  988.     move.l    d4,-(sp)
  989.     movea.l    d0,a0
  990.     movea.l    50(a0),a1
  991.     moveq    #0,d4
  992.     move.b    25(a1),d4
  993. ;---Set PenA to currrexxcolor
  994.     move.l    _currrexxcolor,d0
  995.     movea.l    _GfxBase,a6
  996.     jsr    _LVOSetAPen(a6)
  997. ;---Call our vector for this rexx command
  998.     movea.l    a4,a0    ;put Argstring in a0 too
  999.     jsr    (a3)
  1000. ;---Restore PenA
  1001.     move.l    d4,d0
  1002.     movea.l    _Window,a0
  1003.     movea.l    50(a0),a1
  1004.     movea.l    _GfxBase,a6
  1005.     jsr    _LVOSetAPen(a6)
  1006.     move.l    (sp)+,d4
  1007. ;---if error = 0 (success), SetupResults(Rexxmsg, 0, 0, ResultStr)
  1008.     movea.l    ResultStr,a0
  1009.     move.l    error,d0    ;primary return
  1010.     bne.s    1$
  1011.     moveq    #0,d1
  1012. 3$    movea.l    a2,a1
  1013.     movea.l    _rexxBase,a6
  1014.     jsr    _LVOSetupResults(a6)
  1015. ;---Tell the lib to reply it now
  1016.     moveq    #1,d0
  1017.     rts
  1018. ;---ERROR: SetupResults(Rexxmsg, error, 10, NULL)
  1019. 1$    moveq    #10,d1
  1020.     suba.l    a0,a0        ;no return Argstring
  1021.     bra.s    3$
  1022.  
  1023. ;*******************************************************
  1024. ;This handler sets the current rexx color.
  1025. ;
  1026. ;rexxcolor(Rexxmsg, string)
  1027. ;        a2   a0,a4
  1028.  
  1029.     XDEF    rexxcolor
  1030. rexxcolor:
  1031. ;---Get 1 number from the ascii string
  1032.     bsr.s    getnm
  1033.     move.l    d0,_currrexxcolor
  1034. rxout    rts
  1035.  
  1036. ;***********************************************************************
  1037. ;This function takes an address of a string (in a0), parses the next number
  1038. ;(ie converts the next ascii digits into a numeric value), returns it in d0,
  1039. ;and advances a0 to point to the next char after the last ascii digit. If
  1040. ;there are no ascii digits in the string at all (if we called this function
  1041. ;then we must have expected some), then set error to indicate an error in
  1042. ;this ARexx supplied string (ie there's an arg missing from this ARexx line).
  1043. ;
  1044. ;number,string = getnm(string)
  1045. ; d0     a0        a0
  1046.  
  1047.     XDEF    getnm
  1048. getnm:
  1049. ;---value = 0
  1050.     moveq    #0,d0
  1051.     moveq    #0,d1
  1052. ;---If between '0' to '9'
  1053. 2$    move.b    (a0)+,d1
  1054.     beq.s    3$
  1055.     subi.b    #'0',d1
  1056.     bcs.s    2$
  1057.     cmp.b    #9,d1
  1058.     bhi.s    2$
  1059. 5$    mulu.w    #10,d0
  1060.     add.l    d1,d0
  1061.     move.b    (a0)+,d1
  1062.     beq.s    6$
  1063.     subi.b    #'0',d1
  1064.     bcs.s    6$
  1065.     cmp.b    #9,d1
  1066.     bls.s    5$
  1067.     subq.l    #1,a0
  1068. 4$    rts
  1069. ;---No ascii chars to convert
  1070. 3$    move.b    #20,error+3    ;indicate an error upon return to myDispatch of level 20
  1071. 6$    subq.l    #1,a0
  1072.     rts
  1073.  
  1074. ;**********************************************************************
  1075. ;This function trys to find `numArgs' numeric arguments in the command
  1076. ;string, and stuffs them into the args array.
  1077. ;
  1078. ;parseargs(string, numArgs)
  1079. ;         a0         d0
  1080.  
  1081.     XDEF    parseargs
  1082. parseargs:
  1083.     move.l    d4,-(sp)
  1084.     move.l    d0,d4
  1085.     lea    Points,a1
  1086.     bra.s    2$
  1087. 1$    bsr.s    getnm
  1088.     move.l    d0,(a1)+
  1089. 2$    dbra    d4,1$(pc)
  1090.     move.l    (sp)+,d4
  1091.     rts
  1092.  
  1093. ;***********************************************************************
  1094. ;This function silently clips the x and y values of the passed Point
  1095. ;structure to the current window bounds. My Point is defined as so:
  1096. ;
  1097. ;X     dc.l    [x pixel position of the Point]
  1098. ;Y     dc.l    [y pixel position]
  1099. ;
  1100. ;clipxy(LineStruct)
  1101. ;      a0
  1102.  
  1103.     XDEF    clipxy
  1104. clipxy:
  1105. ;---Check that Rectangle[leftX] > MinX
  1106.     moveq    #0,d1
  1107.     move.w    _MinX,d1
  1108.     move.l    (a0),d0
  1109.     cmp.l    d0,d1
  1110.     bls.s    1$
  1111.     move.l    d1,d0
  1112. ;---Check that Rectangle[leftX] < MaxX
  1113. 1$    move.w    _MaxX,d1
  1114.     cmp.l    d0,d1
  1115.     bcc.s    2$
  1116.     move.l    d1,d0
  1117. 2$    move.l    d0,(a0)+
  1118. ;---Check that Rectangle[topY] > MinY
  1119.     move.w    _MinY,d1
  1120.     move.l    (a0),d0
  1121.     cmp.l    d0,d1
  1122.     bls.s    3$
  1123.     move.l    d1,d0
  1124. ;---Check that Rectangle[topY] < MaxY
  1125. 3$    move.w    _MaxY,d1
  1126.     cmp.l    d0,d1
  1127.     bcc.s    4$
  1128.     move.l    d1,d0
  1129. 4$    move.l    d0,(a0)+
  1130.     rts
  1131.  
  1132. ;*************************************************************************
  1133. ; This gets 4 numbers from the passed ascii string and stores them in the
  1134. ; Rectangle array (4 LONGS). It then clips the Rec to the window dimensions.
  1135. ;
  1136. ;leftX     dc.l    [the left x pixel position of the rectangle]
  1137. ;topY     dc.l    [the upper y pixel position]
  1138. ;rightX  dc.l    [the right x]
  1139. ;bottomY dc.l    [the bottom y pixel position]
  1140. ;
  1141. ;Note that I treat the Rectangle structure as two adjacent Point structures
  1142. ;
  1143. ;GetBoxCoords(string)
  1144. ;        a0
  1145.  
  1146. GetBoxCoords:
  1147. ;---Parse 4 numbers from the ARexx string into a Rectangle structure
  1148.     moveq    #4,d0
  1149.     bsr.s    parseargs
  1150. ;---Check the leftX and topY coords
  1151.     lea    Points,a0
  1152.     bsr.s    clipxy
  1153. ;---Now check the rightX and bottomY coords
  1154.     bra.s    clipxy
  1155.  
  1156. ;***********************************************************
  1157. ;This handler parses 4 numbers into Rectangle struct and draws a wireframe box.
  1158. ;
  1159. ;rexxbox(Rexxmsg, string)
  1160.  
  1161.     XDEF    rexxbox
  1162. rexxbox:
  1163.     bsr.s    GetBoxCoords
  1164. ;DrawBox(args[0], args[1], args[2], args[3], Window, currrexxcolor)
  1165.     move.l    _currrexxcolor,-(sp)
  1166.     move.l    _Window,-(sp)
  1167.     move.l    Points+12,-(sp)
  1168.     move.l    Points+8,-(sp)
  1169.     move.l    Points+4,-(sp)
  1170.     move.l    Points,-(sp)
  1171.     bsr    DrawBox
  1172.     lea    24(sp),sp
  1173.     unlk    a5
  1174.     rts
  1175.  
  1176. ;******************************************************************
  1177. ; This handler parses 4 numbers into Rectangle struct and draws a filled box.
  1178. ;
  1179. ; rexxfbox(Rexxmsg, string)
  1180.  
  1181.     XDEF    rexxfbox
  1182. rexxfbox:
  1183.     movem.l    d2/d3,-(sp)
  1184.     bsr.s    GetBoxCoords
  1185. ;---Get 4 corners and error check
  1186.     move.l    Points+12,d3
  1187.     move.l    Points+8,d2
  1188.     move.l    Points+4,d1
  1189.     move.l    Points,d0
  1190.     cmp.l    d2,d0
  1191.     bls.s    1$
  1192.     exg.l    d0,d2
  1193. 1$    cmp.l    d3,d1
  1194.     ble.s    2$
  1195.     exg.l    d1,d3
  1196. ;---Draw box
  1197. 2$    movea.l    _Window,a0
  1198.     movea.l    50(a0),a1
  1199.     movea.l    _GfxBase,a6
  1200.     jsr    _LVORectFill(a6)
  1201.     movem.l    (sp)+,d2/d3
  1202.     rts
  1203.  
  1204. ;*********************************************************************
  1205. ;This handler grabs four numbers from the Rexxstring and draws a line
  1206. ;We interprete the 4 numbers as X and Y pixel start positions, and X and Y end
  1207. ;positions.
  1208. ;
  1209. ;rexxline(Rexxmsg, string)
  1210.  
  1211.     XDEF    rexxline
  1212. rexxline:
  1213.     bsr    GetBoxCoords
  1214. ;---Move to start position
  1215.     move.l    Points+4,d1
  1216.     move.l    Points,d0
  1217.     movea.l    _Window,a0
  1218.     movea.l    50(a0),a1
  1219.     movea.l    _GfxBase,a6
  1220.     jsr    _LVOMove(a6)
  1221. ;---Draw to end position
  1222.     move.l    Points+12,d1
  1223.     move.l    Points+8,d0
  1224.     movea.l    _Window,a0
  1225.     movea.l    50(a0),a1
  1226.     jmp    _LVODraw(a6)
  1227.  
  1228. ;**********************************************************
  1229. ;This handler pops the window to front.
  1230. ;
  1231. ;rexxtofront(Rexxmsg, string)
  1232.  
  1233.     XDEF    rexxtofront
  1234. rexxtofront:
  1235.     movea.l    _Window,a0
  1236.     movea.l    _IntuitionBase,a6
  1237.     jmp    _LVOWindowToFront(a6)
  1238.  
  1239. ;******************************************************************
  1240. ;This handler pops the window to back.
  1241. ;
  1242. ;rexxtoback(Rexxmsg, string)
  1243.  
  1244.     XDEF    rexxtoback
  1245. rexxtoback:
  1246.     movea.l    _Window,a0
  1247.     movea.l    _IntuitionBase,a6
  1248.     jmp    _LVOWindowToBack(a6)
  1249.  
  1250. ;***************************************************************
  1251. ;This handler sets the exit flag.
  1252. ;
  1253. ;rexxexit(Rexxmsg, string)
  1254.  
  1255.     XDEF    rexxexit
  1256. rexxexit:
  1257.     clr.w    _KeepGoing
  1258.     suba.l    a0,a0        ;no returned Result string
  1259.     rts
  1260.  
  1261. ;**************************************************************
  1262. ;This handler returns the version of the program.
  1263. ;
  1264. ;rexxversion(Rexxmsg, string)
  1265.  
  1266.     XDEF    rexxversion
  1267. rexxversion:
  1268. ;---Setup the address of VERSION as the returned Argstring
  1269. ;   Note that this is our only example of returning a Result string
  1270.     lea    VERSION,a0
  1271.     move.l    a0,ResultStr
  1272.     rts
  1273.  
  1274. ;***********************************************************************
  1275. ;This handler sends the rest of the command asynchronously, allowing us to
  1276. ;run macros in parallel. Note that the App lib strips leading whitespace from
  1277. ;the Argstring, so we don't have to do that here.
  1278. ;
  1279. ;rexxspawn(Rexxmsg, string)
  1280.  
  1281.     XDEF    rexxspawn
  1282. rexxspawn:
  1283.     ;string in a0
  1284.     movea.l    _rexxBase,a6
  1285.     jmp    _LVOASyncRexxCmd(a6)
  1286.  
  1287. ;*************************************************************************
  1288. ; The error routine for Rexxmsgs that we sent out and were returned with an
  1289. ; error. The error message is in a0 and the error code is in d0. Let's just
  1290. ; print out the message in the title bar.
  1291.  
  1292. printRexxErr:
  1293.     movea.l    _IntuitionBase,a6
  1294.     movea.l    a0,a1
  1295.     movea.l    _Window,a0
  1296.     move.l    a2,-(sp)
  1297.     suba.l    a2,a2
  1298.     jsr    _LVOSetWindowTitles(a6)
  1299.     movea.l    (sp)+,a2
  1300.     rts
  1301.  
  1302. ;*************************************************************************
  1303. ; The Result routine for Rexxmsgs that we sent out and were returned success-
  1304. ; fully. The Result string is in a0 (or NULL if none) and the Result1 code is
  1305. ; in d0. Let's just print out the message in the title bar (if not 0) since
  1306. ; we really don't have any rexx handlers that expect returned strings.
  1307.  
  1308. doResult:
  1309.     move.l    a0,d1
  1310.     bne.s    printRexxErr
  1311.     rts
  1312.  
  1313.     ENDIF
  1314.  
  1315. ;    SECTION    FDdata,DATA    ;some asms may need this uncommented
  1316.  
  1317. _Window        dc.l    0
  1318. _MinX        dc.w    0
  1319. _MinY        dc.w    0
  1320. _MaxX        dc.w    0
  1321. _MaxY        dc.w    0
  1322. _KeepGoing    dc.w    1    ;when this is a 0, we exit
  1323.  
  1324.     XDEF    _IntuitionBase,_GfxBase
  1325. _IntuitionBase    dc.l    0
  1326. _GfxBase    dc.l    0
  1327.  
  1328. ; This is the Window structure declaration. Nothing fancy is going on here,
  1329. ;but note the Flags and IDCMPFlags members of the structure define which
  1330. ;messages will be sent by Intuition.  I haven't used them all and if you want
  1331. ;to change the settings you should probably do it here instead of using
  1332. ;ModifyIDCMP later.
  1333.  
  1334.     XDEF    _NewWindow
  1335. _NewWindow:
  1336.     dc.w    10,10,600,180
  1337.     dc.b    0,1
  1338. ;CLOSEWINDOW | MOUSEMOVE | MOUSEBUTTONS | MENUPICK | NEWSIZE | INACTIVEWINDOW
  1339.     dc.l    $8031a
  1340. ;WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING | REPORTMOUSE
  1341.     dc.l    $120f
  1342.     dc.l    0,0
  1343.     dc.l    WindowTitle
  1344.     dc.l    0,0
  1345.     dc.w    100,35,-1,-1
  1346.     dc.w    1
  1347.  
  1348. ;****************************** MENUS ********************************
  1349.  
  1350. _menu1    dc.l    _menu2
  1351.     dc.w    10,0,50,10,1
  1352.     dc.l    Color
  1353.     dc.l    _coloritem
  1354.     dc.w    0,0,0,0
  1355. _menu2    dc.l    0
  1356.     dc.w    65,0,85,10,1
  1357.     dc.l    DrawMode
  1358.     dc.l    EraseItem
  1359.     dc.w    0,0,0,0
  1360.  
  1361. ;================= Menu Items For DrawMode Menu =================
  1362.  
  1363. EraseItem:
  1364.     dc.l    HollowItem
  1365.     dc.w    0,0,112,10
  1366.     dc.w    146        ;ITEMTEXT|ITEMENABLED|HIGHBOX
  1367.     dc.l    0
  1368.     dc.l    EraseText
  1369.     dc.l    0
  1370.     dc.b    0,0
  1371.     dc.l    0
  1372.     dc.w    0
  1373. HollowItem:
  1374.     dc.l    FilledItem
  1375.     dc.w    0,10,112,10
  1376.     dc.w    146
  1377.     dc.l    0
  1378.     dc.l    HollowBoxText
  1379.     dc.l    0
  1380.     dc.b    0,0
  1381.     dc.l    0
  1382.     dc.w    0
  1383. FilledItem:
  1384.     dc.l    PenItem
  1385.     dc.w    0,20,112,10
  1386.     dc.w    146
  1387.     dc.l    0
  1388.     dc.l    FilledBoxText
  1389.     dc.l    0
  1390.     dc.b    0,0
  1391.     dc.l    0
  1392.     dc.w    0
  1393. PenItem:
  1394.     dc.l    0
  1395.     dc.w    0,30,112,10
  1396.     dc.w    146
  1397.     dc.l    0
  1398.     dc.l    PenDrawText
  1399.     dc.l    0
  1400.     dc.b    0,0
  1401.     dc.l    0
  1402.     dc.w    0
  1403.  
  1404. EraseText:
  1405.     dc.b    0,1,1,0
  1406.     dc.w    0,1
  1407.     dc.l    0,EraseAll,0
  1408. HollowBoxText:
  1409.     dc.b    0,1,1,0
  1410.     dc.w    0,1
  1411.     dc.l    0,HollowBox,0
  1412. FilledBoxText:
  1413.     dc.b    0,1,1,0
  1414.     dc.w    0,1
  1415.     dc.l    0,FilledBox,0
  1416. PenDrawText:
  1417.     dc.b    0,1,1,0
  1418.     dc.w    0,1
  1419.     dc.l    0,PenDraw,0
  1420.  
  1421. ;******************************************************
  1422. ;               Color Select Menu                     *
  1423. ;                                                     *
  1424. ;    This is where the menu for color selection is    *
  1425. ; defined.  It should be flexible enough to allow for *
  1426. ; increased palette sizes, but this version is only   *
  1427. ; for the 4-color mode of the WorkBench screen.       *
  1428.  
  1429. _coloritem    ds.b    136
  1430. _colorimage    ds.b    80
  1431. ;array of palette sizes to correspond with depth of window in bit-planes
  1432. _palette    dc.b    0,2,4,8,16,32
  1433.  
  1434.  
  1435.     IFNE TALKTOREXX
  1436.  
  1437. ;These first 6 variables are only needed by this program and are not required
  1438. ;by the Rexx App lib. (ie they exist merely for the use of FreeDraw's ARexx
  1439. ;handlers)
  1440.  
  1441. ;the base of rexxapp.library
  1442. _rexxBase    dc.l    0
  1443.  
  1444. ;A buffer into which we place the user's command string for ARexx
  1445. ArexxCmdStr    ds.b 256
  1446.  
  1447. ;The address of the Result string
  1448. ResultStr    dc.l 0
  1449.  
  1450. ;What color is *rexx* drawing in?
  1451. _currrexxcolor    dc.l    1
  1452.  
  1453. ;what args did we see to this function? MAX 4 LONGS
  1454. Points        ds.l    4
  1455.  
  1456. ;was argument parsing successful? A 0 if so, a 1 for error
  1457. error        dc.l    0
  1458.  
  1459. ;******************************** RexxData *********************************
  1460. ; This part is the mandatory data section needed by the Rexx App lib. Whenever
  1461. ; you call a function in this library, register a5 must be setup with the base
  1462. ; of this data block (ie  lea  _rexxPort,a5). The data must be in this order
  1463. ; up to the end of the association list! Note that the association list can
  1464. ; be any length as long as it ends with a 0 LONG.
  1465. ;
  1466. ; For another program, you will need to alter the command association list
  1467. ; (and the strings for it). Also, change RexxMacroExt and RXname. If you call
  1468. ; your Dispatch, Error, and Result vector routines the same as I did, then you
  1469. ; won't need to alter the variables dispatchFunc, ErrorVector and ResultVector.
  1470.  
  1471. ;These are the offsets from the base of the data (ie from _rexxPort)
  1472. mr_RexxPort    equ    0  ;The imbedded RexxPort (to be setup by SetRexxPort)
  1473. mr_RxName    equ    10 ;DO NOT ALTER
  1474. mr_RxSig    equ    15 ;DO NOT ALTER
  1475. mr_RxTask    equ    16 ;DO NOT ALTER
  1476. mr_Flags    equ    32 ;DO NOT ALTER the highest 4 bits (4-7)
  1477. mr_MsgsOut    equ    33 ;how many RexxMsgs this app created and has not received back (DO NOT ALTER)
  1478. mr_Exten    equ    34 ;the extension for invoking Rexx scripts
  1479. mr_Func        equ    38 ;a routine to handle received RexxMsg's from some other application
  1480. mr_RxsLib    equ    42 ;the lib base of ARexx server library (DO NOT ALTER)
  1481. mr_ErrorV    equ    46 ;a routine for error return of a RexxMsg the app created and sent
  1482. mr_Return    equ    50 ;a routine for successful return of a RexxMsg the app created and sent
  1483. mr_RexxMask    equ    54 ;signal mask of the Rexx port's mp_SigBit
  1484. mr_UserData    equ    58 ;for application's use
  1485. mr_AsscList    equ    62 ;the imbedded association list
  1486.  
  1487.     CNOP    0,2
  1488.     XDEF    _rexxPort
  1489. ;Our Rexx port
  1490. _rexxPort:
  1491.     dc.l 0,0
  1492.     dc.b 4,0
  1493.     dc.l RXname
  1494.     dc.b 0
  1495.     dc.b -1    ;This is negative (bit 7 set) whenever our port isn't set up
  1496.     dc.l 0
  1497. rxmsg    dc.l rxmsg+4
  1498.     dc.l 0
  1499.     dc.l rxmsg
  1500.     dc.b 0    ;DO NOT ALTER THESE LAST 2 BYTES OF THE PORT
  1501.     dc.b 0
  1502.  
  1503. ;extension is the address of a null-term file extension string for ARexx macros
  1504. ;invoked by this program.  If not 0, any `primitive' not in the association
  1505. ;list will be sent out to ARexx for interpretation, thus allowing macro
  1506. ;programs to work just like primitives. If you do not want this behavior,
  1507. ;supply a 0 here, and those commands not specified in your association list
  1508. ;will be sent back to ARexx with an error value of RXERRORNOCMD. It should be
  1509. ;noted that extension should point to a nulled string if no particular
  1510. ;extention is desired. Here, I've set it to point to 'fd',0
  1511. extension    dc.l    RexxMacroExt
  1512.  
  1513. ;dispatchFunc is the address of the app's Dispatch function.  This function
  1514. ;will *only* be called by the library when the application calls ReceiveRexx().
  1515. ;Anytime a command match is found in the association list, this function will
  1516. ;be called with 3 arguments--- the Rexx message that was received (a2), a
  1517. ;pointer to the association jmp vector in a3 (ie the handler to be executed),
  1518. ;and the Argstring in a4 (ARG0) stripped of the command.  This function should
  1519. ;return a 1 if the message is to be replied to by the lib or a 0 if not. If
  1520. ;not, the application itself is responsible for replying the message later via
  1521. ;Exec's ReplyMsg(). Otherwise, the library ALWAYS takes care of properly
  1522. ;replying all messages. (Freedraw lets the lib take care of all replies. Unless
  1523. ;you need to hold onto a Rexxmsg and consequently "put the Rexx script to
  1524. ;sleep" until you reply it later, you'll let the lib take care of replies.
  1525. ;Also, the app should setup the return values with SetupResults().
  1526. dispatchFunc    dc.l    myDispatch
  1527.  
  1528. ;Address of rexxsyslib.library (DO NOT ALTER)
  1529. _RexxSysBase    dc.l    0
  1530.  
  1531. ;This routine is called when each msg that the application created and sent out
  1532. ;is returned with an error. It is passed an appropriate error message in a0,
  1533. ;and the error code in d0. Typically, this routine needs to do nothing more
  1534. ;than print the message for the user. You must supply at least a dummy routine.
  1535. ErrorVector    dc.l    printRexxErr
  1536.  
  1537. ;This routine is called when each msg that the application created and sent out
  1538. ;is returned successfully. It is passed any returned Result string in a0,
  1539. ;and the Result1 code in d0. This routine may do various things with the
  1540. ;Result1 string or code depending upon which function initially sent the
  1541. ;message out. You must supply at least a dummy routine.
  1542. ResultVector    dc.l    doResult
  1543.  
  1544. ;The mask of our rexxPort's SigBit (used by our app to wait for Arexx msgs)
  1545. RexxMask    dc.l    0
  1546.  
  1547. ;The application can do anything with this
  1548.         dc.l    0
  1549.  
  1550. ;Here is our command association list. This is simply a table of LONGS. Each
  1551. ;two LONGS is an entry for a REXX command. For example, the first 2 LONGS in
  1552. ;the table are for the first REXX command. Remember that REXX commands are
  1553. ;null-terminated strings. The first LONG is the address of the command string.
  1554. ;For example, in our command association list for FreeDraw, the first long
  1555. ;points to the string "color". The next LONG is the address of the function
  1556. ;that implements the REXX command. For example, the next LONG points to the
  1557. ;function, rexxcolor. Now whenever we receive a REXX msg with its command
  1558. ;string being "color", we jsr to the function, rexxcolor. This is the way the
  1559. ;Rexx app lib determines whether a received Rexxmsg holds a legitimate command
  1560. ;for our application. For another program, you simply make a new association
  1561. ;list (and write the respective handlers). This list MUST end with a 0 LONG.
  1562. ;Please note that your command strings must also be lower case letters (and
  1563. ;only letters with no imbedded spaces). You will probably also write a new
  1564. ;dispatch function (modeled after myDispatch), since you may need to do other
  1565. ;things besides change window colors, check for an open window, etc like what
  1566. ;FreeDraw needs to do with its ARexx implementation.
  1567.  
  1568.     XDEF    myAsscList
  1569. myAsscList:
  1570. ;"color"
  1571.     dc.l    color
  1572.     dc.l    rexxcolor
  1573. ;"box"
  1574.     dc.l    box
  1575.     dc.l    rexxbox
  1576. ;"fbox"
  1577.     dc.l    fbox
  1578.     dc.l    rexxfbox
  1579. ;"line"
  1580.     dc.l    line
  1581.     dc.l    rexxline
  1582. ;"tofront"
  1583.     dc.l    tofront
  1584.     dc.l    rexxtofront
  1585. ;"toback"
  1586.     dc.l    toback
  1587.     dc.l    rexxtoback
  1588. ;"exit"
  1589.     dc.l    exit
  1590.     dc.l    rexxexit
  1591. ;"version"
  1592.     dc.l    version
  1593.     dc.l    rexxversion
  1594. ;"spawn"
  1595.     dc.l    spawn
  1596.     dc.l    rexxspawn
  1597. ;END OF LIST
  1598.     dc.l    0
  1599.  
  1600. ;The following data can be placed anywhere, and will change for another application
  1601.  
  1602. ;These are the command strings that we will accept ARexx msgs for
  1603. color    dc.b    'color',0
  1604. box    dc.b    'box',0
  1605. fbox    dc.b    'fbox',0
  1606. line    dc.b    'line',0
  1607. version    dc.b    'version',0
  1608. spawn    dc.b    'spawn',0
  1609. exit    dc.b    'exit',0
  1610. tofront    dc.b    'tofront',0
  1611. toback    dc.b    'toback',0
  1612.  
  1613. ;This is the name of our Rexx port, and is used with the ADDRESS command
  1614. ;within a Rexx macro to find this app's rexx port. This must be unique for
  1615. ;every Rexx application. Note that if the user runs 2 copies of FreeDraw,
  1616. ;the second port's name will be "freedraw2". Also, note that we have an extra
  1617. ;null byte on the end of our name. THIS EXTRA BYTE IS REQUIRED!
  1618. RXname        dc.b    'freedraw',0,0
  1619.  
  1620. RexxMacroExt    dc.b    'fd',0        ;the macro extention desired for ARexx
  1621.  
  1622. RexxName    dc.b    'rexxapp.library',0
  1623.  
  1624.     ENDIF
  1625.  
  1626. ;********************** END OF MANDATORY REXX DATA **********************
  1627.  
  1628. GfxName        dc.b    'graphics.library',0
  1629. IntuiName    dc.b    'intuition.library',0
  1630. VERSION        dc.b    'Freedraw 0.01 by Richard M. Ross',0
  1631. WindowTitle    dc.b    'AMIGA FreeDraw 0.01',0
  1632. Color        dc.b    'Color',0
  1633. DrawMode    dc.b    'DrawMode',0
  1634. EraseAll    dc.b    'Erase All',0
  1635. HollowBox    dc.b    'Hollow Box',0
  1636. FilledBox    dc.b    'Filled Box',0
  1637. PenDraw        dc.b    'Pen Draw',0
  1638.  
  1639.     END
  1640.