home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 530b.lha / AMenu_v1.3 / Menu.c < prev    next >
C/C++ Source or Header  |  1991-07-03  |  10KB  |  322 lines

  1. /*********************************************************************\
  2. **                               ________________________________    **
  3. **    A n t h o n y             |________    __    __    ________|   **
  4. **                                       |  |o_|  |o_|  |            **
  5. **            T h y s s e n            __|   __    __   |__          **
  6. **                                  __|   __|  |  |  |__   |__       **
  7. **   `` Dragon Computing ! ''    __|   __|     |  |     |__   |__    **
  8. **                              |_____|        |__|        |_____|   **
  9. **                                                                   **
  10. \*********************************************************************/
  11. /*   Given individual menu entries (Menu,Item,SubItem,CommandChar),
  12. ** add them to the MPort as Extended Menu Items.
  13. ** Calculate positioning information required to complete the menus.
  14. */
  15. #include "AMenu.h"
  16. #include "AllocStr.h"          /* string copy/allocate/deallocate macros */
  17. #include <Graphics/GfxBase.h>  /* so we can get the font width and height */
  18.  
  19. unsigned WBMenus, NextGap, MenuGap;     /* Number WB menus, Menu Pos */
  20. UBYTE    Color[]={2,1}, TColor[]={2,3}; /* Colors :- Items and Title */
  21. USHORT   ItemStyle = HIGHCOMP;          /* MenuItem Highlighting style */
  22. UWORD    FontWidth, FontHeight;         /* size of font in use */
  23.  
  24. struct ExtMenuItem  **EItemList;        /* Last ExtMenuItem in EItemList */
  25. struct Menu         **MenuList, *CurrMenu;
  26. struct MenuItem     **OldItemList, **ItemList, *CurrSubMenu;
  27. unsigned              OldItemPos, ItemPos;
  28.  
  29. DB( int NumMenus; int NumItems; )    /* Debugging variables - memory checks */
  30.  
  31.  
  32. /*   NOTE: The TopEdge entry in the head element of a menu or sub-menu
  33. ** is used to store information about the column structure of that
  34. ** menu.  The macros that follow, map this information in to, and out
  35. ** of this store.
  36. */
  37. #define SHIFTCOLS(n) ((n)&255)
  38. #define SHIFTPOS(n)  (((n)&255)<<8)
  39. #define NUMCOLS(n)   ((n)&255)
  40. #define NUMPOS(n)    (((n)>>8)&255)
  41.  
  42. /*   The LeftEdge entry in individual items (including the sub-menu head
  43. ** item) is used to hold the position number of that item in the final
  44. ** columned array of the menu.
  45. */
  46.  
  47. /*---------------------------------------------------------------*/
  48.  
  49.  
  50. void
  51. StartMenu()
  52.   /* Initialise the facts needed */
  53. {
  54.   struct Menu        *Menu;
  55.   ULONG Ilock;
  56.  
  57.   M->AMenu = NULL;
  58.   MenuList = &M->AMenu;
  59.   M->EItemList = NULL;
  60.   EItemList = &M->EItemList;
  61.   FontWidth  = GfxBase->DefaultFont->tf_XSize; /* font size */
  62.   FontHeight = GfxBase->DefaultFont->tf_YSize;
  63.  
  64.   Ilock = LockIBase(0L);
  65.   Menu = M->WBWindow->MenuStrip;               /* The First WB Menu */
  66.   MenuGap = Menu->NextMenu->LeftEdge -
  67.               (Menu->LeftEdge + Menu->Width);  /* The Gap between WB Menus */
  68.   for( WBMenus=1; Menu->NextMenu; Menu=Menu->NextMenu)  /* Count WB Menus */
  69.     WBMenus++;
  70.   NextGap = Menu->LeftEdge + Menu->Width;      /* Start of Next Menu Gap */
  71.   UnlockIBase(Ilock);
  72.  
  73.   DB( NumMenus = NumItems = 0; )
  74. }
  75.  
  76.  
  77. static void
  78. PositionMenu(ItemList, SavedInfo, Top, Left)
  79.   struct MenuItem  *ItemList;
  80.   unsigned          SavedInfo, Top, Left;
  81. /*   Given an ItemList organise it into a number of Columns
  82. ** Offset by Top and Left (for SubMenus).
  83. ** Assumes that LeftEdge contains the Position Number for
  84. ** each Item in Item List.
  85. */
  86. {
  87.   struct MenuItem *Start, *End;       /* Position within ItemList */
  88.   unsigned  NumColumns, ItemsPerColumn, Column;
  89.  
  90.   NumColumns = NUMCOLS(SavedInfo);
  91.   ItemsPerColumn = NUMPOS(SavedInfo) / NumColumns + 1;
  92.  
  93.   End = ItemList;
  94.  
  95.   for(Column=0; Column<NumColumns; Column++ ) {
  96.     SHORT  Width, ColWidth=0;
  97.  
  98.     Start = End;       /* first Item in column = End of last Column */
  99.  
  100.       /* determine Columns Width and Extent */
  101.     while( End && (End->LeftEdge/ItemsPerColumn) == Column ) {
  102.       Width = End->Width;
  103.       if( End->Flags & COMMSEQ )
  104.         Width += COMMWIDTH + FontWidth + 4;
  105.       if( Width > ColWidth )
  106.         ColWidth = Width;
  107.  
  108.       End = End->NextItem;
  109.     }
  110.  
  111.      /* Position all the Items in Column */
  112.     while( Start != End ) {
  113.  
  114.       /* if their a Sub-Menu within this menu - Position it*/
  115.       if( Start->SubItem )
  116.         PositionMenu( Start->SubItem, Start->TopEdge, 0, ColWidth );
  117.  
  118.        /* position this Item */
  119.       Start->TopEdge  = Top +
  120.                     (Start->LeftEdge % ItemsPerColumn) * (FontHeight+2);
  121.       Start->LeftEdge = Left;
  122.       Start->Width    = ColWidth;
  123.  
  124.       Start = Start->NextItem;
  125.     }
  126.  
  127.     Left = Left + ColWidth + 8;  /* Gap between columns */
  128.   } /* For each Column */
  129.  
  130. }
  131.  
  132.  
  133. BOOL
  134. FinishMenu()
  135.   /* Cleanup New Menus - Postition, Size, etc. */
  136. {
  137.   struct Menu  *Menu;
  138.   BOOL          ScreenOverflow;
  139.  
  140.   DB( Printf("Added -- %ld Menus, %ld Items\n", NumMenus, NumItems); )
  141.  
  142.   ScreenOverflow = ( NextGap > M->WBWindow->Width );
  143.                         /* screen overflow on number of menus ? */
  144.  
  145.   for (Menu = M->AMenu;  Menu;  Menu=Menu->NextMenu) {
  146.     PositionMenu( Menu->FirstItem, Menu->TopEdge, 0, 0 );
  147.     Menu->TopEdge = 0;    /* explictly remove information saved */
  148.   }
  149.  
  150.   return ScreenOverflow;        /* if overflow - have parser WARN user */
  151. }
  152.  
  153.  
  154. /*---------------------------------------------------------------------*/
  155.  
  156. /* create and initialize a new menu item */
  157. struct ExtMenuItem *
  158. AddItem(ItemName, CommandChar)
  159.   char *ItemName, CommandChar;
  160. {
  161.   register struct ExtMenuItem *EItem;
  162.   register struct MenuItem    *Item;
  163.   register struct IntuiText   *IText;
  164.  
  165.   EItem = (struct ExtMenuItem *)
  166.            AllocMem(sizeof(struct ExtMenuItem), MEMF_PUBLIC|MEMF_CLEAR);
  167.   IText = (struct IntuiText *)
  168.            AllocMem(sizeof(struct IntuiText), MEMF_PUBLIC|MEMF_CLEAR);
  169.   Item = (struct MenuItem *)EItem;    /* same object different type */
  170.  
  171.     /* fill out the selection */
  172.   IText->FrontPen = Color[0];
  173.   IText->BackPen  = Color[1];
  174.   IText->DrawMode = JAM2;
  175.   IText->IText    = (UBYTE*)AllocStr(ItemName);
  176.   Item->Height   = FontHeight;
  177.   Item->Width    = IntuiTextLength(IText);
  178.   Item->Flags    = ITEMTEXT | ITEMENABLED | ItemStyle;
  179.   Item->ItemFill = (APTR)IText;
  180.   if( CommandChar ) {
  181.     Item->Command = CommandChar;
  182.     Item->Flags |= COMMSEQ;
  183.   }
  184.  
  185.   *EItemList = EItem;            /* add to EItemList for Free'ing */
  186.   EItemList = &EItem->NextEItem;
  187.  
  188.   *ItemList = Item;              /* add to the current MenuItem chain */
  189.   ItemList = &Item->NextItem;
  190.   Item->LeftEdge = ItemPos++;
  191.  
  192.   DB( NumItems++; )
  193.   return EItem;
  194. }
  195.  
  196.  
  197. void
  198. AddTitle( TitleName )
  199.   char *TitleName;
  200. /* create a Menu Item in the form of a Title
  201. */
  202. {
  203.   struct ExtMenuItem *EItem = AddItem( TitleName, '\0' );
  204.   struct IntuiText *IText =
  205.            (struct IntuiText *)EItem->MenuItem.ItemFill;
  206.   IText->FrontPen = TColor[0];
  207.   IText->BackPen  = TColor[1];
  208.   EItem->MenuItem.Flags = ITEMTEXT | ITEMENABLED | HIGHNONE;
  209. }
  210.  
  211.  
  212. void
  213. AddSkip()
  214. /* skip a position in the Menu Items (Leave a space)
  215. */
  216. {
  217.   ItemPos++;  /* adjust position number for latter items and menu size */
  218. }
  219.  
  220.  
  221. /*-------------------------------------------------------------*/
  222.  
  223. void
  224. AddSubMenu(SubName, NumColumns)
  225.   char *SubName;
  226.   int   NumColumns;
  227. {
  228.   struct ExtMenuItem *EItem = AddItem(SubName, '\0');
  229.   struct MenuItem    *Item  = (struct MenuItem *)EItem;
  230.  
  231.   Item->TopEdge = SHIFTCOLS(NumColumns);  /* store information needed */
  232.  
  233.   CurrSubMenu = Item;
  234.   OldItemList = ItemList;       /* setup item list */
  235.   ItemList = &Item->SubItem;
  236.   OldItemPos = ItemPos;
  237.   ItemPos = 0;
  238. }
  239.  
  240.  
  241. void
  242. EndSubMenu()
  243. /* Cleanup and finalize a SubMenu */
  244. {
  245.   CurrSubMenu->TopEdge |= SHIFTPOS(ItemPos-1); /* last position number */
  246.   ItemPos  = OldItemPos;      /* return to a normal Menu */
  247.   ItemList = OldItemList;
  248. }
  249.  
  250. /*------------------------------------------------------------*/
  251.  
  252. void
  253. AddMenu(MenuName, NumColumns)
  254.   char *MenuName;
  255.   int  NumColumns;
  256. /* Start a new menu attaching it to the AMenu list and storing
  257. ** Information about its characteristics
  258. */
  259.  
  260. {
  261.   struct Menu *Menu = (struct Menu *)
  262.           AllocMem(sizeof(struct Menu), MEMF_PUBLIC|MEMF_CLEAR);
  263.  
  264.   Menu->MenuName = (UBYTE *)AllocStr(MenuName);
  265.   Menu->LeftEdge = NextGap + MenuGap;      /* use menugap on creation */
  266.   Menu->Width = (strlen(MenuName)+1) * FontWidth;
  267.   Menu->Flags = MENUENABLED;
  268.   NextGap = Menu->LeftEdge + Menu->Width;
  269.   Menu->TopEdge = SHIFTCOLS(NumColumns);
  270.  
  271.   CurrMenu = Menu;
  272.   *MenuList = Menu;              /* add to menu list */
  273.   MenuList = &Menu->NextMenu;
  274.   ItemList = &Menu->FirstItem;   /* initialize Item list */
  275.   ItemPos = 0;
  276.  
  277.   DB( NumMenus++; );
  278. }
  279.  
  280.  
  281. void
  282. EndMenu()
  283. /* Finalize the Position Tally for this Menu */
  284. {
  285.   CurrMenu->TopEdge |= SHIFTPOS(ItemPos-1); /* last position number */
  286. }
  287.  
  288. /*------------------------------------------------------------*/
  289.  
  290. void
  291. FreeMenus()
  292.   /* free up all space taken up by our menus */
  293. {
  294.   struct Menu *Menu;
  295.   struct ExtMenuItem *EItem;
  296.   struct IntuiText *IText;
  297.  
  298.   DB( NumMenus = NumItems = 0; )
  299.  
  300.   while( EItem = M->EItemList ) {           /* free all the ExtMenuItems */
  301.     M->EItemList = EItem->NextEItem;
  302.     if( EItem->Cmd )       FreeStr(EItem->Cmd);
  303.     if( EItem->Args )      FreeStr(EItem->Args);
  304.     if( EItem->Console )   FreeStr(EItem->Console);
  305.     if( EItem->Directory ) FreeStr(EItem->Directory);
  306.     IText = (struct IntuiText *)EItem->MenuItem.ItemFill;
  307.     FreeStr(IText->IText);
  308.     FreeMem(IText, sizeof(struct IntuiText));
  309.     FreeMem(EItem, sizeof(struct ExtMenuItem));
  310.     DB( NumItems++; )
  311.   }
  312.  
  313.   while( Menu = M->AMenu ) {             /* Free all the Menus */
  314.     M->AMenu = Menu->NextMenu;
  315.     FreeStr(Menu->MenuName);
  316.     FreeMem(Menu, sizeof(struct Menu));
  317.     DB( NumMenus++; )
  318.   }
  319.   DB( Printf("\nFreed -- %ld Menus, %ld Items\n", NumMenus, NumItems); )
  320. }
  321.  
  322.