GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libmenu/m_global.c Lines: 0 157 0.0 %
Date: 2017-11-13 Branches: 0 150 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: m_global.c,v 1.8 2010/01/12 23:22:07 nicm Exp $ */
2
3
/****************************************************************************
4
 * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc.              *
5
 *                                                                          *
6
 * Permission is hereby granted, free of charge, to any person obtaining a  *
7
 * copy of this software and associated documentation files (the            *
8
 * "Software"), to deal in the Software without restriction, including      *
9
 * without limitation the rights to use, copy, modify, merge, publish,      *
10
 * distribute, distribute with modifications, sublicense, and/or sell       *
11
 * copies of the Software, and to permit persons to whom the Software is    *
12
 * furnished to do so, subject to the following conditions:                 *
13
 *                                                                          *
14
 * The above copyright notice and this permission notice shall be included  *
15
 * in all copies or substantial portions of the Software.                   *
16
 *                                                                          *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
20
 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
21
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
22
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
23
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
24
 *                                                                          *
25
 * Except as contained in this notice, the name(s) of the above copyright   *
26
 * holders shall not be used in advertising or otherwise to promote the     *
27
 * sale, use or other dealings in this Software without prior written       *
28
 * authorization.                                                           *
29
 ****************************************************************************/
30
31
/****************************************************************************
32
 *   Author:  Juergen Pfeifer, 1995,1997                                    *
33
 ****************************************************************************/
34
35
/***************************************************************************
36
* Module m_global                                                          *
37
* Globally used internal routines and the default menu and item structures *
38
***************************************************************************/
39
40
#include "menu.priv.h"
41
42
MODULE_ID("$Id: m_global.c,v 1.8 2010/01/12 23:22:07 nicm Exp $")
43
44
static char mark[] = "-";
45
/* *INDENT-OFF* */
46
NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu = {
47
  16,				  /* Nr. of chars high */
48
  1,				  /* Nr. of chars wide */
49
  16,				  /* Nr. of items high */
50
  1,			          /* Nr. of items wide */
51
  16,				  /* Nr. of formatted items high */
52
  1,				  /* Nr. of formatted items wide */
53
  16,				  /* Nr. of items high (actual) */
54
  0,				  /* length of widest name */
55
  0,				  /* length of widest description */
56
  1,				  /* length of mark */
57
  1,				  /* length of one item */
58
  1,                              /* Spacing for descriptor */
59
  1,                              /* Spacing for columns */
60
  1,                              /* Spacing for rows */
61
  (char *)0,			  /* buffer used to store match chars */
62
  0,				  /* Index into pattern buffer */
63
  (WINDOW *)0,			  /* Window containing entire menu */
64
  (WINDOW *)0,			  /* Portion of menu displayed */
65
  (WINDOW *)0,			  /* User's window */
66
  (WINDOW *)0,			  /* User's subwindow */
67
  (ITEM **)0,			  /* List of items */
68
  0,				  /* Total Nr. of items in menu */
69
  (ITEM *)0,			  /* Current item */
70
  0,				  /* Top row of menu */
71
  (chtype)A_REVERSE,		  /* Attribute for selection */
72
  (chtype)A_NORMAL,		  /* Attribute for nonselection */
73
  (chtype)A_UNDERLINE,		  /* Attribute for inactive */
74
  ' ',  			  /* Pad character */
75
  (Menu_Hook)0,			  /* Menu init */
76
  (Menu_Hook)0,			  /* Menu term */
77
  (Menu_Hook)0,			  /* Item init */
78
  (Menu_Hook)0,			  /* Item term */
79
  (void *)0,			  /* userptr */
80
  mark,				  /* mark */
81
  ALL_MENU_OPTS,                  /* options */
82
  0			          /* status */
83
};
84
85
NCURSES_EXPORT_VAR(ITEM) _nc_Default_Item = {
86
  { (char *)0, 0 },		  /* name */
87
  { (char *)0, 0 },		  /* description */
88
  (MENU *)0,		          /* Pointer to parent menu */
89
  (char *)0,			  /* Userpointer */
90
  ALL_ITEM_OPTS,		  /* options */
91
  0,				  /* Item Nr. */
92
  0,				  /* y */
93
  0,				  /* x */
94
  FALSE,			  /* value */
95
  (ITEM *)0,		          /* left */
96
  (ITEM *)0,		          /* right */
97
  (ITEM *)0,		          /* up */
98
  (ITEM *)0		          /* down */
99
  };
