@DATABASE AmigaMail @NODE MAIN "I-7: The ASL Library" @TOC "Table_of_Contents/I" by John Orr The asl.library library provides the release 2.0 Amiga OS with system standard file and font requesters. Any application that needs to use a file or font requester should use asl.library requesters because they are easy to implement, they are easy for the user to learn, and because they are the same from one application to the next, they make applications more user friendly. This article requires a general understanding of several Amiga concepts: TagItems and TagLists (see the Utility library Autodocs), Intuition screens and windows, some of the graphics.library's font structures, and AmigaDOS pattern matching. @{" Opening a Simple File Requester " link I-7-1} @{" File Pattern Matching and Multiple Selects " link I-7-2} @{" The ASL_Window Tag " link I-7-3} @{" The Save Requester " link I-7-4} @{" A Directory Requester " link I-7-5} @{" The Font Requester " link I-7-6} @{" The ASL_HookFunc Tag " link I-7-7} @ENDNODE @NODE I-7-1 "Opening a Simple File Requester" Using an ASL requester requires the use of three functions: myrequester = APTR AllocAslRequest( ULONG type, struct TagItem *tagList ); void FreeAslRequest( APTR request ); made_selection = BOOL AslRequest( APTR request, struct TagItem *tagList ); An ASL requester is based on a FileRequester or a FontRequester structure. Programs must allocate this structure with AllocAslRequest() (or AllocFileRequest()see the asl.library Autodoc for more on this function). Currently, the type field (from the above prototype) can be one of two values (as defined in ), ASL_FileRequest, to ask for a FileRequester structure, or ASL_FontRequest, to ask for a FontRequester structure. The values in this structure are for read access only. Any changes to them are carried out through asl.library function calls. The FreeAslRequest() function deallocates an ASL requester structure. struct FileRequester { /* (from ) */ APTR rf_Reserved1; BYTE *rf_File; /* Filename pointer */ BYTE *rf_Dir; /* Directory name pointer */ CPTR rf_Reserved2; UBYTE rf_Reserved3; UBYTE rf_Reserved4; APTR rf_Reserved5; WORD rf_LeftEdge,rf_TopEdge; /* Preferred window pos */ WORD rf_Width,rf_Height; /* Preferred window size */ WORD rf_Reserved6; LONG rf_NumArgs; /* A-la WB Args, for multiselects */ struct WBArg *rf_ArgList; APTR rf_UserData; /* Applihandle (you may write!!) */ APTR rf_Reserved7; APTR rf_Reserved8; BYTE *rf_Pat; /* Pattern match pointer */ }; /* note - more reserved fields follow */ Based on the requester structure passed to it, AslRequest() brings up a font or file requester. When the user makes a selection, AslRequest returns a value. If it returns anything but FALSE (0), the user selected a file (or a font). AslRequest() returns FALSE if the user cancels the requester or the requester failed for some reason. Both AslRequest() and AllocAslRequest() accept a tag list. This tag list is used to set the values in the FileRequester (or FontRequester) structure. The C code example @{"SimpleFR.c" link I-7/SimpleFR.c/MAIN} at the end of this article uses the following tags (all the ASL tags are defined in ): ASL_Hail ASL_Width ASL_Height ASL_LeftEdge ASL_TopEdge ASL_OKText ASL_CancelText ASL_File ASL_Dir ASL_Hail supplies a requester with a string to placed in the title bar of the requester window. ASL_Width, _Height, _LeftEdge, and _TopEdge describe the initial dimensions and position of the requester window. ASL_OKText and ASL_CancelText provide alternate strings for the ``OK'' and ``Cancel'' gadgets. Currently, the size of these gadgets limits the length of the names to about six characters. The two remaining tags from the above list, ASL_File and ASL_Dir, tags are specific to file requesters. They supply the initial file and directory names for the file requester. For a file requester, if AslRequest() returns anything but FALSE, @{"SimpleFR.c" link I-7/SimpleFR.c/MAIN} looks at the FileRequester's rf_File and rf_Dir fields to get the name and directory of the file the user selected. Note that the requester allows the user to type in a name for the file and directory, which makes it possible for a file requester to return a file and directory that do not (currently) exist. In the case of a save requester (discussed a little later), the requester can create that non-existent directory. @{" Figure 1 - The SimpleFR.c file requester " link "I-7/simpleFR.ilbm/MAIN"} The @{"simpleFR.c" link I-7/simpleFR.c/MAIN} example (and the rest of the ASL examples for that matter) may be a little misleading because it only uses the requester once. Any application that needs a requester should allocate the requester only once and pop up that requester every time the application needs one. If instead, the application allocated, used, and deallocated a requester each time it needed one, all of the settings the user left in the requester (like the names the user last typed into the drawer or file string gadgets) would be reset to their initial values. By reusing a requester, the values stored in it are preserved. Although retaining previous requester values from one request to another preserves user preferences, it also preserves other values stored in the requester structure. The file and font requester structures contain many private fields that toggle various features of the ASL requesters (those features are set via tags). If a program sets up a file requester with a specific feature, after the requester returns, the file requester structure is still set up with the specific feature. The next time the application wants to use that file requester without that specific feature, it must explicitly turn that feature off in the subsequent AslRequest() call. @ENDNODE @NODE I-7-2 "File Pattern Matching and Multiple Selects" A file requester can filter out certain file and directory entries using dos.library's ``wildcarding''. Turning on a file requester's ``wildcarding'' requires using the ASL_FuncFlags tag. This tag passes a bit field to a requester to set several options. The options are specific to the type of requester (file or font). The bitmasks are defined in . The ASL_FuncFlags's FILF_PATGAD flag toggles the file requester's ``Pattern'' gadget. The user can type an AmigaDOS wildcard pattern into this gadget that the requester uses to limit the file names that appear in the requester. An application can supply the ``Pattern'' gadget with a default pattern matching string using the ASL_Pattern tag. Another feature of the ASL file requester is multiple selection. When an application sets up a file requester, it can set the FILF_MULTISELECT flag in the ASL_FuncFlags tag that allows the user to select several files at once. When the user selects several files in the requester, the FileRequester's rf_NumArgs field contains the number of files selected. When the FILF_MULTISELECT bit is not set, rf_NumArgs is 0. If rf_NumArgs is not zero, rf_ArgList is a base pointer to an array of WBArg structures (defined in ). There is a WBArg structure for each file the user selected. The example @{"FilePat.c" link I-7/FilePat.c/MAIN} illustrates multiple selection. @{"FilePat.c" link I-7/FilePat.c/MAIN} also introduces a new function and a new tag. APTR AllocAslRequestTags( unsigned long type, Tag Tag1, ... ); BOOL AslRequestTags( APTR request, Tag Tag1, ... ); @{"FilePat.c" link I-7/FilePat.c/MAIN} uses AllocAslRequestTags() instead of AllocAslRequest() to allocate and set up the file requester. AllocAslRequestTags() is an Amiga.lib function that accepts tag pairs in its parameter list, rather than a pointer to a tag list. AslRequestTags() also accepts tag pairs. @ENDNODE @NODE I-7-3 "The ASL_Window Tag" An application that uses a custom screen normally wants its requesters to open on its screen. Using the ASL_Window tag, a program can associate a requester with a window so the requester appears on the window's screen. The ASL_Window tag is followed by a pointer to a window structure. ASL_Window works with both file and font requesters. Normally, a requester associated with a window (using ASL_Window) uses the window's IDCMP port for its communication. An application may not want to share an IDCMP port with the requester. Using the ASL_FuncFlags tag, a program can ask for a requester that creates its own IDCMP port. There are two flags that accomplish this. The first, FILF_NEWIDCMP, is used on file requesters. The other, FONF_NEWIDCMP, is used on font requesters. @ENDNODE @NODE I-7-4 "The Save Requester" The Save requester is a special type of file requester. The release 2.0 save requester differs from the regular file requester in several ways. The first is its appearance. The color of the text making up the file name list and the color of the backround the text is rendered on are swapped for the save requester. This makes the difference between the save and file requesters visual as well as functional. Another difference, is that a save requester does not allow the user to select by double-clicking on a file name. This prevents the user from accidentally double-clicking, and thus over-writing, the wrong file. The other difference is that if the user types a directory name into the save requester and the directory doesn't exist, the save requester will create that directory (after getting the user's permission via another requester). The FILF_SAVE flag from the ASL_FuncFlags tag creates a save requester. Note that it does not make sense to have multiple selection in a save requester, so the FILF_SAVE flag overrides the FILF_MULTISELECT flag. @ENDNODE @NODE I-7-5 "A Directory Requester" A program may not need to process files in a requester, only the directories. There is another variation on asl.library's file requester that allows this. A new tag, ASL_ExtFlags1, toggles this option. ASL_ExtFlags1 passes a bit field like ASL_FuncFlags. One of ASL_ExtFlags1's flags, FIL1F_NOFILES, sets up a requester that has no string gadget for files and displays only directory names in the requester's scrolling list. When AslRequest() (or AslRequestTags() ) returns successfully, the FileRequester structure's rf__Dir field contains the name of the directory the user selected. Currently, there is another flag defined for ASL_ExtFlags1, FIL1F_MATCHDIRS. If file pattern matching is on (see the FILF_PATGAD flag for ASL_FuncFlags), setting FIL1F_MATCHDIRS tells the file requester to pattern match directory names as well as file names. Of course, if both of ASL_ExtFlags1's flags are set, the requester will only pattern match directory names. @ENDNODE @NODE I-7-6 "The Font Requester" The ASL library also contains a font requester. The default font requester consists of two scrolling lists, one containing font names, the other containing font sizes. Each scrolling list is accompanied by a string gadget which lets the user type in the name and size of the font they want. @{" Figure 2 - The FontReq.c font requester " link "I-7/fontreq.ilbm/MAIN"} The font size string gadget (actually, an integer gadget) is especially useful because it allows the user to type in a font size that doesn't appear in the font size scrolling list. If the font size the user requests does not already exist in the system, the Amiga can generate the font size the user requests either through bitmap scaling, or, if scalable outline fonts are available, by scaling an outline font. Using the font requester is similar to using the file requester. First, allocate a requester structure. A font requester requires the FontRequester structure: struct FontRequester { APTR fo_Reserved1[2]; struct TextAttr fo_Attr; /* Returned TextAttr */ UBYTE fo_FrontPen; /* Returned pens, if selected */ UBYTE fo_BackPen; UBYTE fo_DrawMode; APTR fo_UserData; }; To allocate this structure, use AllocAslRequest() or AllocAslRequestTags() with the first argument set to ASL_FontRequest. There are several tags that are specific to the font requester: ASL_FontName ASL_FontHeight ASL_FontStyles ASL_FontFlags ASL_FrontPen ASL_BackPen ASL_MinHeight ASL_MaxHeight ASL_ModeList The first six tags are used to place initial values into the FontRequester structure. They correspond respectively to the FontRequester's fo_Attr.ta_Name, fo_Attr.ta_YSize, fo_Attr.ta_Style, fo_Attr.ta_Flags, fo_FrontPen, and fo_BackPen fields. ASL_MinHeight specifies the minimum Y height that the font requester should list. ASL_MaxHeight specifies the maximum Y height that the font requester should list. Note that these tags only limit the range of font sizes that the font requester displays, the user is free to type in any value. The ASL_ModeList tag specifies the strings used for the font requester's drawing mode gadget. This is discussed later in the chapter. The are several options available to the font requester that are toggled by setting flags with the ASL_FuncFlags tag. These flags are: FONF_FRONTCOLOR FONF_BACKCOLOR FONF_STYLES FONF_FIXEDWIDTH FONF_DRAWMODE A simple font requester (one without any of the above FONF_ flags set) only lets the user choose a font and a Y size. Setting the flags above adds options to the font requester. FONF_FRONTCOLOR and FONF_BACKCOLOR add color selection gadgets to the requester, one for choosing a font's foreground color (labeled ``Text'' on the requester) and the other for choosing the backround color (labeled ``Field''). The font requester records the user's setting in the FontRequester's fo_FrontPen and fo_BackPen fields. FONF_STYLES sets up several gadgets to choose the style of the font (bold, italics, underline). The font requester saves these setting in the fo_Attr.ta_Style bit field according to the style flags defined in . FONF_FIXEDWIDTH limits the font name display to fixed width (non-proportional) fonts (note that this does not prevent the user from typing in a proportional font name). FONF_DRAWMODE adds a cycle gadget to the font requester so the user can choose the draw mode. The draw mode is saved in the requester's fo_DrawMode field. The number stored there corresponds to the draw mode's position in the gadget's cycle. The draw mode cycle gadget initially is labeled ``Mode'' and has three elements in its cycle: ``JAM1'', ``JAM2'', and ``Complement''. These yield a result of 0, 1, and 2, respectively. It is possible to change the names and number of draw modes with the ASL_ModeList tag. This tag accepts a pointer to an array of strings. The first string replaces ``Mode'' as the label for the draw mode cycle gadget. The strings that follow replace the elements of the cycle gadget. The last entry in the array has to be NULL to tell the requester where the list of entries ends. The @{"FontReq.c" link I-7/FontReq.c/MAIN} example illustrates how to use a font requester. @ENDNODE @NODE I-7-7 "The ASL_HookFunc Tag" The ASL_HookFunc tag passes an ASL requester a pointer to a custom function. The requester can use this function for two purposes. The first is to determine if the requester should display a particular file or font name. The other purpose is to process messages that the requester receives at its IDCMP port that are not meant for the requester. Some ASL_FuncFlags flags toggle these options: FILF_DOWILDFUNC FONF_DOWILDFUNC FILF_DOMSGFUNC FONF_DOMSGFUNC The FILF_DOWILDFUNC and FONF_DOWILDFUNC flags cause a requester to call the hook function for every file or font entry. The requester displays the file or font name only if the hook function tells it to. For a file requester, if the hook function returns a zero, the file requester will display the file name. For a font requester, if the hook function returns anything but zero, the font requester will display the font name and size. Note that if the DOWILDFUNC function changes the current directory, it must restort the current directory before it exits. Neglecting to restore the current directory can confuse DOS. The FILF_DOMSGFUNC and FONF_DOMSGFUNC flags cause a requester to call the hook function when it receives certain IntuiMessages at the IDCMP port it shares with a window (see the ASL_Window tag). The requester passes on IntuiMessages not meant for the requester. The hook function is responsible for returning a pointer to the IntuiMessage. The requester will take care of replying to the message. A requester passes three parameters to the hook function: ULONG MyHookFunc(ULONG type, CPTR object, CPTR AslRequester) If MyHookFunc() is called from a file requester doing DOWILDFUNC: type = FILF_DOWILDFUNC object is a pointer to an AnchorPath structure (from ) AslRequester is a pointer to the FileRequester that called the hook function (Return a zero to display this file) Note that the AnchorPath structure is a dos.library structure used in pattern matching. See dos.library documentation for more details. Referencing the specific file or directory from within the DOWILDFUNC hook function is a little tricky. For a file requester, the rf_Dir field is not guaranteed to contain the name of the directory being scanned. The correct way to find the file and directory name is from the AnchorPath structure passed to the DOWILDFUNC. The structure contains a FileInfoBlock structure called ap_Info that contains the file name (fib_FileName). The AnchorPath structure's ap_Current field contains a pointer to an AChain structure (from ) which contains a field called an_Lock. This is a lock on the directory being scanned. If MyHookFunc() is called from a font requester doing DOWILDFUNC: type = FONF_DOWILDFUNC object is a pointer to a TextAttr structure (from ) AslRequester is a pointer to the FontRequester that called the hook function (Return non-zero to display this particular font size) If MyHookFunc() is called from a file or font requester doing DOMSGFUNC: type = FILF_DOMSGFUNC object is a pointer to the IntuiMessage for the function to process AslRequester is a pointer to the FileRequester or FontRequester that called the hook function (Return the pointer to the IntuiMessage) Notice that it is possible for a requester to use both DOWILDFUNC and DOMSGFUNC at the same time. The hook function has to differentiate between the two cases by testing the type passed to it. It is not possible for font and file requester to share a hook function for a DOWILDFUNC, because FILF_DOWILDFUNC is defined to be the same value as FONF_DOWILDFUNC, so the hook function cannot tell if object (from the prototype above) is a pointer to an AnchorPath structure or a pointer to a TextAttr structure. It is possible for font and file requesters to share one hook function for DOMSGFUNC (even though FILF_DOMSGFUNC and FONF_DOMSGFUNC are equal) because, in this case, font and file requesters both call the hook function in the same manner. The example @{"FileHook.c" link I-7/FileHook.c/MAIN} illustrates the use of a hook function for both DOWILDFUNC and DOMSGFUNC. @ENDNODE