home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / new / misc / sci / splines / popmenu.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  10KB  |  309 lines

  1. /* The routines in this file are copyright (c) 1987 by Helene (Lee) Taran.
  2.  * Permission is granted for use and free distribution as long as the
  3.  * original author's name is included with the code.
  4.  */
  5.  
  6. /*
  7.  * Reformatted, and modified to compile without warnings and errors
  8.  * under SAS/C -6.5x by gduncan@philips.oz.au (GMD). This included
  9.  * proto generation, renaming of some literals to avoid name collisions,
  10.  * and Amiga Version string (also displayed in Title bar).
  11.  * No original version number, this version arbitrarily named 1.1. 
  12.  * - otherwise no functional changes.
  13.  * GMD - Sep 94
  14.  */
  15.  
  16. #include "all.h"
  17.  
  18. LAYER_INFO *PopUp_LayerInfo;
  19. TEXTFONT *menufont;
  20.  
  21. /* User should call Init_MenuPackage() before trying to pop up any
  22.  * menus. Will return TRUE if the package has been initialized correctly.
  23.  * Do not attempt to use this package if this initialization routine 
  24.  * returns FALSE.
  25.  */
  26.  
  27. BOOL
  28. Init_MenuPackage ()
  29. {
  30.   static TEXTATTR MenuFont =
  31.   {(UBYTE *) "topaz.font", 8, 0, 0};
  32.  
  33.   if (!(menufont = OpenFont (&MenuFont)))
  34.     {
  35.       fprintf (stderr, "sorry couldn't find topaz eight for menu font]\n");
  36.       return (FALSE);
  37.     }
  38.   if (!(PopUp_LayerInfo = (LAYER_INFO *) NewLayerInfo ()))
  39.     {
  40.       fprintf (stderr, "sorry, couldn't allocate a layer info structure\n");
  41.       return (FALSE);
  42.     }
  43.   return (TRUE);
  44. }
  45.  
  46. /* The user should call Close_MenuPackage before exiting their program
  47.  * to ensure that the menu package releases any memory that it
  48.  * has allocated for its own use. 
  49.  */
  50.  
  51. void
  52. Close_MenuPackage ()
  53. {
  54.   CloseFont (menufont);
  55.   if (PopUp_LayerInfo != NULL)
  56.     DisposeLayerInfo (PopUp_LayerInfo);
  57.  
  58. }
  59.  
  60. BOOL
  61. Init_PopUp_Menu (menu)
  62.      SPL_POPUP_MENU *menu;
  63. {
  64.  
  65.   SPL_POPUP_ITEM *item;
  66.   int longest = 0;
  67.   int total_height = 0;
  68.   int i;
  69.  
  70.   if (menu == NULL)
  71.     return (FALSE);
  72.   item = menu->first_item;
  73.   while (item != NULL)
  74.     {
  75.       /* note: bad things may happen if you allocate an empty string for
  76.        * your item text.
  77.        */
  78.  
  79.       i = strlen (item->text);    /* GMD ; extract to deconfuse compiler */
  80.  
  81.       item->width = MAX (item->width, FONT_WIDTH * i);
  82.       item->left = MAX (0, item->left);
  83.       longest = MAX (longest, (item->width + item->left));
  84.       item->height = MAX (item->height, FONT_HEIGHT);
  85.       item->top = MAX (0, item->top);
  86.       total_height += (item->height + item->top);
  87.       /* re-initialize item-top to be the top relative to the menu top */
  88.       item->top = (total_height - item->height);
  89.       item = item->next;
  90.     }
  91.   menu->height = total_height + 1;
  92.   menu->width = MAX (menu->width, longest);
  93.  
  94.   /* initialize a bitmap the same size as the required menu image  */
  95.   /* initialize a raster port to facillitate drawing into the bitmap */
  96.   InitBitMap (&(menu->bitmap), menu->depth, menu->width, menu->height);
  97.   InitRastPort (&(menu->rp));
  98.  
  99. #if 1
  100.   SetFont (&menu->rp, menufont);    /*GMD */
  101. #else
  102.   SetFont (menu->rp, menufont);
  103. #endif
  104.  
  105.   for (i = 0; i < menu->depth; i++)
  106.     if (!(menu->bitmap.Planes[i] = (PLANEPTR)
  107.       AllocRaster (menu->width, menu->height)))
  108.       {
  109.     Dispose_PopUp (menu);
  110.     return (FALSE);
  111.       }
  112.   menu->rp.BitMap = &(menu->bitmap);
  113.   menu->cr.BitMap = &(menu->bitmap);
  114.  
  115.   /* draw the menu outline and background color into its own bitmap */
  116.   SetDrMd (&(menu->rp), JAM1);
  117.   SetAPen (&(menu->rp), menu->area_color);
  118.   SetOPen (&(menu->rp), menu->outline_color);
  119.  
  120.   RectFill (&(menu->rp), 0, 0, menu->width - 1, menu->height - 1);
  121.   BNDRYOFF (&(menu->rp));    /* turn off the raster port outlining */
  122.  
  123.   item = menu->first_item;
  124.  
  125.   /* Now, draw each menu item */
  126.   while (item != NULL)
  127.     {
  128.       SetAPen (&(menu->rp), item->color);
  129.       Move (&(menu->rp), item->left, item->top + FONT_BASELINE);
  130.       Text (&(menu->rp), item->text, strlen (item->text));
  131.       item = item->next;
  132.     }
  133.   return (TRUE);
  134. }
  135.  
  136. /* SelectItem : activates the item located at <x,y>. Assumes the <menu>
  137.  * is currently active and thus, menu->left and menu->top should represent
  138.  * the menu's current top,left corner.  If there is an item located
  139.  * at <x,y> within the menu, then it is made 'active' ...this means
  140.  * that the item becomes menu->active_item and is highlighted. The
  141.  * old menu->active_item, if any, is deselected. Note: if you're using
  142.  * a GIMMEZEROZERO window you'll have to fiddle with the x,y coordinates.
  143.  */
  144.  
  145. void
  146. SelectItem (menu, Window)
  147.      SPL_POPUP_MENU *menu;
  148.      WINDOW *Window;
  149. {
  150.   SPL_POPUP_ITEM *item;
  151.  
  152.   SHORT x = Window->MouseX + Window->LeftEdge;
  153.   SHORT y = Window->MouseY + Window->TopEdge;
  154.  
  155.   item = menu->first_item;
  156.   x -= menu->left;
  157.   y -= menu->top;
  158.   if ((x >= 0) && (x < menu->width) && (y >= 0) && (y < menu->height))
  159.     while (item != NULL)
  160.       {
  161.     if ((y >= item->top - 1) && (y < item->top - 1 + item->height))
  162.       break;        /* we found an active item {yeah yeah...bad style, i know...} */
  163.     else
  164.       item = item->next;
  165.       }
  166.   else
  167.     item = NULL;        /* mouse isn't on menu */
  168.  
  169.   if (menu->active_item != item)
  170.     {                /* deselect previously active item */
  171.       ComplementItem (menu, menu->active_item, Window);
  172.       ComplementItem (menu, item, Window);
  173.     }
  174.   menu->active_item = item;
  175. }
  176.  
  177.  
  178.  
  179.  
  180. /* ComplementItem : complements the given menu item area.  Assumes that
  181.  * the <menu> is currently being displayed and thus,the current menu->left
  182.  * and menu->top represent the current coordinates of the menu's top,left
  183.  * corner.  Assumes the <item> is  an popup_item that belongs to <menu>
  184.  * and that its left/top offsets have been initialized.
  185.  */
  186.  
  187. void
  188. ComplementItem (menu, item, Window)
  189.      SPL_POPUP_MENU *menu;
  190.      SPL_POPUP_ITEM *item;
  191.      WINDOW *Window;
  192. {
  193.   BYTE old_mode = Window->WScreen->RastPort.DrawMode;
  194.  
  195.   if (item == NULL)
  196.     return;            /* do nothing */
  197.   SetDrMd (&(Window->WScreen->RastPort), COMPLEMENT);
  198.   RectFill (&(Window->WScreen->RastPort), menu->left,
  199.         menu->top + item->top - 1,
  200.         menu->left + menu->width - 1,
  201.         menu->top + item->top + item->height - 2);
  202.   SetDrMd (&(Window->WScreen->RastPort), (int) old_mode);
  203. }
  204.  
  205. /* PopUp : this is one of those 'do everything' type of functions. It
  206.  * displays the <menu> in the window  given its upper left hand 
  207.  * coordinates <left,top>.  It tracks the user's mouse movements,
  208.  * highlighting the currently active item until the user deselects
  209.  * the menu by releasing the mouse's select button, at which time,
  210.  * this function will remove the menu from the display. Returns the
  211.  * selection_id of the item that was active when the user releases
  212.  * the select button. Returns 0 if nothing was selected.
  213.  * Assumes that the <menu> has been initialized by a call to 
  214.  * Init_SPL_POPUP_MENU and that the user has requested ReportMouse for the
  215.  * Window in question (ReportMouse makes sure that the Window's MouseX and
  216.  * MouseY coordinates are kept up to date).
  217.  */
  218. int
  219. PopUp (menu, Window)
  220.      SPL_POPUP_MENU *menu;
  221.      WINDOW *Window;
  222. {
  223.   ULONG oldflags;
  224.   SHORT left, top;
  225.  
  226.   left = Window->MouseX;
  227.   top = Window->MouseY;
  228.   if (!Inside_Window (left, top, Window))
  229.     return (OUTSIDE_WINDOW);
  230.  
  231.   if ((menu->width <= Window->Width) && (left + menu->width > Window->Width))
  232.     left += Window->Width - (left + menu->width);
  233.  
  234.   if ((menu->height <= Window->Height) && (top + menu->height > Window->Height))
  235.     top += Window->Height - (top + menu->height);
  236.  
  237.   LockLayers (PopUp_LayerInfo);
  238.  
  239.   /* SwapBits...() requires that the clipping rectangle's bounds are given
  240.    * with respect to the screen's 0,0 coordinate but mouse movements
  241.    * are reported to the Window and are given in terms of the window's
  242.    * coordinate system so...sLeft and sTop represent the adjustment of
  243.    * the Window's coordinates to match the screen's coordinates.
  244.    * Note: if you're using a GIMMEZEROZERO window, you'll have to muck
  245.    * with the left,top coordinates to get the complementing to work.
  246.    */
  247.   left = (left + Window->LeftEdge) & 0xfff0;
  248.   top = top + Window->TopEdge;
  249.  
  250.   menu->cr.bounds.MinX = left;
  251.   menu->cr.bounds.MinY = top;
  252.   menu->cr.bounds.MaxX = left + menu->width - 1;
  253.   menu->cr.bounds.MaxY = top + menu->height - 1;
  254.   SwapBitsRastPortClipRect (Window->RPort, &(menu->cr));
  255.  
  256.   menu->left = left;
  257.   menu->top = top;
  258.   SelectItem (menu, Window);
  259.   oldflags = Window->IDCM