Scout: handle address NULL. This avoids a segfault when clicking
[AROS-Contrib.git] / scout / source / classes / scout_functions.c
blobe33ed00e154599514c5ca1d9c2fc54ec3e44288d
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 <sonic_amiga@mail.ru>
27 #include "system_headers.h"
29 struct FunctionsWinData {
30 TEXT fwd_Title[WINDOW_TITLE_LENGTH];
31 APTR fwd_FunctionsList;
32 APTR fwd_FunctionsText;
33 APTR fwd_FunctionsCount;
34 APTR fwd_DisassembleButton;
37 struct MUIP_FunctionsWin_ShowFunctionsMessage {
38 STACKED ULONG MethodID;
39 STACKED ULONG nodeType;
40 STACKED APTR base;
41 STACKED STRPTR name;
44 struct FunctionsEntry {
45 APTR fe_Address;
46 TEXT fe_AddressStr[ADDRESS_LENGTH];
47 ULONG fe_Offset;
48 TEXT fe_OffsetDec[ADDRESS_LENGTH];
49 TEXT fe_OffsetHex[ADDRESS_LENGTH];
50 TEXT fe_FuncName[FILENAME_LENGTH];
53 HOOKPROTONHNO(funclist_con2func, IPTR, struct NList_ConstructMessage *msg)
55 return AllocListEntry(msg->pool, msg->entry, sizeof(struct FunctionsEntry));
57 MakeStaticHook(funclist_con2hook, funclist_con2func);
59 HOOKPROTONHNO(funclist_des2func, void, struct NList_DestructMessage *msg)
61 FreeListEntry(msg->pool, &msg->entry);
63 MakeStaticHook(funclist_des2hook, funclist_des2func);
65 HOOKPROTONHNO(funclist_dsp2func, void, struct NList_DisplayMessage *msg)
67 struct FunctionsEntry *fe = (struct FunctionsEntry *)msg->entry;
69 if (fe) {
70 msg->strings[0] = fe->fe_OffsetDec;
71 msg->strings[1] = fe->fe_OffsetHex;
72 msg->strings[2] = fe->fe_AddressStr;
73 msg->strings[3] = fe->fe_FuncName;
74 } else {
75 msg->strings[0] = txtOffset;
76 msg->strings[1] = txtHexadecimal;
77 msg->strings[2] = txtAddress;
78 msg->strings[3] = txtName;
79 msg->preparses[0] = (STRPTR)MUIX_B;
80 msg->preparses[1] = (STRPTR)MUIX_B;
81 msg->preparses[2] = (STRPTR)MUIX_B;
82 msg->preparses[3] = (STRPTR)MUIX_B;
85 MakeStaticHook(funclist_dsp2hook, funclist_dsp2func);
87 STATIC LONG funclist_cmp2colfunc( struct FunctionsEntry *fe1,
88 struct FunctionsEntry *fe2,
89 ULONG column )
91 switch (column) {
92 default:
93 case 0:
94 case 1: return (IPTR)fe1->fe_Offset - (IPTR)fe2->fe_Offset;
95 case 2: return (IPTR)fe1->fe_Address - (IPTR)fe2->fe_Address;
96 case 3: return stricmp(fe1->fe_FuncName, fe2->fe_FuncName);
100 HOOKPROTONHNO(funclist_cmp2func, LONG, struct NList_CompareMessage *msg)
102 LONG cmp;
103 struct FunctionsEntry *fe1, *fe2;
104 ULONG col1, col2;
106 fe1 = (struct FunctionsEntry *)msg->entry1;
107 fe2 = (struct FunctionsEntry *)msg->entry2;
108 col1 = msg->sort_type & MUIV_NList_TitleMark_ColMask;
109 col2 = msg->sort_type2 & MUIV_NList_TitleMark2_ColMask;
111 if ((ULONG)msg->sort_type == MUIV_NList_SortType_None) return 0;
113 if (msg->sort_type & MUIV_NList_TitleMark_TypeMask) {
114 cmp = funclist_cmp2colfunc(fe2, fe1, col1);
115 } else {
116 cmp = funclist_cmp2colfunc(fe1, fe2, col1);
119 if (cmp != 0 || col1 == col2) return cmp;
121 if (msg->sort_type2 & MUIV_NList_TitleMark2_TypeMask) {
122 cmp = funclist_cmp2colfunc(fe2, fe1, col2);
123 } else {
124 cmp = funclist_cmp2colfunc(fe1, fe2, col2);
127 return cmp;
129 MakeStaticHook(funclist_cmp2hook, funclist_cmp2func);
131 STATIC IPTR mNew( struct IClass *cl,
132 Object *obj,
133 struct opSet *msg )
135 APTR funclist, functext, funccount, disasmButton, exitButton;
137 if ((obj = (Object *)DoSuperNew(cl, obj,
138 MUIA_Window_ID, MakeID('.','L','F','T'),
139 WindowContents, VGroup,
140 Child, (IPTR)MyNListviewObject(&funclist, MakeID('F','T','L','V'), "BAR P=" MUIX_R ",BAR P=" MUIX_R ",BAR,BAR", &funclist_con2hook, &funclist_des2hook, &funclist_dsp2hook, &funclist_cmp2hook, TRUE),
141 Child, (IPTR)MyBelowListview(&functext, &funccount),
143 Child, (IPTR)MyVSpace(4),
145 Child, (IPTR)HGroup, MUIA_Group_SameSize, TRUE,
146 Child, (IPTR)(disasmButton = MakeButton(txtDisassemble)),
147 Child, (IPTR)(exitButton = MakeButton(txtExit)),
148 End,
149 End,
150 TAG_MORE, msg->ops_AttrList)) != NULL)
152 struct FunctionsWinData *fwd = INST_DATA(cl, obj);
153 APTR parent;
155 fwd->fwd_FunctionsList = funclist;
156 fwd->fwd_FunctionsText = functext;
157 fwd->fwd_FunctionsCount = funccount;
158 fwd->fwd_DisassembleButton = disasmButton;
160 parent = (APTR)GetTagData(MUIA_Window_ParentWindow, (IPTR)NULL, msg->ops_AttrList);
162 set(obj, MUIA_Window_DefaultObject, funclist);
163 set(disasmButton, MUIA_Disabled, TRUE);
165 DoMethod(parent, MUIM_Window_AddChildWindow, obj);
166 DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, MUIV_Notify_Application, 5, MUIM_Application_PushMethod, parent, 2, MUIM_Window_RemChildWindow, obj);
167 DoMethod(funclist, MUIM_Notify, MUIA_NList_DoubleClick, MUIV_EveryTime, obj, 1, MUIM_FunctionsWin_Disassemble);
168 DoMethod(funclist, MUIM_Notify, MUIA_NList_Active, MUIV_EveryTime, obj, 1, MUIM_FunctionsWin_ListChange);
169 DoMethod(disasmButton, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, MUIM_FunctionsWin_Disassemble);
170 DoMethod(exitButton, MUIM_Notify, MUIA_Pressed, FALSE, obj, 3, MUIM_Set, MUIA_Window_CloseRequest, TRUE);
171 DoMethod(funclist, MUIM_NList_Sort3, MUIV_NList_Sort3_SortType_1, MUIV_NList_SortTypeAdd_None, MUIV_NList_Sort3_SortType_Both);
174 return (IPTR)obj;
177 STATIC IPTR mDispose( struct IClass *cl,
178 Object *obj,
179 Msg msg )
181 struct FunctionsWinData *fwd = INST_DATA(cl, obj);
183 set(obj, MUIA_Window_Open, FALSE);
184 DoMethod(fwd->fwd_FunctionsList, MUIM_NList_Clear);
186 return (DoSuperMethodA(cl, obj, msg));
189 STATIC IPTR mShowFunctions( struct IClass *cl,
190 Object *obj,
191 Msg msg )
193 struct FunctionsWinData *fwd = INST_DATA(cl, obj);
194 struct MUIP_FunctionsWin_ShowFunctionsMessage *sfm = (struct MUIP_FunctionsWin_ShowFunctionsMessage *)msg;
196 if (sfm->nodeType != MUIV_FunctionsWin_NodeType_Resource ||
197 (stricmp(sfm->name, FSRNAME) != 0 &&
198 //stricmp(sfm->name, CARDRESNAME) != 0 &&
199 stricmp(sfm->name, KEYMAPRESNAME) != 0)) {
201 struct FunctionsEntry *fe;
203 if ((fe = tbAllocVecPooled(globalPool, sizeof(struct FunctionsEntry))) != NULL) {
204 struct Library *lib = (struct Library *)sfm->base;
205 ULONG max, offset;
206 BOOL useIdLib = (IdentifyBase != NULL);
208 max = lib->lib_NegSize;
210 set(fwd->fwd_FunctionsList, MUIA_NList_Quiet, TRUE);
212 NoReqOn();
214 for (offset = LIB_VECTSIZE; offset <= max; offset += LIB_VECTSIZE) {
215 #ifdef __AROS__
216 fe->fe_Address = __AROS_GETVECADDR (lib, offset / LIB_VECTSIZE);
218 if (fe->fe_Address) {
219 if (points2ram(fe->fe_Address)) {
220 _snprintf(fe->fe_AddressStr, sizeof(fe->fe_AddressStr), MUIX_PH ADDRESS_FORMAT MUIX_PT, fe->fe_Address);
221 } else {
222 _snprintf(fe->fe_AddressStr, sizeof(fe->fe_AddressStr), ADDRESS_FORMAT, fe->fe_Address);
224 } else {
225 fe->fe_Address = (APTR)-1;
226 stccpy(fe->fe_AddressStr, txtNoJump, sizeof(fe->fe_AddressStr));
228 #else
229 struct JumpEntry *je;
231 je = (struct JumpEntry *)((UBYTE *)lib - offset);
233 #ifdef __MORPHOS__
234 if (je->je_JMPInstruction == 0x4ef9 || je->je_JMPInstruction == 0x4afc) {
235 #else
236 if (je->je_JMPInstruction == 0x4ef9) {
237 #endif
238 fe->fe_Address = je->je_JumpAddress;
239 if (points2ram(je->je_JumpAddress)) {
240 _snprintf(fe->fe_AddressStr, sizeof(fe->fe_AddressStr), MUIX_PH "$%08lx" MUIX_PT, je->je_JumpAddress);
241 } else {
242 _snprintf(fe->fe_AddressStr, sizeof(fe->fe_AddressStr), "$%08lx", je->je_JumpAddress);
244 } else {
245 fe->fe_Address = (APTR)-1;
246 stccpy(fe->fe_AddressStr, txtNoJump, sizeof(fe->fe_AddressStr));
248 #endif
250 fe->fe_Offset = offset;
251 _snprintf(fe->fe_OffsetDec, sizeof(fe->fe_OffsetDec), "-%ld", offset);
252 _snprintf(fe->fe_OffsetHex, sizeof(fe->fe_OffsetHex), "-$%04lx", offset);
254 if ((offset <= LIB_VECTSIZE * 6 && sfm->nodeType == MUIV_FunctionsWin_NodeType_Device) ||
255 (offset <= LIB_VECTSIZE * 4 && sfm->nodeType == MUIV_FunctionsWin_NodeType_Library)) {
256 CONST_STRPTR help;
258 switch (offset) {
259 case LIB_VECTSIZE * 1: help = "Open"; break;
260 case LIB_VECTSIZE * 2: help = "Close"; break;
261 case LIB_VECTSIZE * 3: help = "Expunge"; break;
262 case LIB_VECTSIZE * 4: help = "ExtFunc"; break;
263 case LIB_VECTSIZE * 5: help = "BeginIO"; break;
264 case LIB_VECTSIZE * 6: help = "AbortIO"; break;
265 default: help = ""; break;
267 stccpy(fe->fe_FuncName, (TEXT *)help, sizeof(fe->fe_FuncName));
268 } else if (useIdLib) {
269 ULONG error;
270 ULONG id_offset;
272 if (sfm->name) {
273 #ifdef __AROS__
274 /* identify.library on AROS assumes LIB_VECTSIZE of 6 */
275 id_offset = (offset / LIB_VECTSIZE) * 6;
276 #else
277 id_offset = offset;
278 #endif
279 if (stricmp(sfm->name, CIAANAME) == 0 || stricmp(sfm->name, CIABNAME) == 0) {
280 error = IdFunctionTags((STRPTR)"cia.resource", id_offset,
281 IDTAG_FuncNameStr, (IPTR)fe->fe_FuncName,
282 IDTAG_StrLength, sizeof(fe->fe_FuncName),
283 TAG_DONE);
284 } else if (stricmp(sfm->name, CARDRESNAME) == 0) {
285 error = IdFunctionTags((STRPTR)"cardres.resource", id_offset,
286 IDTAG_FuncNameStr, (IPTR)fe->fe_FuncName,
287 IDTAG_StrLength, sizeof(fe->fe_FuncName),
288 TAG_DONE);
289 } else {
290 error = IdFunctionTags(sfm->name, id_offset,
291 IDTAG_FuncNameStr, (IPTR)fe->fe_FuncName,
292 IDTAG_StrLength, sizeof(fe->fe_FuncName),
293 TAG_DONE);
295 switch (error) {
296 case IDERR_NOFD:
297 stccpy(fe->fe_FuncName, txtNoFDFile, sizeof(fe->fe_FuncName));
298 break;
300 case IDERR_NOMEM:
301 fe->fe_FuncName[0] = 0x00;
302 useIdLib = FALSE;
303 break;
305 case IDERR_OFFSET:
306 stccpy(fe->fe_FuncName, txtNoFunctionEntry, sizeof(fe->fe_FuncName));
307 break;
309 } else {
310 stccpy(fe->fe_FuncName, txtNoFDFile, sizeof(fe->fe_FuncName));
312 } else {
313 fe->fe_FuncName[0] = 0x00;
316 InsertBottomEntry(fwd->fwd_FunctionsList, fe);
319 NoReqOff();
321 set(fwd->fwd_FunctionsList, MUIA_NList_Quiet, FALSE);
322 SetCountText(fwd->fwd_FunctionsCount, max / LIB_VECTSIZE);
324 set(obj, MUIA_Window_Title, MyGetChildWindowTitle(txtFunctionsTitle, sfm->name, fwd->fwd_Title, sizeof(fwd->fwd_Title)));
327 tbFreeVecPooled(globalPool, fe);
330 set(obj, MUIA_Window_Open, TRUE);
332 return 0;
335 STATIC IPTR mListChange( struct IClass *cl,
336 Object *obj,
337 UNUSED Msg msg )
339 struct FunctionsWinData *fwd = INST_DATA(cl, obj);
340 struct FunctionsEntry *fe;
342 if ((fe = (struct FunctionsEntry *)GetActiveEntry(fwd->fwd_FunctionsList)) != NULL) {
343 if (fe->fe_FuncName[0] == '<') {
344 MySetContents(fwd->fwd_FunctionsText, "%s %s", fe->fe_OffsetDec, fe->fe_FuncName);
345 } else {
346 MySetContents(fwd->fwd_FunctionsText, "%s %s()", fe->fe_OffsetDec, fe->fe_FuncName);
348 set(fwd->fwd_DisassembleButton, MUIA_Disabled, (clientstate || fe->fe_Address == (APTR)-1 || fe->fe_Address == NULL));
351 return 0;
354 STATIC IPTR mDisassemble( struct IClass *cl,
355 Object *obj,
356 UNUSED Msg msg )
358 struct FunctionsWinData *fwd = INST_DATA(cl, obj);
359 struct FunctionsEntry *fe;
361 if ((fe = (struct FunctionsEntry *)GetActiveEntry(fwd->fwd_FunctionsList)) != NULL) {
362 APTR disasmWin;
364 if ((disasmWin = (Object *)DisassemblerWindowObject,
365 MUIA_Window_ParentWindow, (IPTR)obj,
366 MUIA_DisassemblerWin_Address, (IPTR)fe->fe_Address,
367 End) != NULL) {
368 COLLECT_RETURNIDS;
369 DoMethod(disasmWin, MUIM_DisassemblerWin_Disassemble);
370 set(disasmWin, MUIA_Window_Open, TRUE);
371 REISSUE_RETURNIDS;
375 return 0;
378 DISPATCHER(FunctionsWinDispatcher)
380 switch (msg->MethodID) {
381 case OM_NEW: return (mNew(cl, obj, (APTR)msg));
382 case OM_DISPOSE: return (mDispose(cl, obj, (APTR)msg));
383 case MUIM_FunctionsWin_ShowFunctions: return (mShowFunctions(cl, obj, (APTR)msg));
384 case MUIM_FunctionsWin_ListChange: return (mListChange(cl, obj, (APTR)msg));
385 case MUIM_FunctionsWin_Disassemble: return (mDisassemble(cl, obj, (APTR)msg));
388 return (DoSuperMethodA(cl, obj, msg));
391 APTR MakeFunctionsWinClass( void )
393 return MUI_CreateCustomClass(NULL, NULL, ParentWinClass, sizeof(struct FunctionsWinData), ENTRY(FunctionsWinDispatcher));