2 ** $PROJECT: amigaguide.datatype
4 ** $VER: amigaguideclass.c 50.1 (13.06.03)
6 ** $AUTHOR: Stefan Ruppert <stefan@ruppert-it.de>
10 /* ------------------------------- includes ------------------------------- */
12 #include "classbase.h"
13 #include <libraries/diskfont.h>
15 /* ------------------------------ prototypes ------------------------------ */
17 ULONG
om_new(Class
*cl
, Object
*obj
, struct opSet
*msg
);
18 ULONG
om_dispose(Class
*cl
, Object
*obj
, Msg msg
);
19 ULONG
_om_set(Class
*cl
, Object
*obj
, struct opSet
*msg
);
20 ULONG
_om_update(Class
*cl
, Object
*obj
, struct opSet
*msg
);
22 ULONG
gm_render(Class
*cl
, Object
*obj
, struct gpRender
*msg
);
23 ULONG
gm_layout(Class
*cl
, Object
*obj
, struct gpLayout
*msg
);
24 ULONG
gm_input(Class
*cl
, Object
*obj
, struct gpInput
*msg
);
26 ULONG
dtm_asynclayout(Class
*cl
, Object
*obj
, struct gpLayout
*msg
);
27 ULONG
dtm_trigger(Class
*cl
, Object
*obj
, struct dtTrigger
*msg
);
30 static void ActivateAGObject(Class
*cl
, Object
*obj
, struct GadgetInfo
*ginfo
,
31 struct AmigaGuideObject
*agobj
);
33 /* ------------------------------ constants ------------------------------- */
35 static const struct NavigatorButton navbuttons
[] =
37 {"Contents", STM_CONTENTS
, NBF_DISABLED
},
38 {"Index", STM_INDEX
, NBF_DISABLED
},
39 {"Help", STM_HELP
, 0},
40 {"Retrace", STM_RETRACE
, NBF_DISABLED
},
41 {"< Browse", STM_BROWSE_PREV
, NBF_DISABLED
},
42 {"> Browse", STM_BROWSE_NEXT
, NBF_DISABLED
},
46 static const struct DTMethod triggermethods
[] =
48 {"Contents", "CONTENTS", STM_CONTENTS
},
49 {"Index", "INDEX", STM_INDEX
},
50 {"Help", "HELP", STM_HELP
},
51 {"Retrace", "RETRACE", STM_RETRACE
},
52 {"< Browse", "PREVIOUS", STM_BROWSE_PREV
},
53 {"> Browse", "NEXT", STM_BROWSE_NEXT
},
54 {"Next Field", NULL
, STM_NEXT_FIELD
},
55 {"Prev Field", NULL
, STM_PREV_FIELD
},
56 {"Activate Field", NULL
, STM_ACTIVATE_FIELD
},
60 static const struct TagItem navmap
[] =
62 {NA_Command
, AGNA_Command
},
66 static const ULONG supported_methods
[] =
78 /* -------------------------- user library init --------------------------- */
80 BOOL
UserClassBaseOpen(struct ClassBase
*cb
)
82 cb
->cb_Navigator
= MakeNavigatorClass(cb
);
83 cb
->cb_NodeClass
= MakeNodeClass(cb
);
84 if(cb
->cb_Navigator
!= NULL
&&
85 cb
->cb_NodeClass
!= NULL
)
93 int UserClassBaseClose(struct ClassBase
*cb
)
95 if(cb
->cb_Navigator
!= NULL
)
96 if(FreeNavigatorClass(cb
, cb
->cb_Navigator
))
97 cb
->cb_Navigator
= NULL
;
98 if(cb
->cb_NodeClass
!= NULL
)
99 if(FreeNodeClass(cb
, cb
->cb_NodeClass
))
100 cb
->cb_NodeClass
= NULL
;
106 #include <aros/symbolsets.h>
108 ADD2INITLIB(UserClassBaseOpen
, -1);
109 ADD2EXPUNGELIB(UserClassBaseClose
, -1);
110 #endif /* __AROS__ */
112 /* ------------------------------ functions ------------------------------- */
115 void MakeNavGadget(Class
*cl
, Object
*obj
, struct IBox
*domain
)
120 if(data
->ag_Gadget
!= NULL
)
124 NewObject(cb
->cb_Navigator
,NULL
,
125 ((CAST_GAD(obj
)->Flags
& GFLG_RELRIGHT
) == GFLG_RELRIGHT
) ? GA_RelRight
: GA_Left
, domain
->Left
,
126 ((CAST_GAD(obj
)->Flags
& GFLG_RELBOTTOM
) == GFLG_RELBOTTOM
) ? GA_RelBottom
: GA_Top
, domain
->Top
,
127 GA_RelWidth
, CAST_GAD(obj
)->Width
,
129 NA_Buttons
, (ULONG
) data
->ag_Buttons
,
130 NA_Target
, (ULONG
) obj
,
131 ICA_MAP
, (ULONG
) navmap
,
132 ICA_TARGET
, (ULONG
) obj
,
136 /****** amigaguide.datatype/OM_NEW *******************************************
139 OM_NEW -- create an amigaguide datatype object
145 struct TagItem *ops_AttrList;
146 struct GadgetInfo *ops_GInfo;
150 This method creates and initializes an amigaguide datatype object.
151 Currently only DTST_FILE source type is supported. All tags for
152 OM_SET method can be passed to the method. Additionally the following
153 tags are only used during initialization.
156 DTA_NodeName -- (STRPTR) name of the node to load initially.
158 DTA_ARexxPortName -- (STRPTR) base name for the ARexx port.
161 datatypes.library/NewDTObjectA(), OM_DISPOSE, OM_SET, --arexx--
163 ******************************************************************************
167 ULONG
om_new(Class
*cl
, Object
*obj
, struct opSet
*msg
)
172 STRPTR nodename
= "main";
176 struct TagItem
*tstate
= msg
->ops_AttrList
;
179 rv
= DoSuperMethodA(cl
, obj
, (Msg
)msg
);
185 data
= (struct AmigaGuideData
*)INST_DATA(cl
, obj
);
188 /* initialize the instance data */
189 data
->ag_Pool
= CreatePool(MEMF_CLEAR
| MEMF_ANY
, AG_PUDDLE_SIZE
, AG_PUDDLE_SIZE
);
192 NewList(&data
->ag_Files
);
193 NewList(&data
->ag_Visited
);
195 InitSemaphore(&data
->ag_ASyncLayout
);
197 data
->ag_ARexxPortName
= "AMIGAGUIDE";
199 /* lets use this object for the actual one until one node
200 could be loaded. Therefore we don't need to check some
201 conditions if a node is loaded or not. */
202 data
->ag_Actual
= obj
;
203 data
->ag_InitialNode
= CopyAGString(cl
, obj
, nodename
);
204 data
->ag_Creator
= FindTask(NULL
);
206 /* process attributes that only belongs to this class
207 and intialization phase. */
208 while((tag
= NextTagItem((const struct TagItem
**)&tstate
)) != NULL
)
213 nodename
= (STRPTR
) tag
->ti_Data
;
215 case DTA_ARexxPortName
:
216 data
->ag_ARexxPortName
= (STRPTR
) tag
->ti_Data
;
221 data
->ag_File
= AllocAGFile(cl
, obj
);
222 if(data
->ag_File
== NULL
)
226 /* set attributes provided by the user */
227 _om_set(cl
, obj
, msg
);
229 /* now get the source type only DTST_FILE is supported.
230 Then start scanning the AmigaGuide file */
232 DTA_SourceType
, (ULONG
) &sourcetype
,
233 DTA_Handle
, (ULONG
) &handle
,
242 data
->ag_File
->agf_Handle
= handle
;
243 data
->ag_File
->agf_Lock
= DupLockFromFH(handle
);
244 ScanFile(cl
, obj
, data
->ag_File
);
246 if(data
->ag_File
->agf_OnOpen
!= NULL
)
247 if(SendRexxCommand(cl
, obj
, data
->ag_File
->agf_OnOpen
, AGRX_RX
) != RC_OK
)
251 DB(("sourcetype unsupported : %ld\n",sourcetype
));
256 /* now create navigation bar */
257 if(rv
!= (ULONG
) NULL
)
261 if(GetDTDomain(cl
, obj
, &domain
))
263 data
->ag_Buttons
= AllocAGVec(cl
, obj
, sizeof(navbuttons
));
264 if(data
->ag_Buttons
!= NULL
)
266 memcpy(data
->ag_Buttons
, navbuttons
, sizeof(navbuttons
));
268 MakeNavGadget(cl
, obj
, &domain
);
272 /* create external process for this object */
273 if(CreateAGProcess(cl
, obj
) != data
->ag_Process
)
278 if (rv
== (ULONG
)NULL
)
279 CoerceMethod(cl
, obj
, OM_DISPOSE
);
285 /****** amigaguide.datatype/OM_DISPOSE ***************************************
288 OM_DISPOSE -- dispose an amigaguide datatype object
294 This method disposes an amigaguide datatype object. It deallocates
295 any resource obtained by the amigaguide object.
298 datatypes.library/DisposeDTObject(), OM_NEW
300 ******************************************************************************
304 ULONG
om_dispose(Class
*cl
,Object
*obj
,Msg msg
)
308 struct AmigaGuideObject
*ago
;
309 struct AmigaGuideFile
*agf
;
311 DeleteAGProcess(cl
, obj
);
313 /* close and unlock files, memory will be free's by DeletePool() */
314 while((agf
= (struct AmigaGuideFile
*) RemHead(&data
->ag_Files
)) != NULL
)
316 if(agf
->agf_Handle
!= NULL
)
317 if(agf
->agf_Flags
.CloseHandle
)
318 Close(agf
->agf_Handle
);
320 if(agf
->agf_Lock
!= NULL
)
321 UnLock(agf
->agf_Lock
);
324 while((ago
= (struct AmigaGuideObject
*) RemHead(&data
->ag_Visited
)) != NULL
)
326 FreeAGObject(cl
, obj
, ago
);
329 /* cleanup navigator gadget */
330 if(data
->ag_Gadget
!= NULL
)
331 DisposeObject(data
->ag_Gadget
);
333 /* cleanup our data here */
334 if(data
->ag_Pool
!= NULL
)
335 DeletePool(data
->ag_Pool
);
337 rv
= DoSuperMethodA(cl
,obj
,msg
);
342 /****** amigaguide.datatype/OM_GET *******************************************
345 OM_GET -- gets an amigaguide datatype object attribute
356 This method gets an amigaguide datatype object attribute. See the
357 following TAGS section for directly supported (overwritten) attributes
358 by the datatype. All attributes of super classes are supported as
362 DTA_Title -- (STRPTR) name of the amigaguide document.
364 DTA_NominalHoriz -- (ULONG) nominal width of the document in pixel.
365 See @width AmigaGuide command.
367 DTA_NominalVert -- (ULONG) nominal height of the document in pixel.
368 See @height AmigaGuide command.
370 DTA_Methods -- (ULONG *) array of supported datatype methods.
373 datatypes.library/GetDTAttrsA(), OM_SET
375 ******************************************************************************
379 ULONG
om_get(Class
*cl
,Object
*obj
,struct opGet
*msg
)
385 switch(msg
->opg_AttrID
)
388 *msg
->opg_Storage
= (ULONG
) data
->ag_File
->agf_Name
;
390 case DTA_NominalHoriz
:
393 GetFontDimension(cl
, obj
, data
->ag_File
->agf_Font
, &x
, &y
);
394 *msg
->opg_Storage
= data
->ag_File
->agf_Width
*x
;
397 case DTA_NominalVert
:
400 GetFontDimension(cl
, obj
, data
->ag_File
->agf_Font
, &x
, &y
);
401 *msg
->opg_Storage
= data
->ag_File
->agf_Height
*y
;
404 case DTA_ARexxPortName
:
405 *msg
->opg_Storage
= (ULONG
) data
->ag_RexxName
;
407 case DTA_TriggerMethods
:
408 *msg
->opg_Storage
= (ULONG
) triggermethods
;
412 if(data
->ag_File
->agf_TOC
!= NULL
)
413 *msg
->opg_Storage
= (ULONG
) data
->ag_File
->agf_TOC
;
415 *msg
->opg_Storage
= (ULONG
) "main";
418 if(data
->ag_File
->agf_Help
!= NULL
)
419 *msg
->opg_Storage
= (ULONG
) data
->ag_File
->agf_Help
;
421 *msg
->opg_Storage
= (ULONG
) "sys/amigaguide.guide";
424 *msg
->opg_Storage
= (ULONG
) data
->ag_File
->agf_Index
;
427 if(data
->ag_Actual
== obj
)
428 *msg
->opg_Storage
= (ULONG
) supported_methods
;
430 /* get methods from sub object. */
431 if(DoMethodA(data
->ag_Actual
, (Msg
) msg
) == 0)
435 rv
= DoSuperMethodA(cl
,obj
,(Msg
) msg
);
441 ULONG
_om_update(Class
*cl
, Object
*obj
, struct opSet
*msg
)
445 struct TagItem
*tstate
= msg
->ops_AttrList
;
448 /* process attributes that only belongs to this class */
449 while((tag
= NextTagItem((const struct TagItem
**)&tstate
)) != NULL
)
454 DoTrigger(cl
, obj
, msg
->ops_GInfo
, tag
->ti_Data
, NULL
);
462 /****** amigaguide.datatype/OM_SET *******************************************
465 OM_SET -- sets an amigaguide datatype object attribute
471 struct TagItem *ops_AttrList;
472 struct GadgetInfo *ops_GInfo;
476 This method sets the passed amigaguide datatype object attributes. See
477 the following TAGS section for directly supported (overwritten)
478 attributes by the datatype. All attributes of super classes are
482 AGA_Secure, AGDTA_Secure -- (BOOL) if TRUE no program or ARexx script
483 will be launched by the amigaguide datatype. Defaults to FALSE.
486 datatypes.library/SetDTAttrsA(), OM_GET
488 ******************************************************************************
493 ULONG
_om_set(Class
*cl
,Object
*obj
,struct opSet
*msg
)
498 struct TagItem
*tstate
= msg
->ops_AttrList
;
501 /* process attributes that only belongs to this class */
502 while((tag
= NextTagItem((const struct TagItem
**)&tstate
)) != NULL
)
508 data
->ag_Flags
.Secure
= tag
->ti_Data
? TRUE
: FALSE
;
510 case AGDTA_HelpGroup
:
511 /* TODO: help group set attr? */
514 /* now redraw the object */
518 data
->ag_ICTarget
= (Object
*) tag
->ti_Data
;
521 data
->ag_ICMap
= (struct TagItem
*) tag
->ti_Data
;
525 DA(msg
->MethodID
== OM_SET
, ("OM_SET: %lx=0x%lx\n", tag
->ti_Tag
, tag
->ti_Data
));
526 DA(msg
->MethodID
== OM_UPDATE
, ("OM_UPDATE: %lx=0x%lx\n", tag
->ti_Tag
, tag
->ti_Data
));
529 if(data
->ag_Flags
.Redraw
)
532 if(data
->ag_Actual
!= obj
)
534 rv
+= DoMethodA(data
->ag_Actual
, (Msg
) msg
);
540 ULONG
gm_layout(Class
*cl
, Object
*obj
, struct gpLayout
*msg
)
545 /* remember window pointer to be used by ARexx commands */
546 if(data
->ag_Window
== NULL
)
547 data
->ag_Window
= msg
->gpl_GInfo
->gi_Window
;
549 rc
= DoSuperMethodA(cl
,obj
,(Msg
) msg
);
551 DB(("inital layout %ld\n", msg
->gpl_Initial
));
553 if(data
->ag_Gadget
== NULL
)
556 if(GetDTDomain(cl
, obj
, &domain
))
557 MakeNavGadget(cl
, obj
, &domain
);
560 if(data
->ag_Gadget
!= NULL
)
561 DoMethodA(CAST_OBJ(data
->ag_Gadget
),(Msg
) msg
);
563 if(GetDTDomain(cl
, obj
, &data
->ag_SubObjDomain
))
565 if(data
->ag_Gadget
!= NULL
)
566 data
->ag_NavHeight
= CAST_GAD(data
->ag_Gadget
)->Height
+ AG_NAV_DISTANCE
;
568 data
->ag_SubObjDomain
.Top
+= data
->ag_NavHeight
;
569 data
->ag_SubObjDomain
.Height
-= data
->ag_NavHeight
;
572 if(data
->ag_Actual
!= obj
)
574 rc
+= DoMethodA(data
->ag_Actual
, (Msg
) msg
);
575 /* adjust initial layout domain attributes */
578 SetAttrs(data
->ag_Actual
,
579 GA_Top
, CAST_GAD(obj
)->TopEdge
+ data
->ag_NavHeight
,
580 GA_RelHeight
, CAST_GAD(obj
)->Height
- data
->ag_NavHeight
,
585 if(!data
->ag_Flags
.InAsyncLayout
)
587 /* if we aren't in our external process send layout msg. */
588 if(data
->ag_Process
!= (struct Process
*) FindTask(NULL
))
590 struct DTSpecialInfo
*si
= CAST_GAD(obj
)->SpecialInfo
;
592 ObtainSemaphore(&data
->ag_ASyncLayout
);
593 if(si
->si_Flags
& DTSIF_LAYOUT
)
595 si
->si_Flags
|= DTSIF_NEWSIZE
;
596 /* terminate layout process */
597 Signal(&data
->ag_Process
->pr_Task
, SIGBREAKF_CTRL_C
);
600 if(SendAGLayout(cl
, obj
, msg
))
601 si
->si_Flags
|= DTSIF_LAYOUT
;
603 ReleaseSemaphore(&data
->ag_ASyncLayout
);
606 struct gpLayout layout
= *msg
;
608 layout
.MethodID
= DTM_ASYNCLAYOUT
;
609 DoMethodA(obj
, (Msg
) &layout
);
611 if(data
->ag_Flags
.GotoLine
)
613 /* set possible new vertical top position (goto line). */
614 SetAttrs(obj
, DTA_TopVert
, data
->ag_ActualObject
->ago_TopVert
, TAG_DONE
);
615 /* and also tell others... */
616 NotifyAttrs(obj
, msg
->gpl_GInfo
, 0,
617 GA_ID
, CAST_GAD(obj
)->GadgetID
,
618 DTA_TopVert
, data
->ag_ActualObject
->ago_TopVert
,
620 data
->ag_Flags
.GotoLine
= FALSE
;
628 ULONG
gm_render(Class
*cl
, Object
*obj
, struct gpRender
*msg
)
631 struct DTSpecialInfo
*si
= CAST_GAD(obj
)->SpecialInfo
;
634 /* do not render in busy state */
635 if(si
->si_Flags
& DTSIF_LAYOUT
)
637 DB(("gm_render(): in layout\n"));
638 data
->ag_Flags
.Redraw
= TRUE
;
642 if(!AttemptSemaphore(&si
->si_Lock
))
644 DB(("gm_render(): lock failed\n"));
647 /* first draw navigator gadget */
648 Object
*nav
= CAST_OBJ(data
->ag_Gadget
);
651 ULONG drawmode
= msg
->gpr_Redraw
;
652 ULONG draw
= data
->ag_Flags
.Redraw
|| drawmode
== GREDRAW_REDRAW
;
654 if(drawmode
== GREDRAW_UPDATE
)
655 if(DoMethod(nav
, NVM_CHANGED
))
660 struct IBox
*domain
= &data
->ag_SubObjDomain
;
661 struct RastPort
*rp
= msg
->gpr_RPort
;
662 struct GadgetInfo
*ginfo
= msg
->gpr_GInfo
;
663 WORD y
= domain
->Top
- AG_NAV_DISTANCE
;
664 struct gpRender render
;
666 render
.MethodID
= GM_RENDER
;
667 render
.gpr_GInfo
= ginfo
;
668 render
.gpr_RPort
= rp
;
669 render
.gpr_Redraw
= drawmode
;
671 DoMethodA(CAST_OBJ(nav
), (Msg
) &render
);
673 SetAPen(rp
, ginfo
->gi_DrInfo
->dri_Pens
[SHINEPEN
]);
674 Move(rp
, domain
->Left
, y
);
675 Draw(rp
, domain
->Left
+ domain
->Width
- 1, y
);
676 SetAPen(rp
, ginfo
->gi_DrInfo
->dri_Pens
[SHADOWPEN
]);
677 Move(rp
, domain
->Left
, ++y
);
678 Draw(rp
, domain
->Left
+ domain
->Width
- 1, y
);
682 /* now lets draw the actual displayed object */
683 if(data
->ag_Actual
!= obj
)
685 rv
= DoMethodA(data
->ag_Actual
, (Msg
) msg
);
690 data
->ag_Flags
.Redraw
= FALSE
;
691 ReleaseSemaphore(&si
->si_Lock
);
697 /****** amigaguide.datatype/GM_HANDLEINPUT ***********************************
700 GM_HANDLEINPUT -- handles input events
706 struct GadgetInfo *gpi_GInfo;
707 struct InputEvent *gpi_IEvent;
708 LONG *gpi_Termination;
714 struct TabletData *gpi_TabletData;
718 This method handles incoming input events. Checks if the event resides
719 in the navigation bar and executes any action if so. Otherwise it
720 forwards the incoming events to its viewed node or datatype object.
721 In case of an AmigaGuide node it handles any mouse event to enable
722 link activation through the mouse.
726 ******************************************************************************
730 ULONG
gm_input(Class
*cl
, Object
*obj
, struct gpInput
*msg
)
733 struct DTSpecialInfo
*si
= CAST_GAD(obj
)->SpecialInfo
;
734 ULONG rv
= GMR_MEACTIVE
;
736 /* do not handle input in busy state */
737 if(si
->si_Flags
& DTSIF_LAYOUT
)
740 } else if(!AttemptSemaphore(&si
->si_Lock
))
745 struct InputEvent
*ie
= msg
->gpi_IEvent
;
746 struct Gadget
*nav
= (struct Gadget
*) data
->ag_Gadget
;
750 case IECLASS_RAWMOUSE
:
751 if(nav
!= NULL
&& ((msg
->gpi_Mouse
.Y
< nav
->Height
&&
752 !data
->ag_Flags
.InDocInput
) ||
753 data
->ag_Flags
.InNavInput
))
755 /* check if gadget is even active. This is needed to deactivate the gadget, if
756 * the user makes a great step with the mouse, so that msg->gpi_Mouse.Y > nav->Height !
758 rv
= DoMethodA(CAST_OBJ(nav
),(Msg
) msg
);
760 data
->ag_Flags
.InNavInput
= (rv
== GMR_MEACTIVE
) ? TRUE
: FALSE
;
761 } else if(data
->ag_Actual
!= obj
)
763 /* adjust mouse y coordinate so the sub-object doesn't need to
764 * know about the navigation bar height.
766 msg
->gpi_Mouse
.Y
-= (nav
->Height
+ AG_NAV_DISTANCE
);
768 rv
= DoMethodA(data
->ag_Actual
, (Msg
) msg
);
770 data
->ag_Flags
.InDocInput
= (rv
== GMR_MEACTIVE
) ? TRUE
: FALSE
;
774 ReleaseSemaphore(&si
->si_Lock
);
780 ULONG
dtm_removedtobject(Class
*cl
, Object
*obj
, Msg msg
)
784 /* clear window pointer which is used in the external process
785 using DoDTMethod() to get a valid GInfo structure. */
786 data
->ag_Window
= NULL
;
790 if(data
->ag_Gadget
!= NULL
)
792 DisposeObject(data
->ag_Gadget
);
793 data
->ag_Gadget
= NULL
;
797 return DoSuperMethodA(cl
, obj
, msg
);
800 ULONG
dtm_asynclayout(Class
*cl
, Object
*obj
, struct gpLayout
*msg
)
803 struct DTSpecialInfo
*si
= (struct DTSpecialInfo
*) CAST_GAD(obj
)->SpecialInfo
;
804 struct DTSpecialInfo
*sosi
= (struct DTSpecialInfo
*) CAST_GAD(data
->ag_Actual
)->SpecialInfo
;
806 LONG topv
,totv
,unitv
;
807 LONG toph
,toth
,unith
;
808 STRPTR title
= "amigaguide.datatype";
810 GetDTDomain(cl
, obj
, &domain
);
812 ObtainSemaphore(&si
->si_Lock
);
814 /* indicate sub object that we are in layout */
815 sosi
->si_Flags
|= DTSIF_LAYOUT
;
817 /* try to load initial node */
818 if(data
->ag_Actual
== obj
)
820 data
->ag_Flags
.InAsyncLayout
= TRUE
;
821 GotoObject(cl
, obj
, msg
->gpl_GInfo
, data
->ag_InitialNode
, 0);
822 data
->ag_Flags
.InAsyncLayout
= FALSE
;
825 /* layout the actual sub object. */
826 if(data
->ag_Actual
!= obj
)
828 BOOL initial
= msg
->gpl_Initial
;
829 ULONG mid
= msg
->MethodID
;
831 /* if ag_Flags.InitialLayout is set to TRUE, the sub-object
832 * needs an initial layout! */
833 if(data
->ag_Flags
.InitialLayout
)
835 msg
->gpl_Initial
= TRUE
;
836 data
->ag_Flags
.InitialLayout
= FALSE
;
839 /* we are in asynclayout, so make really sure, overwriting proclayout id! */
840 msg
->MethodID
= DTM_ASYNCLAYOUT
;
841 DoMethodA(data
->ag_Actual
, (Msg
) msg
);
845 msg
->gpl_Initial
= FALSE
;
848 if(GetDTAttrs(data
->ag_Actual
,
849 DTA_TopVert
, (ULONG
) &topv
,
850 DTA_TotalVert
, (ULONG
) &totv
,
851 DTA_TopHoriz
, (ULONG
) &toph
,
852 DTA_TotalHoriz
, (ULONG
) &toth
,
853 DTA_VertUnit
, (ULONG
) &unitv
,
854 DTA_HorizUnit
, (ULONG
) &unith
,
857 unitv
= (unitv
== 0) ? 1 : unitv
;
858 unith
= (unith
== 0) ? 1 : unith
;
860 if(GetDTAttrs(data
->ag_Actual
, DTA_Title
, (ULONG
) &title
, TAG_DONE
) == 0)
861 if(GetDTAttrs(data
->ag_Actual
, DTA_Name
, (ULONG
) &title
, TAG_DONE
) == 0)
863 /* these values must be set explicitly
864 * possible error in datatypesclass ?
866 si
->si_VisVert
= (domain
.Height
- data
->ag_NavHeight
) / unitv
;
867 si
->si_VisHoriz
= domain
.Width
/ unith
;
869 DB(("topvert %ld, visvert %ld, totvert %ld\n",
870 topv
, si
->si_VisVert
, totv
));
873 /* fix for a different version of the datatypesclass, normally
874 * this should be done by the datatypesclass itself */
876 si
->si_TopHoriz
= -1;
880 /* TODO: if wrapping is on this value maybe wrong after an layout */
881 /* remember last vertical top value */
882 si
->si_TopVert
= topv
;
883 si
->si_TopHoriz
= toph
;
888 si
->si_TotVert
= totv
;
889 si
->si_TotHoriz
= toth
;
892 DB(("before async notify...\n"));
894 NotifyAttrs(obj
, msg
->gpl_GInfo
, 0,
895 GA_ID
, CAST_GAD(obj
)->GadgetID
,
900 DTA_VisibleVert
,si
->si_VisVert
,
903 DTA_TotalHoriz
, toth
,
904 DTA_HorizUnit
, unith
,
905 DTA_VisibleHoriz
,si
->si_VisHoriz
,
915 sosi
->si_Flags
&= ~DTSIF_LAYOUT
;
917 ReleaseSemaphore(&si
->si_Lock
);
922 /****** amigaguide.datatype/DTM_TRIGGER **************************************
925 DTM_TRIGGER -- triggers some functions on the AmigaGuide object.
931 struct GadgetInfo *dtt_GInfo;
937 This method triggers the following functions specified via the
938 dtt_Function field of the message. NOTE that you have to mask out
939 the real STM_#? function from the field by applying the function
940 mask (dtt_Function & STMG_METHOD_MASK):
942 STM_RETRACE -- Go to the previous viewed node. Same as pressing the
945 STM_HELP -- Go to the help node. Same as pressing the "Help" button
947 STM_INDEX -- Go to the index node. Same as pressing the "Index" button
949 STM_CONTENTS -- Go to the contents/main node. Same as pressing the
952 STM_BROWSE_PREV -- Go to the previous logical node in the database.
953 Same as pressing the "< Browse" button
955 STM_BROWSE_NEXT -- Go to the next logical node in the database. Same
956 as pressing the "> Browse" button
958 STM_COMMAND -- Execute the command found in the dtt_Data field.
959 Currently only null-terminated strings are supported. To make this
960 function save it only operates on data found in dtt_Data if
961 (dtt_Function & STMF_DATA_MASK) == STMD_STRPTR. The following
962 commands are supported:
964 link <nodename> -- Goto to the named node.
965 system <command> -- Execute the given command.
966 rxs <arexx-string> -- Executes the given ARexx string.
967 rx <arexx-script> -- Executes the given ARexx macro script.
969 STM_PREV_FIELD -- if the current node has links select previous link.
971 STM_NEXT_FIELD -- if the current node has links select next link.
973 STM_ACTIVATE_FIELD -- if a link is selected activate it, by sending
974 a STM_COMMAND trigger method.
979 ******************************************************************************
984 ULONG
dtm_trigger(Class
*cl
, Object
*obj
, struct dtTrigger
*msg
)
989 /* make sure any trigger command is only executed in our external
992 if(data
->ag_Process
!= (struct Process
*) FindTask(NULL
))
994 SendAGTrigger(cl
, obj
, msg
);
998 DB(("do trigger command (proc=\"%s\") function=%lx\n",
999 FindTask(NULL
)->tc_Node
.ln_Name
, msg
->dtt_Function
));
1001 switch(msg
->dtt_Function
& STMF_METHOD_MASK
)
1004 if(data
->ag_ActualObject
->ago_Node
.ln_Succ
->ln_Succ
!= NULL
)
1006 struct AmigaGuideObject
*old
= (struct AmigaGuideObject
*) RemHead(&data
->ag_Visited
);
1007 DB(("old is %lx (%s)\n", old
, old
->ago_Node
.ln_Name
));
1008 data
->ag_Flags
.GotoLine
= TRUE
;
1009 ActivateAGObject(cl
, obj
, msg
->dtt_GInfo
,
1010 (struct AmigaGuideObject
*) data
->ag_Visited
.lh_Head
);
1011 FreeAGObject(cl
, obj
, old
);
1016 ULONG cmdtype
= CMDTYPE_UNKNOWN
;
1018 STRPTR destend
= NULL
;
1022 DB(("got trigger command\n"));
1023 switch(msg
->dtt_Function
& STMF_DATA_MASK
)
1026 STRPTR type
, typeend
;
1027 STRPTR ptr
= (STRPTR
) msg
->dtt_Data
;
1029 DB(("string is %s\n", ptr
));
1031 while(*ptr
!= '\0' && *ptr
!= ' ' && *ptr
!= '\t')
1038 while(*ptr
!= '\0' && *ptr
!= ' ' && *ptr
!= '\t')
1043 /* get line number to goto. */
1045 StrToLong(ptr
, &line
);
1050 while(*ptr
!= '\0' && *ptr
!= '"')
1057 /* get line number to goto. */
1059 StrToLong(ptr
, &line
);
1064 if(!Strnicmp(type
, "link", typeend
-type
))
1065 cmdtype
= CMDTYPE_LINK
;
1066 else if(!Strnicmp(type
, "system", typeend
-type
))
1067 cmdtype
= CMDTYPE_SYSTEM
;
1068 else if(!Strnicmp(type
, "rxs", typeend
-type
) && (typeend
-type
) == 3)
1069 cmdtype
= CMDTYPE_RXS
;
1070 else if(!Strnicmp(type
, "rx", typeend
-type
))
1071 cmdtype
= CMDTYPE_RX
;
1075 DB(("cmdtype %ld (dest=\"%s\") %ld\n", cmdtype
, dest
, line
));
1080 rv
= GotoObject(cl
, obj
, msg
->dtt_GInfo
, dest
, line
);
1082 case CMDTYPE_SYSTEM
:
1083 SystemCommand(cl
, obj
, dest
);
1086 SendRexxCommand(cl
, obj
, dest
, AGRX_RXS
);
1089 SendRexxCommand(cl
, obj
, dest
, AGRX_RX
);
1092 DB(("unknown command\n"));
1099 rv
= GotoObjectTag(cl
, obj
, msg
->dtt_GInfo
, AGNA_Help
);
1102 rv
= GotoObjectTag(cl
, obj
, msg
->dtt_GInfo
, AGNA_Contents
);
1105 rv
= GotoObjectTag(cl
, obj
, msg
->dtt_GInfo
, AGNA_Index
);
1107 case STM_BROWSE_PREV
:
1108 rv
= GotoObjectTag(cl
, obj
, msg
->dtt_GInfo
, AGNA_Previous
);
1109 /* no object found try previous node in linked list */
1112 if(data
->ag_ActualObject
->ago_AGNode
->agn_Node
.ln_Pred
->ln_Pred
!= NULL
)
1113 rv
= GotoObject(cl
, obj
, msg
->dtt_GInfo
, data
->ag_ActualObject
->ago_AGNode
->agn_Node
.ln_Pred
->ln_Name
, 0);
1116 case STM_BROWSE_NEXT
:
1117 rv
= GotoObjectTag(cl
, obj
, msg
->dtt_GInfo
, AGNA_Next
);
1118 /* no object found try next node in linked list */
1121 if(data
->ag_ActualObject
->ago_AGNode
->agn_Node
.ln_Succ
->ln_Succ
!= NULL
)
1122 rv
= GotoObject(cl
, obj
, msg
->dtt_GInfo
, data
->ag_ActualObject
->ago_AGNode
->agn_Node
.ln_Succ
->ln_Name
, 0);
1126 rv
= DoMethodA(data
->ag_Actual
, (Msg
) msg
);
1133 void UpdateNavigator(Class
*cl
, Object
*obj
, struct GadgetInfo
*ginfo
)
1136 struct AmigaGuideObject
*agobj
= data
->ag_ActualObject
;
1138 struct npChangeStatus chg
;
1139 struct NavigatorStatus cmds
[6];
1141 STRPTR index
= NULL
;
1146 GetDTAttrs(data
->ag_Actual
,
1147 AGNA_Contents
, (ULONG
) &toc
,
1148 AGNA_Index
, (ULONG
) &index
,
1149 AGNA_Previous
, (ULONG
) &prev
,
1150 AGNA_Next
, (ULONG
) &next
,
1151 AGNA_Help
, (ULONG
) &help
,
1157 BPTR lock
= GetFileLock(cl
, obj
, "sys/amigaguide.guide", &nodetype
);
1161 help
= "sys/amigaguide.guide";
1162 SetAttrs(data
->ag_Actual
,
1163 AGNA_Help
, (ULONG
) help
,
1167 cmds
[0].ns_Command
= STM_CONTENTS
;
1168 cmds
[0].ns_Status
= (toc
== NULL
&& !Stricmp(agobj
->ago_Node
.ln_Name
, "main")) ? NVS_DISABLE
: NVS_ENABLE
;
1169 cmds
[1].ns_Command
= STM_INDEX
;
1170 cmds
[1].ns_Status
= (index
== NULL
|| !Stricmp(agobj
->ago_Node
.ln_Name
, index
)) ? NVS_DISABLE
: NVS_ENABLE
;
1171 cmds
[2].ns_Command
= STM_RETRACE
;
1172 cmds
[2].ns_Status
= (agobj
->ago_Node
.ln_Succ
->ln_Succ
== NULL
) ? NVS_DISABLE
: NVS_ENABLE
;
1173 cmds
[3].ns_Command
= STM_BROWSE_PREV
;
1174 cmds
[3].ns_Status
= (prev
== NULL
&& (agobj
->ago_AGNode
== NULL
|| agobj
->ago_AGNode
->agn_Node
.ln_Pred
->ln_Pred
== NULL
)) ? NVS_DISABLE
: NVS_ENABLE
;
1175 cmds
[4].ns_Command
= STM_BROWSE_NEXT
;
1176 cmds
[4].ns_Status
= (next
== NULL
&& (agobj
->ago_AGNode
== NULL
|| agobj
->ago_AGNode
->agn_Node
.ln_Succ
->ln_Succ
== NULL
)) ? NVS_DISABLE
: NVS_ENABLE
;
1177 cmds
[5].ns_Command
= STM_HELP
;
1178 cmds
[5].ns_Status
= (help
== NULL
) ? NVS_DISABLE
: NVS_ENABLE
;
1180 chg
.MethodID
= NVM_CHANGESTATUS
;
1181 chg
.np_GInfo
= ginfo
;
1182 chg
.np_NumCommands
= 6;
1183 chg
.np_Commands
= cmds
;
1185 if(DoMethodA(CAST_OBJ(data
->ag_Gadget
), (Msg
) &chg
))
1187 NotifyAttrs(obj
, ginfo
, 0,
1188 GA_ID
, CAST_GAD(obj
)->GadgetID
,
1195 void ActivateAGObject(Class
*cl
, Object
*obj
, struct GadgetInfo
*ginfo
,
1196 struct AmigaGuideObject
*agobj
)
1199 struct gpLayout layout
;
1200 struct IBox
*domain
;
1202 data
->ag_Actual
= agobj
->ago_Object
;
1203 data
->ag_ActualObject
= agobj
;
1205 /* if the current object is an amigaguide node set the appropriate
1206 file structure into the global data section to find nodes within
1207 this AmigaGuide file again. */
1208 if(agobj
->ago_AGNode
!= NULL
)
1209 data
->ag_File
= agobj
->ago_AGNode
->agn_File
;
1211 /* adjust state of navigation bar */
1212 UpdateNavigator(cl
, obj
, ginfo
);
1214 /* clear object domain */
1216 struct RastPort
*rp
;
1218 domain
= &data
->ag_SubObjDomain
;
1219 rp
= ObtainGIRPort(ginfo
);
1222 EraseRect(rp
, domain
->Left
, domain
->Top
,
1223 domain
->Left
+domain
->Width
-1,
1224 domain
->Top
+domain
->Height
-1);
1229 /* now lets layout our and its sub object. */
1230 layout
.MethodID
= GM_LAYOUT
;
1231 layout
.gpl_GInfo
= ginfo
;
1232 layout
.gpl_Initial
= FALSE
;
1233 DoMethodA(obj
, (Msg
) &layout
);
1237 /****** amigaguide.datatype/DTM_GOTO *****************************************
1240 DTM_GOTO -- goto the given node/object.
1246 struct GadgetInfo *dtg_GInfo;
1247 STRPTR dtg_NodeName;
1248 struct TagItem *dtg_AttrList;
1252 This method tries to load and view the node or object specified in the
1253 dtg_NodeName field. This field can also contain a file name for a file
1254 to be viewed within the AmigaGuide object. And this also may have an
1255 additionally added node name. For example if you want to open an
1256 external AmigaGuide file called index.guide and you want to open the
1257 node named "B" for index entries starting with the letter "B" you can
1258 just pass index.guide/B to the method via the dtg_NodeName field. Also
1259 the tags listed in the TAGS section are passed to the newly created
1263 DTA_TopVert -- vertical (line) position to go to.
1266 1 -- if object could be loaded
1267 0 -- if object could not be found
1268 -1 -- if some error occured during loading
1273 ******************************************************************************
1278 ULONG
dtm_goto(Class
*cl
, Object
*obj
, struct dtGoto
*msg
)
1283 struct DataType
*dt
;
1284 struct AmigaGuideNode
*agnode
;
1285 struct AmigaGuideObject
*agobj
= NULL
;
1286 Object
*dtobj
= NULL
;
1289 UBYTE fontname
[MAXFONTNAME
];
1291 struct TextAttr
*textattr
= NULL
;
1292 BOOL aginternal
= TRUE
;
1294 if(msg
->dtg_NodeName
== NULL
|| *msg
->dtg_NodeName
== '\0')
1296 NotifyAttrs(obj
, msg
->dtg_GInfo
, 0,
1297 GA_ID
, CAST_GAD(obj
)->GadgetID
,
1299 DTA_ErrorString
, "goto empty node name",
1300 DTA_ErrorNumber
, ERROR_REQUIRED_ARG_MISSING
,
1306 if(data
->ag_File
->agf_Font
!= NULL
)
1308 ta
.ta_Name
= fontname
;
1309 DB(("parse font %s\n", data
->ag_File
->agf_Font
));
1310 ParseFontLine(cl
, obj
, data
->ag_File
->agf_Font
, &ta
);
1314 DB(("try loading object \"%s\"\n", msg
->dtg_NodeName
));
1316 /* currently protected input.device task */
1317 if(FindTask(NULL
)->tc_Node
.ln_Type
!= NT_PROCESS
)
1319 DB(("goto object \"%s\" within input task\n", msg
->dtg_NodeName
));
1323 /* TODO: check this work around...
1324 * don't notify loading title if its the main and initial node. There
1325 * are some asynchron notification problems. Sometimes this notification
1326 * is send to MultiView after the complete async layout method has
1327 * completed including all notifications (DTA_Busy == FALSE). Which is
1328 * then overwritten by this notification...
1330 if(!data
->ag_Flags
.InAsyncLayout
)
1332 mysprintf(cb
, data
->ag_Message
, sizeof(data
->ag_Message
),
1333 "Loading %s ...", msg
->dtg_NodeName
);
1335 NotifyAttrs(obj
, msg
->dtg_GInfo
, 0,
1336 GA_ID
, CAST_GAD(obj
)->GadgetID
,
1338 DTA_Title
, data
->ag_Message
,
1341 agnode
= GetAGNode(cl
, obj
, data
->ag_File
, msg
->dtg_NodeName
);
1344 STRPTR file
= CopyAGString(cl
, obj
, msg
->dtg_NodeName
);
1348 BOOL nodetype
= FALSE
;
1349 BPTR lock
= GetFileLock(cl
, obj
, file
, &nodetype
);
1351 DB(("node \"%s\" not found (lock=%lx)\n", file
, lock
));
1355 if((dt
= ObtainDataTypeA(DTST_FILE
, (APTR
) lock
, NULL
)) != NULL
)
1357 if(nodetype
== TRUE
&& !Strnicmp(dt
->dtn_Header
->dth_Name
, "AmigaGuide", 10))
1359 struct AmigaGuideFile
*agf
= (struct AmigaGuideFile
*) data
->ag_Files
.lh_Head
;
1361 /* search current list of opened AG files */
1362 while(agf
->agf_Node
.ln_Succ
!= NULL
)
1364 if(SameLock(agf
->agf_Lock
, lock
) == LOCK_SAME
)
1366 /* found a previously opened AG file, so try to find node */
1367 agnode
= GetAGNode(cl
, obj
, agf
, FilePart(msg
->dtg_NodeName
));
1370 /* set active AG file */
1371 data
->ag_File
= agf
;
1375 agf
= (struct AmigaGuideFile
*) agf
->agf_Node
.ln_Succ
;
1378 /* no ag file and node found so load it now */
1381 DB(("found amigaguide file\n"));
1382 agf
= AllocAGFile(cl
, obj
);
1385 if((agf
->agf_Handle
= OpenFromLock(lock
)) != NULL
)
1387 agf
->agf_Lock
= DupLockFromFH(agf
->agf_Handle
);
1388 agf
->agf_Flags
.CloseHandle
= TRUE
;
1390 ScanFile(cl
, obj
, agf
);
1391 data
->ag_File
= agf
;
1392 agnode
= GetAGNode(cl
, obj
, data
->ag_File
, FilePart(msg
->dtg_NodeName
));
1398 STRPTR filename
= AllocAGMem(cl
, obj
, 1024);
1399 agobj
= AllocAGObject(cl
, obj
);
1400 if(agobj
!= NULL
&& filename
!= NULL
)
1402 NameFromLock(lock
, filename
, 1024);
1403 DB(("try to open file \"%s\"\n", file
));
1404 DTL(msg
->dtg_AttrList
);
1405 if(msg
->dtg_AttrList
!= NULL
)
1406 agobj
->ago_TopVert
= GetTagData(DTA_TopVert
, 0, msg
->dtg_AttrList
);
1408 dtobj
= NewDTObject(filename
,
1411 GA_Top
, data
->ag_SubObjDomain
.Top
,
1412 GA_Left
, data
->ag_SubObjDomain
.Left
,
1413 GA_RelWidth
, CAST_GAD(obj
)->Width
,
1414 GA_RelHeight
, CAST_GAD(obj
)->Height
- data
->ag_NavHeight
,
1415 GA_ID
, CAST_GAD(obj
)->GadgetID
,
1416 ICA_TARGET
, (ULONG
) data
->ag_ICTarget
,
1417 ICA_MAP
, (ULONG
) data
->ag_ICMap
,
1418 DTA_TopVert
, agobj
->ago_TopVert
,
1419 (textattr
!= NULL
) ? DTA_TextAttr
: TAG_IGNORE
, (ULONG
) textattr
,
1421 data
->ag_Flags
.InitialLayout
= TRUE
;
1427 if(filename
!= NULL
)
1428 FreeAGMem(cl
, obj
, filename
, 1024);
1430 ReleaseDataType(dt
);
1434 FreeAGVec(cl
,obj
, file
);
1440 /* GEORGFIX: data->ag_ActualObject could be NULL here so added
1441 "data->ag_ActualObject" to checks (to make sure it is != NULL) */
1443 if(data
->ag_ActualObject
&& data
->ag_ActualObject
->ago_AGNode
!= NULL
&& aginternal
&&
1444 !Stricmp(agnode
->agn_Node
.ln_Name
, data
->ag_ActualObject
->ago_AGNode
->agn_Node
.ln_Name
))
1446 DB(("link within same node \"%s\"\n", agnode
->agn_Node
.ln_Name
));
1447 agobj
= AllocAGObject(cl
, obj
);
1450 dtobj
= agobj
->ago_Object
= data
->ag_Actual
;
1451 agobj
->ago_AGNode
= data
->ag_ActualObject
->ago_AGNode
;
1452 agobj
->ago_NoDispose
= TRUE
;
1456 agobj
= AllocAGObjectNode(cl
, obj
, data
->ag_File
, agnode
);
1463 mysprintf(cb
, buf
, sizeof(buf
), "T:%s_%ld", FilePart(msg
->dtg_NodeName
), ++i
);
1464 agobj
->ago_TmpHandle
= Open(buf
, MODE_NEWFILE
);
1465 } while(agobj
->ago_TmpHandle
== NULL
&& i
<100);
1466 if(agobj
->ago_TmpHandle
!= NULL
)
1468 Write(agobj
->ago_TmpHandle
, agobj
->ago_Buffer
, agobj
->ago_BufferLen
);
1469 Close(agobj
->ago_TmpHandle
);
1470 agobj
->ago_TmpHandle
= Lock(buf
, SHARED_LOCK
);
1473 if(agnode
->agn_Font
!= NULL
)
1475 ta
.ta_Name
= fontname
;
1476 ParseFontLine(cl
, obj
, agnode
->agn_Font
, &ta
);
1480 dt
= ObtainDataTypeA(DTST_FILE
, (APTR
) agobj
->ago_TmpHandle
, NULL
);
1482 /* TODO: Currently MorphOS datatypes.library doesn't support DTST_MEMORY... */
1483 DTA_SourceType
, DTST_MEMORY
,
1484 DTA_SourceAddress
,agobj
->ago_Buffer
,
1485 DTA_SourceSize
, agobj
->ago_BufferLen
,
1488 DA(dt
== NULL
, ("can't determine datatype\n"));
1493 dtobj
= NewObject(cb
->cb_NodeClass
, NULL
,
1494 GA_Top
, data
->ag_SubObjDomain
.Top
,
1495 GA_Left
, data
->ag_SubObjDomain
.Left
,
1496 GA_RelWidth
, CAST_GAD(obj
)->Width
,
1497 GA_RelHeight
, CAST_GAD(obj
)->Height
- data
->ag_NavHeight
,
1498 GA_ID
, CAST_GAD(obj
)->GadgetID
,
1499 DTA_DataType
, (ULONG
) dt
,
1500 DTA_Name
, (ULONG
) buf
,
1501 DTA_SourceType
, DTST_FILE
,
1502 DTA_Handle
, (ULONG
) agobj
->ago_TmpHandle
,
1503 ICA_TARGET
, (ULONG
) data
->ag_ICTarget
,
1504 ICA_MAP
, (ULONG
) data
->ag_ICMap
,
1505 /* special attributes for amigagudienode class */
1506 AGNA_RootObject
, (ULONG
) obj
,
1507 AGNA_AGFile
, (ULONG
) data
->ag_File
,
1509 (textattr
!= NULL
) ? DTA_TextAttr
: TAG_IGNORE
, (ULONG
) textattr
,
1510 (msg
->dtg_AttrList
!= NULL
) ? TAG_MORE
: TAG_DONE
, (ULONG
) msg
->dtg_AttrList
);
1513 agobj
->ago_TmpHandle
= NULL
;
1514 data
->ag_Flags
.InitialLayout
= TRUE
;
1516 ReleaseDataType(dt
);
1525 DB(("couldn't create dtobj %ld for node=\"%s\"\n", err
, msg
->dtg_NodeName
));
1527 FreeAGObject(cl
, obj
, agobj
);
1530 AddHead(&data
->ag_Visited
, &agobj
->ago_Node
);
1531 if(msg
->dtg_AttrList
!= NULL
)
1532 agobj
->ago_TopVert
= GetTagData(DTA_TopVert
, 0, msg
->dtg_AttrList
);
1533 DB(("top vert is %ld\n", agobj
->ago_TopVert
));
1534 ActivateAGObject(cl
, obj
, msg
->dtg_GInfo
, agobj
);
1540 DB(("error occured %ld for node=\"%s\"\n", err
, msg
->dtg_NodeName
));
1542 NotifyAttrs(obj
, msg
->dtg_GInfo
, 0,
1543 GA_ID
, CAST_GAD(obj
)->GadgetID
,
1545 DTA_ErrorString
, msg
->dtg_NodeName
,
1546 DTA_ErrorNumber
, err
,
1556 IPTR
om_update(Class
*cl
, Object
*obj
, struct opSet
*msg
)
1560 /* avoid update loops */
1561 if(DoMethod(obj
, ICM_CHECKLOOP
))
1564 rv
= _om_update(cl
, obj
, msg
);
1565 rv
+= _om_set(cl
, obj
, msg
);
1567 rv
+= (ULONG
)DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1569 DB(("set returned %ld\n", rv
));
1570 /* this class is derived from the gadgetclass, check
1571 * if the gadget needs a refresh : */
1572 if(rv
!= 0 && (OCLASS (obj
) == cl
))
1574 struct RastPort
*rp
;
1575 if((rp
= ObtainGIRPort(CAST_SET(msg
)->ops_GInfo
)) != NULL
)
1577 struct gpRender render
;
1578 render
.MethodID
= GM_RENDER
;
1579 render
.gpr_GInfo
= CAST_SET(msg
)->ops_GInfo
;
1580 render
.gpr_RPort
= rp
;
1581 render
.gpr_Redraw
= GREDRAW_UPDATE
;
1582 DoMethodA(obj
, (Msg
) &render
);
1591 IPTR
om_set(Class
*cl
, Object
*obj
, struct opSet
*msg
)
1593 ULONG rv
= _om_set(cl
, obj
, CAST_SET(msg
));
1595 rv
+= (ULONG
)DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1597 DB(("set returned %ld\n", rv
));
1598 /* this class is derived from the gadgetclass, check
1599 * if the gadget needs a refresh : */
1600 if(rv
!= 0 && (OCLASS (obj
) == cl
))
1602 struct RastPort
*rp
;
1603 if((rp
= ObtainGIRPort(CAST_SET(msg
)->ops_GInfo
)) != NULL
)
1605 struct gpRender render
;
1606 render
.MethodID
= GM_RENDER
;
1607 render
.gpr_GInfo
= CAST_SET(msg
)->ops_GInfo
;
1608 render
.gpr_RPort
= rp
;
1609 render
.gpr_Redraw
= GREDRAW_UPDATE
;
1610 DoMethodA(obj
, (Msg
) &render
);
1619 IPTR
dtm_proclayout(Class
*cl
, Object
*obj
, struct gpLayout
*msg
)
1621 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
1623 return dtm_asynclayout(cl
, obj
, msg
);
1626 #else /* !defined(__AROS__) */
1628 IPTR
class_dispatcher(Class
*cl
, Object
*obj
, Msg msg
)
1633 switch(msg
->MethodID
)
1636 rv
= om_new(cl
, obj
, CAST_SET(msg
));
1639 rv
= om_dispose(cl
, obj
, msg
);
1643 rv
= om_get(cl
,obj
,(struct opGet
*) msg
);
1647 /* avoid update loops */
1648 if(DoMethod(obj
, ICM_CHECKLOOP
))
1651 rv
= _om_update(cl
, obj
, CAST_SET(msg
));
1653 rv
+= _om_set(cl
, obj
, CAST_SET(msg
));
1655 rv
+= DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1657 DB(("set returned %ld\n", rv
));
1658 /* this class is derived from the gadgetclass, check
1659 * if the gadget needs a refresh : */
1660 if(rv
!= 0 && (OCLASS (obj
) == cl
))
1662 struct RastPort
*rp
;
1663 if((rp
= ObtainGIRPort(CAST_SET(msg
)->ops_GInfo
)) != NULL
)
1665 struct gpRender render
;
1666 render
.MethodID
= GM_RENDER
;
1667 render
.gpr_GInfo
= CAST_SET(msg
)->ops_GInfo
;
1668 render
.gpr_RPort
= rp
;
1669 render
.gpr_Redraw
= GREDRAW_UPDATE
;
1670 DoMethodA(obj
, (Msg
) &render
);
1677 rv
= gm_layout(cl
, obj
, CAST_GPL(msg
));
1680 rv
= gm_render(cl
, obj
, (struct gpRender
*) msg
);
1683 case GM_HANDLEINPUT
:
1684 rv
= gm_input(cl
, obj
, (struct gpInput
*) msg
);
1686 case DTM_REMOVEDTOBJECT
:
1687 rv
= dtm_removedtobject(cl
, obj
, msg
);
1689 case DTM_PROCLAYOUT
:
1690 rv
= DoSuperMethodA(cl
, obj
, msg
);
1692 case DTM_ASYNCLAYOUT
:
1693 rv
= dtm_asynclayout(cl
, obj
, CAST_GPL(msg
));
1696 rv
= dtm_trigger(cl
, obj
, (struct dtTrigger
*) msg
);
1699 rv
= dtm_goto(cl
, obj
, (struct dtGoto
*) msg
);
1702 rv
= DoSuperMethodA(cl
,obj
,msg
);
1708 #endif /* __AROS__ */