home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d0xx / d034 / browser.lha / Browser / menustack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-09-03  |  6.6 KB  |  248 lines

  1. #define MANX
  2. /*
  3.  *  Simple menu package.  Needs lotsa work to handle some cases.
  4.  *
  5.  *  Copyright 1985
  6.  *  Louis A. Mamakos
  7.  *  Software & Stuff
  8.  *  14813 Ashford Place
  9.  *  Laurel, MD  20707
  10.  *
  11.  *  For non-commerical use only.  This program, or any modifications, may not
  12.  *  be sold or incorporated into any product without prior permission from the
  13.  *  author.
  14.  *
  15.  *  Modified by mwm to handle "stacking" menus.
  16.  *    NB - adding item to a menu that's been "popped" back to doesn't work,
  17.  *    and probably never will.
  18.  *     I took at the subitem code at the same time - mwm
  19.  */
  20.  
  21.  
  22. #define SCREENHEIGHT        200
  23. #ifdef MANX
  24. #include <functions.h>
  25. #endif
  26. #include <exec/types.h>
  27. #include <exec/nodes.h>
  28. #include <exec/lists.h>
  29. #include <exec/ports.h>
  30. #include <exec/devices.h>
  31. #include <exec/memory.h>
  32. #include <hardware/blit.h>
  33. #include <graphics/copper.h>
  34. #include <graphics/regions.h>
  35. #include <graphics/rastport.h>
  36. #include <graphics/gfxbase.h>
  37. #include <graphics/gels.h>
  38. #include <intuition/intuition.h>
  39.  
  40. #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub))
  41.  
  42. struct    Mem_Node {
  43.    struct Node mn_Node;
  44.    struct Remember mn_Memory;
  45.    struct Menu *mn_Menu;
  46. #ifdef MANX
  47.    } *Top;
  48. #else
  49.    } *Top, *RemHead();
  50. #endif
  51.  
  52. static struct List Memory;
  53. static int Cur_Menu, Cur_MenuItem, Cur_SubItem;
  54. static struct Menu *LastMenu;
  55. static struct MenuItem *LastMenuItem;
  56.  
  57. struct Menu *AutoMenu;      /* menu struct being dynamically built */
  58.  
  59. char *strsave();        /* Save a string in the remember list */
  60.  
  61. Menu_Init()
  62. {
  63. #ifdef DEBUG
  64. printf("mem init called\n");
  65. #endif
  66.    Memory.lh_Head = (struct Node *) &(Memory.lh_Tail);
  67.    Memory.lh_TailPred = (struct Node *) &(Memory.lh_Head);
  68.    Memory.lh_Tail = NULL;
  69.    Memory.lh_Type = NT_MEMORY;
  70.    Top = NULL;
  71.    Cur_Menu = Cur_MenuItem = -1;
  72.    AutoMenu = LastMenu = NULL;     /* no menu chain yet */
  73.    LastMenuItem = NULL;
  74. }
  75.  
  76. Menu_Clear()
  77. {
  78.  
  79.    while ((Top = RemHead(&Memory)) != NULL) {
  80.       FreeRemember(&(Top->mn_Memory), 1L);
  81.       FreeMem(Top, (long) sizeof(struct Mem_Node));
  82.   }
  83.   Menu_Init();            /* Just for safeties sake */
  84. }
  85.  
  86. Menu_Pop()
  87. {
  88.  
  89.    if ((Top = RemHead(&Memory)) == NULL) return NULL;
  90.    FreeRemember(&(Top->mn_Memory), 1L);
  91.    FreeMem(Top, (long) sizeof(struct Mem_Node));
  92.    /* Now, set Top back to the real list head */
  93.    Top = (struct Mem_Node *) Memory.lh_Head;
  94.    LastMenu = Top->mn_Menu;
  95.    LastMenuItem = NULL;        /* Wrong, but you can't add items here anyway */
  96.    Cur_Menu--;
  97. }
  98. /*
  99.  *  Add a MENU item.  Args are the text of the menu item, and an enable
  100.  *  flag.  Returns an Intuition type menu number, with the MenuItem and
  101.  *  Menu SubItem being NOITEM and NOSUB.  The MENUITEM part is valid.
  102.  */
  103. Menu_Add(name, enabled)
  104. char *name;
  105. long enabled;
  106. {
  107.    register struct Menu *m;
  108. #ifdef DEBUG
  109. printf("menu add:%s\n", name);
  110. #endif
  111.  
  112.    if ((Top = (struct Mem_Node *) AllocMem(
  113.     (long) sizeof(struct Mem_Node), (long) MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  114.       return NULL;
  115.    Top->mn_Node.ln_Type = NT_MEMORY;
  116.  
  117.    if ((m = (struct Menu *)AllocRemember(&(Top->mn_Memory),
  118.      (long) sizeof (struct Menu), (long) MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  119.       return NULL;
  120.    Top->mn_Menu = m;
  121.  
  122. #ifdef DEBUG
  123. printf("mem ok\n");
  124. #endif
  125.  
  126.    if (LastMenu == NULL)
  127.       AutoMenu = m;     /* first menu on list */
  128.    else
  129.       LastMenu->NextMenu = m;      /* link it in */
  130.  
  131.    LastMenuItem = NULL;            /* end of previous MenuItem list */
  132.    Cur_MenuItem = -1; /* reset item numbers */
  133.    if (LastMenu == NULL)
  134.       m->LeftEdge = 0;
  135.    else
  136.       m->LeftEdge = LastMenu->LeftEdge + LastMenu->Width;
  137.    m->TopEdge = 0;
  138.    m->Width = strlen(name) * 8;
  139.    Top->mn_Node.ln_Name = m->MenuName = strsave(name);
  140.    m->Height = 0;
  141.    m->Flags = enabled ? MENUENABLED : 0;
  142.    m->FirstItem = NULL;
  143.    LastMenu = m;
  144.  
  145.    AddHead(&Memory, Top);
  146.    return MNUM(++Cur_Menu, NOITEM, NOSUB);
  147. }
  148.  
  149. /*
  150.  *  Add a menu item to the current MENU.  Note that Add_Menu *must* be
  151.  *  called before this function.
  152.  */
  153. Menu_Item_Add(name, flags, mux, ch)
  154.    char *name;       /* name of menu item */
  155.    long flags;
  156.    LONG mux;         /* mutual exclusion mask */
  157.    BYTE ch;        /* command sequence character, if COMMSEQ */
  158. {
  159.    register struct MenuItem *m, *n;
  160.    register struct IntuiText *it;
  161.  
  162.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  163.    if (LastMenu == NULL)
  164.       return MNUM(NOMENU, NOITEM, NOSUB);
  165.  
  166.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  167.      (long) sizeof(struct MenuItem), (long) MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  168.       return MNUM(NOMENU, NOITEM, NOSUB);
  169.  
  170.    if (LastMenuItem == NULL)
  171.       LastMenu->FirstItem  = m;
  172.    else
  173.       LastMenuItem->NextItem = m;
  174.    m->Flags = flags | ITEMTEXT;
  175.    /*
  176.     *  Check for highlight mode:  if none selected, use HIGHCOMP
  177.     */
  178.    if ((m->Flags & (HIGHCOMP | HIGHBOX)) == 0)
  179.       m->Flags |= HIGHCOMP;
  180.    m->Command = ch;
  181.    m->MutualExclude = mux;
  182.    m->SubItem = NULL;
  183.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  184.           (long)  sizeof(struct IntuiText), (long) MEMF_PUBLIC | MEMF_CLEAR);
  185.    it = (struct IntuiText *) m->ItemFill;
  186.    it->FrontPen = AUTOFRONTPEN;
  187.    it->BackPen = AUTOBACKPEN;
  188.    it->DrawMode = JAM2;
  189.    if (flags & CHECKIT)
  190.       it->LeftEdge = CHECKWIDTH + 1;
  191.    else
  192.       it->LeftEdge = 1;
  193.    it->TopEdge = 1;
  194.    it->ITextFont = NULL;      /* default font */
  195.    it->IText = strsave(name);
  196.    it->NextText = NULL;
  197.    m->Width = 0;
  198.    if (LastMenuItem == NULL) {
  199.       m->TopEdge = 2;
  200.       m->LeftEdge = 0;
  201.    } else if (LastMenuItem->TopEdge + 40 > SCREENHEIGHT) {
  202.       m->TopEdge = 2;
  203.       m->LeftEdge = LastMenuItem->LeftEdge + LastMenuItem->Width + 12;
  204.    } else {
  205.       m->TopEdge = LastMenuItem->TopEdge + 12;
  206.       m->LeftEdge = LastMenuItem->LeftEdge;
  207.    }
  208.    if (flags & CHECKIT)
  209.       m->Width += CHECKWIDTH;
  210.    if (flags & COMMSEQ)
  211.       m->Width += COMMWIDTH + 20;
  212.    m->Width += IntuiTextLength(m->ItemFill);
  213.    m->Height = 10;
  214.    /*
  215.     *  Check last menu item's width to see if it is larger than this
  216.     *  item's.  If new item is larger, then update width of all other
  217.     *  items.
  218.     */
  219.    if (LastMenuItem) {
  220.       if (LastMenuItem->Width > m->Width)
  221.         m->Width = LastMenuItem->Width;
  222.       else {
  223.          register short delta = m->Width - LastMenuItem->Width;
  224.  
  225.      for (n = LastMenu->FirstItem; n != m; n = n->NextItem) {
  226.         n->Width = m->Width;
  227.         if (n->LeftEdge > 0) n->LeftEdge += delta;
  228.      }
  229.      if (m->LeftEdge > 0) m->LeftEdge += delta;
  230.       }
  231.    }
  232.    LastMenuItem = m;
  233.    return MNUM(Cur_Menu, ++Cur_MenuItem, NOSUB);
  234. }
  235.  
  236.  
  237.  
  238. char *
  239. strsave(string) char *string; {
  240.    char *out ;
  241.  
  242.    out = (char *) AllocRemember(&(Top->mn_Memory), (long) strlen(string) + 1,
  243.     (long) MEMF_PUBLIC) ;
  244.    if (out == NULL) return NULL ;
  245.    (void) strcpy(out, string) ;
  246.    return out ;
  247. }
  248.