100
/* *INDENT-ON* */
101
102
/*---------------------------------------------------------------------------
103
|   Facility      :  libnmenu
104
|   Function      :  static void ComputeMaximum_NameDesc_Lenths(MENU *menu)
105
|
106
|   Description   :  Calculates the maximum name and description lengths
107
|                    of the items connected to the menu
108
|
109
|   Return Values :  -
110
+--------------------------------------------------------------------------*/
111
NCURSES_INLINE static void
112
ComputeMaximum_NameDesc_Lengths(MENU * menu)
113
{
114
  unsigned MaximumNameLength = 0;
115
  unsigned MaximumDescriptionLength = 0;
116
  ITEM **items;
117
  unsigned check;
118
119
  assert(menu && menu->items);
120
  for (items = menu->items; *items; items++)
121
    {
122
      check = _nc_Calculate_Text_Width(&((*items)->name));
123
      if (check > MaximumNameLength)
124
	MaximumNameLength = check;
125
126
      check = _nc_Calculate_Text_Width(&((*items)->description));
127
      if (check > MaximumDescriptionLength)
128
	MaximumDescriptionLength = check;
129
    }
130
131
  menu->namelen = MaximumNameLength;
132
  menu->desclen = MaximumDescriptionLength;
133
  T(("ComputeMaximum_NameDesc_Lengths %d,%d", menu->namelen, menu->desclen));
134
}
135
136
/*---------------------------------------------------------------------------
137
|   Facility      :  libnmenu
138
|   Function      :  static void ResetConnectionInfo(MENU *, ITEM **)
139
|
140
|   Description   :  Reset all informations in the menu and the items in
141
|                    the item array that indicates a connection
142
|
143
|   Return Values :  -
144
+--------------------------------------------------------------------------*/
145
NCURSES_INLINE static void
146
ResetConnectionInfo(MENU * menu, ITEM ** items)
147
{
148
  ITEM **item;
149
150
  assert(menu && items);
151
  for (item = items; *item; item++)
152
    {
153
      (*item)->index = 0;
154
      (*item)->imenu = (MENU *) 0;
155
    }
156
  if (menu->pattern)
157
    free(menu->pattern);
158
  menu->pattern = (char *)0;
159
  menu->pindex = 0;
160
  menu->items = (ITEM **) 0;
161
  menu->nitems = 0;
162
}
163
164
/*---------------------------------------------------------------------------
165
|   Facility      :  libnmenu
166
|   Function      :  bool _nc_Connect_Items(MENU *menu, ITEM **items)
167
|
168
|   Description   :  Connect the items in the item array to the menu.
169
|                    Decorate all the items with a number and a backward
170
|                    pointer to the menu.
171
|
172
|   Return Values :  TRUE       - successful connection
173
|                    FALSE      - connection failed
174
+--------------------------------------------------------------------------*/
175
NCURSES_EXPORT(bool)
176
_nc_Connect_Items(MENU * menu, ITEM ** items)
177
{
178
  ITEM **item;
179
  unsigned int ItemCount = 0;
180
181
  if (menu && items)
182
    {
183
      for (item = items; *item; item++)
184
	{
185
	  if ((*item)->imenu)
186
	    {
187
	      /* if a item is already connected, reject connection */
188
	      break;
189
	    }
190
	}
191
      if (!(*item))
192
	/* we reached the end, so there was no connected item */
193
	{
194
	  for (item = items; *item; item++)
195
	    {
196
	      if (menu->opt & O_ONEVALUE)
197
		{
198
		  (*item)->value = FALSE;
199
		}
200
	      (*item)->index = ItemCount++;
201
	      (*item)->imenu = menu;
202
	    }
203
	}
204
    }
205
  else
206
    return (FALSE);
207
208
  if (ItemCount != 0)
209
    {
210
      menu->items = items;
211
      menu->nitems = ItemCount;
212
      ComputeMaximum_NameDesc_Lengths(menu);
213
      if ((menu->pattern = typeMalloc(char, (unsigned)(1 + menu->namelen))))
214
	{
215
	  Reset_Pattern(menu);
216
	  set_menu_format(menu, menu->frows, menu->fcols);
217
	  menu->curitem = *items;
218
	  menu->toprow = 0;
219
	  return (TRUE);
220
	}
221
    }
222
223
  /* If we fall through to this point, we have to reset all items connection
224
     and inform about a reject connection */
225
  ResetConnectionInfo(menu, items);
226
  return (FALSE);
227
}
228
229
/*---------------------------------------------------------------------------
230
|   Facility      :  libnmenu
231
|   Function      :  void _nc_Disconnect_Items(MENU *menu)
232
|
233
|   Description   :  Disconnect the menus item array from the menu
234
|
235
|   Return Values :  -
236
+--------------------------------------------------------------------------*/
237
NCURSES_EXPORT(void)
238
_nc_Disconnect_Items(MENU * menu)
239
{
240
  if (menu && menu->items)
241
    ResetConnectionInfo(menu, menu->items);
242
}
243
244
/*---------------------------------------------------------------------------
245
|   Facility      :  libnmenu
246
|   Function      :  int _nc_Calculate_Text_Width(const TEXT * item)
247
|
248
|   Description   :  Calculate the number of columns for a TEXT.
249
|
250
|   Return Values :  the width
251
+--------------------------------------------------------------------------*/
252
NCURSES_EXPORT(int)
253
_nc_Calculate_Text_Width(const TEXT * item /*FIXME: limit length */ )
254
{
255
#if USE_WIDEC_SUPPORT
256
  int result = item->length;
257
258
  T((T_CALLED("_nc_menu_text_width(%p)"), item));
259
  if (result != 0 && item->str != 0)
260
    {
261
      int count = mbstowcs(0, item->str, 0);
262
      wchar_t *temp = 0;
263
264
      if (count > 0
265
	  && (temp = typeMalloc(wchar_t, 2 + count)) != 0)
266
	{
267
	  int n;
268
269
	  result = 0;
270
	  mbstowcs(temp, item->str, (unsigned)count);
271
	  for (n = 0; n < count; ++n)
272
	    {
273
	      int test = wcwidth(temp[n]);
274
275
	      if (test <= 0)
276
		test = 1;
277
	      result += test;
278
	    }
279
	  free(temp);
280
	}
281
    }
282
  returnCode(result);
283
#else
284
  return item->length;
285
#endif
286
}
287
288
/*
289
 * Calculate the actual width of a menu entry for wide-characters.
290
 */
