home *** CD-ROM | disk | FTP | other *** search
- /**
- *
- * Name MNITEM -- Add, change, or remove an item in a menu.
- *
- * Synopsis presult = mnitem (pmenu, row, col, option, pstring);
- *
- * BMENU *presult Pointer to menu which item and key(s)
- * were just added to, or NIL for failure.
- * BMENU *pmenu Pointer to menu to which to add item.
- * int row, Row and column (relative to menu's
- * col window data area) at which to place
- * the item.
- * int option The bitwise OR-ing of the following values:
- * MN_PROTECT
- * Item is protected.
- * MN_NOPROTECT
- * Item is not protected.
- * MN_CHAR_ATTR
- * PSTRING contains character/attribute
- * pairs, terminated by a '\0' in a
- * character cell.
- * MN_CHARS_ONLY
- * PSTRING contains a normal '\0'
- * terminated string.
- * const char *pstring
- * Text of the item.
- *
- * Description This function writes an item to a menu. An example
- * is probably best here:
- *
- * The call:
- * presult = mnitem (pmenu, 5, 2, MN_PROTECT, "Close");
- *
- * Will add the text "Close" to the menu at (5,2). The
- * item will be in the "protection" attribute, because
- * "option" is MN_PROTECT.
- *
- * If row and col match an existing item, then MNITEM will
- * change the existing item if pstring is not NIL or the
- * NULL string (""), or it will remove the existing item
- * if pstring is NIL or the NULL string.
- *
- * An error occurs if row or col exceeds the menu's
- * window dimensions.
- *
- * Returns presult Pointer to changed menu, or
- * NIL if failure.
- * b_wnerr Possible values:
- * (No change) Success.
- * MN_BAD_MENU Pmenu is invalid.
- * MN_BAD_ITEM A member of pmenu's item
- * list is bad.
- * WN_BAD_WIN Pmenu's window is invalid.
- * WN_NO_MEMORY Insufficient memory.
- * WN_ILL_DIM Row or col out of range
- *
- * Version 6.00 (C)Copyright Blaise Computing Inc. 1987,1989
- *
- **/
-
-
- #include <string.h>
-
- #include <bmenu.h>
-
- #define TRUE 1
- #define FALSE 0
-
- #define NUL '\0'
-
- static int write_item(const BMENU *,const BITEM *,const char *);
-
-
- BMENU *mnitem (pmenu, row, col, option, pstring)
- BMENU *pmenu;
- int row, col, option;
- const char *pstring;
- {
- int done = FALSE;
- BITEM *pitem, *qitem;
- BKEYMAP *pkey;
-
- /* Validate menu data structures. */
- mnvalidm (pmenu)
-
- /* Make sure given row and col are within bounds. */
- if (utrange (row, 0, pmenu->pwin->img.dim.h - 1) ||
- utrange (col, 0, pmenu->pwin->img.dim.w - 1))
- wnreterr (WN_ILL_DIM);
-
- /* Go through all existing menu items, and make */
- /* qitem trail pitem through the list. */
- for (pitem = pmenu->pitems, qitem = NIL;
- (pitem != NIL) && (!done);
- qitem = pitem, pitem = pitem->next)
- {
- /* Check item signature byte. */
- if (pitem->signature != MN_ITEM_SIGN)
- wnreterr (MN_BAD_ITEM);
-
- /* If existing row and column match, replace */
- /* existing item. */
- if ((pitem->row == row) && (pitem->col == col))
- {
- /* Erase the area used by the old item in the menu. */
- if (NIL == wnscrblk (pmenu->pwin,
- row, col, row, (col + pitem->len) - 1,
- -1, -1, WNSCR_LEFT, 0, WN_UPDATE))
- return NIL;
-
- /* Delete existing item if replacement string is */
- /* NIL or the NUL-string. */
- if ((pstring == NIL) || (*pstring == NUL))
- {
- done = TRUE;
-
- /* Make previous item point at next item. */
- if (qitem == NIL)
- pmenu->pitems = pitem->next;
- else
- qitem->next = pitem->next;
-
- /* Delete item signature. */
- pitem->signature = MN_DEAD_ITEM;
-
- /* Free memory used by old item, and delete any key */
- /* bindings to this row and column. */
- if (pitem->plstring)
- free (pitem->plstring);
- if (pitem->pcharattr)
- free (pitem->pcharattr);
- free (pitem);
-
- for (pkey = pmenu->pkeys; pkey != NIL; pkey = pkey->next)
- {
- /* Make sure to remove every key for the item. */
- if ((pkey->row == row) &&
- (pkey->col == col))
- {
- if (NIL == mnkey(pmenu,row,col,pkey->ch,pkey->scan,
- 0,MN_DELETE))
- return NIL;
- }
- }
- }
- else
- { /* The replacement string is not NULL, so do a true */
- /* replacement. */
- done = TRUE;
-
- /* Figure out length of new item within bounds of */
- /* window it has to fit in (or be truncated by). */
- if (option & MN_CHAR_ATTR)
- {
-
- /* If the string contains character/attribute pairs,*/
- /* find the index of the first character equal to */
- /* '\0'. Note that pitem->len is the length of the */
- /* ASCII text, not the entire buffer. */
-
- for (pitem->len = 0; pstring[pitem->len];
- pitem->len += 2)
- ;
- pitem->len /= 2;
- }
- else
- pitem->len = strlen(pstring);
- pitem->len = mntrunc (pmenu, pitem->len, col);
-
- /* Copy new char_attr string, if present, into item.*/
- if (option & MN_CHAR_ATTR)
- {
- if (pitem->pcharattr != NIL)
- free(pitem->pcharattr);
- if ((pitem->pcharattr = malloc(pitem->len * 2)) == NIL)
- wnreterr (WN_NO_MEMORY);
- memmove((void *) pitem->pcharattr, (void *) pstring,
- pitem->len * 2);
- }
-
- /* Figure out protection value, record attribute. */
- pitem->option = option;
- pitem->attr = pmenu->pwin->attr;
-
- /* Write the text of the new item to the menu's */
- /* window. */
- if (write_item(pmenu, pitem, pstring))
- return NIL;
- }
- }
- }
-
- /* If there is a non-NUL string to place, and we */
- /* have not already done anything with it, it must */
- /* be a string to be added... so we will add it. */
-
- /* qitem points to the last item in the list, or is */
- /* NIL if there is no item list yet. */
- if ((!done) && (pstring != NIL) && (*pstring != NUL))
- {
- /* Attempt to allocate space for the new item. */
- if ((pitem = utalloc (BITEM)) == NIL)
- wnreterr (WN_NO_MEMORY);
-
- /* Figure out length of new item within bounds of */
- /* window it has to fit in (or be truncated by). */
- if (option & MN_CHAR_ATTR)
- {
- /* If the string contains character/attribute pairs,*/
- /* find the index of the first character equal to */
- /* '\0'. Note that pitem->len is the length of the */
- /* ASCII text, not the entire buffer. */
-
- for (pitem->len = 0; pstring[pitem->len]; pitem->len += 2)
- ;
- pitem->len /= 2;
- }
- else
- pitem->len = strlen(pstring);
- pitem->len = mntrunc (pmenu, pitem->len, col);
-
- /* Store values for future reference. */
- pitem->attr = pmenu->pwin->attr;
- pitem->row = row;
- pitem->col = col;
- pitem->option = option;
- pitem->plstring = NIL;
- pitem->pcharattr = NIL;
- pitem->next = NIL;
-
- /* Copy char_attr string, if present, into item. */
- if (option & MN_CHAR_ATTR)
- {
- if ((pitem->pcharattr = malloc(pitem->len * 2)) == NIL)
- wnreterr (WN_NO_MEMORY);
- memmove((void *) pitem->pcharattr, (void *) pstring,
- pitem->len * 2);
- }
-
- /* Create item signature. */
- pitem->signature= MN_ITEM_SIGN;
-
- /* If there is no item list, add this as the first */
- /* item, otherwise add this item to the tail of the */
- /* item list. */
- if (pmenu->pitems == NIL)
- pmenu->pitems = pitem;
- else
- qitem->next = pitem;
-
- /* Write the text of the new item to the menu's */
- /* window. */
- if (write_item(pmenu, pitem, pstring))
- return NIL;
-
- done = TRUE;
-
- }
-
- return (pmenu);
- }
-
- /**
- *
- * Name WRITE_ITEM -- Write the text (and attributes, if
- * present) of an item into its window.
- *
- * Synopsis error = write_item(pmenu, pitem, pstring);
- *
- * int error Nonzero if error, zero if okay.
- * const BMENU *pmenu The menu to write to.
- * const BITEM *pitem Item to write to the menu.
- * const char *pstring The item's text (possibly character/
- * attribute pairs).
- *
- * Description This function writes an item's text into a menu. If the
- * item's MN_CHAR_ATTR bit is set, pstring contains character/
- * attribute pairs; if the item's MN_PROTECT bit is not set,
- * these attributes are also written.
- *
- * Returns error Nonzero if error, zero if okay.
- *
- **/
-
- static int write_item(pmenu, pitem, pstring)
- const BMENU *pmenu;
- const BITEM *pitem;
- const char *pstring;
- {
- return (NIL == wnwrrect(pmenu->pwin,
- pitem->row,pitem->col,
- pitem->row,pitem->col + pitem->len - 1,
- pstring,
- (pitem->option & MN_PROTECT)
- ? (utlonyb (pmenu->proattr)) : (-1),
- (pitem->option & MN_PROTECT)
- ? (uthinyb (pmenu->proattr)) : (-1),
- WN_UPDATE |
- ((pitem->option & MN_CHAR_ATTR)
- ? CHAR_ATTR : CHARS_ONLY)));
- }