xref: /openbsd-src/lib/libmenu/m_global.c (revision c7ef0cfc17afcba97172c25e1e3a943e893bc632)
1*c7ef0cfcSnicm /* $OpenBSD: m_global.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */
29f1aa62bSmillert 
3457960bfSmillert /****************************************************************************
4*c7ef0cfcSnicm  * Copyright 2020,2021 Thomas E. Dickey                                     *
5*c7ef0cfcSnicm  * Copyright 1998-2012,2014 Free Software Foundation, Inc.                  *
6457960bfSmillert  *                                                                          *
7457960bfSmillert  * Permission is hereby granted, free of charge, to any person obtaining a  *
8457960bfSmillert  * copy of this software and associated documentation files (the            *
9457960bfSmillert  * "Software"), to deal in the Software without restriction, including      *
10457960bfSmillert  * without limitation the rights to use, copy, modify, merge, publish,      *
11457960bfSmillert  * distribute, distribute with modifications, sublicense, and/or sell       *
12457960bfSmillert  * copies of the Software, and to permit persons to whom the Software is    *
13457960bfSmillert  * furnished to do so, subject to the following conditions:                 *
14457960bfSmillert  *                                                                          *
15457960bfSmillert  * The above copyright notice and this permission notice shall be included  *
16457960bfSmillert  * in all copies or substantial portions of the Software.                   *
17457960bfSmillert  *                                                                          *
18457960bfSmillert  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
19457960bfSmillert  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
20457960bfSmillert  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
21457960bfSmillert  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
22457960bfSmillert  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
23457960bfSmillert  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
24457960bfSmillert  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
25457960bfSmillert  *                                                                          *
26457960bfSmillert  * Except as contained in this notice, the name(s) of the above copyright   *
27457960bfSmillert  * holders shall not be used in advertising or otherwise to promote the     *
28457960bfSmillert  * sale, use or other dealings in this Software without prior written       *
29457960bfSmillert  * authorization.                                                           *
30457960bfSmillert  ****************************************************************************/
31457960bfSmillert 
32457960bfSmillert /****************************************************************************
3381d8c4e1Snicm  *   Author:  Juergen Pfeifer, 1995,1997                                    *
34457960bfSmillert  ****************************************************************************/
35c166cd22Stholo 
36c166cd22Stholo /***************************************************************************
379f1aa62bSmillert * Module m_global                                                          *
38c166cd22Stholo * Globally used internal routines and the default menu and item structures *
39c166cd22Stholo ***************************************************************************/
40c166cd22Stholo 
41c166cd22Stholo #include "menu.priv.h"
42c166cd22Stholo 
43*c7ef0cfcSnicm MODULE_ID("$Id: m_global.c,v 1.9 2023/10/17 09:52:10 nicm Exp $")
440107aba4Smillert 
4581d8c4e1Snicm static char mark[] = "-";
4681d8c4e1Snicm /* *INDENT-OFF* */
47*c7ef0cfcSnicm MENU_EXPORT_VAR(MENU) _nc_Default_Menu = {
48c166cd22Stholo   16,				  /* Nr. of chars high */
49c166cd22Stholo   1,				  /* Nr. of chars wide */
50c166cd22Stholo   16,				  /* Nr. of items high */
51c166cd22Stholo   1,			          /* Nr. of items wide */
52c166cd22Stholo   16,				  /* Nr. of formatted items high */
53c166cd22Stholo   1,				  /* Nr. of formatted items wide */
540107aba4Smillert   16,				  /* Nr. of items high (actual) */
55c166cd22Stholo   0,				  /* length of widest name */
56c166cd22Stholo   0,				  /* length of widest description */
57c166cd22Stholo   1,				  /* length of mark */
58c166cd22Stholo   1,				  /* length of one item */
590107aba4Smillert   1,                              /* Spacing for descriptor */
600107aba4Smillert   1,                              /* Spacing for columns */
610107aba4Smillert   1,                              /* Spacing for rows */
62c166cd22Stholo   (char *)0,			  /* buffer used to store match chars */
63c166cd22Stholo   0,				  /* Index into pattern buffer */
64c166cd22Stholo   (WINDOW *)0,			  /* Window containing entire menu */
65c166cd22Stholo   (WINDOW *)0,			  /* Portion of menu displayed */
66c166cd22Stholo   (WINDOW *)0,			  /* User's window */
67c166cd22Stholo   (WINDOW *)0,			  /* User's subwindow */
68c166cd22Stholo   (ITEM **)0,			  /* List of items */
69c166cd22Stholo   0,				  /* Total Nr. of items in menu */
70c166cd22Stholo   (ITEM *)0,			  /* Current item */
71c166cd22Stholo   0,				  /* Top row of menu */
72c166cd22Stholo   (chtype)A_REVERSE,		  /* Attribute for selection */
73c166cd22Stholo   (chtype)A_NORMAL,		  /* Attribute for nonselection */
74c166cd22Stholo   (chtype)A_UNDERLINE,		  /* Attribute for inactive */
75c166cd22Stholo   ' ',  			  /* Pad character */
76c166cd22Stholo   (Menu_Hook)0,			  /* Menu init */
77c166cd22Stholo   (Menu_Hook)0,			  /* Menu term */
78c166cd22Stholo   (Menu_Hook)0,			  /* Item init */
79c166cd22Stholo   (Menu_Hook)0,			  /* Item term */
80c166cd22Stholo   (void *)0,			  /* userptr */
8181d8c4e1Snicm   mark,				  /* mark */
82c166cd22Stholo   ALL_MENU_OPTS,                  /* options */
83c166cd22Stholo   0			          /* status */
84c166cd22Stholo };
85c166cd22Stholo 
86*c7ef0cfcSnicm MENU_EXPORT_VAR(ITEM) _nc_Default_Item = {
87c166cd22Stholo   { (char *)0, 0 },		  /* name */
88c166cd22Stholo   { (char *)0, 0 },		  /* description */
89c166cd22Stholo   (MENU *)0,		          /* Pointer to parent menu */
90c166cd22Stholo   (char *)0,			  /* Userpointer */
91c166cd22Stholo   ALL_ITEM_OPTS,		  /* options */
92c166cd22Stholo   0,				  /* Item Nr. */
93c166cd22Stholo   0,				  /* y */
94c166cd22Stholo   0,				  /* x */
95c166cd22Stholo   FALSE,			  /* value */
96c166cd22Stholo   (ITEM *)0,		          /* left */
97c166cd22Stholo   (ITEM *)0,		          /* right */
98c166cd22Stholo   (ITEM *)0,		          /* up */
99c166cd22Stholo   (ITEM *)0		          /* down */
100c166cd22Stholo   };
10181d8c4e1Snicm /* *INDENT-ON* */
102c166cd22Stholo 
103c166cd22Stholo /*---------------------------------------------------------------------------
104c166cd22Stholo |   Facility      :  libnmenu
105c166cd22Stholo |   Function      :  static void ComputeMaximum_NameDesc_Lenths(MENU *menu)
106c166cd22Stholo |
107c166cd22Stholo |   Description   :  Calculates the maximum name and description lengths
108c166cd22Stholo |                    of the items connected to the menu
109c166cd22Stholo |
110c166cd22Stholo |   Return Values :  -
111c166cd22Stholo +--------------------------------------------------------------------------*/
11281d8c4e1Snicm NCURSES_INLINE static void
ComputeMaximum_NameDesc_Lengths(MENU * menu)11381d8c4e1Snicm ComputeMaximum_NameDesc_Lengths(MENU *menu)
114c166cd22Stholo {
115c166cd22Stholo   unsigned MaximumNameLength = 0;
116c166cd22Stholo   unsigned MaximumDescriptionLength = 0;
117c166cd22Stholo   ITEM **items;
118c166cd22Stholo 
119c166cd22Stholo   assert(menu && menu->items);
120c166cd22Stholo   for (items = menu->items; *items; items++)
121c166cd22Stholo     {
122*c7ef0cfcSnicm       unsigned check = (unsigned)_nc_Calculate_Text_Width(&((*items)->name));
123*c7ef0cfcSnicm 
12481d8c4e1Snicm       if (check > MaximumNameLength)
12581d8c4e1Snicm 	MaximumNameLength = check;
126c166cd22Stholo 
127*c7ef0cfcSnicm       check = (unsigned)_nc_Calculate_Text_Width(&((*items)->description));
12881d8c4e1Snicm       if (check > MaximumDescriptionLength)
12981d8c4e1Snicm 	MaximumDescriptionLength = check;
130c166cd22Stholo     }
131c166cd22Stholo 
132*c7ef0cfcSnicm   menu->namelen = (short)MaximumNameLength;
133*c7ef0cfcSnicm   menu->desclen = (short)MaximumDescriptionLength;
13481d8c4e1Snicm   T(("ComputeMaximum_NameDesc_Lengths %d,%d", menu->namelen, menu->desclen));
135c166cd22Stholo }
136c166cd22Stholo 
137c166cd22Stholo /*---------------------------------------------------------------------------
138c166cd22Stholo |   Facility      :  libnmenu
139c166cd22Stholo |   Function      :  static void ResetConnectionInfo(MENU *, ITEM **)
140c166cd22Stholo |
141*c7ef0cfcSnicm |   Description   :  Reset all information in the menu and the items in
142c166cd22Stholo |                    the item array that indicates a connection
143c166cd22Stholo |
144c166cd22Stholo |   Return Values :  -
145c166cd22Stholo +--------------------------------------------------------------------------*/
14681d8c4e1Snicm NCURSES_INLINE static void
ResetConnectionInfo(MENU * menu,ITEM ** items)14781d8c4e1Snicm ResetConnectionInfo(MENU *menu, ITEM **items)
148c166cd22Stholo {
149c166cd22Stholo   ITEM **item;
150c166cd22Stholo 
151c166cd22Stholo   assert(menu && items);
152c166cd22Stholo   for (item = items; *item; item++)
153c166cd22Stholo     {
154c166cd22Stholo       (*item)->index = 0;
155c166cd22Stholo       (*item)->imenu = (MENU *)0;
156c166cd22Stholo     }
157c166cd22Stholo   if (menu->pattern)
158c166cd22Stholo     free(menu->pattern);
159c166cd22Stholo   menu->pattern = (char *)0;
160c166cd22Stholo   menu->pindex = 0;
161c166cd22Stholo   menu->items = (ITEM **)0;
162c166cd22Stholo   menu->nitems = 0;
163c166cd22Stholo }
164c166cd22Stholo 
165c166cd22Stholo /*---------------------------------------------------------------------------
166c166cd22Stholo |   Facility      :  libnmenu
167c166cd22Stholo |   Function      :  bool _nc_Connect_Items(MENU *menu, ITEM **items)
168c166cd22Stholo |
169c166cd22Stholo |   Description   :  Connect the items in the item array to the menu.
170c166cd22Stholo |                    Decorate all the items with a number and a backward
171c166cd22Stholo |                    pointer to the menu.
172c166cd22Stholo |
17369395a6eSderaadt |   Return Values :  TRUE       - successful connection
174c166cd22Stholo |                    FALSE      - connection failed
175c166cd22Stholo +--------------------------------------------------------------------------*/
176*c7ef0cfcSnicm MENU_EXPORT(bool)
_nc_Connect_Items(MENU * menu,ITEM ** items)17784af20ceSmillert _nc_Connect_Items(MENU *menu, ITEM **items)
178c166cd22Stholo {
179c166cd22Stholo   unsigned int ItemCount = 0;
180c166cd22Stholo 
181c166cd22Stholo   if (menu && items)
182c166cd22Stholo     {
183*c7ef0cfcSnicm       ITEM **item;
184*c7ef0cfcSnicm 
185c166cd22Stholo       for (item = items; *item; item++)
186c166cd22Stholo 	{
187c166cd22Stholo 	  if ((*item)->imenu)
188c166cd22Stholo 	    {
189c166cd22Stholo 	      /* if a item is already connected, reject connection */
190c166cd22Stholo 	      break;
191c166cd22Stholo 	    }
192c166cd22Stholo 	}
193c166cd22Stholo       if (!(*item))
194c166cd22Stholo 	/* we reached the end, so there was no connected item */
195c166cd22Stholo 	{
196c166cd22Stholo 	  for (item = items; *item; item++)
197c166cd22Stholo 	    {
198c166cd22Stholo 	      if (menu->opt & O_ONEVALUE)
199c166cd22Stholo 		{
200c166cd22Stholo 		  (*item)->value = FALSE;
201c166cd22Stholo 		}
202*c7ef0cfcSnicm 	      (*item)->index = (short)ItemCount++;
203c166cd22Stholo 	      (*item)->imenu = menu;
204c166cd22Stholo 	    }
205c166cd22Stholo 	}
206c166cd22Stholo     }
207c166cd22Stholo   else
208c166cd22Stholo     return (FALSE);
209c166cd22Stholo 
2100107aba4Smillert   if (ItemCount != 0)
211c166cd22Stholo     {
212c166cd22Stholo       menu->items = items;
213*c7ef0cfcSnicm       menu->nitems = (short)ItemCount;
214c166cd22Stholo       ComputeMaximum_NameDesc_Lengths(menu);
21581d8c4e1Snicm       if ((menu->pattern = typeMalloc(char, (unsigned)(1 + menu->namelen))))
216c166cd22Stholo 	{
217c166cd22Stholo 	  Reset_Pattern(menu);
218c166cd22Stholo 	  set_menu_format(menu, menu->frows, menu->fcols);
219c166cd22Stholo 	  menu->curitem = *items;
220c166cd22Stholo 	  menu->toprow = 0;
221c166cd22Stholo 	  return (TRUE);
222c166cd22Stholo 	}
223c166cd22Stholo     }
224c166cd22Stholo 
225c166cd22Stholo   /* If we fall through to this point, we have to reset all items connection
226c166cd22Stholo      and inform about a reject connection */
227c166cd22Stholo   ResetConnectionInfo(menu, items);
228c166cd22Stholo   return (FALSE);
229c166cd22Stholo }
230c166cd22Stholo 
231c166cd22Stholo /*---------------------------------------------------------------------------
232c166cd22Stholo |   Facility      :  libnmenu
233c166cd22Stholo |   Function      :  void _nc_Disconnect_Items(MENU *menu)
234c166cd22Stholo |
235c166cd22Stholo |   Description   :  Disconnect the menus item array from the menu
236c166cd22Stholo |
237c166cd22Stholo |   Return Values :  -
238c166cd22Stholo +--------------------------------------------------------------------------*/
239*c7ef0cfcSnicm MENU_EXPORT(void)
_nc_Disconnect_Items(MENU * menu)24084af20ceSmillert _nc_Disconnect_Items(MENU *menu)
241c166cd22Stholo {
242c166cd22Stholo   if (menu && menu->items)
243c166cd22Stholo     ResetConnectionInfo(menu, menu->items);
244c166cd22Stholo }
245c166cd22Stholo 
246c166cd22Stholo /*---------------------------------------------------------------------------
247c166cd22Stholo |   Facility      :  libnmenu
24881d8c4e1Snicm |   Function      :  int _nc_Calculate_Text_Width(const TEXT * item)
24981d8c4e1Snicm |
25081d8c4e1Snicm |   Description   :  Calculate the number of columns for a TEXT.
25181d8c4e1Snicm |
25281d8c4e1Snicm |   Return Values :  the width
25381d8c4e1Snicm +--------------------------------------------------------------------------*/
254*c7ef0cfcSnicm MENU_EXPORT(int)
_nc_Calculate_Text_Width(const TEXT * item)25581d8c4e1Snicm _nc_Calculate_Text_Width(const TEXT *item /*FIXME: limit length */ )
25681d8c4e1Snicm {
25781d8c4e1Snicm #if USE_WIDEC_SUPPORT
25881d8c4e1Snicm   int result = item->length;
25981d8c4e1Snicm 
260*c7ef0cfcSnicm   T((T_CALLED("_nc_menu_text_width(%p)"), (const void *)item));
26181d8c4e1Snicm   if (result != 0 && item->str != 0)
26281d8c4e1Snicm     {
263*c7ef0cfcSnicm       int count = (int)mbstowcs(0, item->str, 0);
26481d8c4e1Snicm       wchar_t *temp = 0;
26581d8c4e1Snicm 
26681d8c4e1Snicm       if (count > 0
26781d8c4e1Snicm 	  && (temp = typeMalloc(wchar_t, 2 + count)) != 0)
26881d8c4e1Snicm 	{
26981d8c4e1Snicm 	  int n;
27081d8c4e1Snicm 
27181d8c4e1Snicm 	  result = 0;
27281d8c4e1Snicm 	  mbstowcs(temp, item->str, (unsigned)count);
27381d8c4e1Snicm 	  for (n = 0; n < count; ++n)
27481d8c4e1Snicm 	    {
27581d8c4e1Snicm 	      int test = wcwidth(temp[n]);
27681d8c4e1Snicm 
27781d8c4e1Snicm 	      if (test <= 0)
27881d8c4e1Snicm 		test = 1;
27981d8c4e1Snicm 	      result += test;
28081d8c4e1Snicm 	    }
28181d8c4e1Snicm 	  free(temp);
28281d8c4e1Snicm 	}
28381d8c4e1Snicm     }
28481d8c4e1Snicm   returnCode(result);
28581d8c4e1Snicm #else
28681d8c4e1Snicm   return item->length;
28781d8c4e1Snicm #endif
28881d8c4e1Snicm }
28981d8c4e1Snicm 
29081d8c4e1Snicm /*
29181d8c4e1Snicm  * Calculate the actual width of a menu entry for wide-characters.
29281d8c4e1Snicm  */
29381d8c4e1Snicm #if USE_WIDEC_SUPPORT
29481d8c4e1Snicm static int
calculate_actual_width(MENU * menu,bool name)29581d8c4e1Snicm calculate_actual_width(MENU *menu, bool name)
29681d8c4e1Snicm {
29781d8c4e1Snicm   int width = 0;
29881d8c4e1Snicm 
29981d8c4e1Snicm   assert(menu && menu->items);
30081d8c4e1Snicm 
30181d8c4e1Snicm   if (menu->items != 0)
30281d8c4e1Snicm     {
303*c7ef0cfcSnicm       ITEM **items;
304*c7ef0cfcSnicm 
30581d8c4e1Snicm       for (items = menu->items; *items; items++)
30681d8c4e1Snicm 	{
307*c7ef0cfcSnicm 	  int check = (name
308*c7ef0cfcSnicm 		       ? _nc_Calculate_Text_Width(&((*items)->name))
309*c7ef0cfcSnicm 		       : _nc_Calculate_Text_Width(&((*items)->description)));
310*c7ef0cfcSnicm 
31181d8c4e1Snicm 	  if (check > width)
31281d8c4e1Snicm 	    width = check;
31381d8c4e1Snicm 	}
31481d8c4e1Snicm     }
31581d8c4e1Snicm   else
31681d8c4e1Snicm     {
31781d8c4e1Snicm       width = (name ? menu->namelen : menu->desclen);
31881d8c4e1Snicm     }
31981d8c4e1Snicm 
32081d8c4e1Snicm   T(("calculate_actual_width %s = %d/%d",
32181d8c4e1Snicm      name ? "name" : "desc",
32281d8c4e1Snicm      width,
32381d8c4e1Snicm      name ? menu->namelen : menu->desclen));
32481d8c4e1Snicm   return width;
32581d8c4e1Snicm }
32681d8c4e1Snicm #else
32781d8c4e1Snicm #define calculate_actual_width(menu, name) (name ? menu->namelen : menu->desclen)
32881d8c4e1Snicm #endif
32981d8c4e1Snicm 
33081d8c4e1Snicm /*---------------------------------------------------------------------------
33181d8c4e1Snicm |   Facility      :  libnmenu
332c166cd22Stholo |   Function      :  void _nc_Calculate_Item_Length_and_Width(MENU *menu)
333c166cd22Stholo |
334c166cd22Stholo |   Description   :  Calculate the length of an item and the width of the
335c166cd22Stholo |                    whole menu.
336c166cd22Stholo |
337c166cd22Stholo |   Return Values :  -
338c166cd22Stholo +--------------------------------------------------------------------------*/
339*c7ef0cfcSnicm MENU_EXPORT(void)
_nc_Calculate_Item_Length_and_Width(MENU * menu)34084af20ceSmillert _nc_Calculate_Item_Length_and_Width(MENU *menu)
341c166cd22Stholo {
342c166cd22Stholo   int l;
343c166cd22Stholo 
344c166cd22Stholo   assert(menu);
3450107aba4Smillert 
346*c7ef0cfcSnicm   menu->height = (short)(1 + menu->spc_rows * (menu->arows - 1));
3470107aba4Smillert 
34881d8c4e1Snicm   l = calculate_actual_width(menu, TRUE);
34981d8c4e1Snicm   l += menu->marklen;
35081d8c4e1Snicm 
351c166cd22Stholo   if ((menu->opt & O_SHOWDESC) && (menu->desclen > 0))
35281d8c4e1Snicm     {
35381d8c4e1Snicm       l += calculate_actual_width(menu, FALSE);
35481d8c4e1Snicm       l += menu->spc_desc;
35581d8c4e1Snicm     }
356c166cd22Stholo 
357*c7ef0cfcSnicm   menu->itemlen = (short)l;
358c166cd22Stholo   l *= menu->cols;
3590107aba4Smillert   l += (menu->cols - 1) * menu->spc_cols;	/* for the padding between the columns */
360*c7ef0cfcSnicm   menu->width = (short)l;
36181d8c4e1Snicm 
36281d8c4e1Snicm   T(("_nc_CalculateItem_Length_and_Width columns %d, item %d, width %d",
36381d8c4e1Snicm      menu->cols,
36481d8c4e1Snicm      menu->itemlen,
36581d8c4e1Snicm      menu->width));
366c166cd22Stholo }
367c166cd22Stholo 
368c166cd22Stholo /*---------------------------------------------------------------------------
369c166cd22Stholo |   Facility      :  libnmenu
370c166cd22Stholo |   Function      :  void _nc_Link_Item(MENU *menu)
371c166cd22Stholo |
37281d8c4e1Snicm |   Description   :  Statically calculate for every item its four neighbors.
373c166cd22Stholo |                    This depends on the orientation of the menu. This
37481d8c4e1Snicm |                    static approach simplifies navigation in the menu a lot.
375c166cd22Stholo |
376c166cd22Stholo |   Return Values :  -
377c166cd22Stholo +--------------------------------------------------------------------------*/
378*c7ef0cfcSnicm MENU_EXPORT(void)
_nc_Link_Items(MENU * menu)37984af20ceSmillert _nc_Link_Items(MENU *menu)
380c166cd22Stholo {
381c166cd22Stholo   if (menu && menu->items && *(menu->items))
382c166cd22Stholo     {
383*c7ef0cfcSnicm       int i;
384c166cd22Stholo       ITEM *item;
385c166cd22Stholo       int Number_Of_Items = menu->nitems;
386c166cd22Stholo       int col = 0, row = 0;
387c166cd22Stholo       int Last_in_Row;
388c166cd22Stholo       int Last_in_Column;
389c166cd22Stholo       bool cycle = (menu->opt & O_NONCYCLIC) ? FALSE : TRUE;
390c166cd22Stholo 
391*c7ef0cfcSnicm       ClrStatus(menu, _LINK_NEEDED);
392c166cd22Stholo 
393c166cd22Stholo       if (menu->opt & O_ROWMAJOR)
394c166cd22Stholo 	{
395c166cd22Stholo 	  int Number_Of_Columns = menu->cols;
396c166cd22Stholo 
397c166cd22Stholo 	  for (i = 0; i < Number_Of_Items; i++)
398c166cd22Stholo 	    {
399c166cd22Stholo 	      item = menu->items[i];
400c166cd22Stholo 
401c166cd22Stholo 	      Last_in_Row = row * Number_Of_Columns + (Number_Of_Columns - 1);
402c166cd22Stholo 
403c166cd22Stholo 	      item->left = (col) ?
404c166cd22Stholo 	      /* if we are not in the leftmost column, we can use the
405c166cd22Stholo 	         predecessor in the items array */
406c166cd22Stholo 		menu->items[i - 1] :
407c166cd22Stholo 		(cycle ? menu->items[(Last_in_Row >= Number_Of_Items) ?
408c166cd22Stholo 				     Number_Of_Items - 1 :
409c166cd22Stholo 				     Last_in_Row] :
410c166cd22Stholo 		 (ITEM *)0);
411c166cd22Stholo 
412c166cd22Stholo 	      item->right = ((col < (Number_Of_Columns - 1)) &&
413c166cd22Stholo 			     ((i + 1) < Number_Of_Items)
414c166cd22Stholo 		)?
415c166cd22Stholo 		menu->items[i + 1] :
416c166cd22Stholo 		(cycle ? menu->items[row * Number_Of_Columns] :
417c166cd22Stholo 		 (ITEM *)0
418c166cd22Stholo 		);
419c166cd22Stholo 
420c166cd22Stholo 	      Last_in_Column = (menu->rows - 1) * Number_Of_Columns + col;
421c166cd22Stholo 
422c166cd22Stholo 	      item->up = (row) ? menu->items[i - Number_Of_Columns] :
423c166cd22Stholo 		(cycle ? menu->items[(Last_in_Column >= Number_Of_Items) ?
424c166cd22Stholo 				     Number_Of_Items - 1 :
425c166cd22Stholo 				     Last_in_Column] :
426c166cd22Stholo 		 (ITEM *)0);
427c166cd22Stholo 
428c166cd22Stholo 	      item->down = ((i + Number_Of_Columns) < Number_Of_Items)
429c166cd22Stholo 		?
430c166cd22Stholo 		menu->items[i + Number_Of_Columns] :
431c166cd22Stholo 		(cycle ? menu->items[(row + 1) < menu->rows ?
432c166cd22Stholo 				     Number_Of_Items - 1 : col] :
433c166cd22Stholo 		 (ITEM *)0);
434*c7ef0cfcSnicm 	      item->x = (short)col;
435*c7ef0cfcSnicm 	      item->y = (short)row;
436c166cd22Stholo 	      if (++col == Number_Of_Columns)
437c166cd22Stholo 		{
438c166cd22Stholo 		  row++;
439c166cd22Stholo 		  col = 0;
440c166cd22Stholo 		}
441c166cd22Stholo 	    }
442c166cd22Stholo 	}
443c166cd22Stholo       else
444c166cd22Stholo 	{
445c166cd22Stholo 	  int Number_Of_Rows = menu->rows;
446*c7ef0cfcSnicm 	  int j;
447c166cd22Stholo 
448c166cd22Stholo 	  for (j = 0; j < Number_Of_Items; j++)
449c166cd22Stholo 	    {
450c166cd22Stholo 	      item = menu->items[i = (col * Number_Of_Rows + row)];
451c166cd22Stholo 
452c166cd22Stholo 	      Last_in_Column = (menu->cols - 1) * Number_Of_Rows + row;
453c166cd22Stholo 
454c166cd22Stholo 	      item->left = (col) ?
455c166cd22Stholo 		menu->items[i - Number_Of_Rows] :
456c166cd22Stholo 		(cycle ? (Last_in_Column >= Number_Of_Items) ?
457c166cd22Stholo 		 menu->items[Last_in_Column - Number_Of_Rows] :
458c166cd22Stholo 		 menu->items[Last_in_Column] :
459c166cd22Stholo 		 (ITEM *)0);
460c166cd22Stholo 
461c166cd22Stholo 	      item->right = ((i + Number_Of_Rows) < Number_Of_Items)
462c166cd22Stholo 		?
463c166cd22Stholo 		menu->items[i + Number_Of_Rows] :
464c166cd22Stholo 		(cycle ? menu->items[row] : (ITEM *)0);
465c166cd22Stholo 
466c166cd22Stholo 	      Last_in_Row = col * Number_Of_Rows + (Number_Of_Rows - 1);
467c166cd22Stholo 
468c166cd22Stholo 	      item->up = (row) ?
469c166cd22Stholo 		menu->items[i - 1] :
470c166cd22Stholo 		(cycle ?
471c166cd22Stholo 		 menu->items[(Last_in_Row >= Number_Of_Items) ?
472c166cd22Stholo 			     Number_Of_Items - 1 :
473c166cd22Stholo 			     Last_in_Row] :
474c166cd22Stholo 		 (ITEM *)0);
475c166cd22Stholo 
476c166cd22Stholo 	      item->down = (row < (Number_Of_Rows - 1))
477c166cd22Stholo 		?
478c166cd22Stholo 		(menu->items[((i + 1) < Number_Of_Items) ?
479c166cd22Stholo 			     i + 1 :
480c166cd22Stholo 			     (col - 1) * Number_Of_Rows + row + 1]) :
481c166cd22Stholo 		(cycle ?
482c166cd22Stholo 		 menu->items[col * Number_Of_Rows] :
483c166cd22Stholo 		 (ITEM *)0
484c166cd22Stholo 		);
485c166cd22Stholo 
486*c7ef0cfcSnicm 	      item->x = (short)col;
487*c7ef0cfcSnicm 	      item->y = (short)row;
488c166cd22Stholo 	      if ((++row) == Number_Of_Rows)
489c166cd22Stholo 		{
490c166cd22Stholo 		  col++;
491c166cd22Stholo 		  row = 0;
492c166cd22Stholo 		}
493c166cd22Stholo 	    }
494c166cd22Stholo 	}
495c166cd22Stholo     }
496c166cd22Stholo }
497c166cd22Stholo 
498c166cd22Stholo /*---------------------------------------------------------------------------
499c166cd22Stholo |   Facility      :  libnmenu
500c166cd22Stholo |   Function      :  void _nc_Show_Menu(const MENU* menu)
501c166cd22Stholo |
502c166cd22Stholo |   Description   :  Update the window that is associated with the menu
503c166cd22Stholo |
504c166cd22Stholo |   Return Values :  -
505c166cd22Stholo +--------------------------------------------------------------------------*/
506*c7ef0cfcSnicm MENU_EXPORT(void)
_nc_Show_Menu(const MENU * menu)50784af20ceSmillert _nc_Show_Menu(const MENU *menu)
508c166cd22Stholo {
509*c7ef0cfcSnicm   assert(menu);
510*c7ef0cfcSnicm   if ((menu->status & _POSTED) && !(menu->status & _IN_DRIVER))
511*c7ef0cfcSnicm     {
512c166cd22Stholo       WINDOW *win;
513c166cd22Stholo       int maxy, maxx;
514c166cd22Stholo 
515c166cd22Stholo       /* adjust the internal subwindow to start on the current top */
516c166cd22Stholo       assert(menu->sub);
5170107aba4Smillert       mvderwin(menu->sub, menu->spc_rows * menu->toprow, 0);
518c166cd22Stholo       win = Get_Menu_Window(menu);
519c166cd22Stholo 
520c166cd22Stholo       maxy = getmaxy(win);
521c166cd22Stholo       maxx = getmaxx(win);
522c166cd22Stholo 
523c166cd22Stholo       if (menu->height < maxy)
524c166cd22Stholo 	maxy = menu->height;
525c166cd22Stholo       if (menu->width < maxx)
526c166cd22Stholo 	maxx = menu->width;
527c166cd22Stholo 
528c166cd22Stholo       copywin(menu->sub, win, 0, 0, 0, 0, maxy - 1, maxx - 1, 0);
529c166cd22Stholo       pos_menu_cursor(menu);
530c166cd22Stholo     }
531c166cd22Stholo }
532c166cd22Stholo 
533c166cd22Stholo /*---------------------------------------------------------------------------
534c166cd22Stholo |   Facility      :  libnmenu
535c166cd22Stholo |   Function      :  void _nc_New_TopRow_and_CurrentItem(
536c166cd22Stholo |                            MENU *menu,
537c166cd22Stholo |                            int new_toprow,
538c166cd22Stholo |                            ITEM *new_current_item)
539c166cd22Stholo |
540c166cd22Stholo |   Description   :  Redisplay the menu so that the given row becomes the
541c166cd22Stholo |                    top row and the given item becomes the new current
542c166cd22Stholo |                    item.
543c166cd22Stholo |
544c166cd22Stholo |   Return Values :  -
545c166cd22Stholo +--------------------------------------------------------------------------*/
546*c7ef0cfcSnicm MENU_EXPORT(void)
_nc_New_TopRow_and_CurrentItem(MENU * menu,int new_toprow,ITEM * new_current_item)547*c7ef0cfcSnicm _nc_New_TopRow_and_CurrentItem(
548*c7ef0cfcSnicm 				MENU *menu,
549*c7ef0cfcSnicm 				int new_toprow,
550*c7ef0cfcSnicm 				ITEM *new_current_item)
551*c7ef0cfcSnicm {
552*c7ef0cfcSnicm   assert(menu);
553*c7ef0cfcSnicm   if (menu->status & _POSTED)
554c166cd22Stholo     {
555c166cd22Stholo       ITEM *cur_item;
556c166cd22Stholo       bool mterm_called = FALSE;
557c166cd22Stholo       bool iterm_called = FALSE;
558c166cd22Stholo 
559c166cd22Stholo       if (new_current_item != menu->curitem)
560c166cd22Stholo 	{
561c166cd22Stholo 	  Call_Hook(menu, itemterm);
562c166cd22Stholo 	  iterm_called = TRUE;
563c166cd22Stholo 	}
564c166cd22Stholo       if (new_toprow != menu->toprow)
565c166cd22Stholo 	{
566c166cd22Stholo 	  Call_Hook(menu, menuterm);
567c166cd22Stholo 	  mterm_called = TRUE;
568c166cd22Stholo 	}
569c166cd22Stholo 
570c166cd22Stholo       cur_item = menu->curitem;
571c166cd22Stholo       assert(cur_item);
572*c7ef0cfcSnicm       menu->toprow = (short)(((menu->rows - menu->frows) >= 0)
573*c7ef0cfcSnicm 			     ? min(menu->rows - menu->frows, new_toprow)
574*c7ef0cfcSnicm 			     : 0);
575c166cd22Stholo       menu->curitem = new_current_item;
576c166cd22Stholo 
577c166cd22Stholo       if (mterm_called)
578c166cd22Stholo 	{
579c166cd22Stholo 	  Call_Hook(menu, menuinit);
580c166cd22Stholo 	}
581c166cd22Stholo       if (iterm_called)
582c166cd22Stholo 	{
583c166cd22Stholo 	  /* this means, move from the old current_item to the new one... */
584c166cd22Stholo 	  Move_To_Current_Item(menu, cur_item);
585c166cd22Stholo 	  Call_Hook(menu, iteminit);
586c166cd22Stholo 	}
587c166cd22Stholo       if (mterm_called || iterm_called)
588c166cd22Stholo 	{
589c166cd22Stholo 	  _nc_Show_Menu(menu);
590c166cd22Stholo 	}
591c166cd22Stholo       else
592c166cd22Stholo 	pos_menu_cursor(menu);
593c166cd22Stholo     }
594c166cd22Stholo   else
595c166cd22Stholo     {				/* if we are not posted, this is quite simple */
596*c7ef0cfcSnicm       menu->toprow = (short)(((menu->rows - menu->frows) >= 0)
597*c7ef0cfcSnicm 			     ? min(menu->rows - menu->frows, new_toprow)
598*c7ef0cfcSnicm 			     : 0);
599c166cd22Stholo       menu->curitem = new_current_item;
600c166cd22Stholo     }
601c166cd22Stholo }
602c166cd22Stholo 
603c166cd22Stholo /* m_global.c ends here */
604