home *** CD-ROM | disk | FTP | other *** search
/ YPA: Your Privacy Assured / YPA.ISO / other_goodies / utilities / amigaguid.lha / AmigaGuide / AG_V34 / Source / NodeHost.c < prev    next >
C/C++ Source or Header  |  1992-12-30  |  9KB  |  375 lines

  1. /* nodehost.c
  2.  * Written by David N. Junod
  3.  *
  4.  * Example of a Dynamic Node Host.  This example is useful for determining
  5.  * what nodes an AmigaGuide database is calling when it brings up the
  6.  * "Can't locate node" requester.
  7.  *
  8.  * I use it when I'm writing help files for AppShell applications...
  9.  *
  10.  */
  11.  
  12. #include <exec/types.h>
  13. #include <intuition/intuition.h>
  14. #include <intuition/screens.h>
  15. #include <libraries/amigaguide.h>
  16. #include <dos/dos.h>
  17. #include <dos/dosextens.h>
  18. #include <clib/exec_protos.h>
  19. #include <clib/dos_protos.h>
  20. #include <clib/intuition_protos.h>
  21. #include <clib/graphics_protos.h>
  22. #include <clib/amigaguide_protos.h>
  23. #include <pragmas/exec.h>
  24. #include <pragmas/amigaguide_pragmas.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <stdio.h>
  28.  
  29. extern struct Library *SysBase, *DOSBase;
  30. struct Library *IntuitionBase, *GfxBase, *AmigaGuideBase;
  31.  
  32. void kprintf (void *, ...);
  33. #define    DB(x)    ;
  34.  
  35. #define    ASM    __asm
  36. #define    REG(x)    register __ ## x
  37.  
  38. ULONG __saveds dispatchAmigaGuideHost (struct Hook *h, STRPTR db, Msg msg);
  39. ULONG ASM hookEntry (register __a0 struct Hook *,register __a2 VOID *,register __a1 VOID *);
  40.  
  41. main (int argc, char **argv)
  42. {
  43.     struct Hook hook;
  44.     AMIGAGUIDEHOST hh;
  45.  
  46.     IntuitionBase = OpenLibrary ("intuition.library", 0);
  47.     GfxBase = OpenLibrary ("graphics.library", 0);
  48.  
  49.     /* amigaguide.library works with 1.3 and newer versions of the OS */
  50.     if (AmigaGuideBase = OpenLibrary ("amigaguide.library", 33))
  51.     {
  52.     /* Initialize the hook */
  53.     hook.h_Entry = hookEntry;
  54.     hook.h_SubEntry = dispatchAmigaGuideHost;
  55.  
  56.     /* Add the AmigaGuideHost to the system */
  57.     if (hh = AddAmigaGuideHost (&hook, "ExampleHost", NULL))
  58.     {
  59.         printf ("Added AmigaGuideHost 0x%lx\n", hh);
  60.  
  61.         /* Wait until we're told to quit */
  62.         Wait (SIGBREAKF_CTRL_C);
  63.  
  64.         printf ("Remove AmigaGuideHost 0x%lx", hh);
  65.  
  66.         /* Try removing the host */
  67.         while (RemoveAmigaGuideHost (hh, NULL) > 0)
  68.         {
  69.         /* Wait a while */
  70.         printf (".");
  71.         Delay (250);
  72.         }
  73.         printf ("\n");
  74.     }
  75.     else
  76.     {
  77.         printf ("Couldn't add AmigaGuideHost\n");
  78.     }
  79.  
  80.     /* close the library */
  81.     CloseLibrary (AmigaGuideBase);
  82.     }
  83.  
  84.     CloseLibrary (GfxBase);
  85.     CloseLibrary (IntuitionBase);
  86. }
  87.  
  88. /*** Common tag manipulation routines ************************************/
  89.  
  90. struct TagItem    *nextTagItem(struct TagItem **tp)
  91. {
  92.     struct TagItem *nextti;
  93.  
  94.     /* 'tp' already holds "next" item in list */
  95.     nextti = *tp;
  96.  
  97.     /* walk all TAG_MORE and TAG_IGNORE chaining */
  98.     while ( nextti )
  99.     {
  100.     switch ( nextti->ti_Tag )
  101.     {
  102.     case TAG_MORE:
  103.         nextti = (struct TagItem *) nextti->ti_Data;
  104.         break;
  105.     case TAG_SKIP:
  106.         nextti+= 1 + (int) nextti->ti_Data;
  107.         break;
  108.     case TAG_IGNORE:
  109.         nextti++;
  110.         break;
  111.     case TAG_DONE:
  112.         return ( *tp = NULL );
  113.         break;
  114.     default:    /* a normal tag item    */
  115.         *tp = nextti + 1;
  116.         return ( nextti );
  117.     }
  118.     }
  119.     return ( *tp = NULL );
  120. }
  121.  
  122. struct TagItem    *findTagItem(Tag tag, struct TagItem * ti)
  123. {
  124.     struct TagItem    *tistate;
  125.  
  126.     tistate = ti;
  127.  
  128.     while ( ti = nextTagItem( &tistate ) )
  129.     {
  130.     if ( ti->ti_Tag == tag ) break;
  131.     }
  132.     return ( ti );
  133. }
  134.  
  135. ULONG getTagData(Tag tag, ULONG deflt, struct TagItem *ti)
  136. {
  137.     if ( ti = findTagItem( tag, ti ) )
  138.     {
  139.     return ( ti->ti_Data );
  140.     }
  141.     return ( deflt );
  142. }
  143.  
  144. #define    TEMP_NODE "This AmigaGuideHost is example, that can also\nbe used as a debuggin tool.\n"
  145. #define    LINK "Link: "
  146.  
  147. struct TextAttr TOPAZ8  = {"topaz.font", 8,     NULL, NULL};
  148. struct TextAttr TOPAZ8B = {"topaz.font", 8, FSF_BOLD, NULL};
  149.  
  150. /* We really need the screen, rectangle, and pen spec. */
  151. VOID Display (struct opNodeIO *onm)
  152. {
  153.     struct TagItem *attrs = onm->onm_Attrs;
  154.     struct IntuiText it1 = {NULL};
  155.     struct IntuiText it2 = {NULL};
  156.     struct Rectangle *rect = NULL;
  157.     struct NewWindow nw = {NULL};
  158.     struct Screen *scr = NULL;
  159.     struct IntuiMessage *msg;
  160.     struct Window *win;
  161.     UWORD *pens = NULL;
  162.     BOOL going = TRUE;
  163.     LONG width = 0L;
  164.     WORD w = 640;
  165.     WORD h = 200;
  166.     WORD dif;
  167.  
  168.     /* Get attributes, could be NULL */
  169.     if (attrs)
  170.     {
  171.     scr = (struct Screen *) getTagData (HTNA_Screen, NULL, attrs);
  172.     pens = (UWORD *) getTagData (HTNA_Pens, NULL, attrs);
  173.     rect = (struct Rectangle *) getTagData (HTNA_Rectangle, NULL, attrs);
  174.     }
  175.  
  176.     /* Prepare the IntuiText */
  177.     it1.FrontPen = it2.FrontPen = ((pens) ? pens[SHADOWPEN] : 1);
  178.     it1.DrawMode = it2.DrawMode = JAM1;
  179.     it1.ITextFont = &TOPAZ8;
  180.     it2.ITextFont = &TOPAZ8B;
  181.     it1.IText = LINK;
  182.     it2.IText = onm->onm_Node;
  183.  
  184.     /* Get the width of the first string */
  185.     width = IntuiTextLength (&it1);
  186.     it2.LeftEdge = (SHORT) width;
  187.  
  188.     /* Add in the length of the node name */
  189.     width += IntuiTextLength (&it2);
  190.  
  191.     /* Link the text */
  192.     it1.NextText = &it2;
  193.  
  194.     /* Prepare the window */
  195.     nw.IDCMPFlags = IDCMP_VANILLAKEY | IDCMP_MOUSEBUTTONS;
  196.     nw.Flags = WFLG_BORDERLESS | WFLG_SMART_REFRESH | WFLG_NOCAREREFRESH \
  197.            | WFLG_ACTIVATE;
  198.     nw.Width = 8 + width + 8;
  199.     nw.Height = 16;
  200.     nw.Screen = scr;
  201.     nw.Type = (scr) ? CUSTOMSCREEN : WBENCHSCREEN;
  202.  
  203.     /* Cache the screen size */
  204.     if (scr)
  205.     {
  206.     w = scr->Width;
  207.     h = scr->Height;
  208.     }
  209.  
  210.     /* See if we have a open help window */
  211.     if (rect)
  212.     {
  213.     /* Center the window within the help window */
  214.     nw.LeftEdge = rect->MinX + ((rect->MaxX - nw.Width) / 2);
  215.     nw.TopEdge =  rect->MinY + ((rect->MaxY - nw.Height) / 2);
  216.     }
  217.     /* No help window, so go off the screen */
  218.     else if (scr)
  219.     {
  220.     /* Center the window horizontally under the mouse and place it
  221.      * vertically over the mouse position. */
  222.     nw.LeftEdge = scr->MouseX - (nw.Width / 2);
  223.     nw.TopEdge = scr->MouseY - (nw.Height - 2);
  224.  
  225.     /* Make sure the window can open */
  226.     nw.LeftEdge = (nw.LeftEdge < 0) ? 0 : nw.LeftEdge;
  227.     nw.TopEdge = (nw.TopEdge < 0) ? 0 : nw.TopEdge;
  228.     }
  229.  
  230.     /* Make sure window is on-screen */
  231.     dif = (nw.LeftEdge + nw.Width) - w;
  232.     nw.LeftEdge = (dif > 0) ? nw.LeftEdge - dif : nw.LeftEdge;
  233.     dif = (nw.TopEdge + nw.Height) - h;
  234.     nw.TopEdge = (dif > 0) ? nw.TopEdge - dif : nw.TopEdge;
  235.  
  236.     /* Open the temporary window */
  237.     if (win = OpenWindow (&nw))
  238.     {
  239.     /* Clear the window background */
  240.     SetAPen (win->RPort, ((pens) ? pens[SHADOWPEN] : 1));
  241.     RectFill (win->RPort, 0, 0, (win->Width - 1), (win->Height - 1));
  242.     SetAPen (win->RPort, ((pens) ? pens[SHINEPEN] : 2));
  243.     RectFill (win->RPort, 1, 1, (win->Width - 2), (win->Height - 2));
  244.  
  245.     /* Print the text */
  246.     PrintIText (win->RPort, &it1, 8, 4);
  247.  
  248.     /* Keep on going til the going gets tough */
  249.     while (going)
  250.     {
  251.         /* Wait around for something eventful */
  252.         Wait (1L << win->UserPort->mp_SigBit);
  253.  
  254.         /* Pull each message and handle it */
  255.         while (msg = (struct IntuiMessage *) GetMsg (win->UserPort))
  256.         {
  257.         switch (msg->Class)
  258.         {
  259.             case IDCMP_MOUSEBUTTONS:
  260.             /* Stop if we were touched */
  261.             if (msg->Code == SELECTDOWN)
  262.             {
  263.                 going = FALSE;
  264.             }
  265.             break;
  266.  
  267.             case IDCMP_VANILLAKEY:
  268.             /* Stop on significant keypress */
  269.             if ((msg->Code == 27) || (msg->Code == 13))
  270.             {
  271.                 going = FALSE;
  272.             }
  273.             break;
  274.         }
  275.  
  276.         ReplyMsg ((struct Message *) msg);
  277.         }
  278.     }
  279.  
  280.     /* Close the window */
  281.     CloseWindow (win);
  282.     }
  283. }
  284.  
  285. /* This is your AmigaGuideHost dispatch hook.  It will never run on your
  286.  * own process. */
  287. ULONG __saveds dispatchAmigaGuideHost (struct Hook *h, STRPTR db, Msg msg)
  288. {
  289.     struct opNodeIO *onm = (struct opNodeIO *) msg;
  290.     ULONG retval = 0;
  291.  
  292.     switch (msg->MethodID)
  293.     {
  294.     /* Does this node belong to you? */
  295.     case HM_FindNode:
  296.         {
  297.         struct opFindHost *ofh = (struct opFindHost *) msg;
  298.  
  299.         DB (kprintf ("Find [%s] in %s\n", ofh->ofh_Node, db));
  300.  
  301.         /* See if they want to find our table of contents */
  302.         if ((stricmp (ofh->ofh_Node, "main")) == 0)
  303.         {
  304.             /* Return TRUE to indicate that it's your node,
  305.              * otherwise return FALSE. */
  306.             retval = TRUE;
  307.         }
  308.         else
  309.         {
  310.             /* Display the name of the node */
  311.             Display (onm);
  312.  
  313.             /* Return TRUE to indicate that it's your node,
  314.              * otherwise return FALSE. */
  315.             retval = FALSE;
  316.         }
  317.         }
  318.         break;
  319.  
  320.     /* Open a node. */
  321.     case HM_OpenNode:
  322.         DB (kprintf ("Open [%s] in %s\n", onm->onm_Node, db));
  323.  
  324.         /* See if they want to display our table of contents */
  325.         if ((stricmp (onm->onm_Node, "main")) == 0)
  326.         {
  327.         /* Provide the contents of the node */
  328.         onm->onm_DocBuffer = TEMP_NODE;
  329.         onm->onm_BuffLen = strlen (TEMP_NODE);
  330.         }
  331.         else
  332.         {
  333.         /* Display the name of the node */
  334.         Display (onm);
  335.  
  336.         /* Indicate that we want the node removed from our database,
  337.          * and that we handled the display of the node */
  338.         onm->onm_Flags |= (HTNF_CLEAN | HTNF_DONE);
  339.         }
  340.  
  341.         /* Indicate that we were able to open the node */
  342.         retval = TRUE;
  343.         break;
  344.  
  345.     /* Close a node, that has no users. */
  346.     case HM_CloseNode:
  347.         DB (kprintf ("Close [%s] in %s\n", onm->onm_Node, db));
  348.  
  349.         /* Indicate that we were able to close the node */
  350.         retval = TRUE;
  351.         break;
  352.  
  353.     /* Free any extra memory */
  354.     case HM_Expunge:
  355.         DB (kprintf ("Expunge [%s]\n", db));
  356.         break;
  357.  
  358.     default:
  359.         DB (kprintf ("Unknown method %ld\n", msg->MethodID));
  360.         break;
  361.     }
  362.  
  363.     return (retval);
  364. }
  365.  
  366. /* Main entry point for your AmigaGuideHost dispatch hook */
  367. ULONG __asm hookEntry (
  368.     register __a0 struct Hook *h,
  369.     register __a2 VOID *obj,
  370.     register __a1 VOID *msg)
  371. {
  372.     /* Pass the parameters on the stack */
  373.     return ((h->h_SubEntry)(h, obj, msg));
  374. }
  375.