home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ncurses-1.9.9e-src.tgz / tar.out / fsf / ncurses / menu / m_global.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  14KB  |  467 lines

  1.  
  2. /***************************************************************************
  3. *                            COPYRIGHT NOTICE                              *
  4. ****************************************************************************
  5. *                ncurses is copyright (C) 1992-1995                        *
  6. *                          Zeyd M. Ben-Halim                               *
  7. *                          zmbenhal@netcom.com                             *
  8. *                          Eric S. Raymond                                 *
  9. *                          esr@snark.thyrsus.com                           *
  10. *                                                                          *
  11. *        Permission is hereby granted to reproduce and distribute ncurses  *
  12. *        by any means and for any fee, whether alone or as part of a       *
  13. *        larger distribution, in source or in binary form, PROVIDED        *
  14. *        this notice is included with any such distribution, and is not    *
  15. *        removed from any of its header files. Mention of ncurses in any   *
  16. *        applications linked with it is highly appreciated.                *
  17. *                                                                          *
  18. *        ncurses comes AS IS with no warranty, implied or expressed.       *
  19. *                                                                          *
  20. ***************************************************************************/
  21.  
  22. /***************************************************************************
  23. * Module menu_global                                                       *
  24. * Globally used internal routines and the default menu and item structures *
  25. ***************************************************************************/
  26.  
  27. #include "menu.priv.h"
  28.  
  29. MENU _nc_Default_Menu = {
  30.   16,                  /* Nr. of chars high */
  31.   1,                  /* Nr. of chars wide */
  32.   16,                  /* Nr. of items high */
  33.   1,                      /* Nr. of items wide */
  34.   16,                  /* Nr. of formatted items high */
  35.   1,                  /* Nr. of formatted items wide */
  36.   0,                  /* length of widest name */
  37.   0,                  /* length of widest description */
  38.   1,                  /* length of mark */
  39.   1,                  /* length of one item */
  40.   (char *)0,              /* buffer used to store match chars */
  41.   0,                  /* Index into pattern buffer */
  42.   (WINDOW *)0,              /* Window containing entire menu */
  43.   (WINDOW *)0,              /* Portion of menu displayed */
  44.   (WINDOW *)0,              /* User's window */
  45.   (WINDOW *)0,              /* User's subwindow */
  46.   (ITEM **)0,              /* List of items */
  47.   0,                  /* Total Nr. of items in menu */
  48.   (ITEM *)0,              /* Current item */
  49.   0,                  /* Top row of menu */
  50.   (chtype)A_REVERSE,          /* Attribute for selection */
  51.   (chtype)A_NORMAL,          /* Attribute for nonselection */
  52.   (chtype)A_UNDERLINE,          /* Attribute for inactive */    
  53.   ' ',                /* Pad character */
  54.   (Menu_Hook)0,              /* Menu init */
  55.   (Menu_Hook)0,              /* Menu term */
  56.   (Menu_Hook)0,              /* Item init */
  57.   (Menu_Hook)0,              /* Item term */
  58.   (void *)0,              /* userptr */
  59.   "-",                  /* mark */
  60.   ALL_MENU_OPTS,                  /* options */
  61.   0                      /* status */        
  62. };
  63.  
  64. ITEM _nc_Default_Item = {
  65.   { (char *)0, 0 },          /* name */
  66.   { (char *)0, 0 },          /* description */
  67.   (MENU *)0,                  /* Pointer to parent menu */
  68.   (char *)0,              /* Userpointer */
  69.   ALL_ITEM_OPTS,          /* options */
  70.   0,                  /* Item Nr. */
  71.   0,                  /* y */
  72.   0,                  /* x */
  73.   FALSE,              /* value */
  74.   (ITEM *)0,                  /* left */
  75.   (ITEM *)0,                  /* right */
  76.   (ITEM *)0,                  /* up */
  77.   (ITEM *)0                  /* down */
  78.   };
  79.  
  80. /*---------------------------------------------------------------------------
  81. |   Facility      :  libnmenu  
  82. |   Function      :  static void ComputeMaximum_NameDesc_Lenths(MENU *menu)
  83. |   
  84. |   Description   :  Calculates the maximum name and description lengths
  85. |                    of the items connected to the menu
  86. |
  87. |   Return Values :  -
  88. +--------------------------------------------------------------------------*/
  89. INLINE static void ComputeMaximum_NameDesc_Lengths(MENU * menu)
  90. {
  91.   unsigned MaximumNameLength        = 0;
  92.   unsigned MaximumDescriptionLength = 0;
  93.   ITEM **items;
  94.   
  95.   assert(menu && menu->items);
  96.   for( items = menu->items; *items ; items++ )
  97.     {
  98.       if (items[0]->name.length > MaximumNameLength )
  99.     MaximumNameLength  = items[0]->name.length;
  100.       
  101.       if (items[0]->description.length > MaximumDescriptionLength)
  102.     MaximumDescriptionLength = items[0]->description.length;
  103.     }
  104.   
  105.   menu->namelen = MaximumNameLength;
  106.   menu->desclen = MaximumDescriptionLength;
  107. }
  108.  
  109. /*---------------------------------------------------------------------------
  110. |   Facility      :  libnmenu  
  111. |   Function      :  static void ResetConnectionInfo(MENU *, ITEM **)
  112. |   
  113. |   Description   :  Reset all informations in the menu and the items in
  114. |                    the item array that indicates a connection
  115. |
  116. |   Return Values :  -
  117. +--------------------------------------------------------------------------*/
  118. INLINE static void ResetConnectionInfo(MENU *menu, ITEM **items)
  119. {
  120.   ITEM **item;
  121.   
  122.   assert(menu && items);
  123.   for(item=items; *item; item++)
  124.     {
  125.       (*item)->index = 0;
  126.       (*item)->imenu = (MENU *)0;        
  127.     }
  128.   if (menu->pattern)
  129.     free(menu->pattern);
  130.   menu->pattern = (char *)0;
  131.   menu->pindex  = 0;
  132.   menu->items   = (ITEM **)0;
  133.   menu->nitems  = 0;
  134. }
  135.  
  136. /*---------------------------------------------------------------------------
  137. |   Facility      :  libnmenu  
  138. |   Function      :  bool _nc_Connect_Items(MENU *menu, ITEM **items)
  139. |
  140. |   Description   :  Connect the items in the item array to the menu.
  141. |                    Decorate all the items with a number and a backward
  142. |                    pointer to the menu.
  143. |
  144. |   Return Values :  TRUE       - successfull connection
  145. |                    FALSE      - connection failed
  146. +--------------------------------------------------------------------------*/
  147. bool _nc_Connect_Items(MENU *menu, ITEM **items)
  148. {
  149.   ITEM **item;
  150.   unsigned int ItemCount = 0;
  151.   
  152.   if ( menu && items )
  153.     {    
  154.       for(item=items; *item ; item++)
  155.     {
  156.       if ( (*item)->imenu )
  157.         {
  158.           /* if a item is already connected, reject connection */
  159.           break;
  160.         }
  161.     }
  162.       if (! (*item) )        
  163.     /* we reached the end, so there was no connected item */
  164.     {
  165.       for(item=items; *item ; item++)
  166.         {
  167.           if (menu->opt & O_ONEVALUE)
  168.         {
  169.           (*item)->value = FALSE;
  170.         }
  171.           (*item)->index = ItemCount++;
  172.           (*item)->imenu = menu;
  173.         }            
  174.     }
  175.     }
  176.   else
  177.     return(FALSE);
  178.   
  179.   if (ItemCount > 0)
  180.     {
  181.       menu->items  = items;
  182.       menu->nitems = ItemCount;
  183.       ComputeMaximum_NameDesc_Lengths(menu);
  184.       if ( (menu->pattern = (char *)malloc( (unsigned)(1 + menu->namelen))) )
  185.     {
  186.       Reset_Pattern(menu);    
  187.       set_menu_format(menu,menu->frows,menu->fcols);
  188.       menu->curitem = *items;
  189.       menu->toprow = 0;
  190.       return(TRUE);
  191.     }
  192.     }
  193.   
  194.   /* If we fall through to this point, we have to reset all items connection 
  195.      and inform about a reject connection */
  196.   ResetConnectionInfo( menu, items );
  197.   return(FALSE);
  198. }
  199.  
  200. /*---------------------------------------------------------------------------
  201. |   Facility      :  libnmenu  
  202. |   Function      :  void _nc_Disconnect_Items(MENU *menu)
  203. |   
  204. |   Description   :  Disconnect the menus item array from the menu
  205. |
  206. |   Return Values :  -
  207. +--------------------------------------------------------------------------*/
  208. void _nc_Disconnect_Items(MENU * menu)
  209. {
  210.   if (menu && menu->items)
  211.     ResetConnectionInfo( menu, menu->items );
  212. }
  213.  
  214. /*---------------------------------------------------------------------------
  215. |   Facility      :  libnmenu  
  216. |   Function      :  void _nc_Calculate_Item_Length_and_Width(MENU *menu)
  217. |   
  218. |   Description   :  Calculate the length of an item and the width of the
  219. |                    whole menu.
  220. |
  221. |   Return Values :  -
  222. +--------------------------------------------------------------------------*/
  223. void _nc_Calculate_Item_Length_and_Width(MENU * menu)
  224. {
  225.   int l;
  226.   
  227.   assert(menu);
  228.   if (menu->items && *(menu->items))
  229.     {
  230.       l = menu->namelen + menu->marklen;
  231.       if ( (menu->opt & O_SHOWDESC) && (menu->desclen > 0) )
  232.     l += (menu->desclen + 1);
  233.       
  234.       menu->itemlen = l;
  235.       l *= menu->cols;
  236.       l += (menu->cols-1);    /* for the padding between the columns */
  237.       menu->width = l;
  238.     }
  239. }
  240.  
  241. /*---------------------------------------------------------------------------
  242. |   Facility      :  libnmenu  
  243. |   Function      :  void _nc_Link_Item(MENU *menu)
  244. |   
  245. |   Description   :  Statically calculate for every item its four neighbours.
  246. |                    This depends on the orientation of the menu. This
  247. |                    static aproach simplifies navigation in the menu a lot.
  248. |
  249. |   Return Values :  -
  250. +--------------------------------------------------------------------------*/
  251. void _nc_Link_Items(MENU * menu)
  252. {
  253.   if (menu && menu->items && *(menu->items))
  254.     {
  255.       int i,j;
  256.       ITEM *item;
  257.       int Number_Of_Items = menu->nitems;
  258.       int col = 0, row = 0;
  259.       int Last_in_Row;
  260.       int Last_in_Column;
  261.       bool cycle = (menu->opt & O_NONCYCLIC) ? FALSE : TRUE;
  262.       
  263.       menu->status &= ~_LINK_NEEDED;
  264.       
  265.       if (menu->opt & O_ROWMAJOR)
  266.     {
  267.       int Number_Of_Columns = menu->cols;
  268.       
  269.       for(i=0; i < Number_Of_Items; i++)
  270.         {
  271.           item = menu->items[i];
  272.           
  273.           Last_in_Row = row * Number_Of_Columns + (Number_Of_Columns-1);
  274.           
  275.           item->left  = (col) ? 
  276.         /* if we are not in the leftmost column, we can use the
  277.            predecessor in the items array */
  278.         menu->items[i-1] :
  279.           (cycle ? menu->items[(Last_in_Row>=Number_Of_Items) ? 
  280.                        Number_Of_Items-1:
  281.                        Last_in_Row] : 
  282.            (ITEM *)0 );
  283.           
  284.           item->right = (  (col < (Number_Of_Columns-1)) && 
  285.                  ((i+1) < Number_Of_Items) 
  286.                  ) ? 
  287.                    menu->items[i+1] :
  288.                  ( cycle ? menu->items[row * Number_Of_Columns] : 
  289.                   (ITEM *)0
  290.                   );
  291.           
  292.           Last_in_Column = (menu->rows-1) * Number_Of_Columns + col;
  293.           
  294.           item->up    = (row) ? menu->items[i-Number_Of_Columns] :
  295.         (cycle ? menu->items[(Last_in_Column>=Number_Of_Items) ?
  296.                      Number_Of_Items-1 : 
  297.                      Last_in_Column] : 
  298.          (ITEM *)0);
  299.           
  300.           item->down  = ( (i+Number_Of_Columns) < Number_Of_Items ) 
  301.         ? 
  302.           menu->items[i + Number_Of_Columns] :
  303.             (cycle ? menu->items[(row+1)<menu->rows ?
  304.                      Number_Of_Items-1:col] : 
  305.              (ITEM *)0);
  306.           item->x = col;
  307.           item->y = row;
  308.           if ( ++col == Number_Of_Columns )
  309.         {
  310.           row++;
  311.           col = 0;
  312.         }
  313.         }
  314.     }
  315.       else
  316.     {
  317.       int Number_Of_Rows = menu->rows;
  318.       
  319.       for(j=0; j<Number_Of_Items; j++)
  320.         {
  321.           item = menu->items[i=(col * Number_Of_Rows + row)];
  322.           
  323.           Last_in_Column = (menu->cols-1) * Number_Of_Rows + row;
  324.           
  325.           item->left  = (col) ? 
  326.         menu->items[i - Number_Of_Rows] :
  327.           (cycle ? (Last_in_Column >= Number_Of_Items ) ? 
  328.            menu->items[Last_in_Column-Number_Of_Rows] : 
  329.            menu->items[Last_in_Column] : 
  330.            (ITEM *)0 );
  331.           
  332.           item->right = ((i + Number_Of_Rows) <Number_Of_Items) 
  333.         ? 
  334.           menu->items[i + Number_Of_Rows] :
  335.             (cycle ? menu->items[row] : (ITEM *)0);
  336.           
  337.           Last_in_Row = col * Number_Of_Rows + (Number_Of_Rows - 1);
  338.           
  339.           item->up    = (row) ? 
  340.         menu->items[i-1] :
  341.           (cycle ?
  342.            menu->items[(Last_in_Row>=Number_Of_Items) ? 
  343.                    Number_Of_Items-1:
  344.                    Last_in_Row] :
  345.            (ITEM *)0);
  346.           
  347.           item->down  = (row < (Number_Of_Rows-1)) 
  348.         ? 
  349.           (menu->items[((i+1)<Number_Of_Items) ? 
  350.                    i+1 :
  351.                    (col-1)*Number_Of_Rows + row + 1]) :
  352.                  (cycle ?
  353.                   menu->items[col * Number_Of_Rows] :
  354.                   (ITEM *)0
  355.                   );
  356.           
  357.           item->x = col;
  358.           item->y = row;
  359.           if ( (++row) == Number_Of_Rows )
  360.         {
  361.           col++;
  362.           row = 0;
  363.         }
  364.         }
  365.     }
  366.     }
  367. }
  368.  
  369. /*---------------------------------------------------------------------------
  370. |   Facility      :  libnmenu  
  371. |   Function      :  void _nc_Show_Menu(const MENU *menu)
  372. |   
  373. |   Description   :  Update the window that is associated with the menu
  374. |
  375. |   Return Values :  -
  376. +--------------------------------------------------------------------------*/
  377. void _nc_Show_Menu(const MENU *menu)
  378. {
  379.   WINDOW *win;
  380.   int maxy, maxx;
  381.   
  382.   assert(menu);
  383.   if ( (menu->status & _POSTED) && !(menu->status & _IN_DRIVER) )
  384.     {
  385.       /* adjust the internal subwindow to start on the current top */
  386.       assert(menu->sub);
  387.       mvderwin(menu->sub,menu->toprow,0);
  388.       win = Get_Menu_Window(menu);
  389.       
  390.       maxy = getmaxy(win);
  391.       maxx = getmaxx(win);     
  392.       
  393.       if (menu->height < maxy) 
  394.     maxy = menu->height;
  395.       if (menu->width < maxx) 
  396.     maxx = menu->width;
  397.       
  398.       copywin(menu->sub,win,0,0,0,0,maxy-1,maxx-1,0);
  399.       pos_menu_cursor(menu);
  400.     }    
  401. }    
  402.  
  403. /*---------------------------------------------------------------------------
  404. |   Facility      :  libnmenu  
  405. |   Function      :  void _nc_New_TopRow_and_CurrentItem(
  406. |                            MENU *menu, 
  407. |                            int new_toprow, 
  408. |                            ITEM *new_current_item)
  409. |   
  410. |   Description   :  Redisplay the menu so that the given row becomes the
  411. |                    top row and the given item becomes the new current
  412. |                    item.
  413. |
  414. |   Return Values :  -
  415. +--------------------------------------------------------------------------*/
  416. void _nc_New_TopRow_and_CurrentItem(MENU *menu, int new_toprow,
  417.                     ITEM *new_current_item)
  418. {
  419.   ITEM *cur_item;
  420.   bool mterm_called = FALSE;
  421.   bool iterm_called = FALSE;
  422.   
  423.   assert(menu);
  424.   if (menu->status & _POSTED)
  425.     {
  426.       if (new_current_item != menu->curitem)
  427.     {
  428.       Call_Hook(menu,itemterm);
  429.       iterm_called = TRUE;
  430.     }
  431.       if (new_toprow != menu->toprow)
  432.     {
  433.       Call_Hook(menu,menuterm);
  434.       mterm_called = TRUE;
  435.     }            
  436.       
  437.       cur_item  = menu->curitem;
  438.       assert(cur_item);
  439.       menu->toprow  = new_toprow;
  440.       menu->curitem = new_current_item;            
  441.       
  442.       if (mterm_called)
  443.     {
  444.       Call_Hook(menu,menuinit);
  445.     }
  446.       if (iterm_called)
  447.     {
  448.       /* this means, move from the old current_item to the new one... */
  449.       Move_To_Current_Item( menu, cur_item );
  450.       Call_Hook(menu,iteminit);
  451.     }
  452.       if (mterm_called || iterm_called)
  453.     {
  454.       _nc_Show_Menu(menu);
  455.     }
  456.       else
  457.     pos_menu_cursor(menu);
  458.     }
  459.   else
  460.     { /* if we are not posted, this is quite simple */
  461.       menu->toprow  = new_toprow;
  462.       menu->curitem = new_current_item;
  463.     }
  464. }
  465.  
  466. /* m_global.c ends here */
  467.