The FileSelector Object: 3.8 File Selector Instance Data: Searching Via Callback Routine

Up: GEOS SDK TechDocs | Up | Prev: 3.7 Matching a File's File Attributes | Next: 3.9 Resetting a Filter
MSG_GEN_FILE_SELECTOR_GET_FILTER_ROUTINE, GenFileSelectorFilterRoutine

If the built-in search limitations do not provide the functionality you require, you can set up a callback routine that the File Selector will call for each file or subdirectory in a directory scan. This routine will serve as the final filter for each file; if a file passes all other filters, it will be subjected to your routine. This procedure adds overhead to any scan, of course, so you should try to use the built-in File Selector functions whenever possible.

To set the File Selector to use the callback functionality, you must set FSFC_FILTER_FILE in the GFSI_fileCriteria field. If your callback routine is written in C, you must also set FSFC_FILTER_IS_C; the routine must also follow the Pascal calling convention.

In order to take advantage of the callback functionality, you must first subclass GenFileSelectorClass to handle the message MSG_GEN_FILE_SELECTOR_GET_FILTER_ROUTINE , which the File Selector will send to itself before beginning the directory scan. Your handler should return the address of the callback routine along with a pointer to an array of attributes that will be passed to it.

The callback routine can assume that if it is being called, the file has passed all other filters--the callback is therefore the last word on acceptance or rejection of the file. In essence, the callback is asked whether the file should be rejected: It should return the constant TRUE if the file is to be rejected but FALSE if it is not to be rejected.

As mentioned above, you can designate an array of extended file attributes that will be passed to the callback routine. This array contains a number of FileExtAttrDesc structures, each of which defines a certain attribute and some extra data for the attribute. This structure is shown below:

typedef struct {
    FileExtendedAttribute FEAD_attr;
				/* file attribute to
				 * get or set */
    void		* FEAD_value;
				/* pointer to a buffer
				 * or new value */
    word		FEAD_size;		/* size of buffer or
				 * new value */
    char		* FEAD_name;
				/* if custom attribute,
				 * pointer to name */
} FileExtAttrDesc;

In the above context, FEAD_value is meaningless and FEAD_size is the number of bytes required to hold the value of the attribute. Note that this array is not passed to the callback routine; instead, it specifies the structure and composition of the values that will be.

An example of filtering files using a callback routine is shown in Filtering Files Via a Callback Routine . The FileExtAttrDesc structure is defined and detailed in the File System chapter.

Code Display 14-10 Filtering Files Via a Callback Routine

/*******************************************************************************
 * This is a sample handler for MSG_GEN_FILE_SELECTOR_GET_FILTER_ROUTINE.
 * You should be able to use this code in your subclass. Note that the routine
 * name "FilterFileSelectorRoutine" is application-specific; it can be whatever
 * you want. It must be declared as static Boolean, however. See below.
 * PARAMETERS: 
 * void (GenFileSelectorGetFilterRoutineResults *filter) 
 *******************************************************************************/
@method FilterFileSelectorClass, MSG_GEN_FILE_SELECTOR_GET_FILTER_ROUTINE {
    /* We need to return a virtual pointer to the filter routine so the
     * file selector can lock and unlock the routine's code resource as
     * appropriate. Unfortunately, the compiler optimizes the simple
     * implementation (just assigning filter->filterRoutine the address of
     * the routine) by storing CS for the segment, which is unhelpful. So
     * we need a static variable holding the routine's address instead. */
    static GenFileSelectorFilterRoutine *const filterRoutine =
					&FilterFileSelectorRoutine;
    /* Specify the address of the routine to call. It need not be locked into
     * memory, as the GenFileSelector will do that for us. */
    filter->filterRoutine = filterRoutine;
    /* Specify the additional attributes we need to look at in our filter
     * routine. As with the filterRoutine, these need not be in fixed or
     * locked memory. */
    filter->filterAttrs = &filterFileSelectorFilterAttrs;
}
/*******************************************************************************
 * This is a sample File Selector callback routine. It may be called whatever
 * you want and must be declared static Boolean.
 * This routine is called once per file or directory that passes all other File
 * Selector filters. This routine is limited to examining the attributes of the
 * file. It may not do anything that could cause the File Selector's instance chunk
 * to move in memory.
 * Return: TRUE to reject the file, FALSE to accept the file.
 *******************************************************************************/
