home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 2 / DATAFILE_PDCD2.iso / utilities2 / desklib / Libraries / Menu / c / NewMenu < prev    next >
Encoding:
Text File  |  1993-07-14  |  5.4 KB  |  205 lines

  1. /*
  2.     ####             #    #     # #
  3.     #   #            #    #       #          The FreeWare C library for 
  4.     #   #  ##   ###  #  # #     # ###             RISC OS machines
  5.     #   # #  # #     # #  #     # #  #   ___________________________________
  6.     #   # ####  ###  ##   #     # #  #                                      
  7.     #   # #        # # #  #     # #  #    Please refer to the accompanying
  8.     ####   ### ####  #  # ##### # ###    documentation for conditions of use
  9.     ________________________________________________________________________
  10.  
  11.     File:    Menu.NewMenu.c
  12.     Author:  Copyright © 1993 Shaun Blackmore and Jason Williams
  13.     Version: 1.00 (30 Apr 1993)
  14.     Purpose: Creates a new menu given a textual description string
  15. */
  16.  
  17.  
  18. #include <stdlib.h>
  19. #include <string.h>
  20.  
  21. #include "DeskLib:Core.h"
  22. #include "DeskLib:Error.h"
  23. #include "DeskLib:Screen.h"
  24. #include "DeskLib:Wimp.h"
  25.  
  26.  
  27. /* Description format:                               
  28.  *      opt   :- " "  no special options (i.e. leading spaces are skipped)
  29.  *               "!"  ticked
  30.  *               "~"  shaded
  31.  *               ">"  has submenu/subwindow
  32.  *               "-"  dotted
  33.  *      name  :- any character except "," and "|" 
  34.  *      entry :- {opt}* name
  35.  *      sep   :- ","  to separate normal items
  36.  *               "|"  to separate items and place a dotted line between them
  37.  *      descr :- entry {sep entry}*
  38.  *
  39.  *      EXAMPLE:
  40.  *        ">Info, Create, Quit"
  41.  *        "!Ticked,~Disabled|>Submenu"
  42.  */
  43.  
  44.  
  45. extern void Menu__CountItems(char *description, int *numitems, int *menuwidth)
  46. /*  For internal use - counts the number of items in a menu description
  47.  *  string, and also returns the widest menu item (in terms of characters)
  48.  */
  49. {
  50.   char *s;
  51.   int  width = 0, maxwidth = 0, count = 0;
  52.   BOOL in_option = TRUE;
  53.  
  54.   for (s = description; *s; s++)
  55.   {
  56.     if (*s == ',' || *s == '|')
  57.     {
  58.      if (width > maxwidth)
  59.        maxwidth = width;
  60.      count++;
  61.      width = 0;
  62.      in_option = TRUE;
  63.     }
  64.     else
  65.     {
  66.       if (in_option)
  67.       {
  68.         if(*s != '!' && *s != '>' && *s != '~' && *s != ' ')
  69.         {
  70.           in_option = FALSE;
  71.           width++;
  72.         }
  73.       }
  74.       else
  75.         width++;
  76.     }
  77.   }
  78.  
  79.   *numitems = count + 1;                    /* Count last item and its width */
  80.  
  81.   if (width > maxwidth)
  82.     maxwidth=width;
  83.  
  84.   *menuwidth = maxwidth + 2;       /* Add room for a gap/sublink arrows, etc */
  85. }
  86.  
  87.  
  88. extern BOOL Menu__Create(menu_item *item, char *description, int numitems)
  89. {
  90.   menu_item *it;
  91.   char *s, *t;
  92.   int  i, index;
  93.   BOOL foundtext;
  94.  
  95.   s = description;
  96.   for (i = 0; i < numitems; i++)
  97.   {
  98.     it = &item[i];
  99.     it->menuflags.value = 0;
  100.     it->submenu.value   = NULL;
  101.     it->iconflags.value = icon_TEXT | icon_FILLED;
  102.     it->iconflags.data.foreground = 7;
  103.  
  104.     foundtext = FALSE;
  105.     do
  106.     {
  107.       switch(*s++)
  108.       {
  109.         case '!':
  110.           it->menuflags.data.ticked = TRUE;
  111.           break;
  112.   
  113.         case '~':
  114.           it->iconflags.data.shaded = TRUE;
  115.           break;
  116.   
  117.         case '>':
  118.           it->menuflags.data.notifysub = TRUE;  /* Ask for sublink warnings */
  119.           it->submenu.value = 1;                /* This is sublink item '1' */
  120.           break;
  121.   
  122.         case ' ':  /* No option */
  123.           break;
  124.   
  125.         default:   /* Any other == start of menu item text, so don't lose it */
  126.           s--;
  127.           foundtext = TRUE;
  128.           break;
  129.       }
  130.     } while (!foundtext);
  131.  
  132.     t = s;
  133.     for (index = 0; ; index++)
  134.       if (t[index] == 0 || t[index] == '|' || t[index] == ',')
  135.         break;
  136.  
  137.     if (index <= wimp_MAXNAME)
  138.       t = it->icondata.text;            /* Copy text directly into menu item */
  139.     else
  140.     {
  141.       /* Copy text into indirected menu item */
  142.       it->iconflags.data.indirected = TRUE;
  143.       it->icondata.indirecttext.buffer = malloc(index + 1);
  144.       if (it->icondata.indirecttext.buffer == NULL)
  145.         return(Error_OutOfMemory(FALSE, "menus"));
  146.  
  147.       it->icondata.indirecttext.bufflen = index + 1;
  148.       it->icondata.indirecttext.validstring = (char *) -1;
  149.  
  150.       t = it->icondata.indirecttext.buffer;
  151.     }
  152.  
  153.     while (*s != 0 && *s != ',' && *s != '|')
  154.       *t++ = *s++;
  155.  
  156.     *t = 0;                                          
  157.     if (*s++ == '|')                        /* Step over separator...        */
  158.       it->menuflags.data.dotted = TRUE;     /* ...setting 'dotted' if needed */
  159.   }
  160.  
  161.   return(TRUE);
  162. }
  163.  
  164.  
  165.  
  166. extern menu_ptr Menu_New(char *title, char *description)
  167. {
  168.   menu_ptr   menu;
  169.   menu_item  *item;
  170.   int        numitems, maxwidth;
  171.  
  172.   Menu__CountItems(description, &numitems, &maxwidth);
  173.  
  174.   if (strlen(title) > maxwidth)    /* Make sure it is wide enough for title  */
  175.     maxwidth = strlen(title);
  176.             
  177.   menu = (menu_ptr) malloc(sizeof(menu_block) + (numitems * sizeof(menu_item)));
  178.  
  179.   if (menu == NULL)
  180.     return((menu_ptr) Error_OutOfMemory(FALSE, "menus")); 
  181.  
  182.   item = (menu_item *) &(menu[1]);
  183.  
  184.   /*  Copy the string. If it's less than 12 characters we need it to be
  185.    *  zero-terminated. We can let it go to 12 chars without any terminator
  186.    *  though, so we don't need to bother terminating after the strncpy.
  187.    */
  188.   strncpy(menu->title, title, wimp_MAXNAME);
  189.  
  190.   menu->titlefore = 7;
  191.   menu->titleback = 2;
  192.   menu->workfore  = 7;
  193.   menu->workback  = 0;
  194.   menu->width     = maxwidth * 8 * screen_delta.x;
  195.   menu->height    = 44;
  196.   menu->gap       = 0;
  197.  
  198.   if (!Menu__Create(item, description, numitems))
  199.     return((menu_ptr) NULL);
  200.   item[numitems - 1].menuflags.data.last = TRUE;
  201.  
  202.   return(menu);
  203. }
  204.  
  205.