home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_GEN / FACETV.ZIP / MENUBARS.CPP < prev    next >
C/C++ Source or Header  |  1994-01-04  |  7KB  |  246 lines

  1. /************************************************************************
  2. **
  3. ** @(#)menubars.cpp    04/01/93    Chris Ahlstrom
  4. **
  5. **  ------------------------
  6. **  73340.26!compuserve.com
  7. **  ------------------------
  8. **
  9. **    Routines for handling generic menu-bars and drop-down menus
  10. ** that are specified not by code, but by a set of data structures
  11. ** suitable for use by Borland's Turbo Vision.
  12. **
  13. **    Also handles the status line.
  14. **
  15. *************************************************************************/
  16.  
  17. #define MENUBARS_cpp        // just in case
  18.  
  19. #if defined(__BORLANDC__)
  20. #pragma warn -amp        // ignore superfluous "&" warning
  21. #endif
  22.  
  23. #include "menubars.h"        // class definition
  24.  
  25. #if defined(__BORLANDC__)
  26. #pragma warn .amp        // restore superfluous "&" warning
  27. #endif
  28.  
  29.  
  30. /************************************************************************
  31. ** MenuBarApp constructor
  32. *************************************************************************/
  33.  
  34. MenuBarApp::MenuBarApp ()
  35.  :
  36.     TProgInit                // initialize the desktop
  37.     (
  38.     MenuBarApp::initStatusLine,
  39.     MenuBarApp::initMenuBar,
  40.     MenuBarApp::initDeskTop
  41.     )
  42. {
  43. }
  44.  
  45. /************************************************************************
  46. ** MenuBarApp destructor unnecessary
  47. *************************************************************************/
  48.  
  49. /************************************************************************
  50. ** Overloading "+" for TMenuItems
  51. **
  52. **    Menu items are always in a linked list.  Since the "+" operator
  53. ** is processed from left-to-right, we define it as appending item 2
  54. ** to the end of item 1, and returning item 1.
  55. **
  56. *************************************************************************/
  57.  
  58. TMenuItem& operator +
  59. (
  60.     TMenuItem& item1,
  61.     TMenuItem& item2
  62. )
  63. {
  64.     TMenuItem *p = &item1;    // start at the first item
  65.  
  66.     while (p->next != NULL)    // traverse to the end of the item
  67.     {
  68.     p = p->next;
  69.     }
  70.     p->next = &item2;        // insert item 2
  71.  
  72.     return item1;        // return original first item
  73. }
  74.  
  75.  
  76. /************************************************************************
  77. ** MenuBarApp::menuBox()
  78. **
  79. **    This global function knows how to recursively handle a nested
  80. ** list of menus as defined in tvmenus.h.
  81. **
  82. **    It returns a null pointer if a problem occurred.
  83. **
  84. **    See mt32app.men for examples of the NestItems structures used.
  85. **
  86. *************************************************************************/
  87.  
  88. TMenuItem *
  89. MenuBarApp::menuBox
  90. (
  91.     NestPtr n
  92. )
  93. {
  94.     TMenuItem *anchor, *tmi;
  95.     int ncount = 0;
  96.  
  97.     if (n->item != MENU_TERMINATE)        // bogus empty menu?
  98.     {
  99.     if (*n->item == NEWLINE)        // bogus, new-line at start
  100.     {
  101.         anchor = (TMenuItem *) 0;        // return an error code
  102.     }
  103.     else
  104.     {
  105.         while (n->item != MENU_TERMINATE)    // handle every menu item
  106.         {
  107.         if (n->nest == MENU_END_NEST)    // menu item is a leaf
  108.         {
  109.             if (*n->item == NEWLINE)    // menu item is just a line
  110.             tmi = &newLine();
  111.             else
  112.             tmi = new TMenuItem    // add the leaf item
  113.             (
  114.                 n->item, n->cmcode, n->key, n->help, n->label
  115.             );
  116.         }
  117.         else if (*n->item == NEWLINE)    // menu item is just a line
  118.         {
  119.             tmi = &newLine();
  120.         }
  121.         else                // menu item not a leaf
  122.         {
  123.             tmi = new TMenuItem
  124.             (
  125.             n->item,
  126.             n->key,
  127.             new TMenu        // create a sub-menu
  128.             (
  129.                 *menuBox(n->nest)    // recursive call
  130.             ),
  131.             n->help
  132.             );
  133.         }
  134.         if (ncount == 0)        // first case
  135.             anchor = tmi;        // start the linked list
  136.         else
  137.             *anchor = *anchor + *tmi;    // append to linked list
  138.  
  139.         ncount++;            // count the case
  140.         n++;                // finished first one
  141.         }
  142.     }
  143.     }
  144.     else
  145.     {
  146.     anchor = (TMenuItem *) 0;        // return an error code
  147.     }
  148.  
  149.     return anchor;
  150. }
  151.  
  152.  
  153. /************************************************************************
  154. ** MenuBarApp::initMenuBar
  155. **
  156. **    Rather than hard-wiring the menubar and it's entries, we leave
  157. ** an opening for the usage of resources.  Right now, it's still very
  158. ** primitive... the resource is essentially part of a C++ header file
  159. ** (*.men) that sets up the menu.
  160. **
  161. **    Basically, we take two linear lists of entries (one for the
  162. ** menubar, and one for each set of entries in the menubar), and
  163. ** dynamically use the lists to build the menu tree.
  164. **
  165. **    We create the first entry (TSubMenu) in the menubar tree;
  166. ** this entry anchors the whole tree.  We then add its menu-items.
  167. ** The rest of the main entries are added, and, for each, we add
  168. ** the menu-items.
  169. **
  170. **    Note that any menu-item with a newline for a label is simply
  171. ** inserted as a straightline (see MENU_NEWLINE in midi_ex.men, and
  172. ** NEWLINE here, below).
  173. **
  174. ** New parameters:
  175. **
  176. **    menubar
  177. **    menubarsize
  178. **
  179. **    These parameters get copied to their global versions (menuBar
  180. ** and menuBarSize).
  181. **
  182. *************************************************************************/
  183.  
  184. TMenuBar *
  185. MenuBarApp::initMenuBar
  186. (
  187.     TRect r
  188. )
  189. {
  190.     TSubMenu *mb;            // to be an alias for menu bar
  191.     const NestBar *bar;            // pointer to main list
  192.     const Nests *men;            // pointer to current sub-menu
  193.     TMenuItem *m;            // pointer to current menu-item
  194.  
  195.     bar = menuBar;            // point to first sub-menu
  196.     men = bar->items;            // point to first item in menu
  197.     for (int i = 0; i < bar->barCount; i++, men++)
  198.     {
  199.     if (i == 0)            // first item is the anchor
  200.     {
  201.         mb = new TSubMenu(men->submenu, men->submenukey);
  202.     }
  203.     else                // append another node
  204.     {
  205.         *mb = *mb + *new TSubMenu(men->submenu, men->submenukey);
  206.     }
  207.     m = menuBox(men->items);    // process first item in TSubMenu
  208.     if (m)
  209.         *mb = *mb + *m;
  210.     }
  211.  
  212.     r.b.y = r.a.y + 1;            // set bottom 1 line below top line
  213.  
  214.     return new TMenuBar(r, *mb);
  215. }
  216.  
  217.  
  218. /************************************************************************
  219. ** MenuBarApp::initStatusLine
  220. *************************************************************************/
  221.  
  222. TStatusLine *
  223. MenuBarApp::initStatusLine
  224. (
  225.     TRect r
  226. )
  227. {
  228.     TStatusDef *sb;            // to be an alias for menu bar
  229.     const StatusBar *stat;        // pointer to current sub-menu
  230.     const StatusItems *s;        // pointer to current menu-item
  231.  
  232.     stat = statusBar;            // point to status-bar
  233.     s = stat->items;            // point to first item in status-bar
  234.     for (int i = 0; i < stat->barCount; i++, s++)
  235.     {
  236.     if (i == 0)            // first item is the anchor
  237.     {
  238.         sb = new TStatusDef(0, 0xFFFF);    // range of help contexts
  239.     }
  240.     *sb = *sb + *new TStatusItem(s->item, s->key, s->cmcode);
  241.     }
  242.     r.a.y = r.b.y - 1;            // move top to 1 line above bottom
  243.  
  244.     return new TStatusLine(r, *sb);
  245. }
  246.