static Boolean FilterFileSelectorRoutine(optr oself,
				FileEnumCallbackData *fecd, word frame)
/* The code of the routine is not included here; to see it, look at the FSFilter
 * sample application. */
	/* Following is the array of attributes examined by our filter routine.
	 * This array contains an arbitrary number of elements, the last of which
	 * has FEA_END_OF_LIST as its FEAD_attr field. FEAD_value is unused in this
	 * context. FEAD_size is set to the total number of bytes needed for each
	 * attribute. 
	 * Each structure's fields are FEAD_attr, FEAD_value, FEAD_size,
	 * and FEAD_name */
const FileExtAttrDesc filterFileSelectorFilterAttrs[] = {
    { FEA_NAME, 0, sizeof(FileLongName), NULL },
    { FEA_FILE_ATTR, 0, sizeof(FileAttrs), NULL },
    { FEA_FILE_TYPE, 0, sizeof(GeosFileType), NULL },
    { FEA_END_OF_LIST, 0, 0, NULL }
};

MSG_GEN_FILE_SELECTOR_GET_FILTER_ROUTINE

void	MSG_GEN_FILE_SELECTOR_GET_FILTER_ROUTINE(
        GenFileSelectorGetFilterRoutineResults *filter);

This message returns the address of the callback routine used by the File Selector as well as the array of FileExtAttrDesc structures specifying the callback's parameters.

For the callback function to be used, you must set FSFC_FILE_FILTER in the File Selector's GFSI_fileCriteria instance data field. If your callback routine is in C, you must also set FSFC_FILTER_IS_C. In addition, the callback routine must follow the Pascal calling convention.

Source: Sent by the File Selector object to itself before calling FileEnum() . Also may be used by other objects to retrieve the callback information for the File Selector.

Destination: Any GenFileSelector object.

Parameters: filter A pointer to an empty return value structure. This structure is detailed below.

Return: The structure pointed to by filter must be filled by this method.

Structures: The single parameter is a pointer to an empty structure of type GenFileSelectorGetFilterRoutineResults . This structure has two parts: filterRoutine is a pointer to your callback routine, and filterAttrs is a pointer to an array of FileExtAttrDesc structures. You must fill in this structure in your handler so the File Selector knows how to call your callback routine. The structure is shown below:

typedef struct {
    GenFileSelectorFilterRoutine						*filterRoutine;
    const FileExtAttrDesc						*filterAttrs;
} GenFileSelectorGetFilterRoutineResults;

Interception: If a callback routine is to be used, you must subclass and handle this message to return the proper structures.

Tips: If your callback has no requirements other than the file name, you can pass NULL in the filterAttrs field of filter .

Warnings: The handler for this message must return a virtual segment for the callback routine in filter 's filterRoutine field. This can cause problems with most compilers; to avoid these problems, set a static variable in your method as shown in Filtering Files Via a Callback Routine , below (taken from the FSFilter sample application).

See Also: FileEnum()

GenFileSelectorFilterRoutine()

Boolean	GenFileSelectorFilterRoutine(
        optr			oself,
        FileEnumCallbackData			*fecd,
        word			frame);

This routine is defined by your application and is called for each file in a directory scan. It may be of any name of your choice as shown in Filtering Files Via a Callback Routine . It serves as the final filter; when called, it can assume the subject file has passed all other filters applied. This routine is set up and executed in the same manner as the callback routine for FileEnum() ; see the File System chapterfor complete details.

Parameters: oself The optr of the File Selector object

fecd
A pointer to a FileEnumCallbackData structure.
frame
An inherited stack frame passed by FileEnum() to each of its helper routines.

Return: Your callback must return the constant FALSE if the file should be accepted, TRUE if the file should be rejected.

Warnings: Your routine must not do anything that may cause the File Selector or its object block to move in memory (adding variable data fields, for instance).

See Also: FileEnum()


Up: GEOS SDK TechDocs | Up | Prev: 3.7 Matching a File's File Attributes | Next: 3.9 Resetting a Filter