291
#if USE_WIDEC_SUPPORT
292
static int
293
calculate_actual_width(MENU * menu, bool name)
294
{
295
  int width = 0;
296
  int check = 0;
297
  ITEM **items;
298
299
  assert(menu && menu->items);
300
301
  if (menu->items != 0)
302
    {
303
      for (items = menu->items; *items; items++)
304
	{
305
	  if (name)
306
	    {
307
	      check = _nc_Calculate_Text_Width(&((*items)->name));
308
	    }
309
	  else
310
	    {
311
	      check = _nc_Calculate_Text_Width(&((*items)->description));
312
	    }
313
	  if (check > width)
314
	    width = check;
315
	}
316
    }
317
  else
318
    {
319
      width = (name ? menu->namelen : menu->desclen);
320
    }
321
322
  T(("calculate_actual_width %s = %d/%d",
323
     name ? "name" : "desc",
324
     width,
325
     name ? menu->namelen : menu->desclen));
326
  return width;
327
}
328
#else
329
#define calculate_actual_width(menu, name) (name ? menu->namelen : menu->desclen)
330
#endif
331
332
/*---------------------------------------------------------------------------
333
|   Facility      :  libnmenu
334
|   Function      :  void _nc_Calculate_Item_Length_and_Width(MENU *menu)
335
|
336
|   Description   :  Calculate the length of an item and the width of the
337
|                    whole menu.
338
|
339
|   Return Values :  -
340
+--------------------------------------------------------------------------*/
341
NCURSES_EXPORT(void)
342
_nc_Calculate_Item_Length_and_Width(MENU * menu)
343
{
344
  int l;
345
346
  assert(menu);
347
348
  menu->height = 1 + menu->spc_rows * (menu->arows - 1);
349
350
  l = calculate_actual_width(menu, TRUE);
351
  l += menu->marklen;
352
353
  if ((menu->opt & O_SHOWDESC) && (menu->desclen > 0))
354
    {
355
      l += calculate_actual_width(menu, FALSE);
356
      l += menu->spc_desc;
357
    }
358
359
  menu->itemlen = l;
360
  l *= menu->cols;
361
  l += (menu->cols - 1) * menu->spc_cols;	/* for the padding between the columns */
362
  menu->width = l;
363
364
  T(("_nc_CalculateItem_Length_and_Width columns %d, item %d, width %d",
365
     menu->cols,
366
     menu->itemlen,
367
     menu->width));
368
}
369
370
/*---------------------------------------------------------------------------
371
|   Facility      :  libnmenu
372
|   Function      :  void _nc_Link_Item(MENU *menu)
373
|
374
|   Description   :  Statically calculate for every item its four neighbors.
375
|                    This depends on the orientation of the menu. This
376
|                    static approach simplifies navigation in the menu a lot.
377
|
378
|   Return Values :  -
379
+--------------------------------------------------------------------------*/
380
NCURSES_EXPORT(void)
381
_nc_Link_Items(MENU * menu)
382
{
383
  if (menu && menu->items && *(menu->items))
384
    {
385
      int i, j;
386
      ITEM *item;
387
      int Number_Of_Items = menu->nitems;
388
      int col = 0, row = 0;
389
      int Last_in_Row;
390
      int Last_in_Column;
391
      bool cycle = (menu->opt & O_NONCYCLIC) ? FALSE : TRUE;
392
393
      menu->status &= ~_LINK_NEEDED;
394
395
      if (menu->opt & O_ROWMAJOR)
396
	{
397
	  int Number_Of_Columns = menu->cols;
398
399
	  for (i = 0; i < Number_Of_Items; i++)
400
	    {
401
	      item = menu->items[i];
402
403
	      Last_in_Row = row * Number_Of_Columns + (Number_Of_Columns - 1);
404
405
	      item->left = (col) ?
406
	      /* if we are not in the leftmost column, we can use the
407
	         predecessor in the items array */
408
		menu->items[i - 1] :
409
		(cycle ? menu->items[(Last_in_Row >= Number_Of_Items) ?
410
				     Number_Of_Items - 1 :
411
				     Last_in_Row] :
412
		 (ITEM *) 0);
413
414
	      item->right = ((col < (Number_Of_Columns - 1)) &&
415
			     ((i + 1) < Number_Of_Items)
416
		)?
417
		menu->items[i + 1] :
418
		(cycle ? menu->items[row * Number_Of_Columns] :
419
		 (ITEM *) 0
420
		);
421
422
	      Last_in_Column = (menu->rows - 1) * Number_Of_Columns + col;
423
424
	      item->up = (row) ? menu->items[i - Number_Of_Columns] :
425
		(cycle ? menu->items[(Last_in_Column >= Number_Of_Items) ?
426
				     Number_Of_Items - 1 :
427
				     Last_in_Column] :
428
		 (ITEM *) 0);
429
430
	      item->down = ((i + Number_Of_Columns) < Number_Of_Items)
431
		?
432
		menu->items[i + Number_Of_Columns] :
433
		(cycle ? menu->items[(row + 1) < menu->rows ?
434
				     Number_Of_Items - 1 : col] :
435
		 (ITEM *) 0);
436
	      item->x = col;
437
	      item->y = row;
438
	      if (++col == Number_Of_Columns)
439
		{
440
		  row++;
441
		  col = 0;
442
		}
443
	    }
444
	}
445
      else
446
	{
447
	  int Number_Of_Rows = menu->rows;
448
449
	  for (j = 0; j < Number_Of_Items; j++)
450
	    {
451
	      item = menu->items[i = (col * Number_Of_Rows + row)];
452
453
	      Last_in_Column = (menu->cols - 1) * Number_Of_Rows + row;
454
455
	      item->left = (col) ?
456
		menu->items[i - Number_Of_Rows] :
457
		(cycle ? (Last_in_Column >= Number_Of_Items) ?
458
		 menu->items[Last_in_Column - Number_Of_Rows] :
459
		 menu->items[Last_in_Column] :
460
		 (ITEM *) 0);
461
462
	      item->right = ((i + Number_Of_Rows) < Number_Of_Items)
463
		?
464
		menu->items[i + Number_Of_Rows] :
465
		(cycle ? menu->items[row] : (ITEM *) 0);
466
467
	      Last_in_Row = col * Number_Of_Rows + (Number_Of_Rows - 1);
468
469
	      item->up = (row) ?
470
		menu->items[i - 1] :
471
		(cycle ?
472
		 menu->items[(Last_in_Row >= Number_Of_Items) ?
473
			     Number_Of_Items - 1 :
474
			     Last_in_Row] :
475
		 (ITEM *) 0);
476
477
	      item->down = (row < (Number_Of_Rows - 1))
478
		?
479
		(menu->items[((i + 1) < Number_Of_Items) ?
480
			     i + 1 :
481
			     (col - 1) * Number_Of_Rows + row + 1]) :
482
		(cycle ?
483
		 menu->items[col * Number_Of_Rows] :
484
		 (ITEM *) 0
485
		);
486
487
	      item->x = col;
488
	      item->y = row;
489
	      if ((++row) == Number_Of_Rows)
490
		{
491
		  col++;
492
		  row = 0;
493
		}
494
	    }
495
	}
496
    }
497
}
498
499
/*---------------------------------------------------------------------------
500
|   Facility      :  libnmenu
501
|   Function      :  void _nc_Show_Menu(const MENU *menu)
502
|
503
|   Description   :  Update the window that is associated with the menu
504
|
505
|   Return Values :  -
506
+--------------------------------------------------------------------------*/
507
NCURSES_EXPORT(void)
508
_nc_Show_Menu(const MENU * menu)
509
{
510
  WINDOW *win;
511
  int maxy, maxx;
512
513
  assert(menu);
514
  if ((menu->status & _POSTED) && !(menu->status & _IN_DRIVER))
515
    {
516
      /* adjust the internal subwindow to start on the current top */
517
      assert(menu->sub);
518
      mvderwin(menu->sub, menu->spc_rows * menu->toprow, 0);
519
      win = Get_Menu_Window(menu);
520
521
      maxy = getmaxy(win);
522
      maxx = getmaxx(win);
523
524
      if (menu->height < maxy)
525
	maxy = menu->height;
526
      if (menu->width < maxx)
527
	maxx = menu->width;
528
529
      copywin(menu->sub, win, 0, 0, 0, 0, maxy - 1, maxx - 1, 0);
530
      pos_menu_cursor(menu);
531
    }
532
}
533
534
/*---------------------------------------------------------------------------
535
|   Facility      :  libnmenu
536
|   Function      :  void _nc_New_TopRow_and_CurrentItem(
537
|                            MENU *menu,
538
|                            int new_toprow,
539
|                            ITEM *new_current_item)
540
|
541
|   Description   :  Redisplay the menu so that the given row becomes the
542
|                    top row and the given item becomes the new current
543
|                    item.
544
|
545
|   Return Values :  -
546
+--------------------------------------------------------------------------*/
547
NCURSES_EXPORT(void)
548
  _nc_New_TopRow_and_CurrentItem
