Corso di AmigaOS

Torna all'elenco delle lezioniPer dubbi, consigli o richieste, potete mandare un'e-mail ad Andrea Carolfi.
Ringraziamo Amiga Transactor Mailing List per questo tangibile contributo!


La amigaguide.library (Ventunesima lezione)

Come anticipato nella scorsa lezione, invece di spiegare una per una le funzioni della libreria amigaguide ho commentato un sorgente di esempio, che vi spiega i passi elementari per invocare una pagina di un file amigaguide premendo il tasto help mentre il mouse è su un gadget o si sta selezionando un menù.
Questo per permettervi di entrare nell'ottica e poter da subito fare pratica senza attendere le lezioni successive sulla libreria. Nella prossima puntata vedremo cos'altro ci riserva questa libreria.

Vediamo quindi un sorgente di esempio, preso dal CD degli sviluppatori:

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <exec/libraries.h>
#include <intuition/screens.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <graphics/text.h>
#include <libraries/amigaguide.h>
#include <libraries/gadtools.h>
#include <string.h>
#include <stdio.h>

#include <clib/alib_protos.h>
#include <proto/amigaguide.h>
#include <proto/exec.h>
#include <proto/gadtools.h>
#include <proto/graphics.h>
#include <proto/intuition.h>

/*****************************************************************************/

#define  DB(x) ;

/*****************************************************************************/
/* Struttura di comodo per memorizzare le informazioni della nostra appl.    */
/*****************************************************************************/
struct AppInfo
{
         struct Screen *ai_Screen;    /* Screen that our application will open on */
         APTR     ai_VI;        /* GadTools visual info */
         struct Window *ai_Window;    /* Window pointer */
         struct Menu      *ai_Menu;      /* Menus */

         /* Gadgets that we want to set attributes on */
         struct Gadget *ai_GStatus;      /* Status window */

         /* Help related information */
         AMIGAGUIDECONTEXT    ai_AmigaGuide;      /* Pointer to the AmigaGuide context */
         struct NewAmigaGuide ai_NAG;    /* Used to start AmigaGuide */
         LONG     ai_Region;    /* Region that the mouse if over */

         /* Control information */
         BOOL     ai_Done;      /* Done yet? */
};

/*****************************************************************************/
/* ID di contesto da inviare all'AmigaGuide.                                 */
/* Sono i nomi dei nodi del file .guide.                                     */
/*****************************************************************************/
STRPTR context[] =
{
         "MAIN",
         "STATUS",
         "LISTVIEW",
         "ACCEPT",
         "CANCEL",
         "QUIT",
         NULL
};

/*****************************************************************************/
/* ID dei bottoni della finestra.                                            */
/*****************************************************************************/
#define  MCMD_MAIN   0
#define  MCMD_STATUS 1
#define  MCMD_LISTVIEW  2
#define  MCMD_ACCEPT 3
#define  MCMD_CANCEL 4
#define  MCMD_QUIT   5

/*****************************************************************************/
/* Aiuto rapido da visualizzare nella barra di stato della finestra          */
/*****************************************************************************/
STRPTR quickhelp[] =
{
         "AGHelp main window.",
         "Quick-Help or status window.",
         "List of absolutely nothing.",
         "Accept changes.",
         "Cancel changes.",
         "",
         "Window sizing gadget.",
         "Window drag bar.",
         "Screen drag bar.",
         "Window depth gadget.",
         "Screen depth gadget.",
         "Window zoom gadget.",
         "",
         "Window close gadget.",
         NULL
};

#define  MAX_REGION  14

/*****************************************************************************/
/* Carattere utilizzato nell'interfaccia.                                    */
/*****************************************************************************/
struct TextAttr topaz8 = {"topaz.font", 8, FS_NORMAL, FPF_ROMFONT|FPF_DESIGNED};

