home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 13 / AACD13.ISO / AACD / Resources / System / BoingBag1 / Contributions / Workbench / RexxArpLib3p6 / src / sreq / simpmenu.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  15KB  |  652 lines

  1. /** simpmenu.c
  2.  *
  3.  *   Simple Menu routines.
  4.  *
  5. **/
  6. #include <exec/types.h>
  7. #include <exec/exec.h>
  8. #include <intuition/intuition.h>
  9. #include <graphics/gfx.h>
  10. #include <functions.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <stdio.h>
  14.  
  15. #include <simpmenu.h>
  16. #include <simpreq.h>
  17.  
  18. static struct MenuItem *SItemY( struct Menu *menu, UBYTE *s, BYTE c, long excl, int dy );
  19. static struct MenuItem *SSItemY( struct Menu *menu, UBYTE *s, BYTE c, long excl, int dy );
  20. static struct Menu *LastMenu( struct Menu *menu );
  21. static struct MenuItem *LastItem( struct MenuItem *item );
  22. static void   FixupItemLength( struct MenuItem *item, int leftedge );
  23. static void   FixupSubItemPos( struct MenuItem *item );
  24. static struct MenuItem *MakeMenuItem( WORD x, WORD y, UBYTE *s, BYTE c, long excl );
  25. static struct MenuItem *FreeItem( struct MenuItem *item );
  26.  
  27. #define MENUSIZE ((long) sizeof(struct Menu))
  28. #define ITEMSIZE ((long) sizeof(struct XMenuItem))
  29. #define COMMANDSIZE   45
  30. #define LINESPACING   10
  31. #define VSLOP          1
  32. #define CHARWIDTH      8
  33. #define MENUOFFSET     5
  34. #define MENUSPACING   10
  35. #define SUBMENUINDENT 10
  36.     
  37.     /**
  38.      *
  39.      *
  40.      *    SMenu(1.0)    ARP Programmers Manual   SMenu(1.0)
  41.      *
  42.      *
  43.      *    NAME
  44.      *   SMenu      -- Allocate and initialize a new Menu structure.
  45.      *
  46.      *    SYNOPSIS
  47.      *   struct Menu *menu = SMenu(menutree, menuname);
  48.      *
  49.      *    FUNCTION
  50.      *   This function is used to create and initialize a new Menu structure.
  51.      *         and link it to a previously created menu tree.
  52.      *
  53.      *    INPUTS
  54.      *         struct Menu *menutree Pointer to a menu tree to be extended
  55.      *                               or NULL to create a first Menu structure.
  56.      *         char *menuname        Name for new menu to be added
  57.      *
  58.      *    RESULT
  59.      *   Pointer to the newly created Menu structure, NULL on failure.
  60.      *
  61.      *    ADDITIONAL CONSIDERATIONS
  62.      *   This routine assumes the necessary libraries to be open.
  63.      *         Typically, this routine is called the first time with a NULL
  64.      *         first argument. This will create the first Menu structure.
  65.      *         Subsequent calls to any of the simple menu functions should all
  66.      *         use that first pointer as a first argument, and the menu will
  67.      *         be built in sequence.
  68.      *
  69.      *    BUGS
  70.      *   None reported sofar.
  71.      *
  72.      *    AUTHOR
  73.      *   W.G.J. Langeveld (WGL)
  74.      *
  75.     **/
  76. struct Menu *SMenu( struct Menu *menu, UBYTE *s)
  77. {
  78.     struct Menu *m, *lm = NULL;
  79.     int    l = 0;
  80.     ULONG *foo;
  81.     ULONG  bar;
  82.     
  83.     lm = LastMenu(menu);
  84.     
  85.     l = MENUOFFSET;
  86.     if (lm)
  87.         l = strlen(lm->MenuName) * CHARWIDTH + lm->LeftEdge + MENUSPACING;
  88.     
  89.     m = AllocMem(MENUSIZE, MEMF_CLEAR);
  90.     if (m == NULL)
  91.         goto cleanup;
  92.     
  93.     m->LeftEdge = l;
  94.     m->Width    = strlen(s) * CHARWIDTH + MENUSPACING;
  95.     m->Flags    = MENUENABLED;
  96.     bar = strlen( s ) + 5;
  97.     foo = (ULONG *) AllocMem( bar, MEMF_CLEAR );
  98.     *foo++ = bar;
  99. //    m->MenuName = (BYTE *) malloc(strlen(s) + 1);
  100.     m->MenuName = (BYTE *) foo;
  101.     if (m->MenuName)
  102.         strcpy(m->MenuName, s);
  103.     else
  104.         goto cleanup;
  105.     
  106.     if (lm)
  107.         lm->NextMenu = m;
  108.     
  109.     return(m);
  110.     
  111.     cleanup:
  112.     if (m)
  113.         FreeSMenu(m);
  114.     
  115.     return(NULL);
  116. }
  117.  
  118.  
  119. /**
  120.  *
  121.  *
  122.  *    SItem(1.0)    ARP Programmers Manual   SItem(1.0)
  123.  *
  124.  *
  125.  *    NAME
  126.  *   SItem      -- Allocate and initialize a new MenuItem structure.
  127.  *
  128.  *    SYNOPSIS
  129.  *   struct MenuItem *item = SItem(menutree, itemname, command, exclude);
  130.  *
  131.  *    FUNCTION
  132.  *   This function is used to create and initialize a new MenuItem structure
  133.  *         and link it to a menutree.
  134.  *
  135.  *    INPUTS
  136.  *         struct Menu *menutree Pointer to a menu tree to be extended
  137.  *         char *itemname        Name of new item to be added
  138.  *         int command           Character to be used in Right-Amiga combination.
  139.  *         long exclude          Mutual Exclude mask (see Intuition manual);
  140.  *                               0L means no check marks, -1L means check mark
  141.  *                               but no mutual exclusion.
  142.  *
  143.  *    RESULT
  144.  *   Pointer to the newly created item, NULL on failure.
  145.  *
  146.  *    ADDITIONAL CONSIDERATIONS
  147.  *   This routine assumes the necessary libraries to be open.
  148.  *         When called, this routine will automatically create the item as a
  149.  *         new line in the menu below the previous item. See SItemB().
  150.  *
  151.  *    BUGS
  152.  *   None reported sofar.
  153.  *
  154.  *    AUTHOR
  155.  *   W.G.J. Langeveld (WGL)
  156.  *
  157.  *
  158. **/
  159. struct MenuItem *SItem( struct Menu *menu, UBYTE *s, BYTE c, long excl )
  160. {
  161.     return(SItemY(menu, s, c, excl, LINESPACING));
  162. }
  163.  
  164. /**
  165.  *
  166.  *
  167.  *    SItemB(1.0)    ARP Programmers Manual   SItemB(1.0)
  168.  *
  169.  *
  170.  *    NAME
  171.  *   SItemB      -- Allocate and initialize a new MenuItem structure.
  172.  *
  173.  *    SYNOPSIS
  174.  *   struct MenuItem *item = SItemB(menutree,itemname,command,exclude);
  175.  *
  176.  *    FUNCTION
  177.  *   This function is used to create and initialize a new MenuItem structure
  178.  *         and link it to a menutree.
  179.  *
  180.  *    INPUTS
  181.  *         struct Menu *menutree Pointer to a menu tree to be extended
  182.  *         char *itemname        Name of new item to be added
  183.  *         BYTE command           Character to be used in Right-Amiga combination.
  184.  *         long exclude          Mutual Exclude mask (see Intuition manual);
  185.  *                               0L means no check marks, -1L means check mark
  186.  *                               but no mutual exclusion.
  187.  *
  188.  *    RESULT
  189.  *   Pointer to the newly created item, NULL on failure.
  190.  *
  191.  *    ADDITIONAL CONSIDERATIONS
  192.  *   This routine assumes the necessary libraries to be open.
  193.  *         When called, this routine will automatically create the item on the
  194.  *         same line in the menu to the right of the previous item. See SItem().
  195.  *
  196.  *    BUGS
  197.  *   None reported sofar.
  198.  *
  199.  *    AUTHOR
  200.  *   W.G.J. Langeveld (WGL)
  201.  *
  202.  *
  203. **/
  204. struct MenuItem *SItemB( struct Menu *menu, UBYTE *s, BYTE c, long excl )
  205. {
  206.     return(SItemY(menu, s, c, excl, 0));
  207. }
  208.  
  209. /**
  210.  *
  211.  *
  212.  *    SSItem(1.0)    ARP Programmers Manual   SSItem(1.0)
  213.  *
  214.  *
  215.  *    NAME
  216.  *   SSItem      -- Allocate and initialize a new MenuItem structure.
  217.  *
  218.  *    SYNOPSIS
  219.  *   struct MenuItem *item = SSItem(menutree,itemname,command,exclude);
  220.  *
  221.  *    FUNCTION
  222.  *   This function is used to create and initialize a new MenuItem structure
  223.  *         and link it to a menutree.
  224.  *
  225.  *    INPUTS
  226.  *         struct Menu *menutree Pointer to a menu tree to be extended
  227.  *         UBYTE *itemname       Name of new subitem to be added
  228.  *         BYTE command          Character to be used in Right-Amiga combination.
  229.  *         long exclude          Mutual Exclude mask (see Intuition manual);
  230.  *                               0L means no check marks, -1L means check mark
  231.  *                               but no mutual exclusion.
  232.  *
  233.  *    RESULT
  234.  *   Pointer to the newly created subitem, NULL on failure.
  235.  *
  236.  *    ADDITIONAL CONSIDERATIONS
  237.  *   This routine assumes the necessary libraries to be open.
  238.  *         When called, this routine will automatically create the subitem as a
  239.  *         new line in the submenu below the previous subitem.
  240.  *         See SSItemB().
  241.  *
  242.  *    BUGS
  243.  *   None reported sofar.
  244.  *
  245.  *    AUTHOR
  246.  *   W.G.J. Langeveld (WGL)
  247.  *
  248.  *
  249. **/
  250. struct MenuItem *SSItem( struct Menu *menu, UBYTE *s, BYTE c, long excl )
  251. {
  252.     return(SSItemY(menu, s, c, excl, LINESPACING));
  253. }
  254.  
  255. /**
  256.  *
  257.  *
  258.  *    SSItemB(1.0)    ARP Programmers Manual   SSItemB(1.0)
  259.  *
  260.  *
  261.  *    NAME
  262.  *   SSItemB  -- Allocate and initialize a new MenuItem structure.
  263.  *
  264.  *    SYNOPSIS
  265.  *   struct MenuItem *item=SSItemB(menutree,itemname,command,exclude);
  266.  *
  267.  *    FUNCTION
  268.  *   This function is used to create and initialize a new MenuItem structure
  269.  *         and link it to a menutree.
  270.  *
  271.  *    INPUTS
  272.  *         struct Menu *menutree Pointer to a menu tree to be extended
  273.  *         char *itemname        Name of new subitem to be added
  274.  *         BYTE command          Character to be used in Right-Amiga combination.
  275.  *         long exclude          Mutual Exclude mask (see Intuition manual);
  276.  *                               0L means no check marks, -1L means check mark
  277.  *                               but no mutual exclusion.
  278.  *
  279.  *    RESULT
  280.  *   Pointer to the newly created subitem, NULL on failure.
  281.  *
  282.  *    ADDITIONAL CONSIDERATIONS
  283.  *   This routine assumes the necessary libraries to be open.
  284.  *         When called, this routine will automatically create the subitem on the
  285.  *         same line in the submenu to the right of the previous subitem.
  286.  *         See SSItem().
  287.  *
  288.  *    BUGS
  289.  *   None reported sofar.
  290.  *
  291.  *    AUTHOR
  292.  *   W.G.J. Langeveld (WGL)
  293.  *
  294.  *
  295. **/
  296. struct MenuItem *SSItemB( struct Menu *menu, UBYTE *s, BYTE c, long excl )
  297. {
  298.     return(SSItemY(menu, s, c, excl, 0));
  299. }
  300.  
  301. /**
  302.  *
  303.  *
  304.  *    FreeSMenu(1.0)    ARP Programmers Manual   FreeSMenu(1.0)
  305.  *
  306.  *
  307.  *    NAME
  308.  *   FreeSMenu  -- Allocate and initialize a new MenuItem structure.
  309.  *
  310.  *    SYNOPSIS
  311.  *   struct Menu *menu = FreeSMenu(menutree);
  312.  *
  313.  *    FUNCTION
  314.  *   This function is used to free all resources allocated for a particular
  315.  *         menutree.
  316.  *
  317.  *    INPUTS
  318.  *         struct Menu *menutree Pointer to a menu tree to be freed
  319.  *
  320.  *    RESULT
  321.  *   Guaranteed NULL.
  322.  *
  323.  *    ADDITIONAL CONSIDERATIONS
  324.  *   This routine assumes the necessary libraries to be open.
  325.  *         This routine uses recursion.
  326.  *
  327.  *    BUGS
  328.  *   None reported sofar.
  329.  *
  330.  *    AUTHOR
  331.  *   W.G.J. Langeveld (WGL)
  332.  *
  333.  *
  334. **/
  335. struct Menu *FreeSMenu( struct Menu *menu )
  336. {
  337.     ULONG *foo;
  338.     
  339.     if (menu == NULL)
  340.         return(NULL);
  341.     
  342.     FreeSMenu(menu->NextMenu);
  343.     
  344.     if (menu->FirstItem)
  345.         menu->FirstItem = FreeItem(menu->FirstItem);
  346.     
  347.     foo = (ULONG *) menu->MenuName;
  348.     foo--;
  349.     FreeMem( foo, *foo );
  350. //    free(menu->MenuName);
  351.     FreeMem(menu, MENUSIZE);
  352.     
  353.     return(NULL);
  354. }
  355.  
  356. /**
  357.  *
  358.  *   Adjust the menu items and subitems.
  359.  *
  360. **/
  361. void AdjustItems( struct Menu *menu )
  362. {
  363.     struct MenuItem *item;
  364.     
  365.     while (menu) 
  366.     {
  367.         item = menu->FirstItem;
  368.         FixupItemLength(item, menu->LeftEdge);
  369.         while (item) 
  370.         {
  371.             if (item->SubItem)
  372.                 FixupItemLength(item->SubItem,
  373.             menu->LeftEdge + item->LeftEdge + item->Width - SUBMENUINDENT);
  374.             item = item->NextItem;
  375.         }
  376.         menu = menu->NextMenu;
  377.     }
  378.     return;
  379. }
  380.  
  381.  
  382. /**
  383.  *
  384.  *   Internal routines
  385.  *   ======== ========
  386.  *
  387. **/
  388.  
  389. /**
  390.  *
  391.  *   Internal routine: creates a new menu item with a certain line spacing.
  392.  *
  393. **/
  394. static struct MenuItem *SItemY( struct Menu *menu, UBYTE *s, BYTE c, long excl, int dy )
  395. {
  396.     struct Menu *lm = NULL;
  397.     struct MenuItem *i, *li = NULL;
  398.     int itemy = 0, itemx = 0;
  399.     
  400.     lm = LastMenu(menu);
  401.     if (lm == NULL)
  402.         return(NULL);
  403.     
  404.     li = LastItem(lm->FirstItem);
  405.     if (li) 
  406.     {
  407.         if (!dy)
  408.             itemx = li->LeftEdge + li->Width;
  409.         itemy = li->TopEdge + dy;
  410.     }
  411.     
  412.     i = MakeMenuItem(itemx, itemy, s, c, excl);
  413.     
  414.     if (li)
  415.         li->NextItem  = i;
  416.     else
  417.         lm->FirstItem = i;
  418.     
  419.     return(i);
  420.     
  421.     cleanup:
  422.     if (i)
  423.         FreeItem(i);
  424.     
  425.     return(NULL);
  426. }
  427.  
  428. /**
  429.  *
  430.  *   Internal routine: creates a new subitem with a certain line spacing.
  431.  *
  432. **/
  433. static struct MenuItem *SSItemY( struct Menu *menu, UBYTE *s, BYTE c, long excl, int dy )
  434. {
  435.     struct Menu *lm = NULL;
  436.     struct MenuItem *i, *li = NULL, *lsi = NULL;
  437.     int sitemy = 0, sitemx = 0;
  438.     
  439.     lm = LastMenu(menu);
  440.     if (lm == NULL)
  441.         return(NULL);
  442.     
  443.     li = LastItem(lm->FirstItem);
  444.     if (li == NULL)
  445.         return(NULL);
  446.     
  447.     sitemx = li->LeftEdge + li->Width - SUBMENUINDENT;
  448.     
  449.     lsi = LastItem(li->SubItem);
  450.     if (lsi) 
  451.     {
  452.         if (!dy)
  453.             sitemx = lsi->LeftEdge + lsi->Width;
  454.         sitemy = lsi->TopEdge + dy;
  455.     }
  456.     
  457.     i = MakeMenuItem(sitemx, sitemy, s, c, excl);
  458.     
  459.     if (lsi)
  460.         lsi->NextItem = i;
  461.     else
  462.         li->SubItem   = i;
  463.     
  464.     return(i);
  465.     
  466.     cleanup:
  467.     if (i)
  468.         FreeItem(i);
  469.     
  470.     return(NULL);
  471. }
  472.  
  473. /**
  474.  *
  475.  *   Internal routine: returns the last non-NULL menu pointer in a list of menus.
  476.  *
  477. **/
  478. static struct Menu *LastMenu( struct Menu *menu )
  479. {
  480.     struct Menu *lm = menu;
  481.     
  482.     while (menu) 
  483.     {
  484.         menu = lm->NextMenu;
  485.         if (menu)
  486.             lm = menu;
  487.     }
  488.     return(lm);
  489. }
  490.  
  491. /**
  492.  *
  493.  *   Internal routine: returns the last non-NULL item in a list of items.
  494.  *
  495. **/
  496. static struct MenuItem *LastItem( struct MenuItem *item )
  497. {
  498.     struct MenuItem *li = item;
  499.     
  500.     while (item) 
  501.     {
  502.         item = item->NextItem;
  503.         if (item)
  504.             li = item;
  505.     }
  506.     return(li);
  507. }
  508.  
  509. /**
  510.  *
  511.  *   Internal routine: computes the longest menu item and makes all others
  512.  *   have the same length hitbox.
  513.  *
  514. **/
  515. static void FixupItemLength( struct MenuItem *item, int leftedge )
  516. {
  517.     int l = 0, m = 0, commset = 0, le = 0;
  518.     struct MenuItem *fi = item;
  519.     
  520.     while (item) 
  521.     {
  522.         m = strlen( ((struct IntuiText *) item->ItemFill)->IText ) * CHARWIDTH;
  523.         if (item->Command) 
  524.         {
  525.             commset = 1;
  526.             if (item->Command == -1)
  527.                 m -= COMMANDSIZE;
  528.         }
  529.         if (m > l)
  530.             l = m;
  531.         
  532.         item = item->NextItem;
  533.     }
  534.     
  535.     if (commset)
  536.         l += COMMANDSIZE;
  537.     else
  538.         l += CHARWIDTH;
  539.     /*
  540.      *   Fix up menus that fall off the edge
  541.      */
  542.     if (l + leftedge > 630)
  543.         le = 630 - l - leftedge;
  544.     
  545.     item = fi;
  546.     while (item) 
  547.     {
  548.         item->Width     = l;
  549.         item->LeftEdge += le;
  550.         if (item->SubItem)
  551.             FixupSubItemPos(item);
  552.         item = item->NextItem;
  553.     }
  554.     return;
  555. }
  556.  
  557. /**
  558.  *
  559.  *   Internal routine: Goes through a list of items and aligns all subitem
  560.  *   hitboxes with the right edge.
  561.  *
  562. **/
  563. static void FixupSubItemPos( struct MenuItem *item )
  564. {
  565.     int l = 0, m = 0;
  566.     struct MenuItem *i = NULL;
  567.     
  568.     if (item == NULL)
  569.         return;
  570.     
  571.     if (i = item->SubItem)
  572.         m = 5000;
  573.     while (i) 
  574.     {
  575.         if (i->LeftEdge < m)
  576.             m = i->LeftEdge;
  577.         i = i->NextItem;
  578.     }
  579.     
  580.     l = item->LeftEdge + item->Width - SUBMENUINDENT - m;
  581.     
  582.     i = item->SubItem;
  583.     while (i) 
  584.     {
  585.         i->LeftEdge += l;
  586.         i = i->NextItem;
  587.     }
  588.     return;
  589. }
  590.  
  591. /**
  592.  *
  593.  *   Internal routine: Allocate a MenuItem plus room for a UserData pointer
  594.  *   and initialize it.
  595.  *
  596. **/
  597. static struct MenuItem *MakeMenuItem( WORD x, WORD y, UBYTE *s, BYTE c, long excl )
  598. {
  599.     struct MenuItem *i = NULL;
  600.     struct IntuiText *MakeSIText();
  601.     
  602.     i = AllocMem(ITEMSIZE, MEMF_CLEAR);
  603.     if (i == NULL)
  604.         return(NULL);
  605.     
  606.     
  607.     i->Flags = ITEMTEXT + ITEMENABLED + HIGHCOMP;
  608.     if (c && (c != -1))
  609.         i->Flags |= COMMSEQ;
  610.     if (excl)
  611.         i->Flags |= CHECKIT;
  612.     if (excl == -1L)
  613.         i->Flags |= MENUTOGGLE;
  614.     
  615.     i->LeftEdge = x;
  616.     i->TopEdge  = y;
  617.     i->Height   = LINESPACING;
  618.     
  619.     i->Width = strlen(s) * CHARWIDTH;
  620.     if (c && (c != -1))
  621.         i->Width += COMMANDSIZE;
  622.     
  623.     if (excl && excl != -1L)
  624.         i->MutualExclude = excl;
  625.     i->Command  = c;
  626.     i->ItemFill = (APTR) MakeSIText(0, 1, (int) JAM1, 0, VSLOP, s);
  627.     
  628.     return(i);
  629. }
  630.  
  631. /**
  632.  *
  633.  *   Internal routine: free all resources associated with an item list.
  634.  *
  635. **/
  636. static struct MenuItem *FreeItem( struct MenuItem *item )
  637. {
  638.     if (item == NULL)
  639.         return(NULL);
  640.     
  641.     FreeItem(item->NextItem);
  642.     
  643.     if (item->SubItem)
  644.         item->SubItem = FreeItem(item->SubItem);
  645.     
  646.     FreeSIText(item->ItemFill);
  647.     FreeMem(item, ITEMSIZE);
  648.     
  649.     return(NULL);
  650. }
  651.  
  652.