home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Original C Code written by Stefan Stuntz
- **
- ** Translation into E by Klaus Becker
- **
- ** All comments are from the C-Source
- */
-
- /* Remember the following note from Wouter:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- "[note: v3.1 (v40) of the amiga operating system is known to contain
- a bug in the IEEE code. Be sure to run a SetPatch that fixes this]"
- */
-
- /*
-
- This little demo show how to write classes which need a long
- time to render their contents. In this case, we take a little
- fractal algorithm as example. The actual calculations are
- done in a separate task, the display is updated from time
- to time.
-
- */
-
- OPT PREPROCESS
-
- MODULE 'graphics/gfx'
- MODULE 'muimaster','libraries/mui','libraries/muip',
- 'mui/muicustomclass','amigalib/boopsi',
- 'intuition/classes','intuition/classusr',
- 'intuition/screens','intuition/intuition',
- 'dos/dostags','dos/dosextens','exec/memory','exec/semaphores',
- 'graphics/rastport','exec/ports',
- 'utility/tagitem','exec/tasks'
-
- /* Pixel dimensions of our fractal */
-
- CONST FRACTALWIDTH = 300
- CONST FRACTALHEIGHT = 300
-
- /* Fractal Description */
-
- OBJECT fractaldesc
- left:LONG
- right:LONG
- top:LONG
- bottom:LONG
- ENDOBJECT
-
-
- #define MaxIterations 60
-
- /* Attributes and methods for the custom class */
-
- #define MUISERIALNR_STUNTZI 1
- #define TAGBASE_STUNTZI (TAG_USER OR (Shl(MUISERIALNR_STUNTZI,16)))
-
- #define MUIM_Class4_Update (TAGBASE_STUNTZI OR 1)
-
- OBJECT muip_class4_update
- id,percent
- ENDOBJECT
-
- #define MUIM_Class4_Calc (TAGBASE_STUNTZI OR 2)
-
- OBJECT muip_class4_calc
- id
- fd:PTR TO fractaldesc
- ENDOBJECT
-
- #define MUIA_Class4_Percent (TAGBASE_STUNTZI OR 3)
-
- #define STC_START 0
- #define STC_STOP 1
-
- /* Instance Data for the fractal class */
-
- OBJECT data
- sema:ss /* data item protection */
- app /* pointer to application */
- self /* pointer to ourselves */
- subtask:PTR TO subtask /* our sub task */
- rp:rastport /* rastport FOR the sub task */
- udlines:PTR TO CHAR /* line update flags ARRAY */
- ENDOBJECT
-
- /**************************************************************/
- /* Functions for easy and secure spawning/killing of subtasks */
- /**************************************************************/
-
- OBJECT subtaskmsg
- stm_Message:mn
- stm_Command:INT
- stm_Parameter:LONG
- stm_Result:LONG
- ENDOBJECT
-
- OBJECT subtask
- st_Task:PTR TO tc /* sub task pointer */
- st_Port:PTR TO mp /* allocated by sub task */
- st_Reply:PTR TO mp /* allocated by main task */
- st_Data:LONG /* more initial data to pass to the sub task */
- st_Message:subtaskmsg /* Message buffer */
- ENDOBJECT
-
- #define STC_STARTUP -2
- #define STC_SHUTDOWN -1
-
- PROC sendsubtaskmsg(st:PTR TO subtask,command,params)
- st.st_Message.stm_Message.replyport:= st.st_Reply
- st.st_Message.stm_Message.length := SIZEOF subtaskmsg
- st.st_Message.stm_Command := command
- st.st_Message.stm_Parameter := params
- st.st_Message.stm_Result := 0
-
- PutMsg(IF command=STC_STARTUP THEN st.st_Task::process.msgport ELSE st.st_Port,st.st_Message)
- WaitPort(st.st_Reply)
- GetMsg(st.st_Reply)
- ENDPROC (st.st_Message.stm_Result)
-
- PROC spawnsubtask(name,func,data:PTR TO data)
- DEF st=NIL:PTR TO subtask
-
- IF (st:=AllocVec(SIZEOF subtask,MEMF_PUBLIC OR MEMF_CLEAR))
- st.st_Reply:=CreateMsgPort()
- IF (st.st_Reply)
- st.st_Data:=data
- st.st_Task:= CreateNewProc([NP_ENTRY,func, -> = {renderfunc}
- NP_NAME,name,
- TAG_DONE])
- IF (st.st_Task)
- IF (sendsubtaskmsg(st,STC_STARTUP,st)) THEN RETURN (st)
- ENDIF
- DeleteMsgPort(st.st_Reply)
- ENDIF
- FreeVec(st)
- ENDIF
- ENDPROC
-
- PROC killsubtask(st:PTR TO subtask)
- sendsubtaskmsg(st,STC_SHUTDOWN,st)
- DeleteMsgPort(st.st_Reply)
- FreeVec(st)
- ENDPROC
-
- PROC exitsubtask(st:PTR TO subtask,stm:PTR TO subtaskmsg)
- /*
- ** We reply after a Forbid() to make sure we're really gone
- ** when the main task continues.
- */
- IF (st.st_Port) THEN DeleteMsgPort(st.st_Port)
- Forbid()
- stm.stm_Result:= FALSE
- ReplyMsg(stm)
- ENDPROC
-
- PROC initsubtask()
- DEF me=NIL:PTR TO tc,
- st=NIL:PTR TO subtask,
- stm=NIL:PTR TO subtaskmsg
-
- me:= FindTask(NIL)
-
- /*
- ** Wait for our startup message from the SpawnSubTask() function.
- */
-
- WaitPort(me::process.msgport)
- stm:= GetMsg(me::process.msgport)
- st:= stm.stm_Parameter
- st.st_Port:=CreateMsgPort()
- IF (st.st_Port)
- /*
- ** Reply startup message, everything ok.
- ** Note that if the initialization fails, the code falls
- ** through and replies the startup message with a stm_Result
- ** of 0 after a Forbid(). This tells SpawnSubTask() that the
- ** sub task failed to run.
- */
- stm.stm_Result:= TRUE
- ReplyMsg(stm)
- RETURN (st)
- ELSE
- exitsubtask(st,stm)
- RETURN (NIL)
- ENDIF
- ENDPROC
-
- /*******************************************************/
- /* Subtask which does all the time-consuming rendering */
- /*******************************************************/
-
- PROC renderfunc()
- DEF st=NIL:PTR TO subtask
- DEF data=NIL:PTR TO data
- DEF running=TRUE,worktodo=FALSE,x,y
- DEF stm=NIL:PTR TO subtaskmsg
- DEF left,top,right,bottom
- DEF zr,zi,cr,ci,rr,ii
- DEF counter
- DEF command,i
- DEF float[20]:STRING
-
- geta4() -> !!!
-
- IF (st:= initsubtask())
- data:= st.st_Data
- LOOP
- /*
- ** after the sub task is up and running, we go into
- ** a loop and process the messages from the main task.
- */
- WHILE (stm:= GetMsg(st.st_Port))
- command:=stm.stm_Command
- SELECT command
- CASE STC_SHUTDOWN
- /*
- ** This is the shutdown message from KillSubTask().
- */
- running:= FALSE
- CASE STC_START
- /*
- ** we received a start message with a fractal description.
- ** clear the rastport and the line update array and start
- ** rendering.
- */
- SetRast(data.rp,1)
- FOR i:=0 TO FRACTALHEIGHT-1 DO data.udlines[i]:=0
- left := stm.stm_Parameter::fractaldesc.left
- top := stm.stm_Parameter::fractaldesc.top
- right := stm.stm_Parameter::fractaldesc.right
- bottom := stm.stm_Parameter::fractaldesc.bottom
- y:=0
- worktodo:= TRUE
- CASE STC_STOP
- /* this message is not used in this example */
- worktodo:= FALSE
- ENDSELECT
- /*
- ** If we received a shutdown message, we do not reply it
- ** immediately. First, we need to free our resources.
- */
- IF (running=FALSE) THEN BRA exit
- ReplyMsg(stm.stm_Message)
- ENDWHILE
- IF (running=FALSE) THEN BRA exit
- IF (worktodo)
- /* if there is work to do, i.e. if the fractal is not
- ** finished yet, we calculate the next line and draw
- ** it to the offscreen rastport.
- */
- FOR x:=0 TO (FRACTALWIDTH-1)
- zr:= 0.0
- zi:= 0.0
- cr:= !left+(!x*(!right - left)/FRACTALWIDTH )
- ci:= !top+ (!y*(!bottom - top)/FRACTALHEIGHT )
- rr:= !zr*zr
- ii:= !zi*zi
- FOR counter:=0 TO MaxIterations-1
- zi:=!ci + (!zr*zi*2.0)
- zr:=!cr + rr - ii
- rr:=!zr*zr
- ii:=!zi*zi
- IF (!rr+ii>4.0)
- /*
- ** set the pixel in the offscreen rastport.
- ** this demo is kind of dirty, as it does no
- ** nice color allocation and palette stuff.
- ** dont be so dirty in your own programs! :-)
- */
- SetAPen(data.rp,1+counter)
- WritePixel(data.rp,x,y)
- BRA next
- ENDIF
- INC counter
- EXIT (counter=MaxIterations)
- ENDFOR
- next:
- ENDFOR
- /*
- ** after the line is finished, we set the corresponding
- ** flag in the line update array to FALSE. This shows the
- ** main task that this line needs to be redrawn the next
- ** time it gets the chance.
- */
-
- ObtainSemaphore(data.sema)
- data.udlines[y]:= FALSE
- IF (data.app)
- /*
- ** if our class is attached to an application, we send ourselves
- ** an update method. Note that because we are in a separate task,
- ** we cannot send this method directly but instead have to use
- ** the MUIM_Application_PushMethod call. This is the only method
- ** that you may send to a MUI object from a separate task. What it
- ** does is to copy the method to a private buffer and wait until
- ** the next time the main task calls the input method. Then, our
- ** update method will be executed under the main tasks context.
- **
- ** If our class is not attached to an application
- ** (i.e. we are outside of MUIM_Setup/MUIM_Cleanup), there is
- ** nobody who could render something anyway so we just skip
- ** the update method and continue to render in our private
- ** buffer.
- */
- -> Gauge
- doMethodA(data.app,[ MUIM_Application_PushMethod,
- data.self,2,MUIM_Class4_Update,(100*(y+1)/FRACTALHEIGHT)])
- ENDIF
- ReleaseSemaphore(data.sema)
- y++
- IF (y=FRACTALHEIGHT)
- /* check if we are finished to draw our fractal */
- worktodo:= FALSE
- ENDIF
- /* Since we are very busy working, we do not Wait() for signals. */
- ELSE
- /* We have nothing to do, just sit quietly and wait for something to happen */
- WaitPort(st.st_Port)
- ENDIF
- ENDLOOP
- exit:
- exitsubtask(st,stm)
- ENDIF
- ENDPROC
-
- PROC mNew(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO msg)
- DEF data=NIL:PTR TO data
-
- IF (obj:=doSuperMethodA(cl,obj,msg))=NIL THEN RETURN 0
-
- data:= INST_DATA(cl,obj)
-
- /* store a pointer to ourselves so the subtask knows about us */
- data.self:= obj
-
- /*
- ** initialization and allocation of data structures.
- ** note that if something fails here, we *must* do a
- ** CoerceMethod(cl,obj,OM_DISPOSE) to give ourselves
- ** (and MUI!) a chance to clean up.
- */
-
- InitSemaphore(data.sema)
- InitRastPort(data.rp)
-
- data.udlines:= AllocVec(FRACTALHEIGHT,MEMF_CLEAR)
- IF (data.udlines)
- data.rp.bitmap:= AllocBitMap(FRACTALWIDTH,FRACTALHEIGHT,8,BMF_CLEAR,NIL)
- IF (data.rp.bitmap)
- SetRast(data.rp,1)
-
- /* the following call starts the sub task */
-
- data.subtask:= spawnsubtask('Class4-Render-Task',{renderfunc},data)
- IF (data.subtask)
- SetTaskPri(data.subtask.st_Task,-1)
- RETURN obj
- ENDIF
- ENDIF
- ENDIF
- coerceMethodA(cl,obj,OM_DISPOSE)
- ENDPROC
-
- PROC mDispose(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO msg)
- DEF data:PTR TO data
- data:=INST_DATA(cl,obj)
- IF (data.subtask) THEN killsubtask(data.subtask)
- IF (data.rp.bitmap) THEN FreeBitMap(data.rp.bitmap)
- IF (data.udlines) THEN FreeVec(data.udlines)
- ENDPROC doSuperMethodA(cl,obj,msg)
-
- /*
- ** AskMinMax method will be called before the window is opened
- ** and before layout takes place. We need to tell MUI the
- ** minimum, maximum and default size of our object.
- */
-
- PROC mAskMinMax(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO muip_askminmax)
- /*
- ** let our superclass first fill in what it thinks about sizes.
- ** this will e.g. add the size of frame and inner spacing.
- */
-
- doSuperMethodA(cl,obj,msg)
-
- /*
- ** now add the values specific to our object. note that we
- ** indeed need to *add* these values, not just set them!
- */
-
- msg.minmaxinfo.minwidth:=msg.minmaxinfo.minwidth+10
- msg.minmaxinfo.defwidth:=msg.minmaxinfo.defwidth+100
- msg.minmaxinfo.maxwidth:=msg.minmaxinfo.maxwidth+FRACTALWIDTH
-
- msg.minmaxinfo.minheight:=msg.minmaxinfo.minheight+10
- msg.minmaxinfo.defheight:=msg.minmaxinfo.defheight+100
- msg.minmaxinfo.maxheight:=msg.minmaxinfo.maxheight+FRACTALHEIGHT
- ENDPROC
-
- /*
- ** Draw method is called whenever MUI feels we should render
- ** our object. This usually happens after layout is finished
- ** or when we need to refresh in a simplerefresh window.
- ** Note: You may only render within the rectangle
- ** _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj).
- */
-
- PROC mDraw(cl:PTR TO iclass,obj:PTR TO object,msg:PTR TO muip_draw)
- DEF data:PTR TO data
- DEF l
-
- data:=INST_DATA(cl,obj)
-
- /*
- ** let our superclass draw itself first, area class would
- ** e.g. draw the frame and clear the whole region. What
- ** it does exactly depends on msg.flags.
- **
- ** Note: You *must* call the super method prior to do
- ** anything else, otherwise msg.flags will not be set
- ** properly !!!
- */
-
- doSuperMethodA(cl,obj,msg)
-
- IF (msg.flags AND MADF_DRAWUPDATE)
- /*
- ** This flag indicates that we were called from our
- ** update method. We needn't render the complete
- ** image, we only need to update the lines that
- ** were changed. So what we do is to browse through
- ** the line flag array and blit each changed line
- ** from the offscreen buffer into the display.
- ** We could do a better and more efficient job
- ** by collecting subsequent changed lines to blit
- ** larger rectangles, but hey... this is only a demo! :-)
- */
-
- /*
- ** note the usage of semaphores to protect access
- ** to variables use by both tasks.
- */
-
- ObtainSemaphore(data.sema)
- FOR l:=0 TO _mheight(obj)-1
- IF (data.udlines[l])=NIL
- /*
- ** once we copied the line, we set the corresponding line flag
- ** to indicate that this line is uptodate and does not need
- ** to be redrawn the next time. When our sub task gets the message
- ** to calculate a new fractal, it will reset the flag to FALSE again.
- */
-
- BltBitMapRastPort(data.rp.bitmap,0,l,_rp(obj),_mleft(obj),_mtop(obj)+l,_mwidth(obj),1,$c0)
- data.udlines[l]:= TRUE
- ENDIF
- ENDFOR
- ReleaseSemaphore(data.sema)
- ELSEIF (msg.flags AND MADF_DRAWOBJECT)
- /*
- ** we were called directly from MUI because the window needs refresh.
- ** no need to care about our line array here, we just copy the complete
- ** offscreen buffer to our display.
- */
- ObtainSemaphore(data.sema)
- BltBitMapRastPort(data.rp.bitmap,0,0,_rp(obj),_mleft(obj),_mtop(obj),_mwidth(obj),_mheight(obj),$c0)
- ReleaseSemaphore(data.sema)
- ENDIF
- ENDPROC
-
- PROC mSetup(cl:PTR TO iclass,obj,msg:PTR TO muip_handleinput)
- DEF data:PTR TO data
- DEF app
- data:=INST_DATA(cl,obj)
- IF (doSuperMethodA(cl,obj,msg))=NIL THEN RETURN FALSE
-
- /*
- ** set a pointer to our application in our instance data.
- ** this indicates the sub task that we should be notified
- ** when a new line is calculated.
- */
-
- ObtainSemaphore(data.sema)
- get(obj,MUIA_ApplicationObject,{app})
- data.app:=app
- ReleaseSemaphore(data.sema)
- ENDPROC TRUE
-
- PROC mCleanup(cl:PTR TO iclass,obj,msg:PTR TO muip_handleinput)
- DEF data:PTR TO data
- data:=INST_DATA(cl,obj)
- ObtainSemaphore(data.sema)
- data.app:=NIL
- ReleaseSemaphore(data.sema)
- ENDPROC doSuperMethodA(cl,obj,msg)
-
- /*
- ** a simple method that sends a START msg with
- ** fractal description packet to the sub task.
- */
-
- PROC mCalc(cl:PTR TO iclass,obj,msg:PTR TO muip_class4_calc)
- DEF data:PTR TO data
- data:=INST_DATA(cl,obj)
- sendsubtaskmsg(data.subtask,STC_START,msg.fd)
- ENDPROC
-
- /*
- ** thats the method that is called through MUIM_Application_PushMethod
- ** from the subtask.
- */
-
- PROC mUpdate(cl:PTR TO iclass,obj,msg:PTR TO muip_class4_update)
-
- /* Tell MUI to redraw our object. Set the update flag
- ** so we know that only the changed lines are subject
- ** to render.
- */
-
- Mui_Redraw(obj,MADF_DRAWUPDATE)
-
- /*
- ** Also the the percentage attribute. The class itself doesnt
- ** have any use for this, but if we set it, its possible
- ** for other objects (e.g. a gauge) to receive notifications
- */
-
- set(obj,MUIA_Class4_Percent,msg.percent)
-
- ENDPROC
-
- /*
- ** Here comes the dispatcher for our custom class.
- ** Unknown/unused methods are passed to the superclass immediately.
- */
-
- PROC mydispatcher(cl:PTR TO iclass,obj,msg:PTR TO msg)
- DEF methodid
- methodid:=msg.methodid
-
- SELECT methodid
- CASE OM_NEW ; RETURN mNew (cl,obj,msg)
- CASE OM_DISPOSE ; RETURN mDispose (cl,obj,msg)
- CASE MUIM_AskMinMax ; RETURN mAskMinMax(cl,obj,msg)
- CASE MUIM_Draw ; RETURN mDraw (cl,obj,msg)
- CASE MUIM_Setup ; RETURN mSetup (cl,obj,msg)
- CASE MUIM_Cleanup ; RETURN mCleanup (cl,obj,msg)
- CASE MUIM_Class4_Update ; RETURN mUpdate (cl,obj,msg)
- CASE MUIM_Class4_Calc ; RETURN mCalc (cl,obj,msg)
- ENDSELECT
-
- ENDPROC doSuperMethodA(cl,obj,msg)
-
- /****************************************************************************/
- /* Misc Help Functions */
- /****************************************************************************/
-
- PROC xget(obj,attribute)
- DEF x
- get(obj,attribute,{x})
- ENDPROC x
-
- PROC getstr(obj) IS xget(obj,MUIA_String_Contents)
-
- /***************************************************************************/
- /* Thats all there is about it. Now lets see how things are used... */
- /***************************************************************************/
-
- PROC main() HANDLE
- DEF app,window,myObj
- DEF strleft,strtop,strright,strbottom,start,gauge
- DEF mcc=NIL:PTR TO mui_customclass
- DEF signals,running=TRUE,result
- DEF fd:fractaldesc
-
- storea4() -> save A4 !!!
-
- IF (KickVersion(39)=FALSE) THEN
- Raise('runs only with V39 and up')
- IF (muimasterbase:=OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN))=NIL THEN
- Raise('Failed to open muimasterlibrary')
-
- /* Create the new custom class with a call to eMui_CreateCustomClass(). */
- /* Caution: This function returns not a struct IClass, but a */
- /* struct MUI_CustomClass which contains a struct IClass to be */
- /* used with NewObjectA() calls. */
- /* Note well: MUI creates the dispatcher hook for you, you may */
- /* *not* use its h_Data field! If you need custom data, use the */
- /* cl_UserData of the IClass structure! */
-
- IF (mcc:= eMui_CreateCustomClass(NIL,MUIC_Area,NIL,SIZEOF data,{mydispatcher}))=NIL THEN
- Raise('Could not create custom class.')
-
- app:= ApplicationObject,
- MUIA_Application_Title , 'Class4',
- MUIA_Application_Version , '$VER: Class4 12.10 (21.11.95)',
- MUIA_Application_Copyright , 'c1993, Stefan Stuntz',
- MUIA_Application_Author , 'Stefan Stuntz & Klaus Becker',
- MUIA_Application_Description, 'Demonstrate rendering from sub tasks.',
- MUIA_Application_Base , 'Class4',
- SubWindow, window:= WindowObject,
- MUIA_Window_Title, 'Subtask rendering',
- MUIA_Window_ID , "CLS4",
- WindowContents, VGroup,
- Child, HGroup, GroupSpacing(8),
- Child, ColGroup(2),
- Child, Label2('_Left:' ), Child, strleft := Mui_MakeObjectA(MUIO_String,['_L',30]),
- Child, Label2('_Right:' ), Child, strright := Mui_MakeObjectA(MUIO_String,['_R',30]),
- End,
- Child, ColGroup(2),
- Child, Label2('_Top:' ), Child, strtop := Mui_MakeObjectA(MUIO_String,['_T',30]),
- Child, Label2('_Bottom:'), Child, strbottom := Mui_MakeObjectA(MUIO_String,['_B',30]),
- End,
- Child, Mui_MakeObjectA(MUIO_VBar,[2]),
- Child, start := VGroup,
- GroupSpacing(0),
- MUIA_Weight, 0,
- ButtonFrame,
- MUIA_InputMode , MUIV_InputMode_RelVerify,
- MUIA_Background, MUII_ButtonBack,
- Child, VSpace(0),
- Child, TextObject, MUIA_Text_Contents, '\ec Start ', End,
- Child, VSpace(0),
- End,
- End,
- Child, gauge := GaugeObject,
- GaugeFrame,
- MUIA_Gauge_Horiz, MUI_TRUE,
- MUIA_Gauge_Max, 100,
- MUIA_FixHeight, 8,
- End,
- Child, myObj := NewObjectA(mcc.mcc_class,NIL,
- [TextFrame,
- MUIA_Background, MUII_BACKGROUND,
- TAG_DONE]),
- End,
- End,
- End
-
- IF (app=NIL) THEN Raise('Failed to create Application.')
-
- set(window,MUIA_Window_DefaultObject, myObj)
-
- doMethodA(window,[MUIM_Notify,MUIA_Window_CloseRequest,MUI_TRUE,
- app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit])
-
- doMethodA(start,[MUIM_Notify,MUIA_Pressed,FALSE,
- app,2,MUIM_Application_ReturnID,1])
-
- doMethodA(myObj,[MUIM_Notify,MUIA_Class4_Percent,MUIV_EveryTime,
- gauge,3,MUIM_Set,MUIA_Gauge_Current,MUIV_TriggerValue])
-
- set(strleft ,MUIA_String_Contents,'-2.0')
- set(strright ,MUIA_String_Contents,'1.0')
- set(strtop ,MUIA_String_Contents,'1.5')
- set(strbottom,MUIA_String_Contents,'-1.5')
-
- /*
- ** Input loop...
- */
-
- set(window,MUIA_Window_Open,MUI_TRUE)
-
- WHILE running
- result:=doMethodA(app,[MUIM_Application_Input,{signals}])
- SELECT result
- CASE MUIV_Application_ReturnID_Quit
- running:= FALSE
- CASE 1 -> Start-Button
- fd.left := RealVal(getstr(strleft ))
- fd.right := RealVal(getstr(strright ))
- fd.top := RealVal(getstr(strtop ))
- fd.bottom := RealVal(getstr(strbottom))
- IF ( (fd.right > fd.left) AND (fd.top > fd.bottom) )
- doMethodA(myObj,[MUIM_Class4_Calc,fd])
- ELSE
- DisplayBeep(0)
- ENDIF
- ENDSELECT
-
- IF (running AND signals) THEN Wait(signals)
- ENDWHILE
- set(window,MUIA_Window_Open,FALSE)
-
- /*
- ** Shut down...
- */
- EXCEPT DO
- IF app THEN Mui_DisposeObject(app) /* dispose all objects. */
- IF mcc THEN Mui_DeleteCustomClass(mcc) /* delete the custom class. */
- IF muimasterbase THEN CloseLibrary(muimasterbase)
- IF exception THEN WriteF('\s\n',exception)
- ENDPROC
-
- -> geta4.e - store and get the global data pointer kept in register A4
- -> (C) Leon Woestenberg
-
- PROC storea4()
- LEA a4storage(PC),A0
- MOVE.L A4,(A0)
- ENDPROC
-
- PROC geta4()
- LEA a4storage(PC),A0
- MOVE.L (A0),A4
- ENDPROC
-
- a4storage:
- LONG NIL
-
-
-