2 * Scout - The Amiga System Monitor
4 *------------------------------------------------------------------
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *------------------------------------------------------------------
22 * @author Andreas Gelhausen
23 * @author Richard Körber <rkoerber@gmx.de>
24 * @author Pavel Fedin <pavel.fedin@mail.ru>
27 #include "system_headers.h"
29 /* This class operates on AROS-specific data.
30 On non-AROS systems oop.library and its classes do not exist,
31 however it's possible to retrieve the data via network from the
32 remote AROS machine */
37 #include <proto/oop.h>
39 struct Library
*OOPBase
;
40 OOP_AttrBase MetaAttrBase
;
45 TEXT cwd_Title
[WINDOW_TITLE_LENGTH
];
49 APTR cwd_RemoveButton
;
53 struct OOPCallbackUserData
{
58 HOOKPROTONHNO(classtree_confunc
, LONG
, struct MUIP_NListtree_ConstructMessage
*msg
)
60 return AllocListEntry(msg
->MemPool
, msg
->UserData
, sizeof(struct OOPClassEntry
));
62 MakeStaticHook(classtree_conhook
, classtree_confunc
);
64 HOOKPROTONHNO(classtree_desfunc
, void, struct MUIP_NListtree_DestructMessage
*msg
)
66 FreeListEntry(msg
->MemPool
, &msg
->UserData
);
68 MakeStaticHook(classtree_deshook
, classtree_desfunc
);
70 HOOKPROTONHNO(classtree_dspfunc
, void, struct MUIP_NListtree_DisplayMessage
*msg
)
72 if (msg
->TreeNode
!= NULL
) {
73 struct OOPClassEntry
*ce
= msg
->TreeNode
->tn_User
;
75 msg
->Array
[0] = ce
->ce_Address
;
76 msg
->Array
[1] = ce
->ce_ClassName
;
77 msg
->Array
[2] = ce
->ce_Dispatcher
;
78 msg
->Array
[3] = ce
->ce_CoerceDispatcher
;
79 msg
->Array
[4] = ce
->ce_SuperDispatcher
;
81 msg
->Array
[0] = txtAddress
;
82 msg
->Array
[1] = txtNodeName
;
83 msg
->Array
[2] = txtOOPDoMethod
;
84 msg
->Array
[3] = txtOOPCoerceMethod
;
85 msg
->Array
[4] = txtOOPDoSuperMethod
;
86 msg
->Preparse
[0] = (STRPTR
)MUIX_B
;
87 msg
->Preparse
[1] = (STRPTR
)MUIX_B
;
88 msg
->Preparse
[2] = (STRPTR
)MUIX_B
;
89 msg
->Preparse
[3] = (STRPTR
)MUIX_B
;
90 msg
->Preparse
[4] = (STRPTR
)MUIX_B
;
93 MakeStaticHook(classtree_dsphook
, classtree_dspfunc
);
95 HOOKPROTONHNO(classtree_cmpfunc
, LONG
, struct MUIP_NListtree_CompareMessage
*msg
)
97 struct OOPClassEntry
*ce1
, *ce2
;
100 ce1
= (struct OOPClassEntry
*)msg
->TreeNode1
->tn_User
;
101 ce2
= (struct OOPClassEntry
*)msg
->TreeNode2
->tn_User
;
103 cmp
= stricmp(ce1
->ce_SuperClassName
, ce2
->ce_SuperClassName
);
104 if (cmp
== 0) cmp
= stricmp(ce1
->ce_ClassName
, ce2
->ce_ClassName
);
108 MakeStaticHook(classtree_cmphook
, classtree_cmpfunc
);
110 HOOKPROTONHNO(classtree_findfunc
, LONG
, struct MUIP_NListtree_FindUserDataMessage
*msg
)
112 struct OOPClassEntry
*ce
;
114 ce
= (struct OOPClassEntry
*)msg
->UserData
;
117 return stricmp(msg
->User
, ce
->ce_Address
);
122 MakeStaticHook(classtree_findhook
, classtree_findfunc
);
125 STATIC
void ReceiveList( void (* callback
)( struct OOPClassEntry
*ce
, void *userData
),
128 struct OOPClassEntry
*ce
;
130 if ((ce
= tbAllocVecPooled(globalPool
, sizeof(struct OOPClassEntry
))) != NULL
) {
131 if (SendDaemon("GetOOPClassList")) {
132 while (ReceiveDecodedEntry(&ce
, sizeof(struct OOPClassEntry
))) {
133 callback(ce
, userData
);
137 tbFreeVecPooled(globalPool
, ce
);
141 STATIC
void FormatAddress(STRPTR buf
, APTR dispentry
)
143 if (points2ram(dispentry
)) {
144 _snprintf(buf
, ADDRESS_LENGTH
, MUIX_PH
"$%08lx" MUIX_PT
, dispentry
);
146 _snprintf(buf
, ADDRESS_LENGTH
, "$%08lx", dispentry
);
150 STATIC
void IterateList( void (* callback
)( struct OOPClassEntry
*ce
, void *userData
),
158 struct OOP_InterfaceDescr my_if
= {NULL
, NULL
, 0};
159 struct TagItem mytags
[] = {
160 {aMeta_SuperID
, (IPTR
)CLID_Root
},
161 {aMeta_InterfaceDescr
, (IPTR
)&my_if
},
162 {aMeta_InstSize
, 0 },
166 if ((myclass
= OOP_NewObject(NULL
, CLID_SIMeta
, mytags
)) != NULL
) {
169 struct MinList tmplist
;
170 struct OOPClassEntry
*ce
;
172 NewList((struct List
*)&tmplist
);
174 OOP_AddClass(myclass
);
178 clist
= FindListOfNode(&myclass
->ClassNode
);
179 ITERATE_LIST(clist
, OOP_Class
*, cl
) {
181 if ((ce
= AllocVec(sizeof(struct OOPClassEntry
), MEMF_CLEAR
)) != NULL
) {
183 _snprintf(ce
->ce_Address
, sizeof(ce
->ce_Address
), "$%08lx", cl
);
184 if (cl
->superclass
) {
185 stccpy(ce
->ce_SuperClassName
, (TEXT
*)nonetest((STRPTR
)cl
->superclass
->ClassNode
.ln_Name
), sizeof(ce
->ce_SuperClassName
));
187 stccpy(ce
->ce_SuperClassName
, (TEXT
*)nonetest(NULL
), sizeof(ce
->ce_SuperClassName
));
189 _snprintf(ce
->ce_SuperClassAddress
, sizeof(ce
->ce_SuperClassAddress
), "$%08lx", cl
->superclass
);
191 FormatAddress(ce
->ce_Dispatcher
, cl
->cl_DoMethod
);
192 FormatAddress(ce
->ce_CoerceDispatcher
, cl
->cl_CoerceMethod
);
193 FormatAddress(ce
->ce_SuperDispatcher
, cl
->cl_DoSuperMethod
);
195 stccpy(ce
->ce_ClassName
, (TEXT
*)nonetest(cl
->ClassNode
.ln_Name
), sizeof(ce
->ce_ClassName
));
197 healstring(ce
->ce_ClassName
);
199 AddTail((struct List
*)&tmplist
, (struct Node
*)ce
);
206 ITERATE_LIST(&tmplist
, struct OOPClassEntry
*, ce
) {
207 callback(ce
, userData
);
209 FreeLinkedList((struct List
*)&tmplist
);
211 OOP_RemoveClass(myclass
);
212 OOP_DisposeObject((OOP_Object
*)myclass
);
219 STATIC
void UpdateCallback( struct OOPClassEntry
*ce
,
220 UNUSED
void *userData
)
222 struct OOPCallbackUserData
*ud
= (struct OOPCallbackUserData
*)userData
;
223 struct MUI_NListtree_TreeNode
*parent
;
225 parent
= (struct MUI_NListtree_TreeNode
*)DoMethod(ud
->ud_Tree
, MUIM_NListtree_FindUserData
, MUIV_NListtree_FindUserData_ListNode_Root
, ce
->ce_SuperClassAddress
, MUIV_NListtree_FindUserData_Flag_StartNode
);
226 DoMethod(ud
->ud_Tree
, MUIM_NListtree_Insert
, ce
->ce_ClassName
, ce
, parent
, MUIV_NListtree_Insert_PrevNode_Sorted
, TNF_LIST
| TNF_OPEN
);
229 INLINE STRPTR
SkipFormat(STRPTR str
)
231 if (strncmp(str
, MUIX_PH
, strlen(MUIX_PH
)))
237 STATIC
void PrintCallback( struct OOPClassEntry
*ce
,
240 PrintFOneLine((BPTR
)userData
, txtOOPPrintLine
, ce
->ce_Address
, ce
->ce_SuperClassName
,
241 SkipFormat(ce
->ce_Dispatcher
), SkipFormat(ce
->ce_CoerceDispatcher
), SkipFormat(ce
->ce_SuperDispatcher
), ce
->ce_ClassName
);
244 STATIC
void SendCallback( struct OOPClassEntry
*ce
,
245 UNUSED
void *userData
)
247 SendEncodedEntry(ce
, sizeof(struct OOPClassEntry
));
250 STATIC ULONG
mNew( struct IClass
*cl
,
254 APTR classtree
, classtext
, classcount
, updateButton
, printButton
, removeButton
, moreButton
, exitButton
;
256 if ((obj
= (Object
*)DoSuperNew(cl
, obj
,
257 MUIA_HelpNode
, "OOPClass",
258 MUIA_Window_ID
, MakeID('O','O','P',' '),
259 WindowContents
, VGroup
,
261 Child
, (IPTR
)MyNListtreeObject(&classtree
, "BAR,BAR,BAR,BAR,BAR", &classtree_conhook
, &classtree_deshook
, &classtree_dsphook
, &classtree_cmphook
, &classtree_findhook
, 1, TRUE
),
263 Child
, (IPTR
)MyBelowListview(&classtext
, &classcount
),
265 Child
, (IPTR
)MyVSpace(4),
267 Child
, HGroup
, MUIA_Group_SameSize
, TRUE
,
268 Child
, (IPTR
)(updateButton
= MakeButton(txtUpdate
)),
269 Child
, (IPTR
)(printButton
= MakeButton(txtPrint
)),
270 Child
, (IPTR
)(removeButton
= MakeButton(txtRemove
)),
271 Child
, (IPTR
)(moreButton
= MakeButton(txtMore
)),
272 Child
, (IPTR
)(exitButton
= MakeButton(txtExit
)),
275 TAG_MORE
, msg
->ops_AttrList
)) != NULL
)
277 struct OOPWinData
*cwd
= INST_DATA(cl
, obj
);
280 cwd
->cwd_ClassTree
= classtree
;
281 cwd
->cwd_ClassText
= classtext
;
282 cwd
->cwd_ClassCount
= classcount
;
283 cwd
->cwd_RemoveButton
= removeButton
;
284 cwd
->cwd_MoreButton
= moreButton
;
286 parent
= (APTR
)GetTagData(MUIA_Window_ParentWindow
, (ULONG
)NULL
, msg
->ops_AttrList
);
288 set(obj
, MUIA_Window_Title
, MyGetWindowTitle(txtOOPTitle
, cwd
->cwd_Title
, sizeof(cwd
->cwd_Title
)));
289 set(obj
, MUIA_Window_DefaultObject
, classtree
);
290 DoMethod(obj
, MUIM_MultiSet
, MUIA_Disabled
, TRUE
, cwd
->cwd_RemoveButton
,
294 DoMethod(parent
, MUIM_Window_AddChildWindow
, obj
);
295 DoMethod(obj
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
, MUIV_Notify_Application
, 5, MUIM_Application_PushMethod
, parent
, 2, MUIM_Window_RemChildWindow
, obj
);
296 DoMethod(classtree
, MUIM_Notify
, MUIA_NList_Active
, MUIV_EveryTime
, obj
, 1, MUIM_OOPWin_ListChange
);
297 DoMethod(classtree
, MUIM_Notify
, MUIA_NList_DoubleClick
, MUIV_EveryTime
, obj
, 1, MUIM_OOPWin_More
);
298 DoMethod(updateButton
, MUIM_Notify
, MUIA_Pressed
, FALSE
, obj
, 1, MUIM_OOPWin_Update
);
299 DoMethod(printButton
, MUIM_Notify
, MUIA_Pressed
, FALSE
, obj
, 1, MUIM_OOPWin_Print
);
300 DoMethod(removeButton
, MUIM_Notify
, MUIA_Pressed
, FALSE
, obj
, 1, MUIM_OOPWin_Remove
);
301 DoMethod(moreButton
, MUIM_Notify
, MUIA_Pressed
, FALSE
, obj
, 1, MUIM_OOPWin_More
);
302 DoMethod(exitButton
, MUIM_Notify
, MUIA_Pressed
, FALSE
, obj
, 3, MUIM_Set
, MUIA_Window_CloseRequest
, TRUE
);
308 STATIC ULONG
mDispose( struct IClass
*cl
,
312 struct OOPWinData
*cwd
= INST_DATA(cl
, obj
);
314 set(obj
, MUIA_Window_Open
, FALSE
);
315 DoMethod(cwd
->cwd_ClassTree
, MUIM_NListtree_Clear
, NULL
, 0);
317 return (DoSuperMethodA(cl
, obj
, msg
));
320 STATIC ULONG
mUpdate( struct IClass
*cl
,
324 struct OOPWinData
*cwd
= INST_DATA(cl
, obj
);
325 struct OOPCallbackUserData ud
;
327 ApplicationSleep(TRUE
);
328 set(cwd
->cwd_ClassTree
, MUIA_NListtree_Quiet
, TRUE
);
329 DoMethod(cwd
->cwd_ClassTree
, MUIM_NListtree_Clear
, NULL
, 0);
331 ud
.ud_Tree
= cwd
->cwd_ClassTree
;
335 ReceiveList(UpdateCallback
, &ud
);
337 IterateList(UpdateCallback
, &ud
);
340 SetCountText(cwd
->cwd_ClassCount
, ud
.ud_Count
);
341 MySetContents(cwd
->cwd_ClassText
, "");
343 set(cwd
->cwd_ClassTree
, MUIA_NListtree_Quiet
, FALSE
);
344 set(cwd
->cwd_ClassTree
, MUIA_NListtree_Active
, MUIV_NListtree_Active_Off
);
345 DoMethod(obj
, MUIM_MultiSet
, MUIA_Disabled
, TRUE
, cwd
->cwd_RemoveButton
,
348 ApplicationSleep(FALSE
);
353 STATIC ULONG
mPrint( UNUSED
struct IClass
*cl
,
362 STATIC ULONG
mRemove( struct IClass
*cl
,
366 struct OOPWinData
*cwd
= INST_DATA(cl
, obj
);
367 struct MUI_NListtree_TreeNode
*tn
;
369 if ((tn
= GetActiveTreeNode(cwd
->cwd_ClassTree
)) != NULL
) {
370 struct OOPClassEntry
*ce
= (struct OOPClassEntry
*)tn
->tn_User
;
372 if (MyRequest(msgYesNo
, msgWantToRemoveClass
, ce
->ce_ClassName
)) {
373 if (MyDoCommand("RemoveClass %s", ce
->ce_Address
) == RETURN_OK
) {
374 DoMethod(obj
, MUIM_ClassesWin_Update
);
382 STATIC ULONG
mMore( struct IClass
*cl
,
387 struct OOPWinData
*cwd
= INST_DATA(cl
, obj
);
388 struct MUI_NListtree_TreeNode
*tn
;
390 if ((tn
= GetActiveTreeNode(cwd
->cwd_ClassTree
)) != NULL
) {
391 struct ClassEntry
*ce
= (struct ClassEntry
*)tn
->tn_User
;
394 if ((detailWin
= (Object
*)(OOPDetailWindowObject
,
395 MUIA_Window_ParentWindow
, (IPTR
)obj
,
398 set(detailWin
, MUIA_OOPDetailWin_Class
, ce
);
399 set(detailWin
, MUIA_Window_Open
, TRUE
);
408 STATIC ULONG
mListChange( struct IClass
*cl
,
412 struct OOPWinData
*cwd
= INST_DATA(cl
, obj
);
413 struct MUI_NListtree_TreeNode
*tn
;
415 if ((tn
= GetActiveTreeNode(cwd
->cwd_ClassTree
)) != NULL
) {
416 struct OOPClassEntry
*ce
= (struct OOPClassEntry
*)tn
->tn_User
;
418 MySetContents(cwd
->cwd_ClassText
, "%s \"%s\"", ce
->ce_Address
, ce
->ce_ClassName
);
419 DoMethod(obj
, MUIM_MultiSet
, MUIA_Disabled
, FALSE
, cwd
->cwd_RemoveButton
,
420 (clientstate
) ? NULL
: cwd
->cwd_MoreButton
,
427 DISPATCHER(OOPWinDispatcher
)
429 switch (msg
->MethodID
) {
430 case OM_NEW
: return (mNew(cl
, obj
, (APTR
)msg
));
431 case OM_DISPOSE
: return (mDispose(cl
, obj
, (APTR
)msg
));
432 case MUIM_OOPWin_Update
: return (mUpdate(cl
, obj
, (APTR
)msg
));
433 case MUIM_OOPWin_Print
: return (mPrint(cl
, obj
, (APTR
)msg
));
434 case MUIM_OOPWin_Remove
: return (mRemove(cl
, obj
, (APTR
)msg
));
435 case MUIM_OOPWin_More
: return (mMore(cl
, obj
, (APTR
)msg
));
436 case MUIM_OOPWin_ListChange
: return (mListChange(cl
, obj
, (APTR
)msg
));
439 return (DoSuperMethodA(cl
, obj
, msg
));
442 void PrintOOPClass( STRPTR filename
)
446 if ((handle
= HandlePrintStart(filename
)) != ZERO
) {
447 PrintFOneLine(handle
, txtOOPPrintHeader
);
448 IterateList(PrintCallback
, (void *)handle
);
454 void SendOOPClassList( STRPTR UNUSED dummy
)
456 IterateList(SendCallback
, NULL
);
459 APTR
MakeOOPWinClass( void )
461 return MUI_CreateCustomClass(NULL
, NULL
, ParentWinClass
, sizeof(struct OOPWinData
), ENTRY(OOPWinDispatcher
));
468 OOPBase
= OpenLibrary("oop.library", 0);
472 MetaAttrBase
= OOP_ObtainAttrBase(IID_Meta
);
481 void CleanupOOP(void)
484 OOP_ReleaseAttrBase(IID_Meta
);
487 CloseLibrary(OOPBase
);
499 void CleanupOOP(void)