Synch'd Scout with source from its CVS repository.
[AROS-Contrib.git] / scout / source / classes / scout_oop.c
blobf09bec851e610aad3f0feba302438b0e9cc52ac3
1 /**
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
9 * any later version.
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 */
34 #ifdef __AROS__
36 #include <oop/oop.h>
37 #include <proto/oop.h>
39 struct Library *OOPBase;
40 OOP_AttrBase MetaAttrBase;
42 #endif
44 struct OOPWinData {
45 TEXT cwd_Title[WINDOW_TITLE_LENGTH];
46 APTR cwd_ClassTree;
47 APTR cwd_ClassText;
48 APTR cwd_ClassCount;
49 APTR cwd_RemoveButton;
50 APTR cwd_MoreButton;
53 struct OOPCallbackUserData {
54 APTR ud_Tree;
55 ULONG ud_Count;
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;
80 } else {
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;
98 LONG cmp;
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);
106 return cmp;
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;
116 if (ce) {
117 return stricmp(msg->User, ce->ce_Address);
118 } else {
119 return ~0;
122 MakeStaticHook(classtree_findhook, classtree_findfunc);
125 STATIC void ReceiveList( void (* callback)( struct OOPClassEntry *ce, void *userData ),
126 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);
145 } else {
146 _snprintf(buf, ADDRESS_LENGTH, "$%08lx", dispentry);
150 STATIC void IterateList( void (* callback)( struct OOPClassEntry *ce, void *userData ),
151 void *userData )
154 #ifdef __AROS__
156 OOP_Class *myclass;
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 },
163 {TAG_DONE , 0 }
166 if ((myclass = OOP_NewObject(NULL, CLID_SIMeta, mytags)) != NULL) {
167 struct List *clist;
168 OOP_Class *cl;
169 struct MinList tmplist;
170 struct OOPClassEntry *ce;
172 NewList((struct List *)&tmplist);
174 OOP_AddClass(myclass);
176 Forbid();
178 clist = FindListOfNode(&myclass->ClassNode);
179 ITERATE_LIST(clist, OOP_Class *, cl) {
180 if (cl != myclass) {
181 if ((ce = AllocVec(sizeof(struct OOPClassEntry), MEMF_CLEAR)) != NULL) {
182 ce->ce_Addr = cl;
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));
186 } else {
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);
204 Permit();
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);
215 #endif
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)))
232 return str;
233 else
234 return str + 2;
237 STATIC void PrintCallback( struct OOPClassEntry *ce,
238 void *userData )
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,
251 Object *obj,
252 struct opSet *msg )
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)),
273 End,
274 End,
275 TAG_MORE, msg->ops_AttrList)) != NULL)
277 struct OOPWinData *cwd = INST_DATA(cl, obj);
278 APTR parent;
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,
291 cwd->cwd_MoreButton,
292 NULL);
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);
305 return (ULONG)obj;
308 STATIC ULONG mDispose( struct IClass *cl,
309 Object *obj,
310 Msg msg )
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,
321 Object *obj,
322 UNUSED Msg msg )
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;
332 ud.ud_Count = 0;
334 if (clientstate) {
335 ReceiveList(UpdateCallback, &ud);
336 } else {
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,
346 cwd->cwd_MoreButton,
347 NULL);
348 ApplicationSleep(FALSE);
350 return 0;
353 STATIC ULONG mPrint( UNUSED struct IClass *cl,
354 UNUSED Object *obj,
355 UNUSED Msg msg )
357 PrintOOPClass(NULL);
359 return 0;
362 STATIC ULONG mRemove( struct IClass *cl,
363 Object *obj,
364 UNUSED Msg msg )
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);
379 return 0;
382 STATIC ULONG mMore( struct IClass *cl,
383 Object *obj,
384 UNUSED Msg msg )
386 if (!clientstate) {
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;
392 APTR detailWin;
394 if ((detailWin = (Object *)(OOPDetailWindowObject,
395 MUIA_Window_ParentWindow, (IPTR)obj,
396 End)) != NULL) {
397 COLLECT_RETURNIDS;
398 set(detailWin, MUIA_OOPDetailWin_Class, ce);
399 set(detailWin, MUIA_Window_Open, TRUE);
400 REISSUE_RETURNIDS;
405 return 0;
408 STATIC ULONG mListChange( struct IClass *cl,
409 Object *obj,
410 UNUSED Msg msg )
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,
421 NULL);
424 return 0;
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 )
444 BPTR handle;
446 if ((handle = HandlePrintStart(filename)) != ZERO) {
447 PrintFOneLine(handle, txtOOPPrintHeader);
448 IterateList(PrintCallback, (void *)handle);
451 HandlePrintStop();
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));
464 #ifdef __AROS__
466 BOOL InitOOP(void)
468 OOPBase = OpenLibrary("oop.library", 0);
469 if (!OOPBase)
470 return FALSE;
472 MetaAttrBase = OOP_ObtainAttrBase(IID_Meta);
474 if (MetaAttrBase)
475 return TRUE;
477 CleanupOOP();
478 return FALSE;
481 void CleanupOOP(void)
483 if (MetaAttrBase)
484 OOP_ReleaseAttrBase(IID_Meta);
486 if (OOPBase) {
487 CloseLibrary(OOPBase);
488 OOPBase = NULL;
492 #else
494 BOOL InitOOP(void)
496 return TRUE;
499 void CleanupOOP(void)
503 #endif