549
  (MENU * menu, int new_toprow, ITEM * new_current_item)
550
{
551
  ITEM *cur_item;
552
  bool mterm_called = FALSE;
553
  bool iterm_called = FALSE;
554
555
  assert(menu);
556
  if (menu->status & _POSTED)
557
    {
558
      if (new_current_item != menu->curitem)
559
	{
560
	  Call_Hook(menu, itemterm);
561
	  iterm_called = TRUE;
562
	}
563
      if (new_toprow != menu->toprow)
564
	{
565
	  Call_Hook(menu, menuterm);
566
	  mterm_called = TRUE;
567
	}
568
569
      cur_item = menu->curitem;
570
      assert(cur_item);
571
      menu->toprow = new_toprow;
572
      menu->curitem = new_current_item;
573
574
      if (mterm_called)
575
	{
576
	  Call_Hook(menu, menuinit);
577
	}
578
      if (iterm_called)
579
	{
580
	  /* this means, move from the old current_item to the new one... */
581
	  Move_To_Current_Item(menu, cur_item);
582
	  Call_Hook(menu, iteminit);
583
	}
584
      if (mterm_called || iterm_called)
585
	{
586
	  _nc_Show_Menu(menu);
587
	}
588
      else
589
	pos_menu_cursor(menu);
590
    }
591
  else
592
    {				/* if we are not posted, this is quite simple */
593
      menu->toprow = new_toprow;
594
      menu->curitem = new_current_item;
595
    }
596
}
597
598
/* m_global.c ends here */