Hi,
In a program I'm applying, or trying to at least, a filefilter hook.
Here follow the code parts involved:
Allocating the hook structure.
if ((__GD->gd_FileFilter = IExec->AllocSysObjectTags(ASOT_HOOK, ASOHOOK_Entry, FilterHook, TAG_END))) {
Next the ReAction specs:
LAYOUT_GetFile(GOID_FILENAME, NULL, CATTEXT(CTID_SelFile), 500), GETFILE_Drawer , GETFILE_INITIALDIRECTORY, GETFILE_FilePartOnly, TRUE, GETFILE_ReadOnly , TRUE, GETFILE_RejectIcons , TRUE, GETFILE_FilterFunc , __GD->gd_FileFilter, LAYOUT_GetFileEnd,
Then the FilterHook function:
BOOL FilterHook(struct Hook *hk UNUSED, struct FileRequester *fr, struct ExamineData *ed) { BOOL Acceptable = FALSE; if (EXD_IS_DIRECTORY(ed)) { BPTR NewLock = IDOS->Lock(fr->fr_Drawer, ACCESS_READ), OldLock = IDOS->SetCurrentDir(NewLock), File = IDOS->Open(ed->Name, MODE_OLDFILE); if (File) { Acceptable = Verify_IFF_Format(File, 0, 0); IDOS->Close(File); } IDOS->SetCurrentDir(OldLock); IDOS->UnLock(NewLock); } else { Acceptable = TRUE; } return Acceptable; }
And last the function that might cause the problem, but I don't see why it should:
BOOL Verify_IFF_Format(BPTR File, uint32 Form, uint32 Type) { INFO_ENTER BOOL Acceptable = FALSE; char Buff[12]; if (IDOS->Read(File, Buff, 12) == 12) { if (Form == 0) { if ( (*((uint32 *)&Buff[0]) == ID_FORM) || (*((uint32 *)&Buff[0]) == ID_LIST) || (*((uint32 *)&Buff[0]) == ID_CAT ) || (*((uint32 *)&Buff[0]) == ID_PROP) ) { if (Type == 0) { Acceptable = TRUE; } else { if (*((uint32 *)&Buff[8]) == Type) { Acceptable = TRUE; } } } } else { if ( (*((uint32 *)&Buff[0]) == Form) && (*((uint32 *)&Buff[8]) == Type) ) { Acceptable = TRUE; } } } INFO_VACATE return Acceptable; }
It seems like the filter is passing ALL files it get thrown to.
Why?
OldFart
Looking at the code after pressing the [ Save ] button, I noticed my error:
This filter passes everything which is not a directory, so I changed it.
The problem should have been solved now, or? Now no file is passed at all...
OldFart
Changed it back again to the first version, only with a slight alteration, as I changed from applying EXD_IS_DIRECTORY() to EXD_IS_FILE():
And now I again I get files, however not only the files I had anticipated (IFF files), but also, say, XML-files and the like.
I'm at a loss.
OldFart
The problem is that you are using the old style ASLFR_FilterFunc (GETFILE_FilterFunc) which has a pointer to a struct AnchorPathOld in the 3rd hook parameter instead of struct ExamineData. Replace GETFILE_FilterFunc with GETFILE_FilterHook and you should be okay.
A couple of other minor things to fix:
1) Although it won't matter in practice, the return value of the hook function should be ULONG and not BOOL.
2) You don't check the return value of Lock() function for failure. This means that if it fails your code will look for a file with the same name in "SYS:" (IIRC).
It works! Thanks a lot!
As I was working on a project that had been sleeping for more then a decade, I overlooked the deprecation of GETFILE_FilterFunc.
About the return value:
The AutoDocs on the getfile gadget do not mention anything about it, but as there is a near one-to-one relationship with asl.library I peaked at the corresponding tag in the asl-autodocs and this is what it reads:
ASLFR_FilterHook (struct Hook *)
A function to call for each file and directory encountered.
If the function returns TRUE the file or directory is included
in the list. Otherwise it is rejected and not displayed.
(V52.27)
The function has the following signature:
BOOL Filter(struct Hook *hook,
const struct FileRequester *req,
const struct ExamineData *data);
If multiple filtering methods are employed simultaneously,
the hook specified by this tag will always take precedence.
So, to me it seems that a BOOL is in place there.
And finally: I implemented a check on the Lock() function. A grave omission.
OldFart
I know that the autodoc says BOOL, but the hook function is called via CallHookPkt() which treats the return value as ULONG (or uint32 or in AmigaOS 4.x terms).
If you specify the return value as BOOL then the following code will give a warning with newer gcc:s
hook.h_Entry = (HOOKFUNC)FilterHook;
The fact that the autodoc specifies it as BOOL just means that the high 16 bits of the return value are ignored as it is assigned and truncated into a 16-bit BOOL variable.