nelle precedenti lezioni abbiamo trattato, in maniera più o meno approfondita, diverse librerie di Amiga: exec, dos, intuition, gadtools e graphics.
Queste cinque librerie sono praticamente il cuore (oltre a layer) del nostro amato OS. Esistono però molte altre librerie che non sono fondamentali per il boot del sistema ma molto utili per creare applicazioni o giochi di un certo livello (oltre ad essere ovviamente usate dal resto del sistema).
Cominciamo dunque a vedere la prima di queste librerie di supporto: la asl.library. Le funzioni messe a disposizione sono:
APTR AllocAslRequest( unsigned long reqType, struct TagItem *tagList );
APTR AllocAslRequestTags( unsigned long reqType, Tag Tag1, ... );
BOOL AslRequest( APTR requester, struct TagItem *tagList );
BOOL AslRequestTags( APTR requester, Tag Tag1, ... );
void FreeAslRequest( APTR requester );
L'uso di queste funzioni è molto facile; a seconda del tipo di requester che ci serve, consultando il file libraries/asl.h, potremo decidere quali tag utilizzare e quali no.
Facciamo un esempio:
[...]
struct FileRequester *Req = NULL;
struct Window *win = NULL;
[...]
/* Alloco un file requester con determinate caratteristiche */
if((Req=AllocAslRequestTags(ASL_FileRequest,
ASLFR_Window, win, // finestra associata al requester
ASLFR_SleepWindow, TRUE, // puntatore d'attesa per la fin associata
ASLFR_RejectIcons, TRUE, // non mostrare le icone
TAG_DONE)))
{
/* Modifico il tag per indicare il modo salvataggio */
if(AslRequestTags(Req,ASLFR_TitleText,"Scegli il file da salvare",
ASLFR_DoSaveMode,TRUE,TAG_DONE))
{
/* L'utente ha selezionato un file e premuto su Ok */
}
else
/* L'utente ha selezionato 'Annulla' */
FreeAslRequest(Req);
}
Supponendo che questo codice sia in una vostra routine di salvataggio, ogni volta che viene chiamata, alloca usa e dealloca il filerequester. Questo presenta diversi svantaggi. Quello che l'utente nota, oltre al fatto che magari in determinate situazioni (poca memoria) il vostro programma non salva, è che il requester non si "ricorda" la posizione precedente, sia come finestra che come cassetto di lavoro. É quindi buona norma allocare un unico requester che utilizzeremo per le operazioni sui file e deallocarlo solo alla fine del programma. Infatti è possibile agire tramite la AslRequest() sui vari aspetti di un requester. Come nell'esempio, che imposta il modo salvataggio.
Ovviamente questo discorso é valido anche per gli altri due tipi di requester messi a disposizione da questa libreria.
Tenere presente, che le varie strutture FileRequester ScreenModeRequester e
FontRequester sono a SOLA LETTURA, per modificarle è bene usare l'apposita funzione asl.
Vediamo quindi le strutture dei vari requester:
/* presa dal file workbench/startup.h serve al file requester */
struct WBArg {
BPTR wa_Lock; /* a lock descriptor */
BYTE * wa_Name; /* a string relative to that lock */
};
/*****************************************************************************
*
* ASL File Requester data structures and constants
*
* This structure must only be allocated by asl.library amd is READ-ONLY!
* Control of the various fields is provided via tags when the requester
* is created with AllocAslRequest() and when it is displayed via
* AslRequest()
*/
struct FileRequester
{
UBYTE fr_Reserved0[4];
STRPTR fr_File; /* Contents of File gadget on exit */
STRPTR fr_Drawer; /* Contents of Drawer gadget on exit */
UBYTE fr_Reserved1[10];
WORD fr_LeftEdge; /* Coordinates of requester on exit */
WORD fr_TopEdge;
WORD fr_Width;
WORD fr_Height;
UBYTE fr_Reserved2[2];
LONG fr_NumArgs; /* Number of files selected */
struct WBArg *fr_ArgList; /* List of files selected */
APTR fr_UserData; /* You can store your own data here */
UBYTE fr_Reserved3[8];
STRPTR fr_Pattern; /* Contents of Pattern gadget on exit */
};
Credo che i commenti siano abbastanza esplicativi da soli. In pratica, nell'esempio di prima, dove c'è il commento /* L'utente ha selezionato un file... */ possiamo accedere ai campi della struttura per memorizzarli e/o utilizzarli per i nostri scopi.
TIP: Per utilizzare il nome del cassetto più quello del file per la Open() potete usare il seguente codice:
UBYTE *nomefile,len = strlen(Req -> fr_Drawer) + strlen(Req -> fr_File) + 1;
if(nomefile = AllocVec(len,MEMF_CLEAR))
{
strcpy(nomefile,Req -> fr_Drawer);
AddPart(nomefile,Req -> fr_File,len + 1);
[...]
FreeVec(nomefile);
}
che permette di creare il nome file richiesto senza preoccuparsi se il nome del cassetto è un nome di device (e quindi terminante con : ) o un cassetto (e quindi da aggiungere una / ).
/*****************************************************************************
*
* ASL Font Requester data structures and constants
*
* This structure must only be allocated by asl.library amd is READ-ONLY!
* Control of the various fields is provided via tags when the requester
* is created with AllocAslRequest() and when it is displayed via
* AslRequest()
*/
struct FontRequester
{
UBYTE fo_Reserved0[8];
struct TextAttr fo_Attr; /* Returned TextAttr */
UBYTE fo_FrontPen; /* Returned front pen */
UBYTE fo_BackPen; /* Returned back pen */
UBYTE fo_DrawMode; /* Returned drawing mode */
UBYTE fo_Reserved1;
APTR fo_UserData; /* You can store your own data here */
WORD fo_LeftEdge; /* Coordinates of requester on exit */
WORD fo_TopEdge;
WORD fo_Width;
WORD fo_Height;
struct TTextAttr fo_TAttr; /* Returned TTextAttr */
};
Stesso discorso per questa struttura, nella scorsa lezione abbiamo visto come utilizzare una struttura TextAttr per aprire ed usare un font nella nostra RastPort e non dovrebbe quindi presentare problemi di sorta.
/*****************************************************************************
*
* ASL Screen Mode Requester data structures and constants
*
* This structure must only be allocated by asl.library and is READ-ONLY!
* Control of the various fields is provided via tags when the requester
* is created with AllocAslRequest() and when it is displayed via
* AslRequest()
*/
struct ScreenModeRequester
{
ULONG sm_DisplayID; /* Display mode ID */
ULONG sm_DisplayWidth; /* Width of display in pixels */
ULONG sm_DisplayHeight; /* Height of display in pixels */
UWORD sm_DisplayDepth; /* Number of bit-planes of display */
UWORD sm_OverscanType; /* Type of overscan of display */
BOOL sm_AutoScroll; /* Display should auto-scroll? */
ULONG sm_BitMapWidth; /* Used to create your own BitMap */
ULONG sm_BitMapHeight;
WORD sm_LeftEdge; /* Coordinates of requester on exit */
WORD sm_TopEdge;
WORD sm_Width;
WORD sm_Height;
BOOL sm_InfoOpened; /* Info window opened on exit? */
WORD sm_InfoLeftEdge; /* Last coordinates of Info window */
WORD sm_InfoTopEdge;
WORD sm_InfoWidth;
WORD sm_InfoHeight;
APTR sm_UserData; /* You can store your own data here */
};
Infine anche i campi di questa struttura sono di facile comprensione, in pratica i primi otto campi servono per determinare quale tipo di schermo aprire e con che dimensioni e profondità.
Scarica il sorgente dell'esempio.