/*****************************************************************************/
/* IDCMP sul quale vogliamo ricevere una notifica da parte di Intuition.     */
/*****************************************************************************/
#define  IDCMP_FLAGS IDCMP_RAWKEY | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | \
                        IDCMP_MENUHELP | IDCMP_GADGETUP | IDCMP_MOUSEMOVE | IDCMP_GADGETHELP

/*****************************************************************************/
/* Menù dell'applicazione                                                    */
/*****************************************************************************/
#define  V(x)  ((void *)(x))

struct NewMenu main_menu[] =
{
         {NM_TITLE, "Project",},
         {NM_ITEM,  "Close Window", "Q", NULL, NULL, V(MCMD_QUIT),},
         {NM_END,},
};

/*****************************************************************************/
/* Visualizza l'errore di AmigaGuide.                                        */
/*****************************************************************************/
VOID DisplayError (LONG err)
{
         printf ("%s\n", GetAmigaGuideString (err));
}

/*****************************************************************************/
/* Routine di gestione degli eventi                                          */
/*****************************************************************************/
void HandleEvents (struct AppInfo * ai)
{
        struct Window *win = ai->ai_Window;
        struct AmigaGuideMsg *agm;
        struct IntuiMessage *imsg;
        struct MenuItem *item;
        ULONG sigr = 0L;
        ULONG sigi = 0L;
        ULONG sigb = 0L;
        UWORD selection;
        STRPTR label;
        LONG region;
        LONG qhelp;

        /* Non dobbiamo ancora uscire dall'applicazione */
        ai->ai_Done = FALSE;

        /* Dobbiamo ricevere notifiche da due porte */
        /* Get our signal bits */
        sigb = AmigaGuideSignal (ai->ai_AmigaGuide);
        sigi = (1L << win->UserPort->mp_SigBit);

        /* Resettiamo il contesto AmigaGuide */
        SetAmigaGuideContext (ai->ai_AmigaGuide, 0L, NULL);

        /* Finché non abbiamo finito */
        while (!(ai->ai_Done))
        {
                /* Aspettiamo un evento */
                sigr = Wait (sigb | sigi);

                /* Gestiamo i messaggi Intuition & GadTools */
                while (imsg = GT_GetIMsg (win->UserPort))
                {
                        switch (imsg->Class)
                        {
                                case IDCMP_CLOSEWINDOW:
                                        ai->ai_Done = TRUE;
                                break;

                                case IDCMP_MENUPICK:
                                        selection = imsg->Code;
                                        while (selection != MENUNULL)
                                        {
                                                item = ItemAddress (win->MenuStrip, selection);

                                                switch ((LONG)MENU_USERDATA (item))
                                                {
                                                        case MCMD_QUIT:
                                                                ai->ai_Done = TRUE;
                                                        break;
                                                }
                                                selection = item->NextSelect;
                                        }
                                break;

                                case IDCMP_MENUHELP:
                                        if (item = ItemAddress (win->MenuStrip, imsg->Code))
                                        {
                                                /* Visualizziamo l'aiuto per questa voce di menù */
                                                SendAmigaGuideCmd (ai->ai_AmigaGuide, NULL,
                                                        AGA_Context, (LONG) MENU_USERDATA (item),TAG_DONE);
                                        }
                                break;

                                case IDCMP_GADGETUP:
                                        switch (((struct Gadget *)imsg->IAddress)->GadgetID)
                                        {
                                                case MCMD_ACCEPT:
                                                case MCMD_CANCEL:
                                                        ai->ai_Done = TRUE;
                                                break;
                                        }
                                break;

                                case IDCMP_GADGETHELP:
                                        qhelp = region = -1;
                                        if (imsg->IAddress == NULL)
                                        {
                                                /* Non siamo sopra la finestra */
                                                DB (printf ("not over our window\n"));
                                        }
                                        else if (imsg->IAddress == (APTR) win)
                                        {
                                                /* Siamo sopra la nostra finestra */
                                                DB (printf ("over window\n"));
                                                qhelp = region = 0;
                                        }
                                        else
                                        {
                                                /*
                                                 * Rileviamo i gadgets di sistema.  Lo facciamo controllando i
                                                 * bit system-gadget-type nel campo GadgetType:
                                                 */
                                                LONG sysgtype = ((struct Gadget *) imsg->IAddress)->GadgetType & 0xF0;

                                                /* Set the region */
                                                qhelp = (sysgtype >> 4) + 5;
                                                region = HTFC_SYSGADS + sysgtype;

                                                switch (sysgtype)
                                                {
                                                        case GTYP_SIZING:
                                                                DB (printf ("Gadget Help for window sizing gadget\n"));
                                                        break;

                                                        case GTYP_WDRAGGING:
                                                                DB (printf ("Gadget Help for window drag-bar\n"));
                                                        break;

                                                        case GTYP_WUPFRONT:
                                                                DB (printf ("Gadget Help for window depth gadget\n"));
                                                        break;

                                                        case GTYP_WDOWNBACK:
                                                                DB (printf ("Gadget Help for window zoom gadget\n"));
                                                        break;

                                                        case GTYP_CLOSE:
                                                                DB (printf ("Gadget Help for window close gadget\n"));
                                                        break;

                                                        case 0:
                                                                /*
                                                                 * In questo esempio, abbiamo solo un gadget, così
                                                                 * sappiamo qual'è.  Normalmente, per determinare
                                                                 * quale ha inviato il messaggio bisogna utilizzare
                                                                 * le solite tecniche usate per gli altri messaggi dei
                                                                 * gadget.
                                                                 */
                                                                DB (printf ("Gadget id %d, code %d\n",
                                                                        ((struct Gadget *)imsg->IAddress)->GadgetID, imsg->Code));
                                                                qhelp = region = (LONG) ((struct Gadget *)imsg->IAddress)->GadgetID;
                                                        break;

                                                        default:
                                                                DB (printf ("Gadget Help on some other system gadget\n"));
                                                        break;
                                                }
                                        }

                                        /* Memorizza la regione */
                                        ai->ai_Region = region;

                                        /* Controlliamo il campo della regione */
                                        label = NULL;
                                        if ((qhelp >= 0) && (qhelp < MAX_REGION))
                                                label = quickhelp[qhelp];

                                        /* Aggiorniamo l'informazione dell'aiuto rapido */
                                        GT_SetGadgetAttrs (ai->ai_GStatus, ai->ai_Window, NULL, GTTX_Text, label, TAG_DONE);
                                break;

                                case IDCMP_RAWKEY:
                                        /* Il tasto Help è stato premuto */
                                        if (imsg->Code == 95)
                                        {
                                                /* Visualizza il nodo inerente alla regione memorizzata */
                                                SendAmigaGuideCmd (ai->ai_AmigaGuide, NULL,
                                                        AGA_Context, ai->ai_Region,TAG_DONE);
                                        }
                                break;
                        }

                        /* Replica il messaggio */
                        GT_ReplyIMsg (imsg);
                }

                /* Gestiamo i messaggi AmigaGuide */
                if (sigr & sigb)
                {
                        while (agm = GetAmigaGuideMsg (ai->ai_AmigaGuide))
                        {
                                /* Controlliamo il tipo di messaggio */
                                switch (agm->agm_Type)
                                {
                                        /* AmigaGuide è pronta ad essere gestita */
                                        case ActiveToolID:
                                        break;

                                        /* Questo è un reply ad un nostro comando */
                                        case ToolCmdReplyID:
                                                if (agm->agm_Pri_Ret)
                                                        DisplayError (agm->agm_Sec_Ret);
                                        break;

                                        /* Questo è un messaggio di stato */
                                        case ToolStatusID:
                                                if (agm->agm_Pri_Ret)
                                                        DisplayError (agm->agm_Sec_Ret);
                                        break;

                                        /* Questo è il messaggio di Shutdown */
                                        case ShutdownMsgID:
                                                if (agm->agm_Pri_Ret)
                                                        DisplayError (agm->agm_Sec_Ret);
                                        break;

                                        default:
                                        break;
                                }

                                /* Replichiamo il messaggio */
                                ReplyAmigaGuideMsg (agm);
                        }
                }
        }
}

