home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c070 / 4.ddi / TOOLS.4 / TCTSRC1.EXE / MNITEM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-31  |  8.6 KB  |  302 lines

  1. /**
  2. *
  3. * Name        MNITEM -- Add, change, or remove an item in a menu.
  4. *
  5. * Synopsis    presult = mnitem (pmenu, row, col, option, pstring);
  6. *
  7. *        BMENU *presult    Pointer to menu which item and key(s)
  8. *                were just added to, or NIL for failure.
  9. *        BMENU *pmenu    Pointer to menu to which to add item.
  10. *        int    row,    Row and column (relative to menu's
  11. *               col    window data area) at which to place
  12. *                the item.
  13. *        int    option    The bitwise OR-ing of the following values:
  14. *                    MN_PROTECT
  15. *                    Item is protected.
  16. *                    MN_NOPROTECT
  17. *                    Item is not protected.
  18. *                    MN_CHAR_ATTR
  19. *                    PSTRING contains character/attribute
  20. *                    pairs, terminated by a '\0' in a
  21. *                    character cell.
  22. *                    MN_CHARS_ONLY
  23. *                    PSTRING contains a normal '\0'
  24. *                    terminated string.
  25. *        const char *pstring
  26. *                Text of the item.
  27. *
  28. * Description    This function writes an item to a menu.  An example
  29. *        is probably best here:
  30. *
  31. *        The call:
  32. *            presult = mnitem (pmenu, 5, 2, MN_PROTECT, "Close");
  33. *
  34. *        Will add the text "Close" to the menu at (5,2).  The
  35. *        item will be in the "protection" attribute, because
  36. *        "option" is MN_PROTECT.
  37. *
  38. *        If row and col match an existing item, then MNITEM will
  39. *        change the existing item if pstring is not NIL or the
  40. *        NULL string (""), or it will remove the existing item
  41. *        if pstring is NIL or the NULL string.
  42. *
  43. *        An error occurs if row or col exceeds the menu's
  44. *        window dimensions.
  45. *
  46. * Returns    presult         Pointer to changed menu, or
  47. *                    NIL if failure.
  48. *        b_wnerr     Possible values:
  49. *                (No change)    Success.
  50. *                MN_BAD_MENU    Pmenu is invalid.
  51. *                MN_BAD_ITEM    A member of pmenu's item
  52. *                        list is bad.
  53. *                WN_BAD_WIN    Pmenu's window is invalid.
  54. *                WN_NO_MEMORY    Insufficient memory.
  55. *                WN_ILL_DIM    Row or col out of range
  56. *
  57. * Version    6.00 (C)Copyright Blaise Computing Inc.  1987,1989
  58. *
  59. **/
  60.  
  61.  
  62. #include <string.h>
  63.  
  64. #include <bmenu.h>
  65.  
  66. #define TRUE  1
  67. #define FALSE 0
  68.  
  69. #define NUL '\0'
  70.  
  71. static int write_item(const BMENU *,const BITEM *,const char *);
  72.  
  73.  
  74. BMENU *mnitem (pmenu, row, col, option, pstring)
  75. BMENU *pmenu;
  76. int    row, col, option;
  77. const char *pstring;
  78. {
  79.     int      done = FALSE;
  80.     BITEM    *pitem, *qitem;
  81.     BKEYMAP  *pkey;
  82.  
  83.         /* Validate menu data structures.            */
  84.     mnvalidm (pmenu)
  85.  
  86.         /* Make sure given row and col are within bounds.   */
  87.     if (utrange (row, 0, pmenu->pwin->img.dim.h - 1) ||
  88.     utrange (col, 0, pmenu->pwin->img.dim.w - 1))
  89.     wnreterr (WN_ILL_DIM);
  90.  
  91.         /* Go through all existing menu items, and make     */
  92.         /* qitem trail pitem through the list.            */
  93.     for (pitem = pmenu->pitems,  qitem = NIL;
  94.      (pitem != NIL) && (!done);
  95.      qitem = pitem,  pitem = pitem->next)
  96.     {
  97.         /* Check item signature byte.                */
  98.     if (pitem->signature != MN_ITEM_SIGN)
  99.         wnreterr (MN_BAD_ITEM);
  100.  
  101.         /* If existing row and column match, replace        */
  102.         /* existing item.                    */
  103.     if ((pitem->row == row) && (pitem->col == col))
  104.     {
  105.         /* Erase the area used by the old item in the menu. */
  106.         if (NIL == wnscrblk (pmenu->pwin,
  107.                  row, col, row, (col + pitem->len) - 1,
  108.                  -1, -1, WNSCR_LEFT, 0, WN_UPDATE))
  109.         return NIL;
  110.  
  111.         /* Delete existing item if replacement string is    */
  112.         /* NIL or the NUL-string.                */
  113.         if ((pstring == NIL) || (*pstring == NUL))
  114.         {
  115.         done = TRUE;
  116.  
  117.         /* Make previous item point at next item.        */
  118.         if (qitem == NIL)
  119.             pmenu->pitems = pitem->next;
  120.         else
  121.             qitem->next = pitem->next;
  122.  
  123.         /* Delete item signature.                */
  124.         pitem->signature = MN_DEAD_ITEM;
  125.  
  126.         /* Free memory used by old item, and delete any key */
  127.         /* bindings to this row and column.            */
  128.         if (pitem->plstring)
  129.             free (pitem->plstring);
  130.         if (pitem->pcharattr)
  131.             free (pitem->pcharattr);
  132.         free (pitem);
  133.  
  134.         for (pkey = pmenu->pkeys; pkey != NIL; pkey = pkey->next)
  135.         {
  136.         /* Make sure to remove every key for the item.        */
  137.             if ((pkey->row == row)   &&
  138.             (pkey->col == col))
  139.             {
  140.             if (NIL == mnkey(pmenu,row,col,pkey->ch,pkey->scan,
  141.                      0,MN_DELETE))
  142.                 return NIL;
  143.             }
  144.         }
  145.         }
  146.         else
  147.         {    /* The replacement string is not NULL, so do a true */
  148.         /* replacement.                     */
  149.         done = TRUE;
  150.  
  151.         /* Figure out length of new item within bounds of   */
  152.         /* window it has to fit in (or be truncated by).    */
  153.         if (option & MN_CHAR_ATTR)
  154.         {
  155.  
  156.         /* If the string contains character/attribute pairs,*/
  157.         /* find the index of the first character equal to   */
  158.         /* '\0'. Note that pitem->len is the length of the  */
  159.         /* ASCII text, not the entire buffer.            */
  160.  
  161.             for (pitem->len = 0; pstring[pitem->len];
  162.              pitem->len += 2)
  163.             ;
  164.             pitem->len /= 2;
  165.         }
  166.         else
  167.             pitem->len = strlen(pstring);
  168.         pitem->len = mntrunc (pmenu, pitem->len, col);
  169.  
  170.         /* Copy new char_attr string, if present, into item.*/
  171.         if (option & MN_CHAR_ATTR)
  172.         {
  173.             if (pitem->pcharattr != NIL)
  174.             free(pitem->pcharattr);
  175.             if ((pitem->pcharattr = malloc(pitem->len * 2)) == NIL)
  176.             wnreterr (WN_NO_MEMORY);
  177.             memmove((void *) pitem->pcharattr, (void *) pstring,
  178.                 pitem->len * 2);
  179.         }
  180.  
  181.         /* Figure out protection value, record attribute.   */
  182.         pitem->option = option;
  183.         pitem->attr   = pmenu->pwin->attr;
  184.  
  185.         /* Write the text of the new item to the menu's     */
  186.         /* window.                        */
  187.         if (write_item(pmenu, pitem, pstring))
  188.             return NIL;
  189.         }
  190.     }
  191.     }
  192.  
  193.         /* If there is a non-NUL string to place, and we    */
  194.         /* have not already done anything with it, it must  */
  195.         /* be a string to be added... so we will add it.    */
  196.  
  197.         /* qitem points to the last item in the list, or is */
  198.         /* NIL if there is no item list yet.            */
  199.     if ((!done) && (pstring != NIL) && (*pstring != NUL))
  200.     {
  201.         /* Attempt to allocate space for the new item.        */
  202.     if ((pitem = utalloc (BITEM)) == NIL)
  203.         wnreterr (WN_NO_MEMORY);
  204.  
  205.         /* Figure out length of new item within bounds of   */
  206.         /* window it has to fit in (or be truncated by).    */
  207.     if (option & MN_CHAR_ATTR)
  208.     {
  209.         /* If the string contains character/attribute pairs,*/
  210.         /* find the index of the first character equal to   */
  211.         /* '\0'. Note that pitem->len is the length of the  */
  212.         /* ASCII text, not the entire buffer.            */
  213.  
  214.         for (pitem->len = 0; pstring[pitem->len]; pitem->len += 2)
  215.         ;
  216.         pitem->len /= 2;
  217.     }
  218.     else
  219.         pitem->len = strlen(pstring);
  220.     pitem->len = mntrunc (pmenu, pitem->len, col);
  221.  
  222.         /* Store values for future reference.            */
  223.     pitem->attr     = pmenu->pwin->attr;
  224.     pitem->row     = row;
  225.     pitem->col     = col;
  226.     pitem->option     = option;
  227.     pitem->plstring  = NIL;
  228.     pitem->pcharattr = NIL;
  229.     pitem->next     = NIL;
  230.  
  231.         /* Copy char_attr string, if present, into item.    */
  232.     if (option & MN_CHAR_ATTR)
  233.     {
  234.         if ((pitem->pcharattr = malloc(pitem->len * 2)) == NIL)
  235.         wnreterr (WN_NO_MEMORY);
  236.         memmove((void *) pitem->pcharattr, (void *) pstring,
  237.             pitem->len * 2);
  238.     }
  239.  
  240.         /* Create item signature.                */
  241.     pitem->signature= MN_ITEM_SIGN;
  242.  
  243.         /* If there is no item list, add this as the first  */
  244.         /* item, otherwise add this item to the tail of the */
  245.         /* item list.                        */
  246.     if (pmenu->pitems == NIL)
  247.         pmenu->pitems = pitem;
  248.     else
  249.         qitem->next = pitem;
  250.  
  251.         /* Write the text of the new item to the menu's     */
  252.         /* window.                        */
  253.     if (write_item(pmenu, pitem, pstring))
  254.         return NIL;
  255.  
  256.     done = TRUE;
  257.  
  258.     }
  259.  
  260.     return (pmenu);
  261. }
  262.  
  263. /**
  264. *
  265. * Name        WRITE_ITEM -- Write the text (and attributes, if
  266. *                  present) of an item into its window.
  267. *
  268. * Synopsis    error = write_item(pmenu, pitem, pstring);
  269. *
  270. *        int         error    Nonzero if error, zero if okay.
  271. *        const BMENU *pmenu    The menu to write to.
  272. *        const BITEM *pitem    Item to write to the menu.
  273. *        const char  *pstring  The item's text (possibly character/
  274. *                      attribute pairs).
  275. *
  276. * Description    This function writes an item's text into a menu.  If the
  277. *        item's MN_CHAR_ATTR bit is set, pstring contains character/
  278. *        attribute pairs; if the item's MN_PROTECT bit is not set,
  279. *        these attributes are also written.
  280. *
  281. * Returns    error        Nonzero if error, zero if okay.
  282. *
  283. **/
  284.  
  285. static int write_item(pmenu, pitem, pstring)
  286. const BMENU *pmenu;
  287. const BITEM *pitem;
  288. const char  *pstring;
  289. {
  290.     return (NIL == wnwrrect(pmenu->pwin,
  291.                 pitem->row,pitem->col,
  292.                 pitem->row,pitem->col + pitem->len - 1,
  293.                 pstring,
  294.                 (pitem->option & MN_PROTECT)
  295.                 ? (utlonyb (pmenu->proattr)) : (-1),
  296.                 (pitem->option & MN_PROTECT)
  297.                 ? (uthinyb (pmenu->proattr)) : (-1),
  298.                 WN_UPDATE |
  299.                   ((pitem->option & MN_CHAR_ATTR)
  300.                    ? CHAR_ATTR : CHARS_ONLY)));
  301. }
  302.