/*****************************************************************************/

void main (void)
{
        struct ExecBase *SysBase = (*((struct ExecBase **) 4));
        struct Gadget *anchor = NULL;
        struct NewGadget ng;
        struct AppInfo *ai;
        struct Gadget *gad;

        /* Controlliamo la presenza del kickstart V3.X */
        if (SysBase->LibNode.lib_Version < 39)
        {
                printf ("requires V39\n");
                return;
        }

        if (ai = AllocVec (sizeof (struct AppInfo), MEMF_CLEAR))
        {
                /* Apriamo le librerie in ROM */
                if (IntuitionBase = OpenLibrary ("intuition.library", 39))
                {
                        GadToolsBase = OpenLibrary ("gadtools.library", 39);
                        GfxBase = OpenLibrary ("graphics.library", 39);

                        /* Apriamo l'AmigaGuide */
                        if (AmigaGuideBase = OpenLibrary ("amigaguide.library", 39))
                        {
                                /* Blocchiamo lo schermo pubblico predefinito */
                                if (ai->ai_Screen = LockPubScreen (NULL))
                                {
                                        /* Otteniamo l'informazione visuale dello schermo per GadTools */
                                        if (ai->ai_VI = GetVisualInfoA (ai->ai_Screen, NULL))
                                        {
                                                /* Initializziamo i dato globali */
                                                ai->ai_Region = -1;

                                                anchor = NULL;
                                                gad = CreateContext (&anchor);

                                                /* Impostiamo le costanti */
                                                ng.ng_TextAttr   = &topaz8;
                                                ng.ng_VisualInfo = ai->ai_VI;

                                                /* Creiamo un gadget di stato */
                                                ng.ng_LeftEdge   = ai->ai_Screen->WBorLeft + 4;
                                                ng.ng_TopEdge    = ai->ai_Screen->BarHeight + 1 + 2;
                                                ng.ng_Width      = 312;
                                                ng.ng_Height     = 12;
                                                ng.ng_GadgetText = NULL;
                                                ng.ng_GadgetID   = MCMD_STATUS;
                                                ng.ng_Flags      = NULL;
                                                ng.ng_UserData   = NULL;
                                                gad = CreateGadget (TEXT_KIND, gad, &ng,
                                                        GTTX_Justification, GTJ_CENTER,
                                                        GTTX_Border,  TRUE,TAG_DONE);
                                                ai->ai_GStatus = gad;

                                                /* Creaiamo una list view */
                                                ng.ng_LeftEdge   = ai->ai_Screen->WBorLeft + 4;
                                                ng.ng_TopEdge   += ng.ng_Height + 4;
                                                ng.ng_Height     = 64;
                                                ng.ng_GadgetText = NULL;
                                                ng.ng_GadgetID   = MCMD_LISTVIEW;
                                                gad = CreateGadget (LISTVIEW_KIND, gad, &ng,
                                                        GTLV_ReadOnly,   TRUE,
                                                        GTLV_ScrollWidth,   18,TAG_DONE);

                                                /* Creiamo un bottone Accept */
                                                ng.ng_LeftEdge   = ai->ai_Screen->WBorLeft + 4;
                                                ng.ng_TopEdge    = ai->ai_Screen->BarHeight + 1 + 84;
                                                ng.ng_Width      = 87;
                                                ng.ng_Height     = 12;
                                                ng.ng_GadgetText = "Accept";
                                                ng.ng_GadgetID   = MCMD_ACCEPT;
                                                gad = CreateGadget (BUTTON_KIND, gad, &ng, TAG_DONE);

                                                /* Creiamo un bottone Cancel */
                                                ng.ng_LeftEdge   = ai->ai_Screen->WBorLeft + 229;
                                                ng.ng_GadgetText = "Cancel";
                                                ng.ng_GadgetID   = MCMD_CANCEL;
                                                gad = CreateGadget (BUTTON_KIND, gad, &ng, TAG_DONE);

                                                /* Apriamo la finestra */
                                                if (ai->ai_Window = OpenWindowTags (NULL,
                                                        WA_InnerWidth,   320,
                                                        WA_InnerHeight,  100,
                                                        WA_Gadgets,      anchor,
                                                        WA_IDCMP,     IDCMP_FLAGS,
                                                        WA_Title,     (ULONG) "AmigaGuide Demo",
                                                        WA_PubScreen, ai->ai_Screen,
                                                        WA_MenuHelp,  TRUE,
                                                        WA_AutoAdjust,   TRUE,
                                                        WA_DragBar,      TRUE,
                                                        WA_DepthGadget,  TRUE,
                                                        WA_CloseGadget,  TRUE,
                                                        WA_SmartRefresh, TRUE,
                                                        WA_NewLookMenus, TRUE,
                                                        WA_Activate,  TRUE,
                                                        TAG_DONE))
                                                {
                                                        /* Creiamo i menù */
                                                        if (ai->ai_Menu = CreateMenus (main_menu, TAG_DONE))
                                                                if (LayoutMenus (ai->ai_Menu, ai->ai_VI,
                                                                        GTMN_NewLookMenus,TRUE,TAG_DONE))
                                                                        SetMenuStrip (ai->ai_Window, ai->ai_Menu);

                                                        /* Attiviamo l'aiuto per i bottoni */
                                                        HelpControl (ai->ai_Window, HC_GADGETHELP);

                                                        /* Memorizziamo l'AppInfo */
                                                        ai->ai_Window->UserData = (APTR) ai;

                                                        ai->ai_NAG.nag_Flags = HTF_NOACTIVATE;

                                                        /* Impostiamo il nome base dell'applicazione */
                                                        ai->ai_NAG.nag_BaseName = "AGHelp";

                                                        /* Impostiamo il nome del documento */
                                                        ai->ai_NAG.nag_Name = "aghelp.guide";

                                                        /* Stabiliamo un nome base da usare per la porta Arexx per l'ipertesto *?
                                                        ai->ai_NAG.nag_ClientPort = "AGAPP_HELP";

                                                        /* Impostiamo la tavola del contesto */
                                                        ai->ai_NAG.nag_Context = context;

                                                        /* Apriamo il sistema di aiuto */
                                                        ai->ai_AmigaGuide = OpenAmigaGuideAsync (&ai->ai_NAG, NULL);

                                                        /* Gestiamo gli eventi */
                                                        HandleEvents (ai);

                                                        /* Disattiviamo il sistema di aiuto */
                                                        CloseAmigaGuide (ai->ai_AmigaGuide);

                                                        /* Cancelliamo la striscia di menù */
                                                        ClearMenuStrip (ai->ai_Window);

                                                        /* Deallochiamo i menù */
                                                        FreeMenus (ai->ai_Menu);

                                                        /* Chiudiamo la finestra dell'applicazione */
                                                        CloseWindow (ai->ai_Window);
                                                }

                                                /* Deallochiamo i gadget */
                                                FreeGadgets (anchor);

                                                /* Deallochiamo il visual info per GadTools */
                                                FreeVisualInfo (ai->ai_VI);
                                        }

                                        /* Sblocchiamo lo schermo pubblico predefinito */
                                        UnlockPubScreen (NULL, ai->ai_Screen);
                                }
                                /* Chiudiamo l'AmigaGuide */
                                CloseLibrary (AmigaGuideBase);
                        }

                        /* Chiudiamo le librerie in ROM */
                        CloseLibrary (GfxBase);
                        CloseLibrary (GadToolsBase);
                        CloseLibrary (IntuitionBase);
                }
                FreeVec (ai);
        }
}
La lezione termina quì, con insieme un .guide di esempio.

Lezione precedente Indice delle lezioni
Copyright AMiWoRLD Ph0ton